fixed some graphics problems with loading savestates (for example, wrong colors on title screen of metroid prime 3)

This commit is contained in:
nitsuja 2012-01-01 12:46:02 -08:00 committed by skidau
parent 19b0b02ad7
commit 2be579e8ba
10 changed files with 107 additions and 58 deletions

View File

@ -39,7 +39,7 @@ void FlushPipeline()
VertexManager::Flush(); VertexManager::Flush();
} }
void SetGenerationMode(const BPCmd &bp) void SetGenerationMode()
{ {
g_renderer->SetGenerationMode(); g_renderer->SetGenerationMode();
} }
@ -64,30 +64,30 @@ void SetScissor()
g_renderer->SetScissorRect(trc); g_renderer->SetScissorRect(trc);
} }
void SetLineWidth(const BPCmd &bp) void SetLineWidth()
{ {
g_renderer->SetLineWidth(); g_renderer->SetLineWidth();
} }
void SetDepthMode(const BPCmd &bp) void SetDepthMode()
{ {
g_renderer->SetDepthMode(); g_renderer->SetDepthMode();
} }
void SetBlendMode(const BPCmd &bp) void SetBlendMode()
{ {
g_renderer->SetBlendMode(false); g_renderer->SetBlendMode(false);
} }
void SetDitherMode(const BPCmd &bp) void SetDitherMode()
{ {
g_renderer->SetDitherMode(); g_renderer->SetDitherMode();
} }
void SetLogicOpMode(const BPCmd &bp) void SetLogicOpMode()
{ {
g_renderer->SetLogicOpMode(); g_renderer->SetLogicOpMode();
} }
void SetColorMask(const BPCmd &bp) void SetColorMask()
{ {
g_renderer->SetColorMask(); g_renderer->SetColorMask();
} }
@ -119,7 +119,7 @@ void CopyEFB(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
- convert the RGBA8 color to RGBA6/RGB8/RGB565 and convert it to RGBA8 again - convert the RGBA8 color to RGBA6/RGB8/RGB565 and convert it to RGBA8 again
- convert the Z24 depth value to Z16 and back to Z24 - convert the Z24 depth value to Z16 and back to Z24
*/ */
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc) void ClearScreen(const EFBRectangle &rc)
{ {
bool colorEnable = bpmem.blendmode.colorupdate; bool colorEnable = bpmem.blendmode.colorupdate;
bool alphaEnable = bpmem.blendmode.alphaupdate; bool alphaEnable = bpmem.blendmode.alphaupdate;
@ -152,7 +152,7 @@ void ClearScreen(const BPCmd &bp, const EFBRectangle &rc)
} }
} }
void OnPixelFormatChange(const BPCmd &bp) void OnPixelFormatChange()
{ {
int convtype = -1; int convtype = -1;

View File

@ -37,18 +37,18 @@ enum
}; };
void FlushPipeline(); void FlushPipeline();
void SetGenerationMode(const BPCmd &bp); void SetGenerationMode();
void SetScissor(); void SetScissor();
void SetLineWidth(const BPCmd &bp); void SetLineWidth();
void SetDepthMode(const BPCmd &bp); void SetDepthMode();
void SetBlendMode(const BPCmd &bp); void SetBlendMode();
void SetDitherMode(const BPCmd &bp); void SetDitherMode();
void SetLogicOpMode(const BPCmd &bp); void SetLogicOpMode();
void SetColorMask(const BPCmd &bp); void SetColorMask();
void CopyEFB(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat, void CopyEFB(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf); const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf);
void ClearScreen(const BPCmd &bp, const EFBRectangle &rc); void ClearScreen(const EFBRectangle &rc);
void OnPixelFormatChange(const BPCmd &bp); void OnPixelFormatChange();
u8 *GetPointer(const u32 &address); u8 *GetPointer(const u32 &address);
bool GetConfig(const int &type); bool GetConfig(const int &type);
void SetTextureMode(const BPCmd &bp); void SetTextureMode(const BPCmd &bp);

View File

@ -43,31 +43,6 @@ void LoadBPReg(u32 value0)
BPWritten(bp); BPWritten(bp);
} }
// Called when loading a saved state.
// Needs more testing though.
void BPReload()
{
for (int i = 0; i < 254; i++)
{
switch (i)
{
case BPMEM_BLENDMODE:
case BPMEM_SETDRAWDONE:
case BPMEM_TRIGGER_EFB_COPY:
case BPMEM_LOADTLUT1:
case BPMEM_PERF1:
case BPMEM_PE_TOKEN_ID:
case BPMEM_PE_TOKEN_INT_ID:
// Cases in which we DON'T want to reload the BP
continue;
default:
BPCmd bp = {i, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[i])};
BPWritten(bp);
}
}
}
void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size_t desc_size) void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size_t desc_size)
{ {
const char* no_yes[2] = { "No", "Yes" }; const char* no_yes[2] = { "No", "Yes" };

View File

@ -160,7 +160,7 @@ void BPWritten(const BPCmd& bp)
bpmem.genMode.numtexgens, bpmem.genMode.numcolchans, bpmem.genMode.numtexgens, bpmem.genMode.numcolchans,
bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode, bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode,
bpmem.genMode.numindstages, bpmem.genMode.zfreeze); bpmem.genMode.numindstages, bpmem.genMode.zfreeze);
SetGenerationMode(bp); SetGenerationMode();
break; break;
} }
case BPMEM_IND_MTXA: // Index Matrix Changed case BPMEM_IND_MTXA: // Index Matrix Changed
@ -188,12 +188,12 @@ void BPWritten(const BPCmd& bp)
SetScissor(); SetScissor();
break; break;
case BPMEM_LINEPTWIDTH: // Line Width case BPMEM_LINEPTWIDTH: // Line Width
SetLineWidth(bp); SetLineWidth();
break; break;
case BPMEM_ZMODE: // Depth Control case BPMEM_ZMODE: // Depth Control
PRIM_LOG("zmode: test=%d, func=%d, upd=%d", bpmem.zmode.testenable, bpmem.zmode.func, PRIM_LOG("zmode: test=%d, func=%d, upd=%d", bpmem.zmode.testenable, bpmem.zmode.func,
bpmem.zmode.updateenable); bpmem.zmode.updateenable);
SetDepthMode(bp); SetDepthMode();
break; break;
case BPMEM_BLENDMODE: // Blending Control case BPMEM_BLENDMODE: // Blending Control
{ {
@ -204,16 +204,16 @@ void BPWritten(const BPCmd& bp)
bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode); bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode);
// Set LogicOp Blending Mode // Set LogicOp Blending Mode
if (bp.changes & 2) if (bp.changes & 2)
SetLogicOpMode(bp); SetLogicOpMode();
// Set Dithering Mode // Set Dithering Mode
if (bp.changes & 4) if (bp.changes & 4)
SetDitherMode(bp); SetDitherMode();
// Set Blending Mode // Set Blending Mode
if (bp.changes & 0xFE1) if (bp.changes & 0xFE1)
SetBlendMode(bp); SetBlendMode();
// Set Color Mask // Set Color Mask
if (bp.changes & 0x18) if (bp.changes & 0x18)
SetColorMask(bp); SetColorMask();
} }
break; break;
} }
@ -306,7 +306,7 @@ void BPWritten(const BPCmd& bp)
// Clear the rectangular region after copying it. // Clear the rectangular region after copying it.
if (PE_copy.clear) if (PE_copy.clear)
{ {
ClearScreen(bp, rc); ClearScreen(rc);
} }
break; break;
@ -455,7 +455,7 @@ void BPWritten(const BPCmd& bp)
case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
OnPixelFormatChange(bp); OnPixelFormatChange();
break; break;
case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel
@ -680,3 +680,35 @@ void BPWritten(const BPCmd& bp)
} }
} }
// Called when loading a saved state.
void BPReload()
{
// restore anything that goes straight to the renderer.
// let's not risk actually replaying any writes.
// note that PixelShaderManager is already covered since it has its own DoState.
SetGenerationMode();
SetScissor();
SetLineWidth();
SetDepthMode();
SetLogicOpMode();
SetDitherMode();
SetBlendMode();
SetColorMask();
OnPixelFormatChange();
{
BPCmd bp = {BPMEM_TX_SETMODE0, 0xFFFFFF, ((u32*)&bpmem)[BPMEM_TX_SETMODE0]};
SetTextureMode(bp);
}
{
BPCmd bp = {BPMEM_TX_SETMODE0_4, 0xFFFFFF, ((u32*)&bpmem)[BPMEM_TX_SETMODE0_4]};
SetTextureMode(bp);
}
{
BPCmd bp = {BPMEM_FIELDMASK, 0xFFFFFF, ((u32*)&bpmem)[BPMEM_FIELDMASK]};
SetInterlacingMode(bp);
}
{
BPCmd bp = {BPMEM_FIELDMODE, 0xFFFFFF, ((u32*)&bpmem)[BPMEM_FIELDMODE]};
SetInterlacingMode(bp);
}
}

View File

@ -185,10 +185,6 @@ void VideoBackendHardware::InitializeShared()
// Run from the CPU thread // Run from the CPU thread
void VideoBackendHardware::DoState(PointerWrap& p) void VideoBackendHardware::DoState(PointerWrap& p)
{ {
// Clear all caches that touch RAM
TextureCache::Invalidate(false);
VertexLoaderManager::MarkAllDirty();
VideoCommon_DoState(p); VideoCommon_DoState(p);
// Refresh state. // Refresh state.
@ -196,6 +192,11 @@ void VideoBackendHardware::DoState(PointerWrap& p)
{ {
BPReload(); BPReload();
RecomputeCachedArraybases(); RecomputeCachedArraybases();
// Clear all caches that touch RAM
// (? these don't appear to touch any emulation state that gets saved. moved to on load only.)
TextureCache::Invalidate(false);
VertexLoaderManager::MarkAllDirty();
} }
} }

View File

@ -465,3 +465,16 @@ void PixelShaderManager::SetMaterialColorChanged(int index)
{ {
nMaterialsChanged |= (1 << index); nMaterialsChanged |= (1 << index);
} }
void PixelShaderManager::DoState(PointerWrap &p)
{
p.Do(lastRGBAfull);
p.Do(lastAlpha);
p.Do(lastTexDims);
p.Do(lastZBias);
if (p.GetMode() == PointerWrap::MODE_READ)
{
Dirty();
}
}

View File

@ -22,6 +22,8 @@
#include "XFMemory.h" #include "XFMemory.h"
#include "PixelShaderGen.h" #include "PixelShaderGen.h"
class PointerWrap;
// The non-API dependent parts. // The non-API dependent parts.
class PixelShaderManager class PixelShaderManager
{ {
@ -30,6 +32,7 @@ public:
static void Init(); static void Init();
static void Dirty(); static void Dirty();
static void Shutdown(); static void Shutdown();
static void DoState(PointerWrap &p);
static void SetConstants(); // sets pixel shader constants static void SetConstants(); // sets pixel shader constants

View File

@ -616,3 +616,18 @@ void VertexShaderManager::ResetView()
bProjectionChanged = true; bProjectionChanged = true;
} }
void VertexShaderManager::DoState(PointerWrap &p)
{
p.Do(g_fProjectionMatrix);
p.Do(s_viewportCorrection);
p.Do(s_viewRotationMatrix);
p.Do(s_viewInvRotationMatrix);
p.Do(s_fViewTranslationVector);
p.Do(s_fViewRotation);
if (p.GetMode() == PointerWrap::MODE_READ)
{
Dirty();
}
}

View File

@ -20,6 +20,8 @@
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
class PointerWrap;
struct ProjectionHack struct ProjectionHack
{ {
float sign; float sign;
@ -38,7 +40,8 @@ public:
static void Init(); static void Init();
static void Dirty(); static void Dirty();
static void Shutdown(); static void Shutdown();
static void DoState(PointerWrap &p);
;
// constant management // constant management
static void SetConstants(); static void SetConstants();

View File

@ -24,6 +24,8 @@
#include "Fifo.h" #include "Fifo.h"
#include "CommandProcessor.h" #include "CommandProcessor.h"
#include "PixelEngine.h" #include "PixelEngine.h"
#include "PixelShaderManager.h"
#include "VertexShaderManager.h"
static void DoState(PointerWrap &p) static void DoState(PointerWrap &p)
{ {
@ -48,12 +50,17 @@ static void DoState(PointerWrap &p)
CommandProcessor::DoState(p); CommandProcessor::DoState(p);
PixelEngine::DoState(p); PixelEngine::DoState(p);
// the old way of replaying current bpmem as writes to push side effects to pixel shader manager doesn't really work.
PixelShaderManager::DoState(p);
VertexShaderManager::DoState(p);
// TODO: search for more data that should be saved and add it here
} }
void VideoCommon_DoState(PointerWrap &p) void VideoCommon_DoState(PointerWrap &p)
{ {
DoState(p); DoState(p);
//TODO: search for more data that should be saved and add it here
} }
void VideoCommon_RunLoop(bool enable) void VideoCommon_RunLoop(bool enable)