diff --git a/include/gba/flash_internal.h b/include/gba/flash_internal.h index 7770037bd0ed..1f43139af75c 100644 --- a/include/gba/flash_internal.h +++ b/include/gba/flash_internal.h @@ -1,7 +1,11 @@ #ifndef GUARD_GBA_FLASH_INTERNAL_H #define GUARD_GBA_FLASH_INTERNAL_H +#ifndef PORTABLE #define FLASH_BASE ((u8 *)0xE000000) +#else +extern unsigned char FLASH_BASE[131072]; +#endif #define FLASH_WRITE(addr, data) ((*(vu8 *)(FLASH_BASE + (addr))) = (data)) diff --git a/include/global.h b/include/global.h index 14a62d747099..41c141e0b31d 100644 --- a/include/global.h +++ b/include/global.h @@ -10,14 +10,15 @@ #define VRAM_ _VRAM_ #define OAM _OAM #define PLTT _PLTT +#define FLASH_BASE _FLASH_BASE #define SOUND_INFO_PTR _SOUND_INFO_PTR #define INTR_CHECK _INTR_CHECK #define INTR_VECTOR _INTR_VECTOR -#define fopen _fopen -#define fseek _fseek -#define fclose _fclose -#define fread _fread -#define fwrite _fwrite +#define fopen _fopen +#define fseek _fseek +#define fclose _fclose +#define fread _fread +#define fwrite _fwrite #define puts _puts #define memcpy _memcpy #define memset _memset @@ -30,7 +31,7 @@ #define DmaSet _DmaSet #define BgAffineSet _BgAffineSet #define ObjAffineSet _ObjAffineSet -#define SoftReset _SoftReset +#define SoftReset _SoftReset #define LZ77UnCompVram _LZ77UnCompVram #define LZ77UnCompWram _LZ77UnCompWram #define RLUnCompVram _RLUnCompVram @@ -44,6 +45,7 @@ #define ConvertBcdToBinary _ConvertBcdToBinary #define DoSoftReset _DoSoftReset #define Platform_GetKeyInput _Platform_GetKeyInput +#define Platform_StoreSaveFile _Platform_StoreSaveFile #define Platform_GetStatus _Platform_GetStatus #define Platform_SetStatus _Platform_SetStatus #define Platform_GetDateTime _Platform_GetDateTime diff --git a/include/platform.h b/include/platform.h index c4df8ef80c5f..b0de67235a90 100644 --- a/include/platform.h +++ b/include/platform.h @@ -4,6 +4,7 @@ struct SiiRtcInfo; u16 Platform_GetKeyInput(void); +void Platform_StoreSaveFile(void); void Platform_GetStatus(struct SiiRtcInfo *rtc); void Platform_SetStatus(struct SiiRtcInfo *rtc); void Platform_GetDateTime(struct SiiRtcInfo *rtc); diff --git a/src/agb_flash_dummy.c b/src/agb_flash_dummy.c index 624eff148cf5..d521c47cd12f 100644 --- a/src/agb_flash_dummy.c +++ b/src/agb_flash_dummy.c @@ -34,83 +34,31 @@ const struct FlashSetupInfo DUMMY_SAVE = u16 WaitForFlashWrite_DUMMY(u8 phase, u8 *addr, u8 lastData) { - puts("function WaitForFlashWrite_DUMMY is a stub"); + // stub return 0; } u16 EraseFlashChip_DUMMY(void) { - puts("EraseFlashChip_DUMMY"); - FILE * savefile = fopen("pokeemerald.sav", "w+b"); - fclose(savefile); + memset(FLASH_BASE, 0xFF, sizeof(FLASH_BASE)); return 0; } u16 EraseFlashSector_DUMMY(u16 sectorNum) { - printf("EraseFlashSector_DUMMY(0x%04X)\n",sectorNum); - FILE * savefile = fopen("pokeemerald.sav", "r+b"); - if (savefile == NULL) - { - savefile = fopen("pokeemerald.sav", "w+b"); - } - if (fseek(savefile, (sectorNum << gFlash->sector.shift), SEEK_SET)) - { - fclose(savefile); - return 1; - } - u8 buf[0x1000] = {0xFF}; - if (fwrite(buf, 1, sizeof(buf), savefile) != sizeof(buf)) - { - fclose(savefile); - return 1; - } - fclose(savefile); - return 0; + u8 clearBuffer[0x1000] = { 0xFF }; + return ProgramFlashSector_DUMMY(sectorNum, &clearBuffer[0]); } u16 ProgramFlashByte_DUMMY(u16 sectorNum, u32 offset, u8 data) { - printf("ProgramFlashByte_DUMMY(0x%04X,0x%08X,0x%02X)\n",sectorNum,offset,data); - u8 val = data; - FILE * savefile = fopen("pokeemerald.sav", "r+b"); - if (savefile == NULL) - { - savefile = fopen("pokeemerald.sav", "w+b"); - } - if (fseek(savefile, (sectorNum << gFlash->sector.shift) + offset, SEEK_SET)) - { - fclose(savefile); - return 1; - } - if (fwrite(&val, 1, 1, savefile) != 1) - { - fclose(savefile); - return 1; - } - fclose(savefile); + FLASH_BASE[(sectorNum << gFlash->sector.shift) + offset] = data; return 0; } u16 ProgramFlashSector_DUMMY(u16 sectorNum, void *src) { - printf("ProgramFlashSector_DUMMY(0x%04X)\n",sectorNum); - FILE * savefile = fopen("pokeemerald.sav", "r+b"); - if (savefile == NULL) - { - savefile = fopen("pokeemerald.sav", "w+b"); - } - if (fseek(savefile, (sectorNum << gFlash->sector.shift), SEEK_SET)) - { - fclose(savefile); - return 1; - } - if (fwrite(src, 1, 0x1000, savefile) != 0x1000) - { - fclose(savefile); - return 1; - } - fclose(savefile); + memcpy(&FLASH_BASE[sectorNum << gFlash->sector.shift], src, 0x1000); return 0; } diff --git a/src/agb_flash_mx.c b/src/agb_flash_mx.c index 425091db52c6..422e8a59e041 100644 --- a/src/agb_flash_mx.c +++ b/src/agb_flash_mx.c @@ -1,6 +1,6 @@ +#include "global.h" #include "gba/gba.h" #include "gba/flash_internal.h" -#include "global.h" #ifdef PORTABLE extern unsigned char REG_BASE[0x400] __attribute__((aligned(4))); diff --git a/src/clear_save_data_screen.c b/src/clear_save_data_screen.c index 0d69eb0fa913..e54ffd9736b3 100644 --- a/src/clear_save_data_screen.c +++ b/src/clear_save_data_screen.c @@ -105,6 +105,12 @@ static void Task_ClearSaveDataScreenYesNoChoice(u8 taskId) static void Task_ClearSaveData(u8 taskId) { ClearSaveData(); + +#ifdef PORTABLE + // Calling Platform_StoreSaveFile here to guarantee it is properly erased + Platform_StoreSaveFile(); +#endif + DestroyTask(taskId); SetMainCallback2(CB2_FadeAndDoReset); } diff --git a/src/platform/sdl2.c b/src/platform/sdl2.c index 4206ed1a130b..a4fb872dc107 100644 --- a/src/platform/sdl2.c +++ b/src/platform/sdl2.c @@ -70,12 +70,19 @@ double fixedTimestep = 1.0 / 60.0; // 16.666667ms double timeScale = 1.0; struct SiiRtcInfo internalClock; +static FILE *sSaveFile = NULL; + extern void AgbMain(void); extern void DoSoftReset(void); int DoMain(void *param); void ProcessEvents(void); void VDraw(SDL_Texture *texture); + +static void ReadSaveFile(char *path); +static void StoreSaveFile(void); +static void CloseSaveFile(void); + static void UpdateInternalClock(void); static void RunDMAs(u32 type); @@ -88,6 +95,8 @@ int main(int argc, char **argv) freopen( "CON", "w", stdout ) ; #endif + ReadSaveFile("pokeemerald.sav"); + if(SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); @@ -187,11 +196,62 @@ int main(int argc, char **argv) SDL_RenderPresent(sdlRenderer); } + //StoreSaveFile(); + CloseSaveFile(); + SDL_DestroyWindow(sdlWindow); SDL_Quit(); return 0; } +static void ReadSaveFile(char *path) +{ + // Check whether the saveFile exists, and create it if not + sSaveFile = fopen(path, "r+b"); + if (sSaveFile == NULL) + { + sSaveFile = fopen(path, "w+b"); + } + + fseek(sSaveFile, 0, SEEK_END); + int fileSize = ftell(sSaveFile); + fseek(sSaveFile, 0, SEEK_SET); + + // Only read as many bytes as fit inside the buffer + // or as many bytes as are in the file + int bytesToRead = (fileSize < sizeof(FLASH_BASE)) ? fileSize : sizeof(FLASH_BASE); + + int bytesRead = fread(FLASH_BASE, 1, bytesToRead, sSaveFile); + + // Fill the buffer if the savefile was just created or smaller than the buffer itself + for (int i = bytesRead; i < sizeof(FLASH_BASE); i++) + { + FLASH_BASE[i] = 0xFF; + } +} + +static void StoreSaveFile() +{ + if (sSaveFile != NULL) + { + fseek(sSaveFile, 0, SEEK_SET); + fwrite(FLASH_BASE, 1, sizeof(FLASH_BASE), sSaveFile); + } +} + +void Platform_StoreSaveFile(void) +{ + StoreSaveFile(); +} + +static void CloseSaveFile() +{ + if (sSaveFile != NULL) + { + fclose(sSaveFile); + } +} + // Key mappings #define KEY_A_BUTTON SDLK_z #define KEY_B_BUTTON SDLK_x diff --git a/src/save.c b/src/save.c index bbf4e7dbef56..ef8f3c7d3c26 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,5 @@ #include "global.h" +#include "platform.h" #include "agb_flash.h" #include "gba/flash_internal.h" #include "fieldmap.h" @@ -700,6 +701,11 @@ u8 HandleSavingData(u8 saveType) SaveWriteToFlash(0xFFFF, gRamSaveSectionLocations); break; } + +#ifdef PORTABLE + Platform_StoreSaveFile(); +#endif + gTrainerHillVBlankCounter = backupVar; return 0; } @@ -715,6 +721,9 @@ u8 TrySavingData(u8 saveType) HandleSavingData(saveType); if (!gDamagedSaveSectors) { +#ifdef PORTABLE + Platform_StoreSaveFile(); +#endif gSaveAttemptStatus = SAVE_STATUS_OK; return SAVE_STATUS_OK; }