fix some shit. add support for SPI and firmware.

This commit is contained in:
StapleButter 2016-12-04 03:20:50 +01:00
parent d7c1d77ba2
commit a14c01208a
7 changed files with 328 additions and 7 deletions

18
ARM.cpp
View File

@ -73,6 +73,8 @@ void ARM::JumpTo(u32 addr)
void ARM::RestoreCPSR() void ARM::RestoreCPSR()
{ {
u32 oldcpsr = CPSR;
switch (CPSR & 0x1F) switch (CPSR & 0x1F)
{ {
case 0x11: case 0x11:
@ -99,6 +101,8 @@ void ARM::RestoreCPSR()
printf("!! attempt to restore CPSR under bad mode %02X\n", CPSR&0x1F); printf("!! attempt to restore CPSR under bad mode %02X\n", CPSR&0x1F);
break; break;
} }
UpdateMode(oldcpsr, CPSR);
} }
void ARM::UpdateMode(u32 oldmode, u32 newmode) void ARM::UpdateMode(u32 oldmode, u32 newmode)
@ -177,6 +181,20 @@ void ARM::UpdateMode(u32 oldmode, u32 newmode)
#undef SWAP #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) s32 ARM::Execute(s32 cycles)
{ {
while (cycles > 0) while (cycles > 0)

2
ARM.h
View File

@ -57,6 +57,8 @@ public:
void UpdateMode(u32 oldmode, u32 newmode); void UpdateMode(u32 oldmode, u32 newmode);
void TriggerIRQ();
u8 Read8(u32 addr, u32 forceuser=0) u8 Read8(u32 addr, u32 forceuser=0)
{ {

91
NDS.cpp
View File

@ -3,6 +3,7 @@
#include "NDS.h" #include "NDS.h"
#include "ARM.h" #include "ARM.h"
#include "CP15.h" #include "CP15.h"
#include "SPI.h"
namespace NDS namespace NDS
@ -33,6 +34,9 @@ u8 ARM9DTCM[0x4000];
u32 ARM9DTCMBase, ARM9DTCMSize; u32 ARM9DTCMBase, ARM9DTCMSize;
// IO shit // IO shit
u32 IME[2];
u32 IE[2], IF[2];
u16 IPCSync9, IPCSync7; u16 IPCSync9, IPCSync7;
bool Running; bool Running;
@ -43,6 +47,8 @@ void Init()
ARM9 = new ARM(0); ARM9 = new ARM(0);
ARM7 = new ARM(1); ARM7 = new ARM(1);
SPI::Init();
Reset(); Reset();
} }
@ -87,6 +93,9 @@ void Reset()
ARM9DTCMBase = 0xFFFFFFFF; ARM9DTCMBase = 0xFFFFFFFF;
ARM9DTCMSize = 0; ARM9DTCMSize = 0;
IME[0] = 0;
IME[1] = 0;
IPCSync9 = 0; IPCSync9 = 0;
IPCSync7 = 0; IPCSync7 = 0;
@ -94,6 +103,8 @@ void Reset()
ARM7->Reset(); ARM7->Reset();
CP15::Reset(); CP15::Reset();
SPI::Reset();
ARM9Cycles = 0; ARM9Cycles = 0;
ARM7Cycles = 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) u8 ARM9Read8(u32 addr)
{ {
@ -253,6 +276,14 @@ u32 ARM9Read32(u32 addr)
case 0x03000000: case 0x03000000:
if (SWRAM_ARM9) return *(u32*)&SWRAM_ARM9[addr & SWRAM_ARM9Mask]; if (SWRAM_ARM9) return *(u32*)&SWRAM_ARM9[addr & SWRAM_ARM9Mask];
else return 0; 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]); printf("unknown arm9 read32 %08X | %08X\n", addr, ARM9->R[15]);
@ -328,7 +359,7 @@ void ARM9Write16(u32 addr, u16 val)
IPCSync9 |= (val & 0x4F00); IPCSync9 |= (val & 0x4F00);
if ((val & 0x2000) && (IPCSync7 & 0x4000)) if ((val & 0x2000) && (IPCSync7 & 0x4000))
{ {
printf("ARM9 IPCSYNC IRQ TODO\n"); TriggerIRQ(1, IRQ_IPCSync);
} }
return; return;
} }
@ -359,6 +390,14 @@ void ARM9Write32(u32 addr, u32 val)
case 0x03000000: case 0x03000000:
if (SWRAM_ARM9) *(u32*)&SWRAM_ARM9[addr & SWRAM_ARM9Mask] = val; if (SWRAM_ARM9) *(u32*)&SWRAM_ARM9[addr & SWRAM_ARM9Mask] = val;
return; 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]); printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]);
@ -388,6 +427,10 @@ u8 ARM7Read8(u32 addr)
case 0x04000000: case 0x04000000:
switch (addr) switch (addr)
{ {
case 0x04000138: return 0; // RTC shit
case 0x040001C2: return SPI::ReadData();
case 0x04000241: case 0x04000241:
return WRAMCnt; return WRAMCnt;
} }
@ -420,6 +463,9 @@ u16 ARM7Read16(u32 addr)
switch (addr) switch (addr)
{ {
case 0x04000180: return IPCSync7; case 0x04000180: return IPCSync7;
case 0x040001C0: return SPI::ReadCnt();
case 0x040001C2: return SPI::ReadData();
} }
} }
@ -451,6 +497,13 @@ u32 ARM7Read32(u32 addr)
{ {
case 0x040001A4: case 0x040001A4:
return 0x00800000; // hax 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(); if ((addr&0xFF000000) == 0xEA000000) Halt();
@ -474,9 +527,25 @@ void ARM7Write8(u32 addr, u8 val)
case 0x03800000: case 0x03800000:
*(u8*)&ARM7WRAM[addr & 0xFFFF] = val; *(u8*)&ARM7WRAM[addr & 0xFFFF] = val;
return; 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) void ARM7Write16(u32 addr, u16 val)
@ -506,9 +575,17 @@ void ARM7Write16(u32 addr, u16 val)
IPCSync7 |= (val & 0x4F00); IPCSync7 |= (val & 0x4F00);
if ((val & 0x2000) && (IPCSync9 & 0x4000)) if ((val & 0x2000) && (IPCSync9 & 0x4000))
{ {
printf("ARM7 IPCSYNC IRQ TODO\n"); TriggerIRQ(0, IRQ_IPCSync);
} }
return; 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: case 0x03800000:
*(u32*)&ARM7WRAM[addr & 0xFFFF] = val; *(u32*)&ARM7WRAM[addr & 0xFFFF] = val;
return; 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]); printf("unknown arm7 write32 %08X %08X | %08X\n", addr, val, ARM7->R[15]);

31
NDS.h
View File

@ -7,6 +7,35 @@
namespace NDS 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 ARM9ITCMSize;
extern u32 ARM9DTCMBase, ARM9DTCMSize; extern u32 ARM9DTCMBase, ARM9DTCMSize;
@ -19,6 +48,8 @@ void Halt();
void MapSharedWRAM(); void MapSharedWRAM();
void TriggerIRQ(u32 cpu, u32 irq);
u8 ARM9Read8(u32 addr); u8 ARM9Read8(u32 addr);
u16 ARM9Read16(u32 addr); u16 ARM9Read16(u32 addr);
u32 ARM9Read32(u32 addr); u32 ARM9Read32(u32 addr);

158
SPI.cpp Normal file
View File

@ -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);
}
}

19
SPI.h Normal file
View File

@ -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

View File

@ -3,25 +3,26 @@
<stdio.h> <stdio.h>
"NDS.h" "NDS.h"
1480786007 c:\documents\sources\melonds\nds.h 1480786846 c:\documents\sources\melonds\nds.h
"types.h" "types.h"
1463409689 c:\documents\sources\melonds\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> <stdio.h>
<string.h> <string.h>
"NDS.h" "NDS.h"
"ARM.h" "ARM.h"
"CP15.h" "CP15.h"
"SPI.h"
1480779711 source:c:\documents\sources\melonds\arm.cpp 1480789789 source:c:\documents\sources\melonds\arm.cpp
<stdio.h> <stdio.h>
"NDS.h" "NDS.h"
"ARM.h" "ARM.h"
"ARMInterpreter.h" "ARMInterpreter.h"
1480735953 c:\documents\sources\melonds\arm.h 1480786942 c:\documents\sources\melonds\arm.h
"types.h" "types.h"
"NDS.h" "NDS.h"
@ -64,3 +65,10 @@
<stdio.h> <stdio.h>
"NDS.h" "NDS.h"
1480814622 c:\documents\sources\melonds\spi.h
1480816142 source:c:\documents\sources\melonds\spi.cpp
<stdio.h>
"NDS.h"
"SPI.h"