7#if defined(SDL_LIBRETRO_IMPLEMENTATION) && !defined(SDL_LIBRETRO_CONFIG_IMPL_ONCE)
8#define SDL_LIBRETRO_CONFIG_IMPL_ONCE
13static void SDL_Libretro_SanitizeSectionName(
char* dst,
size_t dstSize,
const char* name) {
16 SDL_strlcpy(dst, name, dstSize);
17 for (
char* p = dst; *p; ++p) {
18 if (*p ==
'[' || *p ==
']' || *p ==
'\n' || *p ==
'\r' || *p ==
' ') {
40 if (!lr || !file)
return false;
43 SDL_free(lr->iniFile);
50 SDL_ini* ini = INI_Load(file);
52 if (SDL_GetPathInfo(file, NULL)) {
53 SDL_SetError(
"[SDL_Libretro] Failed to load config '%s', leaving it untouched: %s", file, SDL_GetError());
54 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"%s", SDL_GetError());
58 if (!ini)
return false;
62 lr->iniFile = SDL_strdup(file);
70 if (INI_HasValue(ini, NULL,
"volume"))
72 if (INI_HasValue(ini, NULL,
"username"))
74 if (INI_HasValue(ini, NULL,
"audiolatency"))
76 if (INI_HasValue(ini, NULL,
"fitmode"))
78 if (INI_HasValue(ini, NULL,
"scalemode"))
80 if (INI_HasValue(ini, NULL,
"savedirectory"))
82 if (INI_HasValue(ini, NULL,
"systemdirectory"))
84 if (INI_HasValue(ini, NULL,
"coredirectory"))
86 if (INI_HasValue(ini, NULL,
"coreassetsdirectory"))
88 if (INI_HasValue(ini, NULL,
"rewindenabled") || INI_HasValue(ini, NULL,
"rewindframes") || INI_HasValue(ini, NULL,
"rewindinterval")) {
91 Sint64 frames = INI_GetInt(ini, NULL,
"rewindframes", (Sint64)lr->rewindCapacity);
92 Sint64 interval = INI_GetInt(ini, NULL,
"rewindinterval", (Sint64)lr->rewindCaptureInterval);
93 unsigned bufferFrames = (frames > 0 && frames <= SDL_MAX_UINT32) ? (
unsigned)frames : 0;
94 unsigned captureInterval = (interval > 0 && interval <= SDL_MAX_UINT32) ? (
unsigned)interval : 0;
98 lr->rewindCapacity = bufferFrames;
99 lr->rewindCaptureInterval = captureInterval;
102 if (INI_HasValue(ini, NULL,
"rewindmemorylimit"))
104 if (INI_HasValue(ini, NULL,
"mouseport"))
106 if (INI_HasValue(ini, NULL,
"language")) {
108 Sint64 language = INI_GetInt(ini, NULL,
"language", (Sint64)lr->language);
111 if (INI_HasValue(ini, NULL,
"filebrowserdirectory"))
112 SDL_strlcpy(lr->fileBrowserStartDirectory, INI_GetString(ini, NULL,
"filebrowserdirectory",
""),
sizeof(lr->fileBrowserStartDirectory));
115 for (
int button = 0; button < SDL_LIBRETRO_MAX_JOYPAD_BUTTONS; button++) {
116 if (!INI_HasValue(ini,
"keyboard", SDL_Libretro_JoypadButtonNames[button])) {
119 SDL_Scancode scancode = SDL_GetScancodeFromName(INI_GetString(ini,
"keyboard", SDL_Libretro_JoypadButtonNames[button],
""));
120 if (scancode != SDL_SCANCODE_UNKNOWN) {
129 SDL_snprintf(section,
sizeof(section),
"gamepad%u", port + 1);
130 for (
int button = 0; button < SDL_LIBRETRO_MAX_JOYPAD_BUTTONS; button++) {
131 if (!INI_HasValue(ini, section, SDL_Libretro_JoypadButtonNames[button])) {
134 SDL_GamepadButton pad = SDL_GetGamepadButtonFromString(INI_GetString(ini, section, SDL_Libretro_JoypadButtonNames[button],
""));
135 if (pad != SDL_GAMEPAD_BUTTON_INVALID) {
140 const char* analog = INI_GetString(ini, section,
"AnalogToDigital", NULL);
141 if (analog != NULL) {
143 if (SDL_strcasecmp(analog, SDL_Libretro_AnalogToDigitalNames[mode]) == 0) {
169 if (!lr)
return false;
170 if (!org || org[0] ==
'\0') org =
"SDL_libretro";
171 if (!app || app[0] ==
'\0') app =
"SDL_libretro";
172 char* prefPath = SDL_GetPrefPath(org, app);
173 if (!prefPath)
return false;
174 char path[SDL_LIBRETRO_MAX_PATH];
175 SDL_snprintf(path,
sizeof(path),
"%s%s.cfg", prefPath, app);
183static void SDL_Libretro_SetCoreConfigOption(
void* userdata,
const SDL_ini* ini,
const char* section,
const char* key,
const char* value) {
192static bool SDL_Libretro_LoadCoreConfig(SDL_Libretro* lr) {
197 SDL_Libretro_SanitizeSectionName(section,
sizeof(section), lr->core.libraryName);
200 if (section[0] ==
'\0') {
203 INI_EnumerateKeys(lr->ini, section, &SDL_Libretro_SetCoreConfigOption, (
void*)lr);
212static const char* SDL_Libretro_GetSavedCoreOption(
const SDL_Libretro* lr,
const char* key) {
213 if (!lr || !lr->ini || !key || lr->core.libraryName[0] ==
'\0')
return NULL;
215 SDL_Libretro_SanitizeSectionName(section,
sizeof(section), lr->core.libraryName);
216 if (section[0] ==
'\0')
return NULL;
217 return INI_GetString(lr->ini, section, key, NULL);
223static bool SDL_Libretro_SaveCoreConfig(SDL_Libretro* lr) {
226 SDL_Libretro_SanitizeSectionName(section,
sizeof(section), lr->core.libraryName);
227 if (section[0] ==
'\0') {
231 for (
int i = 0; i < count; i++) {
233 if (!option)
continue;
236 INI_SetString(lr->ini, section, option->
key, val);
244static bool SDL_Libretro_SaveConfig(SDL_Libretro* lr) {
245 if (!lr || !lr->ini || !lr->iniFile)
return false;
248 SDL_Libretro_SaveCoreConfig(lr);
260 INI_SetInt(lr->ini, NULL,
"rewindframes", (Sint64)lr->rewindCapacity);
261 INI_SetInt(lr->ini, NULL,
"rewindinterval", (Sint64)lr->rewindCaptureInterval);
265 INI_SetInt(lr->ini, NULL,
"language", (Sint64)lr->language);
266 INI_SetString(lr->ini, NULL,
"filebrowserdirectory", lr->fileBrowserStartDirectory);
268 for (
int button = 0; button < SDL_LIBRETRO_MAX_JOYPAD_BUTTONS; button++) {
269 INI_SetString(lr->ini,
"keyboard", SDL_Libretro_JoypadButtonNames[button], SDL_GetScancodeName(lr->keyboardPlayer1[button]));
275 SDL_snprintf(section,
sizeof(section),
"gamepad%u", port + 1);
276 for (
int button = 0; button < SDL_LIBRETRO_MAX_JOYPAD_BUTTONS; button++) {
277 const char* padName = SDL_GetGamepadStringForButton(lr->gamepadButtons[port][button]);
278 INI_SetString(lr->ini, section, SDL_Libretro_JoypadButtonNames[button], padName != NULL ? padName :
"");
280 INI_SetString(lr->ini, section,
"AnalogToDigital", SDL_Libretro_AnalogToDigitalNames[lr->analogToDigital[port]]);
284 char tempPath[SDL_LIBRETRO_MAX_PATH];
285 SDL_IOStream* io = SDL_Libretro_OpenSaveFile(lr->iniFile, tempPath,
sizeof(tempPath));
286 if (!io)
return false;
287 return SDL_Libretro_CommitSaveFile(io, INI_Save_IO(lr->ini, io,
false), tempPath, lr->iniFile);
293static bool SDL_Libretro_CloseConfig(SDL_Libretro* lr) {
294 if (!lr)
return false;
295 bool ok = SDL_Libretro_SaveConfig(lr);
296 SDL_free(lr->iniFile);
298 INI_Destroy(lr->ini);
#define SDL_LIBRETRO_MAX_USERS
The number of controller ports (gamepads) the frontend tracks.
bool SDL_Libretro_IsCoreReady(const SDL_Libretro *lr)
Indicates whether a core is loaded.
bool SDL_Libretro_SetCoreAssetsDirectory(SDL_Libretro *lr, const char *path)
Sets where cores look for their assets, reported through RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY.
bool SDL_Libretro_SetSystemDirectory(SDL_Libretro *lr, const char *path)
Sets where cores look for system files (BIOS, firmware, etc).
bool SDL_Libretro_SetCoreDirectory(SDL_Libretro *lr, const char *path)
Sets the associated libretro core directory, where the default set of cores will be loaded from.
void SDL_Libretro_SetRewindMemoryLimit(SDL_Libretro *lr, size_t maxBytes)
Set the maximum number of bytes of encoded delta history to retain.
const char * SDL_Libretro_GetUsername(SDL_Libretro *lr)
Get the username reported to cores.
SDL_ScaleMode SDL_Libretro_GetScaleMode(const SDL_Libretro *lr)
Gets the texture scale mode used when the libretro frame is scaled.
SDL_LibretroFitMode SDL_Libretro_GetFitMode(const SDL_Libretro *lr)
Gets how the frame is fit into the destination rectangle when rendered.
SDL_LibretroFitMode
When rendering the libretro context, determine how to display within the destination.
bool SDL_Libretro_SetRewindEnabled(SDL_Libretro *lr, bool enabled, unsigned bufferFrames, unsigned captureInterval)
Enable or disable the rewind system.
bool SDL_Libretro_InitConfig(SDL_Libretro *lr, const char *org, const char *app)
Sets up the config file to be the default path, accoring to the organization and app name.
bool SDL_Libretro_InitConfigFile(SDL_Libretro *lr, const char *file)
Initializes the config system based on the given file.
bool SDL_Libretro_SetFitMode(SDL_Libretro *lr, SDL_LibretroFitMode mode)
Sets how the frame is fit into the destination rectangle when rendered.
const SDL_LibretroOption * SDL_Libretro_GetOptionByIndex(const SDL_Libretro *lr, unsigned index)
Retrieve a core option by its registration index.
void SDL_Libretro_SetVolume(SDL_Libretro *lr, float volume)
Set the audio volume when playing sounds.
const char * SDL_Libretro_GetCoreAssetsDirectory(SDL_Libretro *lr)
Get the core assets directory.
void SDL_Libretro_SetGamepadMapping(SDL_Libretro *lr, unsigned port, int retroButton, SDL_GamepadButton button)
Maps an SDL gamepad button to a RETRO_DEVICE_ID_JOYPAD_* button on the given controller port.
void SDL_Libretro_SetAudioLatency(SDL_Libretro *lr, unsigned latencyMs)
Set the desired minimum audio latency for the audio stream.
float SDL_Libretro_GetVolume(const SDL_Libretro *lr)
Get the audio volume.
void SDL_Libretro_SetMousePort(SDL_Libretro *lr, unsigned port)
Selects the one controller port that the mouse drives.
bool SDL_Libretro_GetRewindEnabled(const SDL_Libretro *lr)
Check whether the rewind system is enabled (independent of current direction).
const char * SDL_Libretro_GetSystemDirectory(SDL_Libretro *lr)
Get the system directory.
bool SDL_Libretro_SetOptionValue(SDL_Libretro *lr, const char *key, const char *value)
Set a core option's value; fails if the value isn't one the core declared.
bool SDL_Libretro_SetSaveDirectory(SDL_Libretro *lr, const char *path)
Sets where content will be saved.
size_t SDL_Libretro_GetRewindMemoryLimit(const SDL_Libretro *lr)
Get the current rewind memory budget in bytes (0 if unbounded).
unsigned SDL_Libretro_GetOptionCount(const SDL_Libretro *lr)
Get the number of core options that have been set.
bool SDL_Libretro_SetUsername(SDL_Libretro *lr, const char *username)
Sets the username reported to cores through RETRO_ENVIRONMENT_GET_USERNAME.
bool SDL_Libretro_SetScaleMode(SDL_Libretro *lr, SDL_ScaleMode mode)
Sets the texture scale mode used when the libretro frame is scaled.
unsigned SDL_Libretro_GetAudioLatency(const SDL_Libretro *lr)
Get the minimum audio latency for the audio stream.
void SDL_Libretro_SetAnalogToDigital(SDL_Libretro *lr, unsigned port, SDL_LibretroAnalogToDigital stick)
Selects which analog stick, if any, also registers D-Pad presses on the given controller port,...
const char * SDL_Libretro_GetCoreDirectory(SDL_Libretro *lr)
Get the core directory.
const char * SDL_Libretro_GetSaveDirectory(SDL_Libretro *lr)
Get the save directory.
SDL_LibretroAnalogToDigital
Which analog stick, if any, also registers D-Pad presses for a controller port.
unsigned SDL_Libretro_GetMousePort(const SDL_Libretro *lr)
Get the controller port that the mouse drives.
void SDL_Libretro_SetLanguage(SDL_Libretro *lr, int language)
Override the language reported to cores through RETRO_ENVIRONMENT_GET_LANGUAGE.
void SDL_Libretro_SetKeyboardMapping(SDL_Libretro *lr, int retroButton, SDL_Scancode scancode)
Maps a keyboard key to a RETRO_DEVICE_ID_JOYPAD_* button for Player 1 (controller port 0).
@ SDL_LIBRETRO_ANALOG_TO_DIGITAL_COUNT
The number of possible modes.
A core option and its current state.
const char * value
The current value.
const char * key
Unique identifier the core queries.
const char * defaultValue
The default value.