// Ä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 #include #include #include #include #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); }