This commit is contained in:
JeffRuLz 2019-01-17 12:31:10 -06:00 committed by GitHub
parent b5b2c8feb2
commit 9f7a473fed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 176 additions and 138 deletions

View File

@ -20,7 +20,6 @@ BUILD := build
SOURCES := src SOURCES := src
DATA := data DATA := data
INCLUDES := include INCLUDES := include
#GAME_ICON := $(CURDIR)/icon.bmp
GAME_TITLE := TMFH GAME_TITLE := TMFH
GAME_SUBTITLE1 := Title Manager for HiyaCFW GAME_SUBTITLE1 := Title Manager for HiyaCFW

View File

@ -5,7 +5,6 @@
#include "maketmd.h" #include "maketmd.h"
#include <dirent.h> #include <dirent.h>
enum { enum {
INSTALL_MENU_INSTALL, INSTALL_MENU_INSTALL,
INSTALL_MENU_DELETE, INSTALL_MENU_DELETE,
@ -19,7 +18,6 @@ static int subMenu();
static void install(Menu* m); static void install(Menu* m);
static void delete(Menu* m); static void delete(Menu* m);
void installMenu() void installMenu()
{ {
Menu* m = (Menu*)malloc(sizeof(Menu)); Menu* m = (Menu*)malloc(sizeof(Menu));
@ -30,8 +28,7 @@ void installMenu()
//No files found //No files found
if (getNumberOfMenuItems(m) <= 0) if (getNumberOfMenuItems(m) <= 0)
{ {
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
iprintf("No files found.\n"); iprintf("No files found.\n");
iprintf("Place .nds, .app, or .dsi files in %s\n", ROM_PATH); iprintf("Place .nds, .app, or .dsi files in %s\n", ROM_PATH);
@ -153,8 +150,7 @@ void generateList(Menu* m)
{ {
if (m == NULL) return; if (m == NULL) return;
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
iprintf("Gathering files...\n"); iprintf("Gathering files...\n");
@ -227,9 +223,7 @@ void install(Menu* m)
} }
//Start installation //Start installation
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
iprintf("Installing %s\n", fpath); swiWaitForVBlank(); iprintf("Installing %s\n", fpath); swiWaitForVBlank();
tDSiHeader* header = (tDSiHeader*)malloc(sizeof(tDSiHeader)); tDSiHeader* header = (tDSiHeader*)malloc(sizeof(tDSiHeader));
@ -244,7 +238,7 @@ void install(Menu* m)
} }
else else
{ {
bool patchHeader = false; bool fixHeader = false;
//Read header and banner //Read header and banner
{ {
@ -259,9 +253,9 @@ void install(Menu* m)
if ((strcmp(header->ndshdr.gameCode, "####") == 0 && header->tid_low == 0x23232323) || if ((strcmp(header->ndshdr.gameCode, "####") == 0 && header->tid_low == 0x23232323) ||
(!*header->ndshdr.gameCode && header->tid_low == 0)) (!*header->ndshdr.gameCode && header->tid_low == 0))
{ {
iprintf("Patching header..."); fixHeader = true;
patchHeader = true; iprintf("Fixing Game Code...");
//Set as standard app //Set as standard app
header->tid_high = 0x00030004; header->tid_high = 0x00030004;
@ -282,19 +276,21 @@ void install(Menu* m)
} }
while (titleIsUsed(header->tid_low, header->tid_high) == true); while (titleIsUsed(header->tid_low, header->tid_high) == true);
//Fix header checksum iprintf("Done\n");
header->ndshdr.headerCRC16 = swiCRC16(0xFFFF, header, 0x15E); }
//Fix RSA signature
u8 buffer[20];
swiSHA1Calc(&buffer, header, 0xE00);
memcpy(&(header->rsa_signature[0x6C]), buffer, 20);
//Fix ique header
if (header->ndshdr.reserved1[8] == 0x80)
{
fixHeader = true;
iprintf("iQue Hack...");
header->ndshdr.reserved1[8] = 0x00;
iprintf("Done\n"); iprintf("Done\n");
} }
//Must be DSi rom //Must be DSi rom
//High title id must be one of three //High title id must be one of four
{ {
if (header->tid_high != 0x00030004 && if (header->tid_high != 0x00030004 &&
header->tid_high != 0x00030005 && header->tid_high != 0x00030005 &&
@ -341,8 +337,11 @@ void install(Menu* m)
if (getDsiFree() < fileSize) if (getDsiFree() < fileSize)
{ {
iprintf("No\n"); iprintf("No\n");
if (choiceBox("Try installing anyway?") == NO)
if (choicePrint("Try installing anyway?") == NO)
{
goto error; goto error;
}
} }
else else
{ {
@ -357,8 +356,11 @@ void install(Menu* m)
if (getMenuSlotsFree() <= 0) if (getMenuSlotsFree() <= 0)
{ {
iprintf("No\n"); iprintf("No\n");
if (choiceBox("Try installing anyway?") == NO)
if (choicePrint("Try installing anyway?") == NO)
{
goto error; goto error;
}
} }
else else
{ {
@ -383,19 +385,12 @@ void install(Menu* m)
{ {
closedir(dir); closedir(dir);
iprintf("Title %s is already used.\nInstall anyway?\n", titleID); char msg[512];
iprintf("Yes - A\nNo - B\n"); sprintf(msg, "Title %s is already used.\nInstall anyway?", titleID);
while (1) if (choicePrint(msg) == NO)
{ {
swiWaitForVBlank(); goto complete;
scanKeys();
if (keysDown() & KEY_A)
break;
if (keysDown() & KEY_B)
goto complete;
} }
} }
} }
@ -439,10 +434,18 @@ void install(Menu* m)
iprintf("Done\n"); iprintf("Done\n");
} }
//Write new patched header //Fix and write new header
if (patchHeader == true) if (fixHeader == true)
{ {
iprintf("Writing header..."); iprintf("Writing header...");
//Fix header checksum
header->ndshdr.headerCRC16 = swiCRC16(0xFFFF, header, 0x15E);
//Fix RSA signature
u8 buffer[20];
swiSHA1Calc(&buffer, header, 0xE00);
memcpy(&(header->rsa_signature[0x6C]), buffer, 20);
FILE* f = fopen(appPath, "r+"); FILE* f = fopen(appPath, "r+");

View File

@ -2,7 +2,7 @@
#include "menu.h" #include "menu.h"
#include <time.h> #include <time.h>
#define VERSION "0.5.2" #define VERSION "0.5.5"
enum { enum {
MAIN_MENU_INSTALL, MAIN_MENU_INSTALL,
@ -18,7 +18,7 @@ int main(int argc, char **argv)
{ {
srand(time(0)); srand(time(0));
//Setup top screen //Setup screens
REG_DISPCNT = MODE_FB0; REG_DISPCNT = MODE_FB0;
VRAM_A_CR = VRAM_ENABLE; VRAM_A_CR = VRAM_ENABLE;
@ -28,51 +28,52 @@ int main(int argc, char **argv)
vramSetBankA(VRAM_A_MAIN_BG); vramSetBankA(VRAM_A_MAIN_BG);
vramSetBankC(VRAM_C_SUB_BG); vramSetBankC(VRAM_C_SUB_BG);
consoleInit(&topScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true); consoleInit(&topScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, true, true);
consoleInit(&bottomScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true); consoleInit(&bottomScreen, 3, BgType_Text4bpp, BgSize_T_256x256, 31, 0, false, true);
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
VRAM_A[100] = 0xFFFF; VRAM_A[100] = 0xFFFF;
//Cannot use SD card
if (!fatInitDefault()) if (!fatInitDefault())
{ {
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
//iprintf("fatInitDefault...Failed\n"); iprintf("fatInitDefault()...Failed\n");
//iprintf("\nPress B to exit.\n"); iprintf("\nPress B to exit.\n");
for (int i = 0; i < 32*24; i++)
iprintf("%c", i);
keyWait(KEY_B | KEY_A | KEY_START); keyWait(KEY_B | KEY_A | KEY_START);
return 0;
} }
else
//Main menu selection
bool programEnd = false;
while (!programEnd)
{ {
bool programEnd = false; switch (mainMenu())
while (!programEnd)
{ {
switch (mainMenu()) case MAIN_MENU_INSTALL:
{ installMenu();
case MAIN_MENU_INSTALL: break;
installMenu();
break;
case MAIN_MENU_TITLES: case MAIN_MENU_TITLES:
titleMenu(); titleMenu();
break; break;
case MAIN_MENU_TEST: /* case MAIN_MENU_RESTORE:
testMenu(); restoreMenu();
break; break;
*/
case MAIN_MENU_TEST:
testMenu();
break;
case MAIN_MENU_EXIT: case MAIN_MENU_EXIT:
programEnd = true; programEnd = true;
break; break;
}
} }
} }
@ -81,18 +82,18 @@ int main(int argc, char **argv)
static int mainMenu() static int mainMenu()
{ {
consoleSelect(&topScreen); clearScreen(&topScreen);
consoleClear();
iprintf("\tTitle Manager for HiyaCFW\n"); iprintf("\tTitle Manager for HiyaCFW\n");
iprintf("\nversion %s\n", VERSION); iprintf("\nversion %s\n", VERSION);
iprintf("\x1b[23;0HJeff - 2018"); iprintf("\x1b[23;0HJeff - 2018-2019");
Menu* m = (Menu*)malloc(sizeof(Menu)); Menu* m = (Menu*)malloc(sizeof(Menu));
clearMenu(m); clearMenu(m);
addMenuItem(m, "Install"); addMenuItem(m, "Install");
addMenuItem(m, "Titles"); addMenuItem(m, "Titles");
// addMenuItem(m, "Restore");
addMenuItem(m, "Test"); addMenuItem(m, "Test");
addMenuItem(m, "Exit"); addMenuItem(m, "Exit");
@ -114,4 +115,10 @@ static int mainMenu()
free(m); free(m);
return cursor; return cursor;
}
void clearScreen(PrintConsole* screen)
{
consoleSelect(screen);
consoleClear();
} }

View File

@ -8,6 +8,8 @@
PrintConsole topScreen; PrintConsole topScreen;
PrintConsole bottomScreen; PrintConsole bottomScreen;
void clearScreen(PrintConsole* screen);
#define abs(X) ( (X) < 0 ? -(X): (X) ) #define abs(X) ( (X) < 0 ? -(X): (X) )
#define sign(X) ( ((X) > 0) - ((X) < 0) ) #define sign(X) ( ((X) > 0) - ((X) < 0) )
#define repeat(X) for (int _I_ = 0; _I_ < (X); _I_++) #define repeat(X) for (int _I_ = 0; _I_ < (X); _I_++)

View File

@ -25,8 +25,7 @@ void printMenu(Menu* m)
if (m == NULL) return; if (m == NULL) return;
swiWaitForVBlank(); swiWaitForVBlank();
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
int i = m->scrolly; int i = m->scrolly;
while (i < m->scrolly + SCREEN_ROWS && i < m->numberOfItems) while (i < m->scrolly + SCREEN_ROWS && i < m->numberOfItems)
@ -77,10 +76,10 @@ static void _moveCursor(Menu* m, int dir)
m->scrolly -= 1; m->scrolly -= 1;
} }
int moveCursor(Menu* m) bool moveCursor(Menu* m)
{ {
if (m == NULL) if (m == NULL)
return 0; return false;
int lastCursor = m->cursor; int lastCursor = m->cursor;
@ -131,13 +130,12 @@ void keyWait(u32 key)
} }
} }
int choiceBox(char* message) bool choiceBox(char* message)
{ {
const int choiceRow = 10; const int choiceRow = 10;
int cursor = 0; int cursor = 0;
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
iprintf("%s\n", message); iprintf("%s\n", message);
iprintf("\x1b[%d;0H\tYes\n\tNo\n", choiceRow); iprintf("\x1b[%d;0H\tYes\n\tNo\n", choiceRow);
@ -170,10 +168,38 @@ int choiceBox(char* message)
return (cursor == 0)? YES: NO; return (cursor == 0)? YES: NO;
} }
bool choicePrint(char* message)
{
bool choice = NO;
iprintf("\n%s\n", message);
iprintf("Yes - A\nNo - B\n");
while (1)
{
swiWaitForVBlank();
scanKeys();
if (keysDown() & KEY_A)
{
choice = YES;
break;
}
else if (keysDown() & KEY_B)
{
choice = NO;
break;
}
}
scanKeys();
return choice;
}
void messageBox(char* message) void messageBox(char* message)
{ {
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
iprintf("%s\n", message); iprintf("%s\n", message);
iprintf("\nOkay - A\n"); iprintf("\nOkay - A\n");

View File

@ -25,16 +25,18 @@ void printMenu(Menu* m);
int getMenuCursor(Menu* m); int getMenuCursor(Menu* m);
int getNumberOfMenuItems(Menu* m); int getNumberOfMenuItems(Menu* m);
int moveCursor(Menu* m); bool moveCursor(Menu* m);
void addMenuItem(Menu* m, char* label); void addMenuItem(Menu* m, char* label);
enum {
#define YES 1 YES = true,
#define NO 0 NO = false
};
void keyWait(u32 key); void keyWait(u32 key);
int choiceBox(char* message); bool choiceBox(char* message);
bool choicePrint(char* message);
void messageBox(char* message); void messageBox(char* message);
#endif #endif

View File

@ -3,7 +3,6 @@
#include <nds.h> #include <nds.h>
#include <string.h> #include <string.h>
#include <dirent.h> #include <dirent.h>
//#include <nds/arm7/sdmmc.h>
#define TITLE_LIMIT 39 #define TITLE_LIMIT 39
@ -27,8 +26,7 @@ void printFileInfo(const char* path)
{ {
if (path == NULL) return; if (path == NULL) return;
consoleSelect(&topScreen); clearScreen(&topScreen);
consoleClear();
tDSiHeader* header = (tDSiHeader*)malloc(sizeof(tDSiHeader)); tDSiHeader* header = (tDSiHeader*)malloc(sizeof(tDSiHeader));
tNDSBanner* banner = (tNDSBanner*)malloc(sizeof(tNDSBanner)); tNDSBanner* banner = (tNDSBanner*)malloc(sizeof(tNDSBanner));
@ -125,14 +123,24 @@ void printFileInfo(const char* path)
} }
//Progress bar //Progress bar
void printProgressBar(int progress, int total) void printProgressBar(int percent)
{ {
//Limit 100 max
if (percent > 100)
percent = 100;
//Print frame
iprintf("\x1b[23;0H["); iprintf("\x1b[23;0H[");
iprintf("\x1b[23;31H]"); iprintf("\x1b[23;31H]");
float bar = ((float)progress / (float)total) * 30.f; //Skip if there are no bars
if (percent <= 0)
return;
for (int i = 0; i < bar; i++) //Print bars
int bars = (int)(30.f * (percent / 100.f)) + 1;
for (int i = 0; i < bars; i++)
iprintf("\x1b[23;%dH|", 1 + i); iprintf("\x1b[23;%dH|", 1 + i);
} }
@ -142,12 +150,12 @@ void clearProgressBar()
} }
//Files //Files
int copyFile(const char* in, char* out) bool copyFile(const char* in, char* out)
{ {
int result = 0; bool result = false;
if (in == NULL || out == NULL) if (in == NULL || out == NULL)
return 0; return false;
FILE* fin = fopen(in, "rb"); FILE* fin = fopen(in, "rb");
FILE* fout = fopen(out, "wb"); FILE* fout = fopen(out, "wb");
@ -157,7 +165,7 @@ int copyFile(const char* in, char* out)
fclose(fin); fclose(fin);
fclose(fout); fclose(fout);
return 0; return false;
} }
else else
{ {
@ -165,9 +173,11 @@ int copyFile(const char* in, char* out)
int fileSize = getFileSize(fin); int fileSize = getFileSize(fin);
int totalBytesRead = 0; int totalBytesRead = 0;
int progressTimer = 100;
const int buffSize = 1024*32; //Arbitrary. A value too large freezes the system. int percent = 0;
int lastPercent = 0;
const int buffSize = 1024*8; //Arbitrary. A value too large freezes the system.
unsigned char* buffer = (unsigned char*)malloc(sizeof(unsigned char) * buffSize); unsigned char* buffer = (unsigned char*)malloc(sizeof(unsigned char) * buffSize);
while (1) while (1)
@ -178,10 +188,11 @@ int copyFile(const char* in, char* out)
totalBytesRead += bytesRead; totalBytesRead += bytesRead;
//Re-print progress bar every so often, but not every time //Re-print progress bar every so often, but not every time
if ((progressTimer += 1) >= 25) percent = (int)( ((float)totalBytesRead / (float)fileSize) * 100.f );
if (percent != lastPercent)
{ {
progressTimer = 0; lastPercent = percent;
printProgressBar(totalBytesRead, fileSize); printProgressBar(percent);
} }
if (feof(fin)) if (feof(fin))
@ -233,7 +244,7 @@ unsigned long long getFileSizePath(const char* path)
return size; return size;
} }
int padFile(const char* path, int size) bool padFile(const char* path, int size)
{ {
FILE* f = fopen(path, "ab"); FILE* f = fopen(path, "ab");
@ -252,7 +263,7 @@ int padFile(const char* path, int size)
} }
//Directories //Directories
int dirExists(const char* path) bool dirExists(const char* path)
{ {
if (path == NULL) if (path == NULL)
return 0; return 0;
@ -322,11 +333,11 @@ int copyDir(char* in, char* out)
} }
*/ */
int deleteDir(const char* path) bool deleteDir(const char* path)
{ {
if (strcmp("/", path) == 0) if (strcmp("/", path) == 0)
{ {
//Oh fuck no //oh fuck no
return 0; return 0;
} }
@ -464,9 +475,8 @@ int getMenuSlotsFree()
} }
//SD Card //SD Card
int sdIsInserted() bool sdIsInserted()
{ {
// Undefined reference
// return sdmmc_cardinserted(); // return sdmmc_cardinserted();
return 1; return 1;
@ -501,7 +511,6 @@ int getDsiSize()
{ {
//The DSi has 256MB of internal storage. Some is unavailable and used by other things. //The DSi has 256MB of internal storage. Some is unavailable and used by other things.
//Find a better way to do this //Find a better way to do this
// return 240 * 1024 * 1024;
return 248 * 1024 * 1024; return 248 * 1024 * 1024;
} }

View File

@ -1,6 +1,7 @@
#ifndef STORAGE_H #ifndef STORAGE_H
#define STORAGE_H #define STORAGE_H
#include <nds/ndstypes.h>
#include <stdio.h> #include <stdio.h>
#define BACKUP_PATH "/titlebackup/" #define BACKUP_PATH "/titlebackup/"
@ -13,19 +14,19 @@ void printBytes(unsigned long long bytes);
void printFileInfo(const char* path); void printFileInfo(const char* path);
//Progress bar //Progress bar
void printProgressBar(int progress, int total); void printProgressBar(int percent);
void clearProgressBar(); void clearProgressBar();
//Files //Files
int copyFile(const char* in, char* out); bool copyFile(const char* in, char* out);
unsigned long long getFileSize(FILE* f); unsigned long long getFileSize(FILE* f);
unsigned long long getFileSizePath(const char* path); unsigned long long getFileSizePath(const char* path);
int padFile(const char* path, int size); bool padFile(const char* path, int size);
//Directories //Directories
int dirExists(const char* path); bool dirExists(const char* path);
//int copyDir(const char* in, char* out); //int copyDir(const char* in, char* out);
int deleteDir(const char* path); bool deleteDir(const char* path);
unsigned long long getDirSize(const char* path); unsigned long long getDirSize(const char* path);
//Home menu //Home menu
@ -34,7 +35,7 @@ int getMenuSlotsFree();
#define getMenuSlotsUsed() (getMenuSlots() - getMenuSlotsFree()) #define getMenuSlotsUsed() (getMenuSlots() - getMenuSlotsFree())
//SD Card //SD Card
int sdIsInserted(); bool sdIsInserted();
unsigned long long getSDCardSize(); unsigned long long getSDCardSize();
unsigned long long getSDCardFree(); unsigned long long getSDCardFree();

View File

@ -4,13 +4,11 @@
void testMenu() void testMenu()
{ {
consoleSelect(&topScreen); clearScreen(&topScreen);
consoleClear();
iprintf("Storage Check Test\n\n"); iprintf("Storage Check Test\n\n");
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
unsigned int free = 0; unsigned int free = 0;
unsigned int size = 0; unsigned int size = 0;

View File

@ -15,8 +15,6 @@ static void delete(Menu* m);
enum { enum {
// TITLE_MENU_BACKUP, // TITLE_MENU_BACKUP,
TITLE_MENU_DUMP, TITLE_MENU_DUMP,
// TITLE_MENU_BACKUP_DATA,
// TITLE_MENU_RESTORE_DATA,
TITLE_MENU_DELETE, TITLE_MENU_DELETE,
TITLE_MENU_BACK TITLE_MENU_BACK
}; };
@ -25,11 +23,8 @@ void titleMenu()
{ {
Menu* m = (Menu*)malloc(sizeof(Menu)); Menu* m = (Menu*)malloc(sizeof(Menu));
consoleSelect(&topScreen); clearScreen(&topScreen);
consoleClear(); clearScreen(&bottomScreen);
consoleSelect(&bottomScreen);
consoleClear();
generateList(m); generateList(m);
@ -67,6 +62,10 @@ void titleMenu()
{ {
switch (subMenu()) switch (subMenu())
{ {
/* case TITLE_MENU_BACKUP:
backup(m);
break;
*/
case TITLE_MENU_DUMP: case TITLE_MENU_DUMP:
dump(m); dump(m);
break; break;
@ -217,9 +216,7 @@ void generateList(Menu* m)
{ {
if (m == NULL) return; if (m == NULL) return;
consoleSelect(&bottomScreen); clearScreen(&bottomScreen);
consoleClear();
iprintf("Gathering files...\n"); swiWaitForVBlank(); iprintf("Gathering files...\n"); swiWaitForVBlank();
clearMenu(m); clearMenu(m);
@ -243,10 +240,8 @@ int subMenu()
Menu* m = (Menu*)malloc(sizeof(Menu)); Menu* m = (Menu*)malloc(sizeof(Menu));
clearMenu(m); clearMenu(m);
// iprintf("\tBackup\n"); // addMenuItem(m, "Backup");
addMenuItem(m, "Dump"); addMenuItem(m, "Dump");
// addMenuItem(m, "Backup Saved Data");
// addMenuItem(m, "Restore Saved Data");
addMenuItem(m, "Delete"); addMenuItem(m, "Delete");
addMenuItem(m, "Back"); addMenuItem(m, "Back");
@ -292,7 +287,7 @@ static void dump(Menu* m)
else else
{ {
int fsize = getFileSize(f); unsigned long long fsize = getFileSize(f);
if (fsize > getSDCardFree()) if (fsize > getSDCardFree())
{ {
@ -312,7 +307,7 @@ static void dump(Menu* m)
char outpath[256]; char outpath[256];
sprintf(outpath, "%s%.12s - %.4s.nds", ROM_PATH, header->gameTitle, header->gameCode); sprintf(outpath, "%s%.12s - %.4s.nds", ROM_PATH, header->gameTitle, header->gameCode);
int choice = NO; bool choice = NO;
{ {
char msg[512]; char msg[512];
sprintf(msg, "Dump title to\n%s\n", outpath); sprintf(msg, "Dump title to\n%s\n", outpath);
@ -346,7 +341,7 @@ static void delete(Menu* m)
} }
else else
{ {
int choice = NO; bool choice = NO;
{ {
//Get title name //Get title name
@ -401,7 +396,7 @@ static void delete(Menu* m)
printMenu(m); printMenu(m);
} }
/* Incomplete /* Incomplete
static void backupData(Menu* m) static void backup(Menu* m)
{ {
char msg[512]; char msg[512];
char dirPath[256]; char dirPath[256];
@ -433,8 +428,4 @@ static void backupData(Menu* m)
fclose(f); fclose(f);
} }
*/
static void restoreData(Menu* m)
{
}*/