diff --git a/README.md b/README.md index 3cca6a7bb..b7de7e7ea 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Everything else is much too experimental to make portable/stable release builds ### Platform Support * Windows 7+ (64-bit support only) -* Mac OS X 10.9+ +* macOS 10.9+ * Linux * Arch is known to function with [`glx` vendor setup instructions](https://wiki.archlinux.org/index.php/Category:Graphics) *(main development/testing OS)* * **[WIP]** Vulkan loader detection is also integrated into the cmake for Linux @@ -22,9 +22,9 @@ Everything else is much too experimental to make portable/stable release builds * [Python 3+](https://python.org) * LLVM development package *(headers and libs)* * [Specialized Windows Package](https://www.dropbox.com/s/8vz8ogsxjhhxoi2/LLVM-4.0.0svn-win64-athena.exe?dl=1) - * [OS X Package](http://llvm.org/releases/3.9.0/clang+llvm-3.9.0-x86_64-apple-darwin.tar.xz) + * [macOS Package](http://llvm.org/releases/3.9.0/clang+llvm-3.9.0-x86_64-apple-darwin.tar.xz) * **[Windows]** [Visual Studio 2015 and Windows SDK](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx) -* **[OS X]** [Xcode Tools](https://developer.apple.com/xcode/download/) +* **[macOS]** [Xcode Tools](https://developer.apple.com/xcode/download/) * **[Linux]** recent development packages of `udev`, `x11`, `xcb`, `xinput`, `glx`, `asound` ### Prep Directions @@ -51,7 +51,7 @@ Open the repository's `CMakeLists.txt` via File > Open File or Project. Configure the desired CMake targets to build in the *Projects* area of the IDE. -Build / Debug / Run on Windows, OS X and Linux in a unified way. +Build / Debug / Run on Windows, macOS and Linux in a unified way. #### Visual Studio diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index 71b0bb00c..f35412046 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -17,8 +17,8 @@ static const SGameOption VisorOpts[] = { {EGameOption::VisorOpacity, 21, 0.f, 255.f, 1.f, EOptionType::Float}, {EGameOption::HelmetOpacity, 22, 0.f, 255.f, 1.f, EOptionType::Float}, - {EGameOption::HUDLag, 23, 0.f, 1.f, 1.f, EOptionType::Boolean}, - {EGameOption::HintSystem, 24, 0.f, 1.f, 1.f, EOptionType::Boolean}, + {EGameOption::HUDLag, 23, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::HintSystem, 24, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults} }; @@ -35,15 +35,15 @@ static const SGameOption SoundOpts[] = { {EGameOption::SFXVolume, 29, 0.f, 127.f, 1.f, EOptionType::Float}, {EGameOption::MusicVolume, 30, 0.f, 127.f, 1.f, EOptionType::Float}, - {EGameOption::SoundMode, 31, 0.f, 1.f, 1.f, EOptionType::Enum}, + {EGameOption::SoundMode, 31, 0.f, 1.f, 1.f, EOptionType::TripleEnum}, {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults} }; static const SGameOption ControllerOpts[] = { - {EGameOption::ReverseYAxis, 32, 0.f, 1.f, 1.f, EOptionType::Boolean}, - {EGameOption::Rumble, 33, 0.f, 1.f, 1.f, EOptionType::Boolean}, - {EGameOption::SwapBeamControls, 34, 0.f, 1.f, 1.f, EOptionType::Boolean}, + {EGameOption::ReverseYAxis, 32, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::Rumble, 33, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, + {EGameOption::SwapBeamControls, 34, 0.f, 1.f, 1.f, EOptionType::DoubleEnum}, {EGameOption::RestoreDefaults, 35, 0.f, 1.f, 1.f, EOptionType::RestoreDefaults} }; @@ -170,8 +170,8 @@ CGameOptions::CGameOptions(CBitStreamReader& stream) x54_screenStretch = stream.ReadEncoded(5); x58_sfxVol = stream.ReadEncoded(7); x5c_musicVol = stream.ReadEncoded(7); - x60_helmetAlpha = stream.ReadEncoded(8); - x64_hudAlpha = stream.ReadEncoded(8); + x60_hudAlpha = stream.ReadEncoded(8); + x64_helmetAlpha = stream.ReadEncoded(8); x68_24_hudLag = stream.ReadEncoded(1); x68_28_hintSystem = stream.ReadEncoded(1); @@ -189,8 +189,8 @@ void CGameOptions::ResetToDefaults() x58_sfxVol = 0x7f; x5c_musicVol = 0x7f; x44_soundMode = CAudioSys::ESurroundModes::Stereo; - x60_helmetAlpha = 0xFF; - x64_hudAlpha = 0xFF; + x60_hudAlpha = 0xFF; + x64_helmetAlpha = 0xFF; x68_24_hudLag = true; x68_25_invertY = false; x68_26_rumble = true; @@ -213,8 +213,8 @@ void CGameOptions::PutTo(CBitStreamWriter& writer) const writer.WriteEncoded(x54_screenStretch, 5); writer.WriteEncoded(x58_sfxVol, 7); writer.WriteEncoded(x5c_musicVol, 7); - writer.WriteEncoded(x60_helmetAlpha, 8); - writer.WriteEncoded(x64_hudAlpha, 8); + writer.WriteEncoded(x60_hudAlpha, 8); + writer.WriteEncoded(x64_helmetAlpha, 8); writer.WriteEncoded(x68_24_hudLag, 1); writer.WriteEncoded(x68_28_hintSystem, 1); @@ -304,22 +304,12 @@ void CGameOptions::SetMusicVolume(s32 vol, bool apply) void CGameOptions::SetHUDAlpha(u32 alpha) { - x64_hudAlpha = alpha; -} - -u32 CGameOptions::GetHUDAlpha() const -{ - return x64_hudAlpha; + x60_hudAlpha = alpha; } void CGameOptions::SetHelmetAlpha(u32 alpha) { - x60_helmetAlpha = alpha; -} - -u32 CGameOptions::GetHelmetAlpha() const -{ - return x60_helmetAlpha; + x64_helmetAlpha = alpha; } void CGameOptions::SetHUDLag(bool lag) @@ -327,11 +317,6 @@ void CGameOptions::SetHUDLag(bool lag) x68_24_hudLag = lag; } -bool CGameOptions::GetHUDLag() const -{ - return x68_24_hudLag; -} - void CGameOptions::SetSurroundMode(int mode, bool apply) { x44_soundMode = CAudioSys::ESurroundModes(zeus::clamp(0, mode, 2)); @@ -349,22 +334,12 @@ void CGameOptions::SetInvertYAxis(bool invert) x68_25_invertY = invert; } -bool CGameOptions::GetInvertYAxis() const -{ - return x68_25_invertY; -} - void CGameOptions::SetIsRumbleEnabled(bool rumble) { x68_26_rumble = rumble; } -bool CGameOptions::IsRumbleEnabled() const -{ - return x68_26_rumble; -} - -void CGameOptions::ToggleControls(bool swap) +void CGameOptions::SetSwapBeamControls(bool swap) { x68_27_swapBeamsControls = swap; if (!swap) @@ -378,11 +353,6 @@ void CGameOptions::SetIsHintSystemEnabled(bool hints) x68_28_hintSystem = hints; } -bool CGameOptions::IsHintSystemEnabled() const -{ - return x68_28_hintSystem; -} - void CGameOptions::SetControls(s32 controls) { if (controls == 0) @@ -406,12 +376,12 @@ void CGameOptions::EnsureSettings() SetSfxVolume(x58_sfxVol, true); SetMusicVolume(x5c_musicVol, true); SetSurroundMode(int(x44_soundMode), true); - SetHUDAlpha(x64_hudAlpha); + SetHUDAlpha(x60_hudAlpha); SetHUDLag(x68_24_hudLag); SetInvertYAxis(x68_25_invertY); SetIsRumbleEnabled(x68_26_rumble); SetIsHintSystemEnabled(x68_28_hintSystem); - ToggleControls(x68_27_swapBeamsControls); + SetSwapBeamControls(x68_27_swapBeamsControls); } void CGameOptions::TryRestoreDefaults(const CFinalInput& input, int category, @@ -462,7 +432,7 @@ void CGameOptions::TryRestoreDefaults(const CFinalInput& input, int category, case 3: gameOptions.SetInvertYAxis(false); gameOptions.SetIsRumbleEnabled(true); - gameOptions.ToggleControls(false); + gameOptions.SetSwapBeamControls(false); break; default: break; @@ -515,12 +485,52 @@ void CGameOptions::SetOption(EGameOption option, int value) options.SetIsRumbleEnabled(value); break; case EGameOption::SwapBeamControls: - options.ToggleControls(value); + options.SetSwapBeamControls(value); break; default: break; } } +int CGameOptions::GetOption(EGameOption option) +{ + const CGameOptions& options = g_GameState->GameOptions(); + + switch (option) + { + case EGameOption::VisorOpacity: + return options.GetHUDAlpha(); + case EGameOption::HelmetOpacity: + return options.GetHelmetAlpha(); + case EGameOption::HUDLag: + return options.GetHUDLag(); + case EGameOption::HintSystem: + return options.GetIsHintSystemEnabled(); + case EGameOption::ScreenBrightness: + return options.GetScreenBrightness(); + case EGameOption::ScreenOffsetX: + return options.GetScreenPositionX(); + case EGameOption::ScreenOffsetY: + return options.GetScreenPositionY(); + case EGameOption::ScreenStretch: + return options.GetScreenStretch(); + case EGameOption::SFXVolume: + return options.GetSfxVolume(); + case EGameOption::MusicVolume: + return options.GetMusicVolume(); + case EGameOption::SoundMode: + return int(options.GetSurroundMode()); + case EGameOption::ReverseYAxis: + return options.GetInvertYAxis(); + case EGameOption::Rumble: + return options.GetIsRumbleEnabled(); + case EGameOption::SwapBeamControls: + return options.GetSwapBeamControls(); + default: break; + } + + return 0; +} + CHintOptions::CHintOptions(CBitStreamReader& stream) { const auto& hints = g_MemoryCardSys->GetHints(); diff --git a/Runtime/CGameOptions.hpp b/Runtime/CGameOptions.hpp index 9c87f4f75..aa3a7de03 100644 --- a/Runtime/CGameOptions.hpp +++ b/Runtime/CGameOptions.hpp @@ -32,8 +32,8 @@ enum class EGameOption enum class EOptionType { Float, - Boolean, - Enum, + DoubleEnum, + TripleEnum, RestoreDefaults }; @@ -112,8 +112,8 @@ class CGameOptions s32 x54_screenStretch = 0; u32 x58_sfxVol = 0x7f; u32 x5c_musicVol = 0x7f; - u32 x60_helmetAlpha = 0xff; - u32 x64_hudAlpha = 0xff; + u32 x60_hudAlpha = 0xff; + u32 x64_helmetAlpha = 0xff; union { @@ -139,36 +139,43 @@ public: void InitSoundMode(); void EnsureSettings(); void PutTo(CBitStreamWriter& writer) const; - u32 GetMusicVolume() const { return x5c_musicVol; } float TuneScreenBrightness(); void SetScreenBrightness(s32, bool); + s32 GetScreenBrightness() const { return x48_screenBrightness; } void SetScreenPositionX(s32, bool); + s32 GetScreenPositionX() const { return x4c_screenXOffset; } void SetScreenPositionY(s32, bool); + s32 GetScreenPositionY() const { return x50_screenYOffset; } void SetScreenStretch(s32, bool); + s32 GetScreenStretch() const { return x54_screenStretch; } void SetSfxVolume(s32, bool); + s32 GetSfxVolume() const { return x58_sfxVol; } void SetMusicVolume(s32, bool); + s32 GetMusicVolume() const { return x5c_musicVol; } void SetHUDAlpha(u32); - u32 GetHUDAlpha() const; + u32 GetHUDAlpha() const { return x60_hudAlpha; } void SetHelmetAlpha(u32); - u32 GetHelmetAlpha() const; + u32 GetHelmetAlpha() const { return x64_helmetAlpha; } void SetHUDLag(bool); - bool GetHUDLag() const; + bool GetHUDLag() const { return x68_24_hudLag; } void SetSurroundMode(int mode, bool apply); CAudioSys::ESurroundModes GetSurroundMode() const; void SetInvertYAxis(bool); - bool GetInvertYAxis() const; + bool GetInvertYAxis() const { return x68_25_invertY; } void SetIsRumbleEnabled(bool); - bool IsRumbleEnabled() const; - void ToggleControls(bool); + bool GetIsRumbleEnabled() const { return x68_26_rumble; } + void SetSwapBeamControls(bool); + bool GetSwapBeamControls() const { return x68_27_swapBeamsControls; } void SetIsHintSystemEnabled(bool); - bool IsHintSystemEnabled() const; + bool GetIsHintSystemEnabled() const { return x68_28_hintSystem; } void SetControls(s32); void ResetControllerAssets(); static void TryRestoreDefaults(const CFinalInput& input, int category, int option, bool frontend); static void SetOption(EGameOption option, int value); + static int GetOption(EGameOption option); }; class CHintOptions diff --git a/Runtime/GuiSys/CGuiFrame.cpp b/Runtime/GuiSys/CGuiFrame.cpp index 23e3de37a..0e59528e6 100644 --- a/Runtime/GuiSys/CGuiFrame.cpp +++ b/Runtime/GuiSys/CGuiFrame.cpp @@ -140,7 +140,8 @@ void CGuiFrame::LoadWidgetsInGame(CInputStream& in) x2c_widgets.reserve(count); for (u32 i=0 ; iGetWidgetTypeID(); switch (type) diff --git a/Runtime/GuiSys/CGuiSliderGroup.cpp b/Runtime/GuiSys/CGuiSliderGroup.cpp index 20d9c849a..5cbfaf22a 100644 --- a/Runtime/GuiSys/CGuiSliderGroup.cpp +++ b/Runtime/GuiSys/CGuiSliderGroup.cpp @@ -1,36 +1,120 @@ #include "CGuiSliderGroup.hpp" +#include "Input/CFinalInput.hpp" namespace urde { -CGuiSliderGroup::CGuiSliderGroup(const CGuiWidgetParms& parms, float a, float b, float c, float d) -: CGuiCompoundWidget(parms), xf8_minVal(a), xfc_maxVal(b), x100_curVal(c), x104_increment(d) +CGuiSliderGroup::CGuiSliderGroup(const CGuiWidgetParms& parms, float min, float max, float def, float inc) +: CGuiCompoundWidget(parms), xb8_minVal(min), xbc_maxVal(max), + xc0_roundedCurVal(def), xc4_curVal(def), xc8_increment(inc) { } void CGuiSliderGroup::SetSelectionChangedCallback (std::function&& func) { - x114_changeCallback = std::move(func); + xd8_changeCallback = std::move(func); } void CGuiSliderGroup::SetCurVal(float cur) { - x100_curVal = zeus::clamp(xf8_minVal, cur, xfc_maxVal); - float factor = 0.f; - if (xfc_maxVal != xf8_minVal) - factor = (x100_curVal - xf8_minVal) / (xfc_maxVal - xf8_minVal); + xc0_roundedCurVal = zeus::clamp(xb8_minVal, cur, xbc_maxVal); + xc4_curVal = xc0_roundedCurVal; +} - const zeus::CVector3f& w0Idle = x10c_workers[0]->GetIdlePosition(); - const zeus::CVector3f& w1Idle = x10c_workers[1]->GetIdlePosition(); - x10c_workers[0]->SetLocalPosition(zeus::CVector3f::lerp(w0Idle, w1Idle, factor)); +void CGuiSliderGroup::StartDecreasing() +{ + xf0_state = EState::Decreasing; + xf4_24_inputPending = true; +} + +void CGuiSliderGroup::StartIncreasing() +{ + xf0_state = EState::Increasing; + xf4_24_inputPending = true; +} + +void CGuiSliderGroup::ProcessUserInput(const CFinalInput& input) +{ + if (input.DLALeft()) + { + StartDecreasing(); + return; + } + if (input.DLARight()) + { + StartIncreasing(); + return; + } + if (input.PDPLeft()) + { + StartDecreasing(); + return; + } + if (input.PDPRight()) + { + StartIncreasing(); + return; + } +} + +void CGuiSliderGroup::Update(float dt) +{ + float fullRange = xbc_maxVal - xb8_minVal; + float t1 = fullRange * dt; + + float incCurVal; + for (incCurVal = xb8_minVal ; incCurVal <= xc4_curVal ; incCurVal += xc8_increment) {} + + float upperIncVal = std::min(incCurVal, xbc_maxVal); + float lowerIncVal = upperIncVal - xc8_increment; + + float oldCurVal = xc4_curVal; + if (xf0_state == EState::Decreasing) + { + if (xf4_24_inputPending) + xc4_curVal = std::max(oldCurVal - t1, xb8_minVal); + else + xc4_curVal = std::max(oldCurVal - t1, lowerIncVal); + } + else if (xf0_state == EState::Increasing) + { + if (xf4_24_inputPending) + xc4_curVal = std::min(oldCurVal + t1, xbc_maxVal); + else if (xc4_curVal != lowerIncVal) + xc4_curVal = std::min(oldCurVal + t1, upperIncVal); + } + + if (xc4_curVal == oldCurVal) + xf0_state = EState::None; + + oldCurVal = xc0_roundedCurVal; + if (upperIncVal - xc4_curVal <= xc4_curVal - lowerIncVal) + xc0_roundedCurVal = upperIncVal; + else + xc0_roundedCurVal = lowerIncVal; + + if (oldCurVal != xc0_roundedCurVal && xd8_changeCallback) + xd8_changeCallback(this, oldCurVal); + + float fac; + if (xbc_maxVal == xb8_minVal) + fac = 0.f; + else + fac = (xc4_curVal - xb8_minVal) / (xbc_maxVal - xb8_minVal); + + const zeus::CVector3f& s0 = xcc_sliderRangeWidgets[0]->GetIdlePosition(); + const zeus::CVector3f& s1 = xcc_sliderRangeWidgets[1]->GetIdlePosition(); + + xcc_sliderRangeWidgets[0]->SetLocalPosition(s1 * fac + s0 * (1.f - fac)); + xf4_24_inputPending = false; } bool CGuiSliderGroup::AddWorkerWidget(CGuiWidget* worker) { if (worker->GetWorkerId() < 0 || worker->GetWorkerId() > 1) return true; - x10c_workers[worker->GetWorkerId()] = worker; + xcc_sliderRangeWidgets[worker->GetWorkerId()] = worker; return true; } @@ -38,7 +122,7 @@ CGuiWidget* CGuiSliderGroup::GetWorkerWidget(int id) { if (id < 0 || id > 1) return nullptr; - return x10c_workers[id]; + return xcc_sliderRangeWidgets[id]; } CGuiSliderGroup* CGuiSliderGroup::Create(CGuiFrame* frame, CInputStream& in, bool flag) diff --git a/Runtime/GuiSys/CGuiSliderGroup.hpp b/Runtime/GuiSys/CGuiSliderGroup.hpp index bf9d37f98..3542d15f8 100644 --- a/Runtime/GuiSys/CGuiSliderGroup.hpp +++ b/Runtime/GuiSys/CGuiSliderGroup.hpp @@ -9,22 +9,48 @@ namespace urde class CGuiSliderGroup : public CGuiCompoundWidget { - float xf8_minVal; - float xfc_maxVal; - float x100_curVal; - float x104_increment; - u32 x108_ = 2; - CGuiWidget* x10c_workers[2] = {}; - std::function x114_changeCallback; +public: + enum class EState + { + None, + Decreasing, + Increasing + }; + +private: + float xb8_minVal; + float xbc_maxVal; + float xc0_roundedCurVal; + float xc4_curVal; + float xc8_increment; + CGuiWidget* xcc_sliderRangeWidgets[2] = {}; + std::function xd8_changeCallback; + EState xf0_state = EState::None; + union { + struct + { + bool xf4_24_inputPending : 1; + }; + u8 _dummy = 0; + }; + + void StartDecreasing(); + void StartIncreasing(); + public: CGuiSliderGroup(const CGuiWidgetParms& parms, float a, float b, float c, float d); FourCC GetWidgetTypeID() const {return FOURCC('SLGP');} + EState GetState() const { return xf0_state; } void SetSelectionChangedCallback(std::function&& func); - void SetIncrement(float inc) {x104_increment = inc;} - void SetMinVal(float min) {xf8_minVal = min; SetCurVal(x100_curVal);} - void SetMaxVal(float max) {xfc_maxVal = max; SetCurVal(x100_curVal);} + void SetIncrement(float inc) { xc8_increment = inc; } + void SetMinVal(float min) { xb8_minVal = min; SetCurVal(xc0_roundedCurVal); } + void SetMaxVal(float max) { xbc_maxVal = max; SetCurVal(xc0_roundedCurVal); } void SetCurVal(float cur); + float GetGurVal() const { return xc0_roundedCurVal; } + + void ProcessUserInput(const CFinalInput& input); + void Update(float dt); bool AddWorkerWidget(CGuiWidget* worker); CGuiWidget* GetWorkerWidget(int id); diff --git a/Runtime/Input/CMakeLists.txt b/Runtime/Input/CMakeLists.txt index f99681bd9..260c262e8 100644 --- a/Runtime/Input/CMakeLists.txt +++ b/Runtime/Input/CMakeLists.txt @@ -6,6 +6,7 @@ set(INPUT_SOURCES CFinalInput.hpp CFinalInput.cpp CRumbleManager.hpp CRumbleManager.cpp CRumbleGenerator.hpp CRumbleGenerator.cpp - CRumbleVoice.hpp CRumbleVoice.cpp) + CRumbleVoice.hpp CRumbleVoice.cpp + RumbleFxTable.hpp RumbleFxTable.cpp) runtime_add_list(Input INPUT_SOURCES) diff --git a/Runtime/Input/CRumbleGenerator.cpp b/Runtime/Input/CRumbleGenerator.cpp index aefbbc2f4..45b2ef651 100644 --- a/Runtime/Input/CRumbleGenerator.cpp +++ b/Runtime/Input/CRumbleGenerator.cpp @@ -2,7 +2,24 @@ namespace urde { + CRumbleGenerator::CRumbleGenerator() { } + +void CRumbleGenerator::Update(float) +{ + +} + +void CRumbleGenerator::HardStopAll() +{ + +} + +void CRumbleGenerator::Rumble(const SAdsrData& adsr, float, ERumblePriority prio, EIOPort port) +{ + +} + } diff --git a/Runtime/Input/CRumbleGenerator.hpp b/Runtime/Input/CRumbleGenerator.hpp index 504390b11..b0cddbb2a 100644 --- a/Runtime/Input/CRumbleGenerator.hpp +++ b/Runtime/Input/CRumbleGenerator.hpp @@ -3,6 +3,14 @@ #include "CRumbleVoice.hpp" +enum class EIOPort +{ + Zero, + One, + Two, + Three +}; + namespace urde { class CRumbleGenerator @@ -11,6 +19,7 @@ public: CRumbleGenerator(); void Update(float); void HardStopAll(); + void Rumble(const SAdsrData& adsr, float, ERumblePriority prio, EIOPort port); }; } diff --git a/Runtime/Input/CRumbleVoice.hpp b/Runtime/Input/CRumbleVoice.hpp index 9cb274f67..c9c59ed5a 100644 --- a/Runtime/Input/CRumbleVoice.hpp +++ b/Runtime/Input/CRumbleVoice.hpp @@ -11,7 +11,8 @@ enum class ERumbleFxId }; enum class ERumblePriority { - None, + None = 0, + One = 1, Two = 2 }; diff --git a/Runtime/Input/RumbleFxTable.cpp b/Runtime/Input/RumbleFxTable.cpp new file mode 100644 index 000000000..aa72f0729 --- /dev/null +++ b/Runtime/Input/RumbleFxTable.cpp @@ -0,0 +1,34 @@ +#include "RumbleFxTable.hpp" + +namespace urde +{ + +const SAdsrData RumbleFxTable[] = +{ + {0.48f, 0.f, 0.3f, 0.125f, 0.1f, 0.5f, false, false}, + {0.66f, 0.f, 0.11f, 0.175f, 0.42f, 0.375f, false, false}, + {0.42f, 0.f, 0.1f, 0.225f, 0.225f, 0.f, false, false}, + {1.5f, 0.f, 0.1f, 0.225f, 1.025f, 0.4f, false, false}, + {0.786f, 0.f, 0.1f, 0.16f, 0.655f, 0.255f, false, false}, + {1.2f, 0.f, 0.4f, 0.1f, 1.f, 0.055f, false, false}, + {1.2f, 0.f, 0.05f, 0.3f, 0.4f, 1.1f, false, false}, + {1.02f, 0.f, 0.065f, 0.175f, 0.85f, 0.9f, false, false}, + {0.48f, 0.f, 0.065f, 0.175f, 0.4f, 0.0f, false, false}, + {0.72f, 0.f, 0.001f, 0.001f, 0.6f, 0.1f, false, false}, + {0.24f, 0.f, 0.001f, 0.525f, 0.2f, 0.2f, false, false}, + {2.4f, 0.f, 0.001f, 0.466f, 0.f, 0.f, false, false}, + {0.5532f, 0.f, 0.f, 1.345f, 0.f, 1.756f, false, false}, + {2.4f, 0.f, 0.01f, 0.125f, 0.25f, 0.5f, false, false}, + {0.84f, 0.f, 0.1f, 0.125f, 0.35f, 1.0f, false, false}, + {2.4f, 0.f, 0.1f, 0.225f, 0.38f, 0.3f, false, false}, + {0.48f, 0.f, 0.065f, 0.175f, 0.4f, 0.f, false, false}, + {0.3024f, 0.f, 0.1f, 1.345f, 0.f, 1.756f, false, false}, + {0.72f, 0.f, 0.01f, 0.01f, 0.6f, 0.1f, false, false}, + {1.1904f, 0.f, 0.f, 0.125f, 0.683f, 0.5f, true, false}, + {1.2f, 0.f, 0.01f, 0.621f, 0.f, 0.f, false, false}, + {0.5268f, 0.f, 0.114f, 1.008f, 0.f, 0.325f, false, false}, + {0.6828f, 0.f, 0.f, 0.821f, 0.f, 0.f, false, false}, + {1.8f, 0.f, 0.5f, 0.425f, 0.35f, 0.5f, false, false} +}; + +} diff --git a/Runtime/Input/RumbleFxTable.hpp b/Runtime/Input/RumbleFxTable.hpp new file mode 100644 index 000000000..332afff91 --- /dev/null +++ b/Runtime/Input/RumbleFxTable.hpp @@ -0,0 +1,13 @@ +#ifndef RUMBLEFXTABLE_HPP +#define RUMBLEFXTABLE_HPP + +#include "CRumbleVoice.hpp" + +namespace urde +{ + +extern const SAdsrData RumbleFxTable[]; + +} + +#endif // RUMBLEFXTABLE_HPP diff --git a/Runtime/MP1/CFrontEndUI.cpp b/Runtime/MP1/CFrontEndUI.cpp index 575956295..9acfac087 100644 --- a/Runtime/MP1/CFrontEndUI.cpp +++ b/Runtime/MP1/CFrontEndUI.cpp @@ -21,6 +21,7 @@ #include "GuiSys/CGuiWidgetDrawParms.hpp" #include "CNESEmulator.hpp" #include "CQuitScreen.hpp" +#include "Input/RumbleFxTable.hpp" namespace urde { @@ -1414,22 +1415,73 @@ CFrontEndUI::SOptionsFrontEndFrame::SOptionsFrontEndFrame() void CFrontEndUI::SOptionsFrontEndFrame::DoSliderChange(CGuiSliderGroup* caller, float value) { - + if (x28_tablegroup_rightmenu->GetIsActive()) + { + int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); + int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + CGameOptions::SetOption(option.option, caller->GetGurVal()); + } } void CFrontEndUI::SOptionsFrontEndFrame::DoMenuCancel(CGuiTableGroup* caller) { - + if (x28_tablegroup_rightmenu == caller) + { + DeactivateRightMenu(); + x24_tablegroup_leftmenu->SetIsActive(true); + x28_tablegroup_rightmenu->SetIsActive(false); + x28_tablegroup_rightmenu->SetUserSelection(0); + SetTableColors(x28_tablegroup_rightmenu); + CSfxManager::SfxStart(1094, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } } void CFrontEndUI::SOptionsFrontEndFrame::DoMenuSelectionChange(CGuiTableGroup* caller, int sel) { + SetTableColors(caller); + if (x24_tablegroup_leftmenu == caller) + { + SetRightUIText(); + CSfxManager::SfxStart(1093, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + else if (x28_tablegroup_rightmenu == caller) + { + HandleRightSelectionChange(); + CSfxManager::SfxStart(1093, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + else if (x2c_tablegroup_double == caller || x30_tablegroup_triple == caller) + { + if (x28_tablegroup_rightmenu->GetIsActive()) + { + int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); + int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + CGameOptions::SetOption(option.option, caller->GetUserSelection()); + CSfxManager::SfxStart(1095, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + if (option.option == EGameOption::Rumble && caller->GetUserSelection() > 0) + { + x40_rumbleGen.HardStopAll(); + x40_rumbleGen.Rumble(RumbleFxTable[11], 1.f, ERumblePriority::One, EIOPort::Zero); + } + } + } } void CFrontEndUI::SOptionsFrontEndFrame::DoLeftMenuAdvance(CGuiTableGroup* caller) { - + if (caller == x24_tablegroup_leftmenu) + { + HandleRightSelectionChange(); + x28_tablegroup_rightmenu->SetUserSelection(0); + x24_tablegroup_leftmenu->SetIsActive(false); + x28_tablegroup_rightmenu->SetIsActive(true); + CSfxManager::SfxStart(1096, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(1091, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } } void CFrontEndUI::SOptionsFrontEndFrame::DeactivateRightMenu() @@ -1442,6 +1494,52 @@ void CFrontEndUI::SOptionsFrontEndFrame::DeactivateRightMenu() x34_slidergroup_slider->SetVisibility(false, ETraversalMode::Children); } +void CFrontEndUI::SOptionsFrontEndFrame::HandleRightSelectionChange() +{ + DeactivateRightMenu(); + int leftSel = x24_tablegroup_leftmenu->GetUserSelection(); + int rightSel = x28_tablegroup_rightmenu->GetUserSelection(); + const auto& optionCategory = GameOptionsRegistry[leftSel]; + const SGameOption& option = optionCategory.second[rightSel]; + + switch (option.type) + { + case EOptionType::Float: + x34_slidergroup_slider->SetIsActive(true); + x34_slidergroup_slider->SetVisibility(true, ETraversalMode::Children); + x34_slidergroup_slider->SetMinVal(option.minVal); + x34_slidergroup_slider->SetMaxVal(option.maxVal); + x34_slidergroup_slider->SetIncrement(option.increment); + x34_slidergroup_slider->SetCurVal(CGameOptions::GetOption(option.option)); + x34_slidergroup_slider->SetLocalTransform( + zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * + x34_slidergroup_slider->GetTransform()); + break; + + case EOptionType::DoubleEnum: + x2c_tablegroup_double->SetUserSelection(CGameOptions::GetOption(option.option)); + x2c_tablegroup_double->SetIsVisible(true); + x2c_tablegroup_double->SetIsActive(true); + x2c_tablegroup_double->SetLocalTransform( + zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * + x2c_tablegroup_double->GetTransform()); + SetTableColors(x2c_tablegroup_double); + break; + + case EOptionType::TripleEnum: + x30_tablegroup_triple->SetUserSelection(CGameOptions::GetOption(option.option)); + x30_tablegroup_triple->SetIsVisible(true); + x30_tablegroup_triple->SetIsActive(true); + x30_tablegroup_triple->SetLocalTransform( + zeus::CTransform::Translate(0.f, 0.f, rightSel * x38_rowPitch) * + x30_tablegroup_triple->GetTransform()); + SetTableColors(x30_tablegroup_triple); + break; + + default: break; + } +} + void CFrontEndUI::SOptionsFrontEndFrame::SetRightUIText() { int userSel = x24_tablegroup_leftmenu->GetUserSelection(); @@ -1584,7 +1682,28 @@ bool CFrontEndUI::SOptionsFrontEndFrame::ProcessUserInput(const CFinalInput& inp void CFrontEndUI::SOptionsFrontEndFrame::Update(float dt, CSaveUI* sui) { + x40_rumbleGen.Update(dt); + x134_24_visible = sui && sui->GetUIType() == CSaveUI::EUIType::SaveReady; + if (!PumpLoad()) + return; + + x0_uiAlpha = std::min(1.f, x0_uiAlpha + dt); + x1c_loadedFrame->Update(dt); + + bool isSliding = x34_slidergroup_slider->GetState() != CGuiSliderGroup::EState::None; + if (x3c_sliderSfx.operator bool() != isSliding) + { + if (isSliding) + { + x3c_sliderSfx = CSfxManager::SfxStart(1458, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + else + { + CSfxManager::SfxStop(x3c_sliderSfx); + x3c_sliderSfx.reset(); + } + } } void CFrontEndUI::SOptionsFrontEndFrame::Draw() const diff --git a/Runtime/MP1/CFrontEndUI.hpp b/Runtime/MP1/CFrontEndUI.hpp index 6814fa77b..cc6acb74c 100644 --- a/Runtime/MP1/CFrontEndUI.hpp +++ b/Runtime/MP1/CFrontEndUI.hpp @@ -6,6 +6,7 @@ #include "RetroTypes.hpp" #include "CToken.hpp" #include "Audio/CStaticAudioPlayer.hpp" +#include "Audio/CSfxManager.hpp" #include "CGBASupport.hpp" #include "zeus/CVector3f.hpp" #include "Input/CRumbleGenerator.hpp" @@ -329,7 +330,7 @@ public: CGuiTableGroup* x30_tablegroup_triple = nullptr; CGuiSliderGroup* x34_slidergroup_slider = nullptr; float x38_rowPitch = 0.f; - u32 x3c_ = 0; + CSfxHandle x3c_sliderSfx; CRumbleGenerator x40_rumbleGen; union { @@ -348,6 +349,7 @@ public: void DoLeftMenuAdvance(CGuiTableGroup* caller); void DeactivateRightMenu(); + void HandleRightSelectionChange(); void SetRightUIText(); void SetTableColors(CGuiTableGroup* tbgp) const; diff --git a/amuse b/amuse index 2836e7381..ecd990e94 160000 --- a/amuse +++ b/amuse @@ -1 +1 @@ -Subproject commit 2836e738127b3a315977f1b9c51b30c6cfdf5dd2 +Subproject commit ecd990e94e4b0e6da071cb5f0ada4f65953dda44