aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ARM.cpp31
-rw-r--r--src/ARM.h19
-rw-r--r--src/CP15.cpp12
-rw-r--r--src/CP15.h5
-rw-r--r--src/GPU3D_Soft.cpp22
-rw-r--r--src/NDS.cpp79
-rw-r--r--src/NDS.h11
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;
}
}
diff --git a/src/ARM.h b/src/ARM.h
index 92d47bb..b778be4 100644
--- a/src/ARM.h
+++ b/src/ARM.h
@@ -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;
+}
+
}
diff --git a/src/CP15.h b/src/CP15.h
index 1b92191..a01034c 100644
--- a/src/CP15.h
+++ b/src/CP15.h
@@ -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;
+}
+
diff --git a/src/NDS.h b/src/NDS.h
index 1bf8508..c7913e9 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -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);