diff --git a/Editor/ViewManager.cpp b/Editor/ViewManager.cpp index a0a212322..56ba35569 100644 --- a/Editor/ViewManager.cpp +++ b/Editor/ViewManager.cpp @@ -27,7 +27,6 @@ namespace urde void ViewManager::BuildTestPART(urde::IObjectStore& objStore) { m_modelTest = objStore.GetObj("MP1/Shared/CMDL_B2B41738.blend"); - CModel* ridley = m_modelTest.GetObj(); #if 1 SObjectTag samusCharSet = m_projManager.TagFromPath(_S("MP1/Shared/ANCS_77289A4A.*")); SObjectTag platModel = m_projManager.TagFromPath(_S("MP1/Shared/CMDL_6FA561D0.blend")); @@ -95,7 +94,7 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ) if (m_vm.m_modelTest.IsLoaded()) { -#if 0 +#if 1 CModelFlags flags; flags.m_extendedShaderIdx = 0; diff --git a/Runtime/Audio/CSfxManager.cpp b/Runtime/Audio/CSfxManager.cpp index e471b3826..c224ce63c 100644 --- a/Runtime/Audio/CSfxManager.cpp +++ b/Runtime/Audio/CSfxManager.cpp @@ -37,7 +37,7 @@ CSfxHandle CSfxManager::SfxStop(const CSfxHandle& handle) return {}; } -CSfxHandle CSfxManager::SfxStart(u16 id, s16 vol, s16 pan, bool active, s16 prio, bool inArea, s32 areaId) +CSfxHandle CSfxManager::SfxStart(u16 id, float vol, float pan, bool active, s16 prio, bool inArea, s32 areaId) { return {}; } diff --git a/Runtime/Audio/CSfxManager.hpp b/Runtime/Audio/CSfxManager.hpp index 119571d3b..5ac9c4fed 100644 --- a/Runtime/Audio/CSfxManager.hpp +++ b/Runtime/Audio/CSfxManager.hpp @@ -155,7 +155,7 @@ public: static void PitchBend(const CSfxHandle&, s32) {} static u16 TranslateSFXID(u16); static CSfxHandle SfxStop(const CSfxHandle& handle); - static CSfxHandle SfxStart(u16 id, s16 vol, s16 pan, bool active, s16 prio, bool inArea, s32 areaId); + static CSfxHandle SfxStart(u16 id, float vol, float pan, bool active, s16 prio, bool inArea, s32 areaId); }; } diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index f2ef75eb8..ed27cd5a1 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -80,6 +80,8 @@ class CGameState CPersistentOptions xa8_systemOptions; CGameOptions x17c_gameOptions; CHintOptions x1f8_hintOptions; + u32 x210_; + u32 x214_; union { diff --git a/Runtime/GuiSys/CMakeLists.txt b/Runtime/GuiSys/CMakeLists.txt index a7ca2e759..fa5084de5 100644 --- a/Runtime/GuiSys/CMakeLists.txt +++ b/Runtime/GuiSys/CMakeLists.txt @@ -97,6 +97,8 @@ set(GUISYS_SOURCES CFontImageDef.hpp ITweakGui.hpp CStringTable.cpp - CStringTable.hpp) + CStringTable.hpp + CSaveUI.cpp + CSaveUI.hpp) runtime_add_list(GuiSys GUISYS_SOURCES) diff --git a/Runtime/GuiSys/CSaveUI.cpp b/Runtime/GuiSys/CSaveUI.cpp new file mode 100644 index 000000000..d06f01a58 --- /dev/null +++ b/Runtime/GuiSys/CSaveUI.cpp @@ -0,0 +1,39 @@ +#include "CSaveUI.hpp" +#include "CSimplePool.hpp" +#include "GameGlobalObjects.hpp" +#include "CMemoryCardSys.hpp" + +namespace urde +{ + +CIOWin::EMessageReturn CSaveUI::Update(float dt) +{ + +} + +CSaveUI::CSaveUI(u32 instIdx, u32 a, u32 b) +: x0_instIdx(instIdx), x8_a(a), xc_b(b) +{ + x14_txtrSaveBanner = g_SimplePool->GetObj("TXTR_SaveBanner"); + x20_txtrSaveIcon0 = g_SimplePool->GetObj("TXTR_SaveIcon0"); + x2c_txtrSaveIcon1 = g_SimplePool->GetObj("TXTR_SaveIcon1"); + x38_strgMemoryCard = g_SimplePool->GetObj("STRG_MemoryCard"); + x44_frmeGenericMenu = g_SimplePool->GetObj("FRME_GenericMenu"); + + if (instIdx) + { + x84_navConfirmSfx = 1432; + x88_navMoveSfx = 1436; + x8c_navBackSfx = 1431; + } + x93_secondaryInst = instIdx; + + x70_saveWorlds.reserve(g_MemoryCardSys->GetMemoryWorlds().size()); + for (const std::pair& wld : g_MemoryCardSys->GetMemoryWorlds()) + { + x70_saveWorlds.push_back( + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), wld.second.GetSaveWorldAssetId()})); + } +} + +} diff --git a/Runtime/GuiSys/CSaveUI.hpp b/Runtime/GuiSys/CSaveUI.hpp new file mode 100644 index 000000000..6e5443edd --- /dev/null +++ b/Runtime/GuiSys/CSaveUI.hpp @@ -0,0 +1,44 @@ +#ifndef __URDE_CSAVEUI_HPP__ +#define __URDE_CSAVEUI_HPP__ + +#include "RetroTypes.hpp" +#include "CToken.hpp" +#include "CIOWin.hpp" + +namespace urde +{ +class CTexture; +class CStringTable; +class CGuiFrame; +class CSaveWorld; + +struct CSaveUI +{ + u32 x0_instIdx; + u32 x8_a; + u32 xc_b; + u32 x10_ = 0; + TLockedToken x14_txtrSaveBanner; + TLockedToken x20_txtrSaveIcon0; + TLockedToken x2c_txtrSaveIcon1; + TLockedToken x38_strgMemoryCard; + TLockedToken x44_frmeGenericMenu; + u32 x50_ = 0; + std::unique_ptr x6c_bannerInfo; + std::vector> x70_saveWorlds; + u32 x80_ = 0; + u32 x84_navConfirmSfx = 1460; + u32 x88_navMoveSfx = 1461; + u32 x8c_navBackSfx = 1459; + bool x90_ = false; + bool x91_ = false; + bool x92_ = false; + bool x93_secondaryInst; + + CIOWin::EMessageReturn Update(float dt); + CSaveUI(u32 inst, u32 a, u32 b); +}; + +} + +#endif // __URDE_CSAVEUI_HPP__ diff --git a/Runtime/MP1/CFrontEndUI.cpp b/Runtime/MP1/CFrontEndUI.cpp index c207e3eea..b15f736fb 100644 --- a/Runtime/MP1/CFrontEndUI.cpp +++ b/Runtime/MP1/CFrontEndUI.cpp @@ -6,17 +6,57 @@ #include "GameGlobalObjects.hpp" #include "MP1.hpp" #include "CSlideShow.hpp" +#include "Audio/CSfxManager.hpp" +#include "Graphics/CMoviePlayer.hpp" +#include "GuiSys/CSaveUI.hpp" namespace urde { namespace MP1 { +/* L/R Stereo transition cues */ +static const u16 FETransitionBackSFX[3][2] = +{ + {1090, 1097}, + {1098, 1099}, + {1100, 1101} +}; + +static const u16 FETransitionForwardSFX[3][2] = +{ + {1102, 1103}, + {1104, 1105}, + {1106, 1107} +}; + +struct FEMovie +{ + const char* path; + bool loop; +}; + +static const FEMovie FEMovies[] = +{ + {"Video/00_first_start.thp", false}, + {"Video/01_startloop.thp", true}, + {"Video/02_start_fileselect_A.thp", false}, + {"Video/03_fileselectloop.thp", true}, + {"Video/04_fileselect_playgame_A.thp", false}, + {"Video/06_fileselect_GBA.thp", false}, + {"Video/07_GBAloop.thp", true}, + {"Video/08_GBA_fileselect.thp", false}, + {"Video/08_GBA_fileselect.thp", false}, +}; + SObjectTag g_DefaultWorldTag = {FOURCC('MLVL'), 0x158efe17}; CFrontEndUI::CFrontEndUI(CArchitectureQueue& queue) : CIOWin("FrontEndUI") { + x18_rndA = std::min(rand() * 3 / RAND_MAX, 2); + x1c_rndB = std::min(rand() * 3 / RAND_MAX, 2); + x20_depsGroup = g_SimplePool->GetObj("FrontEnd_DGRP"); x38_pressStart = g_SimplePool->GetObj("TXTR_PressStart"); x44_frontendAudioGrp = g_SimplePool->GetObj("FrontEnd_AGSC"); @@ -79,13 +119,44 @@ std::string CFrontEndUI::GetNextAttractMovieFileName() } void CFrontEndUI::SetCurrentMovie(EMenuMovie movie) -{} +{ + if (xb8_curMovie == movie) + return; + StopAttractMovie(); + + if (xb8_curMovie != EMenuMovie::Stopped) + { + xcc_curMoviePtr->SetPlayMode(CMoviePlayer::EPlayMode::Stopped); + xcc_curMoviePtr->Rewind(); + } + + xb8_curMovie = movie; + + if (xb8_curMovie != EMenuMovie::Stopped) + { + xcc_curMoviePtr = x70_menuMovies[int(xb8_curMovie)].get(); + xcc_curMoviePtr->SetPlayMode(CMoviePlayer::EPlayMode::Playing); + } + else + xcc_curMoviePtr = nullptr; +} void CFrontEndUI::StopAttractMovie() -{} +{ + if (!xc4_attractMovie) + return; + xc4_attractMovie.reset(); + xcc_curMoviePtr = nullptr; +} -void CFrontEndUI::StartAttractMovie(int idx) -{} +void CFrontEndUI::StartAttractMovie() +{ + if (xc4_attractMovie) + return; + SetCurrentMovie(EMenuMovie::Stopped); + xc4_attractMovie = std::make_unique(GetNextAttractMovieFileName().c_str(), 0.f, false, true); + xcc_curMoviePtr = xc4_attractMovie.get(); +} void CFrontEndUI::UpdateMenuHighlights(CGuiTableGroup* grp) {} @@ -99,7 +170,60 @@ bool CFrontEndUI::CanBuild(const SObjectTag& tag) } void CFrontEndUI::StartStateTransition(EScreen screen) -{} +{ + switch (x50_curScreen) + { + case EScreen::One: + if (screen != EScreen::Three) + break; + SetCurrentMovie(EMenuMovie::StartFileSelectA); + SetMovieSeconds(xcc_curMoviePtr->GetTotalSeconds()); + break; + case EScreen::Three: + if (screen == EScreen::Five) + { + SetCurrentMovie(EMenuMovie::FileSelectPlayGameA); + SetMovieSeconds(xcc_curMoviePtr->GetTotalSeconds()); + } + else if (screen == EScreen::Four) + { + SetCurrentMovie(EMenuMovie::FileSelectGBA); + SetMovieSeconds(xcc_curMoviePtr->GetTotalSeconds()); + CSfxManager::SfxStart(1108, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(1109, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + break; + case EScreen::Four: + if (screen == EScreen::Five) + { + SetCurrentMovie(EMenuMovie::GBAFileSelectB); + SetMovieSeconds(xcc_curMoviePtr->GetTotalSeconds()); + } + else if (screen == EScreen::Three) + { + SetCurrentMovie(EMenuMovie::GBAFileSelectA); + SetMovieSeconds(xcc_curMoviePtr->GetTotalSeconds()); + CSfxManager::SfxStart(1110, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(1111, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + default: break; + } + + switch (screen) + { + case EScreen::Zero: + case EScreen::One: + SetCurrentMovie(EMenuMovie::FirstStart); + SetMovieSeconds(xcc_curMoviePtr->GetTotalSeconds()); + break; + case EScreen::Two: + StartAttractMovie(); + SetMovieSecondsDeferred(); + default: break; + } + + x54_nextScreen = screen; +} void CFrontEndUI::HandleDebugMenuReturnValue(CGameDebug::EReturnValue val, CArchitectureQueue& queue) {} @@ -110,15 +234,75 @@ void CFrontEndUI::Draw() const } void CFrontEndUI::UpdateMovies(float dt) -{} +{ + if (xcc_curMoviePtr && x5c_movieSecondsNeeded) + { + x5c_movieSecondsNeeded = false; + x58_movieSeconds = xcc_curMoviePtr->GetTotalSeconds(); + } + + for (auto& movie : x70_menuMovies) + if (movie) + movie->Update(dt); + + if (xc4_attractMovie) + xc4_attractMovie->Update(dt); +} + +bool CFrontEndUI::PumpMovieLoad() +{ + if (xd1_moviesLoaded) + return true; + for (int i=0 ; i<9 ; ++i) + { + if (!x70_menuMovies[i]) + { + x70_menuMovies[i] = std::make_unique(FEMovies[i].path, 0.05f, FEMovies[i].loop, false); + x70_menuMovies[i]->SetPlayMode(CMoviePlayer::EPlayMode::Stopped); + return false; + } + } + xd1_moviesLoaded = true; + return true; +} void CFrontEndUI::ProcessUserInput(const CFinalInput& input, CArchitectureQueue& queue) { } +void CFrontEndUI::TransitionToFive() +{ + if (x14_screen >= EScreen::Five) + return; + + const u16* sfx = FETransitionForwardSFX[x1c_rndB]; + CSfxManager::SfxStart(sfx[0], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + CSfxManager::SfxStart(sfx[1], 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + + x14_screen = EScreen::Five; + StartStateTransition(EScreen::Five); +} + CIOWin::EMessageReturn CFrontEndUI::Update(float dt, CArchitectureQueue& queue) { printf("UPDATE\n"); + + if (xdc_saveUI && x50_curScreen >= EScreen::Three) + { + switch (xdc_saveUI->Update(dt)) + { + case EMessageReturn::Exit: + TransitionToFive(); + break; + case EMessageReturn::RemoveIOWinAndExit: + case EMessageReturn::RemoveIOWin: + xe0_newFileSel.reset(); + xdc_saveUI.reset(); + default: break; + } + } + + return EMessageReturn::Exit; } @@ -139,7 +323,7 @@ CIOWin::EMessageReturn CFrontEndUI::OnMessage(const CArchitectureMessage& msg, C } case EArchMsgType::QuitGameplay: { - x14_phase = Phase::Six; + x14_screen = EScreen::Six; break; } default: break; diff --git a/Runtime/MP1/CFrontEndUI.hpp b/Runtime/MP1/CFrontEndUI.hpp index 85cb21c0c..072a5107c 100644 --- a/Runtime/MP1/CFrontEndUI.hpp +++ b/Runtime/MP1/CFrontEndUI.hpp @@ -15,6 +15,10 @@ struct SObjectTag; class CDependencyGroup; class CTexture; class CAudioGroupSet; +class CSaveWorld; +class CStringTable; +class CGuiFrame; +class CSaveUI; namespace MP1 { @@ -22,7 +26,7 @@ namespace MP1 class CFrontEndUI : public CIOWin { public: - enum class Phase + enum class EScreen { Zero, One, @@ -32,49 +36,71 @@ public: Five, Six }; - struct SScreenData + struct SNewFileSelect { }; + enum class EMenuMovie + { + Stopped = -1, + FirstStart = 0, + StartLoop, + StartFileSelectA, + FileSelectLoop, + FileSelectPlayGameA, + FileSelectGBA, + GBALoop, + GBAFileSelectA, + GBAFileSelectB + }; + private: - Phase x14_phase = Phase::Zero; + EScreen x14_screen = EScreen::Zero; u32 x18_rndA; u32 x1c_rndB; TLockedToken x20_depsGroup; TLockedToken x38_pressStart; TLockedToken x44_frontendAudioGrp; - u32 x50_ = 0; - u32 x54_ = 0; - float x58_ = 0.f; - bool x5c_ = false; + EScreen x50_curScreen = EScreen::Zero; + EScreen x54_nextScreen = EScreen::Zero; + float x58_movieSeconds = 0.f; + bool x5c_movieSecondsNeeded = false; float x60_ = 0.f; float x64_ = 0.f; float x68_ = 1.f; - std::unique_ptr x6c_[9]; - int xb8_nextAttract = -1; + u32 x6c_; + std::unique_ptr x70_menuMovies[9]; + EMenuMovie xb8_curMovie = EMenuMovie::Stopped; int xbc_nextAttract = 0; int xc0_attractCount = 0; - std::unique_ptr xc4_; - u32 xc8_ = 0; - u32 xcc_ = 0; - bool xd0_ = 0; - bool xd1_ = 0; - bool xd2_ = 0; + std::unique_ptr xc4_attractMovie; + CMoviePlayer* xcc_curMoviePtr = nullptr; + bool xd0_ = false; + bool xd1_moviesLoaded = false; + bool xd2_ = false; u32 xd4_ = 0; u32 xd8_ = 0; - std::unique_ptr xdc_scrData; - u32 xe0_ = 0; + std::unique_ptr xdc_saveUI; + std::unique_ptr xe0_newFileSel; u32 xe4_ = 0; u32 xec_ = 0; u32 xf0_ = 0; u32 xf4_ = 0; + + void SetMovieSecondsDeferred() + { + x58_movieSeconds = 1000000.f; + x5c_movieSecondsNeeded = true; + } + + void SetMovieSeconds(float seconds) + { + x58_movieSeconds = seconds; + x5c_movieSecondsNeeded = false; + } + + void TransitionToFive(); public: - enum class EMenuMovie - { - }; - enum class EScreen - { - }; CFrontEndUI(CArchitectureQueue& queue); void OnSliderSelectionChange(CGuiSliderGroup* grp, float); @@ -93,7 +119,7 @@ public: std::string GetNextAttractMovieFileName(); void SetCurrentMovie(EMenuMovie movie); void StopAttractMovie(); - void StartAttractMovie(int idx); + void StartAttractMovie(); void UpdateMenuHighlights(CGuiTableGroup* grp); void CompleteStateTransition(); bool CanBuild(const SObjectTag& tag); @@ -101,6 +127,7 @@ public: void HandleDebugMenuReturnValue(CGameDebug::EReturnValue val, CArchitectureQueue& queue); void Draw() const; void UpdateMovies(float dt); + bool PumpMovieLoad(); void ProcessUserInput(const CFinalInput& input, CArchitectureQueue& queue); EMessageReturn Update(float dt, CArchitectureQueue& queue); EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue);