From 93efce6f58776b6e99c6002ed92bf14786654df5 Mon Sep 17 00:00:00 2001 From: Nico Meister Date: Mon, 19 Oct 2026 18:36:57 +0200 Subject: [PATCH] v2.9.5: schnelleres Umschalten (Miiverse-CA aus dem SD-Zwischenspeicher, kurzes Warten beim Beenden) Co-Authored-By: Claude Opus 5.5 --- Makefile | 2 +- source/admin.c | 2 +- source/admin.h | 2 +- source/main.c | 5 +++++ source/olvpatch.c | 26 ++++++++++++++++++++++++-- source/olvpatch.h | 3 ++- source/patcher.c | 4 +++- source/patcher.h | 3 +++ source/update.c | 2 +- source/update.h | 2 +- 10 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 61dbb3c..2b780f7 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ SOURCES := source INCLUDES := source # Bei jedem Release erhöhen - das Auto-Update vergleicht diese Nummer -VERSION := 2.9.4 +VERSION := 2.9.5 APP_TITLE := MBMNET APP_DESCRIPTION := Dein eigenes 3DS-Netzwerk diff --git a/source/admin.c b/source/admin.c index a0c3e37..6ddf07b 100644 --- a/source/admin.c +++ b/source/admin.c @@ -52,7 +52,7 @@ bool admin_is(void) { return isAdmin; } bool admin_finish(void) { if (!thread) return true; - if (R_FAILED(threadJoin(thread, 15ULL * 1000 * 1000 * 1000))) return false; // läuft noch + if (R_FAILED(threadJoin(thread, 300ULL * 1000 * 1000))) return false; // läuft noch threadFree(thread); thread = NULL; return true; diff --git a/source/admin.h b/source/admin.h index 3e82637..501a240 100644 --- a/source/admin.h +++ b/source/admin.h @@ -6,4 +6,4 @@ void admin_start(const char *server, u32 pid); // Admin? (gemerkte Antwort, bis der Server geantwortet hat) bool admin_is(void); -bool admin_finish(void); // wartet höchstens 15 s, false = läuft noch +bool admin_finish(void); // wartet höchstens 0,3 s, false = läuft noch diff --git a/source/main.c b/source/main.c index e86875c..2f7ae7c 100644 --- a/source/main.c +++ b/source/main.c @@ -293,8 +293,10 @@ static void maintenance_worker(void *arg) } } bool changed = false; + patchFreshCa = true; // im Hintergrund darf es dauern: Miiverse-CA frisch vom Server // Patches auffrischen: neue Versionen bringen neue Ziele mit (z. B. Miiverse ab v2.8.0) if (patch_enable(MBMNET_SERVER, &changed, detail, sizeof(detail)) && changed) maintenanceChanged = true; + patchFreshCa = false; maintaining = false; } @@ -685,6 +687,9 @@ int main(int argc, char **argv) // schreiben sie nach dem Freigeben hinein und Luma zeigt einen Absturz (z. B. beim Neustart nach "Nintendo"). ftpctl_stop(NULL, 0); shopctl_exit(); + // Update- und Admin-Abfrage nur kurz abwarten: Läuft noch etwas, beendet sich die App hart (schneller + // Neustart nach dem Umschalten). Das Auffrischen schreibt Patch-Dateien - darauf warten (beim Umschalten + // ist es ohnehin schon fertig, Aktionen warten darauf). bool clean = true; if (maintenanceThread) { if (R_SUCCEEDED(threadJoin(maintenanceThread, 20ULL * 1000 * 1000 * 1000))) threadFree(maintenanceThread); diff --git a/source/olvpatch.c b/source/olvpatch.c index bac27cb..fff9c49 100644 --- a/source/olvpatch.c +++ b/source/olvpatch.c @@ -13,6 +13,7 @@ #include <3ds.h> #include #include +#include #include "olvpatch.h" @@ -47,17 +48,38 @@ static u32 fetch(const char *server, const char *path, u8 *buf, u32 cap) return R_SUCCEEDED(rc) && status == 200 && got < cap ? got : 0; } -bool olvpatch_fetch_ca(const char *server, u8 *der, u32 *derLen) +// Zwischenspeicher der CA auf der SD: Beim Umschalten nicht jedes Mal den Server fragen (das dauerte +// Sekunden, solange das WLAN noch verbindet). Frisch geholt wird beim Auffrischen im Hintergrund. +#define CA_DER_CACHE "sdmc:/3ds/mbmnet/cache/olv-ca.der" + +static u32 read_cached(u8 *der) { + FILE *f = fopen(CA_DER_CACHE, "rb"); + if (!f) return 0; + u32 n = fread(der, 1, CA_MAX + 1, f); + fclose(f); + FILE *pem = fopen(CA_PEM_FILE, "rb"); // die PEM-Datei für den Browser muss auch da sein + if (!pem) return 0; + fclose(pem); + return n > 0 && n <= CA_MAX ? n : 0; +} + +bool olvpatch_fetch_ca(const char *server, u8 *der, u32 *derLen, bool fresh) +{ + if (!fresh && (*derLen = read_cached(der))) return true; static u8 pem[2048]; u32 n = fetch(server, "/olv/ca.der", der, CA_MAX + 1); - if (n == 0 || n > CA_MAX) return false; + if (n == 0 || n > CA_MAX) return !fresh ? false : (*derLen = read_cached(der)) != 0; u32 p = fetch(server, "/olv/ca.pem", pem, sizeof(pem)); if (p == 0) return false; // Der Browser der Miiverse-App liest die CA von der SD-Karte FILE *f = fopen(CA_PEM_FILE, "wb"); bool ok = f && fwrite(pem, 1, p, f) == p; if (f) fclose(f); + mkdir("sdmc:/3ds/mbmnet", 0777); + mkdir("sdmc:/3ds/mbmnet/cache", 0777); + f = fopen(CA_DER_CACHE, "wb"); + if (f) { fwrite(der, 1, n, f); fclose(f); } *derLen = n; return ok; } diff --git a/source/olvpatch.h b/source/olvpatch.h index e7a9c12..8c0f115 100644 --- a/source/olvpatch.h +++ b/source/olvpatch.h @@ -4,7 +4,8 @@ // Miiverse-Patch (siehe olvpatch.c). Die CA kommt vom MBMNET-Server (/olv/ca.der, /olv/ca.pem). // Holt die MBMNET-CA (DER, höchstens 889 Bytes) und legt die PEM-Fassung für den Browser auf die SD. -bool olvpatch_fetch_ca(const char *server, u8 *der, u32 *derLen); +// fresh = false: erst den Zwischenspeicher auf der SD versuchen (schnell), sonst vom Server holen +bool olvpatch_fetch_ca(const char *server, u8 *der, u32 *derLen, bool fresh); // Ist das genau die Miiverse-Version, für die der Patch gebaut ist? (entpackter .code) bool olvpatch_supported(const u8 *code, u32 size); // Baut den IPS-Patch. Gibt die Länge zurück, 0 bei Fehler. diff --git a/source/patcher.c b/source/patcher.c index 6a5398a..e2f7537 100644 --- a/source/patcher.c +++ b/source/patcher.c @@ -414,6 +414,8 @@ static bool write_ips(const char *path, const u8 *data, u32 n, bool *changed) // Miiverse-Patch (olvpatch.c): eigene Code-Änderungen + MBMNET-CA statt einfacher Text-Regeln. // 0 = nicht installiert, andere Version oder CA nicht vom Server zu holen (dann bleibt ein alter Patch stehen). +bool patchFreshCa; // CA frisch vom Server holen (Auffrischen im Hintergrund), sonst aus dem Zwischenspeicher + static u32 build_miiverse(const Target *t, const char *server, u8 *out, u32 cap) { static u8 der[1024]; @@ -421,7 +423,7 @@ static u32 build_miiverse(const Target *t, const char *server, u8 *out, u32 cap) static int caState; // 0 = noch nicht geholt, 1 = da, -1 = nicht zu holen char fp[64]; fingerprint(t->tid, fp, sizeof(fp)); // leer = kein Zwischenspeicher, gebaut wird trotzdem - if (caState == 0) caState = olvpatch_fetch_ca(server, der, &derLen) ? 1 : -1; + if (caState == 0) caState = olvpatch_fetch_ca(server, der, &derLen, patchFreshCa) ? 1 : -1; if (caState < 0) return 0; u32 sum = 2166136261u; // FNV-1a über die CA: neue CA -> neuer Patch diff --git a/source/patcher.h b/source/patcher.h index f405f2e..2cd6276 100644 --- a/source/patcher.h +++ b/source/patcher.h @@ -4,6 +4,9 @@ // Offizieller MBMNET-Server. Über "Server-Adresse" lässt sich ein anderer eintragen (z. B. zum Testen). // Fester MBMNET-Server: einfaches HTTP über den NetBird-TCP-Service auf Port 81. // Höchstens 21 Zeichen passen in den Patch. +// true: patch_enable holt die Miiverse-CA frisch vom Server (sonst aus dem Zwischenspeicher auf der SD) +extern bool patchFreshCa; + #define MBMNET_SERVER "mbmnetapi.mbm.wtf:81" #define APP_DIR "sdmc:/3ds/mbmnet" diff --git a/source/update.c b/source/update.c index 3ce54ab..39dd0b7 100644 --- a/source/update.c +++ b/source/update.c @@ -273,7 +273,7 @@ bool update_finish(void) if (!thread) return true; // Läuft die Abfrage noch, nicht freigeben (sonst schreibt der Thread in freigegebenen Speicher). // false = läuft noch, die App muss sich hart beenden (main.c). - if (R_FAILED(threadJoin(thread, 15ULL * 1000 * 1000 * 1000))) return false; + if (R_FAILED(threadJoin(thread, 300ULL * 1000 * 1000))) return false; threadFree(thread); thread = NULL; return true; diff --git a/source/update.h b/source/update.h index 3c8db80..40f3519 100644 --- a/source/update.h +++ b/source/update.h @@ -21,7 +21,7 @@ void update_download(void); bool update_pending(void); UpdateState update_state(void); const char *update_new_version(void); -// Wartet auf den Hintergrund-Thread (höchstens 15 s). false = läuft noch. +// Wartet auf den Hintergrund-Thread (höchstens 0,3 s). false = läuft noch. bool update_finish(void); // Laufender Download-Versuch (1-3) int update_attempt(void);