diff options
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | src/ARM.cpp | 25 | ||||
| -rw-r--r-- | src/DMA.cpp | 13 | ||||
| -rw-r--r-- | src/GPU.cpp | 3 | ||||
| -rw-r--r-- | src/NDS.cpp | 130 | ||||
| -rw-r--r-- | src/NDS.h | 6 | ||||
| -rw-r--r-- | src/NDSCart.cpp | 6 | 
7 files changed, 95 insertions, 89 deletions
| @@ -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);      }  } @@ -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)      { |