From 99befafff26172467abd9b640601b80556368dfb Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 22 Jan 2025 17:25:53 -0700 Subject: [PATCH 1/8] Remove `LegoEventNotificationParam` unit (#1372) --- CMakeLists.txt | 3 +-- LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp | 1 + .../lego/legoomni/src/notify/legoeventnotificationparam.cpp | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) delete mode 100644 LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 40a701fe..76bdb406 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -401,10 +401,9 @@ function(add_lego_libraries NAME) # We need to get rid of / refactor the below units into existing/other ones LEGO1/main.cpp LEGO1/lego/legoomni/src/entity/legolocations.cpp - LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp LEGO1/lego/legoomni/src/common/legoactors.cpp - LEGO1/define.cpp LEGO1/lego/legoomni/src/common/legoplants.cpp + LEGO1/define.cpp ) list(APPEND list_targets ${NAME}) diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index f54fb548..70578247 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -11,6 +11,7 @@ DECOMP_SIZE_ASSERT(LegoControlManager, 0x60) DECOMP_SIZE_ASSERT(LegoControlManagerNotificationParam, 0x2c) +DECOMP_SIZE_ASSERT(LegoEventNotificationParam, 0x20) // FUNCTION: LEGO1 0x10028520 LegoControlManager::LegoControlManager() diff --git a/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp b/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp deleted file mode 100644 index dd7b0fb5..00000000 --- a/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "legoeventnotificationparam.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(LegoEventNotificationParam, 0x20) From 82f2e2e755ecd436b4b300e349ae1e80e3036bc4 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 25 Jan 2025 00:09:04 +0100 Subject: [PATCH 2/8] Match `HistoryBook::ReadyWorld()` (#1373) * Some progress on HistoryBook::ReadyWorld * Refactor getter * 48 % * 49 % * 53 % * Improve BETA10 stack, LEGO1 now at 91 * variable number match on BETA10, 91 % on LEGO1 * Cleanup * Match --------- Co-authored-by: jonschz Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/historybook.h | 7 +- LEGO1/lego/legoomni/include/legogamestate.h | 5 +- .../lego/legoomni/src/worlds/historybook.cpp | 120 +++++++++--------- .../legoomni/src/worlds/registrationbook.cpp | 2 +- LEGO1/library_msvc.h | 3 + LEGO1/omni/include/mxvideopresenter.h | 3 + reccmp-project.yml | 3 + 7 files changed, 81 insertions(+), 62 deletions(-) diff --git a/LEGO1/lego/legoomni/include/historybook.h b/LEGO1/lego/legoomni/include/historybook.h index 38f174a0..76912d5d 100644 --- a/LEGO1/lego/legoomni/include/historybook.h +++ b/LEGO1/lego/legoomni/include/historybook.h @@ -41,8 +41,11 @@ public: private: LegoGameState::Area m_destLocation; // 0xf8 MxStillPresenter* m_alphabet[26]; // 0xfc - MxStillPresenter* m_names[20][7]; // 0x164 - MxStillPresenter* m_scores[20]; // 0x394 + + // variable name verified by BETA10 0x1002bd27 + MxStillPresenter* m_name[20][7]; // 0x164 + + MxStillPresenter* m_scores[20]; // 0x394 }; #endif // HISTORYBOOK_H diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index dc1e6a97..291e58d0 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -163,7 +163,9 @@ public: // FUNCTION: BETA10 0x1002c2b0 MxS16 GetCount() { return m_count; } - ScoreItem* GetScore(MxS16 p_index) { return p_index >= m_count ? NULL : &m_scores[p_index]; } + // TODO: Not yet correct + // FUNCTION: BETA10 0x1002c540 + ScoreItem* GetScore(MxS32 p_index) { return p_index >= m_count ? NULL : &m_scores[p_index]; } MxS16 m_count; // 0x00 ScoreItem m_scores[20]; // 0x02 @@ -206,7 +208,6 @@ public: Act GetLoadedAct() { return m_loadedAct; } Area GetPreviousArea() { return m_previousArea; } Area GetUnknown0x42c() { return m_unk0x42c; } - History* GetHistory() { return &m_history; } void SetDirty(MxBool p_isDirty) { m_isDirty = p_isDirty; } void SetPreviousArea(Area p_previousArea) { m_previousArea = p_previousArea; } diff --git a/LEGO1/lego/legoomni/src/worlds/historybook.cpp b/LEGO1/lego/legoomni/src/worlds/historybook.cpp index cf325825..b3df73d5 100644 --- a/LEGO1/lego/legoomni/src/worlds/historybook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/historybook.cpp @@ -16,7 +16,7 @@ DECOMP_SIZE_ASSERT(HistoryBook, 0x3e4) HistoryBook::HistoryBook() { memset(m_alphabet, 0, sizeof(m_alphabet)); - memset(m_names, 0, sizeof(m_names)); + memset(m_name, 0, sizeof(m_name)); memset(m_scores, 0, sizeof(m_scores)); NotificationManager()->Register(this); } @@ -32,11 +32,11 @@ HistoryBook::~HistoryBook() m_scores[scoreIndex] = NULL; } - for (MxS16 letterIndex = 0; letterIndex < (MxS16) sizeOfArray(m_names[0]); letterIndex++) { - if (m_names[scoreIndex][letterIndex]) { - delete m_names[scoreIndex][letterIndex]->GetAction(); - delete m_names[scoreIndex][letterIndex]; - m_names[scoreIndex][letterIndex] = NULL; + for (MxS16 letterIndex = 0; letterIndex < (MxS16) sizeOfArray(m_name[0]); letterIndex++) { + if (m_name[scoreIndex][letterIndex]) { + delete m_name[scoreIndex][letterIndex]->GetAction(); + delete m_name[scoreIndex][letterIndex]; + m_name[scoreIndex][letterIndex] = NULL; } } } @@ -89,88 +89,94 @@ MxLong HistoryBook::Notify(MxParam& p_param) return 0; } -inline void SetColor(MxStillPresenter* p_presenter, MxU8 p_color, MxU8* p_colors, MxS32 p_x, MxS32 p_y) -{ - if (p_color) { - for (MxS32 lax = 0; lax < 4; lax++) { - if (p_presenter->GetAlphaMask() != NULL) { - memset(NULL, p_colors[p_color - 1], 4); - } - else { - memset(p_presenter->GetBitmap()->GetStart(p_x, p_y + lax), p_colors[p_color - 1], 4); - } - } - } -} - // FUNCTION: LEGO1 0x100826f0 +// FUNCTION: BETA10 0x1002b9b9 void HistoryBook::ReadyWorld() { + undefined2 dummy1 = 0x90, dummy2 = 0x79, dummy3 = 0xc8, dummy4 = 0x17, dummy5 = 0x1b; +#ifndef BETA10 LegoWorld::ReadyWorld(); - GameState()->GetHistory()->WriteScoreHistory(); +#endif + GameState()->m_history.WriteScoreHistory(); char bitmap[] = "A_Bitmap"; - for (MxS16 i = 0; i < 26; i++) { - m_alphabet[i] = (MxStillPresenter*) Find("MxStillPresenter", bitmap); - bitmap[0]++; + MxS16 i; + + for (i = 0; i < 26; i++) { + if (i < 26) { + m_alphabet[i] = (MxStillPresenter*) Find("MxStillPresenter", bitmap); + assert(m_alphabet[i]); + bitmap[0]++; + } } MxStillPresenter* scoreboxMaster = (MxStillPresenter*) Find("MxStillPresenter", "ScoreBox"); MxU8 scoreColors[3] = {0x76, 0x4c, 0x38}; // yellow - #FFB900, blue - #00548C, red - #CB1220, background - #CECECE, border - #74818B - MxS32 scoreY = 0x79; - for (MxS16 scoreIndex = 0; scoreIndex < GameState()->GetHistory()->m_count; scoreIndex++) { - LegoGameState::ScoreItem* score = GameState()->GetHistory()->GetScore(scoreIndex); + MxS32 scoreY; - MxStillPresenter** scorebox = &m_scores[scoreIndex]; - *scorebox = scoreboxMaster->Clone(); + for (i = 0, scoreY = 0x79; i < GameState()->m_history.GetCount(); i++, scoreY += 0x1b) { + LegoGameState::ScoreItem* score = GameState()->m_history.GetScore(i); + + m_scores[i] = scoreboxMaster->Clone(); MxS32 scoreX = 0x90; - if (scoreIndex >= 10) { - if (scoreIndex == 10) { + if (i >= 10) { + if (i == 10) { scoreY = 0x79; } scoreX = 0x158; } - MxS32 scoreboxX = 1; - MxS32 scoreboxRow = 5; - MxS32 scoreState = 0; - - for (; scoreboxRow > 0; scoreboxRow--) { + for (MxS32 scoreState = 0, scoreboxX = 1; scoreState < 5; scoreState++, scoreboxX += 5) { for (MxS32 scoreBoxColumn = 0, scoreboxY = 1; scoreBoxColumn < 5; scoreBoxColumn++, scoreboxY += 5) { - SetColor(*scorebox, score->m_scores[scoreState][scoreBoxColumn], scoreColors, scoreboxX, scoreboxY); - } + MxU8 color = score->m_scores[scoreState][scoreBoxColumn]; - scoreState++; - scoreboxX += 5; + if (color > 0) { + for (MxS32 lax = 0; lax < 4; lax++) { +#ifdef BETA10 + memset(m_scores[i]->GetBitmapStart(scoreboxX, scoreboxY + lax), scoreColors[color - 1], 4); +#else + if (m_scores[i]->GetAlphaMask() != NULL) { + memset(NULL, scoreColors[color - 1], 4); + } + else { + memset( + m_scores[i]->GetBitmap()->GetStart(scoreboxX, lax + scoreboxY), + scoreColors[color - 1], + 4 + ); + } +#endif + } + } + } } - (*scorebox)->Enable(TRUE); - (*scorebox)->SetTickleState(MxPresenter::e_repeating); - (*scorebox)->SetPosition(scoreX + 0xa1, scoreY); + m_scores[i]->Enable(TRUE); + m_scores[i]->SetTickleState(MxPresenter::e_repeating); + m_scores[i]->SetPosition(scoreX + 0xa1, scoreY); - for (MxS16 letterIndex = 0; letterIndex < (MxS16) sizeOfArray(m_names[0]);) { - MxS16 letter = score->m_name.m_letters[letterIndex]; +#ifdef BETA10 + for (MxS16 j = 0; score->m_name.m_letters[j] != -1; j++, scoreX += 0x17) +#else + for (MxS16 j = 0; j < (MxS16) sizeOfArray(m_name[0]) && score->m_name.m_letters[j] != -1; j++, scoreX += 0x17) +#endif + { + m_name[i][j] = m_alphabet[score->m_name.m_letters[j]]->Clone(); - if (letter == -1) { - break; - } - - MxS16 nameIndex = letterIndex++; - m_names[scoreIndex][nameIndex] = m_alphabet[letter]->Clone(); - m_names[scoreIndex][nameIndex]->Enable(TRUE); - m_names[scoreIndex][nameIndex]->SetTickleState(MxPresenter::e_repeating); - m_names[scoreIndex][nameIndex]->SetPosition(scoreX, scoreY); - scoreX += 0x17; + assert(m_name[i][j]); + m_name[i][j]->Enable(TRUE); + m_name[i][j]->SetTickleState(MxPresenter::e_repeating); + m_name[i][j]->SetPosition(scoreX, scoreY); } - - scoreY += 0x1b; } +#ifndef BETA10 PlayMusic(JukeboxScript::c_InformationCenter_Music); +#endif } // FUNCTION: LEGO1 0x10082a10 diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 5ade0b3a..0e081133 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -391,7 +391,7 @@ void RegistrationBook::FUN_100778c0() void RegistrationBook::ReadyWorld() { LegoGameState* gameState = GameState(); - gameState->GetHistory()->WriteScoreHistory(); + gameState->m_history.WriteScoreHistory(); MxS16 i; PlayMusic(JukeboxScript::c_InformationCenter_Music); diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 82f3ae87..2ae816e7 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -702,6 +702,9 @@ // LIBRARY: BETA10 0x100f9420 // memcpy +// LIBRARY: BETA10 0x100faa00 +// memcmp + // LIBRARY: BETA10 0x100fb080 // _stricmp diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index 907ddc0e..a1794aec 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -104,6 +104,9 @@ public: MxBitmap* GetBitmap() { return m_frameBitmap; } AlphaMask* GetAlphaMask() { return m_alpha; } + // FUNCTION: BETA10 0x1002c2e0 + MxU8* GetBitmapStart(MxS32 p_left, MxS32 p_top) { return m_frameBitmap->GetStart(p_left, p_top); } + void SetBit0(BOOL p_e) { m_flags.m_bit0 = p_e; } void SetBit1(BOOL p_e) { m_flags.m_bit1 = p_e; } void SetBit2(BOOL p_e) { m_flags.m_bit2 = p_e; } diff --git a/reccmp-project.yml b/reccmp-project.yml index c614cded..009c737f 100644 --- a/reccmp-project.yml +++ b/reccmp-project.yml @@ -24,6 +24,7 @@ targets: # these classes have been changed by hand to account for changes between LEGO1 and BETA10 - Act2Actor - Act2Brick + - HistoryBook - LegoAct2 - LegoCarBuild - LegoCarBuildAnimPresenter @@ -34,3 +35,5 @@ targets: - 0x100f8ad0 - 0x100fa200 - 0x100f9780 + # memset etc. + - 0x100f9570 From 382f058c2383c22e333189f5fdd8e1917c7d6bac Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 24 Jan 2025 16:32:08 -0700 Subject: [PATCH 3/8] Match `RegistrationBook::ReadyWorld` (#1375) --- .../legoomni/src/worlds/registrationbook.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 0e081133..7a4a43c2 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -392,17 +392,20 @@ void RegistrationBook::ReadyWorld() { LegoGameState* gameState = GameState(); gameState->m_history.WriteScoreHistory(); - MxS16 i; PlayMusic(JukeboxScript::c_InformationCenter_Music); char letterBuffer[] = "A_Bitmap"; - for (i = 0; i < 26; i++) { - m_alphabet[i] = (MxStillPresenter*) Find("MxStillPresenter", letterBuffer); + MxS16 i; - // We need to loop through the entire alphabet, - // so increment the first char of the bitmap name - letterBuffer[0]++; + for (i = 0; i < 26; i++) { + if (i < 26) { + m_alphabet[i] = (MxStillPresenter*) Find("MxStillPresenter", letterBuffer); + + // We need to loop through the entire alphabet, + // so increment the first char of the bitmap name + letterBuffer[0]++; + } } // Now we have to do the checkmarks @@ -437,7 +440,7 @@ void RegistrationBook::ReadyWorld() } } - if (m_infocenterState->HasRegistered()) { + if (m_infocenterState->m_letters[0] != NULL) { PlayAction(RegbookScript::c_iic008in_PlayWav); LegoROI* infoman = FindROI(g_infoman); From f542b3aeba18646d56d44465e44b04c84ce9aafc Mon Sep 17 00:00:00 2001 From: MS Date: Sat, 25 Jan 2025 12:17:23 -0500 Subject: [PATCH 4/8] Fix some beta annotations (#1377) --- LEGO1/omni/include/mxatom.h | 10 ++++++---- LEGO1/omni/include/mxpresenterlist.h | 4 ++-- LEGO1/viewmanager/viewlodlist.h | 4 +++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/LEGO1/omni/include/mxatom.h b/LEGO1/omni/include/mxatom.h index d7650bb7..44d467e3 100644 --- a/LEGO1/omni/include/mxatom.h +++ b/LEGO1/omni/include/mxatom.h @@ -147,9 +147,10 @@ private: // _Tree >::_Kfn,MxAtomCompare,allocator >::erase // clang-format on +// clang-format off // TEMPLATE: BETA10 0x10131460 -// _Tree >::_Kfn,MxAtomCompare,allocator -// >::size +// _Tree >::_Kfn,MxAtomCompare,allocator >::size +// clang-format on // clang-format off // TEMPLATE: LEGO1 0x100afc40 @@ -175,9 +176,10 @@ private: // _Tree >::_Kfn,MxAtomCompare,allocator >::_Nil // clang-format on +// clang-format off // TEMPLATE: BETA10 0x10132170 -// _Tree >::_Kfn,MxAtomCompare,allocator -// >::begin +// _Tree >::_Kfn,MxAtomCompare,allocator >::begin +// clang-format on // TEMPLATE: BETA10 0x101321d0 // set >::size diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index 34714def..f5f658ac 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -104,9 +104,9 @@ public: // MxPtrListCursor::MxPtrListCursor // TEMPLATE: BETA10 0x1007d270 -// MxListCursor::MxListCursor +// MxListCursor::MxListCursor // TEMPLATE: BETA10 0x100d9420 -// MxListCursor::Prev +// MxListCursor::Prev #endif // MXPRESENTERLIST_H diff --git a/LEGO1/viewmanager/viewlodlist.h b/LEGO1/viewmanager/viewlodlist.h index 187d6feb..60847caf 100644 --- a/LEGO1/viewmanager/viewlodlist.h +++ b/LEGO1/viewmanager/viewlodlist.h @@ -172,10 +172,12 @@ private: // TEMPLATE: BETA10 0x1017ab10 // map >::erase +// No symbol generated for this? // Two iterators // TEMPLATE: BETA10 0x1017a040 -// map >::erase +// ?erase@?$map@PBDPAVViewLODList@@UROINameComparator@@V?$allocator@PAVViewLODList@@@@@@QAE?AViterator@?$_Tree@PBDU?$pair@QBDPAVViewLODList@@@@U_Kfn@?$map@PBDPAVViewLODList@@UROINameComparator@@V?$allocator@PAVViewLODList@@@@@@UROINameComparator@@V?$allocato +// aka map >::erase // One iterator // TEMPLATE: BETA10 0x10178f80 From fe36c2543ee5e52e164b24a0d87ba70d646cef04 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 26 Jan 2025 08:02:01 +0100 Subject: [PATCH 5/8] BETA10 match `RegistrationBook::ReadyWorld()` (#1376) --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/infocenter.h | 3 +++ LEGO1/lego/legoomni/include/legomain.h | 2 ++ .../lego/legoomni/include/registrationbook.h | 2 +- LEGO1/lego/legoomni/src/common/misc.cpp | 3 +++ .../lego/legoomni/src/worlds/historybook.cpp | 2 ++ .../legoomni/src/worlds/registrationbook.cpp | 25 ++++++++++++++++++- 6 files changed, 35 insertions(+), 2 deletions(-) diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index 7749cc84..f4c86a67 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -40,7 +40,10 @@ public: MxS16 GetMaxNameLength() { return sizeOfArray(m_letters); } MxStillPresenter* GetNameLetter(MxS32 p_index) { return m_letters[p_index]; } void SetNameLetter(MxS32 p_index, MxStillPresenter* p_letter) { m_letters[p_index] = p_letter; } + + // FUNCTION: BETA10 0x10031bd0 MxBool HasRegistered() { return m_letters[0] != NULL; } + Playlist& GetExitDialogueAct1() { return m_exitDialogueAct1; } Playlist& GetExitDialogueAct23() { return m_exitDialogueAct23; } Playlist& GetReturnDialogue(LegoGameState::Act p_act) { return m_returnDialogue[p_act]; } diff --git a/LEGO1/lego/legoomni/include/legomain.h b/LEGO1/lego/legoomni/include/legomain.h index 1ab6c2ee..263d59d5 100644 --- a/LEGO1/lego/legoomni/include/legomain.h +++ b/LEGO1/lego/legoomni/include/legomain.h @@ -168,7 +168,9 @@ public: // FUNCTION: BETA10 0x100e52b0 LegoGameState* GetGameState() { return m_gameState; } + // FUNCTION: BETA10 0x100e5280 MxBackgroundAudioManager* GetBackgroundAudioManager() { return m_bkgAudioManager; } + MxTransitionManager* GetTransitionManager() { return m_transitionManager; } MxDSAction& GetCurrentAction() { return m_action; } LegoCharacterManager* GetCharacterManager() { return m_characterManager; } diff --git a/LEGO1/lego/legoomni/include/registrationbook.h b/LEGO1/lego/legoomni/include/registrationbook.h index 3e2cf367..146bcf30 100644 --- a/LEGO1/lego/legoomni/include/registrationbook.h +++ b/LEGO1/lego/legoomni/include/registrationbook.h @@ -40,7 +40,7 @@ public: MxBool Escape() override; // vtable+0x64 void Enable(MxBool p_enable) override; // vtable+0x68 - inline void PlayAction(MxU32 p_objectId); + inline static void PlayAction(MxU32 p_objectId); // SYNTHETIC: LEGO1 0x10076f30 // RegistrationBook::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 28f6c039..08072b7c 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -212,8 +212,11 @@ MxTransitionManager* TransitionManager() } // FUNCTION: LEGO1 0x10015910 +// FUNCTION: BETA10 0x100e4f4c void PlayMusic(JukeboxScript::Script p_objectId) { + assert(LegoOmni::GetInstance()); + MxDSAction action; action.SetAtomId(*g_jukeboxScript); action.SetObjectId(p_objectId); diff --git a/LEGO1/lego/legoomni/src/worlds/historybook.cpp b/LEGO1/lego/legoomni/src/worlds/historybook.cpp index b3df73d5..f31f1258 100644 --- a/LEGO1/lego/legoomni/src/worlds/historybook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/historybook.cpp @@ -103,6 +103,8 @@ void HistoryBook::ReadyWorld() MxS16 i; for (i = 0; i < 26; i++) { + // TODO: This might be an inline function. + // See also `RegistrationBook::ReadyWorld()`. if (i < 26) { m_alphabet[i] = (MxStillPresenter*) Find("MxStillPresenter", bitmap); assert(m_alphabet[i]); diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 7a4a43c2..c1aed0a9 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -32,6 +32,7 @@ DECOMP_SIZE_ASSERT(RegistrationBook, 0x2d0) // GLOBAL: LEGO1 0x100d9924 +// GLOBAL: BETA10 0x101bfb3c const char* g_infoman = "infoman"; // GLOBAL: LEGO1 0x100f7964 @@ -268,6 +269,7 @@ MxLong RegistrationBook::HandleControl(LegoControlManagerNotificationParam& p_pa } // FUNCTION: LEGO1 0x100775c0 +// STUB: BETA10 0x100f32b2 void RegistrationBook::FUN_100775c0(MxS16 p_playerIndex) { if (m_infocenterState->HasRegistered()) { @@ -388,10 +390,17 @@ void RegistrationBook::FUN_100778c0() } // FUNCTION: LEGO1 0x10077cc0 +// FUNCTION: BETA10 0x100f3671 void RegistrationBook::ReadyWorld() { + // This function is very fragile and appears to oscillate between two versions on small changes. + // This even happens for commenting out `assert()` calls, which shouldn't affect release builds at all. + // See https://github.com/isledecomp/isle/pull/1375 for a version that had 100 %. + +#ifndef BETA10 LegoGameState* gameState = GameState(); gameState->m_history.WriteScoreHistory(); +#endif PlayMusic(JukeboxScript::c_InformationCenter_Music); @@ -399,8 +408,11 @@ void RegistrationBook::ReadyWorld() MxS16 i; for (i = 0; i < 26; i++) { + // TODO: This might be an inline function. + // See also `HistoryBook::ReadyWorld()`. if (i < 26) { m_alphabet[i] = (MxStillPresenter*) Find("MxStillPresenter", letterBuffer); + assert(m_alphabet[i]); // We need to loop through the entire alphabet, // so increment the first char of the bitmap name @@ -412,6 +424,7 @@ void RegistrationBook::ReadyWorld() char checkmarkBuffer[] = "Check0_Ctl"; for (i = 0; i < 10; i++) { m_checkmark[i] = (MxControlPresenter*) Find("MxControlPresenter", checkmarkBuffer); + assert(m_checkmark[i]); // Just like in the prior letter loop, // we need to increment the fifth char @@ -431,6 +444,7 @@ void RegistrationBook::ReadyWorld() // Start building the player names using a two-dimensional array m_name[i][j] = m_alphabet[players[i - 1].m_letters[j]]->Clone(); + assert(m_name[i][j]); // Enable the presenter to actually show the letter in the grid m_name[i][j]->Enable(TRUE); @@ -440,7 +454,15 @@ void RegistrationBook::ReadyWorld() } } - if (m_infocenterState->m_letters[0] != NULL) { +#ifdef BETA10 + InfocenterState* infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); + assert(infocenterState); + + if (infocenterState->HasRegistered()) +#else + if (m_infocenterState->HasRegistered()) +#endif + { PlayAction(RegbookScript::c_iic008in_PlayWav); LegoROI* infoman = FindROI(g_infoman); @@ -453,6 +475,7 @@ void RegistrationBook::ReadyWorld() } } +// FUNCTION: BETA10 0x100f3424 inline void RegistrationBook::PlayAction(MxU32 p_objectId) { MxDSAction action; From 29bf588870a76355c9a0ca00dc9d1abae9def953 Mon Sep 17 00:00:00 2001 From: MS Date: Sun, 26 Jan 2025 21:00:51 -0500 Subject: [PATCH 6/8] LegoRaceCar and LegoJetski tweaks (#1378) --- LEGO1/lego/legoomni/include/legoanimactor.h | 4 + LEGO1/lego/legoomni/include/legoracers.h | 5 +- LEGO1/lego/legoomni/src/race/carrace.cpp | 2 +- LEGO1/lego/legoomni/src/race/jetskirace.cpp | 2 +- .../lego/legoomni/src/race/legoraceactor.cpp | 3 +- LEGO1/lego/legoomni/src/race/legoracers.cpp | 125 +++++++++--------- 6 files changed, 72 insertions(+), 69 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h index 3f115e97..112f215c 100644 --- a/LEGO1/lego/legoomni/include/legoanimactor.h +++ b/LEGO1/lego/legoomni/include/legoanimactor.h @@ -96,8 +96,12 @@ protected: // Vector::~Vector // TEMPLATE: LEGO1 0x1001c7c0 +// TEMPLATE: BETA10 0x1000fb40 // vector >::size +// TEMPLATE: BETA10 0x1000fb90 +// vector >::operator[] + // TEMPLATE: LEGO1 0x1001c7e0 // vector >::_Destroy diff --git a/LEGO1/lego/legoomni/include/legoracers.h b/LEGO1/lego/legoomni/include/legoracers.h index 54a29eca..7709ebb7 100644 --- a/LEGO1/lego/legoomni/include/legoracers.h +++ b/LEGO1/lego/legoomni/include/legoracers.h @@ -82,6 +82,8 @@ public: virtual void FUN_100136f0(float p_worldSpeed); + static void InitSoundIndices(); + // SYNTHETIC: LEGO1 0x10013e30 // LegoJetski::`scalar deleting destructor' }; @@ -146,8 +148,7 @@ public: virtual MxU32 HandleSkeletonKicks(float p_param1); static void FUN_10012de0(); - static void FUN_10012e00(); - static void FUN_10013670(); + static void InitSoundIndices(); // SYNTHETIC: LEGO1 0x10014240 // LegoRaceCar::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp index bd2a0a50..e775a3be 100644 --- a/LEGO1/lego/legoomni/src/race/carrace.cpp +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -100,7 +100,7 @@ MxResult CarRace::Create(MxDSAction& p_dsAction) m_unk0x148 = -1; m_unk0x14c = -1; - LegoRaceCar::FUN_10012e00(); + LegoRaceCar::InitSoundIndices(); MxS32 streamId = DuneBuggy::GetColorOffset(g_strCRCEDGEY0) + (DuneBuggy::GetColorOffset(g_strCRCFRNTY6) * 5 + 15) * 2; diff --git a/LEGO1/lego/legoomni/src/race/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp index d8f9323d..373827ab 100644 --- a/LEGO1/lego/legoomni/src/race/jetskirace.cpp +++ b/LEGO1/lego/legoomni/src/race/jetskirace.cpp @@ -63,7 +63,7 @@ MxResult JetskiRace::Create(MxDSAction& p_dsAction) m_unk0x130.SetTop(317); m_unk0x130.SetRight(543); m_unk0x130.SetBottom(333); - LegoRaceCar::FUN_10013670(); + LegoJetski::InitSoundIndices(); InvokeAction( Extra::e_start, m_atomId, diff --git a/LEGO1/lego/legoomni/src/race/legoraceactor.cpp b/LEGO1/lego/legoomni/src/race/legoraceactor.cpp index 92c99d4f..840ce5ca 100644 --- a/LEGO1/lego/legoomni/src/race/legoraceactor.cpp +++ b/LEGO1/lego/legoomni/src/race/legoraceactor.cpp @@ -13,6 +13,7 @@ DECOMP_SIZE_ASSERT(LegoRaceActor, 0x180) // Initialized at LEGO1 0x100145a0 // GLOBAL: LEGO1 0x10102b08 +// GLOBAL: BETA10 0x102114a8 Mx3DPointFloat LegoRaceActor::g_unk0x10102b08 = Mx3DPointFloat(0.0, 2.0, 0.0); // FUNCTION: LEGO1 0x100145d0 @@ -101,9 +102,9 @@ MxResult LegoRaceActor::HitActor(LegoPathActor* p_actor, MxBool p_bool) } if (p_bool) { + MxMatrix matr; LegoROI* roi = p_actor->GetROI(); // name verified by BETA10 0x100c9fcf assert(roi); - MxMatrix matr; matr = roi->GetLocal2World(); Vector3(matr[3]) += g_unk0x10102b08; diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index 14afc7f9..989c17e3 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -26,7 +26,7 @@ DECOMP_SIZE_ASSERT(LegoJetski, 0x1dc) // name verified by BETA10 0x100cbee6 // GLOBAL: LEGO1 0x100f0a20 -// GLOBAL: BETA10 0x101f5e34 +// GLOBAL: BETA10 0x101f5e30 EdgeReference g_skBMap[] = { {// STRING: LEGO1 0x100f0a10 "EDG03_772", @@ -80,7 +80,7 @@ const char* g_strJetSpeed = "jetSPEED"; // GLOBAL: LEGO1 0x100f0b18 // GLOBAL: BETA10 0x101f5f28 -const char* g_srtsl18to29[] = { +const char* g_playerHitStudsSounds[] = { "srt018sl", "srt019sl", "srt020sl", @@ -97,19 +97,19 @@ const char* g_srtsl18to29[] = { // GLOBAL: LEGO1 0x100f0b48 // GLOBAL: BETA10 0x101f5f58 -const char* g_srtsl6to10[] = {"srt006sl", "srt007sl", "srt008sl", "srt009sl", "srt010sl"}; +const char* g_studsHitPlayerSounds[] = {"srt006sl", "srt007sl", "srt008sl", "srt009sl", "srt010sl"}; // GLOBAL: LEGO1 0x100f0b5c // GLOBAL: BETA10 0x101f5f6c -const char* g_emptySoundKeyList[] = {NULL}; +const char* g_playerHitRhodaSounds[] = {NULL}; // GLOBAL: LEGO1 0x100f0b60 // GLOBAL: BETA10 0x101f5f70 -const char* g_srtrh[] = {"srt004rh", "srt005rh", "srt006rh"}; +const char* g_rhodaHitPlayerSounds[] = {"srt004rh", "srt005rh", "srt006rh"}; // GLOBAL: LEGO1 0x100f0b6c // STRING: LEGO1 0x100f08c4 -const char* g_srt001ra = "srt001ra"; +const char* g_youCantStopSound = "srt001ra"; // GLOBAL: LEGO1 0x100f0b70 // STRING: LEGO1 0x100f08bc @@ -117,31 +117,31 @@ const char* g_soundSkel3 = "skel3"; // GLOBAL: LEGO1 0x100f0b74 // GLOBAL: BETA10 0x101f5f80 -MxU32 g_srtsl18to29Index = 0; +MxU32 g_playerHitStudsSoundsIndex = 0; // GLOBAL: LEGO1 0x100f0b78 // GLOBAL: BETA10 0x101f5f84 -MxU32 g_srtsl6to10Index = 0; +MxU32 g_studsHitPlayerSoundsIndex = 0; // GLOBAL: LEGO1 0x100f0b7c // GLOBAL: BETA10 0x101f5f88 -MxU32 g_emptySoundKeyListIndex = 0; +MxU32 g_playerHitRhodaSoundsIndex = 0; // GLOBAL: LEGO1 0x100f0b80 // GLOBAL: BETA10 0x101f5f8c -MxU32 g_srtrhIndex = 0; +MxU32 g_rhodaHitPlayerSoundsIndex = 0; // GLOBAL: LEGO1 0x100f0b84 // GLOBAL: BETA10 0x101f5f90 -MxLong g_timeLastSoundPlayed = 0; +MxLong g_timeLastRaceCarSoundPlayed = 0; // GLOBAL: LEGO1 0x100f0b88 // GLOBAL: BETA10 0x101f5f94 -MxS32 g_unk0x100f0b88 = 0; +MxS32 g_timePlayerLastMoved = 0; // GLOBAL: LEGO1 0x100f0b8c // GLOBAL: BETA10 0x101f5f98 -MxBool g_unk0x100f0b8c = TRUE; +MxBool g_playedYouCantStopSound = TRUE; // GLOBAL: LEGO1 0x100f0b90 const char* g_hitSnapSounds[] = { @@ -165,9 +165,10 @@ undefined4 g_hitSnapSoundsIndex = 0; undefined4 g_hitValerieSoundsIndex = 0; // GLOBAL: LEGO1 0x100f0bb4 -MxLong g_unk0x100f0bb4 = 0; +MxLong g_timeLastJetskiSoundPlayed = 0; // FUNCTION: LEGO1 0x10012950 +// FUNCTION: BETA10 0x100cad10 LegoRaceCar::LegoRaceCar() { m_userState = 0; @@ -181,12 +182,14 @@ LegoRaceCar::LegoRaceCar() } // FUNCTION: LEGO1 0x10012c80 +// FUNCTION: BETA10 0x100caf67 LegoRaceCar::~LegoRaceCar() { NotificationManager()->Unregister(this); } // FUNCTION: LEGO1 0x10012d90 +// FUNCTION: BETA10 0x100cb0bd MxLong LegoRaceCar::Notify(MxParam& p_param) { return LegoRaceMap::Notify(p_param); @@ -200,21 +203,22 @@ Mx3DPointFloat g_unk0x10102af0 = Mx3DPointFloat(0.0f, 2.0f, 0.0f); // FUNCTION: LEGO1 0x10012de0 void LegoRaceCar::FUN_10012de0() { - g_unk0x100f0b8c = TRUE; - g_timeLastSoundPlayed = 0; - g_unk0x100f0b88 = 0; + // Init to TRUE so we don't play "you can't stop in the middle of the race!" before the player ever moves + g_playedYouCantStopSound = TRUE; + g_timeLastRaceCarSoundPlayed = 0; + g_timePlayerLastMoved = 0; } // FUNCTION: LEGO1 0x10012e00 // FUNCTION: BETA10 0x100cb129 -void LegoRaceCar::FUN_10012e00() +void LegoRaceCar::InitSoundIndices() { // Note the (likely unintentional) order of operations: `%` is executed before `/`, // so the division is performed at runtime. - g_srtsl18to29Index = rand() % sizeof(g_srtsl18to29) / sizeof(g_srtsl18to29[0]); - g_srtsl6to10Index = rand() % sizeof(g_srtsl6to10) / sizeof(g_srtsl6to10[0]); - g_emptySoundKeyListIndex = rand() % sizeof(g_emptySoundKeyList) / sizeof(g_emptySoundKeyList[0]); - g_srtrhIndex = rand() % sizeof(g_srtrh) / sizeof(g_srtrh[0]); + g_playerHitStudsSoundsIndex = rand() % sizeof(g_playerHitStudsSounds) / sizeof(g_playerHitStudsSounds[0]); + g_studsHitPlayerSoundsIndex = rand() % sizeof(g_studsHitPlayerSounds) / sizeof(g_studsHitPlayerSounds[0]); + g_playerHitRhodaSoundsIndex = rand() % sizeof(g_playerHitRhodaSounds) / sizeof(g_playerHitRhodaSounds[0]); + g_rhodaHitPlayerSoundsIndex = rand() % sizeof(g_rhodaHitPlayerSounds) / sizeof(g_rhodaHitPlayerSounds[0]); } // FUNCTION: LEGO1 0x10012e60 @@ -264,27 +268,22 @@ void LegoRaceCar::ParseAction(char* p_extra) MxS32 i; for (i = 0; i < m_animMaps.size(); i++) { - // It appears that the implementation in BETA10 does not use this variable - LegoAnimActorStruct* animMap = m_animMaps[i]; - - if (animMap->m_unk0x00 == -1.0f) { - m_skelKick1Anim = animMap; + if (m_animMaps[i]->GetUnknown0x00() == -1.0f) { + m_skelKick1Anim = m_animMaps[i]; } - else if (animMap->m_unk0x00 == -2.0f) { - m_skelKick2Anim = animMap; + else if (m_animMaps[i]->GetUnknown0x00() == -2.0f) { + m_skelKick2Anim = m_animMaps[i]; } } assert(m_skelKick1Anim && m_skelKick2Anim); // STRING: LEGO1 0x100f0bc4 - const char* edge0344 = "EDG03_44"; - m_kick1B = currentWorld->FindPathBoundary(edge0344); + m_kick1B = currentWorld->FindPathBoundary("EDG03_44"); assert(m_kick1B); // STRING: LEGO1 0x100f0bb8 - const char* edge0354 = "EDG03_54"; - m_kick2B = currentWorld->FindPathBoundary(edge0354); + m_kick2B = currentWorld->FindPathBoundary("EDG03_54"); assert(m_kick2B); for (i = 0; i < sizeOfArray(g_skBMap); i++) { @@ -439,14 +438,16 @@ void LegoRaceCar::Animate(float p_time) } } + // If the player is moving forwards or backwards if (absoluteSpeed != 0.0f) { - g_unk0x100f0b88 = p_time; - g_unk0x100f0b8c = FALSE; + g_timePlayerLastMoved = p_time; + g_playedYouCantStopSound = FALSE; } - if (p_time - g_unk0x100f0b88 > 5000.0f && !g_unk0x100f0b8c) { - SoundManager()->GetCacheSoundManager()->Play(g_srt001ra, NULL, 0); - g_unk0x100f0b8c = TRUE; + // If the player hasn't moved in 5 seconds, play the "you can't stop in the middle of the race!" sound once + if (p_time - g_timePlayerLastMoved > 5000.0f && !g_playedYouCantStopSound) { + SoundManager()->GetCacheSoundManager()->Play(g_youCantStopSound, NULL, 0); + g_playedYouCantStopSound = TRUE; } } } @@ -462,9 +463,9 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool) } if (p_bool) { + MxMatrix matr; LegoROI* roi = p_actor->GetROI(); // name verified by BETA10 0x100cbbf5 assert(roi); - MxMatrix matr; matr = roi->GetLocal2World(); Vector3(matr[3]) += g_unk0x10102af0; @@ -479,41 +480,40 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool) MxLong time = Timer()->GetTime(); const char* soundKey = NULL; - MxLong timeElapsed = time - g_timeLastSoundPlayed; - if (timeElapsed > 3000) { + if (time - g_timeLastRaceCarSoundPlayed > 3000) { if (p_bool) { if (actorIsStuds) { - soundKey = g_srtsl18to29[g_srtsl18to29Index++]; - if (g_srtsl18to29Index >= sizeOfArray(g_srtsl18to29)) { - g_srtsl18to29Index = 0; + soundKey = g_playerHitStudsSounds[g_playerHitStudsSoundsIndex++]; + if (g_playerHitStudsSoundsIndex >= sizeOfArray(g_playerHitStudsSounds)) { + g_playerHitStudsSoundsIndex = 0; } } else if (actorIsRhoda) { - soundKey = g_emptySoundKeyList[g_emptySoundKeyListIndex++]; - if (g_emptySoundKeyListIndex >= sizeOfArray(g_emptySoundKeyList)) { - g_emptySoundKeyListIndex = 0; + soundKey = g_playerHitRhodaSounds[g_playerHitRhodaSoundsIndex++]; + if (g_playerHitRhodaSoundsIndex >= sizeOfArray(g_playerHitRhodaSounds)) { + g_playerHitRhodaSoundsIndex = 0; } } } else { if (actorIsStuds) { - soundKey = g_srtsl6to10[g_srtsl6to10Index++]; - if (g_srtsl6to10Index >= sizeOfArray(g_srtsl6to10)) { - g_srtsl6to10Index = 0; + soundKey = g_studsHitPlayerSounds[g_studsHitPlayerSoundsIndex++]; + if (g_studsHitPlayerSoundsIndex >= sizeOfArray(g_studsHitPlayerSounds)) { + g_studsHitPlayerSoundsIndex = 0; } } else if (actorIsRhoda) { - soundKey = g_srtrh[g_srtrhIndex++]; - if (g_srtrhIndex >= sizeOfArray(g_srtrh)) { - g_srtrhIndex = 0; + soundKey = g_rhodaHitPlayerSounds[g_rhodaHitPlayerSoundsIndex++]; + if (g_rhodaHitPlayerSoundsIndex >= sizeOfArray(g_rhodaHitPlayerSounds)) { + g_rhodaHitPlayerSoundsIndex = 0; } } } if (soundKey) { SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE); - g_timeLastSoundPlayed = g_unk0x100f3308 = time; + g_timeLastRaceCarSoundPlayed = g_unk0x100f3308 = time; } } @@ -567,13 +567,11 @@ MxResult LegoRaceCar::VTable0x9c() } // FUNCTION: LEGO1 0x10013670 -void LegoRaceCar::FUN_10013670() +void LegoJetski::InitSoundIndices() { - g_hitSnapSoundsIndex = (rand() & 0xc) >> 2; - - // Inlining the `rand()` causes this function to mismatch - MxU32 uVar1 = rand(); - g_hitValerieSoundsIndex = uVar1 % 0xc >> 2; + // See note in LegoRaceCar::InitSoundIndices + g_hitSnapSoundsIndex = rand() % sizeof(g_hitSnapSounds) / sizeof(g_hitSnapSounds[0]); + g_hitValerieSoundsIndex = rand() % sizeof(g_hitValerieSounds) / sizeof(g_hitValerieSounds[0]); } // FUNCTION: LEGO1 0x100136a0 @@ -680,8 +678,8 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool) } if (p_bool) { - LegoROI* roi = p_actor->GetROI(); MxMatrix matr; + LegoROI* roi = p_actor->GetROI(); matr = roi->GetLocal2World(); Vector3(matr[3]) += g_unk0x10102af0; @@ -696,9 +694,8 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool) MxLong time = Timer()->GetTime(); const char* soundKey = NULL; - MxLong timeElapsed = time - g_unk0x100f0bb4; - if (timeElapsed > 3000) { + if (time - g_timeLastJetskiSoundPlayed > 3000) { if (actorIsSnap) { soundKey = g_hitSnapSounds[g_hitSnapSoundsIndex++]; if (g_hitSnapSoundsIndex >= sizeOfArray(g_hitSnapSounds)) { @@ -714,7 +711,7 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool) if (soundKey) { SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE); - g_timeLastSoundPlayed = g_unk0x100f3308 = time; + g_timeLastJetskiSoundPlayed = g_unk0x100f3308 = time; } } From dad44535bd53d9de360de2d77dcd394bbd9cdfd9 Mon Sep 17 00:00:00 2001 From: MS Date: Wed, 29 Jan 2025 10:41:50 -0500 Subject: [PATCH 7/8] Beta matching LegoCacheSound (#1379) --- LEGO1/lego/legoomni/include/legocachsound.h | 4 +- .../lego/legoomni/src/audio/legocachsound.cpp | 107 +++++++++++------- 2 files changed, 72 insertions(+), 39 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocachsound.h b/LEGO1/lego/legoomni/include/legocachsound.h index ea55d7fc..ae560004 100644 --- a/LEGO1/lego/legoomni/include/legocachsound.h +++ b/LEGO1/lego/legoomni/include/legocachsound.h @@ -7,6 +7,7 @@ #include "mxstring.h" // VTABLE: LEGO1 0x100d4718 +// VTABLE: BETA10 0x101bb6f0 // SIZE 0x88 class LegoCacheSound : public MxCore { public: @@ -49,12 +50,13 @@ public: void MuteStop(MxBool p_mute); // SYNTHETIC: LEGO1 0x10006610 + // SYNTHETIC: BETA10 0x100675b0 // LegoCacheSound::`scalar deleting destructor' private: void Init(); void CopyData(MxU8* p_data, MxU32 p_dataSize); - MxString FUN_10006d80(const MxString& p_str); + MxString GetBaseFilename(MxString& p_path); LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x08 undefined m_unk0x0c[4]; // 0x0c diff --git a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp index c489fb00..27961810 100644 --- a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp +++ b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp @@ -4,31 +4,36 @@ #include "misc.h" #include "mxomni.h" +#include + DECOMP_SIZE_ASSERT(LegoCacheSound, 0x88) // FUNCTION: LEGO1 0x100064d0 +// FUNCTION: BETA10 0x10066340 LegoCacheSound::LegoCacheSound() { Init(); } // FUNCTION: LEGO1 0x10006630 +// FUNCTION: BETA10 0x100663f3 LegoCacheSound::~LegoCacheSound() { Destroy(); } // FUNCTION: LEGO1 0x100066d0 +// FUNCTION: BETA10 0x10066498 void LegoCacheSound::Init() { m_dsBuffer = NULL; m_data = NULL; m_unk0x58 = FALSE; memset(&m_wfx, 0, sizeof(m_wfx)); - m_unk0x6a = FALSE; - m_unk0x70 = FALSE; m_looping = TRUE; + m_unk0x6a = FALSE; m_volume = 79; + m_unk0x70 = FALSE; m_muted = FALSE; } @@ -42,6 +47,8 @@ MxResult LegoCacheSound::Create( MxU32 p_dataSize ) { + assert(p_pwfx); + WAVEFORMATEX wfx; wfx.wFormatTag = p_pwfx->wf.wFormatTag; wfx.nChannels = p_pwfx->wf.nChannels; @@ -86,7 +93,7 @@ MxResult LegoCacheSound::Create( CopyData(p_data, p_dataSize); } - m_unk0x48 = FUN_10006d80(p_mediaSrcPath); + m_unk0x48 = GetBaseFilename(p_mediaSrcPath); m_wfx = *p_pwfx; return SUCCESS; } @@ -95,6 +102,9 @@ MxResult LegoCacheSound::Create( // FUNCTION: BETA10 0x100667a0 void LegoCacheSound::CopyData(MxU8* p_data, MxU32 p_dataSize) { + assert(p_data); + assert(p_dataSize); + delete[] m_data; m_dataSize = p_dataSize; m_data = new MxU8[m_dataSize]; @@ -102,6 +112,7 @@ void LegoCacheSound::CopyData(MxU8* p_data, MxU32 p_dataSize) } // FUNCTION: LEGO1 0x10006920 +// FUNCTION: BETA10 0x1006685b void LegoCacheSound::Destroy() { if (m_dsBuffer) { @@ -119,19 +130,24 @@ void LegoCacheSound::Destroy() LegoCacheSound* LegoCacheSound::Clone() { LegoCacheSound* pnew = new LegoCacheSound(); + assert(pnew); - if (pnew->Create(&m_wfx, m_unk0x48, m_volume, m_data, m_dataSize) == SUCCESS) { + MxResult result = pnew->Create(&m_wfx, m_unk0x48, m_volume, m_data, m_dataSize); + if (result == SUCCESS) { return pnew; } - - delete pnew; - return NULL; + else { + delete pnew; + return NULL; + } } // FUNCTION: LEGO1 0x10006a30 // FUNCTION: BETA10 0x10066a23 MxResult LegoCacheSound::Play(const char* p_name, MxBool p_looping) { + assert(m_dsBuffer); + if (m_data == NULL || m_dataSize == 0) { return FAILURE; } @@ -162,10 +178,19 @@ MxResult LegoCacheSound::Play(const char* p_name, MxBool p_looping) memcpy(pvAudioPtr2, m_data + dwAudioBytes1, dwAudioBytes2); } - m_dsBuffer->Unlock(pvAudioPtr1, dwAudioBytes1, pvAudioPtr2, dwAudioBytes2); + DWORD sts = m_dsBuffer->Unlock(pvAudioPtr1, dwAudioBytes1, pvAudioPtr2, dwAudioBytes2); + assert(!sts); m_dsBuffer->SetCurrentPosition(0); - m_dsBuffer->Play(0, 0, p_looping); + if (m_dsBuffer->Play(0, 0, p_looping)) { + assert(0); + } } + else { + assert(0); + } + } + else { + assert(0); } if (p_looping == FALSE) { @@ -181,6 +206,7 @@ MxResult LegoCacheSound::Play(const char* p_name, MxBool p_looping) } // FUNCTION: LEGO1 0x10006b80 +// FUNCTION: BETA10 0x10066ca3 void LegoCacheSound::Stop() { DWORD dwStatus; @@ -200,6 +226,7 @@ void LegoCacheSound::Stop() } // FUNCTION: LEGO1 0x10006be0 +// FUNCTION: BETA10 0x10066d23 void LegoCacheSound::FUN_10006be0() { if (!m_looping) { @@ -226,14 +253,16 @@ void LegoCacheSound::FUN_10006be0() } } - if (m_unk0x74.GetLength() != 0 && !m_muted) { - if (!m_sound.UpdatePosition(m_dsBuffer)) { - if (m_unk0x6a) { - return; - } + if (m_unk0x74.GetLength() == 0) { + return; + } - m_dsBuffer->Stop(); - m_unk0x6a = TRUE; + if (!m_muted) { + if (!m_sound.UpdatePosition(m_dsBuffer)) { + if (!m_unk0x6a) { + m_dsBuffer->Stop(); + m_unk0x6a = TRUE; + } } else if (m_unk0x6a) { m_dsBuffer->Play(0, 0, m_looping); @@ -243,12 +272,14 @@ void LegoCacheSound::FUN_10006be0() } // FUNCTION: LEGO1 0x10006cb0 +// FUNCTION: BETA10 0x10066e85 void LegoCacheSound::SetDistance(MxS32 p_min, MxS32 p_max) { m_sound.SetDistance(p_min, p_max); } // FUNCTION: LEGO1 0x10006cd0 +// FUNCTION: BETA10 0x10066eb0 void LegoCacheSound::FUN_10006cd0(undefined4, undefined4) { } @@ -288,33 +319,33 @@ void LegoCacheSound::MuteStop(MxBool p_muted) // FUNCTION: LEGO1 0x10006d80 // FUNCTION: BETA10 0x100670e7 -MxString LegoCacheSound::FUN_10006d80(const MxString& p_str) +MxString LegoCacheSound::GetBaseFilename(MxString& p_path) { - // TODO: Clean up code - char* str = p_str.GetData(); - MxU32 length = strlen(str); + // Get the base filename from the given path + // e.g. "Z:\Lego\Audio\test.wav" --> "test" + char* str = p_path.GetData(); - char* local28 = str + length; - char* local14 = local28; - char* pVar1 = local28; + // Start at the end of the string and work backwards. + char* p = str + strlen(str); + char* end = p; - do { - local14 = pVar1; - pVar1 = local14 + -1; + while (str != p--) { + // If the file has an extension, we want to exclude it from the output. + // Set this as our new end position. + if (*p == '.') { + end = p; + } - if (str == local14) { + // Stop if we hit a directory or drive letter. + if (*p == '\\') { break; } + } - if (*pVar1 == '.') { - local28 = pVar1; - } - } while (*pVar1 != '\\'); - - local14 = pVar1; - - MxString local24; - local14++; - *local28 = '\0'; - return local24 = local14; + MxString output; + // Increment by one to shift p to the start of the filename. + char* x = ++p; + // If end points to the dot in filename, change it to a null terminator. + x[end - p] = '\0'; + return output = x; } From bc0344a8c44e9600d872dfed6be9dcacdb1eb997 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:44:00 +0100 Subject: [PATCH 8/8] Match `Jetski::HandleClick` (#1380) * Match `Jetski::HandleClick` * Formatting * Clean up, document, add BETA10 references * Fix formatting --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/jetski.h | 4 +- LEGO1/lego/legoomni/include/legoactor.h | 1 + LEGO1/lego/legoomni/include/legogamestate.h | 1 + LEGO1/lego/legoomni/src/actors/dunebuggy.cpp | 37 ++++++++++--------- .../legoomni/src/actors/islepathactor.cpp | 1 + LEGO1/lego/legoomni/src/actors/jetski.cpp | 29 ++++++++++++--- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/LEGO1/lego/legoomni/include/jetski.h b/LEGO1/lego/legoomni/include/jetski.h index cf2139d5..984c7751 100644 --- a/LEGO1/lego/legoomni/include/jetski.h +++ b/LEGO1/lego/legoomni/include/jetski.h @@ -35,7 +35,7 @@ public: void ActivateSceneActions(); - MxS16 GetUnknown0x160() { return m_unk0x160; } + MxS16 GetUnknown0x160() { return m_jetskiDashboardStreamId; } // SYNTHETIC: LEGO1 0x1007e5c0 // Jetski::`scalar deleting destructor' @@ -43,7 +43,7 @@ public: private: void RemoveFromWorld(); - MxS16 m_unk0x160; // 0x160 + MxS16 m_jetskiDashboardStreamId; // 0x160 }; #endif // JETSKI_H diff --git a/LEGO1/lego/legoomni/include/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h index 47c399f9..79d8ffeb 100644 --- a/LEGO1/lego/legoomni/include/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -58,6 +58,7 @@ public: virtual MxFloat VTable0x5c() { return m_unk0x70; } // vtable+0x5c // FUNCTION: LEGO1 0x10002d00 + // FUNCTION: BETA10 0x1000f4a0 virtual MxU8 GetActorId() { return m_actorId; } // vtable+0x60 // FUNCTION: LEGO1 0x10002d10 diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 291e58d0..8d1d4d61 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -199,6 +199,7 @@ public: void SwitchArea(Area p_area); void Init(); + // FUNCTION: BETA10 0x10083ff5 MxU8 GetActorId() { return m_actorId; } // FUNCTION: BETA10 0x1004a2d0 diff --git a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp index d01f8352..2d58ce71 100644 --- a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp +++ b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp @@ -157,27 +157,30 @@ MxLong DuneBuggy::HandlePathStruct(LegoPathStructNotificationParam& p_param) } // FUNCTION: LEGO1 0x10068290 +// FUNCTION: BETA10 0x1002765d MxS32 DuneBuggy::GetColorOffset(const char* p_variable) { MxS32 offset = 1; - const char* colorName = VariableTable()->GetVariable(p_variable); + const char* color = VariableTable()->GetVariable(p_variable); + assert(color); - if (strcmpi(colorName, "lego green")) { - if (!strcmpi(colorName, "lego red")) { - offset = 2; - } - else if (!strcmpi(colorName, "lego yellow")) { - offset = 3; - } - else if (!strcmpi(colorName, "lego black")) { - offset = 4; - } - else if (!strcmpi(colorName, "lego blue")) { - offset = 5; - } - else if (!strcmpi(colorName, "lego white")) { - offset = 6; - } + if (!strcmpi(color, "lego green")) { + offset = 1; + } + else if (!strcmpi(color, "lego red")) { + offset = 2; + } + else if (!strcmpi(color, "lego yellow")) { + offset = 3; + } + else if (!strcmpi(color, "lego black")) { + offset = 4; + } + else if (!strcmpi(color, "lego blue")) { + offset = 5; + } + else if (!strcmpi(color, "lego white")) { + offset = 6; } return offset; diff --git a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp index 75e9b03a..e3bbf85f 100644 --- a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp @@ -71,6 +71,7 @@ MxLong IslePathActor::Notify(MxParam& p_param) } // FUNCTION: LEGO1 0x1001a350 +// FUNCTION: BETA10 0x100365ad void IslePathActor::Enter() { m_roi->SetVisibility(FALSE); diff --git a/LEGO1/lego/legoomni/src/actors/jetski.cpp b/LEGO1/lego/legoomni/src/actors/jetski.cpp index e1163ff0..a045bfa8 100644 --- a/LEGO1/lego/legoomni/src/actors/jetski.cpp +++ b/LEGO1/lego/legoomni/src/actors/jetski.cpp @@ -18,12 +18,15 @@ DECOMP_SIZE_ASSERT(Jetski, 0x164) +// These two have been changed between BETA10 and LEGO1 // GLOBAL: LEGO1 0x100f7ab8 // STRING: LEGO1 0x100f3ce0 +// GLOBAL: BETA10 0x101e0be4 const char* g_varJSFRNTY5 = "c_jsfrnty5"; // GLOBAL: LEGO1 0x100f7abc // STRING: LEGO1 0x100f3ca4 +// GLOBAL: BETA10 0x101e0be0 const char* g_varJSWNSHY5 = "c_jswnshy5"; // FUNCTION: LEGO1 0x1007e3b0 @@ -77,6 +80,7 @@ void Jetski::Exit() // FUNCTION: BETA10 0x10037621 MxLong Jetski::HandleClick() { +#ifndef BETA10 if (!FUN_1003ef60()) { return 1; } @@ -89,26 +93,41 @@ MxLong Jetski::HandleClick() if (GameState()->GetActorId() != UserActor()->GetActorId()) { ((IslePathActor*) UserActor())->Exit(); } +#endif - // TODO: Match - m_unk0x160 = ((DuneBuggy::GetColorOffset(g_varJSWNSHY5) * 5 + 15) * 2); - m_unk0x160 += DuneBuggy::GetColorOffset(g_varJSFRNTY5); + // Selects the windshield from `IsleScript::c_JetskiDashboard11_Bitmap` (=41) + // to `IsleScript::c_JetskiDashboard66_Bitmap` based on the user's color selection + MxS32 colorOffset = DuneBuggy::GetColorOffset(g_varJSWNSHY5); + m_jetskiDashboardStreamId = 10 * (colorOffset + 3); + colorOffset = DuneBuggy::GetColorOffset(g_varJSFRNTY5); + m_jetskiDashboardStreamId += colorOffset; - InvokeAction(Extra::ActionType::e_start, *g_isleScript, m_unk0x160, NULL); + InvokeAction(Extra::ActionType::e_start, *g_isleScript, m_jetskiDashboardStreamId, NULL); InvokeAction(Extra::ActionType::e_start, *g_isleScript, IsleScript::c_JetskiDashboard, NULL); + +#ifdef BETA10 + if (UserActor()->GetActorId() != GameState()->GetActorId()) { + ((IslePathActor*) UserActor())->Exit(); + } + Enter(); + ControlManager()->Register(this); + PlayCamAnim(this, FALSE, 0x44, TRUE); +#else GetCurrentAction().SetObjectId(-1); AnimationManager()->FUN_1005f6d0(FALSE); AnimationManager()->FUN_10064670(NULL); Enter(); ControlManager()->Register(this); +#endif + return 1; } // FUNCTION: LEGO1 0x1007e880 void Jetski::RemoveFromWorld() { - RemoveFromCurrentWorld(*g_isleScript, m_unk0x160); + RemoveFromCurrentWorld(*g_isleScript, m_jetskiDashboardStreamId); RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_JetskiArms_Ctl); RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_JetskiInfo_Ctl); RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_JetskiSpeedMeter);