From 52e0270c8014fa9c62c0c749600bf7d07c0c6c8f Mon Sep 17 00:00:00 2001 From: Nico Meister Date: Sun, 18 Oct 2026 22:43:18 +0200 Subject: [PATCH] =?UTF-8?q?v2.9.4:=20einmalige=20Umstellung=20auf=20den=20?= =?UTF-8?q?Zweitnamen=20(MBMNET-ID=20unter=20echtem=20Namen=20wird=20f?= =?UTF-8?q?=C3=BCr=20Pretendo=20gel=C3=B6st)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- Makefile | 2 +- source/main.c | 34 ++++++++++++++++++++++++++++++++-- source/nnid.c | 19 +++++++++++++++++++ source/nnid.h | 2 ++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index a8a817c..61dbb3c 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.3 +VERSION := 2.9.4 APP_TITLE := MBMNET APP_DESCRIPTION := Dein eigenes 3DS-Netzwerk diff --git a/source/main.c b/source/main.c index 2cf92f3..8226879 100644 --- a/source/main.c +++ b/source/main.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include "patcher.h" #include "update.h" @@ -394,14 +396,40 @@ static bool enable(bool confirmed, char *msg, size_t msglen) return true; } +// Umstellung auf den Zweitnamen (einmalig): Steht im MBMNET-Platz noch die ID unter dem echten Namen, blockiert +// sie eine gleichnamige Pretendo-ID (022-2571). Dann wird sie EINMAL gelöst; beim nächsten Wechsel zu MBMNET +// meldet man sich mit ".m" an, und ab dann bleibt alles verknüpft. note bekommt den Hinweis. +#define ALIAS_DONE_MARKER "sdmc:/3ds/mbmnet/zweitname-umgestellt" +static bool free_mbmnet_name(char *note, size_t len) +{ + note[0] = 0; + FILE *m = fopen(ALIAS_DONE_MARKER, "r"); + if (m) { fclose(m); return false; } + char id[20]; + u8 slot = frdswitch_slot_of(FRIEND_ACCOUNT_MBMNET); + if (!slot || !frdswitch_slot_linked(FRIEND_ACCOUNT_MBMNET, id, sizeof(id))) return false; + size_t n = strlen(id); + if (n >= 2 && !strcasecmp(id + n - 2, ".m")) return false; // schon der Zweitname + remember_mbmnet_id(id); + if (!nnid_unlink_slot(slot, note, len)) return false; + mkdir("sdmc:/3ds/mbmnet", 0777); + m = fopen(ALIAS_DONE_MARKER, "w"); + if (m) { fputs(id, m); fclose(m); } + snprintf(note, len, "\"%s\" ist jetzt frei für Pretendo.\nZurück bei MBMNET einmal mit \"%.14s.m\" anmelden,\ndanach nie wieder.", id, id); + return true; +} + // Zurück zu Nintendo. true = der 3DS muss jetzt neu starten. static bool disable(bool confirmed, char *msg, size_t msglen) { (void)confirmed; char detail[160] = ""; PatchState st = patch_state(); + char note[200]; if (st == STATE_ORIGINAL && frdswitch_current() == FRIEND_ACCOUNT_NINTENDO) { - snprintf(msg, msglen, "Nintendo ist schon aktiv."); + if (free_mbmnet_name(note, sizeof(note))) snprintf(msg, msglen, "Nintendo ist schon aktiv.\n%s", note); + else if (note[0]) snprintf(msg, msglen, "%s", note); + else snprintf(msg, msglen, "Nintendo ist schon aktiv."); return false; } if (st == STATE_FOREIGN) { @@ -412,11 +440,13 @@ static bool disable(bool confirmed, char *msg, size_t msglen) // anmelden). Den Namen merken, für den Hinweis auf den Zweitnamen. char id[20] = ""; if (frdswitch_current() == FRIEND_ACCOUNT_MBMNET && nnid_linked(id, sizeof(id))) remember_mbmnet_id(id); + bool freed = free_mbmnet_name(note, sizeof(note)); bool created = false; if (frdswitch_current() != FRIEND_ACCOUNT_NINTENDO && !frdswitch_to(FRIEND_ACCOUNT_NINTENDO, &created, msg, msglen)) return false; patch_disable(detail, sizeof(detail)); spotpass_unregister(); - snprintf(msg, msglen, "Nintendo aktiv! Der 3DS startet neu.\nDeine Nintendo-Freundesliste ist wieder da."); + if (freed) snprintf(msg, msglen, "Nintendo aktiv! Der 3DS startet neu.\n%s", note); + else snprintf(msg, msglen, "Nintendo aktiv! Der 3DS startet neu.\nDeine Nintendo-Freundesliste ist wieder da."); return true; } diff --git a/source/nnid.c b/source/nnid.c index 21224bd..b192ae4 100644 --- a/source/nnid.c +++ b/source/nnid.c @@ -193,6 +193,25 @@ bool nnid_name_elsewhere(const char *name, u8 exceptSlot) return false; } +bool nnid_unlink_slot(u8 slot, char *msg, size_t msglen) +{ + if (!ready) return false; + AccountId id = { 0 }; + ACT_GetAccountInfo(id, sizeof(id), slot, INFO_TYPE_ACCOUNT_ID); + if (!id[0]) return true; + FILE *log = fopen(LOG_FILE, "a"); + Result rc = ACTA_UnbindServerAccount(slot, true); + if (log) fprintf(log, "Platz %u (%s) lösen %08lX\n", slot, id, (unsigned long)rc); + if (R_FAILED(rc)) { + Result u = ACTA_UnloadConsoleAccount(); + rc = ACTA_UnbindServerAccount(slot, true); + if (log) fprintf(log, " nach Abmelden (%08lX): %08lX\n", (unsigned long)u, (unsigned long)rc); + } + if (log) fclose(log); + if (R_FAILED(rc)) snprintf(msg, msglen, "\"%s\" (Platz %u) ließ sich nicht lösen (Fehler %08lX).", id, slot, (unsigned long)rc); + return R_SUCCEEDED(rc); +} + // Löst die ID "name" in allen Konto-Plätzen außer exceptSlot (nur auf dem 3DS). false + msg bei Fehler. bool nnid_unlink_named(const char *name, u8 exceptSlot, char *msg, size_t msglen) { diff --git a/source/nnid.h b/source/nnid.h index 43d8977..73d8f76 100644 --- a/source/nnid.h +++ b/source/nnid.h @@ -18,6 +18,8 @@ bool nnid_unlink(char *msg, size_t msglen); // Gibt es die ID "name" in einem Konto-Platz außer exceptSlot? bool nnid_name_elsewhere(const char *name, u8 exceptSlot); // Löst die ID "name" in allen Konto-Plätzen außer exceptSlot (nur auf dem 3DS) +// Löst die ID in einem bestimmten Konto-Platz (nur auf dem 3DS). false + msg bei Fehler. +bool nnid_unlink_slot(u8 slot, char *msg, size_t msglen); bool nnid_unlink_named(const char *name, u8 exceptSlot, char *msg, size_t msglen); // Schreibt alle Konto-Plätze in die Diagnose void nnid_dump(FILE *f);