diff --git a/CMakeLists.txt b/CMakeLists.txt index 141f3764..9032d762 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,11 @@ endif() set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +# Target Sandy Bridge for all projects +add_compile_options( + -march=sandybridge +) + add_subdirectory(${UNLEASHED_RECOMP_THIRDPARTY_ROOT}) add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}) diff --git a/UnleashedRecomp/CMakeLists.txt b/UnleashedRecomp/CMakeLists.txt index 011244b8..2eed3598 100644 --- a/UnleashedRecomp/CMakeLists.txt +++ b/UnleashedRecomp/CMakeLists.txt @@ -39,9 +39,7 @@ function(BIN2C) endfunction() add_compile_options( - -march=sandybridge -fno-strict-aliasing - -Wno-switch -Wno-unused-function -Wno-unused-variable diff --git a/UnleashedRecomp/api/Hedgehog/Math/Vector.h b/UnleashedRecomp/api/Hedgehog/Math/Vector.h index b1c0f3da..7ea0e382 100644 --- a/UnleashedRecomp/api/Hedgehog/Math/Vector.h +++ b/UnleashedRecomp/api/Hedgehog/Math/Vector.h @@ -17,6 +17,7 @@ namespace Hedgehog::Math be X; be Y; be Z; + be W; }; class CVector4 diff --git a/UnleashedRecomp/api/SWA.h b/UnleashedRecomp/api/SWA.h index 48b0730b..01e0c61c 100644 --- a/UnleashedRecomp/api/SWA.h +++ b/UnleashedRecomp/api/SWA.h @@ -60,6 +60,7 @@ #include "SWA/CSD/GameObjectCSD.h" #include "SWA/Camera/Camera.h" #include "SWA/Camera/CameraController.h" +#include "SWA/CharacterUtility/CharacterProxy.h" #include "SWA/HUD/GeneralWindow/GeneralWindow.h" #include "SWA/HUD/Loading/Loading.h" #include "SWA/HUD/Pause/HudPause.h" diff --git a/UnleashedRecomp/api/SWA/CharacterUtility/CharacterProxy.h b/UnleashedRecomp/api/SWA/CharacterUtility/CharacterProxy.h new file mode 100644 index 00000000..4032727c --- /dev/null +++ b/UnleashedRecomp/api/SWA/CharacterUtility/CharacterProxy.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +namespace SWA +{ + class CCharacterProxy + { + public: + SWA_INSERT_PADDING(0x120); + Hedgehog::Math::CVector m_Position; + Hedgehog::Math::CVector m_Velocity; + }; +} diff --git a/UnleashedRecomp/gpu/imgui/imgui_common.h b/UnleashedRecomp/gpu/imgui/imgui_common.h index 861e72cc..b2bd3fc2 100644 --- a/UnleashedRecomp/gpu/imgui/imgui_common.h +++ b/UnleashedRecomp/gpu/imgui/imgui_common.h @@ -22,6 +22,7 @@ enum class ImGuiCallback : int32_t SetOutline = -6, SetProceduralOrigin = -7, // -8 is ImDrawCallback_ResetRenderState, don't use! + SetAdditive = -9 }; union ImGuiCallbackData @@ -64,6 +65,11 @@ union ImGuiCallbackData { float proceduralOrigin[2]; } setProceduralOrigin; + + struct + { + bool enabled; + } setAdditive; }; extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback); diff --git a/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h b/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h index 51134fe3..89974ced 100644 --- a/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h +++ b/UnleashedRecomp/gpu/rhi/plume_render_interface_types.h @@ -1127,7 +1127,7 @@ namespace plume { desc.srcBlend = RenderBlend::SRC_ALPHA; desc.dstBlend = RenderBlend::INV_SRC_ALPHA; desc.blendOp = RenderBlendOperation::ADD; - desc.srcBlendAlpha = RenderBlend::ONE; + desc.srcBlendAlpha = RenderBlend::SRC_ALPHA; desc.dstBlendAlpha = RenderBlend::INV_SRC_ALPHA; desc.blendOpAlpha = RenderBlendOperation::ADD; return desc; diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index cbdb1023..eab0df4f 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -1141,6 +1141,7 @@ static constexpr size_t SAMPLER_DESCRIPTOR_SIZE = 1024; static std::unique_ptr g_imFontTexture; static std::unique_ptr g_imPipelineLayout; static std::unique_ptr g_imPipeline; +static std::unique_ptr g_imAdditivePipeline; template static void ExecuteCopyCommandList(const T& function) @@ -1309,6 +1310,9 @@ static void CreateImGuiBackend() pipelineDesc.inputSlotsCount = 1; g_imPipeline = g_device->createGraphicsPipeline(pipelineDesc); + pipelineDesc.renderTargetBlend[0].dstBlend = RenderBlend::ONE; + g_imAdditivePipeline = g_device->createGraphicsPipeline(pipelineDesc); + #ifndef ENABLE_IM_FONT_ATLAS_SNAPSHOT ImFontAtlasSnapshot snapshot; snapshot.Snap(); @@ -2091,9 +2095,10 @@ static void ProcDrawImGui(const RenderCommand& cmd) SetFramebuffer(g_backBuffer, nullptr, false); auto& commandList = g_commandLists[g_frame]; + auto pipeline = g_imPipeline.get(); commandList->setGraphicsPipelineLayout(g_imPipelineLayout.get()); - commandList->setPipeline(g_imPipeline.get()); + commandList->setPipeline(pipeline); commandList->setGraphicsDescriptorSet(g_textureDescriptorSet.get(), 0); commandList->setGraphicsDescriptorSet(g_samplerDescriptorSet.get(), 1); @@ -2167,6 +2172,16 @@ static void ProcDrawImGui(const RenderCommand& cmd) case ImGuiCallback::SetProceduralOrigin: setPushConstants(&pushConstants.proceduralOrigin, &callbackData->setProceduralOrigin, sizeof(callbackData->setProceduralOrigin)); break; + case ImGuiCallback::SetAdditive: + { + auto pipelineToSet = callbackData->setAdditive.enabled ? g_imAdditivePipeline.get() : g_imPipeline.get(); + if (pipeline != pipelineToSet) + { + commandList->setPipeline(pipelineToSet); + pipeline = pipelineToSet; + } + break; + } default: assert(false && "Unknown ImGui callback type."); break; diff --git a/UnleashedRecomp/patches/object_patches.cpp b/UnleashedRecomp/patches/object_patches.cpp index b7ebe36e..54c391b0 100644 --- a/UnleashedRecomp/patches/object_patches.cpp +++ b/UnleashedRecomp/patches/object_patches.cpp @@ -1,3 +1,6 @@ +#include +#include + // CObjFlame::CObjFlame // A field is not zero initialized, // causing collisions to constantly get created @@ -8,3 +11,59 @@ 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); +} + +// 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; + } +} diff --git a/UnleashedRecomp/ui/imgui_utils.h b/UnleashedRecomp/ui/imgui_utils.h index 79339740..1c407e87 100644 --- a/UnleashedRecomp/ui/imgui_utils.h +++ b/UnleashedRecomp/ui/imgui_utils.h @@ -108,6 +108,17 @@ inline void ResetProceduralOrigin() SetProceduralOrigin({ 0.0f, 0.0f }); } +inline void SetAdditive(bool enabled) +{ + auto callbackData = AddImGuiCallback(ImGuiCallback::SetAdditive); + callbackData->setAdditive.enabled = enabled; +} + +inline void ResetAdditive() +{ + SetAdditive(false); +} + inline float Scale(float size) { return size * g_aspectRatioScale; diff --git a/UnleashedRecomp/ui/installer_wizard.cpp b/UnleashedRecomp/ui/installer_wizard.cpp index 7ab9c6c0..3a9b0a27 100644 --- a/UnleashedRecomp/ui/installer_wizard.cpp +++ b/UnleashedRecomp/ui/installer_wizard.cpp @@ -613,13 +613,15 @@ static void DrawContainer(ImVec2 min, ImVec2 max, bool isTextArea) ); double gridOverlayAlpha = ComputeMotionInstaller(g_appearTime, g_disappearTime, CONTAINER_INNER_TIME, CONTAINER_INNER_DURATION); - const uint32_t gridColor = IM_COL32(0, 33, 0, (isTextArea ? 128 : 255) * gridAlpha); + const uint32_t gridColor = IM_COL32(0, 33, 0, (isTextArea ? 223 : 255) * gridAlpha); const uint32_t gridOverlayColor = IM_COL32(0, 32, 0, 128 * gridOverlayAlpha); float gridSize = Scale(GRID_SIZE); SetShaderModifier(IMGUI_SHADER_MODIFIER_CHECKERBOARD); + SetAdditive(true); drawList->AddRectFilled(min, max, gridColor); + SetAdditive(false); SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE); if (isTextArea) diff --git a/UnleashedRecomp/ui/options_menu.cpp b/UnleashedRecomp/ui/options_menu.cpp index 124dfbca..056087c4 100644 --- a/UnleashedRecomp/ui/options_menu.cpp +++ b/UnleashedRecomp/ui/options_menu.cpp @@ -887,6 +887,8 @@ static void DrawConfigOptions() { case 0: // SYSTEM DrawConfigOption(rowCount++, yOffset, &Config::Language, !OptionsMenu::s_isPause, cmnReason); + DrawConfigOption(rowCount++, yOffset, &Config::VoiceLanguage, OptionsMenu::s_pauseMenuType == SWA::eMenuType_WorldMap, cmnReason); + DrawConfigOption(rowCount++, yOffset, &Config::Subtitles, true); DrawConfigOption(rowCount++, yOffset, &Config::Hints, !isStage, cmnReason); DrawConfigOption(rowCount++, yOffset, &Config::ControlTutorial, !isStage, cmnReason); DrawConfigOption(rowCount++, yOffset, &Config::AchievementNotifications, true); @@ -906,8 +908,6 @@ static void DrawConfigOptions() DrawConfigOption(rowCount++, yOffset, &Config::MusicVolume, true); DrawConfigOption(rowCount++, yOffset, &Config::EffectsVolume, true); DrawConfigOption(rowCount++, yOffset, &Config::ChannelConfiguration, true); - DrawConfigOption(rowCount++, yOffset, &Config::VoiceLanguage, OptionsMenu::s_pauseMenuType == SWA::eMenuType_WorldMap, cmnReason); - DrawConfigOption(rowCount++, yOffset, &Config::Subtitles, true); DrawConfigOption(rowCount++, yOffset, &Config::MusicAttenuation, AudioPatches::CanAttenuate(), &Localise("Options_Desc_OSNotSupported")); DrawConfigOption(rowCount++, yOffset, &Config::BattleTheme, true); break; diff --git a/UnleashedRecomp/ui/options_menu_thumbnails.cpp b/UnleashedRecomp/ui/options_menu_thumbnails.cpp index d66cb7b6..f963dd98 100644 --- a/UnleashedRecomp/ui/options_menu_thumbnails.cpp +++ b/UnleashedRecomp/ui/options_menu_thumbnails.cpp @@ -65,6 +65,8 @@ void LoadThumbnails() g_namedThumbnails["WindowSize"] = LOAD_ZSTD_TEXTURE(g_window_size); g_configThumbnails[&Config::Language] = LOAD_ZSTD_TEXTURE(g_language); + g_configThumbnails[&Config::VoiceLanguage] = LOAD_ZSTD_TEXTURE(g_voice_language); + g_configThumbnails[&Config::Subtitles] = LOAD_ZSTD_TEXTURE(g_subtitles); g_configThumbnails[&Config::Hints] = LOAD_ZSTD_TEXTURE(g_hints); g_configThumbnails[&Config::ControlTutorial] = LOAD_ZSTD_TEXTURE(g_control_tutorial); g_configThumbnails[&Config::AchievementNotifications] = LOAD_ZSTD_TEXTURE(g_achievement_notifications); @@ -80,8 +82,6 @@ void LoadThumbnails() g_configThumbnails[&Config::MasterVolume] = LOAD_ZSTD_TEXTURE(g_master_volume); g_configThumbnails[&Config::MusicVolume] = LOAD_ZSTD_TEXTURE(g_music_volume); g_configThumbnails[&Config::EffectsVolume] = LOAD_ZSTD_TEXTURE(g_effects_volume); - g_configThumbnails[&Config::VoiceLanguage] = LOAD_ZSTD_TEXTURE(g_voice_language); - g_configThumbnails[&Config::Subtitles] = LOAD_ZSTD_TEXTURE(g_subtitles); g_configThumbnails[&Config::MusicAttenuation] = LOAD_ZSTD_TEXTURE(g_music_attenuation); g_configThumbnails[&Config::BattleTheme] = LOAD_ZSTD_TEXTURE(g_battle_theme); g_configThumbnails[&Config::WindowSize] = LOAD_ZSTD_TEXTURE(g_window_size); diff --git a/UnleashedRecomp/user/config_def.h b/UnleashedRecomp/user/config_def.h index 94395598..a3f78fe8 100644 --- a/UnleashedRecomp/user/config_def.h +++ b/UnleashedRecomp/user/config_def.h @@ -2,6 +2,8 @@ // the preprocessed output. The header is only going to have the declarations this way. CONFIG_DEFINE_ENUM_LOCALISED("System", ELanguage, Language, ELanguage::English); +CONFIG_DEFINE_ENUM_LOCALISED("System", EVoiceLanguage, VoiceLanguage, EVoiceLanguage::English); +CONFIG_DEFINE_LOCALISED("System", bool, Subtitles, true); CONFIG_DEFINE_LOCALISED("System", bool, Hints, true); CONFIG_DEFINE_LOCALISED("System", bool, ControlTutorial, true); CONFIG_DEFINE_LOCALISED("System", bool, AchievementNotifications, true); @@ -17,8 +19,6 @@ CONFIG_DEFINE_LOCALISED("Audio", float, MasterVolume, 1.0f); CONFIG_DEFINE_LOCALISED("Audio", float, MusicVolume, 1.0f); CONFIG_DEFINE_LOCALISED("Audio", float, EffectsVolume, 1.0f); CONFIG_DEFINE_ENUM_LOCALISED("Audio", EChannelConfiguration, ChannelConfiguration, EChannelConfiguration::Stereo); -CONFIG_DEFINE_ENUM_LOCALISED("Audio", EVoiceLanguage, VoiceLanguage, EVoiceLanguage::English); -CONFIG_DEFINE_LOCALISED("Audio", bool, Subtitles, true); CONFIG_DEFINE_LOCALISED("Audio", bool, MusicAttenuation, false); CONFIG_DEFINE_LOCALISED("Audio", bool, BattleTheme, true); diff --git a/UnleashedRecompLib/CMakeLists.txt b/UnleashedRecompLib/CMakeLists.txt index 6b92a236..ac774930 100644 --- a/UnleashedRecompLib/CMakeLists.txt +++ b/UnleashedRecompLib/CMakeLists.txt @@ -1,8 +1,6 @@ project("UnleashedRecompLib") add_compile_options( - -march=sandybridge - -mlzcnt -fno-strict-aliasing ) diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index 7cd63616..e030ef1c 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -792,3 +792,13 @@ registers = ["r3"] name = "TitleMenuRemoveContinueOnCorruptSaveMidAsmHook" address = 0x82585470 registers = ["r3"] + +[[midasm_hook]] +name = "ObjBigBarrelAllocMidAsmHook" +address = 0x8271B778 +registers = ["r3"] + +[[midasm_hook]] +name = "ObjBigBarrelSetPositionMidAsmHook" +address = 0x8271B5C8 +registers = ["r3", "r4"]