diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/GPU.cpp | 60 | ||||
| -rw-r--r-- | src/GPU.h | 4 | ||||
| -rw-r--r-- | src/GPU2D.cpp | 12 | ||||
| -rw-r--r-- | src/NDS.cpp | 24 | ||||
| -rw-r--r-- | src/NDS.h | 2 | ||||
| -rw-r--r-- | src/wx/main.cpp | 6 | 
6 files changed, 72 insertions, 36 deletions
diff --git a/src/GPU.cpp b/src/GPU.cpp index 680f08c..dcf61a6 100644 --- a/src/GPU.cpp +++ b/src/GPU.cpp @@ -30,6 +30,8 @@ namespace GPU  #define FRAME_CYCLES  (LINE_CYCLES * 263)  u16 VCount; +u32 NextVCount; +u16 TotalScanlines;  u16 DispStat[2], VMatch[2]; @@ -50,9 +52,6 @@ u8* VRAM[9] = {VRAM_A, VRAM_B, VRAM_C, VRAM_D, VRAM_E, VRAM_F, VRAM_G, VRAM_H, V  u8 VRAMCNT[9];  u8 VRAMSTAT; -//u32 VRAM_Base[9]; -//u32 VRAM_Mask[9]; -  u32 VRAMMap_LCDC;  u32 VRAMMap_ABG[0x20]; @@ -95,6 +94,8 @@ void DeInit()  void Reset()  {      VCount = 0; +    NextVCount = -1; +    TotalScanlines = 0;      DispStat[0] = 0;      DispStat[1] = 0; @@ -607,6 +608,7 @@ void DisplaySwap(u32 val)  void StartFrame()  { +    TotalScanlines = 0;      StartScanline(0);  } @@ -615,23 +617,37 @@ void StartHBlank(u32 line)      DispStat[0] |= (1<<1);      DispStat[1] |= (1<<1); -    if (line < 192) NDS::CheckDMAs(0, 0x02); +    if (VCount < 192) NDS::CheckDMAs(0, 0x02);      if (DispStat[0] & (1<<4)) NDS::SetIRQ(0, NDS::IRQ_HBlank);      if (DispStat[1] & (1<<4)) NDS::SetIRQ(1, NDS::IRQ_HBlank); -    if (line < 262) +    if (VCount < 262)          NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), StartScanline, line+1); +    else +        NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), FinishFrame, line+1); +} + +void FinishFrame(u32 lines) +{ +    TotalScanlines = lines;  }  void StartScanline(u32 line)  { -    VCount = line; +    if (line == 0) +        VCount = 0; +    else if (NextVCount != -1) +        VCount = NextVCount; +    else +        VCount++; + +    NextVCount = -1;      DispStat[0] &= ~(1<<1);      DispStat[1] &= ~(1<<1); -    if (line == VMatch[0]) +    if (VCount == VMatch[0])      {          DispStat[0] |= (1<<2); @@ -640,7 +656,7 @@ void StartScanline(u32 line)      else          DispStat[0] &= ~(1<<2); -    if (line == VMatch[1]) +    if (VCount == VMatch[1])      {          DispStat[1] |= (1<<2); @@ -649,12 +665,12 @@ void StartScanline(u32 line)      else          DispStat[1] &= ~(1<<2); -    GPU2D_A->CheckWindows(line); -    GPU2D_B->CheckWindows(line); +    GPU2D_A->CheckWindows(VCount); +    GPU2D_B->CheckWindows(VCount); -    if (line >= 2 && line < 194) +    if (VCount >= 2 && VCount < 194)          NDS::CheckDMAs(0, 0x03); -    else if (line == 194) +    else if (VCount == 194)          NDS::StopDMAs(0, 0x03);      if (line < 192) @@ -664,7 +680,8 @@ void StartScanline(u32 line)          // properly would be too much trouble given barely anything          // uses FIFO display          // (TODO, eventually: emulate it properly) -        NDS::CheckDMAs(0, 0x04); +        if (VCount < 192) +            NDS::CheckDMAs(0, 0x04);          if (line == 0)          { @@ -676,7 +693,8 @@ void StartScanline(u32 line)          GPU2D_A->DrawScanline(line);          GPU2D_B->DrawScanline(line);      } -    else if (line == 262) + +    if (VCount == 262)      {          // frame end @@ -685,7 +703,7 @@ void StartScanline(u32 line)      }      else      { -        if (line == 192) +        if (VCount == 192)          {              // VBlank              DispStat[0] |= (1<<0); @@ -703,7 +721,7 @@ void StartScanline(u32 line)              GPU2D_B->VBlank();              GPU3D::VBlank();          } -        else if (line == 215) +        else if (VCount == 215)          {              GPU3D::VCount215();          } @@ -722,4 +740,14 @@ void SetDispStat(u32 cpu, u16 val)      VMatch[cpu] = (val >> 8) | ((val & 0x80) << 1);  } +void SetVCount(u16 val) +{ +    // VCount write is delayed until the next scanline + +    // TODO: how does the 3D engine react to VCount writes while it's rendering? +    // TODO: also check the various DMA types that can be involved + +    NextVCount = val; +} +  } @@ -26,6 +26,7 @@ namespace GPU  {  extern u16 VCount; +extern u16 TotalScanlines;  extern u16 DispStat[2]; @@ -385,10 +386,13 @@ T ReadVRAM_TexPal(u32 addr)  void DisplaySwap(u32 val);  void StartFrame(); +void FinishFrame(u32 lines);  void StartScanline(u32 line);  void SetDispStat(u32 cpu, u16 val); +void SetVCount(u16 val); +  }  #endif diff --git a/src/GPU2D.cpp b/src/GPU2D.cpp index 77b79b4..0b3afd0 100644 --- a/src/GPU2D.cpp +++ b/src/GPU2D.cpp @@ -380,6 +380,18 @@ void GPU2D::DrawScanline(u32 line)  {      u32* dst = &Framebuffer[256*line]; +    line = GPU::VCount; + +    // scanlines that end up outside of the GPU drawing range +    // (as a result of writing to VCount) are filled white +    if (line > 192) +    { +        for (int i = 0; i < 256; i++) +            dst[i] = 0xFF3F3F3F; + +        return; +    } +      u32 dispmode = DispCnt >> 16;      dispmode &= (Num ? 0x1 : 0x3); diff --git a/src/NDS.cpp b/src/NDS.cpp index 4ad325b..ddd6c03 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -380,16 +380,16 @@ void RunSystem(s32 cycles)      }  } -void RunFrame() +u32 RunFrame()  {      s32 framecycles = 560190; -    if (!Running) return; // dorp +    if (!Running) return 263; // dorp      GPU::StartFrame(); -    while (Running && framecycles>0) +    while (Running && GPU::TotalScanlines==0)      {          s32 ndscyclestorun;          s32 ndscycles = 0; @@ -430,21 +430,9 @@ void RunFrame()          RunSystem(ndscyclestorun);          //GPU3D::Run(ndscyclestorun); - -        /*while (ndscycles < ndscyclestorun) -        { -            ARM7->CyclesToRun = ndscyclestorun - ndscycles - ARM7Offset; -            ARM7->Execute(); -            ARM7Offset = 0; - -            RunEvents(ARM7->Cycles); -            ndscycles += ARM7->Cycles; -        } - -        ARM7Offset = ndscycles - ndscyclestorun;*/ - -        framecycles -= ndscyclestorun;      } + +    return GPU::TotalScanlines;  }  void Reschedule() @@ -1657,6 +1645,7 @@ void ARM9IOWrite16(u32 addr, u16 val)      switch (addr)      {      case 0x04000004: GPU::SetDispStat(0, val); return; +    case 0x04000006: GPU::SetVCount(val); return;      case 0x04000060: GPU3D::Write16(addr, val); return; @@ -2198,6 +2187,7 @@ void ARM7IOWrite16(u32 addr, u16 val)      switch (addr)      {      case 0x04000004: GPU::SetDispStat(1, val); return; +    case 0x04000006: GPU::SetVCount(val); return;      case 0x040000B8: DMAs[4]->WriteCnt((DMAs[4]->Cnt & 0xFFFF0000) | val); return;      case 0x040000BA: DMAs[4]->WriteCnt((DMAs[4]->Cnt & 0x0000FFFF) | (val << 16)); return; @@ -104,7 +104,7 @@ void LoadROM(const char* path, bool direct);  void LoadBIOS();  void SetupDirectBoot(); -void RunFrame(); +u32 RunFrame();  void PressKey(u32 key);  void ReleaseKey(u32 key); diff --git a/src/wx/main.cpp b/src/wx/main.cpp index 9864382..e07d3c9 100644 --- a/src/wx/main.cpp +++ b/src/wx/main.cpp @@ -386,7 +386,7 @@ wxThread::ExitCode EmuThread::Entry()          if (emustatus == 1)          { -            NDS::RunFrame(); +            u32 nlines = NDS::RunFrame();              SDL_LockTexture(sdltex, NULL, &texpixels, &texstride);              if (texstride == 256*4) @@ -410,7 +410,9 @@ wxThread::ExitCode EmuThread::Entry()              SDL_RenderPresent(sdlrend);              // framerate limiter based off SDL2_gfx -            float framerate = 1000.0f / 60.0f; +            float framerate; +            if (nlines == 263) framerate = 1000.0f / 60.0f; +            else               framerate = 1000.0f / ((60.0f * nlines) / 263.0f);              fpslimitcount++;              u32 curtick = SDL_GetTicks();  |