diff --git a/Source/Core/Common/ChunkFile.h b/Source/Core/Common/ChunkFile.h index 1d71c44d0f..98dafbeac6 100644 --- a/Source/Core/Common/ChunkFile.h +++ b/Source/Core/Common/ChunkFile.h @@ -13,6 +13,7 @@ // - Zero backwards/forwards compatibility // - Serialization code for anything complex has to be manually written. +#include #include #include #include @@ -159,6 +160,12 @@ public: Do(x.second); } + template + void DoArray(std::array& x) + { + DoArray(x.data(), (u32)x.size()); + } + template void DoArray(T* x, u32 count) { diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp index 09db1697c3..2bcffc9a6e 100644 --- a/Source/Core/Core/State.cpp +++ b/Source/Core/Core/State.cpp @@ -63,7 +63,7 @@ static Common::Event g_compressAndDumpStateSyncEvent; static std::thread g_save_thread; // Don't forget to increase this after doing changes on the savestate system -static const u32 STATE_VERSION = 31; +static const u32 STATE_VERSION = 32; enum { diff --git a/Source/Core/VideoBackends/Software/BPMemLoader.cpp b/Source/Core/VideoBackends/Software/BPMemLoader.cpp index 990d21e539..f2aa429c49 100644 --- a/Source/Core/VideoBackends/Software/BPMemLoader.cpp +++ b/Source/Core/VideoBackends/Software/BPMemLoader.cpp @@ -145,10 +145,10 @@ void SWBPWritten(int address, int newvalue) } break; - case BPMEM_TEV_REGISTER_L: // Reg 1 - case BPMEM_TEV_REGISTER_L+2: // Reg 2 - case BPMEM_TEV_REGISTER_L+4: // Reg 3 - case BPMEM_TEV_REGISTER_L+6: // Reg 4 + case BPMEM_TEV_COLOR_RA: + case BPMEM_TEV_COLOR_RA + 2: + case BPMEM_TEV_COLOR_RA + 4: + case BPMEM_TEV_COLOR_RA + 6: { int regNum = (address >> 1 ) & 0x3; TevReg& reg = bpmem.tevregs[regNum]; @@ -160,10 +160,10 @@ void SWBPWritten(int address, int newvalue) break; } - case BPMEM_TEV_REGISTER_H: // Reg 1 - case BPMEM_TEV_REGISTER_H+2: // Reg 2 - case BPMEM_TEV_REGISTER_H+4: // Reg 3 - case BPMEM_TEV_REGISTER_H+6: // Reg 4 + case BPMEM_TEV_COLOR_BG: + case BPMEM_TEV_COLOR_BG + 2: + case BPMEM_TEV_COLOR_BG + 4: + case BPMEM_TEV_COLOR_BG + 6: { int regNum = (address >> 1 ) & 0x3; TevReg& reg = bpmem.tevregs[regNum]; diff --git a/Source/Core/VideoCommon/BPMemory.h b/Source/Core/VideoCommon/BPMemory.h index 3e5867c418..0d50f3ac51 100644 --- a/Source/Core/VideoCommon/BPMemory.h +++ b/Source/Core/VideoCommon/BPMemory.h @@ -80,8 +80,8 @@ #define BPMEM_TX_SETTLUT_4 0xB8 // 0xB8 + 4 #define BPMEM_TEV_COLOR_ENV 0xC0 // 0xC0 + (2 * 16) #define BPMEM_TEV_ALPHA_ENV 0xC1 // 0xC1 + (2 * 16) -#define BPMEM_TEV_REGISTER_L 0xE0 // 0xE0 + (2 * 4) -#define BPMEM_TEV_REGISTER_H 0xE1 // 0xE1 + (2 * 4) +#define BPMEM_TEV_COLOR_RA 0xE0 // 0xE0 + (2 * 4) +#define BPMEM_TEV_COLOR_BG 0xE1 // 0xE1 + (2 * 4) #define BPMEM_FOGRANGE 0xE8 // 0xE8 + 6 #define BPMEM_FOGPARAM0 0xEE #define BPMEM_FOGBMAGNITUDE 0xEF @@ -853,6 +853,8 @@ union TevReg BitField< 0, 32,u64> low; BitField<32, 32,u64> high; + // TODO: Check if Konst uses all 11 bits or just 8 + // Low register BitField< 0,11,s64> red; diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index 5910488f3c..308badae6e 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -480,6 +480,55 @@ static void BPWritten(const BPCmd& bp) } } return; + + // --------------------------------------------------- + // Set the TEV Color + // --------------------------------------------------- + // + // NOTE: Each of these registers actually maps to two variables internally. + // There's a bit that specifies which one is currently written to. + // + // NOTE: Some games write only to the RA register (or only to the BG register). + // We may not assume that the unwritten register holds a valid value, hence + // both component pairs need to be loaded individually. + case BPMEM_TEV_COLOR_RA: + case BPMEM_TEV_COLOR_RA + 2: + case BPMEM_TEV_COLOR_RA + 4: + case BPMEM_TEV_COLOR_RA + 6: + { + int num = (bp.address >> 1) & 0x3; + if (bpmem.tevregs[num].type_ra) + { + PixelShaderManager::SetTevKonstColor(num, 0, (s32)bpmem.tevregs[num].red); + PixelShaderManager::SetTevKonstColor(num, 3, (s32)bpmem.tevregs[num].alpha); + } + else + { + PixelShaderManager::SetTevColor(num, 0, (s32)bpmem.tevregs[num].red); + PixelShaderManager::SetTevColor(num, 3, (s32)bpmem.tevregs[num].alpha); + } + return; + } + + case BPMEM_TEV_COLOR_BG: + case BPMEM_TEV_COLOR_BG + 2: + case BPMEM_TEV_COLOR_BG + 4: + case BPMEM_TEV_COLOR_BG + 6: + { + int num = (bp.address >> 1) & 0x3; + if (bpmem.tevregs[num].type_bg) + { + PixelShaderManager::SetTevKonstColor(num, 1, (s32)bpmem.tevregs[num].green); + PixelShaderManager::SetTevKonstColor(num, 2, (s32)bpmem.tevregs[num].blue); + } + else + { + PixelShaderManager::SetTevColor(num, 1, (s32)bpmem.tevregs[num].green); + PixelShaderManager::SetTevColor(num, 2, (s32)bpmem.tevregs[num].blue); + } + return; + } + default: break; } @@ -548,29 +597,6 @@ static void BPWritten(const BPCmd& bp) case BPMEM_TX_SETTLUT_4: return; - // --------------------------------------------------- - // Set the TEV Color - // --------------------------------------------------- - case BPMEM_TEV_REGISTER_L: // Reg 1 - case BPMEM_TEV_REGISTER_H: - case BPMEM_TEV_REGISTER_L+2: // Reg 2 - case BPMEM_TEV_REGISTER_H+2: - case BPMEM_TEV_REGISTER_L+4: // Reg 3 - case BPMEM_TEV_REGISTER_H+4: - case BPMEM_TEV_REGISTER_L+6: // Reg 4 - case BPMEM_TEV_REGISTER_H+6: - // some games only send the _L part, so always update - // there actually are 2 register behind each of these - // addresses, selected by the type bit. - { - // don't compare with changes! - int num = (bp.address >> 1) & 0x3; - if ((bp.address & 1) == 0) - PixelShaderManager::SetColorChanged(static_cast(bpmem.tevregs[num].type_ra), num); - else - PixelShaderManager::SetColorChanged(static_cast(bpmem.tevregs[num].type_bg), num); - } - return; default: break; } @@ -1213,19 +1239,19 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc) break; } - case BPMEM_TEV_REGISTER_L: // 0xE0 - case BPMEM_TEV_REGISTER_L+2: - case BPMEM_TEV_REGISTER_L+4: - case BPMEM_TEV_REGISTER_L+6: - SetRegName(BPMEM_TEV_REGISTER_L); + case BPMEM_TEV_COLOR_RA: // 0xE0 + case BPMEM_TEV_COLOR_RA + 2: // 0xE2 + case BPMEM_TEV_COLOR_RA + 4: // 0xE4 + case BPMEM_TEV_COLOR_RA + 6: // 0xE6 + SetRegName(BPMEM_TEV_COLOR_RA); // TODO: Description break; - case BPMEM_TEV_REGISTER_H: // 0xE1 - case BPMEM_TEV_REGISTER_H+2: - case BPMEM_TEV_REGISTER_H+4: - case BPMEM_TEV_REGISTER_H+6: - SetRegName(BPMEM_TEV_REGISTER_H); + case BPMEM_TEV_COLOR_BG: // 0xE1 + case BPMEM_TEV_COLOR_BG + 2: // 0xE3 + case BPMEM_TEV_COLOR_BG + 4: // 0xE5 + case BPMEM_TEV_COLOR_BG + 6: // 0xE7 + SetRegName(BPMEM_TEV_COLOR_BG); // TODO: Description break; diff --git a/Source/Core/VideoCommon/PixelShaderManager.cpp b/Source/Core/VideoCommon/PixelShaderManager.cpp index d9c601e42c..cbd68ce92e 100644 --- a/Source/Core/VideoCommon/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/PixelShaderManager.cpp @@ -12,8 +12,11 @@ #include "VideoCommon/VideoCommon.h" #include "VideoCommon/VideoConfig.h" -static bool s_bFogRangeAdjustChanged; -static bool s_bViewPortChanged; +bool PixelShaderManager::s_bFogRangeAdjustChanged; +bool PixelShaderManager::s_bViewPortChanged; + +std::array PixelShaderManager::s_tev_color; +std::array PixelShaderManager::s_tev_konst_color; PixelShaderConstants PixelShaderManager::constants; bool PixelShaderManager::dirty; @@ -21,6 +24,9 @@ bool PixelShaderManager::dirty; void PixelShaderManager::Init() { memset(&constants, 0, sizeof(constants)); + memset(s_tev_color.data(), 0, sizeof(s_tev_color)); + memset(s_tev_konst_color.data(), 0, sizeof(s_tev_konst_color)); + Dirty(); } @@ -29,14 +35,15 @@ void PixelShaderManager::Dirty() s_bFogRangeAdjustChanged = true; s_bViewPortChanged = true; - SetColorChanged(0, 0); - SetColorChanged(0, 1); - SetColorChanged(0, 2); - SetColorChanged(0, 3); - SetColorChanged(1, 0); - SetColorChanged(1, 1); - SetColorChanged(1, 2); - SetColorChanged(1, 3); + for (unsigned index = 0; index < s_tev_color.size(); ++index) + { + for (int comp = 0; comp < 4; ++comp) + { + SetTevColor(index, comp, s_tev_color[index][comp]); + SetTevKonstColor(index, comp, s_tev_konst_color[index][comp]); + } + } + SetAlpha(); SetDestAlpha(); SetZTextureBias(); @@ -107,16 +114,22 @@ void PixelShaderManager::SetConstants() } } -void PixelShaderManager::SetColorChanged(int type, int num) +void PixelShaderManager::SetTevColor(int index, int component, s32 value) { - int4* c = type ? constants.kcolors : constants.colors; - c[num][0] = static_cast(bpmem.tevregs[num].red); - c[num][3] = static_cast(bpmem.tevregs[num].alpha); - c[num][2] = static_cast(bpmem.tevregs[num].blue); - c[num][1] = static_cast(bpmem.tevregs[num].green); + auto& c = constants.colors[index]; + c[component] = s_tev_color[index][component] = value; dirty = true; - PRIM_LOG("pixel %scolor%d: %d %d %d %d\n", type?"k":"", num, c[num][0], c[num][1], c[num][2], c[num][3]); + PRIM_LOG("tev color%d: %d %d %d %d\n", index, c[0], c[1], c[2], c[3]); +} + +void PixelShaderManager::SetTevKonstColor(int index, int component, s32 value) +{ + auto& c = constants.kcolors[index]; + c[component] = s_tev_konst_color[index][component] = value; + dirty = true; + + PRIM_LOG("tev konst color%d: %d %d %d %d\n", index, c[0], c[1], c[2], c[3]); } void PixelShaderManager::SetAlpha() @@ -265,11 +278,13 @@ void PixelShaderManager::SetFogRangeAdjustChanged() void PixelShaderManager::DoState(PointerWrap &p) { - p.Do(constants); - p.Do(dirty); + p.DoArray(s_tev_color); + p.DoArray(s_tev_konst_color); if (p.GetMode() == PointerWrap::MODE_READ) { + // Reload current state from global GPU state + // NOTE: This requires that all GPU memory has been loaded already. Dirty(); } } diff --git a/Source/Core/VideoCommon/PixelShaderManager.h b/Source/Core/VideoCommon/PixelShaderManager.h index 5c07b0522a..ebf299d9fc 100644 --- a/Source/Core/VideoCommon/PixelShaderManager.h +++ b/Source/Core/VideoCommon/PixelShaderManager.h @@ -4,6 +4,8 @@ #pragma once +#include + #include "VideoCommon/BPMemory.h" #include "VideoCommon/ConstantManager.h" #include "VideoCommon/PixelShaderGen.h" @@ -24,8 +26,11 @@ public: static void SetConstants(); // sets pixel shader constants - // constant management, should be called after memory is committed - static void SetColorChanged(int type, int index); + // constant management + // Some of these functions grab the constant values from global state, + // so make sure to call them after memory is committed + static void SetTevColor(int index, int component, s32 value); + static void SetTevKonstColor(int index, int component, s32 value); static void SetAlpha(); static void SetDestAlpha(); static void SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt); @@ -42,4 +47,12 @@ public: static PixelShaderConstants constants; static bool dirty; + + static bool s_bFogRangeAdjustChanged; + static bool s_bViewPortChanged; + + // These colors aren't available from global BP state, + // hence we keep a copy of them around. + static std::array s_tev_color; + static std::array s_tev_konst_color; };