From 5e06fbc547c47172bc049e86cf30b2d94f59a8e2 Mon Sep 17 00:00:00 2001 From: rogerman Date: Wed, 1 Mar 2017 18:02:20 -0800 Subject: [PATCH] GPU: Change how DISPCAPCNT's CaptureEnable flag is handled, fixing a graphical issue when starting a battle in Pokemon Black/White. (Regression from r5259.) - To note: This fix to Pokemon Black/White does not require CommonSettings.pokehax to be enabled. - The CaptureEnable flag is now only read at the start of line 0, instead of being read directly from the DISPCAPCNT register per line. In addition, this same state is held all the way through line 192. - The CaptureEnable flag is now reset at the start of line 192, instead of near the end of line 191 H-blank. (This is the proper behavior according to GBATEK.) - The CaptureEnable flag is now only reset when the VRAM configuration is LCDC, instead of always being reset. This makes it possible for this flag to remain set on line 192 if the VRAM configuration is changed to a non-LCDC configuration. - CommonSettings.pokehax is now initialized to false. - Fix a small bug when setting CommonSettings.pokehax via the command line. --- desmume/src/GPU.cpp | 30 +++++++++++++++++++++++++++--- desmume/src/GPU.h | 5 +++++ desmume/src/NDSSystem.cpp | 25 +++++++++++++++---------- desmume/src/NDSSystem.h | 1 + desmume/src/commandline.cpp | 2 +- 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/desmume/src/GPU.cpp b/desmume/src/GPU.cpp index 1a71a6880..0892baff5 100644 --- a/desmume/src/GPU.cpp +++ b/desmume/src/GPU.cpp @@ -5122,6 +5122,7 @@ void GPUEngineA::Reset() this->_Reset_Base(); memset(&this->_dispCapCnt, 0, sizeof(DISPCAPCNT_parsed)); + this->_displayCaptureEnable = false; this->_BGLayer[GPULayerID_BG0].BMPAddress = MMU_ABG; this->_BGLayer[GPULayerID_BG1].BMPAddress = MMU_ABG; @@ -5253,7 +5254,22 @@ bool GPUEngineA::WillCapture3DLayerDirect(const size_t l) bool GPUEngineA::WillDisplayCapture(const size_t l) { const IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT; - return (DISPCAPCNT.CaptureEnable != 0) && (vramConfiguration.banks[DISPCAPCNT.VRAMWriteBlock].purpose == VramConfiguration::LCDC) && (l < this->_dispCapCnt.capy); + return this->_displayCaptureEnable && (vramConfiguration.banks[DISPCAPCNT.VRAMWriteBlock].purpose == VramConfiguration::LCDC) && (l < this->_dispCapCnt.capy); +} + +void GPUEngineA::SetDisplayCaptureEnable() +{ + this->_displayCaptureEnable = (this->_IORegisterMap->DISPCAPCNT.CaptureEnable != 0); +} + +void GPUEngineA::ResetDisplayCaptureEnable() +{ + IOREG_DISPCAPCNT &DISPCAPCNT = this->_IORegisterMap->DISPCAPCNT; + if ( this->_displayCaptureEnable && vramConfiguration.banks[DISPCAPCNT.VRAMWriteBlock].purpose == VramConfiguration::LCDC ) + { + DISPCAPCNT.CaptureEnable = 0; + this->_displayCaptureEnable = false; + } } bool GPUEngineA::VerifyVRAMLineDidChange(const size_t blockID, const size_t l) @@ -6683,8 +6699,6 @@ void GPUEngineA::_LineLarge8bpp(GPUEngineCompositorInfo &compInfo) void GPUEngineA::LastLineProcess() { this->GPUEngineBase::LastLineProcess(); - - this->_IORegisterMap->DISPCAPCNT.CaptureEnable = 0; DISP_FIFOreset(); } @@ -6961,6 +6975,16 @@ void GPUSubsystem::SetWillFrameSkip(const bool willFrameSkip) this->_willFrameSkip = willFrameSkip; } +void GPUSubsystem::SetDisplayCaptureEnable() +{ + this->_engineMain->SetDisplayCaptureEnable(); +} + +void GPUSubsystem::ResetDisplayCaptureEnable() +{ + this->_engineMain->ResetDisplayCaptureEnable(); +} + void GPUSubsystem::UpdateRenderProperties() { this->_engineMain->vramBlockOBJIndex = VRAM_NO_3D_USAGE; diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index ba081435a..1cf051034 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -1524,6 +1524,7 @@ protected: u16 *_VRAMCustomBlockPtr[4]; DISPCAPCNT_parsed _dispCapCnt; + bool _displayCaptureEnable; template void _LineLarge8bpp(GPUEngineCompositorInfo &compInfo); @@ -1565,6 +1566,8 @@ public: bool WillRender3DLayer(); bool WillCapture3DLayerDirect(const size_t l); bool WillDisplayCapture(const size_t l); + void SetDisplayCaptureEnable(); + void ResetDisplayCaptureEnable(); bool VerifyVRAMLineDidChange(const size_t blockID, const size_t l); void LastLineProcess(); @@ -1685,6 +1688,8 @@ public: bool GetWillFrameSkip() const; void SetWillFrameSkip(const bool willFrameSkip); + void SetDisplayCaptureEnable(); + void ResetDisplayCaptureEnable(); void UpdateRenderProperties(); // By default, the displays will automatically perform certain postprocessing steps on the diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index ebc84bef6..ac21d5540 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -1480,21 +1480,20 @@ static void execHardware_hstart() //this should be 214, but we are going to be generous for games with tight timing //they shouldnt be changing any textures at 262 but they might accidentally still be at 214 //so.. - if((CommonSettings.rigorous_timing && nds.VCount==214) || (!CommonSettings.rigorous_timing && nds.VCount==262)) + if ( (CommonSettings.rigorous_timing && nds.VCount == 214) || (!CommonSettings.rigorous_timing && nds.VCount == 262) ) { gfx3d_VBlankEndSignal(frameSkipper.ShouldSkip3D()); } - if(nds.VCount==261) - nds.overclock = 0; - - if(nds.VCount==263) + if (nds.VCount == 263) { - nds.VCount=0; + nds.VCount = 0; + GPU->SetDisplayCaptureEnable(); } - else if(nds.VCount==262) + else if (nds.VCount == 262) { - if(!(NDS_ARM9.waitIRQ) && nds.overclock < 200 && CommonSettings.pokehax) { + if (!(NDS_ARM9.waitIRQ) && nds.overclock < 200 && CommonSettings.pokehax) + { nds.overclock++; nds.VCount = 261; } @@ -1504,8 +1503,14 @@ static void execHardware_hstart() execHardware_hstart_vblankEnd(); } } - else if(nds.VCount==192) + else if (nds.VCount == 261) { + nds.overclock = 0; + } + else if (nds.VCount == 192) + { + GPU->ResetDisplayCaptureEnable(); + //turn on vblank status bit T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 1); T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1); @@ -1541,7 +1546,7 @@ static void execHardware_hstart() //trigger hstart dmas triggerDma(EDMAMode_HStart); - if(nds.VCount<192) + if (nds.VCount < 192) { //this is hacky. //there is a corresponding hack in doDMA. diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 999539e03..6d8d3c836 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -502,6 +502,7 @@ extern struct TCommonSettings { , cheatsDisable(false) , rigorous_timing(false) , advanced_timing(true) + , pokehax(false) , micMode(InternalNoise) , spuInterpolationMode(1) , manualBackupType(0) diff --git a/desmume/src/commandline.cpp b/desmume/src/commandline.cpp index bc3ab14b1..e1cb36f43 100644 --- a/desmume/src/commandline.cpp +++ b/desmume/src/commandline.cpp @@ -354,7 +354,7 @@ bool CommandLine::parse(int argc,char **argv) if(_num_cores != -1) CommonSettings.num_cores = _num_cores; if(_rigorous_timing) CommonSettings.rigorous_timing = true; if(_advanced_timing != -1) CommonSettings.advanced_timing = _advanced_timing==1; - if(_advanced_timing != -1) CommonSettings.pokehax = _pokehax==1; + if(_pokehax != -1) CommonSettings.pokehax = _pokehax==1; #ifdef HAVE_JIT if(_cpu_mode != -1) CommonSettings.use_jit = (_cpu_mode==1);