aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--src/ARM.cpp25
-rw-r--r--src/DMA.cpp13
-rw-r--r--src/GPU.cpp3
-rw-r--r--src/NDS.cpp130
-rw-r--r--src/NDS.h6
-rw-r--r--src/NDSCart.cpp6
7 files changed, 95 insertions, 89 deletions
diff --git a/README.md b/README.md
index 5cdfb28..c50a884 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,6 @@ TODO LIST
IMMEDIATE TODO LIST (prior release 1.0)
* UI
- * make timers suck less
TODO LIST FOR LATER
diff --git a/src/ARM.cpp b/src/ARM.cpp
index 536c78c..382f56e 100644
--- a/src/ARM.cpp
+++ b/src/ARM.cpp
@@ -20,7 +20,6 @@
#include "NDS.h"
#include "ARM.h"
#include "ARMInterpreter.h"
-#include "GPU3D.h"
u32 ARM::ConditionTable[16] =
@@ -328,20 +327,19 @@ s32 ARM::Execute()
else
{
Cycles = CyclesToRun;
- GPU3D::Run(CyclesToRun >> 1);
+
+ if (Num == 0) NDS::RunTimingCriticalDevices(0, CyclesToRun >> 1);
+ else NDS::RunTimingCriticalDevices(1, CyclesToRun);
+
return Cycles;
}
}
Cycles = 0;
s32 lastcycles = 0;
- u32 addr = R[15] - (CPSR&0x20 ? 4:8);
- u32 cpsr = CPSR;
while (Cycles < CyclesToRun)
{
- //if(Num==1)printf("%08X %08X\n", R[15] - (CPSR&0x20 ? 4:8), NextInstr);
-
if (CPSR & 0x20) // THUMB
{
// prefetch
@@ -376,15 +374,18 @@ s32 ARM::Execute()
//if (R[15]==0x037F9364) printf("R8=%08X R9=%08X\n", R[8], R[9]);
- // gross hack
- // TODO, though: move timer code here too?
- // quick testing shows that moving this to the NDS loop doesn't really slow things down
if (Num==0)
{
s32 diff = Cycles - lastcycles;
- GPU3D::Run(diff >> 1);
+ NDS::RunTimingCriticalDevices(0, diff >> 1);
lastcycles = Cycles - (diff&1);
}
+ else
+ {
+ s32 diff = Cycles - lastcycles;
+ NDS::RunTimingCriticalDevices(1, diff);
+ lastcycles = Cycles;
+ }
// TODO optimize this shit!!!
if (Halted)
@@ -398,10 +399,6 @@ s32 ARM::Execute()
if (NDS::IME[Num]&1)
TriggerIRQ();
}
-
- // temp. debug cruft
- addr = R[15] - (CPSR&0x20 ? 4:8);
- cpsr = CPSR;
}
if (Halted == 2)
diff --git a/src/DMA.cpp b/src/DMA.cpp
index b3e4f2f..5a7ca1c 100644
--- a/src/DMA.cpp
+++ b/src/DMA.cpp
@@ -26,7 +26,6 @@
// NOTES ON DMA SHIT
//
// * could use optimized code paths for common types of DMA transfers. for example, VRAM
-// * needs to eventually be made more accurate anyway. DMA isn't instant.
DMA::DMA(u32 cpu, u32 num)
@@ -154,7 +153,7 @@ void DMA::WriteCnt(u32 val)
else if (StartMode == 0x07)
GPU3D::CheckFIFODMA();
- if ((StartMode&7)!=0x00 && (StartMode&7)!=0x1 && StartMode!=2 && StartMode!=0x05 && StartMode!=0x12 && StartMode!=0x07)
+ if (StartMode==0x04 || StartMode==0x06 || StartMode==0x13)
printf("UNIMPLEMENTED ARM%d DMA%d START MODE %02X\n", CPU?7:9, Num, StartMode);
}
}
@@ -215,7 +214,10 @@ s32 DMA::Run(s32 cycles)
{
writefn(CurDstAddr, readfn(CurSrcAddr));
- cycles -= (Waitstates[0][(CurSrcAddr >> 24) & 0xF] + Waitstates[0][(CurDstAddr >> 24) & 0xF]);
+ s32 c = (Waitstates[0][(CurSrcAddr >> 24) & 0xF] + Waitstates[0][(CurDstAddr >> 24) & 0xF]);
+ cycles -= c;
+ NDS::RunTimingCriticalDevices(CPU, c);
+
CurSrcAddr += SrcAddrInc<<1;
CurDstAddr += DstAddrInc<<1;
IterCount--;
@@ -231,7 +233,10 @@ s32 DMA::Run(s32 cycles)
{
writefn(CurDstAddr, readfn(CurSrcAddr));
- cycles -= (Waitstates[1][(CurSrcAddr >> 24) & 0xF] + Waitstates[1][(CurDstAddr >> 24) & 0xF]);
+ s32 c = (Waitstates[1][(CurSrcAddr >> 24) & 0xF] + Waitstates[1][(CurDstAddr >> 24) & 0xF]);
+ cycles -= c;
+ NDS::RunTimingCriticalDevices(CPU, c);
+
CurSrcAddr += SrcAddrInc<<2;
CurDstAddr += DstAddrInc<<2;
IterCount--;
diff --git a/src/GPU.cpp b/src/GPU.cpp
index 28c5d24..aaef43f 100644
--- a/src/GPU.cpp
+++ b/src/GPU.cpp
@@ -716,6 +716,9 @@ void StartScanline(u32 line)
//NDS::ScheduleEvent(NDS::Event_LCD, true, LINE_CYCLES, StartScanline, line+1);
}
+ // checkme
+ if (line == 0) NDS::CheckDMAs(0, 0x03);
+
NDS::ScheduleEvent(NDS::Event_LCD, true, HBLANK_CYCLES, StartHBlank, line);
}
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 52a1de0..3ab543e 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -333,17 +333,6 @@ void CalcIterationCycles()
void RunSystem(s32 cycles)
{
- for (int i = 0; i < 8; i++)
- {
- if ((Timers[i].Cnt & 0x84) == 0x80)
- Timers[i].Counter += (ARM9->Cycles >> 1) << Timers[i].CycleShift;
- }
- for (int i = 4; i < 8; i++)
- {
- if ((Timers[i].Cnt & 0x84) == 0x80)
- Timers[i].Counter += ARM7->Cycles << Timers[i].CycleShift;
- }
-
for (int i = 0; i < Event_MAX; i++)
{
if (!(SchedListMask & (1<<i)))
@@ -382,9 +371,6 @@ void RunFrame()
if (cycles > 0) cycles = DMAs[2]->Run(cycles);
if (cycles > 0) cycles = DMAs[3]->Run(cycles);
ndscyclestorun = CurIterationCycles - cycles;
-
- // TODO: run other timing critical shit, like timers
- GPU3D::Run(ndscyclestorun);
}
else
{
@@ -567,6 +553,66 @@ void ResumeCPU(u32 cpu, u32 mask)
+void HandleTimerOverflow(u32 tid)
+{
+ Timer* timer = &Timers[tid];
+
+ timer->Counter += timer->Reload << 16;
+ if (timer->Cnt & (1<<6))
+ SetIRQ(tid >> 2, IRQ_Timer0 + (tid & 0x3));
+
+ if ((tid & 0x3) == 3)
+ return;
+
+ for (;;)
+ {
+ tid++;
+
+ timer = &Timers[tid];
+
+ if ((timer->Cnt & 0x84) != 0x84)
+ break;
+
+ timer->Counter += 0x10000;
+ if (timer->Counter >> 16)
+ break;
+
+ timer->Counter = timer->Reload << 16;
+ if (timer->Cnt & (1<<6))
+ SetIRQ(tid >> 2, IRQ_Timer0 + (tid & 0x3));
+
+ if ((tid & 0x3) == 3)
+ break;
+ }
+}
+
+void RunTimer(u32 tid, s32 cycles)
+{
+ Timer* timer = &Timers[tid];
+ if ((timer->Cnt & 0x84) != 0x80)
+ return;
+
+ u32 oldcount = timer->Counter;
+ timer->Counter += (cycles << timer->CycleShift);
+ if (timer->Counter < oldcount)
+ HandleTimerOverflow(tid);
+}
+
+void RunTimingCriticalDevices(u32 cpu, s32 cycles)
+{
+ RunTimer((cpu<<2)+0, cycles);
+ RunTimer((cpu<<2)+1, cycles);
+ RunTimer((cpu<<2)+2, cycles);
+ RunTimer((cpu<<2)+3, cycles);
+
+ if (cpu == 0)
+ {
+ GPU3D::Run(cycles);
+ }
+}
+
+
+
void CheckDMAs(u32 cpu, u32 mode)
{
cpu <<= 2;
@@ -578,58 +624,16 @@ void CheckDMAs(u32 cpu, u32 mode)
-//const s32 TimerPrescaler[4] = {1, 64, 256, 1024};
+
const s32 TimerPrescaler[4] = {0, 6, 8, 10};
u16 TimerGetCounter(u32 timer)
{
u32 ret = Timers[timer].Counter;
- if ((Timers[timer].Cnt & 0x84) == 0x80)
- {
- u32 c = (timer & 0x4) ? ARM7->Cycles : (ARM9->Cycles>>1);
- ret += (c << Timers[timer].CycleShift);
- }
-
return ret >> 16;
}
-void TimerOverflow(u32 param)
-{
- Timer* timer = &Timers[param];
- timer->Counter = 0;
-
- u32 tid = param & 0x3;
- u32 cpu = param >> 2;
-
- for (;;)
- {
- if (tid == (param&0x3))
- ScheduleEvent(Event_Timer9_0 + param, true, (0x10000 - timer->Reload) << TimerPrescaler[timer->Cnt & 0x03], TimerOverflow, param);
- //timer->Event = ScheduleEvent(TimerPrescaler[timer->Control&0x3], TimerIncrement, param);
-
- if (timer->Counter == 0)
- {
- timer->Counter = timer->Reload << 16;
-
- if (timer->Cnt & (1<<6))
- SetIRQ(cpu, IRQ_Timer0 + tid);
-
- // cascade
- if (tid == 3)
- break;
- timer++;
- if ((timer->Cnt & 0x84) != 0x84)
- break;
- timer->Counter += 0x10000;
- tid++;
- continue;
- }
-
- break;
- }
-}
-
void TimerStart(u32 id, u16 cnt)
{
Timer* timer = &Timers[id];
@@ -637,21 +641,11 @@ void TimerStart(u32 id, u16 cnt)
u16 newstart = cnt & (1<<7);
timer->Cnt = cnt;
+ timer->CycleShift = 16 - TimerPrescaler[cnt & 0x03];
if ((!curstart) && newstart)
{
timer->Counter = timer->Reload << 16;
- timer->CycleShift = 16 - TimerPrescaler[cnt & 0x03];
-
- // start the timer, if it's not a cascading timer
- if (!(cnt & (1<<2)))
- ScheduleEvent(Event_Timer9_0 + id, false, (0x10000 - timer->Reload) << TimerPrescaler[cnt & 0x03], TimerOverflow, id);
- else
- CancelEvent(Event_Timer9_0 + id);
- }
- else if (curstart && (!newstart))
- {
- CancelEvent(Event_Timer9_0 + id);
}
}
diff --git a/src/NDS.h b/src/NDS.h
index 976bd26..28f777e 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -40,14 +40,14 @@ enum
{
Event_LCD = 0,
- Event_Timer9_0,
+ /*Event_Timer9_0,
Event_Timer9_1,
Event_Timer9_2,
Event_Timer9_3,
Event_Timer7_0,
Event_Timer7_1,
Event_Timer7_2,
- Event_Timer7_3,
+ Event_Timer7_3,*/
Event_MAX
};
@@ -149,6 +149,8 @@ void ResumeCPU(u32 cpu, u32 mask);
void CheckDMAs(u32 cpu, u32 mode);
+void RunTimingCriticalDevices(u32 cpu, s32 cycles);
+
u8 ARM9Read8(u32 addr);
u16 ARM9Read16(u32 addr);
u32 ARM9Read32(u32 addr);
diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp
index 16e8435..29da046 100644
--- a/src/NDSCart.cpp
+++ b/src/NDSCart.cpp
@@ -565,11 +565,15 @@ bool Init()
{
if (!NDSCart_SRAM::Init()) return false;
+ CartROM = NULL;
+
return true;
}
void DeInit()
{
+ if (CartROM) delete[] CartROM;
+
NDSCart_SRAM::DeInit();
}
@@ -606,6 +610,8 @@ bool LoadROM(const char* path, bool direct)
// TODO: streaming mode? for really big ROMs or systems with limited RAM
// for now we're lazy
+ if (CartROM) delete[] CartROM;
+
FILE* f = fopen(path, "rb");
if (!f)
{