From 40fcb538521fa3540261185d3ad4efcfcc9ff819 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 20:57:17 +0900 Subject: [PATCH 01/10] [GSH_OpenGL.cpp] Implement sprite rounding hack Added a method to enable sprite rounding hack to fix vertical seams between adjacent sprites. The hack can be toggled via SetSpriteRoundingHackEnabled(). --- Source/gs/GSH_OpenGL/GSH_OpenGL.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp b/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp index 7eb9460f41..67486b463b 100644 --- a/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp +++ b/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp @@ -327,6 +327,16 @@ void CGSH_OpenGL::CheckExtensions() } } +void CGSH_OpenGL::SetSpriteRoundingHackEnabled(bool enabled) +{ + SendGSCall( + [this, enabled]() { + m_spriteRoundingHackEnabled = enabled; + }); +} + + + Framework::OpenGl::CBuffer CGSH_OpenGL::GeneratePresentVertexBuffer() { auto buffer = Framework::OpenGl::CBuffer::Create(); @@ -1642,6 +1652,19 @@ void CGSH_OpenGL::Prim_Sprite() nY1 -= m_nPrimOfsY; nY2 -= m_nPrimOfsY; + // Sprite boundary rounding hack: fixes vertical line seams between + // adjacent sprites (seen in Namco tekken4/tekken5/taiko titles). + // Opt-in only, enabled via SetSpriteRoundingHackEnabled() from the + // arcade boot path (ArcadeUtils::BootArcadeMachine) so it doesn't + // affect unrelated titles. + if(m_spriteRoundingHackEnabled) + { + nX1 = round(nX1); + nY1 = round(nY1); + nX2 = round(nX2); + nY2 = round(nY2); + } + float nS[2] = {0, 0}; float nT[2] = {0, 0}; From 8d22145504e714aca3340c6c70375ed01a028b88 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 20:57:57 +0900 Subject: [PATCH 02/10] [GSH_OpenGL.h] Add sprite rounding hack enabled flag --- Source/gs/GSH_OpenGL/GSH_OpenGL.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/gs/GSH_OpenGL/GSH_OpenGL.h b/Source/gs/GSH_OpenGL/GSH_OpenGL.h index 290deb702a..26835bb584 100644 --- a/Source/gs/GSH_OpenGL/GSH_OpenGL.h +++ b/Source/gs/GSH_OpenGL/GSH_OpenGL.h @@ -54,6 +54,8 @@ class CGSH_OpenGL : public CGSHandler, public CGsDebuggerInterface const VERTEX* GetInputVertices() const override; + void SetSpriteRoundingHackEnabled(bool enabled) override; + protected: void PalCache_Flush(); void LoadPreferences(); @@ -400,6 +402,7 @@ class CGSH_OpenGL : public CGSHandler, public CGsDebuggerInterface bool m_forceBilinearTextures = false; unsigned int m_fbScale = 1; bool m_multisampleEnabled = false; + bool m_spriteRoundingHackEnabled = false; bool m_depthTestingEnabled = true; bool m_alphaBlendingEnabled = true; bool m_alphaTestingEnabled = true; From 1cf82e960d724f456e019a3b15311ed95a792c91 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 20:59:40 +0900 Subject: [PATCH 03/10] [GSH_OpenGLWin32.cpp] enable Vsync Always enabled for screen stability. --- Source/gs/GSH_OpenGLWin32/GSH_OpenGLWin32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/gs/GSH_OpenGLWin32/GSH_OpenGLWin32.cpp b/Source/gs/GSH_OpenGLWin32/GSH_OpenGLWin32.cpp index dc34bcbb55..4d5c9926c1 100644 --- a/Source/gs/GSH_OpenGLWin32/GSH_OpenGLWin32.cpp +++ b/Source/gs/GSH_OpenGLWin32/GSH_OpenGLWin32.cpp @@ -69,7 +69,7 @@ void CGSH_OpenGLWin32::InitializeImpl() if(wglSwapIntervalEXT) { - wglSwapIntervalEXT(-1); + wglSwapIntervalEXT(1); } CGSH_OpenGL::InitializeImpl(); From d03a0b5c6b6d6034d26061e7c99c3f9062c13e9d Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 21:00:27 +0900 Subject: [PATCH 04/10] [GSHandler.h] Add SetSpriteRoundingHackEnabled method Add virtual method for sprite rounding hack in GSHandler --- Source/gs/GSHandler.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/gs/GSHandler.h b/Source/gs/GSHandler.h index 66bfe59a65..1a35f30246 100644 --- a/Source/gs/GSHandler.h +++ b/Source/gs/GSHandler.h @@ -824,6 +824,11 @@ class CGSHandler static void RegisterPreferences(); void NotifyPreferencesChanged(); + // Default no-op. Only overridden by renderer backends (e.g. CGSH_OpenGL) + // that implement the sprite boundary rounding hack for specific arcade + // titles (tekken4/tekken5/taiko series) to fix vertical line seams. + virtual void SetSpriteRoundingHackEnabled(bool enabled) {} + void SetIntc(CINTC*); void Reset(); virtual void SetPresentationParams(const PRESENTATION_PARAMS&); From 84ad4f70bb6ae26d797974e88c5d679365db4bb3 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 21:12:33 +0900 Subject: [PATCH 05/10] [ArcadeUtils.cpp] Implement sprite rounding hack for certain games Added a sprite rounding hack for specific game titles. --- Source/ui_shared/ArcadeUtils.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Source/ui_shared/ArcadeUtils.cpp b/Source/ui_shared/ArcadeUtils.cpp index 9ab3f8b6ea..e838609518 100644 --- a/Source/ui_shared/ArcadeUtils.cpp +++ b/Source/ui_shared/ArcadeUtils.cpp @@ -355,6 +355,22 @@ void ArcadeUtils::BootArcadeMachine(CPS2VM* virtualMachine, const fs::path& arca driver->PrepareEnvironment(virtualMachine, def); driver->Launch(virtualMachine, def); + // --- define specific titles to delete vertical lines + { + bool spriteRoundingHackEnabled = + (def.id.rfind("tekken4", 0) == 0) || + (def.id.rfind("tekken5", 0) == 0) || + (def.id.rfind("soulclb3", 0) == 0) || + (def.id.rfind("taiko", 0) == 0); + + if(auto gsHandler = virtualMachine->GetGSHandler()) + { + gsHandler->SetSpriteRoundingHackEnabled(spriteRoundingHackEnabled); + } + } + + + ApplyPatchesFromArcadeDefinition(virtualMachine, def); ApplyIdleLoopBlocksFromArcadeDefinition(virtualMachine, def); From acbd4bf4ae3987bd009acecb28a5358181417f76 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 21:25:57 +0900 Subject: [PATCH 06/10] [ArcadeUtils.cpp] remove comments Removed comments that were not necessary for understanding the code. --- Source/ui_shared/ArcadeUtils.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Source/ui_shared/ArcadeUtils.cpp b/Source/ui_shared/ArcadeUtils.cpp index e838609518..44e23b740b 100644 --- a/Source/ui_shared/ArcadeUtils.cpp +++ b/Source/ui_shared/ArcadeUtils.cpp @@ -282,10 +282,8 @@ void ArcadeUtils::RegisterArcadeMachines() return; } - //This set is used to track inactive arcadedefs we might have in the database std::set inactiveArcadeDefs; - //Collect all arcadedef files we have registered in the database { auto arcadeBootables = BootablesDb::CClient::GetInstance().GetBootables(BootablesDb::CClient::SORT_METHOD_ARCADE); for(const auto& bootable : arcadeBootables) @@ -298,7 +296,6 @@ void ArcadeUtils::RegisterArcadeMachines() { auto arcadeDefPath = entry.path(); auto arcadeDefFilename = arcadeDefPath.filename(); - //Remove this arcadedef from the inactive set inactiveArcadeDefs.erase(arcadeDefFilename); try { @@ -313,7 +310,6 @@ void ArcadeUtils::RegisterArcadeMachines() } } - //Prune any remaining arcadedef for(const auto& inactiveArcadeDef : inactiveArcadeDefs) { BootablesDb::CClient::GetInstance().UnregisterBootable(inactiveArcadeDef); @@ -322,14 +318,12 @@ void ArcadeUtils::RegisterArcadeMachines() static CNamcoSys246Driver g_sys246Driver; static CNamcoSys147Driver g_sys147Driver; -// clang-format off static CArcadeDriver* g_drivers[] = { nullptr, &g_sys246Driver, &g_sys147Driver, }; -// clang-format on void ArcadeUtils::BootArcadeMachine(CPS2VM* virtualMachine, const fs::path& arcadeDefFilename) { @@ -355,7 +349,6 @@ void ArcadeUtils::BootArcadeMachine(CPS2VM* virtualMachine, const fs::path& arca driver->PrepareEnvironment(virtualMachine, def); driver->Launch(virtualMachine, def); - // --- define specific titles to delete vertical lines { bool spriteRoundingHackEnabled = (def.id.rfind("tekken4", 0) == 0) || From 77aefa625261083194dcb8f5847a9961911d9b8c Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 21:34:38 +0900 Subject: [PATCH 07/10] [GSH_OpenGL.cpp] Removed unnecessary blank lines in GSH_OpenGL.cpp. --- Source/gs/GSH_OpenGL/GSH_OpenGL.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp b/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp index 67486b463b..fd22247ea4 100644 --- a/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp +++ b/Source/gs/GSH_OpenGL/GSH_OpenGL.cpp @@ -335,8 +335,6 @@ void CGSH_OpenGL::SetSpriteRoundingHackEnabled(bool enabled) }); } - - Framework::OpenGl::CBuffer CGSH_OpenGL::GeneratePresentVertexBuffer() { auto buffer = Framework::OpenGl::CBuffer::Create(); From 89a6214e6f12acb73c9e4eec25d2f5c1cfa92332 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 21:36:42 +0900 Subject: [PATCH 08/10] [GSHandler.h] --- Source/gs/GSHandler.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/gs/GSHandler.h b/Source/gs/GSHandler.h index 1a35f30246..e698d190ac 100644 --- a/Source/gs/GSHandler.h +++ b/Source/gs/GSHandler.h @@ -827,7 +827,9 @@ class CGSHandler // Default no-op. Only overridden by renderer backends (e.g. CGSH_OpenGL) // that implement the sprite boundary rounding hack for specific arcade // titles (tekken4/tekken5/taiko series) to fix vertical line seams. - virtual void SetSpriteRoundingHackEnabled(bool enabled) {} + virtual void SetSpriteRoundingHackEnabled(bool enabled) + { + } void SetIntc(CINTC*); void Reset(); From 8987d24c7c7219864f99b165ec1a3c44332e5159 Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 21:38:35 +0900 Subject: [PATCH 09/10] [ArcadeUtils.cpp] --- Source/ui_shared/ArcadeUtils.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/ui_shared/ArcadeUtils.cpp b/Source/ui_shared/ArcadeUtils.cpp index 44e23b740b..6cc46bcdfd 100644 --- a/Source/ui_shared/ArcadeUtils.cpp +++ b/Source/ui_shared/ArcadeUtils.cpp @@ -319,10 +319,10 @@ void ArcadeUtils::RegisterArcadeMachines() static CNamcoSys246Driver g_sys246Driver; static CNamcoSys147Driver g_sys147Driver; static CArcadeDriver* g_drivers[] = -{ - nullptr, - &g_sys246Driver, - &g_sys147Driver, + { + nullptr, + &g_sys246Driver, + &g_sys147Driver, }; void ArcadeUtils::BootArcadeMachine(CPS2VM* virtualMachine, const fs::path& arcadeDefFilename) From 33c9a215432c019b34db9792bc5fedceaa0a12fe Mon Sep 17 00:00:00 2001 From: pizzzza19 Date: Fri, 3 Jul 2026 21:42:20 +0900 Subject: [PATCH 10/10] [ArcadeUtils.cpp] remove blank lines Removed unnecessary blank lines in ArcadeUtils.cpp. --- Source/ui_shared/ArcadeUtils.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/ui_shared/ArcadeUtils.cpp b/Source/ui_shared/ArcadeUtils.cpp index 6cc46bcdfd..3c03bb75b3 100644 --- a/Source/ui_shared/ArcadeUtils.cpp +++ b/Source/ui_shared/ArcadeUtils.cpp @@ -362,8 +362,6 @@ void ArcadeUtils::BootArcadeMachine(CPS2VM* virtualMachine, const fs::path& arca } } - - ApplyPatchesFromArcadeDefinition(virtualMachine, def); ApplyIdleLoopBlocksFromArcadeDefinition(virtualMachine, def);