add support for writing to VCount. incl. fucked-up display and altering framerate accordingly.
This commit is contained in:
parent
63e15d2480
commit
f54f54fb7e
60
src/GPU.cpp
60
src/GPU.cpp
|
@ -30,6 +30,8 @@ namespace GPU
|
||||||
#define FRAME_CYCLES (LINE_CYCLES * 263)
|
#define FRAME_CYCLES (LINE_CYCLES * 263)
|
||||||
|
|
||||||
u16 VCount;
|
u16 VCount;
|
||||||
|
u32 NextVCount;
|
||||||
|
u16 TotalScanlines;
|
||||||
|
|
||||||
u16 DispStat[2], VMatch[2];
|
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 VRAMCNT[9];
|
||||||
u8 VRAMSTAT;
|
u8 VRAMSTAT;
|
||||||
|
|
||||||
//u32 VRAM_Base[9];
|
|
||||||
//u32 VRAM_Mask[9];
|
|
||||||
|
|
||||||
u32 VRAMMap_LCDC;
|
u32 VRAMMap_LCDC;
|
||||||
|
|
||||||
u32 VRAMMap_ABG[0x20];
|
u32 VRAMMap_ABG[0x20];
|
||||||
|
@ -95,6 +94,8 @@ void DeInit()
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
VCount = 0;
|
VCount = 0;
|
||||||
|
NextVCount = -1;
|
||||||
|
TotalScanlines = 0;
|
||||||
|
|
||||||
DispStat[0] = 0;
|
DispStat[0] = 0;
|
||||||
DispStat[1] = 0;
|
DispStat[1] = 0;
|
||||||
|
@ -607,6 +608,7 @@ void DisplaySwap(u32 val)
|
||||||
|
|
||||||
void StartFrame()
|
void StartFrame()
|
||||||
{
|
{
|
||||||
|
TotalScanlines = 0;
|
||||||
StartScanline(0);
|
StartScanline(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -615,23 +617,37 @@ void StartHBlank(u32 line)
|
||||||
DispStat[0] |= (1<<1);
|
DispStat[0] |= (1<<1);
|
||||||
DispStat[1] |= (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[0] & (1<<4)) NDS::SetIRQ(0, NDS::IRQ_HBlank);
|
||||||
if (DispStat[1] & (1<<4)) NDS::SetIRQ(1, 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);
|
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)
|
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[0] &= ~(1<<1);
|
||||||
DispStat[1] &= ~(1<<1);
|
DispStat[1] &= ~(1<<1);
|
||||||
|
|
||||||
if (line == VMatch[0])
|
if (VCount == VMatch[0])
|
||||||
{
|
{
|
||||||
DispStat[0] |= (1<<2);
|
DispStat[0] |= (1<<2);
|
||||||
|
|
||||||
|
@ -640,7 +656,7 @@ void StartScanline(u32 line)
|
||||||
else
|
else
|
||||||
DispStat[0] &= ~(1<<2);
|
DispStat[0] &= ~(1<<2);
|
||||||
|
|
||||||
if (line == VMatch[1])
|
if (VCount == VMatch[1])
|
||||||
{
|
{
|
||||||
DispStat[1] |= (1<<2);
|
DispStat[1] |= (1<<2);
|
||||||
|
|
||||||
|
@ -649,12 +665,12 @@ void StartScanline(u32 line)
|
||||||
else
|
else
|
||||||
DispStat[1] &= ~(1<<2);
|
DispStat[1] &= ~(1<<2);
|
||||||
|
|
||||||
GPU2D_A->CheckWindows(line);
|
GPU2D_A->CheckWindows(VCount);
|
||||||
GPU2D_B->CheckWindows(line);
|
GPU2D_B->CheckWindows(VCount);
|
||||||
|
|
||||||
if (line >= 2 && line < 194)
|
if (VCount >= 2 && VCount < 194)
|
||||||
NDS::CheckDMAs(0, 0x03);
|
NDS::CheckDMAs(0, 0x03);
|
||||||
else if (line == 194)
|
else if (VCount == 194)
|
||||||
NDS::StopDMAs(0, 0x03);
|
NDS::StopDMAs(0, 0x03);
|
||||||
|
|
||||||
if (line < 192)
|
if (line < 192)
|
||||||
|
@ -664,7 +680,8 @@ void StartScanline(u32 line)
|
||||||
// properly would be too much trouble given barely anything
|
// properly would be too much trouble given barely anything
|
||||||
// uses FIFO display
|
// uses FIFO display
|
||||||
// (TODO, eventually: emulate it properly)
|
// (TODO, eventually: emulate it properly)
|
||||||
NDS::CheckDMAs(0, 0x04);
|
if (VCount < 192)
|
||||||
|
NDS::CheckDMAs(0, 0x04);
|
||||||
|
|
||||||
if (line == 0)
|
if (line == 0)
|
||||||
{
|
{
|
||||||
|
@ -676,7 +693,8 @@ void StartScanline(u32 line)
|
||||||
GPU2D_A->DrawScanline(line);
|
GPU2D_A->DrawScanline(line);
|
||||||
GPU2D_B->DrawScanline(line);
|
GPU2D_B->DrawScanline(line);
|
||||||
}
|
}
|
||||||
else if (line == 262)
|
|
||||||
|
if (VCount == 262)
|
||||||
{
|
{
|
||||||
// frame end
|
// frame end
|
||||||
|
|
||||||
|
@ -685,7 +703,7 @@ void StartScanline(u32 line)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (line == 192)
|
if (VCount == 192)
|
||||||
{
|
{
|
||||||
// VBlank
|
// VBlank
|
||||||
DispStat[0] |= (1<<0);
|
DispStat[0] |= (1<<0);
|
||||||
|
@ -703,7 +721,7 @@ void StartScanline(u32 line)
|
||||||
GPU2D_B->VBlank();
|
GPU2D_B->VBlank();
|
||||||
GPU3D::VBlank();
|
GPU3D::VBlank();
|
||||||
}
|
}
|
||||||
else if (line == 215)
|
else if (VCount == 215)
|
||||||
{
|
{
|
||||||
GPU3D::VCount215();
|
GPU3D::VCount215();
|
||||||
}
|
}
|
||||||
|
@ -722,4 +740,14 @@ void SetDispStat(u32 cpu, u16 val)
|
||||||
VMatch[cpu] = (val >> 8) | ((val & 0x80) << 1);
|
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 VCount;
|
||||||
|
extern u16 TotalScanlines;
|
||||||
|
|
||||||
extern u16 DispStat[2];
|
extern u16 DispStat[2];
|
||||||
|
|
||||||
|
@ -385,10 +386,13 @@ T ReadVRAM_TexPal(u32 addr)
|
||||||
void DisplaySwap(u32 val);
|
void DisplaySwap(u32 val);
|
||||||
|
|
||||||
void StartFrame();
|
void StartFrame();
|
||||||
|
void FinishFrame(u32 lines);
|
||||||
void StartScanline(u32 line);
|
void StartScanline(u32 line);
|
||||||
|
|
||||||
void SetDispStat(u32 cpu, u16 val);
|
void SetDispStat(u32 cpu, u16 val);
|
||||||
|
|
||||||
|
void SetVCount(u16 val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -380,6 +380,18 @@ void GPU2D::DrawScanline(u32 line)
|
||||||
{
|
{
|
||||||
u32* dst = &Framebuffer[256*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;
|
u32 dispmode = DispCnt >> 16;
|
||||||
dispmode &= (Num ? 0x1 : 0x3);
|
dispmode &= (Num ? 0x1 : 0x3);
|
||||||
|
|
||||||
|
|
24
src/NDS.cpp
24
src/NDS.cpp
|
@ -380,16 +380,16 @@ void RunSystem(s32 cycles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunFrame()
|
u32 RunFrame()
|
||||||
{
|
{
|
||||||
s32 framecycles = 560190;
|
s32 framecycles = 560190;
|
||||||
|
|
||||||
if (!Running) return; // dorp
|
if (!Running) return 263; // dorp
|
||||||
|
|
||||||
|
|
||||||
GPU::StartFrame();
|
GPU::StartFrame();
|
||||||
|
|
||||||
while (Running && framecycles>0)
|
while (Running && GPU::TotalScanlines==0)
|
||||||
{
|
{
|
||||||
s32 ndscyclestorun;
|
s32 ndscyclestorun;
|
||||||
s32 ndscycles = 0;
|
s32 ndscycles = 0;
|
||||||
|
@ -430,21 +430,9 @@ void RunFrame()
|
||||||
|
|
||||||
RunSystem(ndscyclestorun);
|
RunSystem(ndscyclestorun);
|
||||||
//GPU3D::Run(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()
|
void Reschedule()
|
||||||
|
@ -1657,6 +1645,7 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04000004: GPU::SetDispStat(0, val); return;
|
case 0x04000004: GPU::SetDispStat(0, val); return;
|
||||||
|
case 0x04000006: GPU::SetVCount(val); return;
|
||||||
|
|
||||||
case 0x04000060: GPU3D::Write16(addr, val); return;
|
case 0x04000060: GPU3D::Write16(addr, val); return;
|
||||||
|
|
||||||
|
@ -2198,6 +2187,7 @@ void ARM7IOWrite16(u32 addr, u16 val)
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x04000004: GPU::SetDispStat(1, val); return;
|
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 0x040000B8: DMAs[4]->WriteCnt((DMAs[4]->Cnt & 0xFFFF0000) | val); return;
|
||||||
case 0x040000BA: DMAs[4]->WriteCnt((DMAs[4]->Cnt & 0x0000FFFF) | (val << 16)); 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 LoadBIOS();
|
||||||
void SetupDirectBoot();
|
void SetupDirectBoot();
|
||||||
|
|
||||||
void RunFrame();
|
u32 RunFrame();
|
||||||
|
|
||||||
void PressKey(u32 key);
|
void PressKey(u32 key);
|
||||||
void ReleaseKey(u32 key);
|
void ReleaseKey(u32 key);
|
||||||
|
|
|
@ -386,7 +386,7 @@ wxThread::ExitCode EmuThread::Entry()
|
||||||
|
|
||||||
if (emustatus == 1)
|
if (emustatus == 1)
|
||||||
{
|
{
|
||||||
NDS::RunFrame();
|
u32 nlines = NDS::RunFrame();
|
||||||
|
|
||||||
SDL_LockTexture(sdltex, NULL, &texpixels, &texstride);
|
SDL_LockTexture(sdltex, NULL, &texpixels, &texstride);
|
||||||
if (texstride == 256*4)
|
if (texstride == 256*4)
|
||||||
|
@ -410,7 +410,9 @@ wxThread::ExitCode EmuThread::Entry()
|
||||||
SDL_RenderPresent(sdlrend);
|
SDL_RenderPresent(sdlrend);
|
||||||
|
|
||||||
// framerate limiter based off SDL2_gfx
|
// 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++;
|
fpslimitcount++;
|
||||||
u32 curtick = SDL_GetTicks();
|
u32 curtick = SDL_GetTicks();
|
||||||
|
|
Loading…
Reference in New Issue