GPU: Implement the DISPCNT register's ForceBlank bit by clearing the line to white if the ForceBlank bit is set. (Fixes #775.)
This commit is contained in:
parent
0a6eca6dce
commit
bae67e2d0c
|
@ -924,6 +924,11 @@ const GPU_IOREG& GPUEngineBase::GetIORegisterMap() const
|
||||||
return *this->_IORegisterMap;
|
return *this->_IORegisterMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GPUEngineBase::IsForceBlankSet() const
|
||||||
|
{
|
||||||
|
return (this->_IORegisterMap->DISPCNT.ForceBlank != 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool GPUEngineBase::IsMasterBrightMaxOrMin() const
|
bool GPUEngineBase::IsMasterBrightMaxOrMin() const
|
||||||
{
|
{
|
||||||
return this->_currentRenderState.masterBrightnessIsMaxOrMin;
|
return this->_currentRenderState.masterBrightnessIsMaxOrMin;
|
||||||
|
@ -2940,11 +2945,18 @@ void GPUEngineBase::RenderLayerBG(const GPULayerID layerID, u16 *dstColorBuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPUEngineBase::_RenderLineBlank(const size_t l)
|
||||||
|
{
|
||||||
|
// Native rendering only.
|
||||||
|
// Just clear the line using white pixels.
|
||||||
|
memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(this->_targetDisplay->GetNativeBuffer16() + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH), 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
void GPUEngineBase::_HandleDisplayModeOff(const size_t l)
|
void GPUEngineBase::_HandleDisplayModeOff(const size_t l)
|
||||||
{
|
{
|
||||||
// Native rendering only.
|
// Native rendering only.
|
||||||
// In this display mode, the display is cleared to white.
|
// In this display mode, the line is cleared to white.
|
||||||
memset_u16_fast<GPU_FRAMEBUFFER_NATIVE_WIDTH>(this->_targetDisplay->GetNativeBuffer16() + (l * GPU_FRAMEBUFFER_NATIVE_WIDTH), 0xFFFF);
|
this->_RenderLineBlank(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUEngineBase::_HandleDisplayModeNormal(const size_t l)
|
void GPUEngineBase::_HandleDisplayModeNormal(const size_t l)
|
||||||
|
@ -3536,23 +3548,30 @@ void GPUEngineA::RenderLine(const size_t l)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill the display output
|
// Fill the display output
|
||||||
switch (compInfo.renderState.displayOutputMode)
|
if ( this->IsForceBlankSet() )
|
||||||
{
|
{
|
||||||
case GPUDisplayMode_Off: // Display Off (Display white)
|
this->_RenderLineBlank(l);
|
||||||
this->_HandleDisplayModeOff(l);
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
switch (compInfo.renderState.displayOutputMode)
|
||||||
this->_HandleDisplayModeNormal(l);
|
{
|
||||||
break;
|
case GPUDisplayMode_Off: // Display Off (clear line to white)
|
||||||
|
this->_HandleDisplayModeOff(l);
|
||||||
case GPUDisplayMode_VRAM: // Display VRAM framebuffer
|
break;
|
||||||
this->_HandleDisplayModeVRAM<OUTPUTFORMAT>(compInfo.line);
|
|
||||||
break;
|
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
||||||
|
this->_HandleDisplayModeNormal(l);
|
||||||
case GPUDisplayMode_MainMemory: // Display Memory FIFO
|
break;
|
||||||
this->_HandleDisplayModeMainMemory(compInfo.line);
|
|
||||||
break;
|
case GPUDisplayMode_VRAM: // Display VRAM framebuffer
|
||||||
|
this->_HandleDisplayModeVRAM<OUTPUTFORMAT>(compInfo.line);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPUDisplayMode_MainMemory: // Display Memory FIFO
|
||||||
|
this->_HandleDisplayModeMainMemory(compInfo.line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//capture after displaying so that we can safely display vram before overwriting it here
|
//capture after displaying so that we can safely display vram before overwriting it here
|
||||||
|
@ -4533,29 +4552,36 @@ void GPUEngineB::RenderLine(const size_t l)
|
||||||
{
|
{
|
||||||
GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[l];
|
GPUEngineCompositorInfo &compInfo = this->_currentCompositorInfo[l];
|
||||||
|
|
||||||
switch (compInfo.renderState.displayOutputMode)
|
if ( this->IsForceBlankSet() )
|
||||||
{
|
{
|
||||||
case GPUDisplayMode_Off: // Display Off(Display white)
|
this->_RenderLineBlank(l);
|
||||||
this->_HandleDisplayModeOff(l);
|
}
|
||||||
break;
|
else
|
||||||
|
{
|
||||||
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
switch (compInfo.renderState.displayOutputMode)
|
||||||
{
|
{
|
||||||
if (compInfo.renderState.isAnyWindowEnabled)
|
case GPUDisplayMode_Off: // Display Off (clear line to white)
|
||||||
{
|
this->_HandleDisplayModeOff(l);
|
||||||
this->_RenderLine_Layers<OUTPUTFORMAT, true>(compInfo);
|
break;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->_RenderLine_Layers<OUTPUTFORMAT, false>(compInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->_HandleDisplayModeNormal(l);
|
case GPUDisplayMode_Normal: // Display BG and OBJ layers
|
||||||
break;
|
{
|
||||||
|
if (compInfo.renderState.isAnyWindowEnabled)
|
||||||
|
{
|
||||||
|
this->_RenderLine_Layers<OUTPUTFORMAT, true>(compInfo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->_RenderLine_Layers<OUTPUTFORMAT, false>(compInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_HandleDisplayModeNormal(l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compInfo.line.indexNative >= 191)
|
if (compInfo.line.indexNative >= 191)
|
||||||
|
@ -5454,7 +5480,7 @@ void GPUSubsystem::RenderLine(const size_t l)
|
||||||
this->_engineSub->UpdateRenderStates(l);
|
this->_engineSub->UpdateRenderStates(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || isDisplayCaptureNeeded) && !this->_willFrameSkip )
|
if ( (isFramebufferRenderNeeded[GPUEngineID_Main] || this->_engineMain->IsForceBlankSet() || isDisplayCaptureNeeded) && !this->_willFrameSkip )
|
||||||
{
|
{
|
||||||
// GPUEngineA:WillRender3DLayer() and GPUEngineA:WillCapture3DLayerDirect() both rely on register
|
// GPUEngineA:WillRender3DLayer() and GPUEngineA:WillCapture3DLayerDirect() both rely on register
|
||||||
// states that might change on a per-line basis. Therefore, we need to check these states on a
|
// states that might change on a per-line basis. Therefore, we need to check these states on a
|
||||||
|
@ -5502,7 +5528,7 @@ void GPUSubsystem::RenderLine(const size_t l)
|
||||||
this->_engineMain->UpdatePropertiesWithoutRender(l);
|
this->_engineMain->UpdatePropertiesWithoutRender(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isFramebufferRenderNeeded[GPUEngineID_Sub] && !this->_willFrameSkip)
|
if ( (isFramebufferRenderNeeded[GPUEngineID_Sub] || this->_engineSub->IsForceBlankSet()) && !this->_willFrameSkip)
|
||||||
{
|
{
|
||||||
switch (this->_engineSub->GetTargetDisplay()->GetColorFormat())
|
switch (this->_engineSub->GetTargetDisplay()->GetColorFormat())
|
||||||
{
|
{
|
||||||
|
|
|
@ -117,7 +117,7 @@ typedef union
|
||||||
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
|
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
|
||||||
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
|
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
|
||||||
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
|
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
|
||||||
u8 ForceBlank:1; // 7: A+B;
|
u8 ForceBlank:1; // 7: A+B; 0=Disable, 1=Enable (causes the line to render all white)
|
||||||
|
|
||||||
u8 BG0_Enable:1; // 8: A+B; 0=Disable, 1=Enable
|
u8 BG0_Enable:1; // 8: A+B; 0=Disable, 1=Enable
|
||||||
u8 BG1_Enable:1; // 9: A+B; 0=Disable, 1=Enable
|
u8 BG1_Enable:1; // 9: A+B; 0=Disable, 1=Enable
|
||||||
|
@ -143,7 +143,7 @@ typedef union
|
||||||
u8 ExBGxPalette_Enable:1; // 30: A+B; 0=Disable, 1=Enable BG extended Palette
|
u8 ExBGxPalette_Enable:1; // 30: A+B; 0=Disable, 1=Enable BG extended Palette
|
||||||
u8 ExOBJPalette_Enable:1; // 31: A+B; 0=Disable, 1=Enable OBJ extended Palette
|
u8 ExOBJPalette_Enable:1; // 31: A+B; 0=Disable, 1=Enable OBJ extended Palette
|
||||||
#else
|
#else
|
||||||
u8 ForceBlank:1; // 7: A+B;
|
u8 ForceBlank:1; // 7: A+B; 0=Disable, 1=Enable (causes the line to render all white)
|
||||||
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
|
u8 OBJ_BMP_mapping:1; // 6: A+B; 0=2D (128KB), 1=1D (128..256KB)
|
||||||
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
|
u8 OBJ_BMP_2D_dim:1; // 5: A+B; 0=128x512, 1=256x256 pixels
|
||||||
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
|
u8 OBJ_Tile_mapping:1; // 4: A+B; 0=2D (32KB), 1=1D (32..256KB)
|
||||||
|
@ -1543,6 +1543,8 @@ protected:
|
||||||
void _RenderLine_SetupSprites(GPUEngineCompositorInfo &compInfo);
|
void _RenderLine_SetupSprites(GPUEngineCompositorInfo &compInfo);
|
||||||
template<NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _RenderLine_Layers(GPUEngineCompositorInfo &compInfo);
|
template<NDSColorFormat OUTPUTFORMAT, bool WILLPERFORMWINDOWTEST> void _RenderLine_Layers(GPUEngineCompositorInfo &compInfo);
|
||||||
|
|
||||||
|
void _RenderLineBlank(const size_t l);
|
||||||
|
|
||||||
void _HandleDisplayModeOff(const size_t l);
|
void _HandleDisplayModeOff(const size_t l);
|
||||||
void _HandleDisplayModeNormal(const size_t l);
|
void _HandleDisplayModeNormal(const size_t l);
|
||||||
|
|
||||||
|
@ -1609,6 +1611,7 @@ public:
|
||||||
|
|
||||||
const GPU_IOREG& GetIORegisterMap() const;
|
const GPU_IOREG& GetIORegisterMap() const;
|
||||||
|
|
||||||
|
bool IsForceBlankSet() const;
|
||||||
bool IsMasterBrightMaxOrMin() const;
|
bool IsMasterBrightMaxOrMin() const;
|
||||||
|
|
||||||
bool GetEnableState();
|
bool GetEnableState();
|
||||||
|
|
Loading…
Reference in New Issue