Files
MBMNET-APP/source/lumaconfig.c
T
2026-10-18 17:05:44 +02:00

136 lines
4.1 KiB
C

// Ändert Optionen in Lumas Konfiguration (/luma/config.ini):
// splash_position -> Boot-Splash "MBMNET aktiv" anzeigen
// enable_external_firm_and_modules -> nötig, damit Luma die Patches in /luma/sysmodules lädt
// enable_game_patching -> nötig, damit Luma Patches in /luma/titles lädt (Miiverse)
// Beim Zurücksetzen wird eine Option nur wieder ausgeschaltet, wenn MBMNET sie eingeschaltet hat
// (Merker in /3ds/mbmnet/...).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include "lumaconfig.h"
#define CONFIG_FILE "sdmc:/luma/config.ini"
#define SPLASH_MARKER "sdmc:/3ds/mbmnet/splash-war-aus"
#define MODULES_MARKER "sdmc:/3ds/mbmnet/module-waren-aus"
#define PATCHING_MARKER "sdmc:/3ds/mbmnet/game-patching-war-aus"
// Setzt "key = value". Gibt den alten Wert in oldValue zurück. false, wenn Datei/Option fehlt.
static bool set_option(const char *key, const char *value, char *oldValue, size_t oldLen)
{
FILE *f = fopen(CONFIG_FILE, "rb");
if (!f) return false;
fseek(f, 0, SEEK_END);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
if (size <= 0 || size > 64 * 1024) { fclose(f); return false; }
char *in = malloc(size + 1);
char *out = malloc(size + 128);
bool ok = in && out && fread(in, 1, size, f) == (size_t)size;
fclose(f);
if (!ok) { free(in); free(out); return false; }
in[size] = 0;
size_t keyLen = strlen(key);
bool found = false;
size_t o = 0;
for (char *line = in; *line;) {
char *end = strchr(line, '\n');
size_t len = end ? (size_t)(end - line + 1) : strlen(line);
char *p = line;
while (*p == ' ' || *p == '\t') p++;
char *eq = strchr(p, '=');
bool isKey = !found && strncmp(p, key, keyLen) == 0 && (p[keyLen] == ' ' || p[keyLen] == '=')
&& eq && eq < line + len;
if (isKey) {
char *v = eq + 1;
while (*v == ' ') v++;
size_t vl = strcspn(v, "\r\n");
snprintf(oldValue, oldLen, "%.*s", (int)vl, v);
o += sprintf(out + o, "%s = %s%s", key, value, (end && end > line && end[-1] == '\r') ? "\r\n" : "\n");
found = true;
} else {
memcpy(out + o, line, len);
o += len;
}
line += len;
}
if (found && strcasecmp(oldValue, value) != 0) {
f = fopen(CONFIG_FILE, "wb");
ok = f && fwrite(out, 1, o, f) == o;
if (f) fclose(f);
}
free(in);
free(out);
return found && ok;
}
static void touch(const char *path)
{
FILE *m = fopen(path, "w");
if (m) fclose(m);
}
static bool exists(const char *path)
{
struct stat st;
return stat(path, &st) == 0;
}
bool lumaconfig_enable_splash(void)
{
char old[32] = "";
if (!set_option("splash_position", "after payloads", old, sizeof(old))) return false;
if (strcasecmp(old, "off") == 0) touch(SPLASH_MARKER);
return true;
}
void lumaconfig_restore_splash(void)
{
if (!exists(SPLASH_MARKER)) return; // war schon vorher an: nichts ändern
char old[32] = "";
set_option("splash_position", "off", old, sizeof(old));
remove(SPLASH_MARKER);
}
bool lumaconfig_enable_modules(void)
{
char old[8] = "";
if (!set_option("enable_external_firm_and_modules", "1", old, sizeof(old))) return false;
if (strcmp(old, "0") == 0) touch(MODULES_MARKER);
return true;
}
void lumaconfig_keep_modules(void)
{
remove(MODULES_MARKER);
}
void lumaconfig_restore_modules(void)
{
if (!exists(MODULES_MARKER)) return;
char old[8] = "";
set_option("enable_external_firm_and_modules", "0", old, sizeof(old));
remove(MODULES_MARKER);
}
bool lumaconfig_enable_game_patching(void)
{
char old[8] = "";
if (!set_option("enable_game_patching", "1", old, sizeof(old))) return false;
if (strcmp(old, "0") != 0) return false; // war schon an
touch(PATCHING_MARKER);
return true;
}
void lumaconfig_restore_game_patching(void)
{
if (!exists(PATCHING_MARKER)) return;
char old[8] = "";
set_option("enable_game_patching", "0", old, sizeof(old));
remove(PATCHING_MARKER);
}