diff --git a/desmume/src/FIFO.h b/desmume/src/FIFO.h index a96b4c7fe..15ed5da60 100644 --- a/desmume/src/FIFO.h +++ b/desmume/src/FIFO.h @@ -28,12 +28,12 @@ typedef struct { - bool error; - bool enable; + BOOL error; + BOOL enable; - bool empty; - bool half; - bool full; + BOOL empty; + BOOL half; + BOOL full; u8 irq; u8 sendPos; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 45d5c8746..823f52a61 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -424,11 +424,8 @@ void NDS_FreeROM(void) MMU.bupmem.fp = NULL; } - - void NDS_Reset( void) { - BOOL oldexecute=execute; int i; u32 src; u32 dst; @@ -436,8 +433,6 @@ void NDS_Reset( void) if (!header) return ; - execute = FALSE; - MMU_clearMem(); src = header->ARM9src; @@ -460,6 +455,7 @@ void NDS_Reset( void) src += 4; } + armcpu_init(&NDS_ARM7, header->ARM7exe); armcpu_init(&NDS_ARM9, header->ARM9exe); @@ -543,8 +539,6 @@ void NDS_Reset( void) gfx3d_reset(); gpu3D->NDS_3D_Reset(); SPU_Reset(); - - execute = oldexecute; } int NDS_ImportSave(const char *filename) diff --git a/desmume/src/cp15.h b/desmume/src/cp15.h index 49496f3e5..a6499ca30 100644 --- a/desmume/src/cp15.h +++ b/desmume/src/cp15.h @@ -24,7 +24,7 @@ #include "armcpu.h" -typedef struct +struct armcp15_t { u32 IDCode; u32 cacheType; @@ -70,7 +70,7 @@ typedef struct armcpu_t * cpu; -} armcp15_t; +}; armcp15_t *armcp15_new(armcpu_t *c); BOOL armcp15_dataProcess(armcp15_t *armcp15, u8 CRd, u8 CRn, u8 CRm, u8 opcode1, u8 opcode2); diff --git a/desmume/src/saves.cpp b/desmume/src/saves.cpp index 64483dbe0..538aa0e82 100644 --- a/desmume/src/saves.cpp +++ b/desmume/src/saves.cpp @@ -24,12 +24,14 @@ #endif #include #include -#include "saves.h" -#include "MMU.h" -#include "NDSSystem.h" #include #include #include +#include "saves.h" +#include "MMU.h" +#include "NDSSystem.h" +#include "render3D.h" +#include "cp15.h" #include "memorystream.h" #include "readwrite.h" @@ -202,6 +204,26 @@ SFORMAT SF_MMU[]={ { "MC1T", 4, 1, &MMU.dscard[1].transfer_count}, { "MCHT", 4, 1, &MMU.CheckTimers}, { "MCHD", 4, 1, &MMU.CheckDMAs}, + + //fifos + { "F0ER", 4, 1, &MMU.fifos[0].error}, + { "F0EN", 4, 1, &MMU.fifos[0].enable}, + { "F0EM", 4, 1, &MMU.fifos[0].empty}, + { "F0HA", 4, 1, &MMU.fifos[0].half}, + { "F0FU", 4, 1, &MMU.fifos[0].full}, + { "F0IR", 1, 1, &MMU.fifos[0].irq}, + { "F0SP", 1, 1, &MMU.fifos[0].sendPos}, + { "F0RP", 1, 1, &MMU.fifos[0].recvPos}, + { "F0BU", 1, 0x8000, &MMU.fifos[0].buf}, + { "F1ER", 4, 1, &MMU.fifos[1].error}, + { "F1EN", 4, 1, &MMU.fifos[1].enable}, + { "F1EM", 4, 1, &MMU.fifos[1].empty}, + { "F1HA", 4, 1, &MMU.fifos[1].half}, + { "F1FU", 4, 1, &MMU.fifos[1].full}, + { "F1IR", 1, 1, &MMU.fifos[1].irq}, + { "F1SP", 1, 1, &MMU.fifos[1].sendPos}, + { "F1RP", 1, 1, &MMU.fifos[1].recvPos}, + { "F1BU", 1, 0x8000, &MMU.fifos[1].buf}, { 0 } }; @@ -232,6 +254,117 @@ bool mmu_loadstate(std::istream* is) return true; } +static void cp15_saveone(armcp15_t *cp15, std::ostream* os) +{ + write32le(cp15->IDCode,os); + write32le(cp15->cacheType,os); + write32le(cp15->TCMSize,os); + write32le(cp15->ctrl,os); + write32le(cp15->DCConfig,os); + write32le(cp15->ICConfig,os); + write32le(cp15->writeBuffCtrl,os); + write32le(cp15->und,os); + write32le(cp15->DaccessPerm,os); + write32le(cp15->IaccessPerm,os); + write32le(cp15->protectBaseSize0,os); + write32le(cp15->protectBaseSize1,os); + write32le(cp15->protectBaseSize2,os); + write32le(cp15->protectBaseSize3,os); + write32le(cp15->protectBaseSize4,os); + write32le(cp15->protectBaseSize5,os); + write32le(cp15->protectBaseSize6,os); + write32le(cp15->protectBaseSize7,os); + write32le(cp15->cacheOp,os); + write32le(cp15->DcacheLock,os); + write32le(cp15->IcacheLock,os); + write32le(cp15->ITCMRegion,os); + write32le(cp15->DTCMRegion,os); + write32le(cp15->processID,os); + write32le(cp15->RAM_TAG,os); + write32le(cp15->testState,os); + write32le(cp15->cacheDbg,os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteMask_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadMask_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadMask_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteMask_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionWriteSet_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadSet_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionReadSet_SYS[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_USR[i],os); + for(int i=0;i<8;i++) write32le(cp15->regionExecuteSet_SYS[i],os); +} + +void cp15_savestate(std::ostream* os) +{ + //version + write32le(0,os); + + cp15_saveone((armcp15_t *)NDS_ARM9.coproc[15],os); + cp15_saveone((armcp15_t *)NDS_ARM7.coproc[15],os); +} + +static bool cp15_loadone(armcp15_t *cp15, std::istream* is) +{ + if(!read32le(&cp15->IDCode,is)) return false; + if(!read32le(&cp15->cacheType,is)) return false; + if(!read32le(&cp15->TCMSize,is)) return false; + if(!read32le(&cp15->ctrl,is)) return false; + if(!read32le(&cp15->DCConfig,is)) return false; + if(!read32le(&cp15->ICConfig,is)) return false; + if(!read32le(&cp15->writeBuffCtrl,is)) return false; + if(!read32le(&cp15->und,is)) return false; + if(!read32le(&cp15->DaccessPerm,is)) return false; + if(!read32le(&cp15->IaccessPerm,is)) return false; + if(!read32le(&cp15->protectBaseSize0,is)) return false; + if(!read32le(&cp15->protectBaseSize1,is)) return false; + if(!read32le(&cp15->protectBaseSize2,is)) return false; + if(!read32le(&cp15->protectBaseSize3,is)) return false; + if(!read32le(&cp15->protectBaseSize4,is)) return false; + if(!read32le(&cp15->protectBaseSize5,is)) return false; + if(!read32le(&cp15->protectBaseSize6,is)) return false; + if(!read32le(&cp15->protectBaseSize7,is)) return false; + if(!read32le(&cp15->cacheOp,is)) return false; + if(!read32le(&cp15->DcacheLock,is)) return false; + if(!read32le(&cp15->IcacheLock,is)) return false; + if(!read32le(&cp15->ITCMRegion,is)) return false; + if(!read32le(&cp15->DTCMRegion,is)) return false; + if(!read32le(&cp15->processID,is)) return false; + if(!read32le(&cp15->RAM_TAG,is)) return false; + if(!read32le(&cp15->testState,is)) return false; + if(!read32le(&cp15->cacheDbg,is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteMask_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadMask_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteMask_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionWriteSet_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionReadSet_SYS[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_USR[i],is)) return false; + for(int i=0;i<8;i++) if(!read32le(&cp15->regionExecuteSet_SYS[i],is)) return false; + + return true; +} + +bool cp15_loadstate(std::istream* is) +{ + //read version + int version; + if(read32le(&version,is) != 1) return false; + if(version != 0) return false; + + if(!cp15_loadone((armcp15_t *)NDS_ARM9.coproc[15],is)) return false; + if(!cp15_loadone((armcp15_t *)NDS_ARM7.coproc[15],is)) return false; + + return true; +} + + /* Format time and convert to string */ char * format_time(time_t cal_time) @@ -571,14 +704,15 @@ bool savestate_save (const char *file_name) static void writechunks(std::ostream* os) { savestate_WriteChunk(os,1,SF_ARM9); savestate_WriteChunk(os,2,SF_ARM7); - savestate_WriteChunk(os,3,SF_MEM); - savestate_WriteChunk(os,4,SF_NDS); - savestate_WriteChunk(os,50,SF_MMU); - savestate_WriteChunk(os,51,mmu_savestate); - savestate_WriteChunk(os,6,gpu_savestate); - savestate_WriteChunk(os,7,spu_savestate); - savestate_WriteChunk(os,80,SF_GFX3D); - savestate_WriteChunk(os,81,gfx3d_savestate); + savestate_WriteChunk(os,3,cp15_savestate); + savestate_WriteChunk(os,4,SF_MEM); + savestate_WriteChunk(os,5,SF_NDS); + savestate_WriteChunk(os,60,SF_MMU); + savestate_WriteChunk(os,61,mmu_savestate); + savestate_WriteChunk(os,7,gpu_savestate); + savestate_WriteChunk(os,8,spu_savestate); + savestate_WriteChunk(os,90,SF_GFX3D); + savestate_WriteChunk(os,91,gfx3d_savestate); savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0); } @@ -596,14 +730,15 @@ static bool ReadStateChunks(std::istream* is, s32 totalsize) { case 1: if(!ReadStateChunk(is,SF_ARM9,size)) ret=false; break; case 2: if(!ReadStateChunk(is,SF_ARM7,size)) ret=false; break; - case 3: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break; - case 4: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break; - case 50: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break; - case 51: if(!mmu_loadstate(is)) ret=false; break; - case 6: if(!gpu_loadstate(is)) ret=false; break; - case 7: if(!spu_loadstate(is)) ret=false; break; - case 80: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break; - case 81: if(!gfx3d_loadstate(is)) ret=false; break; + case 3: if(!cp15_loadstate(is)) ret=false; break; + case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break; + case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break; + case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break; + case 61: if(!mmu_loadstate(is)) ret=false; break; + case 7: if(!gpu_loadstate(is)) ret=false; break; + case 8: if(!spu_loadstate(is)) ret=false; break; + case 90: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break; + case 91: if(!gfx3d_loadstate(is)) ret=false; break; default: ret=false; break; @@ -670,14 +805,18 @@ bool savestate_load(std::istream* is) //GO!! READ THE SAVESTATE //THERE IS NO GOING BACK NOW //reset the emulator first to clean out the host's state - //NDS_Reset(); - //************* OH NO ********************** - //we arent saving something we need to! - //maybe MMU state or maybe FIFO - //I will have to look into this soon + + //while the series of resets below should work, + //we are testing the robustness of the savestate system with this full reset. + //the full reset wipes more things, so we can make sure that they are being restored correctly + NDS_Reset(); + + //GPU_Reset(MainScreen.gpu, 0); + //GPU_Reset(SubScreen.gpu, 1); + //gfx3d_reset(); + //gpu3D->NDS_3D_Reset(); + //SPU_Reset(); - //hack - SPU_Reset(); memorystream mstemp(&buf); bool x = ReadStateChunks(&mstemp,(s32)len);