diff --git a/MarathonRecomp/CMakeLists.txt b/MarathonRecomp/CMakeLists.txt index 92f5aa820..27828f767 100644 --- a/MarathonRecomp/CMakeLists.txt +++ b/MarathonRecomp/CMakeLists.txt @@ -137,19 +137,9 @@ set(MARATHON_RECOMP_HID_CXX_SOURCES set(MARATHON_RECOMP_PATCHES_CXX_SOURCES "patches/aspect_ratio_patches.cpp" "patches/audio_patches.cpp" - "patches/camera_patches.cpp" - "patches/CGameModeStageTitle_patches.cpp" - "patches/CHudPause_patches.cpp" - "patches/CTitleStateIntro_patches.cpp" - "patches/CTitleStateMenu_patches.cpp" - "patches/fps_patches.cpp" "patches/frontend_listener.cpp" - "patches/input_patches.cpp" - "patches/inspire_patches.cpp" - "patches/misc_patches.cpp" - "patches/object_patches.cpp" - "patches/player_patches.cpp" - "patches/resident_patches.cpp" + "patches/misc_patches.cpp" + "patches/TitleTask_patches.cpp" "patches/video_patches.cpp" ) diff --git a/MarathonRecomp/api/Marathon.h b/MarathonRecomp/api/Marathon.h index 83deba5ef..035daab7a 100644 --- a/MarathonRecomp/api/Marathon.h +++ b/MarathonRecomp/api/Marathon.h @@ -15,5 +15,11 @@ #include "CSD/Manager/csdmSceneObserver.h" #include "CSD/Manager/csdmSubjectBase.h" #include "CSD/Platform/csdTexList.h" +#include "Sonicteam/SoX/Component.h" +#include "Sonicteam/SoX/Engine/Doc.h" +#include "Sonicteam/SoX/Engine/Task.h" +#include "Sonicteam/SoX/MessageReceiver.h" +#include "Sonicteam/SoX/Object.h" +#include "Sonicteam/TitleTask.h" #include "boost/smart_ptr/make_shared_object.h" #include "boost/smart_ptr/shared_ptr.h" diff --git a/MarathonRecomp/api/Sonicteam/SoX/Component.h b/MarathonRecomp/api/Sonicteam/SoX/Component.h new file mode 100644 index 000000000..e74a4fe2b --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/Component.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +namespace Sonicteam::SoX +{ + class Component : public Object + { + public: + MARATHON_INSERT_PADDING(0x20); + }; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/Engine/Doc.h b/MarathonRecomp/api/Sonicteam/SoX/Engine/Doc.h new file mode 100644 index 000000000..059b02218 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/Engine/Doc.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace Sonicteam::SoX::Engine +{ + class Doc + { + public: + MARATHON_INSERT_PADDING(0x5C); + }; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/Engine/Task.h b/MarathonRecomp/api/Sonicteam/SoX/Engine/Task.h new file mode 100644 index 000000000..f44470302 --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/Engine/Task.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include +#include + +namespace Sonicteam::SoX::Engine +{ + class Task : public Component, public MessageReceiver + { + public: + MARATHON_INSERT_PADDING(0x4C); + }; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/MessageReceiver.h b/MarathonRecomp/api/Sonicteam/SoX/MessageReceiver.h new file mode 100644 index 000000000..95c110a2e --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/MessageReceiver.h @@ -0,0 +1,6 @@ +#pragma once + +namespace Sonicteam::SoX +{ + class MessageReceiver {}; +} diff --git a/MarathonRecomp/api/Sonicteam/SoX/Object.h b/MarathonRecomp/api/Sonicteam/SoX/Object.h new file mode 100644 index 000000000..6effcf63b --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/SoX/Object.h @@ -0,0 +1,6 @@ +#pragma once + +namespace Sonicteam::SoX +{ + class Object {}; +} diff --git a/MarathonRecomp/api/Sonicteam/TitleTask.h b/MarathonRecomp/api/Sonicteam/TitleTask.h new file mode 100644 index 000000000..99d87174a --- /dev/null +++ b/MarathonRecomp/api/Sonicteam/TitleTask.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +namespace Sonicteam +{ + class TitleTask : public Sonicteam::SoX::Engine::Task + { + public: + MARATHON_INSERT_PADDING(0x0C); + be m_SelectedIndex; + }; +} diff --git a/MarathonRecomp/app.cpp b/MarathonRecomp/app.cpp index 4600d26eb..7dac67e1a 100644 --- a/MarathonRecomp/app.cpp +++ b/MarathonRecomp/app.cpp @@ -1,19 +1,16 @@ #include "app.h" -#include "kernel/memory.h" -// #include #include -#include #include #include #include #include -#include -#include #include #include #include #include +static std::thread::id g_mainThreadId = std::this_thread::get_id(); + void App::Restart(std::vector restartArgs) { os::process::StartProcess(os::process::GetExecutablePath(), restartArgs, os::process::GetWorkingDirectory()); @@ -31,217 +28,37 @@ void App::Exit() std::_Exit(0); } -// PPC_FUNC_IMPL(__imp__sub_828B2BF8); -// PPC_FUNC(sub_828B2BF8) -// { -// LOGN_WARNING("sub_828B2BF8 call"); - -// __imp__sub_828B2BF8(ctx, base); -// } - -PPC_FUNC_IMPL(__imp__sub_824A7598); -PPC_FUNC(sub_824A7598) -{ - // LOGN_WARNING("sub_824A7598 RUN INTRO"); - - __imp__sub_824A7598(ctx, base); -} - - -// // SWA::CApplication::CApplication -// PPC_FUNC_IMPL(__imp__sub_824EB490); -// PPC_FUNC(sub_824EB490) -PPC_FUNC_IMPL(__imp__sub_825B2160); -PPC_FUNC(sub_825B2160) +// Sonicteam::AppMarathon::AppMarathon +PPC_FUNC_IMPL(__imp__sub_8262A568); +PPC_FUNC(sub_8262A568) { - LOGN_WARNING("Init app"); App::s_isInit = true; App::s_isMissingDLC = true; App::s_language = Config::Language; - // SWA::SGlobals::Init(); Registry::Save(); - __imp__sub_825B2160(ctx, base); -} - -// PPC_FUNC_IMPL(__imp__sub_828FEB90); -// PPC_FUNC(sub_828FEB90) -// { -// LOGN_WARNING("prerender present"); -// // __builtin_trap(); -// printf("%x %x %x %x\n", ctx.r4.u32, ctx.r5.u32, ctx.r6.u32, ctx.r7.u32); - -// __imp__sub_828FEB90(ctx, base); -// } - -uint32_t read_be32(uint8_t* mem, uint32_t addr) { - return (mem[addr] << 24) | (mem[addr + 1] << 16) | - (mem[addr + 2] << 8) | mem[addr + 3]; -} - -PPC_FUNC_IMPL(__imp__sub_82582648); -PPC_FUNC(sub_82582648) -{ - // __builtin_trap(); - auto _r5 = (uint8_t*)g_memory.Translate(ctx.r5.u32); - - uint32_t data_ptr = read_be32(_r5, 4); // Pointer to char data - uint32_t size = read_be32(_r5, 0 + 0x14); // Length of string - uint32_t capacity = read_be32(_r5, 0 + 0x18); // Capacity - - // printf("Pointer: 0x%08x, Size: %u, Capacity: %u\n", data_ptr, size, capacity); - - // // Read the string data from the emulated memory - if (data_ptr && size > 0) { - printf("Loading file from arc: "); - for (uint32_t i = 0; i < size; i++) { - printf("%c", base[data_ptr + i]); - } - printf("\n"); - } - - __imp__sub_82582648(ctx, base); -} - -PPC_FUNC_IMPL(__imp__sub_825867A8); -PPC_FUNC(sub_825867A8) -{ - auto _r3 = (char*)g_memory.Translate(ctx.r4.u32); - printf("CreateThread by name: %s\n", _r3); - - __imp__sub_825867A8(ctx, base); -} - -// PPC_FUNC_IMPL(__imp__sub_825B1A28); -// PPC_FUNC(sub_825B1A28) -// { -// LOGN_WARNING("SWAP"); -// // __builtin_trap(); -// // printf("%x \n", ctx.r3.u32); - -// __imp__sub_825B1A28(ctx, base); -// } - - -PPC_FUNC_IMPL(__imp__sub_82744840); -PPC_FUNC(sub_82744840) -{ - LOGN_WARNING("RenderFrame"); - - __imp__sub_82744840(ctx, base); -} - -// PPC_FUNC_IMPL(__imp__sub_82558CD0); -// PPC_FUNC(sub_82558CD0) -// { -// LOGN_WARNING("D3DDevice_Present"); - -// __builtin_trap(); - -// __imp__sub_82558CD0(ctx, base); -// } - -// PPC_FUNC_IMPL(__imp__sub_82538B48); -// PPC_FUNC(sub_82538B48) -// { -// // LOGN_WARNING("NtWaitForSingleObjectEx timeout converter"); -// // printf("timeout in ms %d\n", ctx.r4.u32); -// if (ctx.r4.u32 == 0x1) { -// // __builtin_trap(); -// std::this_thread::sleep_for(std::chrono::milliseconds(1)); -// ctx.r4.u32 = -1; -// } + struct RenderConfig + { + be Width; + be Height; + }; -// __imp__sub_82538B48(ctx, base); -// } + auto cfg = reinterpret_cast(g_memory.Translate(ctx.r4.u32)); + cfg->Width = Video::s_viewportWidth; + cfg->Height = Video::s_viewportHeight; -struct DXSettings { - be m_Width; - be m_Height; -}; - -PPC_FUNC_IMPL(__imp__sub_8262A568); -PPC_FUNC(sub_8262A568) -{ - auto dxSettings = reinterpret_cast(g_memory.Translate(ctx.r4.u32)); - dxSettings->m_Width = Video::s_viewportWidth; - dxSettings->m_Height = Video::s_viewportHeight; - - printf("Game changed settings - Width: %d, Height: %d\n", dxSettings->m_Width.get(), dxSettings->m_Height.get()); - printf("Runtime settings: Width: %d, Height: %d\n", Video::s_viewportWidth, Video::s_viewportHeight); + LOGFN_UTILITY("Changed resolution: {}x{}", cfg->Width.get(), cfg->Height.get()); __imp__sub_8262A568(ctx, base); } -// PPC_FUNC_IMPL(__imp__sub_825B1A28); -// PPC_FUNC(sub_825B1A28) -// { -// LOGN_WARNING("MaybePresent"); -// std::thread::id tid = std::this_thread::get_id(); -// // size_t hash_val = std::hash{}(tid); -// printf("present thread id: %x\n", XXH32(&tid, sizeof(tid), 0)); -// __builtin_trap(); - -// __imp__sub_825B1A28(ctx, base); -// } - -// PPC_FUNC_IMPL(__imp__sub_825E7AD8); -// PPC_FUNC(sub_825E7AD8) -// { -// LOGN_WARNING("Sonicteam::Heap::HeapAllocCustom"); -// // printf("%x \n", ctx.r3.u32); - -// __imp__sub_825E7AD8(ctx, base); -// } - -// PPC_FUNC_IMPL(__imp__sub_825E6F70); -// PPC_FUNC(sub_825E6F70) -// { -// LOGN_WARNING("Sonicteam::SpanverseMemory::AllocMemory"); -// printf("size: %x\n", ctx.r3.u32); -// auto initialized = *reinterpret_cast*>(g_memory.Translate(0x82D3BAA8)); -// printf("%x %x\n", initialized, &initialized); - -// __imp__sub_825E6F70(ctx, base); -// } -// 82186158 - -PPC_FUNC_IMPL(__imp__sub_825E7918); -PPC_FUNC(sub_825E7918) -{ - // for some reason, this function checks that r4 is not zero, but it's always zero - ctx.r4.u32 = 1; - LOGN_WARNING("spanverse allocex"); - - __imp__sub_825E7918(ctx, base); -} - -PPC_FUNC_IMPL(__imp__sub_825E7958); -PPC_FUNC(sub_825E7958) -{ - ctx.r4.u32 = 1; - LOGN_WARNING("spanverse freeex"); - - __imp__sub_825E7958(ctx, base); -} - -PPC_FUNC_IMPL(__imp__sub_825822D0); -PPC_FUNC(sub_825822D0) -{ - LOGN_WARNING("sub_825822D0"); - - __imp__sub_825822D0(ctx, base); -} - -static std::thread::id g_mainThreadId = std::this_thread::get_id(); - -// // SWA::CApplication::Update +// Sonicteam::DocMarathonState::Update PPC_FUNC_IMPL(__imp__sub_825EA610); PPC_FUNC(sub_825EA610) { __imp__sub_825EA610(ctx, base); - // LOGN_WARNING("::Update"); + Video::WaitOnSwapChain(); // Correct small delta time errors. @@ -254,8 +71,6 @@ PPC_FUNC(sub_825EA610) } App::s_deltaTime = ctx.f1.f64; - - // printf("s_deltaTime = %f\n", ctx.f1.f64); App::s_time += App::s_deltaTime; // This function can also be called by the loading thread, @@ -268,86 +83,88 @@ PPC_FUNC(sub_825EA610) SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); GameWindow::Update(); } +} -// AudioPatches::Update(App::s_deltaTime); -// InspirePatches::Update(); - -// // Apply subtitles option. -// if (auto pApplicationDocument = SWA::CApplicationDocument::GetInstance()) -// pApplicationDocument->m_InspireSubtitles = Config::Subtitles; - -// if (Config::EnableEventCollisionDebugView) -// *SWA::SGlobals::ms_IsTriggerRender = true; - -// if (Config::EnableGIMipLevelDebugView) -// *SWA::SGlobals::ms_VisualizeLoadedLevel = true; - -// if (Config::EnableObjectCollisionDebugView) -// *SWA::SGlobals::ms_IsObjectCollisionRender = true; +PPC_FUNC_IMPL(__imp__sub_82582648); +PPC_FUNC(sub_82582648) +{ + struct File + { + public: + MARATHON_INSERT_PADDING(4); + xpointer pFilePath; + MARATHON_INSERT_PADDING(0x0C); + be Length; + be Capacity; + }; -// if (Config::EnableStageCollisionDebugView) -// *SWA::SGlobals::ms_IsCollisionRender = true; + auto pFile = reinterpret_cast(base + ctx.r5.u32); - // __imp__sub_825EA610(ctx, base); -} + if (pFile->pFilePath && pFile->Length > 0) + LOGFN_UTILITY("Loading file: {}", pFile->pFilePath.get()); -void DisableMSAA(PPCRegister& val) -{ - val.u32 = 0; + __imp__sub_82582648(ctx, base); } -void DisableStartWait() +#if _DEBUG +// Sonicteam::SoX::Thread +PPC_FUNC_IMPL(__imp__sub_825867A8); +PPC_FUNC(sub_825867A8) { - // printf("DisableStartWait\n"); -} + auto pThreadName = (const char*)g_memory.Translate(ctx.r4.u32); -void IgnoreXAudioLockPlsFixAndDeleteThisMidasm(PPCRegister& val) -{ -} + os::logger::Log(fmt::format("Created thread: {}", pThreadName), os::logger::ELogType::Utility, "Sonicteam::SoX::Thread"); -PPC_FUNC_IMPL(__imp__sub_82511540); -PPC_FUNC(sub_82511540) -{ - // printf("DisableStartWait2\n"); - ctx.r11.u32 = 1; + __imp__sub_825867A8(ctx, base); } +#endif -void EnableTitleButtons(PPCRegister& val) +PPC_FUNC_IMPL(__imp__sub_82744840); +PPC_FUNC(sub_82744840) { - val.u32 = 3; -} + LOG_UTILITY("RenderFrame"); -void EnableTitleButtons2(PPCRegister& val) -{ - val.u32 = 5; + __imp__sub_82744840(ctx, base); } -void TitleMenuDefaultSelection(PPCRegister& r4, PPCRegister& r31) +// Sonicteam::SpanverseHeap::Alloc +PPC_FUNC_IMPL(__imp__sub_825E7918); +PPC_FUNC(sub_825E7918) { - auto saveFilePath = GetSaveFilePath(false); +#if _DEBUG + os::logger::Log(fmt::format("Allocated {} bytes", ctx.r3.u32), os::logger::ELogType::Utility, "Sonicteam::SpanverseHeap"); +#endif - if (std::filesystem::exists(saveFilePath)) { - r4.s64 = 5; + // This function checks if R4 is non-zero + // to allow an allocation, but it's always + // passed in as zero. + ctx.r4.u32 = 1; - auto pSelectedIndex = (be*)g_memory.Translate(r31.u32 + 0x7C); - *pSelectedIndex = 1; - } + __imp__sub_825E7918(ctx, base); } -void DebugZlibMidAsmHook(PPCRegister& id) +// Sonicteam::SpanverseHeap::Free +PPC_FUNC_IMPL(__imp__sub_825E7958); +PPC_FUNC(sub_825E7958) { - // printf("DebugZlibMidAsmHook: %x\n", id.u64); -} +#if _DEBUG + os::logger::Log(fmt::format("Freed {:08X}", ctx.r3.u32), os::logger::ELogType::Utility, "Sonicteam::SpanverseHeap"); +#endif -void DebugZlibMidAsm2Hook(PPCRegister& id) -{ - if (id.u64 == 10) { - printf("DebugZlibMidAsm2Hook: %d\n", id.u64); - } + // This function checks if R4 is non-zero + // to allow a free, but it's always + // passed in as zero. + ctx.r4.u32 = 1; + + __imp__sub_825E7958(ctx, base); } -void DebugIndirectCall(PPCRegister& id) +#if _DEBUG +PPC_FUNC_IMPL(__imp__sub_825822D0); +PPC_FUNC(sub_825822D0) { - printf("DebugIndirectCall: %x\n", id.u64); -} + LOG_UTILITY("!!!"); + __imp__sub_825822D0(ctx, base); +} +#endif diff --git a/MarathonRecomp/app.h b/MarathonRecomp/app.h index fdb465944..8facd0ea0 100644 --- a/MarathonRecomp/app.h +++ b/MarathonRecomp/app.h @@ -1,5 +1,6 @@ #pragma once +#include #include class App @@ -12,7 +13,6 @@ class App static inline bool s_isSaveDataCorrupt; static inline EPlayerCharacter s_playerCharacter; - static inline ELanguage s_language; static inline double s_deltaTime; diff --git a/MarathonRecomp/exports.cpp b/MarathonRecomp/exports.cpp index 9e28d00c3..ea250b7e7 100644 --- a/MarathonRecomp/exports.cpp +++ b/MarathonRecomp/exports.cpp @@ -1,11 +1,9 @@ -// #include #include #include #include #include #include #include -#include void Game_PlaySound(const char* pName) { @@ -14,22 +12,22 @@ void Game_PlaySound(const char* pName) EmbeddedPlayer::Play(pName); } - // TODO: Support in-game sounds see sub_824C7868 - // else - // { - // // Use EVENT category in cutscenes since SYSTEM gets muted by the game. - // uint32_t category = !InspirePatches::s_sceneName.empty() ? 10 : 7; - - // guest_stack_var soundPlayer; - // GuestToHostFunction(sub_82B4DF50, soundPlayer.get(), ((be*)g_memory.Translate(0x83367900))->get(), category, 0, 0); - - // auto soundPlayerVtable = (be*)g_memory.Translate(*(be*)soundPlayer->get()); - // uint32_t virtualFunction = *(soundPlayerVtable + 1); - - // size_t strLen = strlen(pName); - // void *strAllocation = g_userHeap.Alloc(strLen + 1); - // memcpy(strAllocation, pName, strLen + 1); - // GuestToHostFunction(virtualFunction, soundPlayer->get(), strAllocation, 0); - // g_userHeap.Free(strAllocation); - // } + // TODO: support in-game sounds (see sub_824C7868). + // else + // { + // // Use EVENT category in cutscenes since SYSTEM gets muted by the game. + // uint32_t category = !InspirePatches::s_sceneName.empty() ? 10 : 7; + // + // guest_stack_var soundPlayer; + // GuestToHostFunction(sub_82B4DF50, soundPlayer.get(), ((be*)g_memory.Translate(0x83367900))->get(), category, 0, 0); + // + // auto soundPlayerVtable = (be*)g_memory.Translate(*(be*)soundPlayer->get()); + // uint32_t virtualFunction = *(soundPlayerVtable + 1); + // + // size_t strLen = strlen(pName); + // void *strAllocation = g_userHeap.Alloc(strLen + 1); + // memcpy(strAllocation, pName, strLen + 1); + // GuestToHostFunction(virtualFunction, soundPlayer->get(), strAllocation, 0); + // g_userHeap.Free(strAllocation); + // } } diff --git a/MarathonRecomp/misc_impl.cpp b/MarathonRecomp/misc_impl.cpp index a191ab360..4ccdd14c1 100644 --- a/MarathonRecomp/misc_impl.cpp +++ b/MarathonRecomp/misc_impl.cpp @@ -47,16 +47,16 @@ int memcpy_s(void* dest, size_t dest_size, const void* src, size_t count) { #endif GUEST_FUNCTION_HOOK(sub_826DF680, memcpy); -// // GUEST_FUNCTION_HOOK(sub_831CCB98, memcpy); -// // GUEST_FUNCTION_HOOK(sub_831CEAE0, memcpy); -// // GUEST_FUNCTION_HOOK(sub_831CEE04, memcpy); -// // GUEST_FUNCTION_HOOK(sub_831CF2D0, memcpy); -// // GUEST_FUNCTION_HOOK(sub_831CF660, memcpy); +// GUEST_FUNCTION_HOOK(sub_831CCB98, memcpy); +// GUEST_FUNCTION_HOOK(sub_831CEAE0, memcpy); +// GUEST_FUNCTION_HOOK(sub_831CEE04, memcpy); +// GUEST_FUNCTION_HOOK(sub_831CF2D0, memcpy); +// GUEST_FUNCTION_HOOK(sub_831CF660, memcpy); // GUEST_FUNCTION_HOOK(sub_826DFAA0, memcpy); GUEST_FUNCTION_HOOK(sub_826DE940, memmove); GUEST_FUNCTION_HOOK(sub_826DFD40, memset); GUEST_FUNCTION_HOOK(sub_826DEA00, memcpy_s); -// // GUEST_FUNCTION_HOOK(sub_831CCAA0, memset); +// GUEST_FUNCTION_HOOK(sub_831CCAA0, memset); #ifdef _WIN32 GUEST_FUNCTION_HOOK(sub_82537770, OutputDebugStringA); diff --git a/MarathonRecomp/patches/CGameModeStageTitle_patches.cpp b/MarathonRecomp/patches/CGameModeStageTitle_patches.cpp deleted file mode 100644 index 79dba80a1..000000000 --- a/MarathonRecomp/patches/CGameModeStageTitle_patches.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -// SWA::CGameModeStageTitle::Update -// PPC_FUNC_IMPL(__imp__sub_825518B8); -// PPC_FUNC(sub_825518B8) -// { -// auto pGameModeStageTitle = (SWA::CGameModeStageTitle*)g_memory.Translate(ctx.r3.u32); - -// __imp__sub_825518B8(ctx, base); - -// if (g_quitMessageOpen) -// pGameModeStageTitle->m_AdvertiseMovieWaitTime = 0; -// } diff --git a/MarathonRecomp/patches/CHudPause_patches.cpp b/MarathonRecomp/patches/CHudPause_patches.cpp deleted file mode 100644 index 26bfce4eb..000000000 --- a/MarathonRecomp/patches/CHudPause_patches.cpp +++ /dev/null @@ -1,186 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -bool g_isClosed; - -float g_achievementMenuIntroTime = 0.0f; -constexpr float g_achievementMenuIntroThreshold = 3.0f; -float g_achievementMenuOutroTime = 0.0f; -constexpr float g_achievementMenuOutroThreshold = 0.32f; -bool g_isAchievementMenuOutro = false; - -void CHudPauseAddOptionsItemMidAsmHook(PPCRegister& pThis) -{ -// guest_stack_var menu("TopMenu"); -// guest_stack_var name("option"); - - // GuestToHostFunction(sub_824AE690, pThis.u32, menu.get(), name.get()); -} - -//bool InjectMenuBehaviour(uint32_t pThis, uint32_t count) -//{ -// if (App::s_isLoading) -// return true; -// -// auto pHudPause = (SWA::CHudPause*)g_memory.Translate(pThis); -// auto cursorIndex = *(be*)g_memory.Translate(4 * (*(be*)g_memory.Translate(pThis + 0x19C) + 0x68) + pThis); -// -// auto actionType = SWA::eActionType_Undefined; -// auto transitionType = SWA::eTransitionType_Undefined; -// -// switch (pHudPause->m_Menu) -// { -// case SWA::eMenuType_WorldMap: -// case SWA::eMenuType_Stage: -// case SWA::eMenuType_Misc: -// actionType = SWA::eActionType_Return; -// transitionType = SWA::eTransitionType_Quit; -// break; -// -// case SWA::eMenuType_Village: -// case SWA::eMenuType_Hub: -// actionType = SWA::eActionType_Return; -// transitionType = SWA::eTransitionType_Hide; -// break; -// } -// -// if (auto pInputState = SWA::CInputState::GetInstance()) -// { -// if (pInputState->GetPadState().IsTapped(SWA::eKeyState_Select)) -// { -// AchievementMenu::Open(); -// -// pHudPause->m_Action = SWA::eActionType_Undefined; -// pHudPause->m_Transition = SWA::eTransitionType_SubMenu; -// -// return false; -// } -// } -// -// if (pHudPause->m_Status == SWA::eStatusType_Accept) -// { -// if (cursorIndex == count - 2) -// { -// OptionsMenu::Open(true, pHudPause->m_Menu); -// -// pHudPause->m_Action = SWA::eActionType_Undefined; -// pHudPause->m_Transition = SWA::eTransitionType_Hide; -// -// if (pHudPause->m_rcBg1Select) -// pHudPause->m_rcBg1Select->SetHideFlag(true); -// -// return true; -// } -// else if (cursorIndex == count - 1) -// { -// pHudPause->m_Action = actionType; -// pHudPause->m_Transition = transitionType; -// -// return true; -// } -// } -// -// return false; -//} - -//bool CHudPauseItemCountMidAsmHook(PPCRegister& pThis, PPCRegister& count) -//{ -// count.u32 += 1; -// -// return InjectMenuBehaviour(pThis.u32, count.u32); -//} -// -//void CHudPauseVillageItemCountMidAsmHook(PPCRegister& pThis, PPCRegister& count) -//{ -// count.u32 += 1; -// -// InjectMenuBehaviour(pThis.u32, count.u32); -//} -// -//bool CHudPauseMiscItemCountMidAsmHook(PPCRegister& count) -//{ -// if (count.u32 < 3) -// return true; -// -// return false; -//} -// -//bool CHudPauseMiscInjectOptionsMidAsmHook(PPCRegister& pThis) -//{ -// return InjectMenuBehaviour(pThis.u32, 3); -//} - -// SWA::CHudPause::Update -// PPC_FUNC_IMPL(__imp__sub_824B0930); -// PPC_FUNC(sub_824B0930) -// { -// if (App::s_isLoading) -// { -// __imp__sub_824B0930(ctx, base); -// return; -// } - -// auto pHudPause = (SWA::CHudPause*)g_memory.Translate(ctx.r3.u32); -// auto pInputState = SWA::CInputState::GetInstance(); - -// g_achievementMenuIntroTime += App::s_deltaTime; - -// if (g_isAchievementMenuOutro) -// { -// g_achievementMenuOutroTime += App::s_deltaTime; - -// // Re-open pause menu after achievement menu closes with delay. -// if (g_achievementMenuOutroTime >= g_achievementMenuOutroThreshold) -// { -// // GuestToHostFunction(sub_824AFD28, pHudPause, 0, 1, 0, 0); - -// g_achievementMenuOutroTime = 0; -// g_isAchievementMenuOutro = false; -// } -// } - -// if (AchievementMenu::s_isVisible) -// { -// // HACK: wait for transition to finish before restoring control. -// if (g_achievementMenuIntroThreshold >= g_achievementMenuIntroTime) -// __imp__sub_824B0930(ctx, base); - -// if (pInputState->GetPadState().IsTapped(SWA::eKeyState_B) && !g_isAchievementMenuOutro) -// { -// AchievementMenu::Close(); - -// g_isAchievementMenuOutro = true; -// } -// } -// else if (OptionsMenu::s_isVisible && OptionsMenu::s_isPause) -// { -// if (OptionsMenu::CanClose() && pInputState->GetPadState().IsTapped(SWA::eKeyState_B)) -// { -// OptionsMenu::Close(); -// // GuestToHostFunction(sub_824AFD28, pHudPause, 0, 0, 0, 1); -// __imp__sub_824B0930(ctx, base); -// } -// } -// else -// { -// g_achievementMenuIntroTime = 0; - -// if (*SWA::SGlobals::ms_IsRenderHud && pHudPause->m_IsShown && !pHudPause->m_Submenu && pHudPause->m_Transition == SWA::eTransitionType_Undefined) -// { -// ButtonGuide::Open(Button("Achievements_Name", FLT_MAX, EButtonIcon::Back, EButtonAlignment::Left, EFontQuality::Low)); -// g_isClosed = false; -// } -// else if (!g_isClosed) -// { -// ButtonGuide::Close(); -// g_isClosed = true; -// } - -// __imp__sub_824B0930(ctx, base); -// } -// } diff --git a/MarathonRecomp/patches/CTitleStateIntro_patches.cpp b/MarathonRecomp/patches/CTitleStateIntro_patches.cpp deleted file mode 100644 index 346b42588..000000000 --- a/MarathonRecomp/patches/CTitleStateIntro_patches.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#include "CTitleStateIntro_patches.h" -#include -#include -#include -#include -#include -#include -#include -#include - -static std::atomic g_faderBegun = false; - -bool g_quitMessageOpen = false; -static int g_quitMessageResult = -1; - -static std::atomic g_corruptSaveMessageOpen = false; -static int g_corruptSaveMessageResult = -1; - -static std::atomic g_corruptAchievementsMessageOpen = false; -static int g_corruptAchievementsMessageResult = -1; - -static std::atomic g_updateAvailableMessageOpen = false; -static int g_updateAvailableMessageResult = -1; - -static bool ProcessQuitMessage() -{ - if (!g_quitMessageOpen) - return false; - - std::array options = { Localise("Common_Yes"), Localise("Common_No") }; - - if (MessageWindow::Open(Localise("Title_Message_Quit"), &g_quitMessageResult, options, 1) == MSG_CLOSED) - { - if (!g_quitMessageResult) - { - Fader::FadeOut(1, []() { App::Exit(); }); - g_faderBegun = true; - } - - g_quitMessageOpen = false; - g_quitMessageResult = -1; - } - - return true; -} - -static bool ProcessCorruptSaveMessage() -{ - if (!g_corruptSaveMessageOpen) - return false; - - if (MessageWindow::Open(Localise("Title_Message_SaveDataCorrupt"), &g_corruptSaveMessageResult) == MSG_CLOSED) - { - g_corruptSaveMessageOpen = false; - g_corruptSaveMessageOpen.notify_one(); - g_corruptSaveMessageResult = -1; - } - - return true; -} - -static bool ProcessCorruptAchievementsMessage() -{ - if (!g_corruptAchievementsMessageOpen) - return false; - - auto message = AchievementManager::Status == EAchStatus::IOError - ? Localise("Title_Message_AchievementDataIOError") - : Localise("Title_Message_AchievementDataCorrupt"); - - if (MessageWindow::Open(message, &g_corruptAchievementsMessageResult) == MSG_CLOSED) - { - // Allow user to proceed if the achievement data couldn't be loaded. - // Restarting may fix this error, so it isn't worth clearing the data for. - if (AchievementManager::Status != EAchStatus::IOError) - AchievementManager::Save(true); - - g_corruptAchievementsMessageOpen = false; - g_corruptAchievementsMessageOpen.notify_one(); - g_corruptAchievementsMessageResult = -1; - } - - return true; -} - -static bool ProcessUpdateAvailableMessage() -{ - if (!g_updateAvailableMessageOpen) - return false; - - std::array options = { Localise("Common_Yes"), Localise("Common_No") }; - - if (MessageWindow::Open(Localise("Title_Message_UpdateAvailable"), &g_updateAvailableMessageResult, options) == MSG_CLOSED) - { - if (!g_updateAvailableMessageResult) - { - Fader::FadeOut(1, - // - []() - { - UpdateChecker::visitWebsite(); - App::Exit(); - } - ); - - g_faderBegun = true; - } - - g_updateAvailableMessageOpen = false; - g_updateAvailableMessageOpen.notify_one(); - g_updateAvailableMessageResult = -1; - } - - return true; -} - -void StorageDevicePromptMidAsmHook() {} - -// Save data validation hook. -// PPC_FUNC_IMPL(__imp__sub_822C55B0); -// PPC_FUNC(sub_822C55B0) -// { -// App::s_isSaveDataCorrupt = true; -// g_corruptSaveMessageOpen = true; -// g_corruptSaveMessageOpen.wait(true); -// ctx.r3.u32 = 0; -// } - -void PressStartSaveLoadThreadMidAsmHook() -{ - if (UpdateChecker::check() == UpdateChecker::Result::UpdateAvailable) - { - g_updateAvailableMessageOpen = true; - g_updateAvailableMessageOpen.wait(true); - g_faderBegun.wait(true); - } - - AchievementManager::Load(); - - if (AchievementManager::Status != EAchStatus::Success) - { - g_corruptAchievementsMessageOpen = true; - g_corruptAchievementsMessageOpen.wait(true); - } -} - -// SWA::CTitleStateIntro::Update -// PPC_FUNC_IMPL(__imp__sub_82587E50); -// PPC_FUNC(sub_82587E50) -// { -// auto pTitleStateIntro = (SWA::CTitleStateIntro*)g_memory.Translate(ctx.r3.u32); -// auto pTime = (be*)((uint8_t*)pTitleStateIntro->GetContextBase() + 0x10C); - -// if (*SWA::SGlobals::ms_IsAutoSaveWarningShown) -// { -// __imp__sub_82587E50(ctx, base); -// } -// else if (!ProcessUpdateAvailableMessage() && !ProcessCorruptSaveMessage() && !ProcessCorruptAchievementsMessage() && !g_faderBegun) -// { -// if (auto pInputState = SWA::CInputState::GetInstance()) -// { -// if (pInputState->GetPadState().IsTapped(SWA::eKeyState_B) && *pTime > 0.5f) -// g_quitMessageOpen = true; -// } - -// if (!ProcessQuitMessage()) -// __imp__sub_82587E50(ctx, base); -// } -// } diff --git a/MarathonRecomp/patches/CTitleStateIntro_patches.h b/MarathonRecomp/patches/CTitleStateIntro_patches.h deleted file mode 100644 index 74a123acb..000000000 --- a/MarathonRecomp/patches/CTitleStateIntro_patches.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -extern bool g_quitMessageOpen; diff --git a/MarathonRecomp/patches/CTitleStateMenu_patches.cpp b/MarathonRecomp/patches/CTitleStateMenu_patches.cpp deleted file mode 100644 index b18b15c41..000000000 --- a/MarathonRecomp/patches/CTitleStateMenu_patches.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static bool g_installMessageOpen = false; -static bool g_installMessageFaderBegun = false; -static int g_installMessageResult = -1; - -static bool ProcessInstallMessage() -{ - if (!g_installMessageOpen) - return false; - - if (g_installMessageFaderBegun) - return true; - - auto& str = App::s_isMissingDLC - ? Localise("Installer_Message_TitleMissingDLC") - : Localise("Installer_Message_Title"); - - std::array options = { Localise("Common_Yes"), Localise("Common_No") }; - - if (MessageWindow::Open(str, &g_installMessageResult, options, 1) == MSG_CLOSED) - { - switch (g_installMessageResult) - { - case 0: - Fader::FadeOut(1, []() { App::Restart({ "--install-dlc" }); }); - g_installMessageFaderBegun = true; - break; - - case 1: - g_installMessageOpen = false; - g_installMessageResult = -1; - break; - } - } - - return true; -} - -// SWA::CTitleStateMenu::Update -// PPC_FUNC_IMPL(__imp__sub_825882B8); -// PPC_FUNC(sub_825882B8) -// { -// auto pTitleStateMenu = (SWA::CTitleStateMenu*)g_memory.Translate(ctx.r3.u32); -// auto pGameDocument = SWA::CGameDocument::GetInstance(); - -// auto pInputState = SWA::CInputState::GetInstance(); -// auto& pPadState = pInputState->GetPadState(); -// auto isAccepted = pPadState.IsTapped(SWA::eKeyState_A) || pPadState.IsTapped(SWA::eKeyState_Start); - -// auto pContext = pTitleStateMenu->GetContextBase(); -// auto isNewGameIndex = pContext->m_pTitleMenu->m_CursorIndex == 0; -// auto isOptionsIndex = pContext->m_pTitleMenu->m_CursorIndex == 2; -// auto isInstallIndex = pContext->m_pTitleMenu->m_CursorIndex == 3; - -// // Always default to New Game with corrupted save data. -// if (App::s_isSaveDataCorrupt && pContext->m_pTitleMenu->m_CursorIndex == 1) -// pContext->m_pTitleMenu->m_CursorIndex = 0; - -// if (isNewGameIndex && isAccepted) -// { -// if (pContext->m_pTitleMenu->m_IsDeleteCheckMessageOpen && -// pGameDocument->m_pMember->m_pGeneralWindow->m_SelectedIndex == 1) -// { -// LOGN("Resetting achievements..."); - -// AchievementManager::Reset(); -// } -// } -// else if (!OptionsMenu::s_isVisible && isOptionsIndex) -// { -// if (OptionsMenu::s_isRestartRequired) -// { -// static int result = -1; - -// if (MessageWindow::Open(Localise("Options_Message_Restart"), &result) == MSG_CLOSED) -// Fader::FadeOut(1, []() { App::Restart(); }); -// } -// else if (isAccepted) -// { -// Game_PlaySound("sys_worldmap_window"); -// Game_PlaySound("sys_worldmap_decide"); -// OptionsMenu::Open(); -// } -// } -// else if (isInstallIndex && isAccepted) -// { -// g_installMessageOpen = true; -// } - -// if (!OptionsMenu::s_isVisible && !OptionsMenu::s_isRestartRequired && !ProcessInstallMessage()) -// __imp__sub_825882B8(ctx, base); - -// if (isOptionsIndex) -// { -// if (OptionsMenu::CanClose() && pPadState.IsTapped(SWA::eKeyState_B)) -// { -// Game_PlaySound("sys_worldmap_cansel"); -// OptionsMenu::Close(); -// } -// } -// } - -void TitleMenuRemoveContinueOnCorruptSaveMidAsmHook(PPCRegister& r3) -{ - if (!App::s_isSaveDataCorrupt) - return; - - r3.u64 = 0; -} - -void TitleMenuRemoveStorageDeviceOptionMidAsmHook(PPCRegister& r11) -{ - r11.u32 = 0; -} - -void TitleMenuAddInstallOptionMidAsmHook(PPCRegister& r3) -{ - r3.u32 = 1; -} diff --git a/MarathonRecomp/patches/TitleTask_patches.cpp b/MarathonRecomp/patches/TitleTask_patches.cpp new file mode 100644 index 000000000..e6619bb01 --- /dev/null +++ b/MarathonRecomp/patches/TitleTask_patches.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +void RestoreTitleButtons(PPCRegister& val) +{ + val.u32 = 3; +} + +void RestoreTitleButtons2(PPCRegister& val) +{ + val.u32 = 5; +} + +void SetDefaultTitleTaskSelection(PPCRegister& pThis, PPCRegister& csdIndex) +{ + auto pTitleTask = (Sonicteam::TitleTask*)g_memory.Translate(pThis.u32); + auto saveFilePath = GetSaveFilePath(false); + + if (!std::filesystem::exists(saveFilePath)) + return; + + csdIndex.u32 = 5; + pTitleTask->m_SelectedIndex = 1; +} + +bool DisableTitleTaskStartWait() +{ + return Config::DisableTitleInputDelay; +} + +PPC_FUNC_IMPL(__imp__sub_82511540); +PPC_FUNC(sub_82511540) +{ + if (Config::DisableTitleInputDelay) + { + ctx.r3.u32 = 1; + return; + } + + __imp__sub_82511540(ctx, base); +} diff --git a/MarathonRecomp/patches/aspect_ratio_patches.cpp b/MarathonRecomp/patches/aspect_ratio_patches.cpp index 4c53dfe67..e1de67ece 100644 --- a/MarathonRecomp/patches/aspect_ratio_patches.cpp +++ b/MarathonRecomp/patches/aspect_ratio_patches.cpp @@ -1,3 +1,4 @@ +#include "aspect_ratio_patches.h" #include #include #include @@ -6,10 +7,6 @@ #include #include -#include "aspect_ratio_patches.h" -#include "camera_patches.h" -#include "inspire_patches.h" - // These are here for now to not recompile basically all of the project. namespace Chao::CSD { @@ -938,12 +935,6 @@ static void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t str return; } - // That goddamn boss gauge doesn't disappear in the cutscene where Dark Gaia and Chip hug each other - if ((modifier.flags & SKIP_INSPIRE) != 0 && !InspirePatches::s_sceneName.empty() && *reinterpret_cast*>(base + ctx.r4.u32) >= 1280.0f) - { - return; - } - if (g_cornerExtract) { if ((modifier.flags & (STORE_LEFT_CORNER | STORE_RIGHT_CORNER)) != 0) diff --git a/MarathonRecomp/patches/audio_patches.cpp b/MarathonRecomp/patches/audio_patches.cpp index 5c3321b00..d25fa1f57 100644 --- a/MarathonRecomp/patches/audio_patches.cpp +++ b/MarathonRecomp/patches/audio_patches.cpp @@ -3,21 +3,9 @@ #include #include #include -#include int AudioPatches::m_isAttenuationSupported = -1; -static be* GetVolume(bool isMusic = true) -{ - auto ppUnkClass = (be*)g_memory.Translate(0x83362FFC); - - if (!ppUnkClass->get()) - return nullptr; - - // NOTE (Hyper): This is fine, trust me. See 0x82E58728. - return (be*)g_memory.Translate(4 * ((int)isMusic + 0x1C) + ((be*)g_memory.Translate(ppUnkClass->get() + 4))->get()); -} - bool AudioPatches::CanAttenuate() { #if _WIN32 @@ -34,62 +22,5 @@ bool AudioPatches::CanAttenuate() #endif } -void AudioPatches::Update(float deltaTime) -{ - auto pMusicVolume = GetVolume(); - auto pEffectsVolume = GetVolume(false); - - if (!pMusicVolume || !pEffectsVolume) - return; - - if (Config::MusicAttenuation && CanAttenuate()) - { - auto time = 1.0f - expf(2.5f * -deltaTime); - - if (os::media::IsExternalMediaPlaying()) - { - *pMusicVolume = std::lerp(*pMusicVolume, 0.0f, time); - } - else - { - *pMusicVolume = std::lerp(*pMusicVolume, Config::MusicVolume, time); - } - } - else - { - *pMusicVolume = Config::MusicVolume; - } - - *pEffectsVolume = Config::EffectsVolume; -} - -// Stub volume setter. -GUEST_FUNCTION_STUB(sub_82E58728); - -// HORRIBLE HACK ZONE -// The options menu uses se_system_worldmap.csb, which is stored in Title.ar.00. -// This archive gets unloaded in stages, which causes sounds to not play in the options menu. -// To solve this, once the CSB gets loaded at title, we'll keep it PERMANENTLY loaded. -// This'll make the SFX not work if Title never gets loaded, but that'll only happen when quick booting to stages. -static bool g_loadedWorldMapCsb; - -bool MakeCueSheetDataMidAsmHook(PPCRegister& r31) -{ - uint8_t* base = g_memory.base; - uint32_t str = PPC_LOAD_U32(r31.u32); - - if (str != NULL && strcmp(reinterpret_cast(base + str), "se_system_worldmap") == 0) - { - if (!g_loadedWorldMapCsb) - { - g_loadedWorldMapCsb = true; - return false; // Allow load for the first and only time. - } - - // Already loaded before, skip all the loading and name assignment code. - // Not assigning the name prevents it from unloading the CSB file. - return true; - } - - return false; -} +// TODO (Hyper): implement music attenuation. +void AudioPatches::Update(float deltaTime) {} diff --git a/MarathonRecomp/patches/camera_patches.cpp b/MarathonRecomp/patches/camera_patches.cpp deleted file mode 100644 index 4c9f4fa6a..000000000 --- a/MarathonRecomp/patches/camera_patches.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include -#include -#include "camera_patches.h" -#include "aspect_ratio_patches.h" - -//void CameraAspectRatioMidAsmHook(PPCRegister& r30, PPCRegister& r31) -//{ -// r30.u32 = 0; -// -// auto camera = (SWA::CCamera*)g_memory.Translate(r31.u32); -// -// // Dynamically adjust horizontal aspect ratio to window dimensions. -// camera->m_HorzAspectRatio = g_aspectRatio; -//} -// -//float AdjustFieldOfView(float fieldOfView, float aspectRatio) -//{ -// if (Config::AspectRatio == EAspectRatio::OriginalNarrow) -// { -// // Replicate the original incorrect field of view formula if requested. -// fieldOfView *= NARROW_ASPECT_RATIO; -// } -// else if (aspectRatio < WIDE_ASPECT_RATIO) -// { -// // Use proper VERT+ otherwise for narrow aspect ratios. -// fieldOfView = 2.0 * atan(tan(0.5 * fieldOfView) / aspectRatio * WIDE_ASPECT_RATIO); -// } -// -// return fieldOfView; -//} -// -//void CameraFieldOfViewMidAsmHook(PPCRegister& r31, PPCRegister& f31) -//{ -// auto camera = (SWA::CCamera*)g_memory.Translate(r31.u32); -// -// f31.f64 = AdjustFieldOfView(f31.f64, camera->m_HorzAspectRatio); -//} - -// PPC_FUNC_IMPL(__imp__sub_824697B0); -// PPC_FUNC(sub_824697B0) -// { -// auto pCamera = (SWA::CCamera*)g_memory.Translate(ctx.r3.u32); - -// pCamera->m_InvertX = Config::HorizontalCamera == ECameraRotationMode::Reverse; -// pCamera->m_InvertY = Config::VerticalCamera == ECameraRotationMode::Reverse; - -// __imp__sub_824697B0(ctx, base); -// } - -// // SWA::CCamera::UpdateSerial -// PPC_FUNC_IMPL(__imp__sub_82467890); -// PPC_FUNC(sub_82467890) -// { -// if (g_needsResize) -// { -// // Recompute the projection matrix for one frame to fix stretching on pause menu. -// auto r3 = ctx.r3; -// auto r4 = ctx.r4; -// sub_82468E38(ctx, base); -// ctx.r3 = r3; -// ctx.r4 = r4; -// } - -// __imp__sub_82467890(ctx, base); -// } diff --git a/MarathonRecomp/patches/camera_patches.h b/MarathonRecomp/patches/camera_patches.h deleted file mode 100644 index 949a2ddc3..000000000 --- a/MarathonRecomp/patches/camera_patches.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -extern float AdjustFieldOfView(float fieldOfView, float aspectRatio); diff --git a/MarathonRecomp/patches/fps_patches.cpp b/MarathonRecomp/patches/fps_patches.cpp deleted file mode 100644 index 015ded6c7..000000000 --- a/MarathonRecomp/patches/fps_patches.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include -#include -#include -#include -#include - -void DownForceDeltaTimeFixMidAsmHook(PPCRegister& f0) -{ - f0.f64 = 30.0; -} - -void DownForceDeltaTimeFixMidAsmHook(PPCVRegister& v127, PPCRegister& f24) -{ - double factor = 1.0 / (f24.f64 * 30.0); - v127.f32[0] *= factor; - v127.f32[1] *= factor; - v127.f32[2] *= factor; - v127.f32[3] *= factor; -} - -void HighFrameRateDeltaTimeFixMidAsmHook(PPCRegister& f1) -{ - // Having 60 FPS threshold ensures we still retain - // the original game behavior when locked to 30/60 FPS. - constexpr double threshold = 1.0 / 60.0; - - if (f1.f64 < threshold) - f1.f64 = threshold; -} - -// This hook expects the vector register to store delta time at the first index. -void HighFrameRateDeltaTimeFixVectorMidAsmHook(PPCVRegister& v62) -{ - // Having 60 FPS threshold ensures we still retain - // the original game behavior when locked to 30/60 FPS. - constexpr double threshold = 1.0 / 60.0; - - if (v62.f32[3] < threshold) - v62.f32[3] = threshold; -} - -void CameraDeltaTimeFixMidAsmHook(PPCRegister& dest, PPCRegister& src) -{ - dest.f64 = src.f64 / 30.0; -} - -void CameraDeltaTimeFixMidAsmHook(PPCRegister& dest) -{ - dest.f64 /= 30.0; -} - -static double ComputeLerpFactor(double t, double deltaTime) -{ - // This type of lerp still falls behind when - // playing catch with a constantly moving position. - // The bias helps with approximately bringing it closer. - double fps = 1.0 / deltaTime; - double bias = t * 60.0; - return 1.0 - pow(1.0 - t, (30.0 + bias) / (fps + bias)); -} - -// It's important to use global delta time here instead of function provided -// delta time, as it might be time scaled and not match with 30 FPS behavior. -void CameraLerpFixMidAsmHook(PPCRegister& t) -{ - t.f64 = ComputeLerpFactor(t.f64, App::s_deltaTime); -} - -void CameraTargetSideOffsetLerpFixMidAsmHook(PPCVRegister& v13, PPCVRegister& v62) -{ - float factor = float(ComputeLerpFactor(double(v13.f32[0] * v62.f32[0]), App::s_deltaTime)); - - for (size_t i = 0; i < 4; i++) - { - v62.f32[i] = factor; - v13.f32[i] = 1.0f; - } -} - -void Camera2DLerpFixMidAsmHook(PPCRegister& t, PPCRegister& deltaTime) -{ - t.f64 = ComputeLerpFactor(std::min(1.0, t.f64 * 2.0), deltaTime.f64 / 60.0); -} - -void Camera2DSlopeLerpFixMidAsmHook(PPCRegister& t, PPCRegister& deltaTime) -{ - t.f64 = ComputeLerpFactor(t.f64, deltaTime.f64 / 60.0); -} - -using namespace std::chrono_literals; - -static std::chrono::steady_clock::time_point g_prev; - -//bool LoadingUpdateMidAsmHook(PPCRegister& r31) -//{ -// auto now = std::chrono::steady_clock::now(); -// double deltaTime = std::min(std::chrono::duration(now - g_prev).count(), 1.0 / 15.0); -// g_prev = now; -// -// uint8_t* base = g_memory.base; -// uint32_t application = PPC_LOAD_U32(PPC_LOAD_U32(r31.u32 + 4)); -// uint32_t update = PPC_LOAD_U32(PPC_LOAD_U32(application) + 20); -// -// g_ppcContext->r3.u32 = application; -// g_ppcContext->f1.f64 = deltaTime; -// g_memory.FindFunction(update)(*g_ppcContext, base); -// -// bool loading = *SWA::SGlobals::ms_IsLoading; -// if (loading) -// { -// now = std::chrono::steady_clock::now(); -// constexpr auto INTERVAL = 1000000000ns / 30; -// auto next = now + (INTERVAL - now.time_since_epoch() % INTERVAL); -// -// std::this_thread::sleep_until(next); -// } -// -// return loading; -//} - -// ADXM_WaitVsync -// PPC_FUNC_IMPL(__imp__sub_8312DBF8); -// PPC_FUNC(sub_8312DBF8) -// { -// auto now = std::chrono::steady_clock::now(); -// constexpr auto INTERVAL = 1000000000ns / 60; -// auto next = now + (INTERVAL - now.time_since_epoch() % INTERVAL); - -// std::this_thread::sleep_until(next); -// } - -void WaitVsyncMidAsmHook() -{ -} - -void ApplicationFrameLimiterMidAsmHook() -{ -} - -// Tornado Defense boss increments timers without respecting delta time. -// We run the update function with a 30 FPS time step to ensure all timers update at the correct rate. -static constexpr size_t EX_STAGE_BOSS_STATE_BATTLE_SIZE = 0x70; - -void CExStageBossCStateBattleAllocMidAsmHook(PPCRegister& r3) -{ - r3.u32 += sizeof(float); -} - -void CExStageBossCStateBattleCtorMidAsmHook(PPCRegister& r3) -{ - new (g_memory.base + r3.u32 + EX_STAGE_BOSS_STATE_BATTLE_SIZE) float(0); -} - -// SWA::CExStageBoss::CStateBattle::Update -// PPC_FUNC_IMPL(__imp__sub_82B00D00); -// PPC_FUNC(sub_82B00D00) -// { -// constexpr auto referenceDeltaTime = 1.0f / 30.0f; -// constexpr auto deltaTimeTolerance = 0.0001f; - -// auto pElapsedTime = (float*)(base + ctx.r3.u32 + EX_STAGE_BOSS_STATE_BATTLE_SIZE); - -// *pElapsedTime += std::min(App::s_deltaTime, 1.0 / 15.0); - -// if ((*pElapsedTime + deltaTimeTolerance) > referenceDeltaTime) -// { -// __imp__sub_82B00D00(ctx, base); -// *pElapsedTime -= referenceDeltaTime; -// } - -// *pElapsedTime = std::max(*pElapsedTime, 0.0f); -// } - -// Fix for Egg Dragoon's drill missile attack rotating 90 degrees at HFR. -//void BossEggDragoonDrillMissileCMissileSetRotationMidAsmHook(PPCRegister& r4) -//{ -// auto pRotation = (Hedgehog::Math::CQuaternion*)g_memory.Translate(r4.u32); -// auto magnitude = std::sqrt(pRotation->X * pRotation->X + pRotation->Y * pRotation->Y + pRotation->Z * pRotation->Z + pRotation->W * pRotation->W); -// -// if (magnitude < 0.0f) -// return; -// -// auto magnitudeNrm = 1.0f / magnitude; -// -// pRotation->X = pRotation->X * magnitudeNrm; -// pRotation->Y = pRotation->Y * magnitudeNrm; -// pRotation->Z = pRotation->Z * magnitudeNrm; -// pRotation->W = pRotation->W * magnitudeNrm; -//} - -bool SparkleLocusMidAsmHook() -{ - // There is an epsilon check in sparkle locus particle code that seems to never pass at high frame rates, which causes vertex corruption. - // Checking for equality doesn't fix it either, so we can fix it by forcing it to always execute instead. - // This has the side effect of the locus particle eventually snapping to the rest position during pause, but it's better than vertices exploding. - return App::s_deltaTime < (1.0 / 60.0); -} diff --git a/MarathonRecomp/patches/frontend_listener.cpp b/MarathonRecomp/patches/frontend_listener.cpp index a7268d54e..58c22ea70 100644 --- a/MarathonRecomp/patches/frontend_listener.cpp +++ b/MarathonRecomp/patches/frontend_listener.cpp @@ -21,9 +21,7 @@ static class FrontendListener : public SDLEventListener if (event->key.keysym.sym != SDLK_F8 || m_isF8KeyDown) break; -// *SWA::SGlobals::ms_IsRenderHud = !*SWA::SGlobals::ms_IsRenderHud; -// -// LOGFN("HUD {}", *SWA::SGlobals::ms_IsRenderHud ? "ON" : "OFF"); + // TODO m_isF8KeyDown = true; diff --git a/MarathonRecomp/patches/input_patches.cpp b/MarathonRecomp/patches/input_patches.cpp deleted file mode 100644 index 9081a4c1b..000000000 --- a/MarathonRecomp/patches/input_patches.cpp +++ /dev/null @@ -1,454 +0,0 @@ -#include -#include -#include -#include -#include - -constexpr double WORLD_MAP_ROTATE_DEADZONE = 0.69999999; -constexpr double WORLD_MAP_CURSOR_DEADZONE = 0.30000001; - -class WorldMapCursorParams -{ -public: - float Damping{ 0.99f }; - float FlickAccelX{ 0.25f }; - float FlickAccelY{ 0.1f }; - float FlickTerminalVelocity{ 40.0f }; - float FlickThreshold{ 2.25f }; - float SensitivityX{}; - float SensitivityY{}; - float Smoothing{ 0.8f }; -}; - -class WorldMapCursorParamsProspero : public WorldMapCursorParams -{ -public: - WorldMapCursorParamsProspero() - { - SensitivityX = 1.15f; - SensitivityY = 1.05f; - } -} -g_worldMapCursorParamsProspero; - -class WorldMapCursorParamsOrbis : public WorldMapCursorParams -{ -public: - WorldMapCursorParamsOrbis() - { - SensitivityX = 0.95f; - SensitivityY = 1.0f; - } -} -g_worldMapCursorParamsOrbis; - -#ifdef MARATHON_RECOMP_UI_KBM_SUPPORT -class WorldMapCursorParamsMouse : public WorldMapCursorParams -{ -public: - WorldMapCursorParamsMouse() - { - FlickAccelX = 0.025f; - FlickAccelY = 0.025f; - FlickThreshold = 7.5f; - SensitivityX = 0.15f; - SensitivityY = 0.15f; - } -} -g_worldMapCursorParamsMouse; -#endif - -WorldMapCursorParams g_worldMapCursorParams{}; - -static bool g_isCursorActive; - -static float g_worldMapCursorVelocityX; -static float g_worldMapCursorVelocityY; - -class SDLEventListenerForInputPatches : public SDLEventListener -{ - static inline bool ms_isMouseDown; - - static inline int ms_touchpadFingerCount; - - static inline float ms_cursorX; - static inline float ms_cursorY; - static inline float ms_cursorDeltaX; - static inline float ms_cursorDeltaY; - static inline float ms_cursorPrevX; - static inline float ms_cursorPrevY; - -public: - static void Update(float deltaTime) - { - /* NOTE (Hyper): this code was written at 144Hz and was - discovered later to be faulty at any other frame rate, - so this is here to account for that without changing - all the constants that I had tuned. */ - constexpr auto referenceDeltaTime = 1.0f / 144.0f; - - if (g_isCursorActive) - { - auto dxNorm = ms_cursorDeltaX / referenceDeltaTime; - auto dyNorm = ms_cursorDeltaY / referenceDeltaTime; - auto dxSens = dxNorm * g_worldMapCursorParams.SensitivityX; - auto dySens = dyNorm * g_worldMapCursorParams.SensitivityY; - - auto smoothing = powf(g_worldMapCursorParams.Smoothing, deltaTime / referenceDeltaTime); - - g_worldMapCursorVelocityX = smoothing * g_worldMapCursorVelocityX + (1.0f - smoothing) * dxSens; - g_worldMapCursorVelocityY = smoothing * g_worldMapCursorVelocityY + (1.0f - smoothing) * dySens; - - auto flickThreshold = g_worldMapCursorParams.FlickThreshold; - - if (fabs(dxSens) > flickThreshold || fabs(dySens) > flickThreshold) - { - g_worldMapCursorVelocityX += dxNorm * g_worldMapCursorParams.FlickAccelX * (deltaTime / referenceDeltaTime); - g_worldMapCursorVelocityY += dyNorm * g_worldMapCursorParams.FlickAccelY * (deltaTime / referenceDeltaTime); - } - - auto terminalVelocity = g_worldMapCursorParams.FlickTerminalVelocity; - - g_worldMapCursorVelocityX = std::clamp(g_worldMapCursorVelocityX, -terminalVelocity, terminalVelocity); - g_worldMapCursorVelocityY = std::clamp(g_worldMapCursorVelocityY, -terminalVelocity, terminalVelocity); - } - else - { - auto dampingFactor = powf(g_worldMapCursorParams.Damping, deltaTime / referenceDeltaTime); - - g_worldMapCursorVelocityX *= dampingFactor; - g_worldMapCursorVelocityY *= dampingFactor; - } - } - - bool OnSDLEvent(SDL_Event* event) override - { - if (!hid::IsInputAllowed()) - return false; - - switch (event->type) - { -#ifdef MARATHON_RECOMP_UI_KBM_SUPPORT - case SDL_MOUSEMOTION: - { - if (!ms_isMouseDown) - break; - - g_isCursorActive = true; - - ms_cursorDeltaX = (float)event->motion.xrel / 100.0f; - ms_cursorDeltaY = (float)event->motion.yrel / 100.0f; - - break; - } - - case SDL_MOUSEBUTTONDOWN: - { - if (event->button.button == SDL_BUTTON_LEFT) - { - g_worldMapCursorParams = g_worldMapCursorParamsMouse; - ms_isMouseDown = true; - } - - break; - } - - case SDL_MOUSEBUTTONUP: - { - if (event->button.button == SDL_BUTTON_LEFT) - { - g_isCursorActive = false; - ms_isMouseDown = false; - } - - break; - } -#endif - case SDL_CONTROLLERTOUCHPADMOTION: - { - g_isCursorActive = true; - - if (ms_touchpadFingerCount > 1) - { - g_isCursorActive = false; - break; - } - - ms_cursorX = event->ctouchpad.x; - ms_cursorY = event->ctouchpad.y; - ms_cursorDeltaX = ms_cursorX - ms_cursorPrevX; - ms_cursorDeltaY = ms_cursorY - ms_cursorPrevY; - ms_cursorPrevX = ms_cursorX; - ms_cursorPrevY = ms_cursorY; - - break; - } - - case SDL_CONTROLLERTOUCHPADDOWN: - { - g_worldMapCursorParams = hid::g_inputDeviceExplicit == hid::EInputDeviceExplicit::DualSense - ? (WorldMapCursorParams)g_worldMapCursorParamsProspero - : (WorldMapCursorParams)g_worldMapCursorParamsOrbis; - - ms_touchpadFingerCount++; - ms_cursorPrevX = event->ctouchpad.x; - ms_cursorPrevY = event->ctouchpad.y; - - break; - } - - case SDL_CONTROLLERTOUCHPADUP: - g_isCursorActive = false; - ms_touchpadFingerCount--; - break; - } - - return false; - } -} -g_sdlEventListenerForInputPatches; - -// -------------- COMMON --------------- // - -//static bool IsDPadThreshold(const SWA::SPadState* pPadState) -//{ -// if (Config::DisableDPadAsAnalogInput) -// return false; -// -// return pPadState->IsDown(SWA::eKeyState_DpadUp) || -// pPadState->IsDown(SWA::eKeyState_DpadDown) || -// pPadState->IsDown(SWA::eKeyState_DpadLeft) || -// pPadState->IsDown(SWA::eKeyState_DpadRight); -//} -// -//static bool IsLeftStickThreshold(const SWA::SPadState* pPadState, double deadzone = 0) -//{ -// return sqrtl((pPadState->LeftStickHorizontal * pPadState->LeftStickHorizontal) + -// (pPadState->LeftStickVertical * pPadState->LeftStickVertical)) > deadzone; -//} -// -//static bool IsCursorThreshold(double deadzone = 0, bool isBelowThreshold = false) -//{ -// auto sqrt = sqrtl((g_worldMapCursorVelocityX * g_worldMapCursorVelocityX) + -// (g_worldMapCursorVelocityY * g_worldMapCursorVelocityY)); -// -// if (isBelowThreshold) -// return sqrt < deadzone; -// -// return sqrt >= deadzone; -//} -// -//static void SetDPadAnalogDirectionX(PPCRegister& pPadState, PPCRegister& x, bool invert, float max = 1.0f) -//{ -// if (Config::DisableDPadAsAnalogInput) -// return; -// -// auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadLeft)) -// x.f64 = invert ? max : -max; -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadRight)) -// x.f64 = invert ? -max : max; -//} -// -//static void SetDPadAnalogDirectionY(PPCRegister& pPadState, PPCRegister& y, bool invert, float max = 1.0f) -//{ -// if (Config::DisableDPadAsAnalogInput) -// return; -// -// auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadUp)) -// y.f64 = invert ? -max : max; -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadDown)) -// y.f64 = invert ? max : -max; -//} - -// -------------- PLAYER --------------- // - -//void PostureDPadSupportMidAsmHook(PPCRegister& pPadState, PPCRegister& x, PPCRegister& y) -//{ -// SetDPadAnalogDirectionX(pPadState, x, false); -// SetDPadAnalogDirectionY(pPadState, y, false); -//} -// -//void PostureDPadSupportInvertYMidAsmHook(PPCRegister& pPadState, PPCRegister& x, PPCRegister& y) -//{ -// SetDPadAnalogDirectionX(pPadState, x, false); -// SetDPadAnalogDirectionY(pPadState, y, true); -//} -// -//void PostureDPadSupportXMidAsmHook(PPCRegister& pPadState, PPCRegister& x) -//{ -// SetDPadAnalogDirectionX(pPadState, x, false); -//} -// -//void PostureDPadSupportYMidAsmHook(PPCRegister& pPadState, PPCRegister& y) -//{ -// SetDPadAnalogDirectionY(pPadState, y, false); -//} -// -//void PostureSpaceHurrierDPadSupportXMidAsmHook(PPCRegister& pPadState, PPCVRegister& vector) -//{ -// if (Config::DisableDPadAsAnalogInput) -// return; -// -// auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadLeft)) -// vector.f32[3] = -1.0f; -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadRight)) -// vector.f32[3] = 1.0f; -//} -// -//void PostureSpaceHurrierDPadSupportYMidAsmHook(PPCRegister& pPadState, PPCVRegister& vector) -//{ -// if (Config::DisableDPadAsAnalogInput) -// return; -// -// auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadUp)) -// vector.f32[3] = 1.0f; -// -// if (pGuestPadState->IsDown(SWA::eKeyState_DpadDown)) -// vector.f32[3] = -1.0f; -//} -// -//void SetXButtonHomingMidAsmHook(PPCRegister& r1) -//{ -// auto pXButtonHoming = (bool*)(g_memory.base + r1.u32 + 0x63); -// -// *pXButtonHoming = !Config::HomingAttackOnJump; -//} -// -//bool IsHomingAttackOnJump() -//{ -// return Config::HomingAttackOnJump; -//} - -// ------------- WORLD MAP ------------- // - -//bool WorldMapDeadzoneMidAsmHook(PPCRegister& pPadState) -//{ -// auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); -// -// if (IsDPadThreshold(pGuestPadState) || IsLeftStickThreshold(pGuestPadState)) -// { -// g_worldMapCursorVelocityX = 0; -// g_worldMapCursorVelocityY = 0; -// } -// else -// { -// SDLEventListenerForInputPatches::Update(App::s_deltaTime); -// -// /* Reduce noise if the cursor is resting in -// place, but allow much precise values for -// proper interpolation to zero. */ -// if (IsCursorThreshold(0.05, true)) -// return !g_isCursorActive; -// -// return IsCursorThreshold(); -// } -// -// return IsDPadThreshold(pGuestPadState) || IsLeftStickThreshold(pGuestPadState, WORLD_MAP_ROTATE_DEADZONE); -//} -// -//bool WorldMapMagnetismMidAsmHook(PPCRegister& f0) -//{ -// if (IsCursorThreshold(f0.f64, true)) -// { -// g_worldMapCursorVelocityX = 0; -// g_worldMapCursorVelocityY = 0; -// -// return true; -// } -// -// return false; -//} -// -//void WorldMapHidSupportXMidAsmHook(PPCRegister& pPadState, PPCRegister& x) -//{ -// auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); -// -// if (IsDPadThreshold(pGuestPadState)) -// { -// SetDPadAnalogDirectionX(pPadState, x, false); -// } -// else if (fabs(g_worldMapCursorVelocityX) > 0) -// { -// x.f64 = -g_worldMapCursorVelocityX; -// } -//} -// -//void WorldMapHidSupportYMidAsmHook(PPCRegister& pPadState, PPCRegister& y) -//{ -// auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32); -// -// if (IsDPadThreshold(pGuestPadState)) -// { -// SetDPadAnalogDirectionY(pPadState, y, false); -// } -// else if (fabs(g_worldMapCursorVelocityY) > 0) -// { -// y.f64 = g_worldMapCursorVelocityY; -// } -//} - -// SWA::CWorldMapCamera::Update -// PPC_FUNC_IMPL(__imp__sub_82486968); -// PPC_FUNC(sub_82486968) -// { -// auto pWorldMapCamera = (SWA::CWorldMapCamera*)g_memory.Translate(ctx.r3.u32); - -// // Reset vertical velocity if maximum pitch reached. -// if (fabs(pWorldMapCamera->m_Pitch) >= 80.0f) -// g_worldMapCursorVelocityY = 0; - -// __imp__sub_82486968(ctx, base); -// } - -// // World Map cursor move hook. -// PPC_FUNC(sub_8256C938) -// { -// auto pWorldMapCursor = (SWA::CWorldMapCursor*)g_memory.Translate(ctx.r3.u32); - -// pWorldMapCursor->m_IsCursorMoving = g_isCursorActive && IsCursorThreshold(1.0); - -// if (ctx.r4.u8) -// { -// pWorldMapCursor->m_LeftStickVertical = 0; -// pWorldMapCursor->m_LeftStickHorizontal = 0; -// } -// else if (auto pInputState = SWA::CInputState::GetInstance()) -// { -// auto& rPadState = pInputState->GetPadState(); - -// pWorldMapCursor->m_LeftStickVertical = rPadState.LeftStickVertical; -// pWorldMapCursor->m_LeftStickHorizontal = rPadState.LeftStickHorizontal; - -// if (!Config::DisableDPadAsAnalogInput) -// { -// if (rPadState.IsDown(SWA::eKeyState_DpadUp)) -// pWorldMapCursor->m_LeftStickVertical = 1.0f; - -// if (rPadState.IsDown(SWA::eKeyState_DpadDown)) -// pWorldMapCursor->m_LeftStickVertical = -1.0f; - -// if (rPadState.IsDown(SWA::eKeyState_DpadLeft)) -// pWorldMapCursor->m_LeftStickHorizontal = -1.0f; - -// if (rPadState.IsDown(SWA::eKeyState_DpadRight)) -// pWorldMapCursor->m_LeftStickHorizontal = 1.0f; -// } - -// if (sqrtl((pWorldMapCursor->m_LeftStickHorizontal * pWorldMapCursor->m_LeftStickHorizontal) + -// (pWorldMapCursor->m_LeftStickVertical * pWorldMapCursor->m_LeftStickVertical)) > WORLD_MAP_ROTATE_DEADZONE) -// { -// pWorldMapCursor->m_IsCursorMoving = true; -// } -// } -// } diff --git a/MarathonRecomp/patches/inspire_patches.cpp b/MarathonRecomp/patches/inspire_patches.cpp deleted file mode 100644 index cfc16a769..000000000 --- a/MarathonRecomp/patches/inspire_patches.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "inspire_patches.h" -#include -#include -#include -#include -#include - -std::string InspirePatches::s_sceneName; - -//static SWA::Inspire::CScene* g_pScene; -static bool g_isFirstFrameChecked; -static uint32_t g_eventDispatchCount; - -// Sonic's mouth EXPLODES for a single frame in Temple Entrance cutscene. -// Looks very nasty. Let's hide morph models inbetween certain frames to solve it. -static bool g_loadedMouthExplosionAnimation; -static bool g_hideMorphModels; - -// 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; -// InspirePatches::s_sceneName.clear(); - -// SDL_User_EvilSonic(App::s_isWerehog); - -// g_loadedMouthExplosionAnimation = false; -// g_hideMorphModels = false; -// } - -// PPC_FUNC_IMPL(__imp__sub_82B9BA98); -// PPC_FUNC(sub_82B9BA98) -// { -// auto sceneName = (Hedgehog::Base::CSharedString*)g_memory.Translate(ctx.r5.u32); - -// InspirePatches::s_sceneName = sceneName->c_str(); - -// __imp__sub_82B9BA98(ctx, base); -// } - -void AnimationDataMakeMidAsmHook(PPCRegister& r31, PPCRegister& r29, PPCRegister& r28) -{ - uint8_t* base = g_memory.base; - - if (r28.u32 == 0x222E0 && - strcmp(reinterpret_cast(base + PPC_LOAD_U32(r31.u32)), "t0_04_SN") == 0 && - XXH3_64bits(base + r29.u32, r28.u32) == 0xEC634F0F379F478A) - { - g_loadedMouthExplosionAnimation = true; - } -} - -// Hedgehog::Mirage::CSingleMorphElement::Render -// PPC_FUNC_IMPL(__imp__sub_82E32048); -// PPC_FUNC(sub_82E32048) -// { -// if (!g_hideMorphModels) -// __imp__sub_82E32048(ctx, base); -// } - -//void InspirePatches::DrawDebug() -//{ -// if (!g_pScene) -// { -// ImGui::Text("There is no active scene."); -// return; -// } -// -// ImGui::Text("Name: %s", InspirePatches::s_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 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 || !InspirePatches::s_sceneName.size()) -// return; -// -// g_hideMorphModels = g_loadedMouthExplosionAnimation && g_pScene->m_pData->Frame >= 185.0f && -// g_pScene->m_pData->Frame < 195.0f && InspirePatches::s_sceneName == "evrt_t0_04"; -//} diff --git a/MarathonRecomp/patches/inspire_patches.h b/MarathonRecomp/patches/inspire_patches.h deleted file mode 100644 index f5537599f..000000000 --- a/MarathonRecomp/patches/inspire_patches.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -class InspirePatches -{ -public: - static std::string s_sceneName; - - static void DrawDebug(); - static void Update(); -}; diff --git a/MarathonRecomp/patches/misc_patches.cpp b/MarathonRecomp/patches/misc_patches.cpp index cd73635a9..dfd46e897 100644 --- a/MarathonRecomp/patches/misc_patches.cpp +++ b/MarathonRecomp/patches/misc_patches.cpp @@ -1,158 +1,7 @@ -#include -#include #include -#include +// TODO (Hyper): implement achievements menu. void AchievementManagerUnlockMidAsmHook(PPCRegister& id) { AchievementManager::Unlock(id.u32); } - -bool DisableHintsMidAsmHook() -{ - return !Config::Hints; -} - -// Disable Perfect Dark Gaia hints. -// PPC_FUNC_IMPL(__imp__sub_82AC36E0); -// PPC_FUNC(sub_82AC36E0) -// { -// auto pPerfectDarkGaiaChipHintName = (xpointer*)g_memory.Translate(0x8338EF10); - -// strcpy(pPerfectDarkGaiaChipHintName->get(), Config::Hints ? "V_CHP_067\0" : "end\0"); - -// __imp__sub_82AC36E0(ctx, base); -// } - -bool DisableControlTutorialMidAsmHook() -{ - return !Config::ControlTutorial; -} - -bool DisableEvilControlTutorialMidAsmHook(PPCRegister& r4, PPCRegister& r5) -{ - if (Config::ControlTutorial) - return true; - - // Only allow enemy QTE prompts to get through. - return r4.u32 == 1 && r5.u32 == 1; -} - -bool DisableDLCIconMidAsmHook() -{ - return Config::DisableDLCIcon; -} - -void WerehogBattleMusicMidAsmHook(PPCRegister& r11) -{ - if (Config::BattleTheme) - return; - - // Swap CStateBattle for CStateNormal. - if (r11.u8 == 4) - r11.u8 = 3; -} - -/* Hook function that gets the game region - and force result to zero for Japanese - to display the correct logos. */ -// PPC_FUNC_IMPL(__imp__sub_825197C0); -// PPC_FUNC(sub_825197C0) -// { -// if (Config::Language == ELanguage::Japanese) -// { -// ctx.r3.u64 = 0; -// return; -// } - -// __imp__sub_825197C0(ctx, base); -// } - -// Logo skip -// PPC_FUNC_IMPL(__imp__sub_82547DF0); -// PPC_FUNC(sub_82547DF0) -// { -// if (Config::SkipIntroLogos) -// { -// ctx.r4.u64 = 0; -// ctx.r5.u64 = 0; -// ctx.r6.u64 = 1; -// ctx.r7.u64 = 0; -// sub_825517C8(ctx, base); -// } -// else -// { -// __imp__sub_82547DF0(ctx, base); -// } -// } - -/* Ignore xercesc::EmptyStackException to - allow DLC stages with invalid XML to load. */ -// PPC_FUNC_IMPL(__imp__sub_8305D5B8); -// PPC_FUNC(sub_8305D5B8) -// { -// auto value = PPC_LOAD_U32(ctx.r3.u32 + 4); - -// if (!value) -// return; - -// __imp__sub_8305D5B8(ctx, base); -// } - -// Disable auto save warning. -// PPC_FUNC_IMPL(__imp__sub_82586698); -// PPC_FUNC(sub_82586698) -// { -// if (Config::DisableAutoSaveWarning) -// *(bool*)g_memory.Translate(0x83367BC2) = true; - -// __imp__sub_82586698(ctx, base); -// } - -// SWA::CObjHint::MsgNotifyObjectEvent::Impl -// Disable only certain hints from hint volumes. -// This hook should be used to allow hint volumes specifically to also prevent them from affecting the player. -// PPC_FUNC_IMPL(__imp__sub_82736E80); -// PPC_FUNC(sub_82736E80) -// { -// // GroupID parameter text -// auto* groupId = (const char*)(base + PPC_LOAD_U32(ctx.r3.u32 + 0x100)); - -// if (!Config::Hints) -// { -// // WhiteIsland_ACT1_001: "Your friend went off that way, Sonic. Quick, let's go after him!" -// // s20n_mykETF_c_navi_2: "Huh? Weird! We can't get through here anymore. We were able to earlier!" -// if (strcmp(groupId, "WhiteIsland_ACT1_001") != 0 && strcmp(groupId, "s20n_mykETF_c_navi_2") != 0) -// return; -// } - -// __imp__sub_82736E80(ctx, base); -// } - -// SWA::CHelpWindow::MsgRequestHelp::Impl -// Disable only certain hints from other sequences. -// This hook should be used to block hint messages from unknown sources. -// PPC_FUNC_IMPL(__imp__sub_824C1E60); -// PPC_FUNC(sub_824C1E60) -// { -// auto pMsgRequestHelp = (SWA::Message::MsgRequestHelp*)(base + ctx.r4.u32); - -// if (!Config::Hints) -// { -// // s10d_mykETF_c_navi: "Looks like we can get to a bunch of places in the village from here!" -// if (strcmp(pMsgRequestHelp->m_Name.c_str(), "s10d_mykETF_c_navi") == 0) -// return; -// } - -// __imp__sub_824C1E60(ctx, base); -// } - -// Remove boost filter -void DisableBoostFilterMidAsmHook(PPCRegister& r11) -{ - if (Config::DisableBoostFilter) - { - if (r11.u32 == 1) - r11.u32 = 0; - } -} diff --git a/MarathonRecomp/patches/object_patches.cpp b/MarathonRecomp/patches/object_patches.cpp deleted file mode 100644 index 9b8528ef8..000000000 --- a/MarathonRecomp/patches/object_patches.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include - -// SWA::CObjFlame::CObjFlame -// A field is not zero initialized, -// causing collisions to constantly get created -// and slow down the game. -// PPC_FUNC_IMPL(__imp__sub_82608E60); -// PPC_FUNC(sub_82608E60) -// { -// memset(base + ctx.r3.u32, 0, 0x154); -// __imp__sub_82608E60(ctx, base); -// } - -// The barrel gets stuck at a slope at high frame rates and softlocks the player. -// We can update the character proxy at 30 FPS, and interpolate the visuals to work around this issue. -static constexpr size_t OBJ_BIG_BARREL_SIZE = 0x1A0; - -struct ObjBigBarrelEx -{ - float elapsedTime{}; - bool interpolate{}; -}; - -void ObjBigBarrelAllocMidAsmHook(PPCRegister& r3) -{ - r3.u32 += sizeof(ObjBigBarrelEx); -} - -// SWA::CObjBigBarrel::CObjBigBarrel -// PPC_FUNC_IMPL(__imp__sub_8271AC08); -// PPC_FUNC(sub_8271AC08) -// { -// new (base + ctx.r3.u32 + OBJ_BIG_BARREL_SIZE) ObjBigBarrelEx(); -// __imp__sub_8271AC08(ctx, base); -// } - -// // CObjBigBarrel::Integrate -// PPC_FUNC_IMPL(__imp__sub_8271AA30); -// PPC_FUNC(sub_8271AA30) -// { -// auto objBigBarrelEx = reinterpret_cast(base + ctx.r3.u32 + OBJ_BIG_BARREL_SIZE); -// objBigBarrelEx->interpolate = ctx.f1.f64 < (1.0 / 30.0); -// objBigBarrelEx->elapsedTime += ctx.f1.f64; - -// if (!objBigBarrelEx->interpolate || objBigBarrelEx->elapsedTime >= (1.0f / 30.0f)) -// { -// ctx.f1.f64 = objBigBarrelEx->elapsedTime; -// __imp__sub_8271AA30(ctx, base); -// objBigBarrelEx->elapsedTime = 0.0f; -// } -// } - -//void ObjBigBarrelSetPositionMidAsmHook(PPCRegister& r3, PPCRegister& r4) -//{ -// uint8_t* base = g_memory.base; -// auto objBigBarrelEx = reinterpret_cast(base + r3.u32 + OBJ_BIG_BARREL_SIZE); -// -// if (objBigBarrelEx->interpolate) -// { -// auto characterProxy = reinterpret_cast(base + PPC_LOAD_U32(r3.u32 + 0x100)); -// auto position = reinterpret_cast(base + r4.u32); -// -// float factor = (1.0f / 30.0f) - objBigBarrelEx->elapsedTime; -// position->X = position->X - characterProxy->m_Velocity.X * factor; -// position->Y = position->Y - characterProxy->m_Velocity.Y * factor; -// position->Z = position->Z - characterProxy->m_Velocity.Z * factor; -// } -//} - -// SWA::CExBullet::AddCallback -// Tornado Defense bullet particles are colored by the button prompt, which differs on PlayStation 3. -// Luckily, the PS3 particles are left in the files, and they get spawned by name when a bullet gets created. -// PPC_FUNC_IMPL(__imp__sub_82B14CC0); -// PPC_FUNC(sub_82B14CC0) -// { -// auto isPlayStation = Config::ControllerIcons == EControllerIcons::PlayStation; - -// if (Config::ControllerIcons == EControllerIcons::Auto) -// isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation; - -// if (isPlayStation) -// { -// PPC_STORE_U8(0x820C2A0B, 'b'); // Cross -// PPC_STORE_U8(0x820C29C3, 'r'); // Circle -// PPC_STORE_U8(0x820C29DB, 'p'); // Square -// PPC_STORE_U8(0x820C29F3, 'g'); // Triangle -// } -// else -// { -// PPC_STORE_U8(0x820C2A0B, 'g'); // A -// PPC_STORE_U8(0x820C29C3, 'r'); // B -// PPC_STORE_U8(0x820C29DB, 'b'); // X -// PPC_STORE_U8(0x820C29F3, 'o'); // Y -// } - -// __imp__sub_82B14CC0(ctx, base); -// } - -// CObjGrindDashPanel is particularly egregious when it comes to overlapping sounds at HFR -// due to the character proxy sending the hit message multiple times in a frame. This is a -// quick workaround to limit the message process function to occur at a 30 FPS time step. -static constexpr size_t OBJ_GRIND_DASH_PANEL_SIZE = 0x160; - -void ObjGrindDashPanelAllocMidAsmHook(PPCRegister& r3) -{ - r3.u32 += sizeof(double); -} - -// SWA::CObjGrindDashPanel::CObjGrindDashPanel -// PPC_FUNC_IMPL(__imp__sub_82614228); -// PPC_FUNC(sub_82614228) -// { -// *reinterpret_cast(base + ctx.r3.u32 + OBJ_GRIND_DASH_PANEL_SIZE) = 0.0; -// __imp__sub_82614228(ctx, base); -// } - -// // SWA::CObjGrindDashPanel::MsgHitEventCollision::Impl -// PPC_FUNC_IMPL(__imp__sub_826145D8); -// PPC_FUNC(sub_826145D8) -// { -// constexpr double REFERENCE_DELTA_TIME = 1.0 / 30.0; -// constexpr double DELTA_TIME_TOLERANCE = 0.0001; - -// auto lastHitTime = reinterpret_cast(base + ctx.r3.u32 + OBJ_GRIND_DASH_PANEL_SIZE); -// auto deltaTime = App::s_time - *lastHitTime; - -// if ((deltaTime + DELTA_TIME_TOLERANCE) > REFERENCE_DELTA_TIME) -// { -// __imp__sub_826145D8(ctx, base); -// *lastHitTime = App::s_time; -// } -// } diff --git a/MarathonRecomp/patches/player_patches.cpp b/MarathonRecomp/patches/player_patches.cpp deleted file mode 100644 index e5c856b0e..000000000 --- a/MarathonRecomp/patches/player_patches.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include -#include -#include -#include - -static uint32_t g_lastEnemyScore; -static uint32_t g_lastTrickScore; -static float g_lastDarkGaiaEnergy; -static bool g_isUnleashCancelled; - -/* Hook function for when checkpoints are activated - to preserve the current checkpoint score. */ -// PPC_FUNC_IMPL(__imp__sub_82624308); -// PPC_FUNC(sub_82624308) -// { -// __imp__sub_82624308(ctx, base); - -// if (!Config::SaveScoreAtCheckpoints) -// return; - -// if (auto pGameDocument = SWA::CGameDocument::GetInstance()) -// { -// g_lastEnemyScore = pGameDocument->m_pMember->m_ScoreInfo.EnemyScore; -// g_lastTrickScore = pGameDocument->m_pMember->m_ScoreInfo.TrickScore; - -// LOGFN("Score: {}", g_lastEnemyScore + g_lastTrickScore); -// } -// } - -/* Hook function that resets the score - and restore the last checkpoint score. */ -// PPC_FUNC_IMPL(__imp__sub_8245F048); -// PPC_FUNC(sub_8245F048) -// { -// __imp__sub_8245F048(ctx, base); - -// if (!Config::SaveScoreAtCheckpoints) -// return; - -// if (auto pGameDocument = SWA::CGameDocument::GetInstance()) -// { -// LOGFN("Score: {}", g_lastEnemyScore + g_lastTrickScore); - -// pGameDocument->m_pMember->m_ScoreInfo.EnemyScore = g_lastEnemyScore; -// pGameDocument->m_pMember->m_ScoreInfo.TrickScore = g_lastTrickScore; -// } -// } - -void ResetScoreOnRestartMidAsmHook() -{ - g_lastEnemyScore = 0; - g_lastTrickScore = 0; -} - -// Dark Gaia energy change hook. -// PPC_FUNC_IMPL(__imp__sub_823AF7A8); -// PPC_FUNC(sub_823AF7A8) -// { -// auto pEvilSonicContext = (SWA::Player::CEvilSonicContext*)g_memory.Translate(ctx.r3.u32); - -// g_lastDarkGaiaEnergy = pEvilSonicContext->m_DarkGaiaEnergy; - -// // Don't drain energy if out of control. -// if (Config::FixUnleashOutOfControlDrain && pEvilSonicContext->m_OutOfControlCount && ctx.f1.f64 < 0.0) -// return; - -// __imp__sub_823AF7A8(ctx, base); - -// if (!Config::AllowCancellingUnleash) -// return; - -// auto pInputState = SWA::CInputState::GetInstance(); - -// // Don't allow cancelling Unleash if the intro anim is still playing. -// if (!pInputState || pEvilSonicContext->m_AnimationID == 39) -// return; - -// if (pInputState->GetPadState().IsTapped(SWA::eKeyState_RightBumper)) -// { -// pEvilSonicContext->m_DarkGaiaEnergy = 0.0f; -// g_isUnleashCancelled = true; -// } -// } - -//void PostUnleashMidAsmHook(PPCRegister& r30) -//{ -// if (!g_isUnleashCancelled) -// return; -// -// if (auto pEvilSonicContext = (SWA::Player::CEvilSonicContext*)g_memory.Translate(r30.u32)) -// pEvilSonicContext->m_DarkGaiaEnergy = std::max(0.0f, g_lastDarkGaiaEnergy - 35.0f); -// -// g_isUnleashCancelled = false; -//} - -// 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 -// PPC_FUNC_IMPL(__imp__sub_823B4590); -// PPC_FUNC(sub_823B4590) -// { -// __imp__sub_823B4590(ctx, base); - -// App::s_isWerehog = false; - -// SDL_User_EvilSonic(false); -// } diff --git a/MarathonRecomp/patches/resident_patches.cpp b/MarathonRecomp/patches/resident_patches.cpp deleted file mode 100644 index 8be5a3233..000000000 --- a/MarathonRecomp/patches/resident_patches.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include -#include -#include -#include - -bool m_isSavedAchievementData = false; - -// SWA::Message::MsgRequestStartLoading::Impl -// PPC_FUNC_IMPL(__imp__sub_824DCF38); -// PPC_FUNC(sub_824DCF38) -// { -// auto pLoading = (SWA::CLoading*)g_memory.Translate(ctx.r3.u32); - -// App::s_isLoading = true; - -// if (ctx.r4.u32 == SWA::eLoadingDisplayType_WerehogMovie) -// { -// if (Config::TimeOfDayTransition == ETimeOfDayTransition::PlayStation) -// { -// ctx.r4.u32 = SWA::eLoadingDisplayType_ChangeTimeOfDay; -// pLoading->m_IsNightToDay = App::s_isWerehog; -// } - -// if (Config::UseArrowsForTimeOfDayTransition) -// ctx.r4.u32 = SWA::eLoadingDisplayType_Arrows; -// } - -// if (Config::FixEggmanlandUsingEventGalleryTransition) -// { -// if (auto pGameDocument = SWA::CGameDocument::GetInstance()) -// { -// auto stageName = pGameDocument->m_pMember->m_StageName.c_str(); - -// if (stageName && strlen(stageName)) -// { -// /* Fix restarting Eggmanland as the Werehog -// erroneously using the Event Gallery transition. */ -// if (ctx.r4.u32 == SWA::eLoadingDisplayType_EventGallery && !strcmp(stageName, "Act_EggmanLand")) -// ctx.r4.u32 = SWA::eLoadingDisplayType_NowLoading; -// } -// } -// } - -// __imp__sub_824DCF38(ctx, base); -// } - -// The game checks for a bool to render the PS3 transition animation. It's never set so it's presumably a "is PS3" bool. -bool LoadingRenderMidAsmHook() -{ - return Config::TimeOfDayTransition == ETimeOfDayTransition::PlayStation; -} - -// Patch "ui_loading.yncp" to remove the medal swinging animation. -// SWA::CCsdProject::Make -// PPC_FUNC_IMPL(__imp__sub_825E4068); -// PPC_FUNC(sub_825E4068) -// { -// if (ctx.r4.u32 != NULL && ctx.r5.u32 == 0x65C0C && XXH3_64bits(base + ctx.r4.u32, ctx.r5.u32) == 0xD4DA1A9BE4D79BED) -// { -// // Keyframe count. First keyframe is at the center of the screen. -// PPC_STORE_U32(ctx.r4.u32 + 0x2794C, 1); -// } - -// __imp__sub_825E4068(ctx, base); -// } - -// SWA::CLoading::Update -// PPC_FUNC_IMPL(__imp__sub_824DAB60); -// PPC_FUNC(sub_824DAB60) -// { -// auto pLoading = (SWA::CLoading*)g_memory.Translate(ctx.r3.u32); - -// __imp__sub_824DAB60(ctx, base); - -// if (!pLoading->m_LoadingDisplayType) -// App::s_isLoading = false; -// } - -// Load voice language files. -// PPC_FUNC_IMPL(__imp__sub_824EB9B0); -// PPC_FUNC(sub_824EB9B0) -// { -// auto pApplicationDocument = (SWA::CApplicationDocument*)g_memory.Translate(ctx.r4.u32); - -// pApplicationDocument->m_VoiceLanguage = (SWA::EVoiceLanguage)Config::VoiceLanguage.Value; - -// __imp__sub_824EB9B0(ctx, base); -// } - -// SWA::CSaveIcon::Update -// PPC_FUNC_IMPL(__imp__sub_824E5170); -// PPC_FUNC(sub_824E5170) -// { -// auto pSaveIcon = (SWA::CSaveIcon*)g_memory.Translate(ctx.r3.u32); - -// __imp__sub_824E5170(ctx, base); - -// App::s_isSaving = pSaveIcon->m_IsVisible; - -// if (pSaveIcon->m_IsVisible) -// { -// App::s_isSaveDataCorrupt = false; - -// if (!m_isSavedAchievementData) -// { -// AchievementManager::Save(); - -// m_isSavedAchievementData = true; -// } -// } -// else -// { -// m_isSavedAchievementData = false; -// } -// } - -// SWA::CApplicationDocument::LoadArchiveDatabases -// PPC_FUNC_IMPL(__imp__sub_824EFD28); -// PPC_FUNC(sub_824EFD28) -// { -// auto r3 = ctx.r3; - -// // SWA::CSigninXenon::InitializeDLC -// ctx.r3.u64 = PPC_LOAD_U32(r3.u32 + 4) + 200; -// ctx.r4.u64 = 0; -// sub_822C57D8(ctx, base); - -// ctx.r3 = r3; -// __imp__sub_824EFD28(ctx, base); -// } - -// SWA::CFileReaderXenon_DLC::InitializeParallel -// PPC_FUNC(sub_822C3778) -// { -// if (!PPC_LOAD_U8(0x83361F10)) // ms_DLCInitialized -// { -// // CFileReaderXenon_DLC::InitializeSerial -// sub_822C2CF0(ctx, base); -// } -// } - -// HasAnyDLC -// NOTE: This is not used outside title screen outro, so it's safe to hook. -// PPC_FUNC(sub_82BD06C8) -// { -// ctx.r3.u64 = 0; -// } - -void LoadingScreenControllerMidAsmHook() -{ - static constexpr size_t STR_ADDRESSES[] = - { - 0x820301AC, // 360_sonic1 - 0x820301B8, // 360_sonic2 - 0x820301C4, // 360_sonic3 - 0x820301D0, // 360_evil - 0x820301DC, // 360_robo - 0x820301E8 // 360_super - }; - - auto isPlayStation = Config::ControllerIcons == EControllerIcons::PlayStation; - - if (Config::ControllerIcons == EControllerIcons::Auto) - isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation; - - const char* prefix = isPlayStation ? "ps3" : "360"; - - for (auto address : STR_ADDRESSES) - memcpy(g_memory.Translate(address), prefix, 3); -} diff --git a/MarathonRecomp/patches/video_patches.cpp b/MarathonRecomp/patches/video_patches.cpp index 65ff5e03e..5d23e795d 100644 --- a/MarathonRecomp/patches/video_patches.cpp +++ b/MarathonRecomp/patches/video_patches.cpp @@ -1,143 +1,4 @@ -#include -#include -#include -#include -#include "aspect_ratio_patches.h" - -//using SVertexData = SWA::Sequence::Utility::CPlayMovieWrapper::CRender::SVertexData; - -// Update movie player aspect ratio. -// PPC_FUNC_IMPL(__imp__sub_82AE30D8); -// PPC_FUNC(sub_82AE30D8) -// { -// auto pViewportWidth = (be*)g_memory.Translate(ctx.r4.u32 + 0x14); -// auto pViewportHeight = (be*)g_memory.Translate(ctx.r4.u32 + 0x18); - -// auto pTopLeft = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C); -// auto pTopRight = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C + sizeof(SVertexData)); -// auto pBottomRight = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C + sizeof(SVertexData) * 2); -// auto pBottomLeft = (SVertexData*)g_memory.Translate(ctx.r4.u32 + 0x6C + sizeof(SVertexData) * 3); - -// auto quadWidth = std::fabs(pTopRight->X - pTopLeft->X) * ((float)*pViewportWidth / 2); -// auto quadHeight = std::fabs(pTopLeft->Y - pBottomLeft->Y) * ((float)*pViewportHeight / 2); - -// auto movieAspectRatio = quadWidth / quadHeight; - -// auto scaleU = 1.0f; -// auto scaleV = 1.0f; -// auto centreV = (pTopLeft->V + pBottomRight->V) / 2.0f; - -// if (g_aspectRatio > movieAspectRatio) -// { -// scaleU = movieAspectRatio / g_aspectRatio; -// } -// else -// { -// scaleV = g_aspectRatio / movieAspectRatio; -// } - -// float halfPixelX = 1.0f / Video::s_viewportWidth; -// float halfPixelY = 1.0f / Video::s_viewportHeight; - -// pTopLeft->X = -1.0f - halfPixelX; -// pTopLeft->Y = 1.0f + halfPixelY; -// pTopLeft->U = (pTopLeft->U - centreV) / scaleU + centreV; -// pTopLeft->V = (pTopLeft->V - centreV) / scaleV + centreV; - -// pTopRight->X = 1.0f - halfPixelX; -// pTopRight->Y = 1.0f + halfPixelY; -// pTopRight->U = (pTopRight->U - centreV) / scaleU + centreV; -// pTopRight->V = (pTopRight->V - centreV) / scaleV + centreV; - -// pBottomLeft->X = -1.0f - halfPixelX; -// pBottomLeft->Y = -1.0f + halfPixelY; -// pBottomLeft->U = (pBottomLeft->U - centreV) / scaleU + centreV; -// pBottomLeft->V = (pBottomLeft->V - centreV) / scaleV + centreV; - -// pBottomRight->X = 1.0f - halfPixelX; -// pBottomRight->Y = -1.0f + halfPixelY; -// pBottomRight->U = (pBottomRight->U - centreV) / scaleU + centreV; -// pBottomRight->V = (pBottomRight->V - centreV) / scaleV + centreV; - -// __imp__sub_82AE30D8(ctx, base); -// } - -void RemoveMoviePlayerLetterboxMidAsmHook() {} - -bool MotionBlurMidAsmHook() +void SetMSAALevel(PPCRegister& val) { - return Config::MotionBlur != EMotionBlur::Off; + val.u32 = 0; } - -// Hedgehog::MirageDebug::PrepareRenderPrimitive2D -// PPC_FUNC_IMPL(__imp__sub_830D25D8); -// PPC_FUNC(sub_830D25D8) -// { -// auto device = reinterpret_cast(base + PPC_LOAD_U32(ctx.r4.u32)); - -// // Set first sampler to use linear filtering. -// // NOTE: We only check for height here since all 2D primitives get centered. -// if (Video::s_viewportHeight > 720) -// { -// device->samplerStates[0].data[3] = (device->samplerStates[0].data[3].get() & ~0x1f80000) | 0x1280000; -// device->dirtyFlags[3] = device->dirtyFlags[3].get() | 0x80000000ull; -// } - -// __imp__sub_830D25D8(ctx, base); -// } - -// Rope renderables sometimes get bogus colors due to the material parameters of whatever -// was rendered last leaking into their render state. We can reset them to fix it. - -static void SetDefaultMaterialParameters(GuestDevice* device) -{ - const be diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f }; - const be ambient[] = { 1.0f, 1.0f, 1.0f, 0.0f }; - const be specular[] = { 0.9f, 0.9f, 0.9f, 0.0f }; - - memcpy(&device->pixelShaderFloatConstants[64], diffuse, sizeof(diffuse)); // g_Diffuse - memcpy(&device->pixelShaderFloatConstants[68], ambient, sizeof(ambient)); // g_Ambient - memcpy(&device->pixelShaderFloatConstants[72], specular, sizeof(specular)); // g_Specular - - device->dirtyFlags[1] = ~0ull; -} - -// SWA::CRopeRenderable::Render -// PPC_FUNC_IMPL(__imp__sub_827CBF68); -// PPC_FUNC(sub_827CBF68) -// { -// SetDefaultMaterialParameters(reinterpret_cast(base + PPC_LOAD_U32(PPC_LOAD_U32(ctx.r4.u32)))); -// __imp__sub_827CBF68(ctx, base); -// } - -// SWA::CObjUpReel::CPrimitiveReel::Render -// PPC_FUNC_IMPL(__imp__sub_8260BBF8); -// PPC_FUNC(sub_8260BBF8) -// { -// SetDefaultMaterialParameters(reinterpret_cast(base + PPC_LOAD_U32(PPC_LOAD_U32(ctx.r4.u32)))); -// __imp__sub_8260BBF8(ctx, base); -// } - -// The pedestal in Gaia Temple is placed on an opaque mesh slot, despite using additive blending. -// This somehow works. Except when the delta time is too stable, it flashes black for one frame. -// We can fix it by detecting the asset runtime, and swapping the mesh slots to transparent by hand. - -// Hedgehog::Mirage::CModelData::Make -// PPC_FUNC_IMPL(__imp__sub_82E38650); -// PPC_FUNC(sub_82E38650) -// { -// if (ctx.r5.u32 == 0xBB90 && XXH3_64bits(base + ctx.r4.u32, ctx.r5.u32) == 0xB524C8C3B80C3F54) -// { -// // Mesh Count -// std::swap( -// *reinterpret_cast(base + ctx.r4.u32 + 0x18), -// *reinterpret_cast(base + ctx.r4.u32 + 0x20)); - -// // Mesh Offset -// std::swap( -// *reinterpret_cast(base + ctx.r4.u32 + 0x1C), -// *reinterpret_cast(base + ctx.r4.u32 + 0x24)); -// } - -// __imp__sub_82E38650(ctx, base); -// } diff --git a/MarathonRecomp/ui/achievement_overlay.cpp b/MarathonRecomp/ui/achievement_overlay.cpp index 7b9305bdd..d36afe80b 100644 --- a/MarathonRecomp/ui/achievement_overlay.cpp +++ b/MarathonRecomp/ui/achievement_overlay.cpp @@ -10,7 +10,6 @@ #include #include #include -#include constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0; constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11; @@ -97,20 +96,7 @@ static std::thread::id g_mainThreadId = std::this_thread::get_id(); static bool CanDequeueAchievement() { - if (g_soundAdministratorUpdated && std::this_thread::get_id() == g_mainThreadId && !AchievementOverlay::s_queue.empty()) - { - // Check if we can actually play any audio right now. If not, we'll wait until we can. - uint32_t audioCenter = *reinterpret_cast*>(g_memory.Translate(0x83362FFC)); - if (audioCenter != NULL) - { - uint32_t member = *reinterpret_cast*>(g_memory.Translate(audioCenter + 0x4)); - uint32_t category = !InspirePatches::s_sceneName.empty() ? 10 : 7; // EVENT category is used during Inspire cutscenes. - - // Check if the volume is non zero. - return *reinterpret_cast(g_memory.Translate(member + 0x7C + category * 0x10 + 0x8)) != 0; - } - } - + // TODO return false; } diff --git a/MarathonRecomp/user/config_def.h b/MarathonRecomp/user/config_def.h index 413857247..6f0f7108c 100644 --- a/MarathonRecomp/user/config_def.h +++ b/MarathonRecomp/user/config_def.h @@ -75,24 +75,11 @@ CONFIG_DEFINE_LOCALISED("Video", bool, XboxColorCorrection, false); CONFIG_DEFINE_ENUM_LOCALISED("Video", ECutsceneAspectRatio, CutsceneAspectRatio, ECutsceneAspectRatio::Original); CONFIG_DEFINE_ENUM_LOCALISED("Video", EUIAlignmentMode, UIAlignmentMode, EUIAlignmentMode::Edge); -CONFIG_DEFINE_HIDDEN("Codes", bool, AllowCancellingUnleash, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, DisableAutoSaveWarning, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, DisableBoostFilter, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, DisableDLCIcon, false); CONFIG_DEFINE_HIDDEN("Codes", bool, DisableDWMRoundedCorners, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, EnableEventCollisionDebugView, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, EnableGIMipLevelDebugView, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, EnableObjectCollisionDebugView, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, EnableStageCollisionDebugView, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, FixEggmanlandUsingEventGalleryTransition, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, FixUnleashOutOfControlDrain, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, HomingAttackOnJump, false); +CONFIG_DEFINE_HIDDEN("Codes", bool, DisableTitleInputDelay, false); CONFIG_DEFINE_HIDDEN("Codes", bool, HUDToggleKey, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, SaveScoreAtCheckpoints, false); CONFIG_DEFINE_HIDDEN("Codes", bool, SkipIntroLogos, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, UseArrowsForTimeOfDayTransition, false); CONFIG_DEFINE_HIDDEN("Codes", bool, UseOfficialTitleOnTitleBar, false); CONFIG_DEFINE_HIDDEN("Codes", bool, DisableLowResolutionFontOnCustomUI, false); -CONFIG_DEFINE_HIDDEN("Codes", bool, DisableDPadAsAnalogInput, false); CONFIG_DEFINE("Update", time_t, LastChecked, 0); diff --git a/MarathonRecompLib/config/Marathon.toml b/MarathonRecompLib/config/Marathon.toml index c0cbf37e3..1bb436455 100644 --- a/MarathonRecompLib/config/Marathon.toml +++ b/MarathonRecompLib/config/Marathon.toml @@ -89,61 +89,42 @@ invalid_instructions = [ { data = 0x00000000, size = 4 }, # Padding { data = 0x826E3E60, size = 8 }, # C++ Frame Handler { data = 0x82AEA1CC, size = 8 } # C Specific Frame Handler - #{ data = 0x00485645, size = 44 } # End of .text + # { data = 0x00485645, size = 44 } # End of .text ] [[midasm_hook]] -name = "DisableMSAA" -address = 0x82607B94 -registers = ["r28"] -after_instruction = true - -[[midasm_hook]] -name = "DisableMSAA" -address = 0x82607BB8 -registers = ["r28"] -after_instruction = true - -[[midasm_hook]] -name = "DisableStartWait" -address = 0x82512748 -jump_address = 0x8251274C +name = "SetMSAALevel" +address = 0x82607CD4 +registers = ["r4"] [[midasm_hook]] -name = "EnableTitleButtons" +name = "RestoreTitleButtons" address = 0x82512810 registers = ["r4"] after_instruction = true [[midasm_hook]] -name = "EnableTitleButtons2" +name = "RestoreTitleButtons2" address = 0x82512874 registers = ["r11"] after_instruction = true [[midasm_hook]] -name = "TitleMenuDefaultSelection" -address = 0x82512B04 -registers = ["r4", "r31"] -after_instruction = true - -#[[midasm_hook]] -#name = "IgnoreXAudioLockPlsFixAndDeleteThisMidasm" -#address = 0x8255AAE8 -#registers = ["r11"] -#jump_address = 0x8255AB24 +name = "DisableTitleTaskStartWait" +address = 0x82512748 +jump_address_on_true = 0x8251274C -#[[midasm_hook]] -#name = "DebugZlibMidAsmHook" -#address = 0x826DC30C -#registers = ["r12"] +[[midasm_hook]] +name = "SetDefaultTitleTaskSelection" +address = 0x82512B10 +registers = ["r3", "r4"] -#[[midasm_hook]] -#name = "DebugZlibMidAsm2Hook" -#address = 0x826DC310 -#registers = ["r10"] +[[midasm_hook]] +name = "RenderCsdCastNodeMidAsmHook" +address = 0x828C8FBC +registers = ["r10", "r24"] -#[[midasm_hook]] -#name = "DebugIndirectCall" -#address = 0x8273C440 -#registers = ["r3"] \ No newline at end of file +[[midasm_hook]] +name = "RenderCsdCastMidAsmHook" +address = 0x828C8FFC +registers = ["r4"]