aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/GPU.cpp60
-rw-r--r--src/GPU.h4
-rw-r--r--src/GPU2D.cpp12
-rw-r--r--src/NDS.cpp24
-rw-r--r--src/NDS.h2
-rw-r--r--src/wx/main.cpp6
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;
+}
+
}
diff --git a/src/GPU.h b/src/GPU.h
index 7009b86..4624495 100644
--- a/src/GPU.h
+++ b/src/GPU.h
@@ -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;
diff --git a/src/NDS.h b/src/NDS.h
index 84616d9..38f2b89 100644
--- a/src/NDS.h
+++ b/src/NDS.h
@@ -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();