disp3dcnt fix (fixes missing zx advent sprites, and I don't know what else) (possibly incomplete though),

32-bit poly+vert-count read fix,
disassembler stack corruption fix,
savestate fix with wifi sequencer,
made wifi random not use rand() since that could potentially cause desyncs,
did some probably-minor savestate optimizations
This commit is contained in:
nitsuja 2009-08-09 22:31:59 +00:00
parent 5e3cb11c83
commit c4be07bc87
6 changed files with 88 additions and 33 deletions

View File

@ -265,7 +265,7 @@ const char MSR_FIELD[16][5] = {
}\
}\
}\
lreg[strlen(lreg)-1]='\0';
if(*lreg) lreg[strlen(lreg)-1]='\0';
static char * OP_UND(u32 adr, u32 i, char * txt)
{

View File

@ -1702,6 +1702,7 @@ void FASTCALL _MMU_ARM9_write08(u32 adr, u8 val)
case REG_DISPA_DISP3DCNT+1:
{
u32 &disp3dcnt = MainScreen.gpu->dispx_st->dispA_DISP3DCNT.val;
val = (val & ~0x30) | (~val & ((disp3dcnt>>8) & 0x30)); // bits 12,13 are ack bits
disp3dcnt = (disp3dcnt&0x00FF) | (val<<8);
gfx3d_Control(disp3dcnt);
break;
@ -1931,7 +1932,9 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
case REG_DISPA_DISP3DCNT:
{
MainScreen.gpu->dispx_st->dispA_DISP3DCNT.val = val;
u32 &disp3dcnt = MainScreen.gpu->dispx_st->dispA_DISP3DCNT.val;
val = (val & ~0x3000) | (~val & (disp3dcnt & 0x3000)); // bits 12,13 are ack bits
disp3dcnt = val;
gfx3d_Control(val);
break;
}
@ -2896,7 +2899,7 @@ u32 FASTCALL _MMU_ARM9_read32(u32 adr)
case 0x4000604:
{
return (gfx3d_GetNumPolys()) & ((gfx3d_GetNumVertex()) << 16);
return (gfx3d_GetNumPolys()) | ((gfx3d_GetNumVertex()) << 16);
//LOG ("read32 - RAM_COUNT -> 0x%X", ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][(adr>>20)&0xFF]))[(adr&MMU.MMU_MASK[ARMCPU_ARM9][(adr>>20)&0xFF])>>2]);
}

View File

@ -1766,6 +1766,7 @@ struct Sequencer
divider.save(os);
sqrtunit.save(os);
gxfifo.save(os);
wifi.save(os);
#define SAVE(I,X,Y) I##_##X##_##Y .save(os);
SAVE(timer,0,0); SAVE(timer,0,1); SAVE(timer,0,2); SAVE(timer,0,3);
SAVE(timer,1,0); SAVE(timer,1,1); SAVE(timer,1,2); SAVE(timer,1,3);
@ -1774,7 +1775,7 @@ struct Sequencer
#undef SAVE
}
bool load(std::istream* is)
bool load(std::istream* is, int version)
{
if(read64le(&nds_timer,is) != 1) return false;
if(read64le(&nds_arm9_timer,is) != 1) return false;
@ -1783,6 +1784,7 @@ struct Sequencer
if(!divider.load(is)) return false;
if(!sqrtunit.load(is)) return false;
if(!gxfifo.load(is)) return false;
if(version >= 1) if(!wifi.load(is)) return false;
#define LOAD(I,X,Y) if(!I##_##X##_##Y .load(is)) return false;
LOAD(timer,0,0); LOAD(timer,0,1); LOAD(timer,0,2); LOAD(timer,0,3);
LOAD(timer,1,0); LOAD(timer,1,1); LOAD(timer,1,2); LOAD(timer,1,3);
@ -2082,7 +2084,7 @@ void execHardware_interrupts();
void nds_savestate(std::ostream* os)
{
//version
write32le(0,os);
write32le(1,os);
sequencer.save(os);
}
@ -2093,9 +2095,9 @@ bool nds_loadstate(std::istream* is, int size)
int version;
if(read32le(&version,is) != 1) return false;
if(version != 0) return false;
if(version > 1) return false;
return sequencer.load(is);
return sequencer.load(is, version);
}
//#define LOG_ARM9

View File

@ -2354,7 +2354,7 @@ void gfx3d_GetLineData15bpp(int line, u16** dst)
//consider building a little state structure that looks exactly like this describes
SFORMAT SF_GFX3D[]={
//{ "GCTL", 4, 1, &control}, //this gets regenerated by the code i hate which regenerates gpu regs
{ "GCTL", 4, 1, &control}, // no longer regenerated indirectly, see comment in loadstate()
{ "GPAT", 4, 1, &polyAttr},
{ "GPAP", 4, 1, &polyAttrPending},
{ "GINB", 4, 1, &inBegin},

View File

@ -690,8 +690,11 @@ int sram_save (const char *file_name) {
}
static const SFORMAT *CheckS(const SFORMAT *sf, u32 size, u32 count, char *desc)
// note: guessSF is so we don't have to do a linear search through the SFORMAT array every time
// in the (most common) case that we already know where the next entry is.
static const SFORMAT *CheckS(const SFORMAT *guessSF, const SFORMAT *firstSF, u32 size, u32 count, char *desc)
{
const SFORMAT *sf = guessSF ? guessSF : firstSF;
while(sf->v)
{
//NOT SUPPORTED RIGHT NOW
@ -709,7 +712,17 @@ static const SFORMAT *CheckS(const SFORMAT *sf, u32 size, u32 count, char *desc)
return 0;
return sf;
}
sf++;
// failed to find it, have to keep iterating
if(guessSF)
{
sf = firstSF;
guessSF = NULL;
}
else
{
sf++;
}
}
return 0;
}
@ -717,7 +730,8 @@ static const SFORMAT *CheckS(const SFORMAT *sf, u32 size, u32 count, char *desc)
static bool ReadStateChunk(std::istream* is, const SFORMAT *sf, int size)
{
const SFORMAT *tmp;
const SFORMAT *tmp = NULL;
const SFORMAT *guessSF = NULL;
int temp = is->tellg();
while(is->tellg()<temp+size)
@ -732,8 +746,12 @@ static bool ReadStateChunk(std::istream* is, const SFORMAT *sf, int size)
if(!read32le(&sz,is)) return false;
if(!read32le(&count,is)) return false;
if((tmp=CheckS(sf,sz,count,toa)))
if((tmp=CheckS(guessSF,sf,sz,count,toa)))
{
#ifdef LOCAL_LE
// no need to ever loop one at a time if not flipping byte order
is->read((char *)tmp->v,sz*count);
#else
if(sz == 1) {
//special case: read a huge byte array
is->read((char *)tmp->v,count);
@ -741,15 +759,17 @@ static bool ReadStateChunk(std::istream* is, const SFORMAT *sf, int size)
for(unsigned int i=0;i<count;i++)
{
is->read((char *)tmp->v + i*sz,sz);
#ifndef LOCAL_LE
FlipByteOrder((u8*)tmp->v + i*sz,sz);
#endif
FlipByteOrder((u8*)tmp->v + i*sz,sz);
}
}
#endif
guessSF = tmp + 1;
}
else
{
is->seekg(sz*count,std::ios::cur);
guessSF = NULL;
}
} // while(...)
return true;
}
@ -799,24 +819,22 @@ static int SubWrite(std::ostream* os, const SFORMAT *sf)
write32le(sf->size,os);
write32le(sf->count,os);
if(size == 1) {
#ifdef LOCAL_LE
// no need to ever loop one at a time if not flipping byte order
os->write((char *)sf->v,size*count);
#else
if(sz == 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
FlipByteOrder((u8*)sf->v + i*size, size);
#endif
FlipByteOrder((u8*)sf->v + i*size, size);
os->write((char*)sf->v + i*size,size);
//Now restore the original byte order.
#ifndef LOCAL_LE
FlipByteOrder((u8*)sf->v + i*size, size);
#endif
FlipByteOrder((u8*)sf->v + i*size, size);
}
}
#endif
}
sf++;
}
@ -838,11 +856,32 @@ static int savestate_WriteChunk(std::ostream* os, int type, const SFORMAT *sf)
return (bsize+8);
}
//TODO TODO TODO TODO TODO TODO TODO
// - this is retarded. why not write placeholders for size and then write directly to the stream
//and then go back and fill them in
static void savestate_WriteChunk(std::ostream* os, int type, void (*saveproc)(std::ostream* os))
{
u32 pos1 = os->tellp();
//write the type, size(placeholder), and data
write32le(type,os);
write32le(0,os); // <-- temporary write, re-written later
saveproc(os);
//get the size
u32 pos2 = os->tellp();
assert(pos2 != (u32)-1); // if this assert fails, saveproc did something bad
u32 size = (pos2 - pos1) - (2 * sizeof(u32));
//fill in the actual size
os->seekp(pos1 + sizeof(u32));
write32le(size,os);
os->seekp(pos2);
/*
// old version of this function,
// for reference in case the new one above starts misbehaving somehow:
// - this is retarded. why not write placeholders for size and then write directly to the stream
//and then go back and fill them in
//get the size
memorystream mstemp;
saveproc(&mstemp);
@ -853,6 +892,7 @@ static void savestate_WriteChunk(std::ostream* os, int type, void (*saveproc)(st
write32le(type,os);
write32le(size,os);
os->write(mstemp.buf(),size);
*/
}
static void writechunks(std::ostream* os);
@ -996,7 +1036,8 @@ static bool ReadStateChunks(std::istream* is, s32 totalsize)
ret=false;
break;
}
if(!ret) return false;
if(!ret)
return false;
}
done:
@ -1020,13 +1061,13 @@ static void loadstate()
//_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i));
// for (int i = REG_BASE_DISPB; i<=REG_BASE_DISPB + 0x7F; i+=2)
//_MMU_write16<ARMCPU_ARM9>(i, _MMU_read16<ARMCPU_ARM9>(i));
static const u8 mainRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x60,0x64,0x66,0x6c};
static const u8 mainRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x64,0x66,0x6c};
static const u8 subRegenAddr[] = {0x00,0x02,0x08,0x0a,0x0c,0x0e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x50,0x52,0x54,0x6c};
for(u32 i=0;i<ARRAY_SIZE(mainRegenAddr);i++)
_MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPA+mainRegenAddr[i]));
for(u32 i=0;i<ARRAY_SIZE(subRegenAddr);i++)
_MMU_write16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i], _MMU_read16<ARMCPU_ARM9>(REG_BASE_DISPB+subRegenAddr[i]));
// no need to restore 0x60 since control and MMU.ARM9_REG are both in the savestates, and restoring it could mess up the ack bits anyway
SetupMMU(nds.debugConsole);
}

View File

@ -1062,7 +1062,16 @@ u16 WIFI_read16(u32 address)
return WIFI_getBB_DATA() ;
case REG_WIFI_RANDOM:
/* FIXME: random generator */
return (rand() & 0x7FF);
// return (rand() & 0x7FF); // disabled (no wonder there were desyncs...)
// probably not right, but it's better than using the unsaved and shared rand().
// at the very least, rand() shouldn't be used when movieMode is active.
{
u16 returnValue = wifiMac.randomSeed;
wifiMac.randomSeed = (wifiMac.randomSeed & 1) ^ (((wifiMac.randomSeed << 1) & 0x7FE) | ((wifiMac.randomSeed >> 10) & 0x1));
return returnValue;
}
return 0 ;
case REG_WIFI_MAC0:
case REG_WIFI_MAC1: