- add mmu to savestate.

- totally change how the savestates work in order to fix a bug in the gfx3d savestate. your old savestates are definitely invalidated.
- rename adress to address everywhere.
This commit is contained in:
zeromus 2008-09-27 06:52:33 +00:00
parent a45b610c70
commit 6a696d6bb8
8 changed files with 360 additions and 304 deletions

View File

@ -2011,6 +2011,7 @@ void GPU_ligne(NDS_Screen * screen, u16 l)
/* initialize the scanline black */ /* initialize the scanline black */
/* not doing this causes invalid colors when all active BGs are prevented to draw at some place */ /* not doing this causes invalid colors when all active BGs are prevented to draw at some place */
//ZERO TODO - shouldnt this be BG palette color 0?
memset(dst,0,256*2) ; memset(dst,0,256*2) ;
// This could almost be changed to use function pointers // This could almost be changed to use function pointers

View File

@ -647,7 +647,7 @@ u16 FASTCALL _MMU_read16(u32 adr)
if(adr&0x04000000) if(adr&0x04000000)
{ {
/* Adress is an IO register */ /* Address is an IO register */
switch(adr) switch(adr)
{ {
case 0x04000604: case 0x04000604:
@ -721,7 +721,7 @@ u32 FASTCALL _MMU_read32(u32 adr)
if((adr >> 24) == 4) if((adr >> 24) == 4)
{ {
/* Adress is an IO register */ /* Address is an IO register */
switch(adr) switch(adr)
{ {
// This is hacked due to the only current 3D core // This is hacked due to the only current 3D core
@ -826,10 +826,10 @@ u32 FASTCALL _MMU_read32(u32 adr)
{ {
u32 val=0; u32 val=0;
if(MMU.dscard[proc].adress) if(MMU.dscard[proc].address)
val = T1ReadLong(MMU.CART_ROM, MMU.dscard[proc].adress); val = T1ReadLong(MMU.CART_ROM, MMU.dscard[proc].address);
MMU.dscard[proc].adress += 4; /* increment adress */ MMU.dscard[proc].address += 4; /* increment address */
MMU.dscard[proc].transfer_count--; /* update transfer counter */ MMU.dscard[proc].transfer_count--; /* update transfer counter */
if(MMU.dscard[proc].transfer_count) /* if transfer is not ended */ if(MMU.dscard[proc].transfer_count) /* if transfer is not ended */
@ -1306,7 +1306,7 @@ void FASTCALL _MMU_write16(u32 adr, u16 val)
((u16 *)(MMU.MMU_MEM[proc][0x40]))[(adr-0x04000000)>>1] = val; ((u16 *)(MMU.MMU_MEM[proc][0x40]))[(adr-0x04000000)>>1] = val;
gfx3d_UpdateToonTable(&((MMU.MMU_MEM[proc][0x40]))[(0x380)]); gfx3d_UpdateToonTable(&((MMU.MMU_MEM[proc][0x40]))[(0x380)]);
} }
/* Adress is an IO register */ /* Address is an IO register */
else switch(adr) else switch(adr)
{ {
case 0x0400035C: case 0x0400035C:
@ -2843,7 +2843,7 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
if(MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB7) if(MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB7)
{ {
MMU.dscard[proc].adress = (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+1) << 24) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+2) << 16) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+3) << 8) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+4)); MMU.dscard[proc].address = (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+1) << 24) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+2) << 16) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+3) << 8) | (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT+4));
MMU.dscard[proc].transfer_count = 0x80;// * ((val>>24)&7)); MMU.dscard[proc].transfer_count = 0x80;// * ((val>>24)&7));
} }
else if (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB8) else if (MEM_8(MMU.MMU_MEM[proc], REG_GCCMDOUT) == 0xB8)
@ -2851,7 +2851,7 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
// Get ROM chip ID // Get ROM chip ID
val |= 0x800000; // Data-Word Status val |= 0x800000; // Data-Word Status
T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);
MMU.dscard[proc].adress = 0; MMU.dscard[proc].address = 0;
} }
else else
{ {
@ -2861,7 +2861,7 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
//CARDLOG("%08X : %08X %08X\r\n", adr, val, adresse[proc]); //CARDLOG("%08X : %08X %08X\r\n", adr, val, adresse[proc]);
val |= 0x00800000; val |= 0x00800000;
if(MMU.dscard[proc].adress == 0) if(MMU.dscard[proc].address == 0)
{ {
val &= ~0x80000000; val &= ~0x80000000;
T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val); T1WriteLong(MMU.MMU_MEM[proc][(REG_GCROMCTRL >> 20) & 0xff], REG_GCROMCTRL & 0xfff, val);

View File

@ -33,7 +33,7 @@
extern char szRomPath[512]; extern char szRomPath[512];
extern char szRomBaseName[512]; extern char szRomBaseName[512];
/* theses macros are designed for reading/writing in memory (m is a pointer to memory, like MMU.MMU_MEM[proc], and a is an adress, like 0x04000000 */ /* theses macros are designed for reading/writing in memory (m is a pointer to memory, like MMU.MMU_MEM[proc], and a is an address, like 0x04000000 */
#define MEM_8(m, a) (((u8*)(m[((a)>>20)&0xff]))[((a)&0xfff)]) #define MEM_8(m, a) (((u8*)(m[((a)>>20)&0xff]))[((a)&0xfff)])
/* theses ones for reading in rom data */ /* theses ones for reading in rom data */
@ -43,60 +43,59 @@ extern char szRomBaseName[512];
//#define MAIN_MEMORY_DISP_FIFO 2 //#define MAIN_MEMORY_DISP_FIFO 2
typedef struct { typedef struct {
//ARM7 mem //ARM7 mem
u8 ARM7_BIOS[0x4000]; u8 ARM7_BIOS[0x4000];
u8 ARM7_ERAM[0x10000]; u8 ARM7_ERAM[0x10000];
u8 ARM7_REG[0x10000]; u8 ARM7_REG[0x10000];
u8 ARM7_WIRAM[0x10000]; u8 ARM7_WIRAM[0x10000];
u8 vram_mode[9]; u8 vram_mode[9];
u8 vScreen;
//Shared ram //Shared ram
u8 SWIRAM[0x8000]; u8 SWIRAM[0x8000];
//Card rom & ram //Card rom & ram
u8 * CART_ROM; u8 * CART_ROM;
u8 CART_RAM[0x10000]; u8 CART_RAM[0x10000];
//Unused ram //Unused ram
u8 UNUSED_RAM[4]; u8 UNUSED_RAM[4];
u8 * * MMU_MEM[2]; u8 * * MMU_MEM[2];
u32 * MMU_MASK[2]; u32 * MMU_MASK[2];
u8 ARM9_RW_MODE; u8 ARM9_RW_MODE;
FIFO fifos[2]; // 0 - ARM9 FIFO FIFO fifos[2]; // 0 - ARM9 FIFO
// 1 - ARM7 FIFO // 1 - ARM7 FIFO
u32 * MMU_WAIT16[2]; u32 * MMU_WAIT16[2];
u32 * MMU_WAIT32[2]; u32 * MMU_WAIT32[2];
u32 DTCMRegion; u32 DTCMRegion;
u32 ITCMRegion; u32 ITCMRegion;
u16 timer[2][4]; u16 timer[2][4];
s32 timerMODE[2][4]; s32 timerMODE[2][4];
u32 timerON[2][4]; u32 timerON[2][4];
u32 timerRUN[2][4]; u32 timerRUN[2][4];
u16 timerReload[2][4]; u16 timerReload[2][4];
u32 reg_IME[2]; u32 reg_IME[2];
u32 reg_IE[2]; u32 reg_IE[2];
u32 reg_IF[2]; u32 reg_IF[2];
u32 DMAStartTime[2][4]; u32 DMAStartTime[2][4];
s32 DMACycle[2][4]; s32 DMACycle[2][4];
u32 DMACrt[2][4]; u32 DMACrt[2][4];
BOOL DMAing[2][4]; BOOL DMAing[2][4];
memory_chip_t fw; memory_chip_t fw;
memory_chip_t bupmem; memory_chip_t bupmem;
nds_dscard dscard[2]; nds_dscard dscard[2];
u32 CheckTimers; u32 CheckTimers;
u32 CheckDMAs; u32 CheckDMAs;
} MMU_struct; } MMU_struct;

View File

@ -1502,7 +1502,7 @@ bool spu_loadstate(std::istream* is)
//copy the core spu (the more accurate) to the user spu //copy the core spu (the more accurate) to the user spu
if(SPU_user) { if(SPU_user) {
memcpy(SPU_core->channels,SPU_user->channels,sizeof(SPU_core->channels)); memcpy(SPU_user->channels,SPU_core->channels,sizeof(SPU_core->channels));
} }
return true; return true;

View File

@ -23,7 +23,7 @@
typedef struct typedef struct
{ {
u32 adress; u32 address;
u32 transfer_count; u32 transfer_count;
} nds_dscard; } nds_dscard;

View File

@ -1472,71 +1472,71 @@ void gfx3d_glGetLightColor(unsigned int index, unsigned int* dest)
SFORMAT SF_GFX3D[]={ SFORMAT SF_GFX3D[]={
{ &control, 4|SS_RLSB, "GCTL" }, { "GCTL", 4, 1, &control},
{ &polyAttr, 4|SS_RLSB, "GPAT" }, { "GPAT", 4, 1, &polyAttr},
{ &textureFormat, 4|SS_RLSB, "GTFM" }, { "GTFM", 4, 1, &textureFormat},
{ &texturePalette, 4|SS_RLSB, "GTPA" }, { "GTPA", 4, 1, &texturePalette},
{ &mode, 4|SS_RLSB, "GMOD" }, { "GMOD", 4, 1, &mode},
{ mtxTemporal, 4|SS_MULT(16), "GMTM" }, { "GMTM", 4,16, mtxTemporal},
{ mtxCurrent, 4|SS_MULT(64), "GMCU" }, { "GMCU", 4,64, mtxCurrent},
{ &mtxStack[0].position, 4|SS_RLSB, "GM0P" }, { "GM0P", 4, 1, &mtxStack[0].position},
{ mtxStack[0].matrix, 4|SS_MULT(16), "GM1M" }, { "GM1M", 4,16, mtxStack[0].matrix},
{ &mtxStack[1].position, 4|SS_RLSB, "GM1P" }, { "GM1P", 4, 1, &mtxStack[1].position},
{ mtxStack[1].matrix, 4|SS_MULT(16*31), "GM1M" }, { "GM1M", 4,496,mtxStack[1].matrix},
{ &mtxStack[2].position, 4|SS_RLSB, "GM2P" }, { "GM2P", 4, 1, &mtxStack[2].position},
{ mtxStack[2].matrix, 4|SS_MULT(16*31), "GM2M" }, { "GM2M", 4,496,mtxStack[2].matrix},
{ &mtxStack[3].position, 4|SS_RLSB, "GM3P" }, { "GM3P", 4, 1, &mtxStack[3].position},
{ mtxStack[3].matrix, 4|SS_MULT(16), "GM3M" }, { "GM3M", 4,16, mtxStack[3].matrix},
{ &ML4x4ind, 1, "ML4I" }, { "ML4I", 1, 1, &ML4x4ind},
{ &ML4x3_c, 1, "ML3C" }, { "ML3C", 1, 1, &ML4x3_c},
{ &ML4x3_l, 1, "ML3L" }, { "ML3L", 1, 1, &ML4x3_l},
{ &MM4x4ind, 1, "MM4I" }, { "MM4I", 1, 1, &MM4x4ind},
{ &MM4x3_c, 1, "MM3C" }, { "MM3C", 1, 1, &MM4x3_c},
{ &MM4x3_l, 1, "MM3L" }, { "MM3L", 1, 1, &MM4x3_l},
{ &MM3x3_c, 1, "MMxC" }, { "MMxC", 1, 1, &MM3x3_c},
{ &MM3x3_l, 1, "MMxL" }, { "MMxL", 1, 1, &MM3x3_l},
{ coord, 4|SS_MULT(4), "GCOR" }, { "GCOR", 4, 1, coord},
{ &coordind, 1, "GCOI" }, { "GCOI", 1, 1, &coordind},
{ &vtxFormat, 4|SS_RLSB, "GCOI" }, { "GVFM", 4, 1, &vtxFormat},
{ trans, 4|SS_MULT(4), "GTRN" }, { "GTRN", 4, 4, trans},
{ &transind, 1, "GTRI" }, { "GTRI", 1, 1, &transind},
{ scale, 4|SS_MULT(4), "GSCA" }, { "GSCA", 4, 4, scale},
{ &scaleind, 1, "GSCI" }, { "GSCI", 1, 1, &scaleind},
{ &_t, 4|SS_RLSB, "G_T_" }, { "G_T_", 4, 1, &_t},
{ &_s, 4|SS_RLSB, "G_S_" }, { "G_S_", 4, 1, &_s},
{ &last_t, 4|SS_RLSB, "GL_T" }, { "GL_T", 4, 1, &last_t},
{ &last_s, 4|SS_RLSB, "GL_S" }, { "GL_S", 4, 1, &last_s},
{ &clCmd, 4|SS_RLSB, "GLCM" }, { "GLCM", 4, 1, &clCmd},
{ &clInd, 4|SS_RLSB, "GLIN" }, { "GLIN", 4, 1, &clInd},
{ &clInd2, 4|SS_RLSB, "GLI2" }, { "GLI2", 4, 1, &clInd2},
{ colorRGB, 4, "GCOL" }, { "GCOL", 1, 4, colorRGB},
{ lightColor, 4|SS_MULT(4), "GLCO" }, { "GLCO", 4, 4, lightColor},
{ lightDirection, 4|SS_MULT(4), "GLDI" }, { "GLDI", 4, 4, lightDirection},
{ &dsDiffuse, 2|SS_RLSB, "GMDI" }, { "GMDI", 2, 1, &dsDiffuse},
{ &dsAmbient, 2|SS_RLSB, "GMAM" }, { "GMAM", 2, 1, &dsAmbient},
{ &dsSpecular, 2|SS_RLSB, "GMSP" }, { "GMSP", 2, 1, &dsSpecular},
{ &dsEmission, 2|SS_RLSB, "GMEM" }, { "GMEM", 2, 1, &dsEmission},
{ &triStripToggle, 4|SS_RLSB, "GTST" }, { "GTST", 4, 1, &triStripToggle},
{ &listTwiddle, 4|SS_RLSB, "GLTW" }, { "GLTW", 4, 1, &listTwiddle},
{ &flushPending, 4|SS_RLSB, "GFLP" }, { "GFLP", 4, 1, &flushPending},
{ &gfx3d.enableTexturing, 4|SS_RLSB, "GSET" }, { "GSET", 4, 1, &gfx3d.enableTexturing},
{ &gfx3d.enableAlphaTest, 4|SS_RLSB, "GSEA" }, { "GSEA", 4, 1, &gfx3d.enableAlphaTest},
{ &gfx3d.enableAlphaBlending, 4|SS_RLSB, "GSEB" }, { "GSEB", 4, 1, &gfx3d.enableAlphaBlending},
{ &gfx3d.enableAntialiasing, 4|SS_RLSB, "GSEX" }, { "GSEX", 4, 1, &gfx3d.enableAntialiasing},
{ &gfx3d.enableEdgeMarking, 4|SS_RLSB, "GSEE" }, { "GSEE", 4, 1, &gfx3d.enableEdgeMarking},
{ &gfx3d.shading, 4|SS_RLSB, "GSSH" }, { "GSSH", 4, 1, &gfx3d.shading},
{ &gfx3d.wbuffer, 4|SS_RLSB, "GSWB" }, { "GSWB", 4, 1, &gfx3d.wbuffer},
{ &gfx3d.sortmode, 4|SS_RLSB, "GSSM" }, { "GSSM", 4, 1, &gfx3d.sortmode},
{ &gfx3d.alphaTestRef, 4|SS_RLSB, "GSAR" }, { "GSAR", 4, 1, &gfx3d.alphaTestRef},
{ &gfx3d.viewport.x, 4|SS_RLSB, "GSVX" }, { "GSVX", 4, 1, &gfx3d.viewport.x},
{ &gfx3d.viewport.y, 4|SS_RLSB, "GSVY" }, { "GSVY", 4, 1, &gfx3d.viewport.y},
{ &gfx3d.viewport.width, 4|SS_RLSB, "GSVW" }, { "GSVW", 4, 1, &gfx3d.viewport.width},
{ &gfx3d.viewport.height, 4|SS_RLSB, "GSVH" }, { "GSVH", 4, 1, &gfx3d.viewport.height},
{ gfx3d.clearColor, 4|SS_MULT(4), "GSCC" }, { "GSCC", 4, 4, gfx3d.clearColor},
{ &gfx3d.clearDepth , 4|SS_RLSB, "GSCD" }, { "GSCD", 4, 1, &gfx3d.clearDepth},
{ gfx3d.fogColor, 4|SS_MULT(4), "GSFC" }, { "GSFC", 4, 4, gfx3d.fogColor},
{ &gfx3d.fogOffset, 4|SS_RLSB, "GSFO" }, { "GSFO", 4, 1, &gfx3d.fogOffset},
{ gfx3d.rgbToonTable, 4|SS_MULT(32), "GSTT" }, { "GSTT", 4, 32, gfx3d.rgbToonTable},
{ 0 } { 0 }
}; };

View File

@ -51,120 +51,188 @@ static const char* magic = "DeSmuME SState\0";
SFORMAT SF_ARM7[]={ SFORMAT SF_ARM7[]={
{ &NDS_ARM7.instruction, 4|SS_RLSB, "7INS" }, { "7INS", 4, 1, &NDS_ARM7.instruction },
{ &NDS_ARM7.instruct_adr, 4|SS_RLSB, "7INA" }, { "7INA", 4, 1, &NDS_ARM7.instruct_adr },
{ &NDS_ARM7.next_instruction, 4|SS_RLSB, "7INN" }, { "7INN", 4, 1, &NDS_ARM7.next_instruction },
{ NDS_ARM7.R, 4|SS_MULT(16), "7REG" }, { "7REG", 4,16, NDS_ARM7.R },
{ &NDS_ARM7.CPSR, 4|SS_RLSB, "7CPS" }, { "7CPS", 4, 1, &NDS_ARM7.CPSR },
{ &NDS_ARM7.SPSR, 4|SS_RLSB, "7SPS" }, { "7SPS", 4, 1, &NDS_ARM7.SPSR },
{ &NDS_ARM7.R13_usr, 4|SS_RLSB, "7DUS" }, { "7DUS", 4, 1, &NDS_ARM7.R13_usr },
{ &NDS_ARM7.R14_usr, 4|SS_RLSB, "7EUS" }, { "7EUS", 4, 1, &NDS_ARM7.R14_usr },
{ &NDS_ARM7.R13_svc, 4|SS_RLSB, "7DSV" }, { "7DSV", 4, 1, &NDS_ARM7.R13_svc },
{ &NDS_ARM7.R14_svc, 4|SS_RLSB, "7ESV" }, { "7ESV", 4, 1, &NDS_ARM7.R14_svc },
{ &NDS_ARM7.R13_abt, 4|SS_RLSB, "7DAB" }, { "7DAB", 4, 1, &NDS_ARM7.R13_abt },
{ &NDS_ARM7.R14_abt, 4|SS_RLSB, "7EAB" }, { "7EAB", 4, 1, &NDS_ARM7.R14_abt },
{ &NDS_ARM7.R13_und, 4|SS_RLSB, "7DUN" }, { "7DUN", 4, 1, &NDS_ARM7.R13_und },
{ &NDS_ARM7.R14_und, 4|SS_RLSB, "7EUN" }, { "7EUN", 4, 1, &NDS_ARM7.R14_und },
{ &NDS_ARM7.R13_irq, 4|SS_RLSB, "7DIR" }, { "7DIR", 4, 1, &NDS_ARM7.R13_irq },
{ &NDS_ARM7.R14_irq, 4|SS_RLSB, "7EIR" }, { "7EIR", 4, 1, &NDS_ARM7.R14_irq },
{ &NDS_ARM7.R8_fiq, 4|SS_RLSB, "78FI" }, { "78FI", 4, 1, &NDS_ARM7.R8_fiq },
{ &NDS_ARM7.R9_fiq, 4|SS_RLSB, "79FI" }, { "79FI", 4, 1, &NDS_ARM7.R9_fiq },
{ &NDS_ARM7.R10_fiq, 4|SS_RLSB, "7AFI" }, { "7AFI", 4, 1, &NDS_ARM7.R10_fiq },
{ &NDS_ARM7.R11_fiq, 4|SS_RLSB, "7BFI" }, { "7BFI", 4, 1, &NDS_ARM7.R11_fiq },
{ &NDS_ARM7.R12_fiq, 4|SS_RLSB, "7CFI" }, { "7CFI", 4, 1, &NDS_ARM7.R12_fiq },
{ &NDS_ARM7.R13_fiq, 4|SS_RLSB, "7DFI" }, { "7DFI", 4, 1, &NDS_ARM7.R13_fiq },
{ &NDS_ARM7.R14_fiq, 4|SS_RLSB, "7EFI" }, { "7EFI", 4, 1, &NDS_ARM7.R14_fiq },
{ &NDS_ARM7.SPSR_svc, 4|SS_RLSB, "7SVC" }, { "7SVC", 4, 1, &NDS_ARM7.SPSR_svc },
{ &NDS_ARM7.SPSR_abt, 4|SS_RLSB, "7ABT" }, { "7ABT", 4, 1, &NDS_ARM7.SPSR_abt },
{ &NDS_ARM7.SPSR_und, 4|SS_RLSB, "7UND" }, { "7UND", 4, 1, &NDS_ARM7.SPSR_und },
{ &NDS_ARM7.SPSR_irq, 4|SS_RLSB, "7IRQ" }, { "7IRQ", 4, 1, &NDS_ARM7.SPSR_irq },
{ &NDS_ARM7.SPSR_fiq, 4|SS_RLSB, "7FIQ" }, { "7FIQ", 4, 1, &NDS_ARM7.SPSR_fiq },
{ &NDS_ARM7.intVector, 4|SS_RLSB, "7int" }, { "7int", 4, 1, &NDS_ARM7.intVector },
{ &NDS_ARM7.LDTBit, 1, "7LDT" }, { "7LDT", 1, 1, &NDS_ARM7.LDTBit },
{ &NDS_ARM7.waitIRQ, 4|SS_RLSB, "7Wai" }, { "7Wai", 4, 1, &NDS_ARM7.waitIRQ },
{ &NDS_ARM7.wIRQ, 4|SS_RLSB, "7wIR" }, { "7wIR", 4, 1, &NDS_ARM7.wIRQ, },
{ &NDS_ARM7.wirq, 4|SS_RLSB, "7wir" }, { "7wir", 4, 1, &NDS_ARM7.wirq, },
{ 0 } { 0 }
}; };
SFORMAT SF_ARM9[]={ SFORMAT SF_ARM9[]={
{ &NDS_ARM9.instruction, 4|SS_RLSB, "9INS" }, { "9INS", 4, 1, &NDS_ARM9.instruction},
{ &NDS_ARM9.instruct_adr, 4|SS_RLSB, "9INA" }, { "9INA", 4, 1, &NDS_ARM9.instruct_adr},
{ &NDS_ARM9.next_instruction, 4|SS_RLSB, "9INN" }, { "9INN", 4, 1, &NDS_ARM9.next_instruction},
{ NDS_ARM9.R, 4|SS_MULT(16), "9REG" }, { "9REG", 4,16, NDS_ARM9.R},
{ &NDS_ARM9.CPSR, 4|SS_RLSB, "9CPS" }, { "9CPS", 4, 1, &NDS_ARM9.CPSR},
{ &NDS_ARM9.SPSR, 4|SS_RLSB, "9SPS" }, { "9SPS", 4, 1, &NDS_ARM9.SPSR},
{ &NDS_ARM9.R13_usr, 4|SS_RLSB, "9DUS" }, { "9DUS", 4, 1, &NDS_ARM9.R13_usr},
{ &NDS_ARM9.R14_usr, 4|SS_RLSB, "9EUS" }, { "9EUS", 4, 1, &NDS_ARM9.R14_usr},
{ &NDS_ARM9.R13_svc, 4|SS_RLSB, "9DSV" }, { "9DSV", 4, 1, &NDS_ARM9.R13_svc},
{ &NDS_ARM9.R14_svc, 4|SS_RLSB, "9ESV" }, { "9ESV", 4, 1, &NDS_ARM9.R14_svc},
{ &NDS_ARM9.R13_abt, 4|SS_RLSB, "9DAB" }, { "9DAB", 4, 1, &NDS_ARM9.R13_abt},
{ &NDS_ARM9.R14_abt, 4|SS_RLSB, "9EAB" }, { "9EAB", 4, 1, &NDS_ARM9.R14_abt},
{ &NDS_ARM9.R13_und, 4|SS_RLSB, "9DUN" }, { "9DUN", 4, 1, &NDS_ARM9.R13_und},
{ &NDS_ARM9.R14_und, 4|SS_RLSB, "9EUN" }, { "9EUN", 4, 1, &NDS_ARM9.R14_und},
{ &NDS_ARM9.R13_irq, 4|SS_RLSB, "9DIR" }, { "9DIR", 4, 1, &NDS_ARM9.R13_irq},
{ &NDS_ARM9.R14_irq, 4|SS_RLSB, "9EIR" }, { "9EIR", 4, 1, &NDS_ARM9.R14_irq},
{ &NDS_ARM9.R8_fiq, 4|SS_RLSB, "98FI" }, { "98FI", 4, 1, &NDS_ARM9.R8_fiq},
{ &NDS_ARM9.R9_fiq, 4|SS_RLSB, "99FI" }, { "99FI", 4, 1, &NDS_ARM9.R9_fiq},
{ &NDS_ARM9.R10_fiq, 4|SS_RLSB, "9AFI" }, { "9AFI", 4, 1, &NDS_ARM9.R10_fiq},
{ &NDS_ARM9.R11_fiq, 4|SS_RLSB, "9BFI" }, { "9BFI", 4, 1, &NDS_ARM9.R11_fiq},
{ &NDS_ARM9.R12_fiq, 4|SS_RLSB, "9CFI" }, { "9CFI", 4, 1, &NDS_ARM9.R12_fiq},
{ &NDS_ARM9.R13_fiq, 4|SS_RLSB, "9DFI" }, { "9DFI", 4, 1, &NDS_ARM9.R13_fiq},
{ &NDS_ARM9.R14_fiq, 4|SS_RLSB, "9EFI" }, { "9EFI", 4, 1, &NDS_ARM9.R14_fiq},
{ &NDS_ARM9.SPSR_svc, 4|SS_RLSB, "9SVC" }, { "9SVC", 4, 1, &NDS_ARM9.SPSR_svc},
{ &NDS_ARM9.SPSR_abt, 4|SS_RLSB, "9ABT" }, { "9ABT", 4, 1, &NDS_ARM9.SPSR_abt},
{ &NDS_ARM9.SPSR_und, 4|SS_RLSB, "9UND" }, { "9UND", 4, 1, &NDS_ARM9.SPSR_und},
{ &NDS_ARM9.SPSR_irq, 4|SS_RLSB, "9IRQ" }, { "9IRQ", 4, 1, &NDS_ARM9.SPSR_irq},
{ &NDS_ARM9.SPSR_fiq, 4|SS_RLSB, "9FIQ" }, { "9FIQ", 4, 1, &NDS_ARM9.SPSR_fiq},
{ &NDS_ARM9.intVector, 4|SS_RLSB, "9int" }, { "9int", 4, 1, &NDS_ARM9.intVector},
{ &NDS_ARM9.LDTBit, 1, "9LDT" }, { "9LDT", 1, 1, &NDS_ARM9.LDTBit},
{ &NDS_ARM9.waitIRQ, 4|SS_RLSB, "9Wai" }, { "9Wai", 4, 1, &NDS_ARM9.waitIRQ},
{ &NDS_ARM9.wIRQ, 4|SS_RLSB, "9wIR" }, { "9wIR", 4, 1, &NDS_ARM9.wIRQ},
{ &NDS_ARM9.wirq, 4|SS_RLSB, "9wir" }, { "9wir", 4, 1, &NDS_ARM9.wirq},
{ 0 } { 0 }
}; };
SFORMAT SF_MEM[]={ SFORMAT SF_MEM[]={
{ ARM9Mem.ARM9_ITCM, 0x8000, "ITCM" }, { "ITCM", 1, 0x8000, ARM9Mem.ARM9_ITCM},
{ ARM9Mem.ARM9_DTCM, 0x4000, "DTCM" }, { "DTCM", 1, 0x4000, ARM9Mem.ARM9_DTCM},
{ ARM9Mem.MAIN_MEM, 0x400000, "WRAM" }, { "WRAM", 1, 0x400000, ARM9Mem.MAIN_MEM},
//NOTE - this is not as large as the allocated memory. //NOTE - this is not as large as the allocated memory.
//the memory is overlarge due to the way our memory map system is setup //the memory is overlarge due to the way our memory map system is setup
//but there are actually no more registers than this //but there are actually no more registers than this
{ ARM9Mem.ARM9_REG, 0x2000, "9REG" }, { "9REG", 1, 0x2000, ARM9Mem.ARM9_REG},
{ ARM9Mem.ARM9_VMEM, 0x800, "VMEM" }, { "VMEM", 1, 0x800, ARM9Mem.ARM9_VMEM},
{ ARM9Mem.ARM9_OAM, 0x800, "OAMS" }, { "OAMS", 1, 0x800, ARM9Mem.ARM9_OAM},
{ ARM9Mem.ARM9_ABG, 0x80000, "ABGM" }, { "ABGM", 1, 0x80000, ARM9Mem.ARM9_ABG},
{ ARM9Mem.ARM9_BBG, 0x20000, "BBGM" }, { "BBGM", 1, 0x20000, ARM9Mem.ARM9_BBG},
{ ARM9Mem.ARM9_AOBJ, 0x40000, "AOBJ" }, { "AOBJ", 1, 0x40000, ARM9Mem.ARM9_AOBJ},
{ ARM9Mem.ARM9_BOBJ, 0x20000, "BOBJ" }, { "BOBJ", 1, 0x20000, ARM9Mem.ARM9_BOBJ},
{ ARM9Mem.ARM9_LCD, 0xA4000, "LCDM" }, { "LCDM", 1, 0xA4000, ARM9Mem.ARM9_LCD},
{ MMU.ARM7_ERAM, 0x10000, "ERAM" },
{ MMU.ARM7_REG, 0x10000, "7REG" },
{ MMU.ARM7_WIRAM, 0x10000, "WIRA" },
{ MMU.SWIRAM, 0x8000, "SWIR" },
{ MMU.CART_RAM, SRAM_SIZE, "SRAM" },
{ 0 } { 0 }
}; };
SFORMAT SF_NDS[]={ SFORMAT SF_NDS[]={
{ &nds.ARM9Cycle, 4|SS_RLSB, "_9CY" }, { "_9CY", 4, 1, &nds.ARM9Cycle},
{ &nds.ARM7Cycle, 4|SS_RLSB, "_7CY" }, { "_7CY", 4, 1, &nds.ARM7Cycle},
{ &nds.cycles, 4|SS_RLSB, "_CYC" }, { "_CYC", 4, 1, &nds.cycles},
{ nds.timerCycle, 4|SS_MULT(8), "_TCY" }, { "_TCY", 4, 8, nds.timerCycle},
{ nds.timerOver, 4|SS_MULT(8), "_TOV" }, { "_TOV", 4, 8, nds.timerOver},
{ &nds.nextHBlank, 4|SS_RLSB, "_NHB" }, { "_NHB", 4, 1, &nds.nextHBlank},
{ &nds.VCount, 4|SS_RLSB, "_VCT" }, { "_VCT", 4, 1, &nds.VCount},
{ &nds.old, 4|SS_RLSB, "_OLD" }, { "_OLD", 4, 1, &nds.old},
{ &nds.diff, 4|SS_RLSB, "_DIF" }, { "_DIF", 4, 1, &nds.diff},
{ &nds.lignerendu, 4|SS_RLSB, "_LIG" }, { "_LIG", 4, 1, &nds.lignerendu},
{ &nds.touchX, 2|SS_RLSB, "_TPX" }, { "_TPX", 2, 1, &nds.touchX},
{ &nds.touchY, 2|SS_RLSB, "_TPY" }, { "_TPY", 2, 1, &nds.touchY},
{ 0 } { 0 }
}; };
SFORMAT SF_MMU[]={
{ "M7BI", 1, 0x4000, MMU.ARM7_BIOS},
{ "M7ER", 1, 0x10000, MMU.ARM7_ERAM},
{ "M7RG", 1, 0x10000, MMU.ARM7_REG},
{ "M7WI", 1, 0x10000, MMU.ARM7_WIRAM},
{ "MVRM", 1, 9, MMU.vram_mode},
{ "MSWI", 1, 0x8000, MMU.SWIRAM},
{ "MCRA", 1, 0x10000, MMU.CART_RAM},
{ "M9RW", 1, 1, &MMU.ARM9_RW_MODE},
{ "MDTC", 4, 1, &MMU.DTCMRegion},
{ "MITC", 4, 1, &MMU.ITCMRegion},
{ "MTIM", 2, 8, MMU.timer},
{ "MTMO", 4, 8, MMU.timerMODE},
{ "MTON", 4, 8, MMU.timerON},
{ "MTRN", 4, 8, MMU.timerRUN},
{ "MTRL", 2, 8, MMU.timerReload},
{ "MIME", 4, 2, MMU.reg_IME},
{ "MIE_", 4, 2, MMU.reg_IE},
{ "MIF_", 4, 2, MMU.reg_IF},
{ "MDST", 4, 8, MMU.DMAStartTime},
{ "MDCY", 4, 8, MMU.DMACycle},
{ "MDCR", 4, 8, MMU.DMACrt},
{ "MDMA", 4, 8, MMU.DMAing},
//begin memory chips
//we are skipping the firmware, because we really don't want to save the firmware to the savestate
//but, we will need to think about the philosophy of this.
//should we perhaps hash the current firmware and save it, so that we can match it against the loader's firmware?
{ "BUCO", 1, 1, &MMU.bupmem.com},
{ "BUAD", 4, 1, &MMU.bupmem.addr},
{ "BUAS", 1, 1, &MMU.bupmem.addr_shift},
{ "BUAZ", 1, 1, &MMU.bupmem.addr_size},
{ "BUWE", 4, 1, &MMU.bupmem.write_enable},
//writeable_buffer ???
//end memory chips
{ "MC0A", 4, 1, &MMU.dscard[0].address},
{ "MC0T", 4, 1, &MMU.dscard[0].transfer_count},
{ "MC1A", 4, 1, &MMU.dscard[1].address},
{ "MC1T", 4, 1, &MMU.dscard[1].transfer_count},
{ "MCHT", 4, 1, &MMU.CheckTimers},
{ "MCHD", 4, 1, &MMU.CheckDMAs},
{ 0 }
};
void mmu_savestate(std::ostream* os)
{
//version
write32le(0,os);
write32le(MMU.bupmem.size,os);
os->write((char*)MMU.bupmem.data,MMU.bupmem.size);
}
bool mmu_loadstate(std::istream* is)
{
//read version
int version;
if(read32le(&version,is) != 1) return false;
if(version != 0) return false;
u32 bupmem_size;
if(read32le(&bupmem_size,is) != 1) return false;
if(bupmem_size != MMU.bupmem.size) return false; //mismatch between current initialized and saved size
is->read((char*)MMU.bupmem.data,bupmem_size);
if(is->fail()) return false;
return true;
}
/* Format time and convert to string */ /* Format time and convert to string */
char * format_time(time_t cal_time) char * format_time(time_t cal_time)
{ {
@ -281,27 +349,28 @@ int sram_save (const char *file_name) {
} }
static SFORMAT *CheckS(SFORMAT *sf, u32 tsize, char *desc) static SFORMAT *CheckS(SFORMAT *sf, u32 size, u32 count, char *desc)
{ {
while(sf->v) while(sf->v)
{ {
if(sf->s==~0) // Link to another SFORMAT structure. //NOT SUPPORTED RIGHT NOW
{ //if(sf->size==~0) // Link to another SFORMAT structure.
SFORMAT *tmp; //{
if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) )) // SFORMAT *tmp;
return(tmp); // if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) ))
sf++; // return(tmp);
continue; // sf++;
} // continue;
//}
if(!memcmp(desc,sf->desc,4)) if(!memcmp(desc,sf->desc,4))
{ {
if(tsize!=(sf->s)) if(sf->size != size || sf->count != count)
return(0); return 0;
return(sf); return sf;
} }
sf++; sf++;
} }
return(0); return 0;
} }
@ -312,34 +381,31 @@ static bool ReadStateChunk(std::istream* is, SFORMAT *sf, int size)
while(is->tellg()<temp+size) while(is->tellg()<temp+size)
{ {
u32 tsize; u32 size, count;
char toa[4]; char toa[4];
is->read(toa,4); is->read(toa,4);
if(is->fail()) if(is->fail())
return false; return false;
read32le(&tsize,is); if(!read32le(&size,is)) return false;
int count = SS_UNMULT(tsize); if(!read32le(&count,is)) return false;
int size = tsize & ~SS_FLAGS;
bool rlsb = (count!=0);
if((tmp=CheckS(sf,tsize,toa))) if((tmp=CheckS(sf,size,count,toa)))
{ {
if(size == 1) {
//special case: read a huge byte array
if(count == 0) count=1; is->read((char *)tmp->v,count);
} else {
for(int i=0;i<count;i++) { for(int i=0;i<count;i++)
{
if(tmp->s&SS_INDIRECT)
is->read(*(char **)tmp->v,size);
else
is->read((char *)tmp->v + i*size,size); is->read((char *)tmp->v + i*size,size);
#ifndef LOCAL_LE #ifndef LOCAL_LE
if(rlsb) if(rlsb)
FlipByteOrder((u8*)tmp->v + i*size,size); FlipByteOrder((u8*)tmp->v + i*size,size);
#endif #endif
}
} }
} }
else else
@ -356,50 +422,49 @@ static int SubWrite(std::ostream* os, SFORMAT *sf)
while(sf->v) while(sf->v)
{ {
if(sf->s==~0) //Link to another struct //not supported right now
{ //if(sf->size==~0) //Link to another struct
uint32 tmp; //{
// uint32 tmp;
if(!(tmp=SubWrite(os,(SFORMAT *)sf->v))) // if(!(tmp=SubWrite(os,(SFORMAT *)sf->v)))
return(0); // return(0);
acc+=tmp; // acc+=tmp;
sf++; // sf++;
continue; // continue;
} //}
int count = SS_UNMULT(sf->s); int count = sf->count;
int size = sf->s & ~SS_FLAGS; int size = sf->size;
bool rlsb = (count!=0);
acc+=8; //Description + size acc+=12; //Description + size + count
if(count==0) count=1;
acc += count * size; acc += count * size;
if(os) //Are we writing or calculating the size of this block? if(os) //Are we writing or calculating the size of this block?
{ {
os->write(sf->desc,4); os->write(sf->desc,4);
write32le(sf->s,os); write32le(sf->size,os);
write32le(sf->count,os);
for(int i=0;i<count;i++) { if(size == 1) {
//special case: write a huge byte array
os->write((char *)sf->v,count);
} else {
for(int i=0;i<count;i++) {
#ifndef LOCAL_LE #ifndef LOCAL_LE
if(rlsb)
FlipByteOrder((u8*)sf->v,sf->s&(~SS_FLAGS)); FlipByteOrder((u8*)sf->v,sf->s&(~SS_FLAGS));
#endif #endif
if(sf->s&SS_INDIRECT)
os->write(*(char **)sf->v,size);
else
os->write((char*)sf->v + i*size,size); os->write((char*)sf->v + i*size,size);
//Now restore the original byte order. //Now restore the original byte order.
#ifndef LOCAL_LE #ifndef LOCAL_LE
if(rlsb) if(rlsb)
FlipByteOrder((u8*)sf->v,sf->s&(~SS_FLAGS)); FlipByteOrder((u8*)sf->v,sf->s&(~SS_FLAGS));
#endif #endif
}
} }
} }
sf++; sf++;
@ -508,10 +573,12 @@ static void writechunks(std::ostream* os) {
savestate_WriteChunk(os,2,SF_ARM7); savestate_WriteChunk(os,2,SF_ARM7);
savestate_WriteChunk(os,3,SF_MEM); savestate_WriteChunk(os,3,SF_MEM);
savestate_WriteChunk(os,4,SF_NDS); savestate_WriteChunk(os,4,SF_NDS);
savestate_WriteChunk(os,5,gpu_savestate); 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,7,spu_savestate);
savestate_WriteChunk(os,60,SF_GFX3D); savestate_WriteChunk(os,80,SF_GFX3D);
savestate_WriteChunk(os,61,gfx3d_savestate); savestate_WriteChunk(os,81,gfx3d_savestate);
savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0); savestate_WriteChunk(os,0xFFFFFFFF,(SFORMAT*)0);
} }
@ -531,10 +598,12 @@ static bool ReadStateChunks(std::istream* is, s32 totalsize)
case 2: if(!ReadStateChunk(is,SF_ARM7,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 3: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break;
case 4: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break; case 4: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break;
case 5: if(!gpu_loadstate(is)) 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 7: if(!spu_loadstate(is)) ret=false; break;
case 60: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break; case 80: if(!ReadStateChunk(is,SF_GFX3D,size)) ret=false; break;
case 61: if(!gfx3d_loadstate(is)) ret=false; break; case 81: if(!gfx3d_loadstate(is)) ret=false; break;
default: default:
ret=false; ret=false;
break; break;

View File

@ -36,32 +36,19 @@ typedef struct
struct SFORMAT struct SFORMAT
{ {
//a void* to the data or a void** to the data
void *v;
//size, plus flags
uint32 s;
//a string description of the element //a string description of the element
char *desc; char *desc;
//the size of each element
u32 size;
//the number of each element
u32 count;
//a void* to the data or a void** to the data
void *v;
}; };
//X multiple multibyte elements
#define SS_MULT(X) (X<<24)
//indicates that the value is a multibyte integer that needs to be put in the correct byte order
//this is the same as SS_MULT(1)
#define SS_RLSB SS_MULT(1)
//all flags together so that we can mask them out and get the size
#define SS_FLAGS (SS_INDIRECT|SS_MULT(127))
//extract the multiplier
#define SS_UNMULT(X) ((X>>24)&0x7F)
extern savestates_t savestates[NB_STATES]; extern savestates_t savestates[NB_STATES];
void clear_savestates(); void clear_savestates();