diff options
-rw-r--r-- | ARM.cpp | 41 | ||||
-rw-r--r-- | ARM.h | 4 | ||||
-rw-r--r-- | ARMInterpreter.cpp | 18 | ||||
-rw-r--r-- | ARMInterpreter_ALU.cpp | 42 | ||||
-rw-r--r-- | ARMInterpreter_LoadStore.cpp | 40 | ||||
-rw-r--r-- | ARMInterpreter_LoadStore.h | 3 | ||||
-rw-r--r-- | ARM_InstrTable.h | 6 | ||||
-rw-r--r-- | CP15.cpp | 6 | ||||
-rw-r--r-- | NDS.cpp | 342 | ||||
-rw-r--r-- | NDS.h | 28 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | melonDS.depend | 22 |
12 files changed, 487 insertions, 74 deletions
@@ -38,6 +38,8 @@ ARM::~ARM() void ARM::Reset() { + Cycles = 0; + for (int i = 0; i < 16; i++) R[i] = 0; @@ -49,22 +51,25 @@ void ARM::Reset() JumpTo(ExceptionBase); } -void ARM::JumpTo(u32 addr) +void ARM::JumpTo(u32 addr, bool restorecpsr) { - // pipeline shit - - //printf("jump from %08X to %08X\n", R[15] - ((CPSR&0x20)?4:8), addr); + if (restorecpsr) + { + RestoreCPSR(); + if (CPSR & 0x20) addr |= 0x1; + else addr &= ~0x1; + } - if (addr&1) + if (addr & 0x1) { - addr &= ~1; + addr &= ~0x1; NextInstr = Read16(addr); R[15] = addr+2; CPSR |= 0x20; } else { - addr &= ~3; + addr &= ~0x3; NextInstr = Read32(addr); R[15] = addr+4; CPSR &= ~0x20; @@ -191,49 +196,57 @@ void ARM::TriggerIRQ() UpdateMode(oldcpsr, CPSR); R_IRQ[2] = oldcpsr; - R[14] = R[15];// - (oldcpsr & 0x20 ? 0 : 4); + R[14] = R[15] + (oldcpsr & 0x20 ? 2 : 0); JumpTo(ExceptionBase + 0x18); } s32 ARM::Execute(s32 cycles) { - while (cycles > 0) + s32 cyclesrun = 0; + + while (cyclesrun < cycles) { if (CPSR & 0x20) // THUMB { // prefetch CurInstr = NextInstr; NextInstr = Read16(R[15]); + //cyclesrun += MemWaitstate(0, R[15]); R[15] += 2; + Cycles = cyclesrun; + // actually execute u32 icode = (CurInstr >> 6); - cycles -= ARMInterpreter::THUMBInstrTable[icode](this); + cyclesrun += ARMInterpreter::THUMBInstrTable[icode](this); } else { // prefetch CurInstr = NextInstr; NextInstr = Read32(R[15]); + //cyclesrun += MemWaitstate(1, R[15]); R[15] += 4; + Cycles = cyclesrun; + // actually execute if (CheckCondition(CurInstr >> 28)) { u32 icode = ((CurInstr >> 4) & 0xF) | ((CurInstr >> 16) & 0xFF0); - cycles -= ARMInterpreter::ARMInstrTable[icode](this); + cyclesrun += ARMInterpreter::ARMInstrTable[icode](this); } else if ((CurInstr & 0xFE000000) == 0xFA000000) { - cycles -= ARMInterpreter::A_BLX_IMM(this); + cyclesrun += ARMInterpreter::A_BLX_IMM(this); } else { // not executing it. oh well - cycles -= 1; // 1S. todo: check + cyclesrun += 1; // 1S. todo: check } } } - return cycles; + return cyclesrun; } @@ -21,7 +21,7 @@ public: void Reset(); - void JumpTo(u32 addr); + void JumpTo(u32 addr, bool restorecpsr = false); void RestoreCPSR(); s32 Execute(s32 cycles); @@ -145,6 +145,8 @@ public: u32 Num; + s32 Cycles; + u32 R[16]; // heh u32 CPSR; u32 R_FIQ[8]; // holding SPSR too diff --git a/ARMInterpreter.cpp b/ARMInterpreter.cpp index 936c860..82ab3d5 100644 --- a/ARMInterpreter.cpp +++ b/ARMInterpreter.cpp @@ -172,6 +172,24 @@ s32 A_MRC(ARM* cpu) +s32 T_SVC(ARM* cpu) +{ + u32 oldcpsr = cpu->CPSR; + cpu->CPSR &= ~0xFF; + cpu->CPSR |= 0xD3; + cpu->UpdateMode(oldcpsr, cpu->CPSR); + + cpu->R_SVC[2] = oldcpsr; + cpu->R[14] = cpu->R[15] - 2; + cpu->JumpTo(cpu->ExceptionBase + 0x08); + + printf("SWI %02X\n", (cpu->CurInstr & 0xFF)); + + return C_S(2) + C_N(1); +} + + + #define INSTRFUNC_PROTO(x) s32 (*x)(ARM* cpu) #include "ARM_InstrTable.h" #undef INSTRFUNC_PROTO diff --git a/ARMInterpreter_ALU.cpp b/ARMInterpreter_ALU.cpp index eae671f..6555793 100644 --- a/ARMInterpreter_ALU.cpp +++ b/ARMInterpreter_ALU.cpp @@ -268,8 +268,7 @@ s32 A_##x##_REG_ROR_REG(ARM* cpu) \ !res); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -302,8 +301,7 @@ A_IMPLEMENT_ALU_OP(AND) !res); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -338,8 +336,7 @@ A_IMPLEMENT_ALU_OP(EOR) OVERFLOW_SUB(a, b, res)); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -374,8 +371,7 @@ A_IMPLEMENT_ALU_OP(SUB) OVERFLOW_SUB(b, a, res)); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -410,8 +406,7 @@ A_IMPLEMENT_ALU_OP(RSB) OVERFLOW_ADD(a, b, res)); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -448,8 +443,7 @@ A_IMPLEMENT_ALU_OP(ADD) OVERFLOW_ADD(a, b, res_tmp) | OVERFLOW_ADD(res_tmp, carry, res)); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -486,8 +480,7 @@ A_IMPLEMENT_ALU_OP(ADC) OVERFLOW_SUB(a, b, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -524,8 +517,7 @@ A_IMPLEMENT_ALU_OP(SBC) OVERFLOW_SUB(b, a, res_tmp) | OVERFLOW_SUB(res_tmp, carry, res)); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -602,8 +594,7 @@ A_IMPLEMENT_ALU_TEST(CMN) !res); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -632,8 +623,7 @@ A_IMPLEMENT_ALU_OP(ORR) !b); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(b); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(b, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -666,8 +656,7 @@ A_IMPLEMENT_ALU_OP(MOV) !res); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(res); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(res, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -698,8 +687,7 @@ A_IMPLEMENT_ALU_OP(BIC) !b); \ if (((cpu->CurInstr>>12) & 0xF) == 15) \ { \ - cpu->JumpTo(b); \ - cpu->RestoreCPSR(); \ + cpu->JumpTo(b, true); \ return C_S(2) + C_I(c) + C_N(1); \ } \ else \ @@ -1057,7 +1045,7 @@ s32 T_ADD_HIREG(ARM* cpu) if (rd == 15) { - cpu->JumpTo(a + b); + cpu->JumpTo((a + b) | 1); return C_S(2) + C_N(1); } else @@ -1090,7 +1078,7 @@ s32 T_MOV_HIREG(ARM* cpu) if (rd == 15) { - cpu->JumpTo(cpu->R[rs]); + cpu->JumpTo(cpu->R[rs] | 1); return C_S(2) + C_N(1); } else @@ -1103,7 +1091,7 @@ s32 T_MOV_HIREG(ARM* cpu) s32 T_ADD_PCREL(ARM* cpu) { - u32 val = cpu->R[15] = ~2; + u32 val = cpu->R[15] & ~2; val += ((cpu->CurInstr & 0xFF) << 2); cpu->R[(cpu->CurInstr >> 8) & 0x7] = val; return C_S(1); diff --git a/ARMInterpreter_LoadStore.cpp b/ARMInterpreter_LoadStore.cpp index 4a78186..c968920 100644 --- a/ARMInterpreter_LoadStore.cpp +++ b/ARMInterpreter_LoadStore.cpp @@ -196,7 +196,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) #define A_STRH \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ cpu->Write16(offset, cpu->R[(cpu->CurInstr>>12) & 0xF]); \ - if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ return C_N(2) + cpu->MemWaitstate(2, offset); #define A_STRH_POST \ @@ -225,7 +225,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) #define A_STRD \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ - if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ u32 r = (cpu->CurInstr>>12) & 0xF; \ cpu->Write32(offset , cpu->R[r ]); \ cpu->Write32(offset+4, cpu->R[r+1]); \ @@ -242,7 +242,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) #define A_LDRH \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ cpu->R[(cpu->CurInstr>>12) & 0xF] = cpu->Read16(offset); \ - if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ return C_N(2) + cpu->MemWaitstate(2, offset); #define A_LDRH_POST \ @@ -254,7 +254,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) #define A_LDRSB \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s8)cpu->Read8(offset); \ - if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ return C_N(2) + cpu->MemWaitstate(3, offset); #define A_LDRSB_POST \ @@ -266,7 +266,7 @@ A_IMPLEMENT_WB_LDRSTR(LDRB) #define A_LDRSH \ offset += cpu->R[(cpu->CurInstr>>16) & 0xF]; \ cpu->R[(cpu->CurInstr>>12) & 0xF] = (s32)(s16)cpu->Read16(offset); \ - if (cpu->CurInstr & (1<<24)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ + if (cpu->CurInstr & (1<<21)) cpu->R[(cpu->CurInstr>>16) & 0xF] = offset; \ return C_N(2) + cpu->MemWaitstate(2, offset); #define A_LDRSH_POST \ @@ -310,6 +310,33 @@ A_IMPLEMENT_HD_LDRSTR(LDRSH) +s32 A_SWP(ARM* cpu) +{ + u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF]; + + u32 val = cpu->Read32(base); + cpu->R[(cpu->CurInstr >> 12) & 0xF] = ROR(val, 8*(base&0x3)); + + cpu->Write32(base, cpu->R[cpu->CurInstr & 0xF]); + + // the 1S is a code cycle. TODO + return C_S(1) + C_N(2) + C_I(1) + 2*cpu->MemWaitstate(3, base); +} + +s32 A_SWPB(ARM* cpu) +{ + u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF]; + + cpu->R[(cpu->CurInstr >> 12) & 0xF] = cpu->Read8(base); + + cpu->Write8(base, cpu->R[cpu->CurInstr & 0xF]); + + // the 1S is a code cycle. TODO + return C_S(1) + C_N(2) + C_I(1) + 2*cpu->MemWaitstate(3, base); +} + + + s32 A_LDM(ARM* cpu) { u32 base = cpu->R[(cpu->CurInstr >> 16) & 0xF]; @@ -359,8 +386,7 @@ s32 A_LDM(ARM* cpu) if (cpu->Num == 1) pc &= ~0x1; - cpu->JumpTo(pc); - if (cpu->CurInstr & (1<<22)) cpu->RestoreCPSR(); + cpu->JumpTo(pc, cpu->CurInstr & (1<<22)); } if ((cpu->CurInstr & (1<<22)) && !(cpu->CurInstr & (1<<15))) diff --git a/ARMInterpreter_LoadStore.h b/ARMInterpreter_LoadStore.h index 4759d1f..773d1ba 100644 --- a/ARMInterpreter_LoadStore.h +++ b/ARMInterpreter_LoadStore.h @@ -40,6 +40,9 @@ A_PROTO_HD_LDRSTR(LDRSH) s32 A_LDM(ARM* cpu); s32 A_STM(ARM* cpu); +s32 A_SWP(ARM* cpu); +s32 A_SWPB(ARM* cpu); + s32 T_LDR_PCREL(ARM* cpu); diff --git a/ARM_InstrTable.h b/ARM_InstrTable.h index 03f7c3a..98d40fc 100644 --- a/ARM_InstrTable.h +++ b/ARM_InstrTable.h @@ -102,7 +102,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = // 0001 0000 0000 A_MRS, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_STRH_REG, + A_UNK, A_SWP, A_UNK, A_STRH_REG, A_UNK, A_LDRD_REG, A_UNK, A_STRD_REG, // 0001 0001 0000 @@ -126,7 +126,7 @@ INSTRFUNC_PROTO(ARMInstrTable[4096]) = // 0001 0100 0000 A_MRS, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, A_UNK, - A_UNK, A_UNK, A_UNK, A_STRH_IMM, + A_UNK, A_SWPB, A_UNK, A_STRH_IMM, A_UNK, A_LDRD_IMM, A_UNK, A_STRD_IMM, // 0001 0101 0000 @@ -1910,7 +1910,7 @@ INSTRFUNC_PROTO(THUMBInstrTable[1024]) = T_BCOND, T_BCOND, T_BCOND, T_BCOND, T_BCOND, T_BCOND, T_BCOND, T_BCOND, T_UNK, T_UNK, T_UNK, T_UNK, - T_UNK, T_UNK, T_UNK, T_UNK, + T_SVC, T_SVC, T_SVC, T_SVC, // 1110 0000 00 T_B, T_B, T_B, T_B, @@ -23,7 +23,7 @@ void UpdateDTCMSetting() if (Control & (1<<16)) { NDS::ARM9DTCMBase = DTCMSetting & 0xFFFFF000; - NDS::ARM9DTCMSize = 256 << (DTCMSetting & 0x3E); + NDS::ARM9DTCMSize = 0x200 << ((DTCMSetting >> 1) & 0x1F); printf("DTCM enabled at %08X, size %X\n", NDS::ARM9DTCMBase, NDS::ARM9DTCMSize); } else @@ -38,8 +38,8 @@ void UpdateITCMSetting() { if (Control & (1<<18)) { - NDS::ARM9ITCMSize = 256 << (DTCMSetting & 0x3E); - printf("ITCM enabled at %08X, size %X\n", 0, NDS::ARM9DTCMSize); + NDS::ARM9ITCMSize = 0x200 << ((ITCMSetting >> 1) & 0x1F); + printf("ITCM enabled at %08X, size %X\n", 0, NDS::ARM9ITCMSize); } else { @@ -9,10 +9,17 @@ namespace NDS { +SchedEvent SchedBuffer[SCHED_BUF_LEN]; +SchedEvent* SchedQueue; + +bool NeedReschedule; + ARM* ARM9; ARM* ARM7; s32 ARM9Cycles, ARM7Cycles; +s32 CompensatedCycles; +s32 SchedCycles; u8 ARM9BIOS[0x1000]; u8 ARM7BIOS[0x4000]; @@ -37,8 +44,12 @@ u32 ARM9DTCMBase, ARM9DTCMSize; u32 IME[2]; u32 IE[2], IF[2]; +Timer Timers[8]; + u16 IPCSync9, IPCSync7; +u16 _soundbias; // temp + bool Running; @@ -103,10 +114,18 @@ void Reset() ARM7->Reset(); CP15::Reset(); + memset(Timers, 0, 8*sizeof(Timer)); + SPI::Reset(); + memset(SchedBuffer, 0, sizeof(SchedEvent)*SCHED_BUF_LEN); + SchedQueue = NULL; + ARM9Cycles = 0; ARM7Cycles = 0; + SchedCycles = 0; + + _soundbias = 0; Running = true; // hax } @@ -116,15 +135,142 @@ void RunFrame() { s32 framecycles = 560190<<1; - // very gross and temp. loop + const s32 maxcycles = 16; while (Running && framecycles>0) { - ARM9Cycles = ARM9->Execute(32 + ARM9Cycles); - ARM7Cycles = ARM7->Execute(16 + ARM7Cycles); + //ARM9Cycles = ARM9->Execute(32 + ARM9Cycles); + //ARM7Cycles = ARM7->Execute(16 + ARM7Cycles); + + //framecycles -= 32; + s32 cyclestorun = maxcycles; + // TODO: scheduler integration here + + CompensatedCycles = ARM9Cycles; + s32 c9 = ARM9->Execute(cyclestorun - ARM9Cycles); + ARM9Cycles = c9 - cyclestorun; + c9 -= CompensatedCycles; + + s32 c7 = ARM7->Execute((c9 - ARM7Cycles) >> 1) << 1; + ARM7Cycles = c7 - c9; + + RunEvents(c9); + framecycles -= cyclestorun; + } +} + +SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param) +{ + // find a free entry + u32 entry = -1; + for (int i = 0; i < SCHED_BUF_LEN; i++) + { + if (SchedBuffer[i].Func == NULL) + { + entry = i; + break; + } + } + + if (entry == -1) + { + printf("!! SCHEDULER BUFFER FULL\n"); + return NULL; + } + + SchedEvent* evt = &SchedBuffer[entry]; + evt->Func = Func; + evt->Param = Param; + + SchedEvent* cur = SchedQueue; + SchedEvent* prev = NULL; + for (;;) + { + if (cur == NULL) break; + if (cur->Delay > Delay) break; + + Delay -= cur->Delay; + prev = cur; + cur = cur->NextEvent; + } + + // so, we found it. we insert our event before 'cur'. + evt->Delay = Delay; + + if (cur == NULL) + { + if (prev == NULL) + { + // list empty + SchedQueue = evt; + evt->PrevEvent = NULL; + evt->NextEvent = NULL; + } + else + { + // inserting at the end of the list + evt->PrevEvent = prev; + evt->NextEvent = NULL; + prev->NextEvent = evt; + } + } + else + { + evt->NextEvent = cur; + evt->PrevEvent = cur->PrevEvent; - framecycles -= 32; + if (evt->PrevEvent) + evt->PrevEvent->NextEvent = evt; + + cur->PrevEvent = evt; + cur->Delay -= evt->Delay; } + + return evt; +} + +void CancelEvent(SchedEvent* event) +{ + event->Func = NULL; + + // unlink + + if (event->PrevEvent) + event->PrevEvent->NextEvent = event->NextEvent; + else + SchedQueue = event->NextEvent; + + if (event->NextEvent) + event->NextEvent->PrevEvent = event->PrevEvent; +} + +void RunEvents(s32 cycles) +{ + SchedCycles += cycles; + + SchedEvent* evt = SchedQueue; + while (evt && evt->Delay <= SchedCycles) + { + evt->Func(evt->Param); + evt->Func = NULL; + SchedCycles -= evt->Delay; + + evt = evt->NextEvent; + } + + SchedQueue = evt; + if (evt) evt->PrevEvent = NULL; +} + +void CompensateARM7() +{ + s32 c9 = ARM9->Cycles - CompensatedCycles; + CompensatedCycles = ARM9->Cycles; + + s32 c7 = ARM7->Execute((c9 - ARM7Cycles) >> 1) << 1; + ARM7Cycles = c7 - c9; + + RunEvents(c9); } @@ -182,6 +328,73 @@ void TriggerIRQ(u32 cpu, u32 irq) +const s32 TimerPrescaler[4] = {2, 128, 512, 2048}; + +void TimerIncrement(u32 param) +{ + Timer* timer = &Timers[param]; + + u32 tid = param & 0x3; + u32 cpu = param >> 2; + + 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); + + if (timer->Counter == 0) + { + timer->Counter = timer->Reload; + + if (timer->Control & (1<<6)) + TriggerIRQ(cpu, IRQ_Timer0 + tid); + + // cascade + if (tid == 3) + break; + timer++; + if ((timer->Control & 0x84) != 0x84) + break; + tid++; + continue; + } + + break; + } +} + +void TimerStart(u32 id, u16 cnt) +{ + Timer* timer = &Timers[id]; + 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) + { + // start the timer, if it's not a cascading timer + if (!(cnt & (1<<2))) + { + timer->Counter = timer->Reload; + timer->Event = ScheduleEvent(TimerPrescaler[cnt&0x3], TimerIncrement, id); + } + else + timer->Event = NULL; + } + else if (curstart && !newstart) + { + if (timer->Event) + CancelEvent(timer->Event); + } +} + + + u8 ARM9Read8(u32 addr) { if ((addr & 0xFFFFF000) == 0xFFFF0000) @@ -245,6 +458,15 @@ u16 ARM9Read16(u32 addr) case 0x04000000: switch (addr) { + case 0x04000100: return Timers[0].Counter; + case 0x04000102: return Timers[0].Control; + case 0x04000104: return Timers[1].Counter; + case 0x04000106: return Timers[1].Control; + case 0x04000108: return Timers[2].Counter; + case 0x0400010A: return Timers[2].Control; + case 0x0400010C: return Timers[3].Counter; + case 0x0400010E: return Timers[3].Control; + case 0x04000180: return IPCSync9; } } @@ -268,6 +490,20 @@ u32 ARM9Read32(u32 addr) return *(u32*)&ARM9DTCM[(addr - ARM9DTCMBase) & 0x3FFF]; } + if (addr >= 0xFFFF1000) + { + Halt(); + /*FILE* f = fopen("ram.bin", "wb"); + fwrite(MainRAM, 0x400000, 1, f); + fclose(f); + fopen("wram.bin", "wb"); + fwrite(ARM7WRAM, 0x10000, 1, f); + fclose(f); + fopen("swram.bin", "wb"); + fwrite(ARM7WRAM, 0x8000, 1, f); + fclose(f);*/ + } + switch (addr & 0xFF000000) { case 0x02000000: @@ -280,13 +516,18 @@ u32 ARM9Read32(u32 addr) case 0x04000000: switch (addr) { + 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); + case 0x0400010C: return Timers[3].Counter | (Timers[3].Control << 16); + 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 %08X %08X\n", addr, ARM9->R[15], ARM9->R[12], ARM9Read32(0x027FF820)); return 0; } @@ -352,6 +593,15 @@ void ARM9Write16(u32 addr, u16 val) case 0x04000000: switch (addr) { + case 0x04000100: Timers[0].Reload = val; return; + case 0x04000102: TimerStart(0, val); return; + case 0x04000104: Timers[1].Reload = val; return; + case 0x04000106: TimerStart(1, val); return; + case 0x04000108: Timers[2].Reload = val; return; + case 0x0400010A: TimerStart(2, val); return; + case 0x0400010C: Timers[3].Reload = val; return; + case 0x0400010E: TimerStart(3, val); return; + case 0x04000180: IPCSync7 &= 0xFFF0; IPCSync7 |= ((val & 0x0F00) >> 8); @@ -361,6 +611,7 @@ void ARM9Write16(u32 addr, u16 val) { TriggerIRQ(1, IRQ_IPCSync); } + CompensateARM7(); return; } } @@ -394,6 +645,23 @@ void ARM9Write32(u32 addr, u32 val) case 0x04000000: switch (addr) { + case 0x04000100: + Timers[0].Reload = val & 0xFFFF; + TimerStart(0, val>>16); + return; + case 0x04000104: + Timers[1].Reload = val & 0xFFFF; + TimerStart(1, val>>16); + return; + case 0x04000108: + Timers[2].Reload = val & 0xFFFF; + TimerStart(2, val>>16); + return; + case 0x0400010C: + Timers[3].Reload = val & 0xFFFF; + TimerStart(3, val>>16); + return; + case 0x04000208: IME[0] = val; return; case 0x04000210: IE[0] = val; return; case 0x04000214: IF[0] &= ~val; return; @@ -462,14 +730,25 @@ u16 ARM7Read16(u32 addr) case 0x04000000: switch (addr) { + case 0x04000100: return Timers[4].Counter; + case 0x04000102: return Timers[4].Control; + case 0x04000104: return Timers[5].Counter; + case 0x04000106: return Timers[5].Control; + case 0x04000108: return Timers[6].Counter; + case 0x0400010A: return Timers[6].Control; + case 0x0400010C: return Timers[7].Counter; + case 0x0400010E: return Timers[7].Control; + case 0x04000180: return IPCSync7; case 0x040001C0: return SPI::ReadCnt(); case 0x040001C2: return SPI::ReadData(); + + case 0x04000504: return _soundbias; } } - printf("unknown arm7 read16 %08X\n", addr); + printf("unknown arm7 read16 %08X %08X\n", addr, ARM7->R[15]); return 0; } @@ -495,6 +774,11 @@ u32 ARM7Read32(u32 addr) case 0x04000000: switch (addr) { + 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); + case 0x0400010C: return Timers[7].Counter | (Timers[7].Control << 16); + case 0x040001A4: return 0x00800000; // hax @@ -507,6 +791,7 @@ u32 ARM7Read32(u32 addr) } } if ((addr&0xFF000000) == 0xEA000000) Halt(); + printf("unknown arm7 read32 %08X | %08X\n", addr, ARM7->R[15]); return 0; } @@ -545,6 +830,19 @@ void ARM7Write8(u32 addr, u8 val) } } + if (addr==0xA20) + { + /*FILE* f = fopen("ram.bin", "wb"); + fwrite(MainRAM, 0x400000, 1, f); + fclose(f); + fopen("wram.bin", "wb"); + fwrite(ARM7WRAM, 0x10000, 1, f); + fclose(f); + fopen("swram.bin", "wb"); + fwrite(ARM7WRAM, 0x8000, 1, f); + fclose(f);*/ + } + 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]); } @@ -568,6 +866,15 @@ void ARM7Write16(u32 addr, u16 val) case 0x04000000: switch (addr) { + case 0x04000100: Timers[4].Reload = val; return; + case 0x04000102: TimerStart(4, val); return; + case 0x04000104: Timers[5].Reload = val; return; + case 0x04000106: TimerStart(5, val); return; + case 0x04000108: Timers[6].Reload = val; return; + case 0x0400010A: TimerStart(6, val); return; + case 0x0400010C: Timers[7].Reload = val; return; + case 0x0400010E: TimerStart(7, val); return; + case 0x04000180: IPCSync9 &= 0xFFF0; IPCSync9 |= ((val & 0x0F00) >> 8); @@ -586,6 +893,10 @@ void ARM7Write16(u32 addr, u16 val) case 0x040001C2: SPI::WriteData(val & 0xFF); return; + + case 0x04000504: + _soundbias = val & 0x3FF; + return; } } @@ -612,13 +923,30 @@ void ARM7Write32(u32 addr, u32 val) case 0x04000000: switch (addr) { + case 0x04000100: + Timers[4].Reload = val & 0xFFFF; + TimerStart(4, val>>16); + return; + case 0x04000104: + Timers[5].Reload = val & 0xFFFF; + TimerStart(5, val>>16); + return; + case 0x04000108: + Timers[6].Reload = val & 0xFFFF; + TimerStart(6, val>>16); + return; + case 0x0400010C: + Timers[7].Reload = val & 0xFFFF; + TimerStart(7, val>>16); + 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; } } - printf("unknown arm7 write32 %08X %08X | %08X\n", addr, val, ARM7->R[15]); + printf("unknown arm7 write32 %08X %08X | %08X %08X\n", addr, val, ARM7->R[15], ARM7->CurInstr); } } @@ -7,6 +7,18 @@ namespace NDS { +#define SCHED_BUF_LEN 64 + +typedef struct _SchedEvent +{ + u32 Delay; + void (*Func)(u32); + u32 Param; + struct _SchedEvent* PrevEvent; + struct _SchedEvent* NextEvent; + +} SchedEvent; + enum { IRQ_VBlank = 0, @@ -36,6 +48,15 @@ enum IRQ_Wifi }; +typedef struct +{ + u16 Reload; + u16 Control; + u16 Counter; + SchedEvent* Event; + +} Timer; + extern u32 ARM9ITCMSize; extern u32 ARM9DTCMBase, ARM9DTCMSize; @@ -44,6 +65,13 @@ void Reset(); void RunFrame(); +SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param); +void CancelEvent(SchedEvent* event); +void RunEvents(s32 cycles); + +// DO NOT CALL FROM ARM7!! +void CompensateARM7(); + void Halt(); void MapSharedWRAM(); @@ -13,4 +13,11 @@ LOVE MELONS NO ASKING ROMZ!! ILLEGAL -license will eventually be GPL or some crap. don't steal the code and make money off of it or claim it as your own or be an asshole.
\ No newline at end of file +license will eventually be GPL or some crap. don't steal the code and make money off of it or claim it as your own or be an asshole. + + + +TODO LIST + + * take code fetch waitstates into account when fetching instructions, and during branches (pipeline shit) (tricky, some code fetches are nonsequential) + *
\ No newline at end of file diff --git a/melonDS.depend b/melonDS.depend index 3a5a4e0..c5e5ee3 100644 --- a/melonDS.depend +++ b/melonDS.depend @@ -3,12 +3,12 @@ <stdio.h> "NDS.h" -1480786846 c:\documents\sources\melonds\nds.h +1480942921 c:\documents\sources\melonds\nds.h "types.h" 1463409689 c:\documents\sources\melonds\types.h -1480816263 source:c:\documents\sources\melonds\nds.cpp +1480953322 source:c:\documents\sources\melonds\nds.cpp <stdio.h> <string.h> "NDS.h" @@ -16,23 +16,23 @@ "CP15.h" "SPI.h" -1480789789 source:c:\documents\sources\melonds\arm.cpp +1480953451 source:c:\documents\sources\melonds\arm.cpp <stdio.h> "NDS.h" "ARM.h" "ARMInterpreter.h" -1480786942 c:\documents\sources\melonds\arm.h +1480951045 c:\documents\sources\melonds\arm.h "types.h" "NDS.h" -1480785229 c:\documents\sources\melonds\arm_instrtable.h +1480954012 c:\documents\sources\melonds\arm_instrtable.h 1480725698 c:\documents\sources\melonds\arminterpreter.h "types.h" "ARM.h" -1480776855 source:c:\documents\sources\melonds\arminterpreter.cpp +1480952246 source:c:\documents\sources\melonds\arminterpreter.cpp <stdio.h> "NDS.h" "CP15.h" @@ -50,24 +50,24 @@ 1480784137 c:\documents\sources\melonds\arminterpreter_alu.h -1480784110 source:c:\documents\sources\melonds\arminterpreter_alu.cpp +1480952092 source:c:\documents\sources\melonds\arminterpreter_alu.cpp "ARM.h" -1480785175 c:\documents\sources\melonds\arminterpreter_loadstore.h +1480953933 c:\documents\sources\melonds\arminterpreter_loadstore.h -1480785158 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp +1480951014 source:c:\documents\sources\melonds\arminterpreter_loadstore.cpp <stdio.h> "ARM.h" 1480776964 c:\documents\sources\melonds\cp15.h -1480777799 source:c:\documents\sources\melonds\cp15.cpp +1480950166 source:c:\documents\sources\melonds\cp15.cpp <stdio.h> "NDS.h" 1480814622 c:\documents\sources\melonds\spi.h -1480816142 source:c:\documents\sources\melonds\spi.cpp +1480816963 source:c:\documents\sources\melonds\spi.cpp <stdio.h> "NDS.h" "SPI.h" |