From 31cfe2ee8f6e3dbcb35bb6e363f9255069101737 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Tue, 30 Apr 2024 17:46:23 -0400 Subject: [PATCH 1/2] implement gx hanging implements hanging on: begin poly with partial poly defined box test with partial poly defined swap buffers with partial poly defined also remove some useless variables: vertexnum wasn't used. NumConsecPolys was only used by triangle strips --- src/GPU3D.cpp | 47 ++++++++++++++++++++++++++++++++++------------- src/GPU3D.h | 9 +++++---- src/NDS.cpp | 3 +-- 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index 47abae2f..a080126c 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -285,7 +285,7 @@ void GPU3D::Reset() noexcept memset(VecTestResult, 0, 2*3); memset(TempVertexBuffer, 0, sizeof(TempVertexBuffer)); - VertexNum = 0; + IncompletePoly = false; VertexNumInPoly = 0; NumConsecutivePolygons = 0; LastStripPolygon = nullptr; @@ -363,7 +363,7 @@ void GPU3D::DoSavestate(Savestate* file) noexcept file->VarArray(ExecParams, 32*4); file->Var32(&ExecParamCount); - file->Var32((u32*)&CycleCount); + file->Var64((u64*)&CycleCount); file->Var64(&Timestamp); file->Var32(&MatrixMode); @@ -387,7 +387,7 @@ void GPU3D::DoSavestate(Savestate* file) noexcept file->VarArray(PosTestResult, 4*4); file->VarArray(VecTestResult, 2*3); - file->Var32(&VertexNum); + file->Bool32(&IncompletePoly); file->Var32(&VertexNumInPoly); file->Var32(&NumConsecutivePolygons); @@ -705,7 +705,7 @@ void GPU3D::UpdateClipMatrix() noexcept -void GPU3D::AddCycles(s32 num) noexcept +void GPU3D::AddCycles(s64 num) noexcept { CycleCount += num; @@ -802,6 +802,15 @@ void GPU3D::StallPolygonPipeline(s32 delay, s32 nonstalldelay) noexcept } } +void GPU3D::HangGX(const char* cause) noexcept +{ + GXHang = true; + Platform::Log(LogLevel::Warn, "GX CRASHED: %s\n", cause); + // this should hang the gx for roughly... 2181 years? + // I think that's close enough to forever for our usecase. + AddCycles(0x1FFFFFFFFFFFFFFF); +} + template @@ -963,6 +972,7 @@ void GPU3D::SubmitPolygon() noexcept PolygonPipeline = 8; VertexSlotCounter = 1; VertexSlotsFree = 0b11110; + IncompletePoly = false; // culling // TODO: work out how it works on the real thing @@ -1382,7 +1392,6 @@ void GPU3D::SubmitVertex() noexcept vertextrans->Clipped = false; - VertexNum++; VertexNumInPoly++; switch (PolygonMode) @@ -1392,8 +1401,8 @@ void GPU3D::SubmitVertex() noexcept { VertexNumInPoly = 0; SubmitPolygon(); - NumConsecutivePolygons++; } + else IncompletePoly = true; break; case 1: // quad @@ -1401,8 +1410,8 @@ void GPU3D::SubmitVertex() noexcept { VertexNumInPoly = 0; SubmitPolygon(); - NumConsecutivePolygons++; } + else IncompletePoly = true; break; case 2: // triangle strip @@ -1422,11 +1431,11 @@ void GPU3D::SubmitVertex() noexcept { VertexNumInPoly = 2; SubmitPolygon(); - NumConsecutivePolygons++; TempVertexBuffer[0] = TempVertexBuffer[1]; TempVertexBuffer[1] = TempVertexBuffer[2]; } + else IncompletePoly = true; break; case 3: // quad strip @@ -1438,11 +1447,11 @@ void GPU3D::SubmitVertex() noexcept VertexNumInPoly = 2; SubmitPolygon(); - NumConsecutivePolygons++; TempVertexBuffer[0] = TempVertexBuffer[3]; TempVertexBuffer[1] = TempVertexBuffer[2]; } + else IncompletePoly = true; break; } @@ -2030,11 +2039,13 @@ void GPU3D::ExecuteCommand() noexcept break; case 0x40: // begin polygons + if (IncompletePoly) + { + HangGX("Begin cmd sent with partial poly defined"); + break; + } StallPolygonPipeline(1, 0); - // TODO: check if there was a polygon being defined but incomplete - // such cases seem to freeze the GPU PolygonMode = entry.Param & 0x3; - VertexNum = 0; VertexNumInPoly = 0; NumConsecutivePolygons = 0; LastStripPolygon = NULL; @@ -2050,6 +2061,11 @@ void GPU3D::ExecuteCommand() noexcept break; case 0x50: // flush + if (IncompletePoly) + { + HangGX("Flush cmd sent with partial poly defined"); + break; + } VertexPipelineCmdDelayed4(); FlushRequest = 1; FlushAttributes = entry.Param & 0x3; @@ -2313,6 +2329,11 @@ void GPU3D::ExecuteCommand() noexcept break; case 0x70: // box test + if (IncompletePoly) + { + HangGX("BoxTest cmd sent with partial poly defined"); + break; + } NumTestCommands -= 3; BoxTest(ExecParams); break; @@ -2325,7 +2346,7 @@ void GPU3D::ExecuteCommand() noexcept } } -s32 GPU3D::CyclesToRunFor() const noexcept +s64 GPU3D::CyclesToRunFor() const noexcept { if (CycleCount < 0) return 0; return CycleCount; diff --git a/src/GPU3D.h b/src/GPU3D.h index 4a5fe6e0..c5e76126 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -98,7 +98,7 @@ public: void ExecuteCommand() noexcept; - s32 CyclesToRunFor() const noexcept; + s64 CyclesToRunFor() const noexcept; void Run() noexcept; void CheckFIFOIRQ() noexcept; void CheckFIFODMA() noexcept; @@ -143,9 +143,10 @@ private: void UpdateClipMatrix() noexcept; void ResetRenderingState() noexcept; - void AddCycles(s32 num) noexcept; + void AddCycles(s64 num) noexcept; void NextVertexSlot() noexcept; void StallPolygonPipeline(s32 delay, s32 nonstalldelay) noexcept; + void HangGX(const char* cause) noexcept; void SubmitPolygon() noexcept; void SubmitVertex() noexcept; void CalculateLighting() noexcept; @@ -204,7 +205,7 @@ public: u32 ExecParams[32] {}; u32 ExecParamCount = 0; - s32 CycleCount = 0; + s64 CycleCount = 0; s32 VertexPipeline = 0; s32 NormalPipeline = 0; s32 PolygonPipeline = 0; @@ -305,7 +306,7 @@ public: s16 VecTestResult[3] {}; Vertex TempVertexBuffer[4] {}; - u32 VertexNum = 0; + bool IncompletePoly = false; u32 VertexNumInPoly = 0; u32 NumConsecutivePolygons = 0; Polygon* LastStripPolygon = nullptr; diff --git a/src/NDS.cpp b/src/NDS.cpp index 68227ea5..3afdfaa8 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -943,8 +943,7 @@ u32 NDS::RunFrame() if (CPUStop & CPUStop_GXStall) { // GXFIFO stall - s32 cycles = GPU.GPU3D.CyclesToRunFor(); - + s64 cycles = GPU.GPU3D.CyclesToRunFor(); ARM9Timestamp = std::min(ARM9Target, ARM9Timestamp+(cycles< Date: Fri, 7 Jun 2024 19:09:28 -0400 Subject: [PATCH 2/2] remove unused variable --- src/GPU3D.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index a080126c..beb6bb95 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -804,7 +804,6 @@ void GPU3D::StallPolygonPipeline(s32 delay, s32 nonstalldelay) noexcept void GPU3D::HangGX(const char* cause) noexcept { - GXHang = true; Platform::Log(LogLevel::Warn, "GX CRASHED: %s\n", cause); // this should hang the gx for roughly... 2181 years? // I think that's close enough to forever for our usecase.