Commit a56bf5c7 authored by StapleButter's avatar StapleButter
Browse files

make timers not suck. fixes issues (Worms2 intro FMV plays at the right speed,...

make timers not suck. fixes issues (Worms2 intro FMV plays at the right speed, aging cart tests get further...)
parent f38bc940
......@@ -40,7 +40,6 @@ TODO LIST
IMMEDIATE TODO LIST (prior release 1.0)
* UI
* make timers suck less
TODO LIST FOR LATER
......
......@@ -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)
......
......@@ -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--;
......
......@@ -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);
}
......
......@@ -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);
}
}
......
......@@ -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);
......
......@@ -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)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment