mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Implemented controller LED timings for cutscenes (#83)
This commit is contained in:
parent
666f93843d
commit
63d474ce91
18 changed files with 262 additions and 23 deletions
|
|
@ -152,6 +152,7 @@ set(SWA_PATCHES_CXX_SOURCES
|
|||
"patches/audio_patches.cpp"
|
||||
"patches/camera_patches.cpp"
|
||||
"patches/fps_patches.cpp"
|
||||
"patches/inspire_patches.cpp"
|
||||
"patches/misc_patches.cpp"
|
||||
"patches/object_patches.cpp"
|
||||
"patches/player_patches.cpp"
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@
|
|||
#include "SWA/HUD/Sonic/HudSonicStage.h"
|
||||
#include "SWA/Inspire/InspireMovieOverlay.h"
|
||||
#include "SWA/Inspire/InspireMovieOverlayInfo.h"
|
||||
#include "SWA/Inspire/InspireOpacityAnimationInfo.h"
|
||||
#include "SWA/Inspire/InspireScene.h"
|
||||
#include "SWA/Inspire/InspireSceneData.h"
|
||||
#include "SWA/Inspire/InspireSceneInfo.h"
|
||||
#include "SWA/Inspire/InspireTextureAnimationInfo.h"
|
||||
#include "SWA/Inspire/InspireTextureOverlay.h"
|
||||
#include "SWA/Inspire/InspireTextureOverlayInfo.h"
|
||||
#include "SWA/Movie/MovieDisplayer.h"
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ namespace SWA::Inspire
|
|||
{
|
||||
public:
|
||||
Hedgehog::Base::CSharedString m_MovieName;
|
||||
be<float> m_StartTime;
|
||||
be<float> m_FadeInStartTime;
|
||||
be<float> m_FadeInEndTime;
|
||||
be<float> m_FadeOutStartTime;
|
||||
be<float> m_FadeOutEndTime;
|
||||
be<float> m_Prepare;
|
||||
be<float> m_InStart;
|
||||
be<float> m_InEnd;
|
||||
be<float> m_OutStart;
|
||||
be<float> m_OutEnd;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <SWA.inl>
|
||||
|
||||
namespace SWA::Inspire
|
||||
{
|
||||
class COpacityAnimationInfo
|
||||
{
|
||||
public:
|
||||
be<float> m_Opacity;
|
||||
be<float> m_Frame;
|
||||
};
|
||||
}
|
||||
21
UnleashedRecomp/api/SWA/Inspire/InspireScene.h
Normal file
21
UnleashedRecomp/api/SWA/Inspire/InspireScene.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <SWA.inl>
|
||||
|
||||
namespace SWA::Inspire
|
||||
{
|
||||
struct SSceneData
|
||||
{
|
||||
be<float> Frame;
|
||||
be<uint32_t> Cut;
|
||||
bool IsPlaying;
|
||||
SWA_INSERT_PADDING(0x177);
|
||||
};
|
||||
|
||||
class CScene
|
||||
{
|
||||
public:
|
||||
SWA_INSERT_PADDING(0xC0);
|
||||
xpointer<SSceneData> m_pData;
|
||||
};
|
||||
}
|
||||
13
UnleashedRecomp/api/SWA/Inspire/InspireSceneData.h
Normal file
13
UnleashedRecomp/api/SWA/Inspire/InspireSceneData.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <SWA.inl>
|
||||
|
||||
namespace SWA::Inspire
|
||||
{
|
||||
class CSceneData // : public Hedgehog::Database::CDatabaseData
|
||||
{
|
||||
public:
|
||||
SWA_INSERT_PADDING(0x80);
|
||||
Hedgehog::Base::CSharedString m_ResourceName;
|
||||
};
|
||||
}
|
||||
8
UnleashedRecomp/api/SWA/Inspire/InspireSceneInfo.h
Normal file
8
UnleashedRecomp/api/SWA/Inspire/InspireSceneInfo.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <SWA.inl>
|
||||
|
||||
namespace SWA::Inspire
|
||||
{
|
||||
class CSceneInfo {};
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <SWA.inl>
|
||||
|
||||
namespace SWA::Inspire
|
||||
{
|
||||
class CTextureAnimationInfo
|
||||
{
|
||||
public:
|
||||
SWA_INSERT_PADDING(0x10);
|
||||
Hedgehog::Base::CSharedString m_MovieTex;
|
||||
Hedgehog::Base::CSharedString m_MovieSfd;
|
||||
SWA_INSERT_PADDING(0x08);
|
||||
be<float> m_Prepare;
|
||||
be<float> m_Start;
|
||||
be<float> m_End;
|
||||
be<float> m_Width;
|
||||
be<float> m_Height;
|
||||
};
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ namespace SWA::Inspire
|
|||
{
|
||||
public:
|
||||
xpointer<void> m_pVftable;
|
||||
boost::shared_ptr<CInspireTextureOverlayInfo> m_spInfo;
|
||||
boost::shared_ptr<CTextureOverlayInfo> m_spInfo;
|
||||
xpointer<CScene> m_pScene;
|
||||
boost::shared_ptr<Hedgehog::Mirage::CTextureData> m_spTextureData;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@
|
|||
|
||||
namespace SWA::Inspire
|
||||
{
|
||||
class CInspireTextureOverlayInfo
|
||||
class CTextureOverlayInfo
|
||||
{
|
||||
public:
|
||||
Hedgehog::Base::CSharedString m_CameraName;
|
||||
be<uint32_t> m_Unk1;
|
||||
be<uint32_t> m_Unk2;
|
||||
be<uint32_t> m_Unk3;
|
||||
Hedgehog::Base::CSharedString m_Picture;
|
||||
be<uint32_t> m_Start;
|
||||
be<uint32_t> m_End;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,9 @@
|
|||
|
||||
namespace SWA::Sequence::Unit
|
||||
{
|
||||
class CPlayMovieUnit : public CUnitBase {};
|
||||
class CPlayMovieUnit : public CUnitBase
|
||||
{
|
||||
public:
|
||||
Hedgehog::Base::CSharedString m_SceneName;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,12 +29,16 @@ namespace SWA::Sequence::Utility
|
|||
SVertexData m_TopRight;
|
||||
SVertexData m_BottomRight;
|
||||
SVertexData m_BottomLeft;
|
||||
bool m_MaintainAspectRatio;
|
||||
bool m_Field1A4;
|
||||
SWA_INSERT_PADDING(0x18);
|
||||
be<float> m_TimeElapsed;
|
||||
};
|
||||
|
||||
SWA_INSERT_PADDING(0x18);
|
||||
xpointer<void> m_pVftable;
|
||||
Hedgehog::Base::CSharedString m_SceneName;
|
||||
SWA_INSERT_PADDING(0x10);
|
||||
xpointer<CRender> m_pRender;
|
||||
SWA_INSERT_PADDING(0x04);
|
||||
xpointer<Hedgehog::Base::CSharedString> m_pResourceName;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@
|
|||
#include <gpu/video.h>
|
||||
#include <install/installer.h>
|
||||
#include <kernel/function.h>
|
||||
#include <ui/game_window.h>
|
||||
#include <patches/audio_patches.h>
|
||||
#include <user/config.h>
|
||||
#include <os/process.h>
|
||||
#include <patches/audio_patches.h>
|
||||
#include <patches/inspire_patches.h>
|
||||
#include <ui/game_window.h>
|
||||
#include <user/config.h>
|
||||
|
||||
void App::Restart(std::vector<std::string> restartArgs)
|
||||
{
|
||||
|
|
@ -24,7 +25,7 @@ void App::Exit()
|
|||
std::_Exit(0);
|
||||
}
|
||||
|
||||
// CApplication::Ctor
|
||||
// SWA::CApplication
|
||||
PPC_FUNC_IMPL(__imp__sub_824EB490);
|
||||
PPC_FUNC(sub_824EB490)
|
||||
{
|
||||
|
|
@ -37,7 +38,7 @@ PPC_FUNC(sub_824EB490)
|
|||
|
||||
static std::thread::id g_mainThreadId = std::this_thread::get_id();
|
||||
|
||||
// CApplication::Update
|
||||
// SWA::CApplication::Update
|
||||
PPC_FUNC_IMPL(__imp__sub_822C1130);
|
||||
PPC_FUNC(sub_822C1130)
|
||||
{
|
||||
|
|
@ -47,6 +48,7 @@ PPC_FUNC(sub_822C1130)
|
|||
if (Config::FPS >= FPS_MIN && Config::FPS < FPS_MAX)
|
||||
{
|
||||
double targetDeltaTime = 1.0 / Config::FPS;
|
||||
|
||||
if (abs(ctx.f1.f64 - targetDeltaTime) < 0.00001)
|
||||
ctx.f1.f64 = targetDeltaTime;
|
||||
}
|
||||
|
|
@ -65,6 +67,7 @@ PPC_FUNC(sub_822C1130)
|
|||
|
||||
GameWindow::Update();
|
||||
AudioPatches::Update(App::s_deltaTime);
|
||||
InspirePatches::Update();
|
||||
|
||||
__imp__sub_822C1130(ctx, base);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ public:
|
|||
static inline bool s_isInit;
|
||||
static inline bool s_isMissingDLC;
|
||||
static inline bool s_isLoading;
|
||||
static inline bool s_isWerehog;
|
||||
|
||||
static inline ELanguage s_language;
|
||||
|
||||
|
|
|
|||
134
UnleashedRecomp/patches/inspire_patches.cpp
Normal file
134
UnleashedRecomp/patches/inspire_patches.cpp
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#include "inspire_patches.h"
|
||||
#include <api/SWA.h>
|
||||
#include <ui/game_window.h>
|
||||
#include <ui/window_events.h>
|
||||
#include <os/logger.h>
|
||||
#include <app.h>
|
||||
|
||||
static SWA::Inspire::CScene* g_pScene;
|
||||
static std::string g_sceneName;
|
||||
static bool g_isFirstFrameChecked;
|
||||
static uint32_t g_eventDispatchCount;
|
||||
|
||||
static std::array<std::string_view, 8> g_alwaysEvilSonic =
|
||||
{
|
||||
"evrt_m2_02", // Same As Ever
|
||||
"evrt_s1_05", // Chun-nan Temple
|
||||
"evrt_s3_04", // Holoskan Temple
|
||||
"evrt_t0_02", // Shamaran Temple
|
||||
"evrt_m7_02", // The Final Temple
|
||||
"evrt_m7_04", // Congratulations
|
||||
"evrt_m8_02", // The Egg Dragoon
|
||||
"evrt_m8_03" // Planet's End
|
||||
};
|
||||
|
||||
static std::unordered_map<std::string_view, std::pair<float, float>> g_evilSonicTimings =
|
||||
{
|
||||
{ "evrt_m0_01_05", { 8189.97f, 10821 } }, // Opening
|
||||
{ "evrt_m0_06", { 0, 5104.07f } }, // A New Journey
|
||||
{ "evrt_m1_02", { 1162.46f, 3513 } }, // The First Night
|
||||
{ "evrt_m6_03", { 2445, 5744 } }, // No Reason
|
||||
{ "evrt_m8_04", { 0, 2314 } } // Dark Gaia Appears
|
||||
};
|
||||
|
||||
// SWA::Inspire::CScene
|
||||
PPC_FUNC_IMPL(__imp__sub_82B98D80);
|
||||
PPC_FUNC(sub_82B98D80)
|
||||
{
|
||||
__imp__sub_82B98D80(ctx, base);
|
||||
|
||||
g_pScene = (SWA::Inspire::CScene*)g_memory.Translate(ctx.r3.u32);
|
||||
g_isFirstFrameChecked = false;
|
||||
g_eventDispatchCount = 0;
|
||||
}
|
||||
|
||||
// ~SWA::Inspire::CScene
|
||||
PPC_FUNC_IMPL(__imp__sub_82B98D30);
|
||||
PPC_FUNC(sub_82B98D30)
|
||||
{
|
||||
__imp__sub_82B98D30(ctx, base);
|
||||
|
||||
g_pScene = nullptr;
|
||||
g_sceneName.clear();
|
||||
|
||||
SDL_User_EvilSonic(App::s_isWerehog);
|
||||
}
|
||||
|
||||
PPC_FUNC_IMPL(__imp__sub_82B9BA98);
|
||||
PPC_FUNC(sub_82B9BA98)
|
||||
{
|
||||
auto sceneName = (Hedgehog::Base::CSharedString*)g_memory.Translate(ctx.r5.u32);
|
||||
|
||||
g_sceneName = sceneName->c_str();
|
||||
|
||||
__imp__sub_82B9BA98(ctx, base);
|
||||
}
|
||||
|
||||
void InspirePatches::DrawDebug()
|
||||
{
|
||||
if (!g_pScene)
|
||||
{
|
||||
ImGui::Text("There is no active scene.");
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Text("Name: %s", g_sceneName.c_str());
|
||||
ImGui::Text("Frame: %f", g_pScene->m_pData->Frame.get());
|
||||
ImGui::Text("Cut: %d", g_pScene->m_pData->Cut.get());
|
||||
|
||||
static std::vector<float> g_loggedFrames{};
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("Log"))
|
||||
g_loggedFrames.push_back(g_pScene->m_pData->Frame);
|
||||
|
||||
if (ImGui::Button("Clear"))
|
||||
g_loggedFrames.clear();
|
||||
|
||||
if (g_loggedFrames.size())
|
||||
{
|
||||
ImGui::Separator();
|
||||
|
||||
for (auto& frame : g_loggedFrames)
|
||||
ImGui::Text("%f", frame);
|
||||
}
|
||||
}
|
||||
|
||||
void InspirePatches::Update()
|
||||
{
|
||||
if (!g_pScene || !g_sceneName.size())
|
||||
return;
|
||||
|
||||
if (!g_isFirstFrameChecked && std::find(g_alwaysEvilSonic.begin(), g_alwaysEvilSonic.end(), g_sceneName) != g_alwaysEvilSonic.end())
|
||||
{
|
||||
SDL_User_EvilSonic(true);
|
||||
g_isFirstFrameChecked = true;
|
||||
return;
|
||||
}
|
||||
|
||||
auto findResult = g_evilSonicTimings.find(g_sceneName);
|
||||
|
||||
if (findResult != g_evilSonicTimings.end())
|
||||
{
|
||||
auto& timings = findResult->second;
|
||||
auto& frame = g_pScene->m_pData->Frame;
|
||||
|
||||
if (!g_isFirstFrameChecked && timings.first > 0)
|
||||
{
|
||||
SDL_User_EvilSonic(false);
|
||||
g_isFirstFrameChecked = true;
|
||||
}
|
||||
|
||||
if (!g_eventDispatchCount && (frame > timings.first && frame < timings.second))
|
||||
{
|
||||
SDL_User_EvilSonic(true);
|
||||
g_eventDispatchCount++;
|
||||
}
|
||||
else if (g_eventDispatchCount == 1 && frame > timings.second)
|
||||
{
|
||||
SDL_User_EvilSonic(false);
|
||||
g_eventDispatchCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
8
UnleashedRecomp/patches/inspire_patches.h
Normal file
8
UnleashedRecomp/patches/inspire_patches.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
class InspirePatches
|
||||
{
|
||||
public:
|
||||
static void DrawDebug();
|
||||
static void Update();
|
||||
};
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include <ui/window_events.h>
|
||||
#include <user/config.h>
|
||||
#include <os/logger.h>
|
||||
#include <app.h>
|
||||
|
||||
static uint32_t g_lastEnemyScore;
|
||||
static uint32_t g_lastTrickScore;
|
||||
|
|
@ -122,20 +123,24 @@ void SetXButtonHomingMidAsmHook(PPCRegister& r30)
|
|||
r30.u32 = Config::HomingAttackOnBoost;
|
||||
}
|
||||
|
||||
// SWA::Player::CEvilSonicContext::Ctor
|
||||
// SWA::Player::CEvilSonicContext
|
||||
PPC_FUNC_IMPL(__imp__sub_823B49D8);
|
||||
PPC_FUNC(sub_823B49D8)
|
||||
{
|
||||
__imp__sub_823B49D8(ctx, base);
|
||||
|
||||
App::s_isWerehog = true;
|
||||
|
||||
SDL_User_EvilSonic(true);
|
||||
}
|
||||
|
||||
// SWA::Player::CEvilSonicContext::Dtor
|
||||
// ~SWA::Player::CEvilSonicContext
|
||||
PPC_FUNC_IMPL(__imp__sub_823B4590);
|
||||
PPC_FUNC(sub_823B4590)
|
||||
{
|
||||
__imp__sub_823B4590(ctx, base);
|
||||
|
||||
App::s_isWerehog = false;
|
||||
|
||||
SDL_User_EvilSonic(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,11 +29,11 @@ inline void SDL_MoveEvent(SDL_Window* pWindow, int x, int y)
|
|||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
||||
inline void SDL_User_EvilSonic(bool isCtor)
|
||||
inline void SDL_User_EvilSonic(bool isEvil)
|
||||
{
|
||||
SDL_Event event{};
|
||||
event.type = SDL_USER_EVILSONIC;
|
||||
event.user.code = isCtor;
|
||||
event.user.code = isEvil;
|
||||
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue