From af596450f764eca8581985b7f8f5fa5cc10cefb3 Mon Sep 17 00:00:00 2001 From: dborth Date: Mon, 29 Sep 2008 07:35:26 +0000 Subject: [PATCH] memory based battery/state working, GC version working --- Makefile.wii | 2 +- source/ngc/dvd.cpp | 48 +++-- source/ngc/dvd.h | 2 +- source/ngc/fileop.cpp | 52 ++--- source/ngc/fileop.h | 2 +- source/ngc/filesel.cpp | 29 ++- source/ngc/filesel.h | 5 +- source/ngc/gcunzip.cpp | 47 +++- source/ngc/gcunzip.h | 4 +- source/ngc/input.cpp | 8 +- source/ngc/input.h | 2 +- source/ngc/menu.cpp | 27 +-- source/ngc/menudraw.cpp | 2 +- source/ngc/preferences.cpp | 17 +- source/ngc/smbop.cpp | 37 ++-- source/ngc/smbop.h | 4 +- source/ngc/vba.cpp | 4 +- source/ngc/vbasupport.cpp | 427 ++++++++++++++++++++++++++----------- source/ngc/vbasupport.h | 8 +- source/ngc/vmmem.cpp | 118 ++++++---- source/ngc/vmmem.h | 2 +- source/vba/Util.cpp | 2 +- source/vba/Util.h | 2 + source/vba/agb/GBA.cpp | 4 + source/vba/dmg/GB.cpp | 321 ++++++++++++++++++++++++++++ source/vba/dmg/GB.h | 3 + 26 files changed, 892 insertions(+), 287 deletions(-) diff --git a/Makefile.wii b/Makefile.wii index 1d1b2b8..825c0f9 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -26,7 +26,7 @@ INCLUDES := source/vba source/ngc #--------------------------------------------------------------------------------- CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) \ - -DNGC -DWORDS_BIGENDIAN -DC_CORE -DFINAL_VERSION \ + -DNGC -DWII_DVD -DWORDS_BIGENDIAN -DC_CORE -DFINAL_VERSION \ -DSDL -DNO_PNG -DHAVE_ZUTIL_H CXXFLAGS = $(CFLAGS) LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref diff --git a/source/ngc/dvd.cpp b/source/ngc/dvd.cpp index 9f5b379..874ec9f 100644 --- a/source/ngc/dvd.cpp +++ b/source/ngc/dvd.cpp @@ -434,7 +434,7 @@ bool SwitchDVDFolder(char origdir[]) ***************************************************************************/ int -LoadDVDFile (unsigned char *buffer) +LoadDVDFile (unsigned char *buffer, int length) { int offset; int blocks; @@ -447,29 +447,37 @@ LoadDVDFile (unsigned char *buffer) offset = 0; discoffset = dvddir; ShowAction ((char*) "Loading..."); - dvd_read (readbuffer, 2048, discoffset); - if (!IsZipFile (readbuffer)) + if(length > 0) { - for (i = 0; i < blocks; i++) - { - dvd_read (readbuffer, 2048, discoffset); - memcpy (buffer + offset, readbuffer, 2048); - offset += 2048; - discoffset += 2048; - } - - /*** And final cleanup ***/ - if (dvddirlength % 2048) - { - i = dvddirlength % 2048; - dvd_read (readbuffer, 2048, discoffset); - memcpy (buffer + offset, readbuffer, i); - } + dvd_read (buffer, length, discoffset); } - else + else // load whole file { - return UnZipFile (buffer, discoffset); // unzip from dvd + dvd_read (readbuffer, 2048, discoffset); + + if (!IsZipFile (readbuffer)) + { + for (i = 0; i < blocks; i++) + { + dvd_read (readbuffer, 2048, discoffset); + memcpy (buffer + offset, readbuffer, 2048); + offset += 2048; + discoffset += 2048; + } + + /*** And final cleanup ***/ + if (dvddirlength % 2048) + { + i = dvddirlength % 2048; + dvd_read (readbuffer, 2048, discoffset); + memcpy (buffer + offset, readbuffer, i); + } + } + else + { + return UnZipFile (buffer, discoffset); // unzip from dvd + } } return dvddirlength; } diff --git a/source/ngc/dvd.h b/source/ngc/dvd.h index 9aaae6b..921973c 100644 --- a/source/ngc/dvd.h +++ b/source/ngc/dvd.h @@ -13,7 +13,7 @@ int getpvd (); int ParseDVDdirectory (); -int LoadDVDFile (unsigned char *buffer); +int LoadDVDFile (unsigned char *buffer, int length); bool TestDVD(); int dvd_read (void *dst, unsigned int len, u64 offset); bool SwitchDVDFolder(char dir[]); diff --git a/source/ngc/fileop.cpp b/source/ngc/fileop.cpp index 3428515..7481913 100644 --- a/source/ngc/fileop.cpp +++ b/source/ngc/fileop.cpp @@ -23,20 +23,6 @@ #include "menudraw.h" #include "filesel.h" #include "preferences.h" -#include "sdfileio.h" - -// temporary -#include "vmmem.h" -#include "agb/GBA.h" -#include "agb/agbprint.h" -#include "Flash.h" -#include "Port.h" -#include "RTC.h" -#include "Sound.h" -#include "unzip.h" -#include "Util.h" -#include "dmg/GB.h" -#include "dmg/gbGlobals.h" FILE * filehandle; @@ -177,7 +163,7 @@ ParseFATdirectory(int method) * LoadFATFile ***************************************************************************/ int -LoadFATFile (char * rbuffer) +LoadFATFile (char * rbuffer, int length) { char zipbuffer[2048]; char filepath[MAXPATHLEN]; @@ -196,20 +182,28 @@ LoadFATFile (char * rbuffer) handle = fopen (filepath, "rb"); if (handle > 0) { - fread (zipbuffer, 1, 2048, handle); - - if (IsZipFile (zipbuffer)) + if(length > 0) { - size = UnZipFile ((unsigned char *)rbuffer, handle); // unzip from FAT + fread (rbuffer, 1, length, handle); + size = length; } - else + else // load whole file { - // Just load the file up - fseek(handle, 0, SEEK_END); - size = ftell(handle); // get filesize - fseek(handle, 2048, SEEK_SET); // seek back to point where we left off - memcpy (rbuffer, zipbuffer, 2048); // copy what we already read - fread (rbuffer + 2048, 1, size - 2048, handle); + fread (zipbuffer, 1, 2048, handle); + + if (IsZipFile (zipbuffer)) + { + size = UnZipFile ((unsigned char *)rbuffer, handle); // unzip from FAT + } + else + { + // Just load the file up + fseek(handle, 0, SEEK_END); + size = ftell(handle); // get filesize + fseek(handle, 2048, SEEK_SET); // seek back to point where we left off + memcpy (rbuffer, zipbuffer, 2048); // copy what we already read + fread (rbuffer + 2048, 1, size - 2048, handle); + } } fclose (handle); return size; @@ -219,8 +213,6 @@ LoadFATFile (char * rbuffer) WaitPrompt((char*) "Error opening file"); return 0; } - - return 0; } /**************************************************************************** @@ -233,8 +225,6 @@ LoadBufferFromFAT (char *filepath, bool silent) int boffset = 0; int read = 0; - ClearSaveBuffer (); - handle = fopen (filepath, "rb"); if (handle <= 0) @@ -282,7 +272,5 @@ SaveBufferToFAT (char *filepath, int datasize, bool silent) fwrite (savebuffer, 1, datasize, handle); fclose (handle); } - - ClearSaveBuffer (); return datasize; } diff --git a/source/ngc/fileop.h b/source/ngc/fileop.h index b949c7c..1a3d957 100644 --- a/source/ngc/fileop.h +++ b/source/ngc/fileop.h @@ -23,7 +23,7 @@ bool ChangeFATInterface(int method, bool silent); int ParseFATdirectory(int method); -int LoadFATFile (char * fbuffer); +int LoadFATFile (char * fbuffer, int length); int SaveBufferToFAT (char *filepath, int datasize, bool silent); int LoadBufferFromFAT (char *filepath, bool silent); diff --git a/source/ngc/filesel.cpp b/source/ngc/filesel.cpp index e074d65..badfc88 100644 --- a/source/ngc/filesel.cpp +++ b/source/ngc/filesel.cpp @@ -49,24 +49,37 @@ int hasloaded = 0; FILEENTRIES filelist[MAXFILES]; char ROMFilename[512]; -int ROMSize = 0; +bool ROMLoaded = false; unsigned char *savebuffer = NULL; /**************************************************************************** - * ClearSaveBuffer () - * Allocate and clear the savebuffer + * AllocSaveBuffer () + * Clear and allocate the savebuffer ***************************************************************************/ void -ClearSaveBuffer () +AllocSaveBuffer () { - if (savebuffer) + if (savebuffer != NULL) free(savebuffer); savebuffer = (unsigned char *) memalign(32, SAVEBUFFERSIZE); memset (savebuffer, 0, SAVEBUFFERSIZE); } +/**************************************************************************** + * FreeSaveBuffer () + * Free the savebuffer memory + ***************************************************************************/ +void +FreeSaveBuffer () +{ + if (savebuffer != NULL) + free(savebuffer); + + savebuffer = NULL; +} + /**************************************************************************** * autoLoadMethod() * Auto-determines and sets the load method @@ -216,7 +229,7 @@ void StripExt(char* returnstring, char * inputstring) strcpy (returnstring, inputstring); loc_dot = strrchr(returnstring,'.'); if (loc_dot != NULL) - *loc_dot = '\0'; // strip file extension + *loc_dot = 0; // strip file extension } /**************************************************************************** @@ -321,9 +334,9 @@ int FileSelector (int method) dvddirlength = filelist[selection].length; } - ROMSize = LoadVBAROM(method); + ROMLoaded = LoadVBAROM(method); - if (ROMSize > 0) + if (ROMLoaded) { return 1; } diff --git a/source/ngc/filesel.h b/source/ngc/filesel.h index ab52a98..f27640e 100644 --- a/source/ngc/filesel.h +++ b/source/ngc/filesel.h @@ -11,7 +11,7 @@ #ifndef _NGCFILESEL_ #define _NGCFILESEL_ -#include +#include #define SAVEBUFFERSIZE (512 * 1024) #define MAXJOLIET 255 @@ -36,7 +36,8 @@ extern int maxfiles; extern char ROMFilename[512]; -void ClearSaveBuffer (); +void AllocSaveBuffer(); +void FreeSaveBuffer(); int OpenROM (int method); int autoLoadMethod(); int autoSaveMethod(); diff --git a/source/ngc/gcunzip.cpp b/source/ngc/gcunzip.cpp index b635fe1..8791c4d 100644 --- a/source/ngc/gcunzip.cpp +++ b/source/ngc/gcunzip.cpp @@ -16,9 +16,11 @@ #include "dvd.h" #include "smbop.h" +#include "fileop.h" #include "video.h" #include "menudraw.h" #include "gcunzip.h" +#include "vba.h" /* * PKWare Zip Header - adopted into zip standard @@ -59,7 +61,7 @@ FLIP16 (u16 b) * IsZipFile * * Returns TRUE when PKZIPID is first four characters of buffer - ****************************************************************************/ + ***************************************************************************/ int IsZipFile (char *buffer) { @@ -77,7 +79,7 @@ IsZipFile (char *buffer) * unzip * * It should be noted that there is a limit of 5MB total size for any ROM - ******************************************************************************/ + *****************************************************************************/ FILE* fatfile; // FAT u64 discoffset; // DVD SMBFILE smbfile; // SMB @@ -119,8 +121,7 @@ UnZipBuffer (unsigned char *outbuffer, short where) pkzip.uncompressedSize = FLIP32 (pkzip.uncompressedSize); - sprintf (msg, "Unzipping %d bytes ... Wait", - pkzip.uncompressedSize); + sprintf (msg, "Unzipping %d bytes ... Wait", pkzip.uncompressedSize); ShowAction (msg); /*** Prepare the zip stream ***/ @@ -227,3 +228,41 @@ UnZipFile (unsigned char *outbuffer, SMBFILE infile) smbfile = infile; return UnZipBuffer(outbuffer, 2); } + +/**************************************************************************** + * GetFirstZipFilename + * + * Returns the filename of the first file in the zipped archive + * The idea here is to do the least amount of work required + ***************************************************************************/ + +char * +GetFirstZipFilename (int method) +{ + char testbuffer[ZIPCHUNK]; + + // read start of ZIP + switch (method) + { + case METHOD_SD: // SD Card + case METHOD_USB: // USB + LoadFATFile (testbuffer, ZIPCHUNK); + break; + + case METHOD_DVD: // DVD + LoadDVDFile ((unsigned char *)testbuffer, ZIPCHUNK); + break; + + case METHOD_SMB: // From SMB + LoadSMBFile (testbuffer, ZIPCHUNK); + break; + } + + testbuffer[28] = 0; // truncate - filename length is 2 bytes long (bytes 26-27) + int namelength = testbuffer[26]; // filename length starts 26 bytes in + + char * firstFilename = &testbuffer[30]; // first filename of a ZIP starts 31 bytes in + firstFilename[namelength] = 0; // truncate at filename length + + return firstFilename; +} diff --git a/source/ngc/gcunzip.h b/source/ngc/gcunzip.h index 68d6ff9..1322065 100644 --- a/source/ngc/gcunzip.h +++ b/source/ngc/gcunzip.h @@ -12,8 +12,8 @@ #include -extern int IsZipFile (char *buffer); - +int IsZipFile (char *buffer); +char * GetFirstZipFilename(int method); int UnZipFile (unsigned char *outbuffer, FILE* infile); // Reading from FAT int UnZipFile (unsigned char *outbuffer, u64 inoffset); // Reading from DVD int UnZipFile (unsigned char *outbuffer, SMBFILE infile); // Reading from SMB diff --git a/source/ngc/input.cpp b/source/ngc/input.cpp index 470919f..d34510a 100644 --- a/source/ngc/input.cpp +++ b/source/ngc/input.cpp @@ -334,16 +334,16 @@ u32 GetJoy() { if (GCSettings.AutoSave == 1) { - SaveBattery(GCSettings.SaveMethod, SILENT); + SaveBatteryOrState(GCSettings.SaveMethod, 0, SILENT); // save battery } else if (GCSettings.AutoSave == 2) { - SaveState(GCSettings.SaveMethod, SILENT); + SaveBatteryOrState(GCSettings.SaveMethod, 1, SILENT); // save state } else if(GCSettings.AutoSave == 3) { - SaveBattery(GCSettings.SaveMethod, SILENT); - SaveState(GCSettings.SaveMethod, SILENT); + SaveBatteryOrState(GCSettings.SaveMethod, 0, SILENT); // save battery + SaveBatteryOrState(GCSettings.SaveMethod, 1, SILENT); // save state } MainMenu(3); return 0; diff --git a/source/ngc/input.h b/source/ngc/input.h index c4b585f..37e0170 100644 --- a/source/ngc/input.h +++ b/source/ngc/input.h @@ -15,7 +15,7 @@ #define PI 3.14159265f #define PADCAL 50 -#define MAXJP 10 +#define MAXJP 10 extern unsigned int gcpadmap[]; extern unsigned int wmpadmap[]; diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index 7a77cd2..8708e3f 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -44,7 +44,7 @@ extern "C" extern void DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsize); extern int menu; -extern int ROMSize; +extern bool ROMLoaded; #define SOFTRESET_ADR ((volatile u32*)0xCC003024) @@ -83,9 +83,9 @@ LoadManager () if ( loadROM == 1 ) // if ROM was loaded, load the battery / state { if (GCSettings.AutoLoad == 1) - LoadBattery(GCSettings.SaveMethod, SILENT); + LoadBatteryOrState(GCSettings.SaveMethod, 0, SILENT); // load battery else if (GCSettings.AutoLoad == 2) - LoadState(GCSettings.SaveMethod, SILENT); + LoadBatteryOrState(GCSettings.SaveMethod, 1, SILENT); // load state } return loadROM; @@ -123,8 +123,6 @@ PreferencesMenu () // they need to be skipped in the order they were enumerated in vba.h // skip - if(GCSettings.LoadMethod == METHOD_DVD) - GCSettings.LoadMethod++; if(GCSettings.SaveMethod == METHOD_MC_SLOTA) GCSettings.SaveMethod++; if(GCSettings.SaveMethod == METHOD_MC_SLOTB) @@ -140,12 +138,6 @@ PreferencesMenu () GCSettings.SaveMethod++; #endif - // check if DVD access in Wii mode is disabled - #ifndef WII_DVD - if(GCSettings.LoadMethod == METHOD_DVD) - GCSettings.LoadMethod++; - #endif - // saving to DVD is impossible if(GCSettings.SaveMethod == METHOD_DVD) GCSettings.SaveMethod++; @@ -306,20 +298,20 @@ GameMenu () break; case 2: // Load Battery - quit = retval = LoadBattery(GCSettings.SaveMethod, NOTSILENT); + quit = retval = LoadBatteryOrState(GCSettings.SaveMethod, 0, NOTSILENT); emulator.emuReset(); break; case 3: // Save Battery - SaveBattery(GCSettings.SaveMethod, NOTSILENT); + SaveBatteryOrState(GCSettings.SaveMethod, 0, NOTSILENT); break; case 4: // Load State - quit = retval = LoadState(GCSettings.SaveMethod, NOTSILENT); + quit = retval = LoadBatteryOrState(GCSettings.SaveMethod, 1, NOTSILENT); break; case 5: // Save State - SaveState(GCSettings.SaveMethod, NOTSILENT); + SaveBatteryOrState(GCSettings.SaveMethod, 1, NOTSILENT); break; case -1: // Button B @@ -630,7 +622,7 @@ MainMenu (int selectedMenu) int ret; // disable game-specific menu items if a ROM isn't loaded - if (ROMSize == 0 ) + if (!ROMLoaded) menuitems[3][0] = '\0'; else sprintf (menuitems[3], "Game Menu"); @@ -697,7 +689,8 @@ MainMenu (int selectedMenu) case -1: // Button B // Return to Game - quit = 1; + if(ROMLoaded) + quit = 1; break; } } diff --git a/source/ngc/menudraw.cpp b/source/ngc/menudraw.cpp index fb28fc4..58ff600 100644 --- a/source/ngc/menudraw.cpp +++ b/source/ngc/menudraw.cpp @@ -366,7 +366,7 @@ WaitPrompt (char *msg) ypos += 32; clearscreen (); - setfontsize(20); + setfontsize(16); DrawText (-1, ypos, msg); ypos += 30; DrawText (-1, ypos, (char*)"Press A to continue"); diff --git a/source/ngc/preferences.cpp b/source/ngc/preferences.cpp index 11e5ce4..e636360 100644 --- a/source/ngc/preferences.cpp +++ b/source/ngc/preferences.cpp @@ -25,12 +25,6 @@ extern int currconfig[4]; -// button map configurations -extern unsigned int gcpadmap[]; -extern unsigned int wmpadmap[]; -extern unsigned int ccpadmap[]; -extern unsigned int ncpadmap[]; - #define PREFS_FILE_NAME "VBAGX.xml" char prefscomment[2][32]; @@ -46,7 +40,7 @@ mxml_node_t *section; mxml_node_t *item; mxml_node_t *elem; -char temp[200]; +char temp[20]; const char * toStr(int i) { @@ -116,7 +110,6 @@ int preparePrefsData (int method) { int offset = 0; - ClearSaveBuffer(); // add save icon and comments for Memory Card saves if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) @@ -305,6 +298,8 @@ SavePrefs (int method, bool silent) int datasize; int offset = 0; + AllocSaveBuffer (); + datasize = preparePrefsData (method); if (!silent) @@ -332,6 +327,8 @@ SavePrefs (int method, bool silent) offset = SaveBufferToMC (savebuffer, CARD_SLOTB, (char *)PREFS_FILE_NAME, datasize, silent); } + FreeSaveBuffer (); + if (offset > 0) { if (!silent) @@ -351,6 +348,8 @@ LoadPrefsFromMethod (int method) char filepath[1024]; int offset = 0; + AllocSaveBuffer (); + if(method == METHOD_SD || method == METHOD_USB) { if(ChangeFATInterface(method, NOTSILENT)) @@ -376,6 +375,8 @@ LoadPrefsFromMethod (int method) if (offset > 0) retval = decodePrefsData (method); + FreeSaveBuffer (); + return retval; } diff --git a/source/ngc/smbop.cpp b/source/ngc/smbop.cpp index 7343b64..3d30650 100644 --- a/source/ngc/smbop.cpp +++ b/source/ngc/smbop.cpp @@ -212,9 +212,11 @@ ParseSMBdirectory () /**************************************************************************** * Load SMB file + * rom - pointer to memory where ROM will be stored + * length - # bytes to read (0 for all) ****************************************************************************/ int -LoadSMBFile (char * rom) +LoadSMBFile (char * rom, int length) { char filepath[MAXPATHLEN]; @@ -226,7 +228,7 @@ LoadSMBFile (char * rom) WaitPrompt((char*) "Maximum filepath length reached!"); return -1; } - return LoadBufferFromSMB(rom, SMBPath(filepath), NOTSILENT); + return LoadBufferFromSMB(rom, SMBPath(filepath), length, NOTSILENT); } /**************************************************************************** @@ -269,8 +271,6 @@ SaveBufferToSMB (char *filepath, int datasize, bool silent) sprintf(msg, "Couldn't save SMB: %s", SMBPath(filepath)); WaitPrompt (msg); } - - ClearSaveBuffer (); return boffset; } @@ -282,12 +282,11 @@ SaveBufferToSMB (char *filepath, int datasize, bool silent) int LoadBufferFromSMB (char *filepath, bool silent) { - ClearSaveBuffer (); - return LoadBufferFromSMB((char *)savebuffer, filepath, silent); + return LoadBufferFromSMB((char *)savebuffer, filepath, 0, silent); } int -LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent) +LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent) { if(!ConnectShare (NOTSILENT)) return 0; @@ -310,17 +309,25 @@ LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent) return 0; } - ret = SMB_ReadFile (sbuffer, 1024, boffset, smbfile); - - if (IsZipFile (sbuffer)) + if(length > 0) { - boffset = UnZipFile ((unsigned char *)sbuffer, smbfile); // unzip from SMB + boffset = SMB_ReadFile (sbuffer, length, 0, smbfile); } - else + else // load whole file { - // Just load the file up - while ((ret = SMB_ReadFile (sbuffer + boffset, 1024, boffset, smbfile)) > 0) - boffset += ret; + ret = SMB_ReadFile (sbuffer, 1024, boffset, smbfile); + + if (IsZipFile (sbuffer)) + { + WaitPrompt("In a ZIP"); + boffset = UnZipFile ((unsigned char *)sbuffer, smbfile); // unzip from SMB + } + else + { + // Just load the file up + while ((ret = SMB_ReadFile (sbuffer + boffset, 1024, boffset, smbfile)) > 0) + boffset += ret; + } } SMB_CloseFile (smbfile); diff --git a/source/ngc/smbop.h b/source/ngc/smbop.h index 31e1bb6..0cebe4d 100644 --- a/source/ngc/smbop.h +++ b/source/ngc/smbop.h @@ -17,9 +17,9 @@ bool ConnectShare (bool silent); char * SMBPath(char * path); int UpdateSMBdirname(); int ParseSMBdirectory (); -int LoadSMBFile (char * fbuffer); +int LoadSMBFile (char * fbuffer, int length); int LoadBufferFromSMB (char *filepath, bool silent); -int LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent); +int LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent); int SaveBufferToSMB (char *filepath, int datasize, bool silent); #endif diff --git a/source/ngc/vba.cpp b/source/ngc/vba.cpp index 097e40b..90e9529 100644 --- a/source/ngc/vba.cpp +++ b/source/ngc/vba.cpp @@ -38,7 +38,7 @@ extern "C" { #include "video.h" #include "vbaconfig.h" -extern int ROMSize; +extern bool ROMLoaded; extern int emulating; @@ -98,7 +98,7 @@ int main() selectedMenu = 2; // change to preferences menu } - while (ROMSize == 0) + while (!ROMLoaded) { MainMenu (selectedMenu); } diff --git a/source/ngc/vbasupport.cpp b/source/ngc/vbasupport.cpp index 0ae2b21..6fb4951 100644 --- a/source/ngc/vbasupport.cpp +++ b/source/ngc/vbasupport.cpp @@ -27,16 +27,19 @@ #include "vba.h" #include "fileop.h" +#include "dvd.h" +#include "smbop.h" +#include "memcardop.h" #include "audio.h" #include "vmmem.h" #include "input.h" #include "video.h" #include "menudraw.h" +#include "gcunzip.h" extern "C" { #include "tbtime.h" -#include "sdfileio.h" } static tb_t start, now; @@ -181,108 +184,261 @@ void debuggerOutput(const char *s, u32 addr) {} void (*dbgOutput)(const char *s, u32 addr) = debuggerOutput; void systemMessage(int num, const char *msg, ...) {} +bool MemCPUReadBatteryFile(char * membuffer, int size) +{ + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + + if(size == 512 || size == 0x2000) + { + memcpy(eepromData, membuffer, size); + } + else + { + if(size == 0x20000) + { + memcpy(flashSaveMemory, membuffer, 0x20000); + flashSetSize(0x20000); + } + else + { + memcpy(flashSaveMemory, membuffer, 0x10000); + flashSetSize(0x10000); + } + } + return true; +} + +extern int gbaSaveType; + +int MemCPUWriteBatteryFile(char * membuffer) +{ + int result = 0; + if(gbaSaveType == 0) + { + if(eepromInUse) + gbaSaveType = 3; + else + switch(saveType) + { + case 1: + gbaSaveType = 1; + break; + case 2: + gbaSaveType = 2; + break; + } + } + + if((gbaSaveType) && (gbaSaveType!=5)) + { + // only save if Flash/Sram in use or EEprom in use + if(gbaSaveType != 3) + { + if(gbaSaveType == 2) + { + memcpy(membuffer, flashSaveMemory, flashSize); + result = flashSize; + } + else + { + memcpy(membuffer, flashSaveMemory, 0x10000); + result = 0x10000; + } + } + else + { + memcpy(membuffer, eepromData, eepromSize); + result = eepromSize; + } + } + return result; +} + /**************************************************************************** -* Saves +* SetFileBytesWritten +* Sets the # of bytes written into a file +* Used by GBA.cpp and GB.cpp ****************************************************************************/ -bool LoadBattery(int method, bool silent) +void SetFileBytesWritten(int bytes) +{ + //datasize = bytes; +} + +/**************************************************************************** +* LoadBatteryOrState +* Load Battery/State file into memory +* action = 0 - Load battery +* action = 1 - Load state +****************************************************************************/ + +bool LoadBatteryOrState(int method, int action, bool silent) { char filepath[1024]; bool result = false; + int offset = 0; + char ext[4]; + + if(action == 0) + sprintf(ext, "sav"); + else + sprintf(ext, "sgm"); ShowAction ((char*) "Loading..."); if(method == METHOD_AUTO) method = autoSaveMethod(); // we use 'Save' because we need R/W - if(method == METHOD_SD || method == METHOD_USB) - { - ChangeFATInterface(method, NOTSILENT); - sprintf (filepath, "%s/%s/%s.sav", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename); - result = emulator.emuReadBattery(filepath); - } + AllocSaveBuffer(); - if(!result && !silent) - WaitPrompt ((char*) "Save file not found"); - - return result; -} - -bool SaveBattery(int method, bool silent) -{ - char filepath[1024]; - bool result = false; - - ShowAction ((char*) "Saving..."); - - if(method == METHOD_AUTO) - method = autoSaveMethod(); // we use 'Save' because we need R/W + // load the file into savebuffer if(method == METHOD_SD || method == METHOD_USB) { - ChangeFATInterface(method, NOTSILENT); - sprintf (filepath, "%s/%s/%s.sav", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename); - result = emulator.emuWriteBattery(filepath); + if(ChangeFATInterface(method, NOTSILENT)) + { + sprintf (filepath, "%s/%s/%s.%s", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename, ext); + offset = LoadBufferFromFAT (filepath, silent); + } } - - if(!silent) + else if(method == METHOD_SMB) { - if(result) - WaitPrompt ((char*) "Save successful"); + sprintf (filepath, "%s/%s.%s", GCSettings.SaveFolder, ROMFilename, ext); + offset = LoadBufferFromSMB (filepath, silent); + } + else if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + sprintf (filepath, "%s.%s", ROMFilename, ext); + + if(method == METHOD_MC_SLOTA) + offset = LoadBufferFromMC (savebuffer, CARD_SLOTA, filepath, silent); else - WaitPrompt ((char*) "Save failed"); + offset = LoadBufferFromMC (savebuffer, CARD_SLOTB, filepath, silent); } - return result; -} - -bool LoadState(int method, bool silent) -{ - char filepath[1024]; - bool result = false; - - ShowAction ((char*) "Loading..."); - - if(method == METHOD_AUTO) - method = autoSaveMethod(); // we use 'Save' because we need R/W - - if(method == METHOD_SD || method == METHOD_USB) + // load savebuffer into VBA memory + if (offset > 0) { - ChangeFATInterface(method, NOTSILENT); - sprintf (filepath, "%s/%s/%s.sgm", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename); - result = emulator.emuReadState(filepath); + if(action == 0) + { + if(cartridgeType == 1) + result = MemgbReadBatteryFile((char *)savebuffer, offset); + else + result = MemCPUReadBatteryFile((char *)savebuffer, offset); + } + else + { + result = emulator.emuReadMemState((char *)savebuffer, offset); + } } - if(!result && !silent) - WaitPrompt ((char*) "State file not found"); + FreeSaveBuffer(); + if(!silent && !result) + { + if(offset == 0) + { + if(action == 0) + WaitPrompt ((char*) "Save file not found"); + else + WaitPrompt ((char*) "State file not found"); + } + else + { + if(action == 0) + WaitPrompt ((char*) "Invalid save file"); + else + WaitPrompt ((char*) "Invalid state file"); + } + } return result; } -bool SaveState(int method, bool silent) + +/**************************************************************************** +* SaveBatteryOrState +* Save Battery/State file into memory +* action = 0 - Save battery +* action = 1 - Save state +****************************************************************************/ + +bool SaveBatteryOrState(int method, int action, bool silent) { char filepath[1024]; bool result = false; + int offset = 0; + char ext[4]; + int datasize = 0; // we need the actual size of the data written + + if(action == 0) + sprintf(ext, "sav"); + else + sprintf(ext, "sgm"); ShowAction ((char*) "Saving..."); if(method == METHOD_AUTO) method = autoSaveMethod(); // we use 'Save' because we need R/W - if(method == METHOD_SD || method == METHOD_USB) + AllocSaveBuffer(); + + // put VBA memory into savebuffer, sets datasize to size of memory written + if(action == 0) { - ChangeFATInterface(method, NOTSILENT); - sprintf (filepath, "%s/%s/%s.sgm", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename); - result = emulator.emuWriteState(filepath); + if(cartridgeType == 1) + datasize = MemgbWriteBatteryFile((char *)savebuffer); + else + datasize = MemCPUWriteBatteryFile((char *)savebuffer); + } + else + { + bool written = emulator.emuWriteMemState((char *)savebuffer, SAVEBUFFERSIZE); + // we really should set datasize to the exact memory size written + // but instead we'll set it at 128K - although much of it will go unused + if(written) + datasize = (512*256); } - if(!silent) + // write savebuffer into file + if(datasize > 0) { - if(result) - WaitPrompt ((char*) "Save successful"); - else - WaitPrompt ((char*) "Save failed"); + if(method == METHOD_SD || method == METHOD_USB) + { + if(ChangeFATInterface(method, NOTSILENT)) + { + sprintf (filepath, "%s/%s/%s.%s", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename, ext); + offset = SaveBufferToFAT (filepath, datasize, silent); + } + } + else if(method == METHOD_SMB) + { + sprintf (filepath, "%s/%s.%s", GCSettings.SaveFolder, ROMFilename, ext); + offset = SaveBufferToSMB (filepath, datasize, silent); + } + else if(method == METHOD_MC_SLOTA || method == METHOD_MC_SLOTB) + { + sprintf (filepath, "%s.%s", ROMFilename, ext); + + if(method == METHOD_MC_SLOTA) + offset = SaveBufferToMC (savebuffer, CARD_SLOTA, filepath, datasize, silent); + else + offset = SaveBufferToMC (savebuffer, CARD_SLOTB, filepath, datasize, silent); + } + + if(offset > 0) + { + if(!silent) + WaitPrompt ((char*) "Save successful"); + result = true; + } } + else + { + if(!silent) + WaitPrompt((char *)"No data to save!"); + } + + FreeSaveBuffer(); return result; } @@ -343,42 +499,72 @@ void systemDrawScreen() } extern bool gbUpdateSizes(); -bool LoadGBROM() +bool LoadGBROM(int method) { - char filepath[1024]; - sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename); - - int size = 0; - + // cleanup GB memory if(gbRom != NULL) - { gbCleanUp(); - } + + gbRom = (u8 *)malloc(1024*1024*4); // allocate 4 MB to GB ROM systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; - gbRom = utilLoad(filepath, - utilIsGBImage, - NULL, - size); - if(!gbRom) - return false; + if(method == METHOD_AUTO) + method = autoLoadMethod(); - gbRomSize = size; + switch (method) + { + case METHOD_SD: + case METHOD_USB: + gbRomSize = LoadFATFile ((char *)gbRom, 0); + break; + + case METHOD_DVD: + gbRomSize = LoadDVDFile ((unsigned char *)gbRom, 0); + break; + + case METHOD_SMB: + gbRomSize = LoadSMBFile ((char *)gbRom, 0); + break; + } + + if(!gbRom) + return false; return gbUpdateSizes(); } -int LoadVBAROM(int method) +bool LoadVBAROM(int method) { - int type = 2; + int type = 0; + bool loaded = false; // image type (checks file extension) -/* if(utilIsGBAImage(filename)) + if(utilIsGBAImage(filelist[selection].filename)) type = 2; - else if(utilIsGBImage(filename)) + else if(utilIsGBImage(filelist[selection].filename)) type = 1; -*/ + else if(utilIsZipFile(filelist[selection].filename)) + { + // we need to check the file extension of the first file in the archive + char * zippedFilename = GetFirstZipFilename (method); + + if(strlen(zippedFilename) > 0) + { + if(utilIsGBAImage(zippedFilename)) + type = 2; + else if(utilIsGBImage(zippedFilename)) + type = 1; + } + } + + // leave before we do anything + if(type != 1 && type != 2) + { + WaitPrompt((char *)"Unknown game image!"); + return false; + } + cartridgeType = 0; srcWidth = 0; srcHeight = 0; @@ -394,7 +580,7 @@ int LoadVBAROM(int method) emulator = GBASystem; srcWidth = 240; srcHeight = 160; - VMCPULoadROM(method); + loaded = VMCPULoadROM(method); // Actual Visual Aspect is 1.57 hAspect = 70; vAspect = 46; @@ -410,7 +596,7 @@ int LoadVBAROM(int method) emulator = GBSystem; srcWidth = 160; srcHeight = 144; - LoadGBROM(); + loaded = LoadGBROM(method); // Actual physical aspect is 1.0 hAspect = 60; vAspect = 46; @@ -418,49 +604,52 @@ int LoadVBAROM(int method) soundQuality = 1; soundBufferLen = 1470 * 2; break; - - default: - WaitPrompt((char *)"Unknown Image"); - return 0; - break; } - // Set defaults - flashSetSize(0x20000); // 128K saves - rtcEnable(true); - agbPrintEnable(false); - soundOffFlag = false; - soundLowPass = true; - - // Setup GX - GX_Render_Init( srcWidth, srcHeight, hAspect, vAspect ); - - if ( cartridgeType == 1 ) + if(!loaded) { - gbSoundReset(); - gbSoundSetQuality(soundQuality); + WaitPrompt((char *)"Error loading game!"); + return false; } else { - soundSetQuality(soundQuality); - CPUInit("/VBA/BIOS/BIOS.GBA", 1); - CPUReset(); + // Set defaults + flashSetSize(0x20000); // 128K saves + rtcEnable(true); + agbPrintEnable(false); + soundOffFlag = false; + soundLowPass = true; + + // Setup GX + GX_Render_Init( srcWidth, srcHeight, hAspect, vAspect ); + + if ( cartridgeType == 1 ) + { + gbSoundReset(); + gbSoundSetQuality(soundQuality); + } + else + { + soundSetQuality(soundQuality); + CPUInit("/VBA/BIOS/BIOS.GBA", 1); + CPUReset(); + } + + soundVolume = 0; + systemSoundOn = true; + + soundInit(); + + emulating = 1; + + // reset frameskip variables + autoFrameSkipLastTime = frameskipadjust = systemFrameSkip = 0; + + // Start system clock + mftb(&start); + + return true; } - - soundVolume = 0; - systemSoundOn = true; - - soundInit(); - - emulating = 1; - - // reset frameskip variables - autoFrameSkipLastTime = frameskipadjust = systemFrameSkip = 0; - - // Start system clock - mftb(&start); - - return 1; } /**************************************************************************** diff --git a/source/ngc/vbasupport.h b/source/ngc/vbasupport.h index a60b9f6..9e9ac49 100644 --- a/source/ngc/vbasupport.h +++ b/source/ngc/vbasupport.h @@ -12,9 +12,7 @@ extern struct EmulatedSystem emulator; extern u32 loadtimeradjust; -int LoadVBAROM(int method); +bool LoadVBAROM(int method); void InitialisePalette(); -bool LoadBattery(int method, bool silent); -bool SaveBattery(int method, bool silent); -bool LoadState(int method, bool silent); -bool SaveState(int method, bool silent); +bool LoadBatteryOrState(int method, int action, bool silent); +bool SaveBatteryOrState(int method, int action, bool silent); diff --git a/source/ngc/vmmem.cpp b/source/ngc/vmmem.cpp index f2ee62e..c404256 100644 --- a/source/ngc/vmmem.cpp +++ b/source/ngc/vmmem.cpp @@ -100,7 +100,7 @@ static void VMClose( void ) * MEM2 version of GBA CPULoadROM ****************************************************************************/ -int VMCPULoadROM(int method) +bool VMCPULoadROM(int method) { VMClose(); VMAllocGBA(); @@ -114,24 +114,28 @@ int VMCPULoadROM(int method) { case METHOD_SD: case METHOD_USB: - GBAROMSize = LoadFATFile ((char *)rom); + GBAROMSize = LoadFATFile ((char *)rom, 0); break; case METHOD_DVD: - GBAROMSize = LoadDVDFile ((unsigned char *)rom); + GBAROMSize = LoadDVDFile ((unsigned char *)rom, 0); break; case METHOD_SMB: - GBAROMSize = LoadSMBFile ((char *)rom); + GBAROMSize = LoadSMBFile ((char *)rom, 0); break; } if(GBAROMSize) + { CPUUpdateRenderBuffers( true ); + return true; + } else + { VMClose(); - - return GBAROMSize; + return false; + } } @@ -202,6 +206,9 @@ u8 VMRead8( u32 address ) #include "Port.h" #include "menudraw.h" +#include "filesel.h" +#include "vba.h" +#include "fileop.h" extern "C" { #include "tbtime.h" @@ -237,7 +244,6 @@ static char *gbabase = NULL; static FILE* romfile = NULL; static int useVM = 0; static u32 GBAROMSize = 0; -static char romfilename[1024]; /** * GBA Memory @@ -365,54 +371,86 @@ static void VMClose( void ) * * VM version of GBA CPULoadROM ****************************************************************************/ -int VMCPULoadROM( char *filename ) + +int VMCPULoadROM(int method) { - int res; - char msg[512]; + int res; + char msg[512]; + char filepath[MAXPATHLEN]; - /** Fix VM **/ - VMClose(); - VMInit(); - VMAllocGBA(); + /** Fix VM **/ + VMClose(); + VMInit(); + VMAllocGBA(); - loadtimeradjust = useVM = GBAROMSize = 0; + loadtimeradjust = useVM = GBAROMSize = 0; - //printf("Filename %s\n", filename); + if(method == METHOD_AUTO) + method = autoLoadMethod(); - romfile = gen_fopen(filename, "rb"); - if ( romfile == NULL ) - { - WaitPrompt((char*) "Error opening file!"); - VMClose(); - return 0; - } + switch (method) + { + case METHOD_SD: + case METHOD_USB: + if(!ChangeFATInterface(method, NOTSILENT)) + { + VMClose(); + return 0; + } + break; - // printf("ROM Size %d\n", romfile->fsize); + case METHOD_DVD: + VMClose(); + return 0; // not implemented + break; - /* Always use VM, regardless of ROM size */ - res = gen_fread(rom, 1, (1 << VMSHIFTBITS), romfile); - if ( res != (1 << VMSHIFTBITS ) ) - { + case METHOD_SMB: + VMClose(); + return 0; // not implemented + break; + } + + /* Check filename length */ + if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN) + sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename); + else + { + WaitPrompt((char*) "Maximum filepath length reached!"); + return -1; + } + + romfile = fopen(filepath, "rb"); + if ( romfile == NULL ) + { + WaitPrompt((char*) "Error opening file!"); + VMClose(); + return 0; + } + + // printf("ROM Size %d\n", romfile->fsize); + + /* Always use VM, regardless of ROM size */ + res = gen_fread(rom, 1, (1 << VMSHIFTBITS), romfile); + if ( res != (1 << VMSHIFTBITS ) ) + { sprintf(msg, "Error reading file! %i \n",res); WaitPrompt(msg); - VMClose(); - return 0; - } + VMClose(); + return 0; + } fseek(romfile, 0, SEEK_END); GBAROMSize = ftell(romfile); fseek(romfile, 0, SEEK_SET); - vmpageno = 0; - vmpage[0].pageptr = rombase; - vmpage[0].pageno = 0; - vmpage[0].pagetype = MEM_VM; - useVM = 1; + vmpageno = 0; + vmpage[0].pageptr = rombase; + vmpage[0].pageno = 0; + vmpage[0].pagetype = MEM_VM; + useVM = 1; - strcpy( romfilename, filename ); + CPUUpdateRenderBuffers( true ); - CPUUpdateRenderBuffers( true ); - - return 1; + return 1; } /**************************************************************************** diff --git a/source/ngc/vmmem.h b/source/ngc/vmmem.h index d757e63..30a316f 100644 --- a/source/ngc/vmmem.h +++ b/source/ngc/vmmem.h @@ -11,7 +11,7 @@ #ifndef __VBAVMHDR__ #define __VBAVMHDR__ -int VMCPULoadROM(int method); +bool VMCPULoadROM(int method); u32 VMRead32( u32 address ); u16 VMRead16( u32 address ); u8 VMRead8( u32 address ); diff --git a/source/vba/Util.cpp b/source/vba/Util.cpp index be3ddaf..a4352ce 100644 --- a/source/vba/Util.cpp +++ b/source/vba/Util.cpp @@ -609,7 +609,7 @@ IMAGE_TYPE utilFindType(const char *file) return IMAGE_UNKNOWN; } -static int utilGetSize(int size) +int utilGetSize(int size) { int res = 1; while(res < size) diff --git a/source/vba/Util.h b/source/vba/Util.h index 6e51802..0d462d3 100644 --- a/source/vba/Util.h +++ b/source/vba/Util.h @@ -35,12 +35,14 @@ typedef struct { int size; } variable_desc; +extern int utilGetSize(int size); extern bool utilWritePNGFile(const char *, int, int, u8 *); extern bool utilWriteBMPFile(const char *, int, int, u8 *); extern void utilApplyIPS(const char *ips, u8 **rom, int *size); extern bool utilIsGBAImage(const char *); extern bool utilIsGBImage(const char *); extern bool utilIsGzipFile(const char *); +extern bool utilIsZipFile(const char *); extern void utilStripDoubleExtension(const char *, char *); extern IMAGE_TYPE utilFindType(const char *); extern u8 *utilLoad(const char *, diff --git a/source/vba/agb/GBA.cpp b/source/vba/agb/GBA.cpp index 5ce6663..02d77cb 100644 --- a/source/vba/agb/GBA.cpp +++ b/source/vba/agb/GBA.cpp @@ -653,6 +653,8 @@ bool CPUWriteState(const char *file) return res; } +extern void SetFileBytesWritten(int bytes); // Tantric - Wii/GameCube addition - store # bytes written + bool CPUWriteMemState(char *memory, int available) { gzFile gzFile = utilMemGzOpen(memory, available, "w"); @@ -668,6 +670,8 @@ bool CPUWriteMemState(char *memory, int available) if(pos >= (available)) res = false; + SetFileBytesWritten((int)pos); // Tantric - Wii/GameCube addition - store # bytes written + utilGzClose(gzFile); return res; diff --git a/source/vba/dmg/GB.cpp b/source/vba/dmg/GB.cpp index 05d3fb1..3664eec 100644 --- a/source/vba/dmg/GB.cpp +++ b/source/vba/dmg/GB.cpp @@ -2303,6 +2303,8 @@ static bool gbWriteSaveState(gzFile gzFile) return true; } +extern void SetFileBytesWritten(int bytes); // Tantric - Wii/GameCube addition - store # bytes written + bool gbWriteMemSaveState(char *memory, int available) { gzFile gzFile = utilMemGzOpen(memory, available, "w"); @@ -2319,6 +2321,8 @@ bool gbWriteMemSaveState(char *memory, int available) if(pos >= (available)) res = false; + SetFileBytesWritten((int)pos); // Tantric - Wii/GameCube addition - store # bytes written + utilGzClose(gzFile); return res; @@ -3469,3 +3473,320 @@ struct EmulatedSystem GBSystem = 1000, #endif }; + +/**************************************************************************** + * Nintendo Wii/Gamecube Port Additions + * + * Duplicate versions of save functions above, using memory + * I want to kill whoever wrote so many stupid functions, and did so without + * doing it memory-based + * Tantric - October 2008 + ***************************************************************************/ + +int MemgbWriteSaveMBC1(char * membuffer) { + if (gbRam) { + memcpy(membuffer, gbRam, (gbRamSizeMask + 1)); + return (gbRamSizeMask + 1); + } + return 0; +} + +int MemgbWriteSaveMBC2(char * membuffer) { + if (gbRam) { + memcpy(membuffer, &gbMemory[0xa000], 256); + return 256; + } + return 0; +} + +int MemgbWriteSaveMBC3(char * membuffer, bool extendedSave) { + int offset = 0; + if (gbRam || extendedSave) { + if (gbRam) { + memcpy(membuffer, gbRam, (gbRamSizeMask + 1)); + offset += (gbRamSizeMask + 1); + } + + if (extendedSave) + { + memcpy(membuffer+offset, &gbDataMBC3.mapperSeconds, (10 * sizeof(int) + + sizeof(time_t))); + offset += (10 * sizeof(int) + sizeof(time_t)); + } + } + return offset; +} + +int MemgbWriteSaveMBC5(char * membuffer) { + if (gbRam) { + memcpy(membuffer, gbRam, (gbRamSizeMask + 1)); + return (gbRamSizeMask + 1); + } + return 0; +} + +int MemgbWriteSaveMBC7(char * membuffer) { + if (gbRam) { + memcpy(membuffer, &gbMemory[0xa000], 256); + return 256; + } + return 0; +} + +int MemgbWriteSaveTAMA5(char * membuffer, bool extendedSave) { + int offset = 0; + +/* if (gbRam) + { + memcpy(membuffer, gbRam, (gbRamSizeMask + 1)); + offset += (gbRamSizeMask + 1); + } + + memcpy(membuffer+offset, gbTAMA5ram, (gbTAMA5ramSize)); + offset += (gbTAMA5ramSize); + + if (extendedSave) + { + memcpy(membuffer+offset, &gbDataTAMA5.mapperSeconds, (14 * sizeof(int) + sizeof(time_t))); + offset += (14 * sizeof(int) + sizeof(time_t)); + }*/ + return offset; +} + +int MemgbWriteSaveMMM01(char * membuffer) { + if (gbRam) { + memcpy(membuffer, gbRam, (gbRamSizeMask + 1)); + return (gbRamSizeMask + 1); + } + return 0; +} + +bool MemgbReadSaveMBC1(char * membuffer, int read) { + if (gbRam) + { + if (read != (gbRamSizeMask + 1)) + return false; + else + memcpy(gbRam, membuffer, read); + return true; + } + return false; +} + +bool MemgbReadSaveMBC2(char * membuffer, int read) { + if (gbRam) + { + if (read != 256) + return false; + else + memcpy(&gbMemory[0xa000], membuffer, read); + return true; + } + return false; +} + +bool MemgbReadSaveMBC3(char * membuffer, int read) { + int offset = 0; + + if (gbRam) + { + if(read < (gbRamSizeMask + 1)) + return false; + memcpy(gbRam, membuffer, (gbRamSizeMask + 1)); + offset += (gbRamSizeMask + 1); + } + + int gbRomType = gbRom[0x147]; + + if ((gbRomType == 0xf) || (gbRomType == 0x10)) + { + if((uint)read < (offset + sizeof(int) * 10 + sizeof(time_t))) + return false; + memcpy(&gbDataMBC3.mapperSeconds, membuffer+offset, sizeof(int) * 10 + sizeof(time_t)); + } + return true; +} + +bool MemgbReadSaveMBC5(char * membuffer, int read) { + if (gbRam) + { + if (read != (gbRamSizeMask + 1)) + return false; + else + memcpy(gbRam, membuffer, read); + return true; + } + return false; +} + +bool MemgbReadSaveMBC7(char * membuffer, int read) { + if (gbRam) + { + if (read != 256) + return false; + else + memcpy(&gbMemory[0xa000], membuffer, read); + return true; + } + return false; +} + +bool MemgbReadSaveTAMA5(char * membuffer, int read) { +/* if (gbRam) + { + if (gbRamSizeMask + gbTAMA5ramSize + 1) + return false; + + memcpy(gbRam, membuffer, (gbRamSizeMask + 1)); + int offset = (gbRamSizeMask + 1); + memcpy(&gbDataTAMA5.mapperSeconds, membuffer+offset, sizeof(int) * 14 + sizeof(time_t)); + return true; + }*/ + return false; +} + +bool MemgbReadSaveMMM01(char * membuffer, int read) { + if (gbRam) + { + if (read != (gbRamSizeMask + 1)) + return false; + else + memcpy(gbRam, membuffer, read); + return true; + } + return false; +} + +int MemgbWriteBatteryFile(char * membuffer) +{ + int result = 0; + if(gbBattery) + { + int type = gbRom[0x147]; + bool extendedSave = true; + + switch(type) + { + case 0x03: + result = MemgbWriteSaveMBC1(membuffer); + break; + case 0x06: + result = MemgbWriteSaveMBC2(membuffer); + break; + case 0x0d: + result = MemgbWriteSaveMMM01(membuffer); + break; + case 0x0f: + case 0x10: + result = MemgbWriteSaveMBC3(membuffer, extendedSave); + break; + case 0x13: + case 0xfc: + result = MemgbWriteSaveMBC3(membuffer, false); + case 0x1b: + case 0x1e: + result = MemgbWriteSaveMBC5(membuffer); + break; + case 0x22: + result = MemgbWriteSaveMBC7(membuffer); + break; + case 0xfd: + result = MemgbWriteSaveTAMA5(membuffer, extendedSave); + break; + case 0xff: + result = MemgbWriteSaveMBC1(membuffer); + break; + } + } + return result; +} + +bool MemgbReadBatteryFile(char * membuffer, int read) +{ + bool res = false; + if (gbBattery) { + int type = gbRom[0x147]; + switch (type) { + case 0x03: + res = MemgbReadSaveMBC1(membuffer, read); + break; + case 0x06: + res = MemgbReadSaveMBC2(membuffer, read); + break; + case 0x0d: + res = MemgbReadSaveMMM01(membuffer, read); + break; + case 0x0f: + case 0x10: + res = MemgbReadSaveMBC3(membuffer, read); + if (!res) { + time(&gbDataMBC3.mapperLastTime); + struct tm *lt; + lt = localtime(&gbDataMBC3.mapperLastTime); + gbDataMBC3.mapperSeconds = lt->tm_sec; + gbDataMBC3.mapperMinutes = lt->tm_min; + gbDataMBC3.mapperHours = lt->tm_hour; + gbDataMBC3.mapperDays = lt->tm_yday & 255; + gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) + | (lt->tm_yday > 255 ? 1 : 0); + res = 0; + break; + } + break; + case 0x13: + case 0xfc: + res = MemgbReadSaveMBC3(membuffer, read); + break; + case 0x1b: + case 0x1e: + res = MemgbReadSaveMBC5(membuffer, read); + break; + case 0x22: + res = MemgbReadSaveMBC7(membuffer, read); + break; + case 0xfd: +/* res = MemgbReadSaveTAMA5(membuffer, read); + if (!res) { + u8 gbDaysinMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, + 31, 30, 31 }; + time(&gbDataTAMA5.mapperLastTime); + struct tm *lt; + lt = localtime(&gbDataTAMA5.mapperLastTime); + gbDataTAMA5.mapperSeconds = lt->tm_sec; + gbDataTAMA5.mapperMinutes = lt->tm_min; + gbDataTAMA5.mapperHours = lt->tm_hour; + gbDataTAMA5.mapperDays = 1; + gbDataTAMA5.mapperMonths = 1; + gbDataTAMA5.mapperYears = 1970; + int days = lt->tm_yday + 365 * 3; + while (days) { + gbDataTAMA5.mapperDays++; + days--; + if (gbDataTAMA5.mapperDays + > gbDaysinMonth[gbDataTAMA5.mapperMonths - 1]) { + gbDataTAMA5.mapperDays = 1; + gbDataTAMA5.mapperMonths++; + if (gbDataTAMA5.mapperMonths > 12) { + gbDataTAMA5.mapperMonths = 1; + gbDataTAMA5.mapperYears++; + if ((gbDataTAMA5.mapperYears & 3) == 0) + gbDaysinMonth[1] = 29; + else + gbDaysinMonth[1] = 28; + } + } + } + gbDataTAMA5.mapperControl = (gbDataTAMA5.mapperControl & 0xfe) + | (lt->tm_yday > 255 ? 1 : 0); + res = false; + break; + }*/ + break; + case 0xff: + res = MemgbReadSaveMBC1(membuffer, read); + break; + } + } + systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED; + return res; +} diff --git a/source/vba/dmg/GB.h b/source/vba/dmg/GB.h index 92e7e08..e20a346 100644 --- a/source/vba/dmg/GB.h +++ b/source/vba/dmg/GB.h @@ -59,4 +59,7 @@ extern bool gbReadGSASnapshot(const char *); extern struct EmulatedSystem GBSystem; +bool MemgbReadBatteryFile(char * membuffer, int read); +int MemgbWriteBatteryFile(char * membuffer); + #endif