#include <windows.h>
#include <wchar.h>
#include <psapi.h>
#include <wincrypt.h>
#include "kpi.h"
#include "kbfmoplmidi_config.h"

extern HINSTANCE g_hKpi;
//キー名
static const wchar_t KEY_KBFMOPLMIDI_DEFAULT_INI[] = L"kbfmoplmidi_default_ini.txt";
static const wchar_t KEY_PATCHFILE[] = L"PatchFile";
static const wchar_t KEY_SAMPLERATE[] = L"SampleRate";
static const wchar_t KEY_FADETIME[] = L"FadeTime";
//static const wchar_t KEY_LOGSOUND[] = L"LogSound";
//static const wchar_t KEY_LOGVGM[] = L"LogVGM";
static const wchar_t KEY_VOLUME[] = L"Volume";
static const wchar_t KEY_MAXLOOPS[] = L"MaxLoops";
static const wchar_t KEY_MAXLOOPSCMF[] = L"MaxLoopsCMF";
static const wchar_t KEY_CHIPSMPLRATE[] = L"ChipSmplRate";
//static const wchar_t KEY_EMULATEPAUSE[] = L"EmulatePause";
//static const wchar_t KEY_ENABLEERRORMSG[] = L"EnableErrorMsg";
//static const wchar_t KEY_FMPORT[] = L"FMPort";
static const wchar_t KEY_VOLUMECALC[] = L"VolumeCalc";
static const wchar_t KEY_OPLMODE[] = L"OPLMode";
static const wchar_t KEY_OPLCHIPS[] = L"OPLChips";
static const wchar_t KEY_BADNOTEOFFS[] = L"BadNoteOffs";
static const wchar_t KEY_WINFM_MODE[] = L"WinFM_Mode";
static const wchar_t KEY_DEFAULTMODE[] = L"DefaultMode";
static const wchar_t KEY_DRUMCHANNEL16[] = L"DrumChannel16";
//static const wchar_t KEY_YM3526_DISABLE[] = L"YM3526_Disable";
//static const wchar_t KEY_YM3812_DISABLE[] = L"YM3812_Disable";
//static const wchar_t KEY_YMF262_DISABLE[] = L"YMF262_Disable";
static const wchar_t KEY_EMUCORE[] = L"EmuCore";

//デフォルト値
static const wchar_t PATCHFILE_DEFAULT[] = L"SB16_VXD_InsDrum.bin";
static const int SAMPLERATE_DEFAULT = 44100;
static const wchar_t SZ_SAMPLERATE_DEFAULT[] = L"44100";
static const int FADETIME_DEFAULT = 8000;
static const wchar_t SZ_FADETIME_DEFAULT[] = L"8000";
//static const bool LOGSOUND_DEFAULT = false;
//static const wchar_t SZ_LOGSOUND_DEFAULT[] = L"0";
//static const bool LOGVGM_DEFAULT = false;
//static const wchar_t SZ_LOGVGM_DEFAULT[] = L"0";
static const double VOLUME_DEFAULT = 1.0;
static const wchar_t SZ_VOLUME_DEFAULT[] = L"1.0";
static const int MAXLOOPS_DEFAULT = 2;
static const wchar_t SZ_MAXLOOPS_DEFAULT[] = L"2";
static const int MAXLOOPSCMF_DEFAULT = 1;
static const wchar_t SZ_MAXLOOPSCMF_DEFAULT[] = L"1";
static const int CHIPSMPLRATE_DEFAULT = -1;
static const wchar_t SZ_CHIPSMPLERATE_DEFAULT[] = L"-1";
//static const bool EMULATEPAUSE_DEFAULT = false;
//static const wchar_t SZ_EMULATEPAUSE_DEFAULT[] = L"0";
//static const bool ENABLEERRORMSG_DEFAULT = false;
//static const wchar_t SZ_ENABLEERRORMSG_DEFAULT[] = L"0";
//static const bool FMPORT_DEFAULT = false;
//static const wchar_t SZ_FMPORT_DEFAULT[] = L"0";
static const int VOLUMECALC_DEFAULT = 0;
static const wchar_t SZ_VOLUMECALC_DEFAULT[] = L"0";
static const int OPLMODE_DEFAULT = 0;
static const wchar_t SZ_OPLMODE_DEFAULT[] = L"0";
static const int OPLCHIPS_DEFAULT = 2;
static const wchar_t SZ_OPLCHIPS_DEFAULT[] = L"2";
static const bool BADNOTEOFFS_DEFAULT = false;
static const wchar_t SZ_BADNOTEOFFS_DEFAULT[] = L"0";
static const int WINFM_MODE_DEFAULT = 0;
static const wchar_t SZ_WINFM_MODE_DEFAULT[] = L"0";
static const int DEFAULTMODE_DEFAULT = 0;
static const wchar_t SZ_DEFAULTMODE_DEFAULT[] = L"0";
static const bool DRUMCHANNEL16_DEFAULT = false;
static const wchar_t SZ_DRUMCHANNEL16_DEFAULT[] = L"0";
//static const bool YM3526_DISABLE_DEFAULT = false;
//static const wchar_t SZ_YM3526_DISABLE_DEFAULT[] = L"0";
//static const bool YM3812_DISABLE_DEFAULT = false;
//static const wchar_t SZ_YM3812_DISABLE_DEFAULT[] = L"0";
//static const bool YMF262_DISABLE_DEFAULT = false;
//static const wchar_t SZ_YMF262_DISABLE_DEFAULT[] = L"0";
static const int EMUCORE_DEFAULT = 0;
static const wchar_t SZ_EMUCORE_DEFAULT[] = L"0";

//////////////////////////////////////////////////////////////////////////////
static void GetKpiPath(wchar_t *pszPath, int nSize)
{
    wchar_t szKpiFile[MAX_PATH];
    GetModuleFileNameW(g_hKpi, szKpiFile, MAX_PATH);
    wchar_t* delimiter = wcsrchr(szKpiFile, L'\\');
    if (delimiter) {
        delimiter[1] = 0;
    }
    wcsncpy_s(pszPath, nSize, szKpiFile, _TRUNCATE);
}
//////////////////////////////////////////////////////////////////////////////
static void GetSectionName(wchar_t *pszSectionName, int nSize)
{//セクション名はプラグインファイル名とする
    wchar_t szKpiFile[MAX_PATH];
    GetModuleFileNameW(g_hKpi, szKpiFile, MAX_PATH);
    const wchar_t* delimiter = wcsrchr(szKpiFile, L'\\');
    if (delimiter) {
        wcsncpy_s(pszSectionName, nSize, delimiter + 1, _TRUNCATE);
    }
    else {
        wcsncpy_s(pszSectionName, nSize, L"kbfmoplmidi.kpi", _TRUNCATE);
    }
}
//////////////////////////////////////////////////////////////////////////////
BOOL __fastcall kbfmoplmidi_EnumConfig(IKpiConfig *pConfig, IKpiConfigEnumerator *pEnumerator)
{
    //static const wchar_t cszIgnored[] = L"本プラグインでは無視されます。";
    wchar_t szSection[MAX_PATH];
    wchar_t szSectionHelp[MAX_PATH + 1024];

    GetSectionName(szSection, _countof(szSection));
    _snwprintf_s(szSectionHelp, _TRUNCATE,
        L"%s に関する一般的な設定です。\r\n"
        L"\"FM OPL MIDI Player\" の設定項目に準じていますが、設定項目のいくつかは無視されます。\r\n"
        L"最も重要な設定項目は \"PatchFile\" です。\r\n"
        L"プラグインのファイル名ごとに異なるセクションを作成します。\r\n"
        L"プラグインのコピーを作成すれば，コピーごとに異なる MIDI デバイスのように扱うことが出来ます。\r\n"
        L"例えば kbfmoplmidi_maui.kpi という名前のコピーを作成し、\"kbfmoplmidi_maui.kpi\" セクションの "
        L"\"PatchFile\" を \"maui.bin\" にしておくと、\"maui.bin\" を使う MIDI デバイスのように扱えます。", szSection);

    KPI_CFG_SECTION section[] = {
        szSection, NULL, szSectionHelp,
        NULL, NULL, NULL
    };
    KPI_CFG_KEY key[] = {
        //   type, section, key, keydesc, default, min, max, list, listdesc, help
            {KPI_CFG_TYPE_BIN, szSection, KEY_KBFMOPLMIDI_DEFAULT_INI, NULL,
                NULL, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                L"本プラグインの元となった \"FM OPL MIDI Player\" の初期設定ファイルを開きます。\r\n"
                L"設定の参考にして下さい。\r\n"
                L"このファイルを編集しても本プラグインの設定は変更されないことに注意して下さい。\r\n"},//help
            {KPI_CFG_TYPE_INT, szSection, KEY_SAMPLERATE, NULL,
                SZ_SAMPLERATE_DEFAULT, L"-192000", L"192000", //default, min, max
                L"44100\t48000\t88200\t96000\t176400\t192000",//list
                NULL, //listdesc
                L"プレイヤーからの要求が 0(既定値)の場合の再生周波数です。\r\n"
                L"負の値を指定するとプレイヤーからの要求を無視します。例えば -192000 にすると 44100Hz で要求されても 192000Hz で再生します。"},
            {KPI_CFG_TYPE_INT, szSection, KEY_FADETIME, NULL,
                SZ_FADETIME_DEFAULT, L"0", NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                L"フェードアウト時間です。通常は MIDI 以外を再生時に適用されます。\r\n"
                L"ループ MIDI を再生時は本体の設定に従います。"},//help
            /*{KPI_CFG_TYPE_BOOL, szSection, KEY_LOGSOUND, NULL,
                SZ_LOGSOUND_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                cszIgnored},//help
                */
            /*{KPI_CFG_TYPE_BOOL, szSection, KEY_LOGVGM, NULL,
                SZ_LOGVGM_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                cszIgnored},//help
                */
            {KPI_CFG_TYPE_FLOAT, szSection, KEY_VOLUME, NULL,
                SZ_VOLUME_DEFAULT, L"0.25", L"2.0", //default, min, max
                NULL, //list
                NULL, //listdesc
                L"音量を小数点で指定します。初期値は 1.0 ですが、少し音が割れるので"
                L"個人的には 0.5〜0.8 程度を推奨します。"},//help
            {KPI_CFG_TYPE_INT, szSection, KEY_MAXLOOPS, NULL,
                SZ_MAXLOOPS_DEFAULT, L"1", NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                NULL},//help
            {KPI_CFG_TYPE_INT, szSection, KEY_MAXLOOPSCMF, NULL,
                SZ_MAXLOOPSCMF_DEFAULT, L"1", NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                NULL},//help
            {KPI_CFG_TYPE_INT, szSection, KEY_CHIPSMPLRATE, NULL,
                SZ_CHIPSMPLERATE_DEFAULT, L"-1", L"192000", //default, min, max
                L"-1\t0", //list
                L"SampleRate と同じ\t49715Hz", //listdesc
                L"-1 - SampleRate と同じ\r\n"
                L" 0 - 49715Hz" },//help
            /*{KPI_CFG_TYPE_BOOL, szSection, KEY_EMULATEPAUSE, NULL,
                SZ_EMULATEPAUSE_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                cszIgnored},//help
                */
            /*{KPI_CFG_TYPE_BOOL, szSection, KEY_ENABLEERRORMSG, NULL,
                SZ_ENABLEERRORMSG_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                cszIgnored},//help
                */
            /*{KPI_CFG_TYPE_BOOL, szSection, KEY_FMPORT, NULL,
                SZ_FMPORT_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                cszIgnored},//help
                */
            {KPI_CFG_TYPE_STR, szSection, KEY_PATCHFILE, NULL,
                PATCHFILE_DEFAULT, NULL, NULL, //default, min, max
                L"SB16_VXD_InsDrum.bin\t"
                L"maui.bin\t"
                L"AdPlug_InsDrum.bin\t"
                L"Scumm_InsDrum.bin\t"
                L"MSOPL_DRV_ins.bin\t"
                L"SB16_VXD_DrumNote_Win95.bin\t"
                L"CTMIDI_Drums.bin\t"
                L"CTMIDI_Instruments.bin", //list
                NULL, //listdesc
                L"音色ファイルを指定します。このプラグインで最も重要な設定項目です。\r\n"
                L"選択可能な中で実用性が高いのは\r\n"
                L"\r\n"
                L"SB16_VXD_InsDrum.bin\r\n"
                L"maui.bin\r\n"
                L"Scumm_InsDrum.bin\r\n"
                L"AdPlug_InsDrum.bin\r\n"
                L"MSOPL_DRV_ins.bin\r\n"
                L"\r\n"
                L"となります。"},//help
            {KPI_CFG_TYPE_INT, szSection, KEY_VOLUMECALC, NULL,
                SZ_VOLUMECALC_DEFAULT, NULL, NULL, //default, min, max
                L"0\t1\t2\t3\t4\t5", //list
                L"Auto(MID: custom/Windows, CMF: SBFM, LAA: AdPlug\t"
                L"Windows\t"
                L"AdPlug\t"
                L"SoundBlaster FM Driver(SMFVDRV.COM for CMF Files)\t"
                L"SCUMM Games\tcustom(100% correct GM -> FM)", //listdesc
                L"0 - Auto(MID: custom/Windows, CMF: SBFM, LAA: AdPlug)\r\n"
                L"1 - Windows\r\n"
                L"2 - AdPlug\r\n"
                L"3 - SoundBlaster FM Driver (SBFMDRV.COM for CMF-Files)\r\n"
                L"4 - SCUMM Games\r\n"
                L"5 - custom (100% correct GM -> FM)"},//help
            {KPI_CFG_TYPE_INT, szSection, KEY_OPLMODE, NULL,
                SZ_OPLMODE_DEFAULT, NULL, NULL, //default, min, max
                L"0\t1\t2\t3", //list
                L"Auto(MID: YMF262, CMF: YM3812, LAA: YM3812)\tYM3526\tYM3812\tYMF262", //listdesc
                L"0 - Auto(MID: YMF262, CMF: YM3812, LAA: YM3812)\r\n"
                L"1 - YM3526\r\n"
                L"2 - YM3812\r\n"
                L"3 - YMF262\r\n"
                },//help
            {KPI_CFG_TYPE_INT, szSection, KEY_OPLCHIPS, NULL,
                SZ_OPLCHIPS_DEFAULT, L"1", L"16", //default, min, max
                NULL, //list
                NULL, //listdesc
                L"値を大きくすると再生時の負荷が高くなります。\r\n"},//help
            {KPI_CFG_TYPE_BOOL, szSection, KEY_BADNOTEOFFS, NULL,
                SZ_BADNOTEOFFS_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                L"send NoteOff-Command 2 times\r\n"
                L"It's the behaviour of some old MIDI-Devices and some MIDIs need that"},//help
            {KPI_CFG_TYPE_BOOL, szSection, KEY_WINFM_MODE, NULL,
                SZ_WINFM_MODE_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                L"mimic the (bad) FM-Driver of Windows"
                    L"(including Pan-Effect, Volume Calculation, missing Controllers/SysEx)"},//help
            {KPI_CFG_TYPE_INT, szSection, KEY_DEFAULTMODE, NULL,
                SZ_DEFAULTMODE_DEFAULT, NULL, NULL, //default, min, max
                L"0\t1\t2\t3", //list
                L"GM\tGS\tXG\tMT32", //listdesc
                L"WinFM_Mode が \"true\" の場合は無視されます。\r\n"
                    L"\r\n"
                    L"0 - GM\r\n"
                    L"1 - GS\r\n"
                    L"2 - XG\r\n"
                    L"3 - MT32"},//help
            {KPI_CFG_TYPE_BOOL, szSection, KEY_DRUMCHANNEL16, NULL,
                SZ_DRUMCHANNEL16_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                NULL},//help
            /*{KPI_CFG_TYPE_BOOL, szSection, KEY_YM3526_DISABLE, NULL,
                SZ_YM3526_DISABLE_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                L"true にすると YM3526 を無効化します。"},//help
            {KPI_CFG_TYPE_BOOL, szSection, KEY_YM3812_DISABLE, NULL,
                SZ_YM3812_DISABLE_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                L"true にすると YM3812 を無効化します。"},//help
            {KPI_CFG_TYPE_BOOL, szSection, KEY_YMF262_DISABLE, NULL,
                SZ_YMF262_DISABLE_DEFAULT, NULL, NULL, //default, min, max
                NULL, //list
                NULL, //listdesc
                L"true にすると YMF262 を無効化します。"},//help
            */
            { KPI_CFG_TYPE_INT, szSection, KEY_EMUCORE, NULL,
                SZ_EMUCORE_DEFAULT, NULL, NULL, //default, min, max
                L"0\t1", //list
                L"DosBox OPL (AdLibEmu)\tMAME", //listdesc
                L"OPLMode が YM3812 または YMF262 のときに有効です。\r\n"
                L"\r\n"
                L"0 - DosBox OPL (AdLibEmu)\r\n"
                L"1 - MAME\r\n"
                L"\r\n"
                L"FM OPL MIDI Player には該当する設定がなく、常に AdlibEmu で再生するようです。\r\n"
                L"AdlibEmu より MAME の方が再生時の負荷が高いようです。\r\n"
                L"" },//help
            {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
    };

    int i;
    for (i = 0; section[i].cszSection; i++) {
        pEnumerator->EnumSection(&section[i]);
    }
    for (i = 0; key[i].cszSection; i++) {
        pEnumerator->EnumKey(&key[i]);
    }
    return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
DWORD __fastcall kbfmoplmidi_ApplyConfig(IKpiConfig *pConfig,
                              const wchar_t *cszSection, //セクション名
                              const wchar_t *cszKey, //キー名
                              INT64  nValue, //変更後の値(BOOL/INT の場合)
                              double dValue, //変更後の値(FLOAT の場合)
                              const wchar_t *cszValue)//変更後の値(文字列)
{
    if (//wcscmp(cszSection, m_szKpiFileName) == 0 &&
        wcscmp(cszKey, KEY_KBFMOPLMIDI_DEFAULT_INI) == 0) {
        wchar_t szIniFile[MAX_PATH];
        GetModuleFileNameW(g_hKpi, szIniFile, MAX_PATH);
        wchar_t* delimiter = wcsrchr(szIniFile, L'\\');
        if (delimiter) {
            delimiter[1] = 0;
        }
        wcsncat_s(szIniFile, KEY_KBFMOPLMIDI_DEFAULT_INI, _TRUNCATE);
        ShellExecuteW(NULL, L"open", szIniFile, NULL, NULL, SW_SHOWNORMAL);
        return KPI_CFGRET_OK;
    }
    pConfig->SetStr(cszSection, cszKey, cszValue);
    return KPI_CFGRET_RELOAD_DATA;
}
//////////////////////////////////////////////////////////////////////////////
void __fastcall kbfmoplmidi_GetSettings(IKpiConfig *pConfig, kbfmoplmidi_Settings *pSettings)
{
    wchar_t szSection[MAX_PATH];
    wchar_t szPatchFile[MAX_PATH];
    GetSectionName(szSection, _countof(szSection));
    
    pConfig->GetStr(szSection, KEY_PATCHFILE, szPatchFile, sizeof(szPatchFile), PATCHFILE_DEFAULT);
    if(!szPatchFile[0]){
        wcsncpy_s(szPatchFile, PATCHFILE_DEFAULT, _TRUNCATE);
    }
    GetKpiPath(pSettings->szPatchFile, _countof(pSettings->szPatchFile));
    wcsncat_s(pSettings->szPatchFile, szPatchFile, _TRUNCATE);

    pSettings->nSampleRate = pConfig->GetInt(szSection, KEY_SAMPLERATE, SAMPLERATE_DEFAULT);
    if(pSettings->nSampleRate < -192000){
        pSettings->nSampleRate = -192000;
    }
    else if(pSettings->nSampleRate > 192000){
        pSettings->nSampleRate = 192000;
    }
    else if(pSettings->nSampleRate == 0){
        pSettings->nSampleRate = SAMPLERATE_DEFAULT;
    }
    
    pSettings->nFadeTime = pConfig->GetInt(szSection, KEY_FADETIME, FADETIME_DEFAULT);
    if(pSettings->nFadeTime < 0){
        pSettings->nFadeTime = FADETIME_DEFAULT;
    }

    pSettings->bLogSound = false;//pConfig->GetInt(szSection, KEY_LOGSOUND, LOGSOUND_DEFAULT) != 0;
    pSettings->bLogVGM = false;//pConfig->GetInt(szSection, KEY_LOGVGM, LOGVGM_DEFAULT) != 0;
    pSettings->dVolume = pConfig->GetFloat(szSection, KEY_VOLUME, VOLUME_DEFAULT);
    if(pSettings->dVolume < 0){
        pSettings->dVolume = VOLUME_DEFAULT;
    }
    else if(pSettings->dVolume > 2.0){
        pSettings->dVolume = 2.0;
    }
    pSettings->nMaxLoops = pConfig->GetInt(szSection, KEY_MAXLOOPS, MAXLOOPS_DEFAULT);
    if(pSettings->nMaxLoops <= 0){
        pSettings->nMaxLoops = MAXLOOPS_DEFAULT;
    }
    pSettings->nMaxLoopsCMF = pConfig->GetInt(szSection, KEY_MAXLOOPSCMF, MAXLOOPSCMF_DEFAULT);
    if (pSettings->nMaxLoopsCMF <= 0) {
        pSettings->nMaxLoopsCMF = MAXLOOPSCMF_DEFAULT;
    }
    pSettings->nChipSmplRate = pConfig->GetInt(szSection, KEY_CHIPSMPLRATE, CHIPSMPLRATE_DEFAULT);
    if (pSettings->nChipSmplRate < 0) {
        pSettings->nChipSmplRate = CHIPSMPLRATE_DEFAULT;
    }
    else if (pSettings->nChipSmplRate > 192000) {
        pSettings->nChipSmplRate = 192000;
    }
    pSettings->bEmulatePause = false;//pConfig->GetInt(szSection, KEY_EMULATEPAUSE, EMULATEPAUSE_DEFAULT) != 0;
    pSettings->bEnableErrorMsg = false;//pConfig->GetInt(szSection, KEY_ENABLEERRORMSG, ENABLEERRORMSG_DEFAULT) != 0;
    pSettings->bFMPort = false;//pConfig->GetInt(szSection, KEY_FMPORT, FMPORT_DEFAULT) != 0;
    pSettings->nVolumeCalc = pConfig->GetInt(szSection, KEY_VOLUMECALC, VOLUMECALC_DEFAULT);
    switch(pSettings->nVolumeCalc){
        case 0: case 1: case 2: case 3: case 4: case 5: break;//OK
        default: pSettings->nChipSmplRate = VOLUMECALC_DEFAULT; break;
    }
    pSettings->nOPLMode = pConfig->GetInt(szSection, KEY_OPLMODE, OPLMODE_DEFAULT);
    switch (pSettings->nOPLMode) {
    case 0: case 1: case 2: case 3: break;//OK
    default: pSettings->nOPLMode = OPLMODE_DEFAULT; break;
    }
    pSettings->nOPLChips = pConfig->GetInt(szSection, KEY_OPLCHIPS, OPLCHIPS_DEFAULT);
    if(pSettings->nOPLChips <= 0){
        pSettings->nOPLChips = 1;
    }
    else if(pSettings->nOPLChips > 16){
        pSettings->nOPLChips = 16;
    }
    pSettings->bBadNoteOffs = pConfig->GetInt(szSection, KEY_BADNOTEOFFS, BADNOTEOFFS_DEFAULT) != 0;
    pSettings->bWinFM_Mode = pConfig->GetInt(szSection, KEY_WINFM_MODE, WINFM_MODE_DEFAULT) != 0;
    pSettings->nDefaultMode = pConfig->GetInt(szSection, KEY_DEFAULTMODE, DEFAULTMODE_DEFAULT);
    switch (pSettings->nDefaultMode) {
    case 0: case 1: case 2: case 3: break;//OK
    default: pSettings->nDefaultMode = DEFAULTMODE_DEFAULT; break;
    }
    pSettings->bDrumChannel16 = pConfig->GetInt(szSection, KEY_DRUMCHANNEL16, DRUMCHANNEL16_DEFAULT) != 0;
    pSettings->bYM3526_Disable = false;//pConfig->GetInt(szSection, KEY_YM3526_DISABLE, YM3526_DISABLE_DEFAULT) != 0;
    pSettings->bYM3812_Disable = false;//pConfig->GetInt(szSection, KEY_YM3812_DISABLE, YM3812_DISABLE_DEFAULT) != 0;
    pSettings->bYMF262_Disable = false;//pConfig->GetInt(szSection, KEY_YMF262_DISABLE, YMF262_DISABLE_DEFAULT) != 0;
    pSettings->nEmuCore = pConfig->GetInt(szSection, KEY_EMUCORE, EMUCORE_DEFAULT);
    switch(pSettings->nEmuCore){
        case 0: case 1:break;//OK
        default: pSettings->nEmuCore = EMUCORE_DEFAULT;break;
    }
}
