aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NDS.cpp144
-rw-r--r--melonDS.depend2
2 files changed, 139 insertions, 7 deletions
diff --git a/NDS.cpp b/NDS.cpp
index 522c51e..0724818 100644
--- a/NDS.cpp
+++ b/NDS.cpp
@@ -75,6 +75,8 @@ u32 ARM9DTCMBase, ARM9DTCMSize;
u32 IME[2];
u32 IE[2], IF[2];
+u8 PostFlag9;
+u8 PostFlag7;
u16 PowerControl9;
u16 PowerControl7;
@@ -88,6 +90,12 @@ u16 IPCFIFOCnt9, IPCFIFOCnt7;
FIFO* IPCFIFO9; // FIFO in which the ARM9 writes
FIFO* IPCFIFO7;
+u16 DivCnt;
+u32 DivNumerator[2];
+u32 DivDenominator[2];
+u32 DivQuotient[2];
+u32 DivRemainder[2];
+
u32 ROMSPIControl;
u32 ROMControl;
u8 ROMCommand[8];
@@ -210,6 +218,8 @@ void Reset()
IME[0] = 0;
IME[1] = 0;
+ PostFlag9 = 0x00;
+ PostFlag7 = 0x00;
PowerControl9 = 0x0001;
PowerControl7 = 0x0001;
@@ -220,6 +230,8 @@ void Reset()
IPCFIFO9->Clear();
IPCFIFO7->Clear();
+ DivCnt = 0;
+
ROMSPIControl = 0;
ROMControl = 0;
memset(ROMCommand, 0, 8);
@@ -634,6 +646,86 @@ u32 ROMReadData(u32 cpu)
+void StartDiv()
+{
+ // TODO: division isn't instant!
+
+ DivCnt &= ~0x2000;
+
+ switch (DivCnt & 0x0003)
+ {
+ case 0x0000:
+ {
+ s32 num = (s32)DivNumerator[0];
+ s32 den = (s32)DivDenominator[0];
+ if (den == 0)
+ {
+ DivQuotient[0] = (num<0) ? 1:-1;
+ DivQuotient[1] = (num<0) ? -1:1;
+ *(s64*)&DivRemainder[0] = num;
+ }
+ else if (num == -0x80000000 && den == -1)
+ {
+ *(s64*)&DivQuotient[0] = 0x80000000;
+ }
+ else
+ {
+ *(s64*)&DivQuotient[0] = (s64)(num / den);
+ *(s64*)&DivRemainder[0] = (s64)(num % den);
+ }
+ }
+ break;
+
+ case 0x0001:
+ case 0x0003:
+ {
+ s64 num = *(s64*)&DivNumerator[0];
+ s32 den = (s32)DivDenominator[0];
+ if (den == 0)
+ {
+ *(s64*)&DivQuotient[0] = (num<0) ? 1:-1;
+ *(s64*)&DivRemainder[0] = num;
+ }
+ else if (num == -0x8000000000000000 && den == -1)
+ {
+ *(s64*)&DivQuotient[0] = 0x8000000000000000;
+ }
+ else
+ {
+ *(s64*)&DivQuotient[0] = (s64)(num / den);
+ *(s64*)&DivRemainder[0] = (s64)(num % den);
+ }
+ }
+ break;
+
+ case 0x0002:
+ {
+ s64 num = *(s64*)&DivNumerator[0];
+ s64 den = *(s64*)&DivDenominator[0];
+ if (den == 0)
+ {
+ *(s64*)&DivQuotient[0] = (num<0) ? 1:-1;
+ *(s64*)&DivRemainder[0] = num;
+ }
+ else if (num == -0x8000000000000000 && den == -1)
+ {
+ *(s64*)&DivQuotient[0] = 0x8000000000000000;
+ }
+ else
+ {
+ *(s64*)&DivQuotient[0] = (s64)(num / den);
+ *(s64*)&DivRemainder[0] = (s64)(num % den);
+ }
+ }
+ break;
+ }
+
+ if ((DivDenominator[0] | DivDenominator[1]) == 0)
+ DivCnt |= 0x2000;
+}
+
+
+
void debug(u32 param)
{
printf("ARM9 PC=%08X\n", ARM9->R[15]);
@@ -1230,9 +1322,7 @@ u8 ARM9IORead8(u32 addr)
case 0x04000248: return GPU2D::VRAMCNT[7];
case 0x04000249: return GPU2D::VRAMCNT[8];
- case 0x04000300:
- printf("ARM9 POSTFLG READ @ %08X\n", ARM9->R[15]);
- return 0;
+ case 0x04000300: return PostFlag9;
}
printf("unknown ARM9 IO read8 %08X\n", addr);
@@ -1281,6 +1371,9 @@ u16 ARM9IORead16(u32 addr)
case 0x04000208: return IME[0];
+ case 0x04000280: return DivCnt;
+
+ case 0x04000300: return PostFlag9;
case 0x04000304: return PowerControl9;
}
@@ -1321,6 +1414,15 @@ u32 ARM9IORead32(u32 addr)
case 0x04000210: return IE[0];
case 0x04000214: return IF[0];
+ case 0x04000290: return DivNumerator[0];
+ case 0x04000294: return DivNumerator[1];
+ case 0x04000298: return DivDenominator[0];
+ case 0x0400029C: return DivDenominator[1];
+ case 0x040002A0: return DivQuotient[0];
+ case 0x040002A4: return DivQuotient[1];
+ case 0x040002A8: return DivRemainder[0];
+ case 0x040002AC: return DivRemainder[1];
+
case 0x04100000:
if (IPCFIFOCnt9 & 0x8000)
{
@@ -1372,6 +1474,11 @@ void ARM9IOWrite8(u32 addr, u8 val)
case 0x04000247: MapSharedWRAM(val); return;
case 0x04000248: GPU2D::MapVRAM_H(7, val); return;
case 0x04000249: GPU2D::MapVRAM_I(8, val); return;
+
+ case 0x04000300:
+ if (PostFlag9 & 0x01) val |= 0x01;
+ PostFlag9 = val & 0x03;
+ return;
}
printf("unknown ARM9 IO write8 %08X %02X\n", addr, val);
@@ -1443,6 +1550,13 @@ void ARM9IOWrite16(u32 addr, u16 val)
GPU2D::MapVRAM_I(8, val >> 8);
return;
+ case 0x04000280: DivCnt = val; StartDiv(); return;
+
+ case 0x04000300:
+ if (PostFlag9 & 0x01) val |= 0x01;
+ PostFlag9 = val & 0x03;
+ return;
+
case 0x04000304: PowerControl9 = val; return;
}
@@ -1533,6 +1647,11 @@ void ARM9IOWrite32(u32 addr, u32 val)
GPU2D::MapVRAM_H(7, val & 0xFF);
GPU2D::MapVRAM_I(8, (val >> 8) & 0xFF);
return;
+
+ case 0x04000290: DivNumerator[0] = val; StartDiv(); return;
+ case 0x04000294: DivNumerator[1] = val; StartDiv(); return;
+ case 0x04000298: DivDenominator[0] = val; StartDiv(); return;
+ case 0x0400029C: DivDenominator[1] = val; StartDiv(); return;
}
printf("unknown ARM9 IO write32 %08X %08X\n", addr, val);
@@ -1552,9 +1671,7 @@ u8 ARM7IORead8(u32 addr)
case 0x04000240: return GPU2D::VRAMSTAT;
case 0x04000241: return WRAMCnt;
- case 0x04000300:
- printf("ARM7 POSTFLG READ @ %08X\n", ARM7->R[15]);
- return 0;
+ case 0x04000300: return PostFlag7;
//case 0x04000403:
//Halt();
@@ -1608,6 +1725,7 @@ u16 ARM7IORead16(u32 addr)
case 0x04000208: return IME[1];
+ case 0x04000300: return PostFlag7;
case 0x04000304: return PowerControl7;
case 0x04000504: return _soundbias;
@@ -1710,6 +1828,13 @@ void ARM7IOWrite8(u32 addr, u8 val)
case 0x04000208: IME[1] = val & 0x1; return;
+ case 0x04000300:
+ if (ARM7->R[15] >= 0x4000)
+ return;
+ if (!(PostFlag7 & 0x01))
+ PostFlag7 = val & 0x01;
+ return;
+
case 0x04000301:
if (val == 0x80) ARM7->Halt(1);
return;
@@ -1774,6 +1899,13 @@ void ARM7IOWrite16(u32 addr, u16 val)
case 0x04000208: IME[1] = val & 0x1; return;
+ case 0x04000300:
+ if (ARM7->R[15] >= 0x4000)
+ return;
+ if (!(PostFlag7 & 0x01))
+ PostFlag7 = val & 0x01;
+ return;
+
case 0x04000304: PowerControl7 = val; return;
case 0x04000504:
diff --git a/melonDS.depend b/melonDS.depend
index 7b48b42..a04007c 100644
--- a/melonDS.depend
+++ b/melonDS.depend
@@ -22,7 +22,7 @@
"SPI.h"
"Wifi.h"
-1484693558 source:c:\documents\sources\melonds\arm.cpp
+1484699468 source:c:\documents\sources\melonds\arm.cpp
<stdio.h>
"NDS.h"
"ARM.h"