From 852fe9c4bebb992aa91d7ba107ca15688ca87221 Mon Sep 17 00:00:00 2001 From: crudelios Date: Wed, 26 Oct 2011 01:19:10 +0100 Subject: [PATCH] Added proper Bounding Box support. Should fix most graphical issues with Paper Mario: TTYD and Super Paper Mario. Fixes issue 360. Since only those two games seem to require BBox support, and as per ector's suggestion, BBox is only enabled for those two games. BBoxes and Display List Caches don't get along too well, causing Paper Mario: TTYD to hang during certain effects where BBoxes are used. For now, I disabled DList Cache for the Paper Mario games, hopefully both will be compatible in the future. --- Data/User/GameConfig/G8ME01.ini | 4 +- Data/User/GameConfig/G8MP01.ini | 4 ++ Data/User/GameConfig/NAEE01.ini | 4 ++ Data/User/GameConfig/R8PE01.ini | 3 + Data/User/GameConfig/R8PP01.ini | 3 + Source/Core/DolphinWX/Src/ISOProperties.cpp | 17 ++++- Source/Core/DolphinWX/Src/ISOProperties.h | 2 +- Source/Core/VideoCommon/Src/BPStructs.cpp | 42 ++++++------ Source/Core/VideoCommon/Src/VertexLoader.cpp | 67 +++++++++++--------- Source/Core/VideoCommon/Src/VideoCommon.h | 6 -- Source/Core/VideoCommon/Src/VideoConfig.cpp | 1 + Source/Core/VideoCommon/Src/VideoConfig.h | 1 + 12 files changed, 93 insertions(+), 61 deletions(-) diff --git a/Data/User/GameConfig/G8ME01.ini b/Data/User/GameConfig/G8ME01.ini index d49e5395d03..0033486b599 100644 --- a/Data/User/GameConfig/G8ME01.ini +++ b/Data/User/GameConfig/G8ME01.ini @@ -41,5 +41,7 @@ $Max Gold $Max Shop Points 026EE7F0 000003E7 [Video] +UseBBox = True ProjectionHack = 0 - +[Video_Hacks] +DlistCachingEnable = False diff --git a/Data/User/GameConfig/G8MP01.ini b/Data/User/GameConfig/G8MP01.ini index db66750a7fd..5e1ff20ee6c 100644 --- a/Data/User/GameConfig/G8MP01.ini +++ b/Data/User/GameConfig/G8MP01.ini @@ -4,3 +4,7 @@ EmulationStateId = 4 [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. +[Video] +UseBBox = True +[Video_Hacks] +DlistCachingEnable = False diff --git a/Data/User/GameConfig/NAEE01.ini b/Data/User/GameConfig/NAEE01.ini index 8ff0d929d06..b385f23889e 100644 --- a/Data/User/GameConfig/NAEE01.ini +++ b/Data/User/GameConfig/NAEE01.ini @@ -5,3 +5,7 @@ EmulationIssues = Sound requires LLE. No graphical issues. EmulationStateId = 4 [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. +[Video] +UseBBox = True +[Video_Hacks] +DlistCachingEnable = False diff --git a/Data/User/GameConfig/R8PE01.ini b/Data/User/GameConfig/R8PE01.ini index 4ae6b899835..ce4ee473209 100644 --- a/Data/User/GameConfig/R8PE01.ini +++ b/Data/User/GameConfig/R8PE01.ini @@ -7,5 +7,8 @@ EmulationIssues = [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Video] +UseBBox = True ProjectionHack = 0 +[Video_Hacks] +DlistCachingEnable = False [Gecko] diff --git a/Data/User/GameConfig/R8PP01.ini b/Data/User/GameConfig/R8PP01.ini index a348557b9c4..ccfb4ec45dd 100644 --- a/Data/User/GameConfig/R8PP01.ini +++ b/Data/User/GameConfig/R8PP01.ini @@ -6,4 +6,7 @@ EmulationIssues = [OnFrame] Add memory patches to be applied every frame here. [ActionReplay] Add action replay cheats here. [Video] +UseBBox = True ProjectionHack = 0 +[Video_Hacks] +DlistCachingEnable = False diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 4618e739ae1..aa554e4b48d 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -325,6 +325,9 @@ void CISOProperties::CreateGUIControls(bool IsWad) DisableWiimoteSpeaker->SetToolTip(_("Mutes the Wiimote speaker. Fixes random disconnections on real wiimotes. No effect on emulated wiimotes.")); // Video + UseBBox = new wxCheckBox(m_GameConfig, ID_ZTP_SPEEDUP, _("Enable Bounding Box Calculation"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER); + UseBBox->SetToolTip(_("If checked, the bounding box registers will be updated. Used by the Paper Mario games.")); + UseZTPSpeedupHack = new wxCheckBox(m_GameConfig, ID_ZTP_SPEEDUP, _("ZTP hack"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE|wxCHK_ALLOW_3RD_STATE_FOR_USER); UseZTPSpeedupHack->SetToolTip(_("Enable this to speed up The Legend of Zelda: Twilight Princess. Disable for ANY other game.")); @@ -383,6 +386,7 @@ void CISOProperties::CreateGUIControls(bool IsWad) wxStaticBoxSizer * const sbVideoOverrides = new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Video")); + sbVideoOverrides->Add(UseBBox, 0, wxLEFT, 5); sbVideoOverrides->Add(UseZTPSpeedupHack, 0, wxLEFT, 5); szrPHackSettings->Add(PHackEnable, 0, wxALIGN_CENTER_VERTICAL|wxLEFT, 5); szrPHackSettings->Add(PHSettings, 0, wxLEFT, 5); @@ -898,7 +902,13 @@ void CISOProperties::LoadGameConfig() DisableWiimoteSpeaker->Set3StateValue((wxCheckBoxState)bTemp); else DisableWiimoteSpeaker->Set3StateValue(wxCHK_UNDETERMINED); - + + if (GameIni.Get("Video", "UseBBox", &bTemp)) + UseBBox->Set3StateValue((wxCheckBoxState)bTemp); + else + UseBBox->Set3StateValue(wxCHK_UNDETERMINED); + + if (GameIni.Get("Video", "ZTPSpeedupHack", &bTemp)) UseZTPSpeedupHack->Set3StateValue((wxCheckBoxState)bTemp); else @@ -992,6 +1002,11 @@ bool CISOProperties::SaveGameConfig() else GameIni.Set("Wii", "DisableWiimoteSpeaker", DisableWiimoteSpeaker->Get3StateValue()); + if (UseBBox->Get3StateValue() == wxCHK_UNDETERMINED) + GameIni.DeleteKey("Video", "UseBBox"); + else + GameIni.Set("Video", "UseBBox", UseBBox->Get3StateValue()); + if (UseZTPSpeedupHack->Get3StateValue() == wxCHK_UNDETERMINED) GameIni.DeleteKey("Video", "ZTPSpeedupHack"); else diff --git a/Source/Core/DolphinWX/Src/ISOProperties.h b/Source/Core/DolphinWX/Src/ISOProperties.h index 0add6e94519..7161585a364 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.h +++ b/Source/Core/DolphinWX/Src/ISOProperties.h @@ -74,7 +74,7 @@ private: // Wii wxCheckBox *EnableProgressiveScan, *EnableWideScreen, *DisableWiimoteSpeaker; // Video - wxCheckBox *UseZTPSpeedupHack, *PHackEnable; + wxCheckBox *UseZTPSpeedupHack, *PHackEnable, *UseBBox; wxButton *PHSettings; wxArrayString arrayStringFor_EmuState; diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp index cee68327f52..d5909fdd954 100644 --- a/Source/Core/VideoCommon/Src/BPStructs.cpp +++ b/Source/Core/VideoCommon/Src/BPStructs.cpp @@ -257,9 +257,8 @@ void BPWritten(const BPCmd& bp) // We should be able to get away with deactivating the current bbox tracking // here. Not sure if there's a better spot to put this. // the number of lines copied is determined by the y scale * source efb height -#ifdef BBOX_SUPPORT + PixelEngine::bbox_active = false; -#endif float yScale; if (PE_copy.scale_invert) @@ -400,28 +399,29 @@ void BPWritten(const BPCmd& bp) case BPMEM_CLEARBBOX1: case BPMEM_CLEARBBOX2: { -#ifdef BBOX_SUPPORT - // which is which? these are GUESSES! - if (bp.address == BPMEM_CLEARBBOX1) { - int right = bp.newvalue >> 10; - int left = bp.newvalue & 0x3ff; + if(g_ActiveConfig.bUseBBox) + { + // which is which? these are GUESSES! + if (bp.address == BPMEM_CLEARBBOX1) { + int right = bp.newvalue >> 10; + int left = bp.newvalue & 0x3ff; - // We should only set these if bbox is calculated properly. - PixelEngine::bbox[0] = left; - PixelEngine::bbox[1] = right; - PixelEngine::bbox_active = true; - // WARN_LOG(VIDEO, "ClearBBox LR: %i, %08x - %i, %i", bp.address, bp.newvalue, left, right); - } else { - int bottom = bp.newvalue >> 10; - int top = bp.newvalue & 0x3ff; + // We should only set these if bbox is calculated properly. + PixelEngine::bbox[0] = left; + PixelEngine::bbox[1] = right; + PixelEngine::bbox_active = true; + // WARN_LOG(VIDEO, "ClearBBox LR: %i, %08x - %i, %i", bp.address, bp.newvalue, left, right); + } else { + int bottom = bp.newvalue >> 10; + int top = bp.newvalue & 0x3ff; - // We should only set these if bbox is calculated properly. - PixelEngine::bbox[2] = top; - PixelEngine::bbox[3] = bottom; - PixelEngine::bbox_active = true; - // WARN_LOG(VIDEO, "ClearBBox TB: %i, %08x - %i, %i", bp.address, bp.newvalue, top, bottom); + // We should only set these if bbox is calculated properly. + PixelEngine::bbox[2] = top; + PixelEngine::bbox[3] = bottom; + PixelEngine::bbox_active = true; + // WARN_LOG(VIDEO, "ClearBBox TB: %i, %08x - %i, %i", bp.address, bp.newvalue, top, bottom); + } } -#endif } break; case BPMEM_TEXINVALIDATE: // Used, if game has manual control the Texture Cache, which we don't allow diff --git a/Source/Core/VideoCommon/Src/VertexLoader.cpp b/Source/Core/VideoCommon/Src/VertexLoader.cpp index ce9e81219d2..ee0538751a8 100644 --- a/Source/Core/VideoCommon/Src/VertexLoader.cpp +++ b/Source/Core/VideoCommon/Src/VertexLoader.cpp @@ -101,7 +101,7 @@ void LOADERDECL PosMtx_Write() void LOADERDECL UpdateBoundingBox() { - if (!PixelEngine::bbox_active) + if (!PixelEngine::bbox_active) return; // Truly evil hack, reading backwards from the write pointer. If we were writing to write-only @@ -119,40 +119,46 @@ void LOADERDECL UpdateBoundingBox() t[1] = p[0] * world_matrix[4] + p[1] * world_matrix[5] + p[2] * world_matrix[6] + world_matrix[7]; t[2] = p[0] * world_matrix[8] + p[1] * world_matrix[9] + p[2] * world_matrix[10] + world_matrix[11]; - float o[4]; - o[2] = t[0] * proj_matrix[8] + t[1] * proj_matrix[9] + t[2] * proj_matrix[10] + proj_matrix[11]; - // Depth culling - if (o[2] < 0.0) { - // No pixels are likely to be drawn - don't update bounding box. - return; - } + float o[3]; o[0] = t[0] * proj_matrix[0] + t[1] * proj_matrix[1] + t[2] * proj_matrix[2] + proj_matrix[3]; o[1] = t[0] * proj_matrix[4] + t[1] * proj_matrix[5] + t[2] * proj_matrix[6] + proj_matrix[7]; - o[3] = t[0] * proj_matrix[12] + t[1] * proj_matrix[13] + t[2] * proj_matrix[14] + proj_matrix[15]; - - o[0] /= o[3]; - o[1] /= o[3]; + o[2] = t[0] * proj_matrix[12] + t[1] * proj_matrix[13] + t[2] * proj_matrix[14] + proj_matrix[15]; + + + o[0] /= o[2]; + o[1] /= o[2]; // should possibly adjust for viewport? - o[0] = (o[0] + 1.0f) * 320.0f; - o[1] = (o[1] + 1.0f) * 240.0f; + o[0] = (o[0] + 1.0f) * 304.0f; + o[1] = (1.0f - o[1]) * 240.0f; - if (o[0] < PixelEngine::bbox[0]) PixelEngine::bbox[0] = (u16)std::max(0.0f, o[0]); - if (o[0] > PixelEngine::bbox[1]) PixelEngine::bbox[1] = (u16)std::min(640.0f, o[0]); - if (o[1] < PixelEngine::bbox[2]) PixelEngine::bbox[2] = (u16)std::max(0.0f, o[1]); - if (o[1] > PixelEngine::bbox[3]) PixelEngine::bbox[3] = (u16)std::min(480.0f, o[1]); + if (o[0] < PixelEngine::bbox[0]) + { + PixelEngine::bbox[0] = (u16) std::max(0.0f, o[0]); - // Hardware tests bounding boxes in 2x2 blocks => left and top are even, right and bottom are odd - PixelEngine::bbox[0] &= ~1; - PixelEngine::bbox[1] |= 1; - PixelEngine::bbox[2] &= ~1; - PixelEngine::bbox[3] |= 1; + // Hardware tests bounding boxes in 2x2 blocks => left and top are even, right and bottom are odd + PixelEngine::bbox[0] &= ~1; + } - /* - if (GetAsyncKeyState(VK_LSHIFT)) { - ERROR_LOG(VIDEO, "XForm: %f %f %f to %f %f", p[0], p[1], p[2], o[0], o[1]); - ERROR_LOG(VIDEO, "%i %i %i %i", g_VideoInitialize.pBBox[0], g_VideoInitialize.pBBox[1], g_VideoInitialize.pBBox[2], g_VideoInitialize.pBBox[3]); - }*/ + if (o[0] > PixelEngine::bbox[1]) + { + PixelEngine::bbox[1] = (u16) std::min(608.0f, o[0]); + if(!(PixelEngine::bbox[1] & 1) && PixelEngine::bbox[1] != 0) + PixelEngine::bbox[1]--; + } + + if (o[1] < PixelEngine::bbox[2]) + { + PixelEngine::bbox[2] = (u16) std::max(0.0f, o[1]); + PixelEngine::bbox[2] &= ~1; + } + + if (o[1] > PixelEngine::bbox[3]) + { + PixelEngine::bbox[3] = (u16) std::min(480.0f, o[1]); + if(!(PixelEngine::bbox[3] & 1) && PixelEngine::bbox[3] != 0) + PixelEngine::bbox[3]--; + } } void LOADERDECL TexMtx_ReadDirect_UByte() @@ -290,9 +296,8 @@ void VertexLoader::CompileVertexTranslator() // OK, so we just got a point. Let's go back and read it for the bounding box. -#ifdef BBOX_SUPPORT - WriteCall(UpdateBoundingBox); -#endif + if(g_ActiveConfig.bUseBBox) + WriteCall(UpdateBoundingBox); // Normals vtx_decl.num_normals = 0; diff --git a/Source/Core/VideoCommon/Src/VideoCommon.h b/Source/Core/VideoCommon/Src/VideoCommon.h index 80c09378849..9f6dd59cd36 100644 --- a/Source/Core/VideoCommon/Src/VideoCommon.h +++ b/Source/Core/VideoCommon/Src/VideoCommon.h @@ -56,12 +56,6 @@ enum MAX_XFB_HEIGHT = 574 }; -// If this is enabled, bounding boxes will be computed for everything drawn. -// This can theoretically have a big speed hit in some geom heavy games. Needs more work. -// Helps some effects in Paper Mario (but they aren't quite right yet). -// Do testing to figure out if the speed hit is bad? -// #define BBOX_SUPPORT - // Logging // ---------- void HandleGLError(); diff --git a/Source/Core/VideoCommon/Src/VideoConfig.cpp b/Source/Core/VideoCommon/Src/VideoConfig.cpp index 2c7788c9cce..b6ba76f45e2 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.cpp +++ b/Source/Core/VideoCommon/Src/VideoConfig.cpp @@ -172,6 +172,7 @@ void VideoConfig::GameIniLoad(const char *ini_file) iniFile.GetIfExists("Video", "PH_ZNear", &sPhackvalue[0]); iniFile.GetIfExists("Video", "PH_ZFar", &sPhackvalue[1]); iniFile.GetIfExists("Video", "ZTPSpeedupHack", &bZTPSpeedHack); + iniFile.GetIfExists("Video", "UseBBox", &bUseBBox); } void VideoConfig::VerifyValidity() diff --git a/Source/Core/VideoCommon/Src/VideoConfig.h b/Source/Core/VideoCommon/Src/VideoConfig.h index 83ec08784da..3bd833cc73b 100644 --- a/Source/Core/VideoCommon/Src/VideoConfig.h +++ b/Source/Core/VideoCommon/Src/VideoConfig.h @@ -135,6 +135,7 @@ struct VideoConfig std::string sPhackvalue[2]; float fAspectRatioHackW, fAspectRatioHackH; bool bZTPSpeedHack; // The Legend of Zelda: Twilight Princess + bool bUseBBox; bool bEnablePixelLighting; bool bEnablePerPixelDepth;