diff options
-rw-r--r-- | ARM.cpp | 18 | ||||
-rw-r--r-- | ARM.h | 2 | ||||
-rw-r--r-- | NDS.cpp | 91 | ||||
-rw-r--r-- | NDS.h | 31 | ||||
-rw-r--r-- | SPI.cpp | 158 | ||||
-rw-r--r-- | SPI.h | 19 | ||||
-rw-r--r-- | melonDS.depend | 16 |
7 files changed, 328 insertions, 7 deletions
@@ -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) @@ -57,6 +57,8 @@ public: void UpdateMode(u32 oldmode, u32 newmode); + void TriggerIRQ(); + u8 Read8(u32 addr, u32 forceuser=0) { @@ -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]); @@ -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); @@ -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); +} + +} @@ -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" + |