// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.

#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/HW/SI.h"
#include "Core/PowerPC/PowerPC.h"
#include "DiscIO/NANDContentLoader.h"

SConfig* SConfig::m_Instance;

SConfig::SConfig()
{
	// Make sure we have log manager
	LoadSettings();
}

void SConfig::Init()
{
	m_Instance = new SConfig;
}

void SConfig::Shutdown()
{
	delete m_Instance;
	m_Instance = nullptr;
}

SConfig::~SConfig()
{
	SaveSettings();
	delete m_SYSCONF;
}


void SConfig::SaveSettings()
{
	// TODO: The is a hotfix to prevent writing of temporary per-game settings
	// (GameINI, Movie, Netplay, ...) to the global Dolphin configuration file.
	// The Config logic should be rewritten instead so that per-game settings
	// aren't stored in the same configuration as the actual user settings.
	if (Core::IsRunning())
		return;

	NOTICE_LOG(BOOT, "Saving settings to %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
	IniFile ini;
	ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX)); // load first to not kill unknown stuff

	SaveGeneralSettings(ini);
	SaveInterfaceSettings(ini);
	SaveDisplaySettings(ini);
	SaveGameListSettings(ini);
	SaveCoreSettings(ini);
	SaveMovieSettings(ini);
	SaveDSPSettings(ini);
	SaveInputSettings(ini);
	SaveFifoPlayerSettings(ini);

	ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
	m_SYSCONF->Save();
}

void SConfig::SaveGeneralSettings(IniFile& ini)
{
	IniFile::Section* general = ini.GetOrCreateSection("General");

	// General
	general->Set("LastFilename", m_LastFilename);
	general->Set("ShowLag", m_ShowLag);
	general->Set("ShowFrameCount", m_ShowFrameCount);

	// ISO folders
	// Clear removed folders
	int oldPaths;
	int numPaths = (int)m_ISOFolder.size();
	general->Get("ISOPaths", &oldPaths, 0);
	for (int i = numPaths; i < oldPaths; i++)
	{
		ini.DeleteKey("General", StringFromFormat("ISOPath%i", i));
	}

	general->Set("ISOPaths", numPaths);
	for (int i = 0; i < numPaths; i++)
	{
		general->Set(StringFromFormat("ISOPath%i", i), m_ISOFolder[i]);
	}

	general->Set("RecursiveISOPaths", m_RecursiveISOFolder);
	general->Set("NANDRootPath", m_NANDPath);
	general->Set("WirelessMac", m_WirelessMac);

#ifdef USE_GDBSTUB
#ifndef _WIN32
	general->Set("GDBSocket", m_LocalCoreStartupParameter.gdb_socket);
#endif
	general->Set("GDBPort", m_LocalCoreStartupParameter.iGDBPort);
#endif
}

void SConfig::SaveInterfaceSettings(IniFile& ini)
{
	IniFile::Section* interface = ini.GetOrCreateSection("Interface");

	interface->Set("ConfirmStop", m_LocalCoreStartupParameter.bConfirmStop);
	interface->Set("UsePanicHandlers", m_LocalCoreStartupParameter.bUsePanicHandlers);
	interface->Set("OnScreenDisplayMessages", m_LocalCoreStartupParameter.bOnScreenDisplayMessages);
	interface->Set("HideCursor", m_LocalCoreStartupParameter.bHideCursor);
	interface->Set("AutoHideCursor", m_LocalCoreStartupParameter.bAutoHideCursor);
	interface->Set("MainWindowPosX", (m_LocalCoreStartupParameter.iPosX == -32000) ? 0 : m_LocalCoreStartupParameter.iPosX); // TODO - HAX
	interface->Set("MainWindowPosY", (m_LocalCoreStartupParameter.iPosY == -32000) ? 0 : m_LocalCoreStartupParameter.iPosY); // TODO - HAX
	interface->Set("MainWindowWidth", m_LocalCoreStartupParameter.iWidth);
	interface->Set("MainWindowHeight", m_LocalCoreStartupParameter.iHeight);
	interface->Set("Language", m_InterfaceLanguage);
	interface->Set("ShowToolbar", m_InterfaceToolbar);
	interface->Set("ShowStatusbar", m_InterfaceStatusbar);
	interface->Set("ShowLogWindow", m_InterfaceLogWindow);
	interface->Set("ShowLogConfigWindow", m_InterfaceLogConfigWindow);
	interface->Set("ExtendedFPSInfo", m_InterfaceExtendedFPSInfo);
	interface->Set("ThemeName40", m_LocalCoreStartupParameter.theme_name);
	interface->Set("PauseOnFocusLost", m_PauseOnFocusLost);
}

void SConfig::SaveDisplaySettings(IniFile& ini)
{
	IniFile::Section* display = ini.GetOrCreateSection("Display");

	display->Set("FullscreenResolution", m_LocalCoreStartupParameter.strFullscreenResolution);
	display->Set("Fullscreen", m_LocalCoreStartupParameter.bFullscreen);
	display->Set("RenderToMain", m_LocalCoreStartupParameter.bRenderToMain);
	display->Set("RenderWindowXPos", m_LocalCoreStartupParameter.iRenderWindowXPos);
	display->Set("RenderWindowYPos", m_LocalCoreStartupParameter.iRenderWindowYPos);
	display->Set("RenderWindowWidth", m_LocalCoreStartupParameter.iRenderWindowWidth);
	display->Set("RenderWindowHeight", m_LocalCoreStartupParameter.iRenderWindowHeight);
	display->Set("RenderWindowAutoSize", m_LocalCoreStartupParameter.bRenderWindowAutoSize);
	display->Set("KeepWindowOnTop", m_LocalCoreStartupParameter.bKeepWindowOnTop);
	display->Set("ProgressiveScan", m_LocalCoreStartupParameter.bProgressive);
	display->Set("DisableScreenSaver", m_LocalCoreStartupParameter.bDisableScreenSaver);
	display->Set("ForceNTSCJ", m_LocalCoreStartupParameter.bForceNTSCJ);
}

void SConfig::SaveGameListSettings(IniFile& ini)
{
	IniFile::Section* gamelist = ini.GetOrCreateSection("GameList");

	gamelist->Set("ListDrives", m_ListDrives);
	gamelist->Set("ListWad", m_ListWad);
	gamelist->Set("ListWii", m_ListWii);
	gamelist->Set("ListGC", m_ListGC);
	gamelist->Set("ListJap", m_ListJap);
	gamelist->Set("ListPal", m_ListPal);
	gamelist->Set("ListUsa", m_ListUsa);
	gamelist->Set("ListAustralia", m_ListAustralia);
	gamelist->Set("ListFrance", m_ListFrance);
	gamelist->Set("ListGermany", m_ListGermany);
	gamelist->Set("ListItaly", m_ListItaly);
	gamelist->Set("ListKorea", m_ListKorea);
	gamelist->Set("ListNetherlands", m_ListNetherlands);
	gamelist->Set("ListRussia", m_ListRussia);
	gamelist->Set("ListSpain", m_ListSpain);
	gamelist->Set("ListTaiwan", m_ListTaiwan);
	gamelist->Set("ListWorld", m_ListWorld);
	gamelist->Set("ListUnknown", m_ListUnknown);
	gamelist->Set("ListSort", m_ListSort);
	gamelist->Set("ListSortSecondary", m_ListSort2);

	gamelist->Set("ColorCompressed", m_ColorCompressed);

	gamelist->Set("ColumnPlatform", m_showSystemColumn);
	gamelist->Set("ColumnBanner", m_showBannerColumn);
	gamelist->Set("ColumnNotes", m_showMakerColumn);
	gamelist->Set("ColumnID", m_showIDColumn);
	gamelist->Set("ColumnRegion", m_showRegionColumn);
	gamelist->Set("ColumnSize", m_showSizeColumn);
	gamelist->Set("ColumnState", m_showStateColumn);
}

void SConfig::SaveCoreSettings(IniFile& ini)
{
	IniFile::Section* core = ini.GetOrCreateSection("Core");

	core->Set("HLE_BS2", m_LocalCoreStartupParameter.bHLE_BS2);
	core->Set("CPUCore", m_LocalCoreStartupParameter.iCPUCore);
	core->Set("Fastmem", m_LocalCoreStartupParameter.bFastmem);
	core->Set("CPUThread", m_LocalCoreStartupParameter.bCPUThread);
	core->Set("DSPHLE", m_LocalCoreStartupParameter.bDSPHLE);
	core->Set("SkipIdle", m_LocalCoreStartupParameter.bSkipIdle);
	core->Set("SyncOnSkipIdle", m_LocalCoreStartupParameter.bSyncGPUOnSkipIdleHack);
	core->Set("SyncGPU", m_LocalCoreStartupParameter.bSyncGPU);
	core->Set("SyncGpuMaxDistance", m_LocalCoreStartupParameter.iSyncGpuMaxDistance);
	core->Set("SyncGpuMinDistance", m_LocalCoreStartupParameter.iSyncGpuMinDistance);
	core->Set("SyncGpuOverclock", m_LocalCoreStartupParameter.fSyncGpuOverclock);
	core->Set("DefaultISO", m_LocalCoreStartupParameter.m_strDefaultISO);
	core->Set("DVDRoot", m_LocalCoreStartupParameter.m_strDVDRoot);
	core->Set("Apploader", m_LocalCoreStartupParameter.m_strApploader);
	core->Set("EnableCheats", m_LocalCoreStartupParameter.bEnableCheats);
	core->Set("SelectedLanguage", m_LocalCoreStartupParameter.SelectedLanguage);
	core->Set("DPL2Decoder", m_LocalCoreStartupParameter.bDPL2Decoder);
	core->Set("Latency", m_LocalCoreStartupParameter.iLatency);
	core->Set("MemcardAPath", m_strMemoryCardA);
	core->Set("MemcardBPath", m_strMemoryCardB);
	core->Set("AgpCartAPath", m_strGbaCartA);
	core->Set("AgpCartBPath", m_strGbaCartB);
	core->Set("SlotA", m_EXIDevice[0]);
	core->Set("SlotB", m_EXIDevice[1]);
	core->Set("SerialPort1", m_EXIDevice[2]);
	core->Set("BBA_MAC", m_bba_mac);
	for (int i = 0; i < MAX_SI_CHANNELS; ++i)
	{
		core->Set(StringFromFormat("SIDevice%i", i), m_SIDevice[i]);
	}
	core->Set("WiiSDCard", m_WiiSDCard);
	core->Set("WiiKeyboard", m_WiiKeyboard);
	core->Set("WiimoteContinuousScanning", m_WiimoteContinuousScanning);
	core->Set("WiimoteEnableSpeaker", m_WiimoteEnableSpeaker);
	core->Set("RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer);
	core->Set("RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient);
	core->Set("FrameLimit", m_Framelimit);
	core->Set("FrameSkip", m_FrameSkip);
	core->Set("Overclock", m_OCFactor);
	core->Set("OverclockEnable", m_OCEnable);
	core->Set("GFXBackend", m_LocalCoreStartupParameter.m_strVideoBackend);
	core->Set("GPUDeterminismMode", m_LocalCoreStartupParameter.m_strGPUDeterminismMode);
	core->Set("GameCubeAdapter", m_GameCubeAdapter);
	core->Set("AdapterRumble", m_AdapterRumble);
}

void SConfig::SaveMovieSettings(IniFile& ini)
{
	IniFile::Section* movie = ini.GetOrCreateSection("Movie");

	movie->Set("PauseMovie", m_PauseMovie);
	movie->Set("Author", m_strMovieAuthor);
	movie->Set("DumpFrames", m_DumpFrames);
	movie->Set("DumpFramesSilent", m_DumpFramesSilent);
	movie->Set("ShowInputDisplay", m_ShowInputDisplay);
}

void SConfig::SaveDSPSettings(IniFile& ini)
{
	IniFile::Section* dsp = ini.GetOrCreateSection("DSP");

	dsp->Set("EnableJIT", m_DSPEnableJIT);
	dsp->Set("DumpAudio", m_DumpAudio);
	dsp->Set("Backend", sBackend);
	dsp->Set("Volume", m_Volume);
	dsp->Set("CaptureLog", m_DSPCaptureLog);
}

void SConfig::SaveInputSettings(IniFile& ini)
{
	IniFile::Section* input = ini.GetOrCreateSection("Input");

	input->Set("BackgroundInput", m_BackgroundInput);
}

void SConfig::SaveFifoPlayerSettings(IniFile& ini)
{
	IniFile::Section* fifoplayer = ini.GetOrCreateSection("FifoPlayer");

	fifoplayer->Set("LoopReplay", m_LocalCoreStartupParameter.bLoopFifoReplay);
}

void SConfig::LoadSettings()
{
	INFO_LOG(BOOT, "Loading Settings from %s", File::GetUserPath(F_DOLPHINCONFIG_IDX).c_str());
	IniFile ini;
	ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));

	LoadGeneralSettings(ini);
	LoadInterfaceSettings(ini);
	LoadDisplaySettings(ini);
	LoadGameListSettings(ini);
	LoadCoreSettings(ini);
	LoadMovieSettings(ini);
	LoadDSPSettings(ini);
	LoadInputSettings(ini);
	LoadFifoPlayerSettings(ini);

	m_SYSCONF = new SysConf();
}

void SConfig::LoadGeneralSettings(IniFile& ini)
{
	IniFile::Section* general = ini.GetOrCreateSection("General");

	general->Get("LastFilename", &m_LastFilename);
	general->Get("ShowLag", &m_ShowLag, false);
	general->Get("ShowFrameCount", &m_ShowFrameCount, false);
#ifdef USE_GDBSTUB
#ifndef _WIN32
	general->Get("GDBSocket", &m_LocalCoreStartupParameter.gdb_socket, "");
#endif
	general->Get("GDBPort", &(m_LocalCoreStartupParameter.iGDBPort), -1);
#endif

	m_ISOFolder.clear();
	int numISOPaths;

	if (general->Get("ISOPaths", &numISOPaths, 0))
	{
		for (int i = 0; i < numISOPaths; i++)
		{
			std::string tmpPath;
			general->Get(StringFromFormat("ISOPath%i", i), &tmpPath, "");
			m_ISOFolder.push_back(std::move(tmpPath));
		}
	}
	// Check for old file path (Changed in 4.0-4003)
	// This can probably be removed after 5.0 stable is launched
	else if (general->Get("GCMPathes", &numISOPaths, 0))
	{
		for (int i = 0; i < numISOPaths; i++)
		{
			std::string tmpPath;
			general->Get(StringFromFormat("GCMPath%i", i), &tmpPath, "");
			bool found = false;
			for (size_t j = 0; j < m_ISOFolder.size(); ++j)
			{
				if (m_ISOFolder[j] == tmpPath)
				{
					found = true;
					break;
				}
			}
			if (!found)
				m_ISOFolder.push_back(std::move(tmpPath));
		}
	}

	if (!general->Get("RecursiveISOPaths", &m_RecursiveISOFolder, false))
	{
		// Check for old name
		general->Get("RecursiveGCMPaths", &m_RecursiveISOFolder, false);
	}

	general->Get("NANDRootPath", &m_NANDPath);
	File::SetUserPath(D_WIIROOT_IDX, m_NANDPath);
	general->Get("WirelessMac", &m_WirelessMac);
}

void SConfig::LoadInterfaceSettings(IniFile& ini)
{
	IniFile::Section* interface = ini.GetOrCreateSection("Interface");

	interface->Get("ConfirmStop",             &m_LocalCoreStartupParameter.bConfirmStop,      true);
	interface->Get("UsePanicHandlers",        &m_LocalCoreStartupParameter.bUsePanicHandlers, true);
	interface->Get("OnScreenDisplayMessages", &m_LocalCoreStartupParameter.bOnScreenDisplayMessages, true);
	interface->Get("HideCursor",              &m_LocalCoreStartupParameter.bHideCursor,       false);
	interface->Get("AutoHideCursor",          &m_LocalCoreStartupParameter.bAutoHideCursor,   false);
	interface->Get("MainWindowPosX",          &m_LocalCoreStartupParameter.iPosX,             100);
	interface->Get("MainWindowPosY",          &m_LocalCoreStartupParameter.iPosY,             100);
	interface->Get("MainWindowWidth",         &m_LocalCoreStartupParameter.iWidth,            800);
	interface->Get("MainWindowHeight",        &m_LocalCoreStartupParameter.iHeight,           600);
	interface->Get("Language",                &m_InterfaceLanguage,                           0);
	interface->Get("ShowToolbar",             &m_InterfaceToolbar,                            true);
	interface->Get("ShowStatusbar",           &m_InterfaceStatusbar,                          true);
	interface->Get("ShowLogWindow",           &m_InterfaceLogWindow,                          false);
	interface->Get("ShowLogConfigWindow",     &m_InterfaceLogConfigWindow,                    false);
	interface->Get("ExtendedFPSInfo",         &m_InterfaceExtendedFPSInfo,                    false);
	interface->Get("ThemeName40",             &m_LocalCoreStartupParameter.theme_name,        "Clean");
	interface->Get("PauseOnFocusLost",        &m_PauseOnFocusLost,                            false);
}

void SConfig::LoadDisplaySettings(IniFile& ini)
{
	IniFile::Section* display = ini.GetOrCreateSection("Display");

	display->Get("Fullscreen",           &m_LocalCoreStartupParameter.bFullscreen,             false);
	display->Get("FullscreenResolution", &m_LocalCoreStartupParameter.strFullscreenResolution, "Auto");
	display->Get("RenderToMain",         &m_LocalCoreStartupParameter.bRenderToMain,           false);
	display->Get("RenderWindowXPos",     &m_LocalCoreStartupParameter.iRenderWindowXPos,       -1);
	display->Get("RenderWindowYPos",     &m_LocalCoreStartupParameter.iRenderWindowYPos,       -1);
	display->Get("RenderWindowWidth",    &m_LocalCoreStartupParameter.iRenderWindowWidth,      640);
	display->Get("RenderWindowHeight",   &m_LocalCoreStartupParameter.iRenderWindowHeight,     480);
	display->Get("RenderWindowAutoSize", &m_LocalCoreStartupParameter.bRenderWindowAutoSize,   false);
	display->Get("KeepWindowOnTop",      &m_LocalCoreStartupParameter.bKeepWindowOnTop,        false);
	display->Get("ProgressiveScan",      &m_LocalCoreStartupParameter.bProgressive,            false);
	display->Get("DisableScreenSaver",   &m_LocalCoreStartupParameter.bDisableScreenSaver,     true);
	display->Get("ForceNTSCJ",           &m_LocalCoreStartupParameter.bForceNTSCJ,             false);
}

void SConfig::LoadGameListSettings(IniFile& ini)
{
	IniFile::Section* gamelist = ini.GetOrCreateSection("GameList");

	gamelist->Get("ListDrives",        &m_ListDrives,  false);
	gamelist->Get("ListWad",           &m_ListWad,     true);
	gamelist->Get("ListWii",           &m_ListWii,     true);
	gamelist->Get("ListGC",            &m_ListGC,      true);
	gamelist->Get("ListJap",           &m_ListJap,     true);
	gamelist->Get("ListPal",           &m_ListPal,     true);
	gamelist->Get("ListUsa",           &m_ListUsa,     true);

	gamelist->Get("ListAustralia",     &m_ListAustralia,     true);
	gamelist->Get("ListFrance",        &m_ListFrance,        true);
	gamelist->Get("ListGermany",       &m_ListGermany,       true);
	gamelist->Get("ListItaly",         &m_ListItaly,         true);
	gamelist->Get("ListKorea",         &m_ListKorea,         true);
	gamelist->Get("ListNetherlands",   &m_ListNetherlands,   true);
	gamelist->Get("ListRussia",        &m_ListRussia,        true);
	gamelist->Get("ListSpain",         &m_ListSpain,         true);
	gamelist->Get("ListTaiwan",        &m_ListTaiwan,        true);
	gamelist->Get("ListWorld",         &m_ListWorld,         true);
	gamelist->Get("ListUnknown",       &m_ListUnknown,       true);
	gamelist->Get("ListSort",          &m_ListSort,       3);
	gamelist->Get("ListSortSecondary", &m_ListSort2,      0);

	// Determines if compressed games display in blue
	gamelist->Get("ColorCompressed", &m_ColorCompressed, true);

	// Gamelist columns toggles
	gamelist->Get("ColumnPlatform",   &m_showSystemColumn,  true);
	gamelist->Get("ColumnBanner",     &m_showBannerColumn,  true);
	gamelist->Get("ColumnNotes",      &m_showMakerColumn,   true);
	gamelist->Get("ColumnID",         &m_showIDColumn,      false);
	gamelist->Get("ColumnRegion",     &m_showRegionColumn,  true);
	gamelist->Get("ColumnSize",       &m_showSizeColumn,    true);
	gamelist->Get("ColumnState",      &m_showStateColumn,   true);
}

void SConfig::LoadCoreSettings(IniFile& ini)
{
	IniFile::Section* core = ini.GetOrCreateSection("Core");

	core->Get("HLE_BS2",      &m_LocalCoreStartupParameter.bHLE_BS2, false);
#ifdef _M_X86
	core->Get("CPUCore",      &m_LocalCoreStartupParameter.iCPUCore, PowerPC::CORE_JIT64);
#elif _M_ARM_64
	core->Get("CPUCore",      &m_LocalCoreStartupParameter.iCPUCore, PowerPC::CORE_JITARM64);
#else
	core->Get("CPUCore",      &m_LocalCoreStartupParameter.iCPUCore, PowerPC::CORE_INTERPRETER);
#endif
	core->Get("Fastmem",           &m_LocalCoreStartupParameter.bFastmem,      true);
	core->Get("DSPHLE",            &m_LocalCoreStartupParameter.bDSPHLE,       true);
	core->Get("CPUThread",         &m_LocalCoreStartupParameter.bCPUThread,    true);
	core->Get("SkipIdle",          &m_LocalCoreStartupParameter.bSkipIdle,     true);
	core->Get("SyncOnSkipIdle",    &m_LocalCoreStartupParameter.bSyncGPUOnSkipIdleHack, true);
	core->Get("DefaultISO",        &m_LocalCoreStartupParameter.m_strDefaultISO);
	core->Get("DVDRoot",           &m_LocalCoreStartupParameter.m_strDVDRoot);
	core->Get("Apploader",         &m_LocalCoreStartupParameter.m_strApploader);
	core->Get("EnableCheats",      &m_LocalCoreStartupParameter.bEnableCheats, false);
	core->Get("SelectedLanguage",  &m_LocalCoreStartupParameter.SelectedLanguage, 0);
	core->Get("DPL2Decoder",       &m_LocalCoreStartupParameter.bDPL2Decoder, false);
	core->Get("Latency",           &m_LocalCoreStartupParameter.iLatency, 2);
	core->Get("MemcardAPath",      &m_strMemoryCardA);
	core->Get("MemcardBPath",      &m_strMemoryCardB);
	core->Get("AgpCartAPath",      &m_strGbaCartA);
	core->Get("AgpCartBPath",      &m_strGbaCartB);
	core->Get("SlotA",       (int*)&m_EXIDevice[0], EXIDEVICE_MEMORYCARD);
	core->Get("SlotB",       (int*)&m_EXIDevice[1], EXIDEVICE_NONE);
	core->Get("SerialPort1", (int*)&m_EXIDevice[2], EXIDEVICE_NONE);
	core->Get("BBA_MAC",           &m_bba_mac);
	core->Get("TimeProfiling",     &m_LocalCoreStartupParameter.bJITILTimeProfiling, false);
	core->Get("OutputIR",          &m_LocalCoreStartupParameter.bJITILOutputIR,      false);
	for (int i = 0; i < MAX_SI_CHANNELS; ++i)
	{
		core->Get(StringFromFormat("SIDevice%i", i), (u32*)&m_SIDevice[i], (i == 0) ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE);
	}
	core->Get("WiiSDCard",                 &m_WiiSDCard,                                   false);
	core->Get("WiiKeyboard",               &m_WiiKeyboard,                                 false);
	core->Get("WiimoteContinuousScanning", &m_WiimoteContinuousScanning,                   false);
	core->Get("WiimoteEnableSpeaker",      &m_WiimoteEnableSpeaker,                        false);
	core->Get("RunCompareServer",          &m_LocalCoreStartupParameter.bRunCompareServer, false);
	core->Get("RunCompareClient",          &m_LocalCoreStartupParameter.bRunCompareClient, false);
	core->Get("MMU",                       &m_LocalCoreStartupParameter.bMMU,              false);
	core->Get("BBDumpPort",                &m_LocalCoreStartupParameter.iBBDumpPort,       -1);
	core->Get("SyncGPU",                   &m_LocalCoreStartupParameter.bSyncGPU,          false);
	core->Get("SyncGpuMaxDistance",        &m_LocalCoreStartupParameter.iSyncGpuMaxDistance,  200000);
	core->Get("SyncGpuMinDistance",        &m_LocalCoreStartupParameter.iSyncGpuMinDistance, -200000);
	core->Get("SyncGpuOverclock",          &m_LocalCoreStartupParameter.fSyncGpuOverclock, 1.0);
	core->Get("FastDiscSpeed",             &m_LocalCoreStartupParameter.bFastDiscSpeed,    false);
	core->Get("DCBZ",                      &m_LocalCoreStartupParameter.bDCBZOFF,          false);
	core->Get("FrameLimit",                &m_Framelimit,                                  1); // auto frame limit by default
	core->Get("Overclock",                 &m_OCFactor,                                    1.0f);
	core->Get("OverclockEnable",           &m_OCEnable,                                    false);
	core->Get("FrameSkip",                 &m_FrameSkip,                                   0);
	core->Get("GFXBackend",                &m_LocalCoreStartupParameter.m_strVideoBackend, "");
	core->Get("GPUDeterminismMode",        &m_LocalCoreStartupParameter.m_strGPUDeterminismMode, "auto");
	core->Get("GameCubeAdapter",           &m_GameCubeAdapter,                             false);
	core->Get("AdapterRumble",             &m_AdapterRumble,                               true);
}

void SConfig::LoadMovieSettings(IniFile& ini)
{
	IniFile::Section* movie = ini.GetOrCreateSection("Movie");

	movie->Get("PauseMovie", &m_PauseMovie, false);
	movie->Get("Author", &m_strMovieAuthor, "");
	movie->Get("DumpFrames", &m_DumpFrames, false);
	movie->Get("DumpFramesSilent", &m_DumpFramesSilent, false);
	movie->Get("ShowInputDisplay", &m_ShowInputDisplay, false);
}

void SConfig::LoadDSPSettings(IniFile& ini)
{
	IniFile::Section* dsp = ini.GetOrCreateSection("DSP");

	dsp->Get("EnableJIT", &m_DSPEnableJIT, true);
	dsp->Get("DumpAudio", &m_DumpAudio, false);
#if defined __linux__ && HAVE_ALSA
	dsp->Get("Backend", &sBackend, BACKEND_ALSA);
#elif defined __APPLE__
	dsp->Get("Backend", &sBackend, BACKEND_COREAUDIO);
#elif defined _WIN32
	dsp->Get("Backend", &sBackend, BACKEND_XAUDIO2);
#elif defined ANDROID
	dsp->Get("Backend", &sBackend, BACKEND_OPENSLES);
#else
	dsp->Get("Backend", &sBackend, BACKEND_NULLSOUND);
#endif
	dsp->Get("Volume", &m_Volume, 100);
	dsp->Get("CaptureLog", &m_DSPCaptureLog, false);

	m_IsMuted = false;
}

void SConfig::LoadInputSettings(IniFile& ini)
{
	IniFile::Section* input = ini.GetOrCreateSection("Input");

	input->Get("BackgroundInput", &m_BackgroundInput, false);
}

void SConfig::LoadFifoPlayerSettings(IniFile& ini)
{
	IniFile::Section* fifoplayer = ini.GetOrCreateSection("FifoPlayer");

	fifoplayer->Get("LoopReplay", &m_LocalCoreStartupParameter.bLoopFifoReplay, true);
}
