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" +  |