bug fixes for RAM/state saves, optimize boot sequence, more intelligent device auto-detect

This commit is contained in:
dborth 2008-12-22 08:38:49 +00:00
parent c7b15e4a89
commit 7ffa0c17db
7 changed files with 236 additions and 171 deletions

View File

@ -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

View File

@ -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;

View File

@ -19,6 +19,7 @@
#include <fat.h>
#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

View File

@ -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;

View File

@ -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;
}
/****************************************************************************

View File

@ -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);

View File

@ -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;