diff options
-rw-r--r-- | src/ARM.cpp | 31 | ||||
-rw-r--r-- | src/ARM.h | 19 | ||||
-rw-r--r-- | src/CP15.cpp | 12 | ||||
-rw-r--r-- | src/CP15.h | 5 | ||||
-rw-r--r-- | src/GPU3D_Soft.cpp | 22 | ||||
-rw-r--r-- | src/NDS.cpp | 79 | ||||
-rw-r--r-- | src/NDS.h | 11 |
7 files changed, 165 insertions, 14 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp index 2368a1b..d71d0e1 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -157,6 +157,8 @@ void ARM::Reset() ExceptionBase = Num ? 0x00000000 : 0xFFFF0000; + CodeMem.Mem = NULL; + // zorp JumpTo(ExceptionBase); } @@ -180,6 +182,24 @@ void ARM::DoSavestate(Savestate* file) file->VarArray(NextInstr, 2*sizeof(u32)); file->Var32(&ExceptionBase); + + if (!file->Saving) + SetupCodeMem(R[15]); // should fix it +} + +void ARM::SetupCodeMem(u32 addr) +{ + if (!Num) + { + if (CP15::GetCodeMemRegion(addr, &CodeMem)) + return; + + NDS::ARM9GetMemRegion(addr, false, &CodeMem); + } + else + { + NDS::ARM7GetMemRegion(addr, false, &CodeMem); + } } void ARM::JumpTo(u32 addr, bool restorecpsr) @@ -196,20 +216,31 @@ void ARM::JumpTo(u32 addr, bool restorecpsr) //if (addr == 0x0201764C) printf("capture test %d: R1=%08X\n", R[6], R[1]); //if (addr == 0x020175D8) printf("capture test %d: res=%08X\n", R[6], R[0]); + u32 oldregion = R[15] >> 23; + u32 newregion = addr >> 23; +//if(!Num)printf("ARM%c branch from %08X to %08X. %03X->%03X\n", Num?'7':'9', R[15], addr, oldregion, newregion); if (addr & 0x1) { addr &= ~0x1; R[15] = addr+2; + + if (newregion != oldregion) SetupCodeMem(addr); + NextInstr[0] = CodeRead16(addr); NextInstr[1] = CodeRead16(addr+2); + CPSR |= 0x20; } else { addr &= ~0x3; R[15] = addr+4; + + if (newregion != oldregion) SetupCodeMem(addr); + NextInstr[0] = CodeRead32(addr); NextInstr[1] = CodeRead32(addr+4); + CPSR &= ~0x20; } } @@ -93,11 +93,19 @@ public: void TriggerIRQ(); + void SetupCodeMem(u32 addr); + u16 CodeRead16(u32 addr) { + Cycles += Waitstates[0][(addr>>24)&0xF]; + + if (CodeMem.Mem) return *(u16*)&CodeMem.Mem[addr & CodeMem.Mask]; + u16 val; // TODO eventually: on ARM9, THUMB opcodes are prefetched with 32bit reads + // probably not worth going through the trouble. we can probably just simulate + // the timing quirks resulting from this. or not. if (!Num) { if (!CP15::HandleCodeRead16(addr, &val)) @@ -106,12 +114,15 @@ public: else val = NDS::ARM7Read16(addr); - Cycles += Waitstates[0][(addr>>24)&0xF]; return val; } u32 CodeRead32(u32 addr) { + Cycles += Waitstates[1][(addr>>24)&0xF]; + + if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask]; + u32 val; if (!Num) { @@ -121,7 +132,6 @@ public: else val = NDS::ARM7Read32(addr); - Cycles += Waitstates[1][(addr>>24)&0xF]; return val; } @@ -220,6 +230,7 @@ public: // waitstates: // 0=code16 1=code32 2=data16 3=data32 // TODO eventually: nonsequential waitstates + // TODO NOT MAKE THIS A FUCKING GROSS HACK!!!!!! s32 Waitstates[4][16]; s32 Cycles; @@ -238,9 +249,9 @@ public: u32 ExceptionBase; - static u32 ConditionTable[16]; + NDS::MemRegion CodeMem; - u32 debug; + static u32 ConditionTable[16]; }; namespace ARMInterpreter diff --git a/src/CP15.cpp b/src/CP15.cpp index e3f0bae..229c560 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -316,4 +316,16 @@ bool HandleDataWrite32(u32 addr, u32 val, u32 forceuser) return false; } +bool GetCodeMemRegion(u32 addr, NDS::MemRegion* region) +{ + if (addr < ITCMSize) + { + region->Mem = ITCM; + region->Mask = 0x7FFF; + return true; + } + + return false; +} + } @@ -22,6 +22,9 @@ namespace CP15 { +extern u8 ITCM[0x8000]; +extern u32 ITCMSize; + void Reset(); void DoSavestate(Savestate* file); @@ -41,6 +44,8 @@ bool HandleDataWrite8(u32 addr, u8 val, u32 forceuser=0); bool HandleDataWrite16(u32 addr, u16 val, u32 forceuser=0); bool HandleDataWrite32(u32 addr, u32 val, u32 forceuser=0); +bool GetCodeMemRegion(u32 addr, NDS::MemRegion* region); + } #endif diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index bb48c97..811d5f6 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -1213,7 +1213,9 @@ void RenderShadowMaskScanline(RendererPolygon* rp, s32 y) // part 1: left edge edge = yedge | 0x1; - xlimit = xstart+l_edgelen; if (xlimit > 256) xlimit = 256; + xlimit = xstart+l_edgelen; + if (xlimit > xend+1) xlimit = xend+1; + if (xlimit > 256) xlimit = 256; for (; x < xlimit; x++) { @@ -1241,7 +1243,9 @@ void RenderShadowMaskScanline(RendererPolygon* rp, s32 y) // part 2: polygon inside edge = yedge; - xlimit = xend-r_edgelen+1; if (xlimit > 256) xlimit = 256; + xlimit = xend-r_edgelen+1; + if (xlimit > xend+1) xlimit = xend+1; + if (xlimit > 256) xlimit = 256; if (wireframe && !edge) x = xlimit; else for (; x < xlimit; x++) { @@ -1265,7 +1269,8 @@ void RenderShadowMaskScanline(RendererPolygon* rp, s32 y) // part 3: right edge edge = yedge | 0x2; - xlimit = xend+1; if (xlimit > 256) xlimit = 256; + xlimit = xend+1; + if (xlimit > 256) xlimit = 256; for (; x < xlimit; x++) { @@ -1436,7 +1441,9 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y) // part 1: left edge edge = yedge | 0x1; - xlimit = xstart+l_edgelen; if (xlimit > 256) xlimit = 256; + xlimit = xstart+l_edgelen; + if (xlimit > xend+1) xlimit = xend+1; + if (xlimit > 256) xlimit = 256; if (l_edgecov & (1<<31)) { xcov = (l_edgecov >> 12) & 0x3FF; @@ -1535,7 +1542,9 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y) // part 2: polygon inside edge = yedge; - xlimit = xend-r_edgelen+1; if (xlimit > 256) xlimit = 256; + xlimit = xend-r_edgelen+1; + if (xlimit > xend+1) xlimit = xend+1; + if (xlimit > 256) xlimit = 256; if (wireframe && !edge) x = xlimit; else for (; x < xlimit; x++) { @@ -1603,7 +1612,8 @@ void RenderPolygonScanline(RendererPolygon* rp, s32 y) // part 3: right edge edge = yedge | 0x2; - xlimit = xend+1; if (xlimit > 256) xlimit = 256; + xlimit = xend+1; + if (xlimit > 256) xlimit = 256; if (r_edgecov & (1<<31)) { xcov = (r_edgecov >> 12) & 0x3FF; diff --git a/src/NDS.cpp b/src/NDS.cpp index 40f0c2d..77810ee 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -36,10 +36,6 @@ namespace NDS { -// TODO LIST -// * stick all the variables in a big structure? -// would make it easier to deal with savestates - ARM* ARM9; ARM* ARM7; @@ -1350,6 +1346,36 @@ void ARM9Write32(u32 addr, u32 val) printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]); } +bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region) +{ + switch (addr & 0xFF000000) + { + case 0x02000000: + region->Mem = MainRAM; + region->Mask = MAIN_RAM_SIZE-1; + return true; + + case 0x03000000: + if (SWRAM_ARM9) + { + region->Mem = SWRAM_ARM9; + region->Mask = SWRAM_ARM9Mask; + return true; + } + break; + } + + if ((addr & 0xFFFFF000) == 0xFFFF0000 && !write) + { + region->Mem = ARM9BIOS; + region->Mask = 0xFFF; + return true; + } + + region->Mem = NULL; + return false; +} + u8 ARM7Read8(u32 addr) @@ -1571,6 +1597,51 @@ void ARM7Write32(u32 addr, u32 val) //printf("unknown arm7 write32 %08X %08X @ %08X\n", addr, val, ARM7->R[15]); } +bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region) +{ + switch (addr & 0xFF800000) + { + case 0x02000000: + case 0x02800000: + region->Mem = MainRAM; + region->Mask = MAIN_RAM_SIZE-1; + return true; + + case 0x03000000: + // note on this, and why we can only cover it in one particular case: + // it is typical for games to map all shared WRAM to the ARM7 + // then access all the WRAM as one contiguous block starting at 0x037F8000 + // this case needs a bit of a hack to cover + // it's not really worth bothering anyway + if (!SWRAM_ARM7) + { + region->Mem = ARM7WRAM; + region->Mask = 0xFFFF; + return true; + } + break; + + case 0x03800000: + region->Mem = ARM7WRAM; + region->Mask = 0xFFFF; + return true; + } + + // BIOS. ARM7 PC has to be within range. + if (addr < 0x00004000 && !write) + { + if (ARM7->R[15] < 0x4000 && (addr >= ARM7BIOSProt || ARM7->R[15] < ARM7BIOSProt)) + { + region->Mem = ARM7BIOS; + region->Mask = 0x3FFF; + return true; + } + } + + region->Mem = NULL; + return false; +} + @@ -87,6 +87,13 @@ typedef struct } Timer; +typedef struct +{ + u8* Mem; + u32 Mask; + +} MemRegion; + // hax extern u32 IME[2]; extern u32 IE[2]; @@ -157,6 +164,8 @@ void ARM9Write8(u32 addr, u8 val); void ARM9Write16(u32 addr, u16 val); void ARM9Write32(u32 addr, u32 val); +bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region); + u8 ARM7Read8(u32 addr); u16 ARM7Read16(u32 addr); u32 ARM7Read32(u32 addr); @@ -164,6 +173,8 @@ void ARM7Write8(u32 addr, u8 val); void ARM7Write16(u32 addr, u16 val); void ARM7Write32(u32 addr, u32 val); +bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region); + u8 ARM9IORead8(u32 addr); u16 ARM9IORead16(u32 addr); u32 ARM9IORead32(u32 addr); |