From c8a0058ebc7440493ed8483b8630140e6811acfd Mon Sep 17 00:00:00 2001 From: StapleButter Date: Mon, 5 Dec 2016 23:17:03 +0100 Subject: implementation of VRAM and other misc crap --- ARM.cpp | 7 +- ARM.h | 6 + ARMInterpreter.h | 4 - ARMInterpreter_ALU.cpp | 27 ++ ARMInterpreter_ALU.h | 2 + ARMInterpreter_LoadStore.cpp | 32 +- ARM_InstrTable.h | 2 +- CP15.cpp | 12 + GPU2D.cpp | 696 ++++++++++++++++++++++++++++++++++++++++++- GPU2D.h | 29 +- NDS.cpp | 282 ++++++++++++++++-- SPI.cpp | 4 +- melonDS.depend | 48 +-- 13 files changed, 1092 insertions(+), 59 deletions(-) diff --git a/ARM.cpp b/ARM.cpp index fab4698..6c6949d 100644 --- a/ARM.cpp +++ b/ARM.cpp @@ -206,7 +206,10 @@ void ARM::UpdateMode(u32 oldmode, u32 newmode) void ARM::TriggerIRQ() { - if (CPSR & 0x80) return; + if ((CPSR & 0x80) && (!Halted)) + return; + + Halted = 0; u32 oldcpsr = CPSR; CPSR &= ~0xFF; @@ -220,6 +223,8 @@ void ARM::TriggerIRQ() s32 ARM::Execute(s32 cycles) { + if (Halted) return cycles; + s32 cyclesrun = 0; while (cyclesrun < cycles) diff --git a/ARM.h b/ARM.h index 72ba088..e420c59 100644 --- a/ARM.h +++ b/ARM.h @@ -40,6 +40,11 @@ public: void JumpTo(u32 addr, bool restorecpsr = false); void RestoreCPSR(); + void Halt(u32 halt) + { + Halted = halt; + } + s32 Execute(s32 cycles); bool CheckCondition(u32 code) @@ -162,6 +167,7 @@ public: u32 Num; s32 Cycles; + u32 Halted; u32 R[16]; // heh u32 CPSR; diff --git a/ARMInterpreter.h b/ARMInterpreter.h index 12005f3..e6fed79 100644 --- a/ARMInterpreter.h +++ b/ARMInterpreter.h @@ -25,10 +25,6 @@ namespace ARMInterpreter { -s32 A_MSR_IMM(ARM* cpu); -s32 A_MSR_REG(ARM* cpu); -s32 A_MRS(ARM* cpu); - extern s32 (*ARMInstrTable[4096])(ARM* cpu); extern s32 (*THUMBInstrTable[1024])(ARM* cpu); diff --git a/ARMInterpreter_ALU.cpp b/ARMInterpreter_ALU.cpp index 676ff5f..16e3153 100644 --- a/ARMInterpreter_ALU.cpp +++ b/ARMInterpreter_ALU.cpp @@ -718,6 +718,33 @@ A_IMPLEMENT_ALU_OP(MVN) +s32 A_CLZ(ARM* cpu) +{ + // TODO: ARM9 only + + u32 val = cpu->R[cpu->CurInstr & 0xF]; + + u32 res = 0; + while ((val & 0xFF000000) == 0) + { + res += 8; + val <<= 8; + val |= 0xFF; + } + while ((val & 0x80000000) == 0) + { + res++; + val <<= 1; + val |= 0x1; + } + + cpu->R[(cpu->CurInstr >> 12) & 0xF] = res; + + return C_S(1); +} + + + // ---- THUMB ---------------------------------- diff --git a/ARMInterpreter_ALU.h b/ARMInterpreter_ALU.h index 1c6fe44..610ffed 100644 --- a/ARMInterpreter_ALU.h +++ b/ARMInterpreter_ALU.h @@ -72,6 +72,8 @@ A_PROTO_ALU_OP(MOV) A_PROTO_ALU_OP(BIC) A_PROTO_ALU_OP(MVN) +s32 A_CLZ(ARM* cpu); + s32 T_LSL_IMM(ARM* cpu); s32 T_LSR_IMM(ARM* cpu); diff --git a/ARMInterpreter_LoadStore.cpp b/ARMInterpreter_LoadStore.cpp index 165a2fe..2106adc 100644 --- a/ARMInterpreter_LoadStore.cpp +++ b/ARMInterpreter_LoadStore.cpp @@ -370,9 +370,19 @@ s32 A_LDM(ARM* cpu) if (cpu->CurInstr & (1<<21)) { - cpu->R[(cpu->CurInstr >> 16) & 0xF] = base; - if (cpu->CurInstr & (1 << ((cpu->CurInstr >> 16) & 0xF))) - printf("!! BAD LDM\n"); + // pre writeback + u32 rb = (cpu->CurInstr >> 16) & 0xF; + if (cpu->CurInstr & (1 << rb)) + { + if (cpu->Num == 0) + { + u32 rlist = cpu->CurInstr & 0xFFFF; + if ((!(rlist & ~(1 << rb))) || (rlist & ~((2 << rb) - 1))) + cpu->R[rb] = base; + } + } + else + cpu->R[rb] = base; } preinc = !preinc; @@ -412,9 +422,19 @@ s32 A_LDM(ARM* cpu) if ((cpu->CurInstr & (1<<23)) && (cpu->CurInstr & (1<<21))) { - cpu->R[(cpu->CurInstr >> 16) & 0xF] = base; - if (cpu->CurInstr & (1 << ((cpu->CurInstr >> 16) & 0xF))) - printf("!! BAD LDM\n"); + // post writeback + u32 rb = (cpu->CurInstr >> 16) & 0xF; + if (cpu->CurInstr & (1 << rb)) + { + if (cpu->Num == 0) + { + u32 rlist = cpu->CurInstr & 0xFFFF; + if ((!(rlist & ~(1 << rb))) || (rlist & ~((2 << rb) - 1))) + cpu->R[rb] = base; + } + } + else + cpu->R[rb] = base; } return cycles; diff --git a/ARM_InstrTable.h b/ARM_InstrTable.h index e39703c..351f40b 100644 --- a/ARM_InstrTable.h +++ b/ARM_InstrTable.h @@ -153,7 +153,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = A_CMP_REG_ASR_IMM, A_LDRSB_IMM, A_CMP_REG_ROR_IMM, A_LDRSH_IMM, // 0001 0110 0000 - A_MSR_REG, A_UNK, A_UNK, A_UNK, + A_MSR_REG, A_CLZ, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_STRH_IMM, A_UNK, A_LDRD_IMM, A_UNK, A_STRD_IMM, diff --git a/CP15.cpp b/CP15.cpp index 528f62e..1213d28 100644 --- a/CP15.cpp +++ b/CP15.cpp @@ -18,8 +18,15 @@ #include #include "NDS.h" +#include "ARM.h" +// derp +namespace NDS +{ +extern ARM* ARM9; +} + namespace CP15 { @@ -81,6 +88,11 @@ void Write(u32 id, u32 val) return; + case 0x704: + NDS::ARM9->Halt(1); + return; + + case 0x910: DTCMSetting = val; UpdateDTCMSetting(); diff --git a/GPU2D.cpp b/GPU2D.cpp index 8145101..a879576 100644 --- a/GPU2D.cpp +++ b/GPU2D.cpp @@ -16,6 +16,8 @@ with melonDS. If not, see http://www.gnu.org/licenses/. */ +#include +#include #include "NDS.h" #include "GPU2D.h" @@ -23,6 +25,698 @@ namespace GPU2D { -// +#define LINE_CYCLES (355*6 * 2) +#define FRAME_CYCLES (LINE_CYCLES * 263) + +u16 VCount; + +u16 DispStat[2], VMatch[2]; + +u8 VRAM_A[128*1024]; +u8 VRAM_B[128*1024]; +u8 VRAM_C[128*1024]; +u8 VRAM_D[128*1024]; +u8 VRAM_E[ 64*1024]; +u8 VRAM_F[ 16*1024]; +u8 VRAM_G[ 16*1024]; +u8 VRAM_H[ 32*1024]; +u8 VRAM_I[ 16*1024]; +u8* VRAM[9] = {VRAM_A, VRAM_B, VRAM_C, VRAM_D, VRAM_E, VRAM_F, VRAM_G, VRAM_H, VRAM_I}; + +u8 VRAMCNT[9]; +u8 VRAMSTAT; + +u8* VRAM_ABG[128]; +u8* VRAM_AOBJ[128]; +u8* VRAM_BBG[128]; +u8* VRAM_BOBJ[128]; +u8* VRAM_LCD[128]; +u8* VRAM_ARM7[2]; + + +void Reset() +{ + VCount = 0; + + DispStat[0] = 0; + DispStat[1] = 0; + VMatch[0] = 0; + VMatch[1] = 0; + + memset(VRAM_A, 0, 128*1024); + memset(VRAM_B, 0, 128*1024); + memset(VRAM_C, 0, 128*1024); + memset(VRAM_D, 0, 128*1024); + memset(VRAM_E, 0, 64*1024); + memset(VRAM_F, 0, 16*1024); + memset(VRAM_G, 0, 16*1024); + memset(VRAM_H, 0, 32*1024); + memset(VRAM_I, 0, 16*1024); + + memset(VRAMCNT, 0, 9); + VRAMSTAT = 0; + + memset(VRAM_ABG, 0, sizeof(u8*)*128); + memset(VRAM_AOBJ, 0, sizeof(u8*)*128); + memset(VRAM_BBG, 0, sizeof(u8*)*128); + memset(VRAM_BOBJ, 0, sizeof(u8*)*128); + memset(VRAM_LCD, 0, sizeof(u8*)*128); + memset(VRAM_ARM7, 0, sizeof(u8*)*2); +} + + +void MapVRAM_AB(u32 bank, u8 cnt) +{ + u8 oldcnt = VRAMCNT[bank]; + VRAMCNT[bank] = cnt; + + if (oldcnt == cnt) return; + + u8 oldofs = (oldcnt >> 3) & 0x3; + u8 ofs = (cnt >> 3) & 0x3; + + u8* vram = VRAM[bank]; + + if (oldcnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (oldcnt & 0x3) + { + case 0: + vrammap = &VRAM_LCD[bank<<3]; + break; + + case 1: + vrammap = &VRAM_ABG[oldofs<<3]; + break; + + case 2: + oldofs &= 0x1; + vrammap = &VRAM_AOBJ[oldofs<<3]; + break; + + case 3: + // not mapped to memory + break; + } + + if (vrammap) + { + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap = NULL; + } + } + + if (cnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (cnt & 0x3) + { + case 0: + vrammap = &VRAM_LCD[bank<<3]; + break; + + case 1: + vrammap = &VRAM_ABG[ofs<<3]; + break; + + case 2: + ofs &= 0x1; + vrammap = &VRAM_AOBJ[ofs<<3]; + break; + + case 3: + // not mapped to memory + break; + } + + if (vrammap) + { + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap = vram; + } + } +} + +void MapVRAM_CD(u32 bank, u8 cnt) +{ + u8 oldcnt = VRAMCNT[bank]; + VRAMCNT[bank] = cnt; + + VRAMSTAT &= ~(1 << (bank-2)); + + if (oldcnt == cnt) return; + + u8 oldofs = (oldcnt >> 3) & 0x7; + u8 ofs = (cnt >> 3) & 0x7; + + u8* vram = VRAM[bank]; + + if (oldcnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (oldcnt & 0x7) + { + case 0: + vrammap = &VRAM_LCD[bank<<3]; + break; + + case 1: + vrammap = &VRAM_ABG[oldofs<<3]; + break; + + case 2: + oldofs &= 0x1; + VRAM_ARM7[oldofs] = NULL; + break; + + case 3: + // not mapped to memory + break; + + case 4: + if (bank == 2) + vrammap = &VRAM_BBG[0]; + else + vrammap = &VRAM_BOBJ[0]; + break; + } + + if (vrammap) + { + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap = NULL; + } + } + + if (cnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (cnt & 0x7) + { + case 0: + vrammap = &VRAM_LCD[bank<<3]; + break; + + case 1: + vrammap = &VRAM_ABG[ofs<<3]; + break; + + case 2: + ofs &= 0x1; + VRAM_ARM7[ofs] = vram; + VRAMSTAT |= (1 << (bank-2)); + break; + + case 3: + // not mapped to memory + break; + + case 4: + if (bank == 2) + vrammap = &VRAM_BBG[0]; + else + vrammap = &VRAM_BOBJ[0]; + break; + } + + if (vrammap) + { + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap++ = vram; vram += 0x4000; + *vrammap = vram; + } + } +} + +void MapVRAM_E(u32 bank, u8 cnt) +{ + u8 oldcnt = VRAMCNT[bank]; + VRAMCNT[bank] = cnt; + + if (oldcnt == cnt) return; + + u8 oldofs = (oldcnt >> 3) & 0x7; + u8 ofs = (cnt >> 3) & 0x7; + + u8* vram = VRAM[bank]; + + if (oldcnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (oldcnt & 0x7) + { + case 0: + VRAM_LCD[0x20] = NULL; + VRAM_LCD[0x21] = NULL; + VRAM_LCD[0x22] = NULL; + VRAM_LCD[0x23] = NULL; + break; + + case 1: + vrammap = &VRAM_ABG[0]; + break; + + case 2: + vrammap = &VRAM_AOBJ[0]; + break; + + case 3: + // not mapped to memory + break; + + case 4: + // BG EXTPAL -- TODO + break; + + case 5: + // OBJ EXTPAL -- TODO + break; + } + + if (vrammap) + { + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap = NULL; + } + } + + if (cnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (cnt & 0x7) + { + case 0: + VRAM_LCD[0x20] = &vram[0x0000]; + VRAM_LCD[0x21] = &vram[0x4000]; + VRAM_LCD[0x22] = &vram[0x8000]; + VRAM_LCD[0x23] = &vram[0xC000]; + break; + + case 1: + vrammap = &VRAM_ABG[0]; + break; + + case 2: + vrammap = &VRAM_AOBJ[0]; + break; + + case 3: + // not mapped to memory + break; + + case 4: + // BG EXTPAL -- TODO + break; + + case 5: + // OBJ EXTPAL -- TODO + break; + } + + if (vrammap) + { + *vrammap++ = &vram[0x0000]; + *vrammap++ = &vram[0x4000]; + *vrammap++ = &vram[0x8000]; + *vrammap++ = &vram[0xC000]; + *vrammap++ = &vram[0x0000]; + *vrammap++ = &vram[0x4000]; + *vrammap++ = &vram[0x8000]; + *vrammap = &vram[0xC000]; + } + } +} + +void MapVRAM_FG(u32 bank, u8 cnt) +{ + u8 oldcnt = VRAMCNT[bank]; + VRAMCNT[bank] = cnt; + + if (oldcnt == cnt) return; + + u8 oldofs = (oldcnt >> 3) & 0x7; + u8 ofs = (cnt >> 3) & 0x7; + + u8* vram = VRAM[bank]; + bank -= 5; + + if (oldcnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (oldcnt & 0x7) + { + case 0: + VRAM_LCD[0x24 + bank] = NULL; + break; + + case 1: + vrammap = &VRAM_ABG[(oldofs & 0x1) | ((oldofs & 0x2) << 1)]; + break; + + case 2: + vrammap = &VRAM_AOBJ[(oldofs & 0x1) | ((oldofs & 0x2) << 1)]; + break; + + case 3: + // not mapped to memory + break; + + case 4: + // BG EXTPAL TODO + break; + + case 5: + // OBJ EXTPAL TODO + break; + } + + if (vrammap) + { + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap = NULL; + } + } + + if (cnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (cnt & 0x7) + { + case 0: + VRAM_LCD[0x24 + bank] = vram; + break; + + case 1: + vrammap = &VRAM_ABG[(ofs & 0x1) | ((ofs & 0x2) << 1)]; + break; + + case 2: + vrammap = &VRAM_AOBJ[(ofs & 0x1) | ((ofs & 0x2) << 1)]; + break; + + case 3: + // not mapped to memory + break; + + case 4: + // BG EXTPAL TODO + break; + + case 5: + // OBJ EXTPAL TODO + break; + } + + if (vrammap) + { + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap = vram; + } + } +} + +void MapVRAM_H(u32 bank, u8 cnt) +{ + u8 oldcnt = VRAMCNT[bank]; + VRAMCNT[bank] = cnt; + + if (oldcnt == cnt) return; + + u8 oldofs = (oldcnt >> 3) & 0x7; + u8 ofs = (cnt >> 3) & 0x7; + + u8* vram = VRAM[bank]; + + if (oldcnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (oldcnt & 0x3) + { + case 0: + VRAM_LCD[0x26] = NULL; + VRAM_LCD[0x27] = NULL; + break; + + case 1: + vrammap = &VRAM_BBG[0x00]; + break; + + case 2: + // BG EXTPAL TODO + break; + } + + if (vrammap) + { + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap = NULL; + } + } + + if (cnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (cnt & 0x3) + { + case 0: + VRAM_LCD[0x26] = &vram[0x0000]; + VRAM_LCD[0x27] = &vram[0x4000]; + break; + + case 1: + vrammap = &VRAM_BBG[0x00]; + break; + + case 2: + // BG EXTPAL TODO + break; + } + + if (vrammap) + { + *vrammap++ = &vram[0x0000]; + *vrammap++ = &vram[0x4000]; + *vrammap++ = &vram[0x0000]; + *vrammap++ = &vram[0x4000]; + *vrammap++ = &vram[0x0000]; + *vrammap++ = &vram[0x4000]; + *vrammap++ = &vram[0x0000]; + *vrammap = &vram[0x4000]; + } + } +} + +void MapVRAM_I(u32 bank, u8 cnt) +{ + u8 oldcnt = VRAMCNT[bank]; + VRAMCNT[bank] = cnt; + + if (oldcnt == cnt) return; + + u8 oldofs = (oldcnt >> 3) & 0x7; + u8 ofs = (cnt >> 3) & 0x7; + + u8* vram = VRAM[bank]; + bank -= 5; + + if (oldcnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (oldcnt & 0x3) + { + case 0: + VRAM_LCD[0x28] = NULL; + break; + + case 1: + vrammap = &VRAM_BBG[0x02]; + break; + + case 2: + vrammap = &VRAM_BOBJ[0x00]; + break; + + case 3: + // not mapped to memory + break; + } + + if (vrammap) + { + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap++ = NULL; + *vrammap = NULL; + } + } + + if (cnt & (1<<7)) + { + u8** vrammap = NULL; + + switch (cnt & 0x3) + { + case 0: + VRAM_LCD[0x28] = vram; + break; + + case 1: + vrammap = &VRAM_BBG[0x02]; + break; + + case 2: + vrammap = &VRAM_BOBJ[0x00]; + break; + + case 3: + // not mapped to memory + break; + } + + if (vrammap) + { + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap++ = vram; + *vrammap = vram; + } + } +} + + +void StartFrame() +{ + StartScanline(0); +} + +void StartScanline(u32 line) +{ + VCount = line; + + if (line == VMatch[0]) + { + DispStat[0] |= (1<<2); + + if (DispStat[0] & (1<<5)) NDS::TriggerIRQ(0, NDS::IRQ_VCount); + } + else + DispStat[0] &= ~(1<<2); + + if (line == VMatch[1]) + { + DispStat[1] |= (1<<2); + + if (DispStat[1] & (1<<5)) NDS::TriggerIRQ(1, NDS::IRQ_VCount); + } + else + DispStat[1] &= ~(1<<2); + + if (line < 192) + { + // TODO: draw shit + + NDS::ScheduleEvent(LINE_CYCLES, StartScanline, line+1); + } + else if (line == 262) + { + // frame end + + DispStat[0] &= ~(1<<0); + DispStat[1] &= ~(1<<0); + } + else + { + if (line == 192) + { + // VBlank + DispStat[0] |= (1<<0); + DispStat[1] |= (1<<0); + + if (DispStat[0] & (1<<3)) NDS::TriggerIRQ(0, NDS::IRQ_VBlank); + if (DispStat[1] & (1<<3)) NDS::TriggerIRQ(1, NDS::IRQ_VBlank); + } + + NDS::ScheduleEvent(LINE_CYCLES, StartScanline, line+1); + } +} + + +void SetDispStat(u32 cpu, u16 val) +{ + val &= 0xFFB8; + DispStat[cpu] &= 0x0047; + DispStat[cpu] |= val; + + VMatch[cpu] = (val >> 8) | ((val & 0x80) << 1); + + if (val & 0x10) printf("!! HBLANK ENABLED\n"); +} } diff --git a/GPU2D.h b/GPU2D.h index 4ff09e5..1b6c178 100644 --- a/GPU2D.h +++ b/GPU2D.h @@ -22,7 +22,34 @@ namespace GPU2D { -// shit here +extern u16 VCount; + +extern u16 DispStat[2]; + +extern u8 VRAMCNT[9]; +extern u8 VRAMSTAT; + +extern u8* VRAM_ABG[128]; +extern u8* VRAM_AOBJ[128]; +extern u8* VRAM_BBG[128]; +extern u8* VRAM_BOBJ[128]; +extern u8* VRAM_LCD[128]; +extern u8* VRAM_ARM7[2]; + + +void Reset(); + +void MapVRAM_AB(u32 bank, u8 cnt); +void MapVRAM_CD(u32 bank, u8 cnt); +void MapVRAM_E(u32 bank, u8 cnt); +void MapVRAM_FG(u32 bank, u8 cnt); +void MapVRAM_H(u32 bank, u8 cnt); +void MapVRAM_I(u32 bank, u8 cnt); + +void StartFrame(); +void StartScanline(u32 line); + +void SetDispStat(u32 cpu, u16 val); } diff --git a/NDS.cpp b/NDS.cpp index 97fa850..dfb6194 100644 --- a/NDS.cpp +++ b/NDS.cpp @@ -21,6 +21,7 @@ #include "NDS.h" #include "ARM.h" #include "CP15.h" +#include "GPU2D.h" #include "SPI.h" @@ -152,25 +153,30 @@ void Reset() void RunFrame() { s32 framecycles = 560190<<1; - const s32 maxcycles = 16; + if (!Running) return; // dorp + + GPU2D::StartFrame(); + while (Running && framecycles>0) { - //ARM9Cycles = ARM9->Execute(32 + ARM9Cycles); - //ARM7Cycles = ARM7->Execute(16 + ARM7Cycles); - - //framecycles -= 32; s32 cyclestorun = maxcycles; - // TODO: scheduler integration here + if (SchedQueue) + { + if (SchedQueue->Delay < cyclestorun) + cyclestorun = SchedQueue->Delay; + } - CompensatedCycles = ARM9Cycles; - s32 c9 = ARM9->Execute(cyclestorun - ARM9Cycles); - ARM9Cycles = c9 - cyclestorun; - c9 -= CompensatedCycles; + //CompensatedCycles = ARM9Cycles; + s32 torun9 = cyclestorun - ARM9Cycles; + s32 c9 = ARM9->Execute(torun9); + ARM9Cycles = c9 - torun9; + //c9 -= CompensatedCycles; - s32 c7 = ARM7->Execute((c9 - ARM7Cycles) >> 1) << 1; - ARM7Cycles = c7 - c9; + s32 torun7 = (c9 - ARM7Cycles) & ~1; + s32 c7 = ARM7->Execute(torun7 >> 1) << 1; + ARM7Cycles = c7 - torun7; RunEvents(c9); framecycles -= cyclestorun; @@ -190,9 +196,24 @@ SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param) } } + //if (Func == GPU2D::StartScanline) + // printf("add scanline event %d delay %d\n", Param, Delay); + if (entry == -1) { printf("!! SCHEDULER BUFFER FULL\n"); + /*void TimerIncrement(u32 param); + for (int i = 0; i < SCHED_BUF_LEN; i++) + { + printf("%d. %s (%08X), delay %d, prev=%d, next=%d\n", + i, + SchedBuffer[i].Func ? ((SchedBuffer[i].Func==TimerIncrement)?"Timer":"Scanline") : "NULL", + SchedBuffer[i].Param, + SchedBuffer[i].Delay, + SchedBuffer[i].PrevEvent ? (SchedBuffer[i].PrevEvent-SchedBuffer) : -1, + SchedBuffer[i].NextEvent ? (SchedBuffer[i].NextEvent-SchedBuffer) : -1); + }*/ + //printf("%p %p %08X %p\n", SchedQueue, SchedQueue->Func, SchedQueue->Param, TimerIncrement); return NULL; } @@ -200,6 +221,8 @@ SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param) evt->Func = Func; evt->Param = Param; + Delay += SchedCycles; + SchedEvent* cur = SchedQueue; SchedEvent* prev = NULL; for (;;) @@ -239,6 +262,8 @@ SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param) if (evt->PrevEvent) evt->PrevEvent->NextEvent = evt; + else + SchedQueue = evt; cur->PrevEvent = evt; cur->Delay -= evt->Delay; @@ -264,6 +289,7 @@ void CancelEvent(SchedEvent* event) void RunEvents(s32 cycles) { + //printf("runevents %d\n", cycles); SchedCycles += cycles; SchedEvent* evt = SchedQueue; @@ -281,7 +307,7 @@ void RunEvents(s32 cycles) } void CompensateARM7() -{ +{return; s32 c9 = ARM9->Cycles - CompensatedCycles; CompensatedCycles = ARM9->Cycles; @@ -358,7 +384,7 @@ void TimerIncrement(u32 param) for (;;) { timer->Counter++; - if (param==7)printf("timer%d increment %04X %04X %04X\n", param, timer->Control, timer->Counter, timer->Reload); + if (tid == (param&0x3)) timer->Event = ScheduleEvent(TimerPrescaler[timer->Control&0x3], TimerIncrement, param); @@ -389,8 +415,6 @@ void TimerStart(u32 id, u16 cnt) u16 curstart = timer->Control & (1<<7); u16 newstart = cnt & (1<<7); - printf("timer%d start: %04X %04X\n", id, timer->Control, cnt); - timer->Control = cnt; if ((!curstart) && newstart) @@ -442,9 +466,36 @@ u8 ARM9Read8(u32 addr) { case 0x04000208: return IME[0]; - case 0x04000247: - return WRAMCnt; + case 0x04000240: return GPU2D::VRAMCNT[0]; + case 0x04000241: return GPU2D::VRAMCNT[1]; + case 0x04000242: return GPU2D::VRAMCNT[2]; + case 0x04000243: return GPU2D::VRAMCNT[3]; + case 0x04000244: return GPU2D::VRAMCNT[4]; + case 0x04000245: return GPU2D::VRAMCNT[5]; + case 0x04000246: return GPU2D::VRAMCNT[6]; + case 0x04000247: return WRAMCnt; + case 0x04000248: return GPU2D::VRAMCNT[7]; + case 0x04000249: return GPU2D::VRAMCNT[8]; } + printf("unknown arm9 IO read8 %08X\n", addr); + return 0; + + case 0x06000000: + { + u32 chunk = (addr >> 14) & 0x7F; + u8* vram = NULL; + switch (addr & 0x00E00000) + { + case 0x00000000: vram = GPU2D::VRAM_ABG[chunk]; break; + case 0x00200000: vram = GPU2D::VRAM_AOBJ[chunk]; break; + case 0x00400000: vram = GPU2D::VRAM_BBG[chunk]; break; + case 0x00600000: vram = GPU2D::VRAM_BOBJ[chunk]; break; + case 0x00800000: vram = GPU2D::VRAM_LCD[chunk]; break; + } + if (vram) + return *(u8*)&vram[addr & 0x3FFF]; + } + return 0; } printf("unknown arm9 read8 %08X\n", addr); @@ -478,6 +529,9 @@ u16 ARM9Read16(u32 addr) case 0x04000000: switch (addr) { + case 0x04000004: return GPU2D::DispStat[0]; + case 0x04000006: return GPU2D::VCount; + case 0x04000100: return Timers[0].Counter; case 0x04000102: return Timers[0].Control; case 0x04000104: return Timers[1].Counter; @@ -491,6 +545,26 @@ u16 ARM9Read16(u32 addr) case 0x04000208: return IME[0]; } + + printf("unknown arm9 IO read16 %08X\n", addr); + return 0; + + case 0x06000000: + { + u32 chunk = (addr >> 14) & 0x7F; + u8* vram = NULL; + switch (addr & 0x00E00000) + { + case 0x00000000: vram = GPU2D::VRAM_ABG[chunk]; break; + case 0x00200000: vram = GPU2D::VRAM_AOBJ[chunk]; break; + case 0x00400000: vram = GPU2D::VRAM_BBG[chunk]; break; + case 0x00600000: vram = GPU2D::VRAM_BOBJ[chunk]; break; + case 0x00800000: vram = GPU2D::VRAM_LCD[chunk]; break; + } + if (vram) + return *(u16*)&vram[addr & 0x3FFF]; + } + return 0; } printf("unknown arm9 read16 %08X\n", addr); @@ -538,6 +612,8 @@ u32 ARM9Read32(u32 addr) case 0x04000000: switch (addr) { + case 0x04000004: return GPU2D::DispStat[0] | (GPU2D::VCount << 16); + case 0x04000100: return Timers[0].Counter | (Timers[0].Control << 16); case 0x04000104: return Timers[1].Counter | (Timers[1].Control << 16); case 0x04000108: return Timers[2].Counter | (Timers[2].Control << 16); @@ -547,6 +623,26 @@ u32 ARM9Read32(u32 addr) case 0x04000210: return IE[0]; case 0x04000214: return IF[0]; } + + printf("unknown arm9 IO read32 %08X | %08X %08X %08X\n", addr, ARM9->R[15], ARM9->R[12], ARM9Read32(0x027FF820)); + return 0; + + case 0x06000000: + { + u32 chunk = (addr >> 14) & 0x7F; + u8* vram = NULL; + switch (addr & 0x00E00000) + { + case 0x00000000: vram = GPU2D::VRAM_ABG[chunk]; break; + case 0x00200000: vram = GPU2D::VRAM_AOBJ[chunk]; break; + case 0x00400000: vram = GPU2D::VRAM_BBG[chunk]; break; + case 0x00600000: vram = GPU2D::VRAM_BOBJ[chunk]; break; + case 0x00800000: vram = GPU2D::VRAM_LCD[chunk]; break; + } + if (vram) + return *(u32*)&vram[addr & 0x3FFF]; + } + return 0; } printf("unknown arm9 read32 %08X | %08X %08X %08X\n", addr, ARM9->R[15], ARM9->R[12], ARM9Read32(0x027FF820)); @@ -581,11 +677,21 @@ void ARM9Write8(u32 addr, u8 val) { case 0x04000208: IME[0] = val; return; + case 0x04000240: GPU2D::MapVRAM_AB(0, val); return; + case 0x04000241: GPU2D::MapVRAM_AB(1, val); return; + case 0x04000242: GPU2D::MapVRAM_CD(2, val); return; + case 0x04000243: GPU2D::MapVRAM_CD(3, val); return; + case 0x04000244: GPU2D::MapVRAM_E(4, val); return; + case 0x04000245: GPU2D::MapVRAM_FG(5, val); return; + case 0x04000246: GPU2D::MapVRAM_FG(6, val); return; case 0x04000247: WRAMCnt = val; MapSharedWRAM(); return; + case 0x04000248: GPU2D::MapVRAM_H(7, val); return; + case 0x04000249: GPU2D::MapVRAM_I(8, val); return; } + break; } printf("unknown arm9 write8 %08X %02X\n", addr, val); @@ -617,6 +723,8 @@ void ARM9Write16(u32 addr, u16 val) case 0x04000000: switch (addr) { + case 0x04000004: GPU2D::SetDispStat(0, val); return; + case 0x04000100: Timers[0].Reload = val; return; case 0x04000102: TimerStart(0, val); return; case 0x04000104: Timers[1].Reload = val; return; @@ -640,6 +748,24 @@ void ARM9Write16(u32 addr, u16 val) case 0x04000208: IME[0] = val; return; } + break; + + case 0x06000000: + { + u32 chunk = (addr >> 14) & 0x7F; + u8* vram = NULL; + switch (addr & 0x00E00000) + { + case 0x00000000: vram = GPU2D::VRAM_ABG[chunk]; break; + case 0x00200000: vram = GPU2D::VRAM_AOBJ[chunk]; break; + case 0x00400000: vram = GPU2D::VRAM_BBG[chunk]; break; + case 0x00600000: vram = GPU2D::VRAM_BOBJ[chunk]; break; + case 0x00800000: vram = GPU2D::VRAM_LCD[chunk]; break; + } + if (vram) + *(u16*)&vram[addr & 0x3FFF] = val; + } + return; } printf("unknown arm9 write16 %08X %04X\n", addr, val); @@ -689,9 +815,27 @@ void ARM9Write32(u32 addr, u32 val) return; case 0x04000208: IME[0] = val; return; - case 0x04000210: IE[0] = val; return; + case 0x04000210: IE[0] = val; printf("ARM9 IE == %08X\n", val); return; case 0x04000214: IF[0] &= ~val; return; } + break; + + case 0x06000000: + { + u32 chunk = (addr >> 14) & 0x7F; + u8* vram = NULL; + switch (addr & 0x00E00000) + { + case 0x00000000: vram = GPU2D::VRAM_ABG[chunk]; break; + case 0x00200000: vram = GPU2D::VRAM_AOBJ[chunk]; break; + case 0x00400000: vram = GPU2D::VRAM_BBG[chunk]; break; + case 0x00600000: vram = GPU2D::VRAM_BOBJ[chunk]; break; + case 0x00800000: vram = GPU2D::VRAM_LCD[chunk]; break; + } + if (vram) + *(u32*)&vram[addr & 0x3FFF] = val; + } + return; } printf("unknown arm9 write32 %08X %08X | %08X\n", addr, val, ARM9->R[15]); @@ -727,9 +871,21 @@ u8 ARM7Read8(u32 addr) case 0x04000208: return IME[1]; - case 0x04000241: - return WRAMCnt; + case 0x04000240: return GPU2D::VRAMSTAT; + case 0x04000241: return WRAMCnt; } + printf("unknown arm7 IO read8 %08X\n", addr); + return 0; + + case 0x06000000: + case 0x06800000: + { + u32 chunk = (addr >> 17) & 0x1; + u8* vram = GPU2D::VRAM_ARM7[chunk]; + if (vram) + return *(u8*)&vram[addr & 0x3FFF]; + } + return 0; } printf("unknown arm7 read8 %08X\n", addr); @@ -758,6 +914,9 @@ u16 ARM7Read16(u32 addr) case 0x04000000: switch (addr) { + case 0x04000004: return GPU2D::DispStat[1]; + case 0x04000006: return GPU2D::VCount; + case 0x04000100: return Timers[4].Counter; case 0x04000102: return Timers[4].Control; case 0x04000104: return Timers[5].Counter; @@ -778,6 +937,23 @@ u16 ARM7Read16(u32 addr) case 0x04000504: return _soundbias; } + + printf("unknown arm7 IO read16 %08X %08X\n", addr, ARM7->R[15]); + return 0; + + case 0x04800000: + // wifi shit + return 0; + + case 0x06000000: + case 0x06800000: + { + u32 chunk = (addr >> 17) & 0x1; + u8* vram = GPU2D::VRAM_ARM7[chunk]; + if (vram) + return *(u16*)&vram[addr & 0x3FFF]; + } + return 0; } printf("unknown arm7 read16 %08X %08X\n", addr, ARM7->R[15]); @@ -806,6 +982,8 @@ u32 ARM7Read32(u32 addr) case 0x04000000: switch (addr) { + case 0x04000004: return GPU2D::DispStat[1] | (GPU2D::VCount << 16); + case 0x04000100: return Timers[4].Counter | (Timers[4].Control << 16); case 0x04000104: return Timers[5].Counter | (Timers[5].Control << 16); case 0x04000108: return Timers[6].Counter | (Timers[6].Control << 16); @@ -821,6 +999,19 @@ u32 ARM7Read32(u32 addr) case 0x04000210: return IE[1]; case 0x04000214: return IF[1]; } + + printf("unknown arm7 IO read32 %08X | %08X\n", addr, ARM7->R[15]); + return 0; + + case 0x06000000: + case 0x06800000: + { + u32 chunk = (addr >> 17) & 0x1; + u8* vram = GPU2D::VRAM_ARM7[chunk]; + if (vram) + return *(u32*)&vram[addr & 0x3FFF]; + } + return 0; } if ((addr&0xFF000000) == 0xEA000000) Halt(); @@ -852,8 +1043,7 @@ void ARM7Write8(u32 addr, u8 val) return; case 0x04000301: - if (val != 0x80) return; - TriggerIRQ(1, IRQ_CartSendDone); // HAAAAXX!! + if (val == 0x80) ARM7->Halt(1); return; case 0x040001C2: @@ -862,10 +1052,22 @@ void ARM7Write8(u32 addr, u8 val) case 0x04000208: IME[1] = val; return; } + break; + + case 0x06000000: + case 0x06800000: + { + u32 chunk = (addr >> 17) & 0x1; + u8* vram = GPU2D::VRAM_ARM7[chunk]; + if (vram) + *(u8*)&vram[addr & 0x3FFF] = val; + } + return; } if (addr==0xA20) { + //TriggerIRQ(1, IRQ_CartSendDone); /*FILE* f = fopen("ram.bin", "wb"); fwrite(MainRAM, 0x400000, 1, f); fclose(f); @@ -900,6 +1102,8 @@ void ARM7Write16(u32 addr, u16 val) case 0x04000000: switch (addr) { + case 0x04000004: GPU2D::SetDispStat(1, val); return; + case 0x04000100: Timers[4].Reload = val; return; case 0x04000102: TimerStart(4, val); return; case 0x04000104: Timers[5].Reload = val; return; @@ -936,6 +1140,21 @@ void ARM7Write16(u32 addr, u16 val) _soundbias = val & 0x3FF; return; } + break; + + case 0x04800000: + // wifi shit + return; + + case 0x06000000: + case 0x06800000: + { + u32 chunk = (addr >> 17) & 0x1; + u8* vram = GPU2D::VRAM_ARM7[chunk]; + if (vram) + *(u16*)&vram[addr & 0x3FFF] = val; + } + return; } printf("unknown arm7 write16 %08X %04X | %08X\n", addr, val, ARM7->R[15]); @@ -978,10 +1197,25 @@ void ARM7Write32(u32 addr, u32 val) TimerStart(7, val>>16); return; + case 0x040001A4: + if (val & 0x80000000) TriggerIRQ(1, IRQ_CartSendDone); // HAX!!!! + return; + case 0x04000208: IME[1] = val; return; case 0x04000210: IE[1] = val; return; - case 0x04000214: IF[1] &= ~val; printf("IRQ ack %08X\n", val);return; + case 0x04000214: IF[1] &= ~val; return; } + return; + + case 0x06000000: + case 0x06800000: + { + u32 chunk = (addr >> 17) & 0x1; + u8* vram = GPU2D::VRAM_ARM7[chunk]; + if (vram) + *(u32*)&vram[addr & 0x3FFF] = val; + } + return; } printf("unknown arm7 write32 %08X %08X | %08X %08X\n", addr, val, ARM7->R[15], ARM7->CurInstr); diff --git a/SPI.cpp b/SPI.cpp index 562cf09..f8f1b6d 100644 --- a/SPI.cpp +++ b/SPI.cpp @@ -79,7 +79,7 @@ void Write(u8 val, u32 hold) Data = 0; DataPos = 1; Addr = 0; - printf("firmware SPI command %02X\n", CurCmd); + //printf("firmware SPI command %02X\n", CurCmd); return; } @@ -93,7 +93,7 @@ void Write(u8 val, u32 hold) Addr |= val; Data = 0; - if (DataPos == 3) printf("firmware SPI read %08X\n", Addr); + //if (DataPos == 3) printf("firmware SPI read %08X\n", Addr); } else { diff --git a/melonDS.depend b/melonDS.depend index a8a280b..b317bfe 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -1,38 +1,39 @@ # depslib dependency file v1.0 -1480007651 source:c:\documents\sources\melonds\main.cpp +1480957085 source:c:\documents\sources\melonds\main.cpp "NDS.h" -1480942921 c:\documents\sources\melonds\nds.h +1480975422 c:\documents\sources\melonds\nds.h "types.h" -1463409689 c:\documents\sources\melonds\types.h +1480957224 c:\documents\sources\melonds\types.h -1480953322 source:c:\documents\sources\melonds\nds.cpp +1480975347 source:c:\documents\sources\melonds\nds.cpp "NDS.h" "ARM.h" "CP15.h" + "GPU2D.h" "SPI.h" -1480953451 source:c:\documents\sources\melonds\arm.cpp +1480975148 source:c:\documents\sources\melonds\arm.cpp "NDS.h" "ARM.h" "ARMInterpreter.h" -1480951045 c:\documents\sources\melonds\arm.h +1480975035 c:\documents\sources\melonds\arm.h "types.h" "NDS.h" -1480954012 c:\documents\sources\melonds\arm_instrtable.h +1480965403 c:\documents\sources\melonds\arm_instrtable.h -1480725698 c:\documents\sources\melonds\arminterpreter.h +1480965273 c:\documents\sources\melonds\arminterpreter.h "types.h" "ARM.h" -1480952246 source:c:\documents\sources\melonds\arminterpreter.cpp +1480975549 source:c:\documents\sources\melonds\arminterpreter.cpp "NDS.h" "CP15.h" @@ -42,33 +43,42 @@ "ARMInterpreter_LoadStore.h" "ARM_InstrTable.h" -1480783605 c:\documents\sources\melonds\arminterpreter_branch.h +1480957205 c:\documents\sources\melonds\arminterpreter_branch.h -1480783825 source:c:\documents\sources\melonds\arminterpreter_branch.cpp +1480957179 source:c:\documents\sources\melonds\arminterpreter_branch.cpp "ARM.h" -1480784137 c:\documents\sources\melonds\arminterpreter_alu.h +1480965420 c:\documents\sources\melonds\arminterpreter_alu.h -1480952092 source:c:\documents\sources\melonds\arminterpreter_alu.cpp +1480966229 source:c:\documents\sources\melonds\arminterpreter_alu.cpp "ARM.h" -1480953933 c:\documents\sources\melonds\arminterpreter_loadstore.h +1480957165 c:\documents\sources\melonds\arminterpreter_loadstore.h -1480953916 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp +1480972662 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp "ARM.h" -1480776964 c:\documents\sources\melonds\cp15.h +1480957212 c:\documents\sources\melonds\cp15.h -1480950166 source:c:\documents\sources\melonds\cp15.cpp +1480975492 source:c:\documents\sources\melonds\cp15.cpp "NDS.h" + "ARM.h" -1480814622 c:\documents\sources\melonds\spi.h +1480957111 c:\documents\sources\melonds\spi.h -1480954747 source:c:\documents\sources\melonds\spi.cpp +1480973443 source:c:\documents\sources\melonds\spi.cpp "NDS.h" "SPI.h" +1480971901 source:c:\documents\sources\melonds\gpu2d.cpp + + + "NDS.h" + "GPU2D.h" + +1480970908 c:\documents\sources\melonds\gpu2d.h + -- cgit v1.2.3