diff --git a/CMakeLists.txt b/CMakeLists.txt
index ca7a086ef..ec6d92f07 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -450,7 +450,9 @@ target_sources(${PROJECT_NAME} PRIVATE
core/cfg/cfg.h
core/cfg/cl.cpp
core/cfg/ini.cpp
- core/cfg/ini.h)
+ core/cfg/ini.h
+ core/cfg/option.cpp
+ core/cfg/option.h)
target_sources(${PROJECT_NAME} PRIVATE
core/hw/aica/aica.cpp
diff --git a/core/build.h b/core/build.h
index f2d95348e..dcfd6132b 100755
--- a/core/build.h
+++ b/core/build.h
@@ -202,10 +202,6 @@
#define FEAT_DSPREC DYNAREC_NONE
#endif
-#if defined(TARGET_NO_COREIO_HTTP)
-#define FEAT_HAS_COREIO_HTTP 0
-#endif
-
//defaults
#ifndef FEAT_SHREC
@@ -232,24 +228,10 @@
#endif
#endif
-#ifndef FEAT_HAS_COREIO_HTTP
- #define FEAT_HAS_COREIO_HTTP 1
-#endif
-
#if HOST_CPU == CPU_X64 || HOST_CPU == CPU_ARM64
#define HOST_64BIT_CPU
#endif
-//Depricated build configs
-#ifdef HOST_NO_REC
-#error Dont use HOST_NO_REC
-#endif
-
-#ifdef HOST_NO_AREC
-#error Dont use HOST_NO_AREC
-#endif
-
-
// Compiler Related
#ifndef _MSC_VER
@@ -278,7 +260,7 @@
#define GD_CLOCK 33868800 //GDROM XTAL -- 768fs
#define AICA_CORE_CLOCK (GD_CLOCK*4/3) //[45158400] GD->PLL 3:4 -> AICA CORE -- 1024fs
-#define ADAC_CLOCK (AICA_CORE_CLOCK/2) //[11289600] 44100*256, AICA CORE -> PLL 4:1 -> ADAC -- 256fs
+#define ADAC_CLOCK (AICA_CORE_CLOCK/4) //[11289600] 44100*256, AICA CORE -> PLL 4:1 -> ADAC -- 256fs
#define AICA_ARM_CLOCK (AICA_CORE_CLOCK/2) //[22579200] AICA CORE -> PLL 2:1 -> ARM
#define AICA_SDRAM_CLOCK (GD_CLOCK*2) //[67737600] GD-> PLL 2 -> SDRAM
#define SH4_MAIN_CLOCK (200*1000*1000) //[200000000] XTal(13.5) -> PLL (33.3) -> PLL 1:6 (200)
diff --git a/core/cfg/cfg.cpp b/core/cfg/cfg.cpp
index c407f1119..0298a06eb 100644
--- a/core/cfg/cfg.cpp
+++ b/core/cfg/cfg.cpp
@@ -1,9 +1,3 @@
-/*
- Config file crap
- Supports various things, as virtual config entries and such crap
- Works surprisingly well considering how old it is ...
-*/
-
#include "cfg.h"
#include "ini.h"
#include "stdclass.h"
@@ -15,10 +9,8 @@ static bool save_config = true;
static bool autoSave = true;
static emucfg::ConfigFile cfgdb;
-static std::string game_id;
-static bool has_game_specific_config = false;
-void savecfgf()
+static void saveConfigFile()
{
FILE* cfgfile = nowide::fopen(cfgPath.c_str(), "wt");
if (!cfgfile)
@@ -31,49 +23,13 @@ void savecfgf()
std::fclose(cfgfile);
}
}
-void cfgSaveStr(const char * Section, const char * Key, const char * String)
+void cfgSaveStr(const std::string& section, const std::string& key, const std::string& string)
{
- const std::string section(Section);
- const std::string key(Key);
- const std::string value(String);
- if (cfgHasGameSpecificConfig())
- {
- if (cfgdb.get(section, key, "") == value)
- // Same value as main config: delete entry
- cfgdb.delete_entry(game_id, key);
- else
- cfgdb.set(game_id, key, value);
- }
- else
- cfgdb.set(section, key, value);
+ cfgdb.set(section, key, string);
if (save_config && autoSave)
- savecfgf();
+ saveConfigFile();
}
-//New config code
-
-/*
- I want config to be really flexible .. so , here is the new implementation :
-
- Functions :
- cfgLoadInt : Load an int , if it does not exist save the default value to it and return it
- cfgSaveInt : Save an int
- cfgLoadStr : Load a str , if it does not exist save the default value to it and return it
- cfgSaveStr : Save a str
- cfgExists : Returns true if the Section:Key exists. If Key is null , it retuns true if Section exists
-
- Config parameters can be read from the config file , and can be given at the command line
- -cfg section:key=value -> defines a value at command line
- If a cfgSave* is made on a value defined by command line , then the command line value is replaced by it
-
- cfg values set by command line are not written to the cfg file , unless a cfgSave* is used
-*/
-
-///////////////////////////////
-/*
-** This will verify there is a working file @ ./szIniFn
-** - if not present, it will write defaults
-*/
bool cfgOpen()
{
@@ -99,7 +55,7 @@ bool cfgOpen()
{
// Config file didn't exist
INFO_LOG(COMMON, "Creating new empty config file at '%s'", cfgPath.c_str());
- savecfgf();
+ saveConfigFile();
}
else
{
@@ -111,105 +67,54 @@ bool cfgOpen()
return true;
}
-//Implementations of the interface :)
-//Section must be set
-//If key is 0 , it looks for the section
-//0 : not found
-//1 : found section , key was 0
-//2 : found section & key
-s32 cfgExists(const char * Section, const char * Key)
+std::string cfgLoadStr(const std::string& section, const std::string& key, const std::string& def)
{
- if(cfgdb.has_entry(std::string(Section), std::string(Key)))
- {
- return 2;
- }
- else
- {
- return (cfgdb.has_section(std::string(Section)) ? 1 : 0);
- }
+ return cfgdb.get(section, key, def);
}
-void cfgLoadStr(const char * Section, const char * Key, char * Return,const char* Default)
+void cfgSaveInt(const std::string& section, const std::string& key, s32 value)
{
- std::string value = cfgdb.get(Section, Key, Default);
- // FIXME: Buffer overflow possible
- strcpy(Return, value.c_str());
+ cfgSaveStr(section, key, std::to_string(value));
}
-std::string cfgLoadStr(const char * Section, const char * Key, const char* Default)
+s32 cfgLoadInt(const std::string& section, const std::string& key, s32 def)
{
- std::string v = cfgdb.get(std::string(Section), std::string(Key), std::string(Default));
- if (cfgHasGameSpecificConfig())
- v = cfgdb.get(game_id, std::string(Key), v);
-
- return v;
+ return cfgdb.get_int(section, key, def);
}
-//These are helpers , mainly :)
-void cfgSaveInt(const char * Section, const char * Key, s32 Int)
+void cfgSaveBool(const std::string& section, const std::string& key, bool value)
{
- char str[32];
- sprintf(str, "%d", Int);
- cfgSaveStr(Section, Key, str);
+ cfgSaveStr(section, key, value ? "yes" : "no");
}
-s32 cfgLoadInt(const char * Section, const char * Key,s32 Default)
+bool cfgLoadBool(const std::string& section, const std::string& key, bool def)
{
- s32 v = cfgdb.get_int(std::string(Section), std::string(Key), Default);
- if (cfgHasGameSpecificConfig())
- v = cfgdb.get_int(game_id, std::string(Key), v);
-
- return v;
+ return cfgdb.get_bool(section, key, def);
}
-void cfgSaveBool(const char * Section, const char * Key, bool BoolValue)
+void cfgSetVirtual(const std::string& section, const std::string& key, const std::string& value)
{
- cfgSaveStr(Section, Key, BoolValue ? "yes" : "no");
+ cfgdb.set(section, key, value, true);
}
-bool cfgLoadBool(const char * Section, const char * Key,bool Default)
+bool cfgIsVirtual(const std::string& section, const std::string& key)
{
- bool v = cfgdb.get_bool(std::string(Section), std::string(Key), Default);
- if (cfgHasGameSpecificConfig())
- v = cfgdb.get_bool(game_id, std::string(Key), v);
-
- return v;
+ return cfgdb.is_virtual(section, key);
}
-void cfgSetVirtual(const char * Section, const char * Key, const char * String)
+bool cfgHasSection(const std::string& section)
{
- cfgdb.set(std::string(Section), std::string(Key), std::string(String), true);
+ return cfgdb.has_section(section);
}
-void cfgSetGameId(const char *id)
+void cfgDeleteSection(const std::string& section)
{
- game_id = id;
-}
-
-const char *cfgGetGameId()
-{
- return game_id.c_str();
-}
-
-bool cfgHasGameSpecificConfig()
-{
- return has_game_specific_config || cfgdb.has_section(game_id);
-}
-
-void cfgMakeGameSpecificConfig()
-{
- has_game_specific_config = true;
-}
-
-void cfgDeleteGameSpecificConfig()
-{
- has_game_specific_config = false;
- cfgdb.delete_section(game_id);
+ cfgdb.delete_section(section);
}
void cfgSetAutoSave(bool autoSave)
{
::autoSave = autoSave;
if (autoSave)
- savecfgf();
+ saveConfigFile();
}
diff --git a/core/cfg/cfg.h b/core/cfg/cfg.h
index ccb4ea72f..89ab53a58 100644
--- a/core/cfg/cfg.h
+++ b/core/cfg/cfg.h
@@ -1,29 +1,19 @@
#pragma once
#include "types.h"
-/*
-** cfg* prototypes, if you pass NULL to a cfgSave* it will wipe out the section
-** } if you pass it to lpKey it will wipe out that particular entry
-** } if you add write to something it will create it if its not present
-** } ** Strings passed to LoadStr should be MAX_PATH in size ! **
-*/
bool cfgOpen();
-s32 cfgLoadInt(const char * lpSection, const char * lpKey,s32 Default);
-void cfgSaveInt(const char * lpSection, const char * lpKey, s32 Int);
-void cfgLoadStr(const char * lpSection, const char * lpKey, char * lpReturn,const char* lpDefault);
-std::string cfgLoadStr(const char * Section, const char * Key, const char* Default);
-void cfgSaveStr(const char * lpSection, const char * lpKey, const char * lpString);
-void cfgSaveBool(const char * Section, const char * Key, bool BoolValue);
-bool cfgLoadBool(const char * Section, const char * Key,bool Default);
-s32 cfgExists(const char * Section, const char * Key);
-void cfgSetVirtual(const char * lpSection, const char * lpKey, const char * lpString);
+s32 cfgLoadInt(const std::string& section, const std::string& key, s32 def);
+void cfgSaveInt(const std::string& section, const std::string& key, s32 value);
+std::string cfgLoadStr(const std::string& section, const std::string& key, const std::string& def);
+void cfgSaveStr(const std::string& section, const std::string& key, const std::string& value);
+void cfgSaveBool(const std::string& section, const std::string& key, bool value);
+bool cfgLoadBool(const std::string& section, const std::string& key, bool def);
+void cfgSetVirtual(const std::string& section, const std::string& key, const std::string& value);
+bool cfgIsVirtual(const std::string& section, const std::string& key);
-bool ParseCommandLine(int argc,char* argv[]);
+bool ParseCommandLine(int argc, char *argv[]);
-void cfgSetGameId(const char *id);
-const char *cfgGetGameId();
-bool cfgHasGameSpecificConfig();
-void cfgMakeGameSpecificConfig();
-void cfgDeleteGameSpecificConfig();
void cfgSetAutoSave(bool autoSave);
+bool cfgHasSection(const std::string& section);
+void cfgDeleteSection(const std::string& section);
diff --git a/core/cfg/ini.cpp b/core/cfg/ini.cpp
index 507b5b9a2..16c36493e 100644
--- a/core/cfg/ini.cpp
+++ b/core/cfg/ini.cpp
@@ -299,5 +299,13 @@ void ConfigFile::delete_entry(const std::string& section_name, const std::string
section->delete_entry(entry_name);
}
+bool ConfigFile::is_virtual(const std::string& section_name, const std::string& entry_name)
+{
+ ConfigSection *section = get_section(section_name, true);
+ if (section == nullptr)
+ return false;
+ return section->has_entry(entry_name);
+}
+
} // namespace emucfg
diff --git a/core/cfg/ini.h b/core/cfg/ini.h
index e9951723d..763b75112 100644
--- a/core/cfg/ini.h
+++ b/core/cfg/ini.h
@@ -31,6 +31,7 @@ struct ConfigFile {
public:
bool has_section(const std::string& name);
bool has_entry(const std::string& section_name, const std::string& entry_name);
+ bool is_virtual(const std::string& section_name, const std::string& entry_name);
void parse(FILE* fd);
void save(FILE* fd);
diff --git a/core/cfg/option.cpp b/core/cfg/option.cpp
new file mode 100644
index 000000000..5c4827342
--- /dev/null
+++ b/core/cfg/option.cpp
@@ -0,0 +1,141 @@
+/*
+ Copyright 2021 flyinghead
+
+ This file is part of Flycast.
+
+ Flycast is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ Flycast is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Flycast. If not, see .
+*/
+#include "option.h"
+
+namespace config {
+
+// Dynarec
+
+Option DynarecEnabled("Dynarec.Enabled", true);
+Option DynarecIdleSkip("Dynarec.idleskip", true);
+Option DynarecUnstableOpt("Dynarec.unstable-opt");
+Option DynarecSafeMode("Dynarec.safe-mode");
+Option DisableVmem32("Dynarec.DisableVmem32");
+
+// General
+
+Option Cable("Dreamcast.Cable", 3); // TV Composite
+Option Region("Dreamcast.Region", 1); // USA
+Option Broadcast("Dreamcast.Broadcast", 0); // NTSC
+Option Language("Dreamcast.Language", 1); // English
+Option FullMMU("Dreamcast.FullMMU");
+Option ForceWindowsCE("Dreamcast.ForceWindowsCE");
+Option AutoSavestate("Dreamcast.AutoSavestate");
+
+// Sound
+
+Option LimitFPS("aica.LimitFPS", true);
+Option DSPEnabled("aica.DSPEnabled", false);
+Option DisableSound("aica.NoSound");
+#if HOST_CPU == CPU_ARM
+Option AudioBufferSize("aica.BufferSize", 5644); // 128 ms
+#else
+Option AudioBufferSize("aica.BufferSize", 2822); // 64 ms
+#endif
+
+OptionString AudioBackend("backend", "auto", "audio");
+
+// Rendering
+
+RendererOption RendererType;
+Option UseMipmaps("rend.UseMipmaps", true);
+Option Widescreen("rend.WideScreen");
+Option ShowFPS("rend.ShowFPS");
+Option RenderToTextureBuffer("rend.RenderToTextureBuffer");
+Option RenderToTextureUpscale("rend.RenderToTextureUpscale", 1);
+Option TranslucentPolygonDepthMask("rend.TranslucentPolygonDepthMask");
+Option ModifierVolumes("rend.ModifierVolumes", true);
+Option Clipping("rend.Clipping", true);
+Option TextureUpscale("rend.TextureUpscale", 1);
+Option MaxFilteredTextureSize("rend.MaxFilteredTextureSize", 256);
+Option ExtraDepthScale("rend.ExtraDepthScale", 1.f);
+Option CustomTextures("rend.CustomTextures");
+Option DumpTextures("rend.DumpTextures");
+Option ScreenScaling("rend.ScreenScaling", 100);
+Option ScreenStretching("rend.ScreenStretching", 100);
+Option Fog("rend.Fog", true);
+Option FloatVMUs("rend.FloatVMUs");
+Option Rotate90("rend.Rotate90");
+Option PerStripSorting("rend.PerStripSorting");
+Option DelayFrameSwapping("rend.DelayFrameSwapping");
+Option WidescreenGameHacks("rend.WidescreenGameHacks");
+std::array