From 9219a084c4c9297ca3712f85ae629a3a2d70a6c0 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Sun, 25 Feb 2024 16:45:22 -0500 Subject: [PATCH] improve edge marking bug accuracy also begin groundwork for rdlines_count register emulation --- src/GPU3D.cpp | 10 ++++++---- src/GPU3D.h | 3 ++- src/GPU3D_Soft.cpp | 50 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 5cf6426f..8706724b 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -241,7 +241,8 @@ void GPU3D::Reset() noexcept AlphaRefVal = 0; AlphaRef = 0; - RDLines = 46; + RDLines = 63; // defaults to 63 for one frame? (CHECKME: when does it reset?) + RDLinesTemp = 46; memset(ToonTable, 0, sizeof(ToonTable)); memset(EdgeTable, 0, sizeof(EdgeTable)); @@ -2401,7 +2402,6 @@ void GPU3D::CheckFIFODMA() noexcept void GPU3D::VCount144(GPU& gpu) noexcept { - RDLines = 46; CurrentRenderer->VCount144(gpu); } @@ -2431,6 +2431,7 @@ bool YSort(Polygon* a, Polygon* b) void GPU3D::VBlank() noexcept { + RDLines = RDLinesTemp; if (GeometryEnabled) { if (RenderingEnabled) @@ -2508,6 +2509,7 @@ void GPU3D::VBlank() noexcept void GPU3D::VCount215(GPU& gpu) noexcept { + //RDLinesTemp = 46; CurrentRenderer->RenderFrame(gpu); } @@ -2645,7 +2647,7 @@ u16 GPU3D::Read16(u32 addr) noexcept return DispCnt; case 0x04000320: - return RDLines; // IT IS TIME + return RDLines; // CHECKME: Can this always be read? Even when the gpu is powered off? case 0x04000600: { @@ -2689,7 +2691,7 @@ u32 GPU3D::Read32(u32 addr) noexcept return DispCnt; case 0x04000320: - return RDLines; // IT IS TIME + return RDLines; case 0x04000600: { diff --git a/src/GPU3D.h b/src/GPU3D.h index 8719a7e1..3d3b0e7f 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -246,7 +246,8 @@ public: bool RenderingEnabled = false; u32 DispCnt = 0; - u32 RDLines = 0; + u8 RDLines = 63; + u8 RDLinesTemp = 46; u8 AlphaRefVal = 0; u8 AlphaRef = 0; diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index d3b72e08..50d1104f 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -1876,13 +1876,17 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys) RenderScanline(gpu, 0, j, &rastertimingeven); RenderScanline(gpu, 1, j, &rastertimingodd); + // it can't proceed to the next scanline unless all others steps are done (both scanlines in the pair, and final pass) RasterTiming = timespent = std::max(std::initializer_list {rastertimingeven, rastertimingodd, FinalPassLen}); + // 12 cycles at the end of a "timeout" are always used for w/e reason RasterTiming += std::clamp(ScanlineTimeout - RasterTiming, 0, 12); + gpu.GPU3D.RDLinesTemp = 46; // if first pair was not delayed past the first read, then later scanlines cannot either // this allows us to implement a fast path //if (slread[0] - timespent + ScanlinePushDelay >= 256) { + // begin scanline timeout ScanlineTimeout = slread[1] - FinalPassLen; RenderScanline(gpu, 2, j, &rastertimingeven); @@ -1891,9 +1895,21 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys) prevtimespent = timespent; RasterTiming += timespent = std::max(std::initializer_list {rastertimingeven, rastertimingodd, FinalPassLen}); RasterTiming += std::clamp(ScanlineTimeout - RasterTiming, 0, 12); - - ScanlineFinalPass(gpu.GPU3D, 0, true, true); + scanlineswaiting++; + + while (RasterTiming >= slread[nextread] + 565) + { + if (RasterTiming < slread[nextread] + 565) + { + RasterTiming += timespent = (slread[nextread] + 565) - RasterTiming; // why + 565? + timespent += 571; // fixes edge marking bug emulation. not sure why this is needed? + } + scanlineswaiting--; + nextread++; + } + + ScanlineFinalPass(gpu.GPU3D, 0, true, timespent >= 502); for (int y = 4; y < 192; y+=2) { ScanlineTimeout = slread[y-1] - FinalPassLen; @@ -1907,9 +1923,13 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys) scanlineswaiting+=2; - while (scanlineswaiting >= 47) + while (scanlineswaiting >= 47 || RasterTiming >= slread[nextread] + 565) { - if (RasterTiming < slread[nextread]) RasterTiming += timespent = (slread[nextread] + 565) - RasterTiming; // why + 565? + if (RasterTiming < slread[nextread] + 565) + { + RasterTiming += timespent = (slread[nextread] + 565) - RasterTiming; // why + 565? + timespent += 571; // fixes edge marking bug emulation. not sure why this is needed? + } scanlineswaiting--; nextread++; } @@ -1917,11 +1937,27 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys) ScanlineFinalPass(gpu.GPU3D, y-3, prevtimespent >= 502 || y-3 == 1, timespent >= 502); ScanlineFinalPass(gpu.GPU3D, y-2, prevtimespent >= 502, timespent >= 502); } + scanlineswaiting+= 2; + prevtimespent = timespent; - ScanlineFinalPass(gpu.GPU3D, 189, timespent >= 502, timespent >= 502); - ScanlineFinalPass(gpu.GPU3D, 190, timespent >= 502, true); + // do this one last time to allow for edge marking bug emulation. + while (scanlineswaiting >= 47 || RasterTiming >= slread[nextread] + 565) + { + if (RasterTiming < slread[nextread] + 565) + { + RasterTiming += timespent = (slread[nextread] + 565) - RasterTiming; // why + 565? + timespent += 571; // fixes edge marking bug emulation. not sure why this is needed? + } + scanlineswaiting--; + nextread++; + } + + ScanlineFinalPass(gpu.GPU3D, 189, prevtimespent >= 502, timespent >= 502); + ScanlineFinalPass(gpu.GPU3D, 190, prevtimespent >= 502, true); + + // skip timing emulation here since it's irrelevant, also use timespent instead of prev because we're skipping timing emulation + ScanlineFinalPass(gpu.GPU3D, 191, timespent >= 502, true); - ScanlineFinalPass(gpu.GPU3D, 191, true, true); } /*else {