From 7ffa0c17db99f6ce82b74b86cc5216590bf8bd2d Mon Sep 17 00:00:00 2001 From: dborth Date: Mon, 22 Dec 2008 08:38:49 +0000 Subject: [PATCH] bug fixes for RAM/state saves, optimize boot sequence, more intelligent device auto-detect --- source/ngc/fceugx.c | 44 +++---- source/ngc/fceuram.c | 55 ++++++--- source/ngc/fceustate.c | 251 ++++++++++++++++++++++----------------- source/ngc/fileop.c | 12 +- source/ngc/filesel.c | 41 ++++--- source/ngc/filesel.h | 2 +- source/ngc/preferences.c | 2 +- 7 files changed, 236 insertions(+), 171 deletions(-) diff --git a/source/ngc/fceugx.c b/source/ngc/fceugx.c index 40af0a1..c5afbb3 100644 --- a/source/ngc/fceugx.c +++ b/source/ngc/fceugx.c @@ -183,59 +183,59 @@ int main(int argc, char *argv[]) int selectedMenu = -1; + InitDeviceThread(); + + InitGCVideo (); + ResetVideo_Menu (); // change to menu video mode + + // Controllers + PAD_Init(); + #ifdef HW_RVL WPAD_Init(); // read wiimote accelerometer and IR data WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); WPAD_SetVRes(WPAD_CHAN_ALL,640,480); - #endif - - PAD_Init(); // Wii Power/Reset buttons - #ifdef HW_RVL WPAD_SetPowerButtonCallback((WPADShutdownCallback)ShutdownCB); SYS_SetPowerCallback(ShutdownCB); SYS_SetResetCallback(ResetCB); #endif - InitGCVideo (); - ResetVideo_Menu (); // change to menu video mode - - /*** Initialise freetype ***/ + // Initialise FreeType if (FT_Init ()) { printf ("Cannot initialise font subsystem!\n"); while (1); } - InitialiseAudio(); + InitialiseAudio(); - // Initialize libFAT for SD and USB - MountAllFAT(); - InitDeviceThread(); + // Initialize libFAT for SD and USB + MountAllFAT(); - // Initialize DVD subsystem (GameCube only) + // Initialize DVD subsystem (GameCube only) #ifdef HW_DOL DVD_Init (); #endif - // allocate memory to store rom - nesrom = (unsigned char *)malloc(1024*1024*3); // 3 MB should be plenty + // allocate memory to store rom + nesrom = (unsigned char *)malloc(1024*1024*3); // 3 MB should be plenty - /*** Minimal Emulation Loop ***/ - if ( !FCEUI_Initialize() ) - { + /*** Minimal Emulation Loop ***/ + if ( !FCEUI_Initialize() ) + { WaitPrompt("Unable to initialize FCE Ultra\n"); ExitToLoader(); - } + } FCEUI_SetGameGenie(0); // 0 - OFF, 1 - ON - memset(FDSBIOS, 0, sizeof(FDSBIOS)); // clear FDS BIOS memory - cleanSFMDATA(); // clear state data + memset(FDSBIOS, 0, sizeof(FDSBIOS)); // clear FDS BIOS memory + cleanSFMDATA(); // clear state data - // Set defaults + // Set defaults DefaultSettings(); // store path app was loaded from diff --git a/source/ngc/fceuram.c b/source/ngc/fceuram.c index 1f1dc12..0c56105 100644 --- a/source/ngc/fceuram.c +++ b/source/ngc/fceuram.c @@ -39,15 +39,42 @@ #include "fileop.h" #include "smbop.h" +extern const unsigned short saveicon[1024]; extern u32 iNESGameCRC32; extern CartInfo iNESCart; extern CartInfo UNIFCart; -int NGCFCEU_GameSave(CartInfo *LocalHWInfo, int operation) +int NGCFCEU_GameSave(CartInfo *LocalHWInfo, int operation, int method) { - int size = 0; + int offset = 0; + char comment[2][32]; + memset(comment, 0, 64); + if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0]) { + // add save icon and comments for Memory Card saves + if(operation == 0 && + (method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)) + { + // Copy in save icon + memcpy(savebuffer, saveicon, sizeof(saveicon)); + offset += sizeof(saveicon); + + // And the comments + sprintf (comment[0], "%s RAM", VERSIONSTR); + strncpy (comment[1],romFilename,31); // we only have 32 chars to work with! + comment[1][31] = 0; + memcpy(savebuffer+offset, comment, 64); + offset += 64; + } + // skip save icon and comments for Memory Card saves + else if(operation == 1 && + (method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB)) + { + offset += sizeof(saveicon); + offset += 64; // sizeof prefscomment + } + int x; for(x=0;x<4;x++) @@ -55,18 +82,14 @@ int NGCFCEU_GameSave(CartInfo *LocalHWInfo, int operation) if(LocalHWInfo->SaveGame[x]) { if(operation == 0) // save to file - { - memcpy(savebuffer, LocalHWInfo->SaveGame[x], LocalHWInfo->SaveGameLen[x]); - } + memcpy(savebuffer+offset, LocalHWInfo->SaveGame[x], LocalHWInfo->SaveGameLen[x]); else // load from file - { - memcpy(LocalHWInfo->SaveGame[x], savebuffer, LocalHWInfo->SaveGameLen[x]); - } - size += LocalHWInfo->SaveGameLen[x]; + memcpy(LocalHWInfo->SaveGame[x], savebuffer+offset, LocalHWInfo->SaveGameLen[x]); + offset += LocalHWInfo->SaveGameLen[x]; } } } - return size; + return offset; } bool SaveRAM (int method, bool silent) @@ -84,7 +107,7 @@ bool SaveRAM (int method, bool silent) } if(method == METHOD_AUTO) - method = autoSaveMethod(); + method = autoSaveMethod(silent); if (!MakeFilePath(filepath, FILE_RAM, method)) return false; @@ -95,9 +118,9 @@ bool SaveRAM (int method, bool silent) // save game save to savebuffer if(nesGameType == 1) - datasize = NGCFCEU_GameSave(&iNESCart, 0); + datasize = NGCFCEU_GameSave(&iNESCart, 0, method); else if(nesGameType == 2) - datasize = NGCFCEU_GameSave(&UNIFCart, 0); + datasize = NGCFCEU_GameSave(&UNIFCart, 0, method); if (datasize) { @@ -133,7 +156,7 @@ bool LoadRAM (int method, bool silent) } if(method == METHOD_AUTO) - method = autoSaveMethod(); // we use 'Save' because we need R/W + method = autoSaveMethod(silent); // we use 'Save' because we need R/W if (!MakeFilePath(filepath, FILE_RAM, method)) return false; @@ -147,9 +170,9 @@ bool LoadRAM (int method, bool silent) if (offset > 0) { if(nesGameType == 1) - NGCFCEU_GameSave(&iNESCart, 1); + NGCFCEU_GameSave(&iNESCart, 1, method); else if(nesGameType == 2) - NGCFCEU_GameSave(&UNIFCart, 1); + NGCFCEU_GameSave(&UNIFCart, 1, method); ResetNES(); retval = true; diff --git a/source/ngc/fceustate.c b/source/ngc/fceustate.c index dd2a2b3..286f897 100644 --- a/source/ngc/fceustate.c +++ b/source/ngc/fceustate.c @@ -19,6 +19,7 @@ #include #include "types.h" #include "state.h" +#include "x6502.h" #include "images/saveicon.h" #include "fceugx.h" @@ -32,10 +33,10 @@ /*** External functions ***/ extern void FCEUPPU_SaveState(void); extern void FCEUSND_SaveState(void); +extern void FCEUPPU_LoadState(int version); +extern void FCEUSND_LoadState(int version); extern void FlipByteOrder(uint8 *src, uint32 count); -extern void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b); -extern void FCEU_ResetPalette(void); -extern void FCEUI_DisableSpriteLimitation( int a ); +extern void (*GameStateRestore)(int version); /*** External save structures ***/ extern SFORMAT SFCPU[]; @@ -47,7 +48,6 @@ extern SFORMAT SFMDATA[64]; extern u32 iNESGameCRC32; #define RLSB 0x80000000 -#define FILESIZEOFFSET 2116 int sboffset; /*** Used as a basic fileptr ***/ int mcversion = 0x981211; @@ -57,9 +57,9 @@ int mcversion = 0x981211; ****************************************************************************/ /*** Open a file ***/ -void memopen() { +void memopen() +{ sboffset = 0; - memset(savebuffer, 0, SAVEBUFFERSIZE); } /*** Close a file ***/ @@ -95,47 +95,59 @@ void memfread( void *buffer, int len ) { * * Read the array of SFORMAT structures to memory ****************************************************************************/ -int GCReadChunk( int chunkid, SFORMAT *sf ) { - int csize; - static char chunk[6]; - int chunklength; - int thischunk; - char info[128]; +int GCReadChunk(int chunkid, SFORMAT *sf) +{ + int csize; + static char chunk[6]; + int chunklength; + int thischunk; + char info[128]; - memfread(&chunk, 4); - memfread(&thischunk, 4); - memfread(&chunklength, 4); + memfread(&chunk, 4); + memfread(&thischunk, 4); + memfread(&chunklength, 4); - if (strcmp(chunk, "CHNK") == 0) { - if (chunkid == thischunk) { - /*** Now decode the array of chunks to this one ***/ - while (sf->v) { - memfread(&chunk, 4); - if ( memcmp(&chunk, "CHKE", 4) == 0 ) - return 1; + if (strcmp(chunk, "CHNK") == 0) + { + if (chunkid == thischunk) + { + /*** Now decode the array of chunks to this one ***/ + while (sf->v) + { + memfread(&chunk, 4); + if (memcmp(&chunk, "CHKE", 4) == 0) + return 1; - if (memcmp(&chunk, sf->desc, 4) == 0) { - memfread(&csize, 4); - if (csize == (sf->s & (~RLSB ))) { - memfread( sf->v, csize ); - sprintf(info,"%s %d", chunk, csize); - } else { - WaitPrompt("Bad chunk link"); - return 0; - } - } else { - sprintf(info, "No Sync %s %s", chunk, sf->desc); - WaitPrompt(info); - return 0; - } - sf++; - } - } else - return 0; - } else - return 0; + if (memcmp(&chunk, sf->desc, 4) == 0) + { + memfread(&csize, 4); + if (csize == (sf->s & (~RLSB))) + { + memfread(sf->v, csize); + sprintf(info, "%s %d", chunk, csize); + } + else + { + WaitPrompt("Bad chunk link"); + return 0; + } + } + else + { + sprintf(info, "No Sync %s %s", chunk, sf->desc); + WaitPrompt(info); + return 0; + } + sf++; + } + } + else + return 0; + } + else + return 0; - return 1; + return 1; } /**************************************************************************** @@ -143,28 +155,47 @@ int GCReadChunk( int chunkid, SFORMAT *sf ) { * * Reads the SFORMAT arrays ****************************************************************************/ -int GCFCEUSS_Load() { - int totalsize = 0; +int GCFCEUSS_Load(int method) +{ + memopen(); // reset file pointer - sboffset = 16 + sizeof(saveicon) + 64; /*** Reset memory file pointer ***/ + // skip save icon and comments for Memory Card saves + if (method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + sboffset += sizeof(saveicon); + sboffset += 64; // sizeof prefscomment + } - memcpy(&totalsize, &savebuffer[FILESIZEOFFSET], 4); + sboffset += 16; // skip FCEU header - /*** Now read the chunks back ***/ - if (GCReadChunk(1, SFCPU)) { - if (GCReadChunk(2, SFCPUC)) { - if (GCReadChunk(3, FCEUPPU_STATEINFO)) { - if (GCReadChunk(4, FCEUCTRL_STATEINFO)) { - if (GCReadChunk(5, FCEUSND_STATEINFO)) { - if (GCReadChunk(0x10, SFMDATA)) - return 1; - } - } - } - } - } + // Now read the chunks back + if (GCReadChunk(1, SFCPU)) + { + if (GCReadChunk(2, SFCPUC)) + { + X.mooPI = X.P; // Quick and dirty hack. + if (GCReadChunk(3, FCEUPPU_STATEINFO)) + { + if (GCReadChunk(4, FCEUCTRL_STATEINFO)) + { + if (GCReadChunk(5, FCEUSND_STATEINFO)) + { + if (GCReadChunk(0x10, SFMDATA)) + { + if (GameStateRestore) + GameStateRestore(FCEU_VERSION_NUMERIC); - return 0; + FCEUPPU_LoadState(FCEU_VERSION_NUMERIC); + FCEUSND_LoadState(FCEU_VERSION_NUMERIC); + return 1; + } + } + } + } + } + } + + return 0; } /**************************************************************************** @@ -172,7 +203,8 @@ int GCFCEUSS_Load() { * * Write the array of SFORMAT structures to the file ****************************************************************************/ -int GCSaveChunk(int chunkid, SFORMAT *sf) { +int GCSaveChunk(int chunkid, SFORMAT *sf) +{ int chnkstart; int csize = 0; int chsize = 0; @@ -199,8 +231,10 @@ int GCSaveChunk(int chunkid, SFORMAT *sf) { memfwrite( &chsize, 4); if ( chsize > 0 ) + { /*** Write the actual data ***/ memfwrite( sf->v, chsize ); + } csize += 8; csize += chsize; @@ -224,59 +258,62 @@ int GCSaveChunk(int chunkid, SFORMAT *sf) { extern void (*SPreSave)(void); extern void (*SPostSave)(void); -int GCFCEUSS_Save() +int GCFCEUSS_Save(int method) { - int totalsize = 0; - static unsigned char header[16] = "FCS\xff"; - char chunk[] = "CHKE"; - int zero = 0; - char Comment[2][100] = { { MENU_CREDITS_TITLE }, { "GAME" } }; + int totalsize = 0; + static unsigned char header[16] = "FCS\xff"; + char chunk[] = "CHKE"; + int zero = 0; + char comment[2][32]; + memset(comment, 0, 64); - memopen(); /*** Reset Memory File ***/ + memopen(); // Reset Memory File - /*** Add version ID ***/ - memcpy(&header[8], &mcversion, 4); + // add save icon and comments for Memory Card saves + if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + // Copy in save icon + memfwrite(&saveicon, sizeof(saveicon)); + totalsize += sizeof(saveicon); - /*** Do internal Saving ***/ - FCEUPPU_SaveState(); - FCEUSND_SaveState(); + // And the comments + sprintf (comment[0], "%s State", VERSIONSTR); + strncpy (comment[1],romFilename,31); // we only have 32 chars to work with! + comment[1][31] = 0; + memfwrite(&comment[0], 64); + totalsize += 64; + } - /*** Write Icon ***/ - memfwrite(&saveicon, sizeof(saveicon)); - totalsize += sizeof(saveicon); + // Add version ID + memcpy(&header[8], &mcversion, 4); - /*** And Comments ***/ - strncpy (Comment[1],romFilename,31); // we only have 32 chars to work with! - Comment[1][31] = 0; - memfwrite(&Comment[0], 64); - totalsize += 64; + // Do internal Saving + FCEUPPU_SaveState(); + FCEUSND_SaveState(); - /*** Write header ***/ - memfwrite(&header, 16); - totalsize += 16; - totalsize += GCSaveChunk(1, SFCPU); - totalsize += GCSaveChunk(2, SFCPUC); - totalsize += GCSaveChunk(3, FCEUPPU_STATEINFO); - totalsize += GCSaveChunk(4, FCEUCTRL_STATEINFO); - totalsize += GCSaveChunk(5, FCEUSND_STATEINFO); + // Write header + memfwrite(&header, 16); + totalsize += 16; + totalsize += GCSaveChunk(1, SFCPU); + totalsize += GCSaveChunk(2, SFCPUC); + totalsize += GCSaveChunk(3, FCEUPPU_STATEINFO); + totalsize += GCSaveChunk(4, FCEUCTRL_STATEINFO); + totalsize += GCSaveChunk(5, FCEUSND_STATEINFO); - if(nesGameType == 4) // FDS - SPreSave(); + if(nesGameType == 4) // FDS + SPreSave(); - totalsize += GCSaveChunk(0x10, SFMDATA); + totalsize += GCSaveChunk(0x10, SFMDATA); - if(nesGameType == 4) // FDS - SPostSave(); + if(nesGameType == 4) // FDS + SPostSave(); - /*** Add terminating CHNK ***/ - memfwrite(&chunk,4); - memfwrite(&zero,4); - totalsize += 8; + // Add terminating CHNK + memfwrite(&chunk,4); + memfwrite(&zero,4); + totalsize += 8; - /*** Update size element ***/ - memcpy(&savebuffer[FILESIZEOFFSET], &totalsize, 4); - - return totalsize; + return totalsize; } bool SaveState (int method, bool silent) @@ -287,7 +324,7 @@ bool SaveState (int method, bool silent) int offset = 0; if(method == METHOD_AUTO) - method = autoSaveMethod(); + method = autoSaveMethod(silent); if (!MakeFilePath(filepath, FILE_STATE, method)) return false; @@ -296,7 +333,7 @@ bool SaveState (int method, bool silent) AllocSaveBuffer (); - datasize = GCFCEUSS_Save(); + datasize = GCFCEUSS_Save(method); if (datasize) { @@ -320,7 +357,7 @@ bool LoadState (int method, bool silent) bool retval = false; if(method == METHOD_AUTO) - method = autoSaveMethod(); // we use 'Save' because we need R/W + method = autoSaveMethod(silent); // we use 'Save' because we need R/W if (!MakeFilePath(filepath, FILE_STATE, method)) return false; @@ -333,7 +370,7 @@ bool LoadState (int method, bool silent) if (offset > 0) { - GCFCEUSS_Load(); + GCFCEUSS_Load(method); retval = true; } else diff --git a/source/ngc/fileop.c b/source/ngc/fileop.c index 6b056c0..5df2957 100644 --- a/source/ngc/fileop.c +++ b/source/ngc/fileop.c @@ -233,15 +233,15 @@ bool ChangeInterface(int method, bool silent) WaitPrompt ("USB drive not found!"); #endif } - else if(method == METHOD_SMB) - { - sprintf(rootdir, "smb:/"); - mounted = ConnectShare(NOTSILENT); - } else if(method == METHOD_DVD) { sprintf(rootdir, "/"); - mounted = MountDVD(NOTSILENT); + mounted = MountDVD(silent); + } + else if(method == METHOD_SMB) + { + sprintf(rootdir, "smb:/"); + mounted = ConnectShare(silent); } return mounted; diff --git a/source/ngc/filesel.c b/source/ngc/filesel.c index fd372fc..ac47a88 100644 --- a/source/ngc/filesel.c +++ b/source/ngc/filesel.c @@ -83,19 +83,21 @@ int autoLoadMethod() { ShowAction ("Attempting to determine load method..."); + int method = 0; + if(ChangeInterface(METHOD_SD, SILENT)) - return METHOD_SD; + method = METHOD_SD; else if(ChangeInterface(METHOD_USB, SILENT)) - return METHOD_USB; + method = METHOD_USB; else if(ChangeInterface(METHOD_DVD, SILENT)) - return METHOD_DVD; + method = METHOD_DVD; else if(ChangeInterface(METHOD_SMB, SILENT)) - return METHOD_SMB; + method = METHOD_SMB; else - { WaitPrompt("Unable to auto-determine load method!"); - return 0; // no method found - } + + GCSettings.LoadMethod = method; // save method found for later use + return method; } /**************************************************************************** @@ -103,25 +105,28 @@ int autoLoadMethod() * Auto-determines and sets the save method * Returns method set ****************************************************************************/ -int autoSaveMethod() +int autoSaveMethod(bool silent) { - ShowAction ("Attempting to determine save method..."); + if(!silent) + ShowAction ("Attempting to determine save method..."); + + int method = 0; if(ChangeInterface(METHOD_SD, SILENT)) - return METHOD_SD; + method = METHOD_SD; else if(ChangeInterface(METHOD_USB, SILENT)) - return METHOD_USB; + method = METHOD_USB; else if(TestCard(CARD_SLOTA, SILENT)) - return METHOD_MC_SLOTA; + method = METHOD_MC_SLOTA; else if(TestCard(CARD_SLOTB, SILENT)) - return METHOD_MC_SLOTB; + method = METHOD_MC_SLOTB; else if(ChangeInterface(METHOD_SMB, SILENT)) - return METHOD_SMB; - else - { + method = METHOD_SMB; + else if(!silent) WaitPrompt("Unable to auto-determine save method!"); - return 0; // no method found - } + + GCSettings.SaveMethod = method; // save method found for later use + return method; } /**************************************************************************** diff --git a/source/ngc/filesel.h b/source/ngc/filesel.h index 843eebb..1744286 100644 --- a/source/ngc/filesel.h +++ b/source/ngc/filesel.h @@ -44,7 +44,7 @@ void FreeSaveBuffer(); bool MakeFilePath(char filepath[], int type, int method); int OpenROM (int method); int autoLoadMethod(); -int autoSaveMethod(); +int autoSaveMethod(bool silent); int FileSortCallback(const void *f1, const void *f2); void StripExt(char* returnstring, char * inputstring); diff --git a/source/ngc/preferences.c b/source/ngc/preferences.c index d87ab51..40964be 100644 --- a/source/ngc/preferences.c +++ b/source/ngc/preferences.c @@ -326,7 +326,7 @@ SavePrefs (bool silent) // We'll save using the first available method (probably SD) since this // is the method preferences will be loaded from by default - int method = autoSaveMethod(); + int method = autoSaveMethod(silent); if(!MakeFilePath(filepath, FILE_PREF, method)) return false;