aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ARM.cpp18
-rw-r--r--ARM.h2
-rw-r--r--NDS.cpp91
-rw-r--r--NDS.h31
-rw-r--r--SPI.cpp158
-rw-r--r--SPI.h19
-rw-r--r--melonDS.depend16
7 files changed, 328 insertions, 7 deletions
diff --git a/ARM.cpp b/ARM.cpp
index 7d4beae..3a067a6 100644
--- a/ARM.cpp
+++ b/ARM.cpp
@@ -73,6 +73,8 @@ void ARM::JumpTo(u32 addr)
void ARM::RestoreCPSR()
{
+ u32 oldcpsr = CPSR;
+
switch (CPSR & 0x1F)
{
case 0x11:
@@ -99,6 +101,8 @@ void ARM::RestoreCPSR()
printf("!! attempt to restore CPSR under bad mode %02X\n", CPSR&0x1F);
break;
}
+
+ UpdateMode(oldcpsr, CPSR);
}
void ARM::UpdateMode(u32 oldmode, u32 newmode)
@@ -177,6 +181,20 @@ void ARM::UpdateMode(u32 oldmode, u32 newmode)
#undef SWAP
}
+void ARM::TriggerIRQ()
+{
+ if (CPSR & 0x80) return;
+
+ u32 oldcpsr = CPSR;
+ CPSR &= ~0xFF;
+ CPSR |= 0xD2;
+ UpdateMode(oldcpsr, CPSR);
+
+ R_IRQ[2] = oldcpsr;
+ R[14] = R[15];// - (oldcpsr & 0x20 ? 0 : 4);
+ JumpTo(ExceptionBase + 0x18);
+}
+
s32 ARM::Execute(s32 cycles)
{
while (cycles > 0)
diff --git a/ARM.h b/ARM.h
index 81c81d9..c5ed6e4 100644
--- a/ARM.h
+++ b/ARM.h
@@ -57,6 +57,8 @@ public:
void UpdateMode(u32 oldmode, u32 newmode);
+ void TriggerIRQ();
+
u8 Read8(u32 addr, u32 forceuser=0)
{
diff --git a/NDS.cpp b/NDS.cpp
index 1b33f3e..7d6f782 100644
--- a/NDS.cpp
+++ b/NDS.cpp
@@ -3,6 +3,7 @@
#include "NDS.h"
#include "ARM.h"
#include "CP15.h"
+#include "SPI.h"
namespace NDS
@@ -33,6 +34,9 @@ u8 ARM9DTCM[0x4000];
u32 ARM9DTCMBase, ARM9DTCMSize;
// IO shit
+u32 IME[2];
+u32 IE[2], IF[2];
+
u16 IPCSync9, IPCSync7;
bool Running;
@@ -43,6 +47,8 @@ void Init()
ARM9 = new ARM(0);
ARM7 = new ARM(1);
+ SPI::Init();
+
Reset();
}
@@ -87,6 +93,9 @@ void Reset()
ARM9DTCMBase = 0xFFFFFFFF;
ARM9DTCMSize = 0;
+ IME[0] = 0;
+ IME[1] = 0;
+
IPCSync9 = 0;
IPCSync7 = 0;
@@ -94,6 +103,8 @@ void Reset()
ARM7->Reset();
CP15::Reset();
+ SPI::Reset();
+
ARM9Cycles = 0;
ARM7Cycles = 0;
@@ -158,6 +169,18 @@ void MapSharedWRAM()
}
+void TriggerIRQ(u32 cpu, u32 irq)
+{
+ if (!(IME[cpu] & 0x1)) return;
+
+ irq = 1 << irq;
+ if (!(IE[cpu] & irq)) return;
+
+ IF[cpu] |= irq;
+ (cpu?ARM7:ARM9)->TriggerIRQ();
+}
+
+
u8 ARM9Read8(u32 addr)
{
@@ -253,6 +276,14 @@ u32 ARM9Read32(u32 addr)
case 0x03000000:
if (SWRAM_ARM9) return *(u32*)&SWRAM_ARM9[addr & SWRAM_ARM9Mask];
else return 0;
+
+ case 0x04000000:
+ switch (addr)
+ {
+ case 0x04000208: return IME[0];
+ case 0x04000210: return IE[0];
+ case 0x04000214: return IF[0];
+ }
}
printf("unknown arm9 read32 %08X | %08X\n", addr, ARM9->R[15]);
@@ -328,7 +359,7 @@ void ARM9Write16(u32 addr, u16 val)
IPCSync9 |= (val & 0x4F00);
if ((val & 0x2000) && (IPCSync7 & 0x4000))
{
- printf("ARM9 IPCSYNC IRQ TODO\n");
+ TriggerIRQ(1, IRQ_IPCSync);
}
return;
}
@@ -359,6 +390,14 @@ void ARM9Write32(u32 addr, u32 val)
case 0x03000000:
if (SWRAM_ARM9) *(u32*)&SWRAM_ARM9[addr & SWRAM_ARM9Mask] = val;
return;
+
+ case 0x04000000:
+ switch (addr)
+ {
+ case 0x04000208: IME[0] = val; return;
+ case 0x04000210: IE[0] = val; return;
+ case 0x04000214: IF[0] &= ~val; return;
+ }
}
printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]);
@@ -388,6 +427,10 @@ u8 ARM7Read8(u32 addr)
case 0x04000000:
switch (addr)
{
+ case 0x04000138: return 0; // RTC shit
+
+ case 0x040001C2: return SPI::ReadData();
+
case 0x04000241:
return WRAMCnt;
}
@@ -420,6 +463,9 @@ u16 ARM7Read16(u32 addr)
switch (addr)
{
case 0x04000180: return IPCSync7;
+
+ case 0x040001C0: return SPI::ReadCnt();
+ case 0x040001C2: return SPI::ReadData();
}
}
@@ -451,6 +497,13 @@ u32 ARM7Read32(u32 addr)
{
case 0x040001A4:
return 0x00800000; // hax
+
+ case 0x040001C0:
+ return SPI::ReadCnt() | (SPI::ReadData() << 16);
+
+ case 0x04000208: return IME[1];
+ case 0x04000210: return IE[1];
+ case 0x04000214: return IF[1];
}
}
if ((addr&0xFF000000) == 0xEA000000) Halt();
@@ -474,9 +527,25 @@ void ARM7Write8(u32 addr, u8 val)
case 0x03800000:
*(u8*)&ARM7WRAM[addr & 0xFFFF] = val;
return;
+
+ case 0x04000000:
+ switch (addr)
+ {
+ case 0x04000138:
+ return;
+
+ case 0x04000301:
+ if (val != 0x80) return;
+ TriggerIRQ(1, IRQ_CartSendDone); // HAAAAXX!!
+ return;
+
+ case 0x040001C2:
+ SPI::WriteData(val);
+ return;
+ }
}
- printf("unknown arm7 write8 %08X %02X | %08X\n", addr, val, ARM7->R[15]);
+ printf("unknown arm7 write8 %08X %02X | %08X | %08X %08X %08X %08X\n", addr, val, ARM7->R[15], IME[1], IE[1], ARM7->R[0], ARM7->R[1]);
}
void ARM7Write16(u32 addr, u16 val)
@@ -506,9 +575,17 @@ void ARM7Write16(u32 addr, u16 val)
IPCSync7 |= (val & 0x4F00);
if ((val & 0x2000) && (IPCSync9 & 0x4000))
{
- printf("ARM7 IPCSYNC IRQ TODO\n");
+ TriggerIRQ(0, IRQ_IPCSync);
}
return;
+
+ case 0x040001C0:
+ SPI::WriteCnt(val);
+ return;
+
+ case 0x040001C2:
+ SPI::WriteData(val & 0xFF);
+ return;
}
}
@@ -531,6 +608,14 @@ void ARM7Write32(u32 addr, u32 val)
case 0x03800000:
*(u32*)&ARM7WRAM[addr & 0xFFFF] = val;
return;
+
+ case 0x04000000:
+ switch (addr)
+ {
+ case 0x04000208: IME[1] = val; return;
+ case 0x04000210: IE[1] = val; return;
+ case 0x04000214: IF[1] &= ~val; printf("IRQ ack %08X\n", val);return;
+ }
}
printf("unknown arm7 write32 %08X %08X | %08X\n", addr, val, ARM7->R[15]);
diff --git a/NDS.h b/NDS.h
index b0a3311..420a749 100644
--- a/NDS.h
+++ b/NDS.h
@@ -7,6 +7,35 @@
namespace NDS
{
+enum
+{
+ IRQ_VBlank = 0,
+ IRQ_HBlank,
+ IRQ_VCount,
+ IRQ_Timer0,
+ IRQ_Timer1,
+ IRQ_Timer2,
+ IRQ_Timer3,
+ IRQ_RTC,
+ IRQ_DMA0,
+ IRQ_DMA1,
+ IRQ_DMA2,
+ IRQ_DMA3,
+ IRQ_Keypad,
+ IRQ_GBASlot,
+ IRQ_Unused14,
+ IRQ_Unused15,
+ IRQ_IPCSync,
+ IRQ_IPCSendDone,
+ IRQ_IPCRecv,
+ IRQ_CartSendDone,
+ IRQ_CartIREQMC,
+ IRQ_GXFIFO,
+ IRQ_LidOpen,
+ IRQ_SPI,
+ IRQ_Wifi
+};
+
extern u32 ARM9ITCMSize;
extern u32 ARM9DTCMBase, ARM9DTCMSize;
@@ -19,6 +48,8 @@ void Halt();
void MapSharedWRAM();
+void TriggerIRQ(u32 cpu, u32 irq);
+
u8 ARM9Read8(u32 addr);
u16 ARM9Read16(u32 addr);
u32 ARM9Read32(u32 addr);
diff --git a/SPI.cpp b/SPI.cpp
new file mode 100644
index 0000000..40bbf11
--- /dev/null
+++ b/SPI.cpp
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include "NDS.h"
+#include "SPI.h"
+
+
+namespace SPI_Firmware
+{
+
+u8* Firmware;
+u32 FirmwareLength;
+
+u32 Hold;
+u8 CurCmd;
+u32 DataPos;
+u8 Data;
+
+u32 Addr;
+
+void Init()
+{
+ Firmware = NULL;
+}
+
+void Reset()
+{
+ if (Firmware) delete[] Firmware;
+
+ FILE* f = fopen("firmware.bin", "rb");
+ fseek(f, 0, SEEK_END);
+ FirmwareLength = (u32)ftell(f);
+ Firmware = new u8[FirmwareLength];
+
+ fseek(f, 0, SEEK_SET);
+ fread(Firmware, FirmwareLength, 1, f);
+
+ fclose(f);
+
+ Hold = 0;
+ CurCmd = 0;
+ Data = 0;
+}
+
+u8 Read()
+{
+ return Data;
+}
+
+void Write(u8 val, u32 hold)
+{
+ if (!hold)
+ {
+ Hold = 0;
+ }
+
+ if (hold && (!Hold))
+ {
+ CurCmd = val;
+ Hold = 1;
+ DataPos = 1;
+ Addr = 0;
+ printf("firmware SPI command %02X\n", CurCmd);
+ return;
+ }
+
+ switch (CurCmd)
+ {
+ case 0x03: // read
+ {
+ if (DataPos < 4)
+ {
+ Addr <<= 8;
+ Addr |= val;
+ Data = 0;
+
+ if (DataPos == 3) printf("firmware SPI read %08X\n", Addr);
+ }
+ else
+ {
+ if (Addr >= FirmwareLength)
+ Data = 0;
+ else
+ Data = Firmware[Addr];
+
+ Addr++;
+ }
+
+ DataPos++;
+ }
+ break;
+
+ default:
+ printf("unknown firmware SPI command %02X\n", CurCmd);
+ break;
+ }
+}
+
+}
+
+
+namespace SPI
+{
+
+u16 CNT;
+
+u32 CurDevice;
+
+
+void Init()
+{
+ SPI_Firmware::Init();
+}
+
+void Reset()
+{
+ CNT = 0;
+
+ SPI_Firmware::Reset();
+}
+
+
+u16 ReadCnt()
+{
+ return CNT;
+}
+
+void WriteCnt(u16 val)
+{
+ CNT = val & 0xCF03;
+ if (val & 0x0400) printf("!! CRAPOED 16BIT SPI MODE\n");
+}
+
+u8 ReadData()
+{
+ if (!(CNT & (1<<15))) return 0;
+
+ switch (CNT & 0x0300)
+ {
+ case 0x0100: return SPI_Firmware::Read();
+ default: return 0;
+ }
+}
+
+void WriteData(u8 val)
+{
+ if (!(CNT & (1<<15))) return;
+
+ // TODO: take delays into account
+
+ switch (CNT & 0x0300)
+ {
+ case 0x0100: SPI_Firmware::Write(val, CNT&(1<<11)); break;
+ }
+
+ if (CNT & (1<<14))
+ NDS::TriggerIRQ(1, NDS::IRQ_SPI);
+}
+
+}
diff --git a/SPI.h b/SPI.h
new file mode 100644
index 0000000..d16e14f
--- /dev/null
+++ b/SPI.h
@@ -0,0 +1,19 @@
+
+#ifndef SPI_H
+#define SPI_H
+
+namespace SPI
+{
+
+void Init();
+void Reset();
+
+u16 ReadCnt();
+void WriteCnt(u16 val);
+
+u8 ReadData();
+void WriteData(u8 val);
+
+}
+
+#endif
diff --git a/melonDS.depend b/melonDS.depend
index 100795b..3a5a4e0 100644
--- a/melonDS.depend
+++ b/melonDS.depend
@@ -3,25 +3,26 @@
<stdio.h>
"NDS.h"
-1480786007 c:\documents\sources\melonds\nds.h
+1480786846 c:\documents\sources\melonds\nds.h
"types.h"
1463409689 c:\documents\sources\melonds\types.h
-1480784993 source:c:\documents\sources\melonds\nds.cpp
+1480816263 source:c:\documents\sources\melonds\nds.cpp
<stdio.h>
<string.h>
"NDS.h"
"ARM.h"
"CP15.h"
+ "SPI.h"
-1480779711 source:c:\documents\sources\melonds\arm.cpp
+1480789789 source:c:\documents\sources\melonds\arm.cpp
<stdio.h>
"NDS.h"
"ARM.h"
"ARMInterpreter.h"
-1480735953 c:\documents\sources\melonds\arm.h
+1480786942 c:\documents\sources\melonds\arm.h
"types.h"
"NDS.h"
@@ -64,3 +65,10 @@
<stdio.h>
"NDS.h"
+1480814622 c:\documents\sources\melonds\spi.h
+
+1480816142 source:c:\documents\sources\melonds\spi.cpp
+ <stdio.h>
+ "NDS.h"
+ "SPI.h"
+