v3.0.4: eigene Werkzeug-Seite, Logs der MBMNET-Server (HTTPS mit MBMNET-CA), Admin nur mit signiertem Nachweis vom Server
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
718c605f6d
commit
d1f5f5add3
+133
-70
@@ -1,7 +1,7 @@
|
||||
// MBMNET Switcher - schaltet den 3DS zwischen MBMNET und Nintendo (Original) um.
|
||||
//
|
||||
// Unten zwei Kacheln: MBMNET und Nintendo. Antippen schaltet um, unter der aktiven steht "Aktiv".
|
||||
// SELECT blendet die Entwickler-Werkzeuge ein und aus (beim Öffnen immer aus).
|
||||
// SELECT öffnet für Admins (vom Server bestätigt) eine eigene Werkzeug-Seite, darin u. a. die Logs.
|
||||
#include <3ds.h>
|
||||
#include <citro2d.h>
|
||||
#include <stdio.h>
|
||||
@@ -19,27 +19,12 @@
|
||||
#include "spotpass.h"
|
||||
#include "shopctl.h"
|
||||
#include "olvpatch.h"
|
||||
#include "logview.h"
|
||||
#include "ui.h"
|
||||
|
||||
#define TOP_W 400
|
||||
#define BOT_W 320
|
||||
#define SCR_H 240
|
||||
|
||||
// Farben (gleiche Palette wie Logo und Webseite)
|
||||
#define COL_RED C2D_Color32(0xE4, 0x00, 0x2B, 0xFF)
|
||||
#define COL_RED_DARK C2D_Color32(0x9E, 0x00, 0x1E, 0xFF)
|
||||
#define COL_BG C2D_Color32(0x16, 0x19, 0x1F, 0xFF)
|
||||
#define COL_BG2 C2D_Color32(0x22, 0x26, 0x2E, 0xFF)
|
||||
#define COL_CARD C2D_Color32(0x2A, 0x2F, 0x39, 0xFF)
|
||||
#define COL_CARD_HI C2D_Color32(0x3A, 0x41, 0x4E, 0xFF)
|
||||
#define COL_WHITE C2D_Color32(0xFF, 0xFF, 0xFF, 0xFF)
|
||||
#define COL_MUTED C2D_Color32(0x9A, 0xA3, 0xAF, 0xFF)
|
||||
#define COL_GREEN C2D_Color32(0x22, 0xC5, 0x5E, 0xFF)
|
||||
#define COL_AMBER C2D_Color32(0xF5, 0x9E, 0x0B, 0xFF)
|
||||
#define COL_NINTENDO C2D_Color32(0xE6, 0x00, 0x12, 0xFF)
|
||||
|
||||
// Bedienelemente auf dem unteren Bildschirm. Die Werkzeuge gibt es nur für Admins (mit SELECT),
|
||||
// die Shop-Leiste nur ohne Werkzeuge.
|
||||
enum { BTN_ENABLE, BTN_DISABLE, BTN_DIAG, BTN_FTP, BTN_UNLINK, BTN_SPOTPASS, BTN_REBOOT, BTN_SHOP, BTN_SHOP_DEL, BTN_COUNT };
|
||||
// Bedienelemente auf dem unteren Bildschirm. Normal: MBMNET / Nintendo und die Shop-Leiste.
|
||||
// Werkzeug-Seite (nur Admins, SELECT): sechs große Knöpfe statt der Kacheln.
|
||||
enum { BTN_ENABLE, BTN_DISABLE, BTN_DIAG, BTN_FTP, BTN_UNLINK, BTN_SPOTPASS, BTN_REBOOT, BTN_LOGS, BTN_SHOP, BTN_SHOP_DEL, BTN_COUNT };
|
||||
|
||||
typedef struct { float x, y, w, h; } Box;
|
||||
|
||||
@@ -47,8 +32,13 @@ typedef struct { float x, y, w, h; } Box;
|
||||
#define TILE_W 142
|
||||
#define TILE_H_FULL 166
|
||||
#define TILE_H_ADMIN 160
|
||||
#define TOOL_COUNT 5
|
||||
static const Box toolBoxes[TOOL_COUNT] = { { 12, 184, 56, 42 }, { 72, 184, 56, 42 }, { 132, 184, 56, 42 }, { 192, 184, 56, 42 }, { 252, 184, 56, 42 } };
|
||||
#define TOOL_COUNT 6
|
||||
// Werkzeug-Seite: 2 Spalten, 3 Reihen, in dieser Reihenfolge
|
||||
static const int toolOrder[TOOL_COUNT] = { BTN_DIAG, BTN_FTP, BTN_UNLINK, BTN_SPOTPASS, BTN_LOGS, BTN_REBOOT };
|
||||
static const Box toolBoxes[TOOL_COUNT] = { { 12, 14, 144, 66 }, { 164, 14, 144, 66 }, { 12, 86, 144, 66 },
|
||||
{ 164, 86, 144, 66 }, { 12, 158, 144, 66 }, { 164, 158, 144, 66 } };
|
||||
static int tool_index(int btn) { for (int i = 0; i < TOOL_COUNT; i++) if (toolOrder[i] == btn) return i; return -1; }
|
||||
static bool logsOpen; // Werkzeuge > Logs ist offen
|
||||
|
||||
static const Box shopBox = { 12, 188, 216, 40 }, shopDelBox = { 232, 188, 76, 40 };
|
||||
static int shopVersion = -1; // installierte Version des MBMNET Shops (-1 = nicht installiert)
|
||||
@@ -56,8 +46,8 @@ static int shopVersion = -1; // installierte Version des MBMNET Shops (-1 = ni
|
||||
// Welche Knöpfe sind gerade da?
|
||||
static bool visible(int btn, bool admin)
|
||||
{
|
||||
if (btn <= BTN_DISABLE) return true;
|
||||
if (btn <= BTN_REBOOT) return admin;
|
||||
if (btn <= BTN_DISABLE) return !admin; // auf der Werkzeug-Seite keine Kacheln
|
||||
if (btn <= BTN_LOGS) return admin;
|
||||
if (btn == BTN_SHOP) return !admin;
|
||||
return !admin && shopVersion >= 0; // Entfernen nur, wenn installiert
|
||||
}
|
||||
@@ -68,13 +58,9 @@ static Box box_of(int btn, bool admin)
|
||||
switch (btn) {
|
||||
case BTN_ENABLE: return (Box){ 12, TILE_Y, TILE_W, h };
|
||||
case BTN_DISABLE: return (Box){ 166, TILE_Y, TILE_W, h };
|
||||
case BTN_DIAG: return toolBoxes[0];
|
||||
case BTN_FTP: return toolBoxes[1];
|
||||
case BTN_UNLINK: return toolBoxes[2];
|
||||
case BTN_SPOTPASS: return toolBoxes[3];
|
||||
case BTN_SHOP: return shopBox;
|
||||
case BTN_SHOP_DEL: return shopDelBox;
|
||||
default: return toolBoxes[4];
|
||||
default: return toolBoxes[tool_index(btn) < 0 ? 0 : tool_index(btn)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +78,41 @@ static void text(const char *s, float x, float y, float size, u32 color, u32 fla
|
||||
C2D_DrawText(&t, C2D_WithColor | flags, x, y, 0.5f, size, size, color);
|
||||
}
|
||||
|
||||
// Für logview.c (ui.h)
|
||||
void ui_text(const char *s, float x, float y, float size, u32 color, u32 flags) { text(s, x, y, size, color, flags); }
|
||||
|
||||
void ui_text_wrap(const char *s, float x, float y, float size, u32 color, float width)
|
||||
{
|
||||
C2D_Text t;
|
||||
C2D_TextParse(&t, textBuf, s);
|
||||
C2D_TextOptimize(&t);
|
||||
C2D_DrawText(&t, C2D_WithColor | C2D_WordWrap, x, y, 0.5f, size, size, color, width);
|
||||
}
|
||||
|
||||
static C2D_TextBuf measureBuf; // nur zum Messen, wird jedes Mal geleert
|
||||
float ui_text_width(const char *s, float size)
|
||||
{
|
||||
C2D_Text t;
|
||||
float w = 0;
|
||||
C2D_TextBufClear(measureBuf);
|
||||
C2D_TextParse(&t, measureBuf, s);
|
||||
C2D_TextGetDimensions(&t, size, size, &w, NULL);
|
||||
return w;
|
||||
}
|
||||
|
||||
void ui_fit(char *out, size_t len, const char *s, float size, float width)
|
||||
{
|
||||
snprintf(out, len, "%s", s);
|
||||
if (ui_text_width(out, size) <= width) return;
|
||||
size_t n = strlen(out);
|
||||
while (n > 1) {
|
||||
n--;
|
||||
while (n > 0 && (out[n] & 0xC0) == 0x80) n--; // nicht mitten in einem UTF-8-Zeichen
|
||||
snprintf(out + n, len - n, "...");
|
||||
if (ui_text_width(out, size) <= width) return;
|
||||
}
|
||||
}
|
||||
|
||||
static void round_rect(float x, float y, float w, float h, float r, u32 color)
|
||||
{
|
||||
C2D_DrawRectSolid(x + r, y, 0.5f, w - 2 * r, h, color);
|
||||
@@ -101,6 +122,7 @@ static void round_rect(float x, float y, float w, float h, float r, u32 color)
|
||||
C2D_DrawCircleSolid(x + r, y + h - r, 0.5f, r, color);
|
||||
C2D_DrawCircleSolid(x + w - r, y + h - r, 0.5f, r, color);
|
||||
}
|
||||
void ui_round_rect(float x, float y, float w, float h, float r, u32 color) { round_rect(x, y, w, h, r, color); }
|
||||
|
||||
// Das MBMNET-Logo: rotes abgerundetes Quadrat mit einem "M" aus verbundenen Netzwerk-Knoten.
|
||||
// Geometrie identisch zu assets/logo.svg (100x100-Raster).
|
||||
@@ -172,23 +194,32 @@ static void draw_top(PatchState st, const char *msg, bool admin, bool isAdmin)
|
||||
text(ftp, 10 + w + 12, 4, 0.4f, COL_GREEN, 0);
|
||||
}
|
||||
|
||||
float y = msg[0] || admin ? 26 : 62;
|
||||
// Werkzeug-Seite: Überschrift und was gerade wirklich los ist
|
||||
if (admin) {
|
||||
draw_logo(16, 26, 40);
|
||||
text("Werkzeuge", 66, 28, 0.75f, COL_WHITE, 0);
|
||||
text("Nur für Admins · B oder SELECT: zurück", 66, 52, 0.4f, COL_MUTED, 0);
|
||||
char line[112], id[20];
|
||||
const char *label = st == STATE_MBMNET ? "Patch: MBMNET" : st == STATE_FOREIGN ? "Patch: fremd (z. B. Pretendo)" : "Patch: keiner";
|
||||
snprintf(line, sizeof(line), "%s · angemeldet: %s · v" APP_VERSION, label, nnid_linked(id, sizeof(id)) ? id : "keine ID");
|
||||
round_rect(16, 76, TOP_W - 32, 22, 8, COL_CARD);
|
||||
text(line, 26, 80, 0.4f, COL_MUTED, 0);
|
||||
if (msg[0]) {
|
||||
round_rect(16, 104, TOP_W - 32, SCR_H - 112, 10, COL_CARD);
|
||||
text(msg, 28, 110, 0.46f, COL_WHITE, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
float y = msg[0] ? 26 : 62;
|
||||
draw_logo(TOP_W / 2 - 32, y, 64);
|
||||
text("MBMNET", TOP_W / 2, y + 70, 0.9f, COL_WHITE, C2D_AlignCenter);
|
||||
y += 108;
|
||||
|
||||
// Admins: was gerade wirklich los ist
|
||||
if (admin) {
|
||||
char line[96], id[20];
|
||||
const char *label = st == STATE_MBMNET ? "Patch: MBMNET" : st == STATE_FOREIGN ? "Patch: fremd (z. B. Pretendo)" : "Patch: keiner";
|
||||
snprintf(line, sizeof(line), "%s · NNID: %s%s", label, nnid_linked(id, sizeof(id)) ? id : "keine", isAdmin ? " · Admin" : "");
|
||||
text(line, TOP_W / 2, y, 0.42f, COL_MUTED, C2D_AlignCenter);
|
||||
y += 18;
|
||||
}
|
||||
if (msg[0]) {
|
||||
round_rect(16, y, TOP_W - 32, SCR_H - y - 8, 10, COL_CARD);
|
||||
text(msg, 28, y + 6, 0.46f, COL_WHITE, 0);
|
||||
} else if (!admin) {
|
||||
} else {
|
||||
text("Tippe unten auf MBMNET oder Nintendo.", TOP_W / 2, 200, 0.45f, COL_MUTED, C2D_AlignCenter);
|
||||
}
|
||||
}
|
||||
@@ -247,19 +278,29 @@ static void draw_shop_bar(int selected)
|
||||
static void draw_bottom(int selected, PatchState st, bool admin)
|
||||
{
|
||||
C2D_DrawRectSolid(0, 0, 0, BOT_W, SCR_H, COL_BG);
|
||||
draw_tile(BTN_ENABLE, selected == BTN_ENABLE, st == STATE_MBMNET, admin);
|
||||
draw_tile(BTN_DISABLE, selected == BTN_DISABLE, st == STATE_ORIGINAL, admin);
|
||||
if (!admin) { draw_shop_bar(selected); return; }
|
||||
|
||||
const char *labels[TOOL_COUNT] = { "Diagnose", ftpOn ? "FTP aus" : "FTP an", "ID lösen", "SpotPass", "Neustart" };
|
||||
if (!admin) {
|
||||
draw_tile(BTN_ENABLE, selected == BTN_ENABLE, st == STATE_MBMNET, admin);
|
||||
draw_tile(BTN_DISABLE, selected == BTN_DISABLE, st == STATE_ORIGINAL, admin);
|
||||
draw_shop_bar(selected);
|
||||
return;
|
||||
}
|
||||
// Werkzeug-Seite: sechs große Knöpfe mit kurzer Erklärung
|
||||
for (int i = 0; i < TOOL_COUNT; i++) {
|
||||
int btn = toolOrder[i];
|
||||
const char *label = btn == BTN_DIAG ? "Diagnose" : btn == BTN_FTP ? (ftpOn ? "FTP aus" : "FTP an")
|
||||
: btn == BTN_UNLINK ? "ID lösen" : btn == BTN_SPOTPASS ? "SpotPass-Test"
|
||||
: btn == BTN_LOGS ? "Logs" : "Neustart";
|
||||
const char *hint = btn == BTN_DIAG ? "Patches und Konten prüfen" : btn == BTN_FTP ? (ftpOn ? "läuft" : "SD-Karte im WLAN")
|
||||
: btn == BTN_UNLINK ? "nur auf dem 3DS" : btn == BTN_SPOTPASS ? "Mitteilung abholen"
|
||||
: btn == BTN_LOGS ? "alle MBMNET-Server" : "3DS neu starten";
|
||||
Box b = toolBoxes[i];
|
||||
bool sel = selected == BTN_DIAG + i;
|
||||
bool on = i == 1 && ftpOn;
|
||||
round_rect(b.x, b.y, b.w, b.h, 10, sel ? COL_CARD_HI : COL_CARD);
|
||||
if (sel) C2D_DrawRectSolid(b.x, b.y + 10, 0.5f, 4, b.h - 20, COL_RED);
|
||||
if (on) C2D_DrawCircleSolid(b.x + 12, b.y + b.h / 2, 0.5f, 4, COL_GREEN);
|
||||
text(labels[i], b.x + b.w / 2, b.y + 13, 0.45f, on ? COL_GREEN : COL_WHITE, C2D_AlignCenter);
|
||||
bool sel = selected == btn;
|
||||
bool on = btn == BTN_FTP && ftpOn;
|
||||
if (sel) round_rect(b.x - 2, b.y - 2, b.w + 4, b.h + 4, 13, COL_RED);
|
||||
round_rect(b.x, b.y, b.w, b.h, 11, sel ? COL_CARD_HI : COL_CARD);
|
||||
if (on) C2D_DrawCircleSolid(b.x + 14, b.y + 21, 0.5f, 4, COL_GREEN);
|
||||
text(label, b.x + b.w / 2, b.y + 14, 0.58f, on ? COL_GREEN : COL_WHITE, C2D_AlignCenter);
|
||||
text(hint, b.x + b.w / 2, b.y + 40, 0.38f, COL_MUTED, C2D_AlignCenter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,7 +536,7 @@ static bool run(int action, char *msg, size_t msglen)
|
||||
bool confirmed = armed == action;
|
||||
armed = -1;
|
||||
// Während ein Update lädt oder installiert wird, nicht umschalten (der 3DS würde mittendrin neu starten)
|
||||
if (action != BTN_DIAG && action != BTN_FTP && action != BTN_SPOTPASS && action < BTN_SHOP && update_pending()) {
|
||||
if (action != BTN_DIAG && action != BTN_FTP && action != BTN_SPOTPASS && action != BTN_LOGS && action < BTN_SHOP && update_pending()) {
|
||||
snprintf(msg, msglen, "Moment: Das Update auf v%s wird gerade installiert.\nDanach startet die App neu.", update_new_version());
|
||||
return false;
|
||||
}
|
||||
@@ -527,6 +568,11 @@ static bool run(int action, char *msg, size_t msglen)
|
||||
if (spotpass_test_start(MBMNET_SERVER, msg, msglen)) spotpassTestFrames = 0;
|
||||
return false;
|
||||
case BTN_REBOOT: return true;
|
||||
case BTN_LOGS:
|
||||
logsOpen = true;
|
||||
logview_open(MBMNET_SERVER);
|
||||
msg[0] = 0;
|
||||
return false;
|
||||
case BTN_SHOP:
|
||||
if (shopctl_job() == SHOPJOB_RUNNING) { snprintf(msg, msglen, "Der Shop wird gerade installiert ..."); return false; }
|
||||
if (shopVersion >= 0 && shopVersion >= APP_TITLE_VERSION) {
|
||||
@@ -568,7 +614,8 @@ int main(int argc, char **argv)
|
||||
C2D_Prepare();
|
||||
C3D_RenderTarget *top = C2D_CreateScreenTarget(GFX_TOP, GFX_LEFT);
|
||||
C3D_RenderTarget *bot = C2D_CreateScreenTarget(GFX_BOTTOM, GFX_LEFT);
|
||||
textBuf = C2D_TextBufNew(4096);
|
||||
textBuf = C2D_TextBufNew(8192); // Logs brauchen mehr Platz
|
||||
measureBuf = C2D_TextBufNew(1024);
|
||||
nnid_init();
|
||||
frdswitch_init();
|
||||
|
||||
@@ -588,14 +635,11 @@ int main(int argc, char **argv)
|
||||
snprintf(msg, sizeof(msg), "Neuer Speicherort für die Patches!\nBitte MBMNET einmal neu antippen.");
|
||||
PatchState st = patch_state();
|
||||
// Nur im MBMNET-Modus ist die verknüpfte NNID ein MBMNET-Konto
|
||||
// Werkzeuge nur für Admins: gefragt wird mit der ID im MBMNET-Platz (auch wenn gerade Nintendo aktiv ist)
|
||||
// Werkzeuge nur für Admins, und nur wenn der Server es per signiertem Anmelde-Nachweis bestätigt.
|
||||
// Das geht nur, solange das MBMNET-Konto angemeldet ist (MBMNET aktiv, ID verknüpft).
|
||||
{
|
||||
u8 mslot = frdswitch_slot_of(FRIEND_ACCOUNT_MBMNET);
|
||||
char mid[20];
|
||||
u32 mpid = 0;
|
||||
if (mslot && frdswitch_slot_linked(FRIEND_ACCOUNT_MBMNET, mid, sizeof(mid)))
|
||||
ACT_GetAccountInfo(&mpid, sizeof(mpid), mslot, INFO_TYPE_PRINCIPAL_ID);
|
||||
admin_start(server, mpid);
|
||||
admin_start(server, st == STATE_MBMNET && frdswitch_current() == FRIEND_ACCOUNT_MBMNET && nnid_linked(mid, sizeof(mid)));
|
||||
}
|
||||
// Ein SpotPass-Test von früher (App mitten im Test verlassen) darf nicht weiterlaufen
|
||||
spotpass_test_cancel();
|
||||
@@ -632,24 +676,39 @@ int main(int argc, char **argv)
|
||||
u32 down = hidKeysDown();
|
||||
if (--ftpCheckIn <= 0) { ftpCheckIn = 120; ftpOn = ftpctl_running(); }
|
||||
if (down & KEY_START && rebootIn == 0) break; // während des Umschaltens nicht abbrechen
|
||||
// Logs offen: die haben ihre eigene Bedienung
|
||||
if (logsOpen) {
|
||||
if (!admin_is() || !logview_update(down, hidKeysDownRepeat(), hidKeysHeld())) logsOpen = false;
|
||||
down = 0;
|
||||
}
|
||||
bool wasTools = toolsToggled;
|
||||
if (down & KEY_SELECT && admin_is()) toolsToggled = !toolsToggled;
|
||||
else if (down & KEY_SELECT) snprintf(msg, sizeof(msg), "%s", admin_why());
|
||||
if (down & KEY_B && toolsToggled) toolsToggled = false;
|
||||
if (!admin_is()) toolsToggled = false; // Werkzeuge nur für Admins (Server hat es bestätigt)
|
||||
// Werkzeuge nur mit SELECT, beim Öffnen immer aus
|
||||
bool admin = toolsToggled;
|
||||
if (!visible(selected, admin)) selected = admin || selected <= BTN_REBOOT ? BTN_ENABLE : BTN_SHOP;
|
||||
if (admin != wasTools) { selected = admin ? BTN_DIAG : BTN_ENABLE; armed = -1; }
|
||||
if (!visible(selected, admin)) selected = admin ? BTN_DIAG : selected <= BTN_LOGS ? BTN_ENABLE : BTN_SHOP;
|
||||
|
||||
int action = -1;
|
||||
// Oben die beiden Kacheln, unten (nur mit Werkzeugen) Diagnose / FTP / ID lösen / SpotPass / Neustart
|
||||
bool left = down & (KEY_LEFT | KEY_CPAD_LEFT), right = down & (KEY_RIGHT | KEY_CPAD_RIGHT);
|
||||
bool up = down & (KEY_UP | KEY_CPAD_UP), dn = down & (KEY_DOWN | KEY_CPAD_DOWN);
|
||||
if (selected < BTN_DIAG) { if (left || right) selected ^= 1; }
|
||||
else if (selected >= BTN_SHOP) { if ((left || right) && shopVersion >= 0) selected = selected == BTN_SHOP ? BTN_SHOP_DEL : BTN_SHOP; }
|
||||
else if (left) selected = selected == BTN_DIAG ? BTN_REBOOT : selected - 1;
|
||||
else if (right) selected = selected == BTN_REBOOT ? BTN_DIAG : selected + 1;
|
||||
if (dn && selected < BTN_DIAG) selected = admin ? (selected == BTN_ENABLE ? BTN_DIAG : BTN_REBOOT)
|
||||
: (selected == BTN_DISABLE && shopVersion >= 0 ? BTN_SHOP_DEL : BTN_SHOP);
|
||||
else if (up && selected >= BTN_SHOP) selected = selected == BTN_SHOP_DEL ? BTN_DISABLE : BTN_ENABLE;
|
||||
else if (up && selected >= BTN_DIAG) selected = selected == BTN_REBOOT ? BTN_DISABLE : BTN_ENABLE;
|
||||
if (admin) {
|
||||
// Werkzeug-Raster: 2 Spalten, 3 Reihen
|
||||
int i = tool_index(selected);
|
||||
if (i < 0) i = 0;
|
||||
if (left || right) i ^= 1;
|
||||
if (up && i >= 2) i -= 2;
|
||||
if (dn && i + 2 < TOOL_COUNT) i += 2;
|
||||
selected = toolOrder[i];
|
||||
} else {
|
||||
if (selected < BTN_DIAG) { if (left || right) selected ^= 1; }
|
||||
else if (selected >= BTN_SHOP) { if ((left || right) && shopVersion >= 0) selected = selected == BTN_SHOP ? BTN_SHOP_DEL : BTN_SHOP; }
|
||||
if (dn && selected < BTN_DIAG) selected = selected == BTN_DISABLE && shopVersion >= 0 ? BTN_SHOP_DEL : BTN_SHOP;
|
||||
else if (up && selected >= BTN_SHOP) selected = selected == BTN_SHOP_DEL ? BTN_DISABLE : BTN_ENABLE;
|
||||
}
|
||||
if (down & KEY_A) action = selected;
|
||||
// Y: verknüpfte ID lösen (für alle, mit Bestätigung durch ein zweites Y)
|
||||
if (down & KEY_Y) action = BTN_UNLINK;
|
||||
@@ -731,10 +790,12 @@ int main(int argc, char **argv)
|
||||
C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
|
||||
C2D_TargetClear(top, COL_BG);
|
||||
C2D_SceneBegin(top);
|
||||
draw_top(st, msg, admin, admin_is());
|
||||
if (logsOpen) logview_draw_top();
|
||||
else draw_top(st, msg, admin, admin_is());
|
||||
C2D_TargetClear(bot, COL_BG);
|
||||
C2D_SceneBegin(bot);
|
||||
draw_bottom(selected, st, admin);
|
||||
if (logsOpen) logview_draw_bottom();
|
||||
else draw_bottom(selected, st, admin);
|
||||
C3D_FrameEnd(0);
|
||||
}
|
||||
|
||||
@@ -754,6 +815,7 @@ int main(int argc, char **argv)
|
||||
else clean = false; // holt nur noch das Zertifikat: hart beenden ist ungefährlich (atomar geschrieben)
|
||||
}
|
||||
clean = admin_finish() && clean;
|
||||
clean = logview_finish() && clean;
|
||||
clean = update_finish() && clean;
|
||||
if (softReboot) {
|
||||
Result rc = nsInit();
|
||||
@@ -770,6 +832,7 @@ int main(int argc, char **argv)
|
||||
httpcExit();
|
||||
if (am) amExit();
|
||||
C2D_TextBufDelete(textBuf);
|
||||
C2D_TextBufDelete(measureBuf);
|
||||
C2D_Fini();
|
||||
C3D_Fini();
|
||||
gfxExit();
|
||||
|
||||
Reference in New Issue
Block a user