From 0c41d2a7df02755867a7fbc30a92992466fb9367 Mon Sep 17 00:00:00 2001 From: PringlesGang Date: Wed, 5 Feb 2025 21:00:41 +0100 Subject: [PATCH] Implemented screencap rendering --- profiles/cc/game.lua | 1 + profiles/cclcc/game.lua | 1 + profiles/chlcc/game.lua | 3 +- profiles/chn/game.lua | 1 + profiles/darling/game.lua | 3 +- profiles/dash/game.lua | 1 + profiles/mo6tw/game.lua | 3 +- profiles/mo7/game.lua | 1 + profiles/mo8/game.lua | 1 + profiles/rne/game.lua | 1 + profiles/sgps3/game.lua | 3 +- src/background2d.cpp | 73 +++++++++++++++++++++++++++------------ src/background2d.h | 16 ++++++--- src/game.cpp | 11 ++++++ src/profile/vm.cpp | 8 ++++- src/profile/vm.h | 6 ++++ 16 files changed, 102 insertions(+), 31 deletions(-) diff --git a/profiles/cc/game.lua b/profiles/cc/game.lua index b8f3d0d1a..0826f382a 100644 --- a/profiles/cc/game.lua +++ b/profiles/cc/game.lua @@ -20,6 +20,7 @@ root.Vm = { UseReturnIds = true, ScrWorkChaStructSize = 40, ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 40, MaxLinkedBgBuffers = 2 }; diff --git a/profiles/cclcc/game.lua b/profiles/cclcc/game.lua index d932c6981..42eb2ded7 100644 --- a/profiles/cclcc/game.lua +++ b/profiles/cclcc/game.lua @@ -18,6 +18,7 @@ root.Vm = { UseReturnIds = true, ScrWorkChaStructSize = 40, ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 20, MaxLinkedBgBuffers = 2 }; diff --git a/profiles/chlcc/game.lua b/profiles/chlcc/game.lua index 0a2535c90..c87b3ad80 100644 --- a/profiles/chlcc/game.lua +++ b/profiles/chlcc/game.lua @@ -19,7 +19,8 @@ root.Vm = { GameInstructionSet = InstructionSet.CHLCC, UseReturnIds = false, ScrWorkChaStructSize = 20, - ScrWorkBgStructSize = 20 + ScrWorkBgStructSize = 20, + ScrWorkCaptureStructSize = 20, }; include('common/scriptinput.lua'); diff --git a/profiles/chn/game.lua b/profiles/chn/game.lua index 918061bab..ffffe96a3 100644 --- a/profiles/chn/game.lua +++ b/profiles/chn/game.lua @@ -18,6 +18,7 @@ root.Vm = { UseSeparateMsbArchive = true, ScrWorkChaStructSize = 40, ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 20, MaxLinkedBgBuffers = 2 }; diff --git a/profiles/darling/game.lua b/profiles/darling/game.lua index f9dfc056b..20153c0ab 100644 --- a/profiles/darling/game.lua +++ b/profiles/darling/game.lua @@ -18,7 +18,8 @@ root.Vm = { GameInstructionSet = InstructionSet.Darling, UseReturnIds = true, ScrWorkChaStructSize = 40, - ScrWorkBgStructSize = 40 + ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 20, }; include('common/scriptinput.lua'); diff --git a/profiles/dash/game.lua b/profiles/dash/game.lua index e033419f5..acc9f001f 100644 --- a/profiles/dash/game.lua +++ b/profiles/dash/game.lua @@ -14,6 +14,7 @@ root.Vm = { UseReturnIds = true, ScrWorkChaStructSize = 40, ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 20, MaxLinkedBgBuffers = 2 }; diff --git a/profiles/mo6tw/game.lua b/profiles/mo6tw/game.lua index 8d6e51d69..1d1c483b9 100644 --- a/profiles/mo6tw/game.lua +++ b/profiles/mo6tw/game.lua @@ -20,7 +20,8 @@ root.Vm = { UseReturnIds=false, RestartMaskUsesThreadAlpha=true, ScrWorkChaStructSize=20, - ScrWorkBgStructSize=20 + ScrWorkBgStructSize=20, + ScrWorkCaptureStructSize=20, }; include('common/scriptinput.lua'); diff --git a/profiles/mo7/game.lua b/profiles/mo7/game.lua index eca8cefd3..29d33fd0b 100644 --- a/profiles/mo7/game.lua +++ b/profiles/mo7/game.lua @@ -19,6 +19,7 @@ root.Vm = { UseReturnIds = true, ScrWorkChaStructSize = 40, ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 20, MaxLinkedBgBuffers = 2 }; diff --git a/profiles/mo8/game.lua b/profiles/mo8/game.lua index 55f75f786..306eac299 100644 --- a/profiles/mo8/game.lua +++ b/profiles/mo8/game.lua @@ -18,6 +18,7 @@ root.Vm = { UseMsbStrings = true, ScrWorkChaStructSize = 40, ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 20, MaxLinkedBgBuffers = 2 }; diff --git a/profiles/rne/game.lua b/profiles/rne/game.lua index c00ab2085..564b9aa14 100644 --- a/profiles/rne/game.lua +++ b/profiles/rne/game.lua @@ -14,6 +14,7 @@ root.Vm = { UseReturnIds = true, ScrWorkChaStructSize = 40, ScrWorkBgStructSize = 40, + ScrWorkCaptureStructSize = 20, MaxLinkedBgBuffers = 2 }; diff --git a/profiles/sgps3/game.lua b/profiles/sgps3/game.lua index 3eb2fcc1f..28d42d47f 100644 --- a/profiles/sgps3/game.lua +++ b/profiles/sgps3/game.lua @@ -19,7 +19,8 @@ root.Vm = { GameInstructionSet = InstructionSet.SGPS3, UseReturnIds = false, ScrWorkChaStructSize = 20, - ScrWorkBgStructSize = 20 + ScrWorkBgStructSize = 20, + ScrWorkCaptureStructSize = 20, }; include('common/scriptinput.lua'); diff --git a/src/background2d.cpp b/src/background2d.cpp index bb3bc4cc0..e2643e681 100644 --- a/src/background2d.cpp +++ b/src/background2d.cpp @@ -80,17 +80,53 @@ void Background2D::MainThreadOnLoad() { } void Background2D::Render(int bgId, int layer) { - if (Status == LS_Loaded && Layer == layer && Show) { - glm::vec4 col = glm::vec4(1.0f); - if (GameInstructionSet == +Vm::InstructionSet::Dash) { + if (Status != LS_Loaded || Layer != layer || !Show) return; + + IsScreencap = false; + + MaskNumber = ScrWork[SW_BG1MASKNO + ScrWorkBgStructSize * bgId]; + FadeCount = ScrWork[SW_BG1FADECT + ScrWorkBgStructSize * bgId]; + FadeRange = ScrWork[SW_BG1MASKFADERANGE + ScrWorkBgStructSize * bgId]; + + glm::vec4 col = glm::vec4(1.0f); + col.a = (ScrWork[SW_BG1ALPHA + ScrWorkBgStructSize * bgId] + + ScrWork[SW_BG1ALPHA_OFS + 10 * bgId]) / + 256.0f; + + switch (GameInstructionSet) { + case Vm::InstructionSet::Dash: col.a = ScrWork[SW_BG1ALPHA + ScrWorkBgStructSize * bgId] / 256.0f; - } else if (GameInstructionSet == +Vm::InstructionSet::CC) { + break; + + case Vm::InstructionSet::CC: if (ScrWork[SW_BGEFF_MODE + 30 * bgId] == 1) col.a = ScrWork[SW_BGEFF_ALPHA + 30 * bgId] / 256.0f; - } - int renderType = ScrWork[SW_BG1FADETYPE + ScrWorkBgStructSize * bgId]; - BackgroundRenderTable[renderType](this, bgId, col); + + default: + break; } + + const int renderType = ScrWork[SW_BG1FADETYPE + ScrWorkBgStructSize * bgId]; + BackgroundRenderTable[renderType](this, col); +} + +void Background2D::RenderCapture(int capId, int layer) { + if (Status != LS_Loaded || Layer != layer || !Show) return; + + IsScreencap = true; + + MaskNumber = ScrWork[SW_CAP1MASKNO + ScrWorkCaptureStructSize * capId]; + FadeCount = ScrWork[SW_CAP1FADECT + ScrWorkCaptureStructSize * capId]; + FadeRange = ScrWork[SW_CAP1MASKFADERANGE + ScrWorkCaptureStructSize * capId]; + + glm::vec4 col = glm::vec4(1.0f); + col.a = (ScrWork[SW_CAP1ALPHA + ScrWorkCaptureStructSize * capId] + + ScrWork[SW_CAP1ALPHA_OFS + 10 * capId]) / + 256.0f; + + const int renderType = + ScrWork[SW_CAP1FADETYPE + ScrWorkCaptureStructSize * capId]; + BackgroundRenderTable[renderType](this, col); } BackgroundRenderer(RenderRegular) { @@ -99,6 +135,7 @@ BackgroundRenderer(RenderRegular) { RectF(bg->DisplayCoords.x, bg->DisplayCoords.y, bg->BgSprite.ScaledWidth(), bg->BgSprite.ScaledHeight()), col, 0.0f, false, bg->IsScreencap); + for (int i = 0; i < MaxLinkedBgBuffers; i++) { if (bg->Links[i].Direction != LD_Off && bg->Links[i].LinkedBuffer != NULL) { Renderer->DrawSprite( @@ -113,37 +150,29 @@ BackgroundRenderer(RenderRegular) { BackgroundRenderer(RenderMasked) { Renderer->DrawMaskedSprite( - bg->BgSprite, - Masks2D[ScrWork[SW_BG1MASKNO + ScrWorkBgStructSize * bgId]].MaskSprite, + bg->BgSprite, Masks2D[bg->MaskNumber].MaskSprite, RectF(bg->DisplayCoords.x, bg->DisplayCoords.y, bg->BgSprite.ScaledWidth(), bg->BgSprite.ScaledHeight()), - col, ScrWork[SW_BG1FADECT + ScrWorkBgStructSize * bgId], - ScrWork[SW_BG1MASKFADERANGE + ScrWorkBgStructSize * bgId], - bg->IsScreencap); + col, bg->FadeCount, bg->FadeRange, bg->IsScreencap); } BackgroundRenderer(RenderMaskedInverted) { Renderer->DrawMaskedSprite( - bg->BgSprite, - Masks2D[ScrWork[SW_BG1MASKNO + ScrWorkBgStructSize * bgId]].MaskSprite, + bg->BgSprite, Masks2D[bg->MaskNumber].MaskSprite, RectF(bg->DisplayCoords.x, bg->DisplayCoords.y, bg->BgSprite.ScaledWidth(), bg->BgSprite.ScaledHeight()), - col, ScrWork[SW_BG1FADECT + ScrWorkBgStructSize * bgId], - ScrWork[SW_BG1MASKFADERANGE + ScrWorkBgStructSize * bgId], - bg->IsScreencap, true); + col, bg->FadeCount, bg->FadeRange, bg->IsScreencap, true); } BackgroundRenderer(RenderFade) { - col.a = ((ScrWork[SW_BG1FADECT + ScrWorkBgStructSize * bgId] * - (ScrWork[SW_BG1ALPHA + ScrWorkBgStructSize * bgId] + - ScrWork[SW_BG1ALPHA_OFS + 10 * bgId])) >> - 8) / - 256.0f; + col.a *= bg->FadeCount / 256.0f; + Renderer->DrawSprite( bg->BgSprite, RectF(bg->DisplayCoords.x, bg->DisplayCoords.y, bg->BgSprite.ScaledWidth(), bg->BgSprite.ScaledHeight()), col, 0.0f, false, bg->IsScreencap); + for (int i = 0; i < MaxLinkedBgBuffers; i++) { if (bg->Links[i].Direction != LD_Off && bg->Links[i].LinkedBuffer != NULL) { Renderer->DrawSprite( diff --git a/src/background2d.h b/src/background2d.h index 89b3298b1..d02ac7199 100644 --- a/src/background2d.h +++ b/src/background2d.h @@ -5,8 +5,7 @@ #include "spritesheet.h" #include "loadable.h" -#define BackgroundRenderer(name) \ - void name(Background2D* bg, int bgId, glm::vec4 col) +#define BackgroundRenderer(name) void name(Background2D* bg, glm::vec4 col) namespace Impacto { @@ -37,12 +36,21 @@ class Background2D : public Loadable { static void Init(); Sprite BgSprite; + glm::vec2 DisplayCoords; - LinkState Links[MaxLinks]; + int MaskNumber; + + int FadeCount; + int FadeRange; + bool Show; bool IsScreencap = false; + int Layer; + LinkState Links[MaxLinks]; + void Render(int bgId, int layer); + void RenderCapture(int capId, int layer); void LoadSolidColor(uint32_t color, int width, int height); protected: @@ -55,7 +63,7 @@ class Background2D : public Loadable { SpriteSheet BgSpriteSheet; }; -typedef void (*BackgroundRenderProc)(Background2D* bg, int bgId, glm::vec4 col); +typedef void (*BackgroundRenderProc)(Background2D* bg, glm::vec4 col); int constexpr MaxBackgrounds2D = 8; int constexpr MaxScreencaptures = 2; diff --git a/src/game.cpp b/src/game.cpp index 842062933..7dce0b612 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -355,6 +355,17 @@ void Render() { } } + for (size_t capId = 0; capId <= 1; capId++) { + if (!GetFlag(SF_CAP1DISP + capId)) continue; + + for (size_t capLayer = 0; capLayer <= 1; capLayer++) { + if (ScrWork[SW_CAP1PRI + capLayer * 10 + capLayer * 8] == + layer) { + Screencaptures[capId].RenderCapture(capId, layer); + } + } + } + if (Profile::UseScreenCapEffects) { if (ScrWork[SW_EFF_CAP_BUF] && ScrWork[SW_EFF_CAP_PRI] == static_cast(layer)) { diff --git a/src/profile/vm.cpp b/src/profile/vm.cpp index 597f31487..01ab2c90c 100644 --- a/src/profile/vm.cpp +++ b/src/profile/vm.cpp @@ -10,18 +10,24 @@ void Configure() { StartScript = EnsureGetMemberUint("StartScript"); StartScriptBuffer = EnsureGetMemberUint("StartScriptBuffer"); + GameInstructionSet = Impacto::Vm::InstructionSet::_from_integral_unchecked( EnsureGetMemberInt("GameInstructionSet")); + UseReturnIds = EnsureGetMemberBool("UseReturnIds"); TryGetMemberBool("UseMsbStrings", UseMsbStrings); TryGetMemberBool("UseSeparateMsbArchive", UseSeparateMsbArchive); + TryGetMemberBool("RestartMaskUsesThreadAlpha", RestartMaskUsesThreadAlpha); + ScrWorkChaStructSize = EnsureGetMemberInt("ScrWorkChaStructSize"); ScrWorkBgStructSize = EnsureGetMemberInt("ScrWorkBgStructSize"); + ScrWorkCaptureStructSize = EnsureGetMemberInt("ScrWorkCaptureStructSize"); + TryGetMemberInt("MaxLinkedBgBuffers", MaxLinkedBgBuffers); TryGetMemberInt("SystemScriptBuffer", SystemScriptBuffer); + TryGetMemberInt("SpeakerPortraitsScrWorkOffset", SpeakerPortraitsScrWorkOffset); - TryGetMemberBool("RestartMaskUsesThreadAlpha", RestartMaskUsesThreadAlpha); Pop(); } diff --git a/src/profile/vm.h b/src/profile/vm.h index 8ab30e5b6..b6f38702e 100644 --- a/src/profile/vm.h +++ b/src/profile/vm.h @@ -9,16 +9,22 @@ namespace Vm { inline uint32_t StartScript; inline uint32_t StartScriptBuffer; + inline Impacto::Vm::InstructionSet GameInstructionSet = Impacto::Vm::InstructionSet::RNE; + inline bool UseReturnIds = true; inline bool UseMsbStrings = false; inline bool UseSeparateMsbArchive = false; inline bool RestartMaskUsesThreadAlpha = false; + inline int ScrWorkChaStructSize; inline int ScrWorkBgStructSize; +inline int ScrWorkCaptureStructSize; + inline int MaxLinkedBgBuffers = 1; inline int SystemScriptBuffer = 1; + inline int SpeakerPortraitsScrWorkOffset = 8; void Configure();