From e5fa35fd99c3edb3e939d1052f0cc39bbed724f3 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:26:10 -0400 Subject: [PATCH] Implement a few registrationbook methods (#703) * Implement a few registrationbook methods * Match RegistrationBook::HandleKeyPress * Match RegistrationBook::CreateSurface --------- Co-authored-by: Christian Semmler --- .../lego/legoomni/include/registrationbook.h | 29 ++-- .../legoomni/src/worlds/registrationbook.cpp | 143 ++++++++++++++++-- LEGO1/omni/include/mxcompositepresenter.h | 2 +- LEGO1/omni/src/common/mxutilities.cpp | 2 +- 4 files changed, 145 insertions(+), 31 deletions(-) diff --git a/LEGO1/lego/legoomni/include/registrationbook.h b/LEGO1/lego/legoomni/include/registrationbook.h index 41fadc0f..9bb23115 100644 --- a/LEGO1/lego/legoomni/include/registrationbook.h +++ b/LEGO1/lego/legoomni/include/registrationbook.h @@ -45,32 +45,33 @@ class RegistrationBook : public LegoWorld { // RegistrationBook::`scalar deleting destructor' private: - undefined4 m_unk0xf8; // 0xf8 + MxS32 m_registerDialogueTimer; // 0xf8 undefined m_unk0xfc; // 0xfc undefined m_unk0xfd[3]; // 0xfd MxStillPresenter* m_alphabet[26]; // 0x100 MxStillPresenter* m_name[10][7]; // 0x168 struct { - MxS16 m_letters[7]; // 0x00 - undefined2 m_unk0x0e; // 0x0e - } m_unk0x280; // 0x280 - MxControlPresenter* m_checkmark[10]; // 0x290 - undefined2 m_unk0x2b8; // 0x2b8 - InfocenterState* m_infocenterState; // 0x2bc - undefined m_unk0x2c0; // 0x2c0 - undefined m_unk0x2c1; // 0x2c1 - undefined m_unk0x2c2[0x02]; // 0x2c2 - undefined4 m_unk0x2c4; // 0x2c4 - undefined4 m_unk0x2c8; // 0x2c8 - LPDIRECTDRAWSURFACE m_unk0x2cc; // 0x2cc + MxS16 m_letters[7]; // 0x00 + MxS16 m_cursorPos; // 0x0e + } m_unk0x280; // 0x280 + MxControlPresenter* m_checkmark[10]; // 0x290 + undefined2 m_unk0x2b8; // 0x2b8 + InfocenterState* m_infocenterState; // 0x2bc + undefined m_unk0x2c0; // 0x2c0 + undefined m_unk0x2c1; // 0x2c1 + undefined m_unk0x2c2[0x02]; // 0x2c2 + LPDIRECTDRAWSURFACE m_checkboxHilite; // 0x2c4 + LPDIRECTDRAWSURFACE m_checkboxSurface; // 0x2c8 + LPDIRECTDRAWSURFACE m_checkboxNormal; // 0x2cc MxLong HandleEndAction(MxEndActionNotificationParam& p_param); - MxLong HandleKeyPress(MxS8 p_key); + MxLong HandleKeyPress(MxU8 p_key); MxLong HandleClick(LegoControlManagerEvent& p_param); MxLong HandleNotification19(MxParam& p_param); void FUN_100775c0(MxS16 p_playerIndex); void WriteInfocenterLetters(MxS16); void FUN_100778c0(); + MxBool CreateSurface(); }; #endif // REGISTRATIONBOOK_H diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 3f0a6108..aef8ad49 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -9,6 +9,7 @@ #include "misc.h" #include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" +#include "mxdisplaysurface.h" #include "mxmisc.h" #include "mxnotificationmanager.h" #include "mxtimer.h" @@ -20,12 +21,18 @@ DECOMP_SIZE_ASSERT(RegistrationBook, 0x2d0) // GLOBAL: LEGO1 0x100d9924 const char* g_infoman = "infoman"; +// GLOBAL: LEGO1 0x100f7964 +MxLong g_checkboxBlinkTimer = 0; + +// GLOBAL: LEGO1 0x100f7968 +MxBool g_nextCheckbox = FALSE; + // FUNCTION: LEGO1 0x10076d20 -RegistrationBook::RegistrationBook() : m_unk0xf8(0x80000000), m_unk0xfc(1) +RegistrationBook::RegistrationBook() : m_registerDialogueTimer(0x80000000), m_unk0xfc(1) { memset(m_alphabet, 0, sizeof(m_alphabet)); memset(m_name, 0, sizeof(m_name)); - m_unk0x280.m_unk0x0e = 0; + m_unk0x280.m_cursorPos = 0; memset(m_checkmark, 0, sizeof(m_checkmark)); memset(&m_unk0x280, -1, sizeof(m_unk0x280) - 2); @@ -36,9 +43,9 @@ RegistrationBook::RegistrationBook() : m_unk0xf8(0x80000000), m_unk0xfc(1) NotificationManager()->Register(this); m_unk0x2c1 = 0; - m_unk0x2c4 = 0; - m_unk0x2c8 = 0; - m_unk0x2cc = 0; + m_checkboxHilite = NULL; + m_checkboxSurface = NULL; + m_checkboxNormal = NULL; } // FUNCTION: LEGO1 0x10076f50 @@ -62,8 +69,8 @@ RegistrationBook::~RegistrationBook() ControlManager()->Unregister(this); NotificationManager()->Unregister(this); - if (m_unk0x2cc) { - m_unk0x2cc->Release(); + if (m_checkboxNormal) { + m_checkboxNormal->Release(); } } @@ -99,11 +106,11 @@ MxLong RegistrationBook::Notify(MxParam& p_param) result = HandleEndAction((MxEndActionNotificationParam&) p_param); break; case c_notificationKeyPress: - m_unk0xf8 = Timer()->GetTime(); + m_registerDialogueTimer = Timer()->GetTime(); result = HandleKeyPress(((LegoEventNotificationParam&) p_param).GetKey()); break; case c_notificationButtonDown: - m_unk0xf8 = Timer()->GetTime(); + m_registerDialogueTimer = Timer()->GetTime(); break; case c_notificationClick: result = HandleClick((LegoControlManagerEvent&) p_param); @@ -139,17 +146,65 @@ MxLong RegistrationBook::HandleEndAction(MxEndActionNotificationParam& p_param) case RegbookScript::c_iic007in_PlayWav: case RegbookScript::c_iic008in_PlayWav: BackgroundAudioManager()->RaiseVolume(); - m_unk0xf8 = Timer()->GetTime(); + m_registerDialogueTimer = Timer()->GetTime(); break; } return 1; } -// STUB: LEGO1 0x100772d0 -MxLong RegistrationBook::HandleKeyPress(MxS8 p_key) +// FUNCTION: LEGO1 0x100772d0 +MxLong RegistrationBook::HandleKeyPress(MxU8 p_key) { - return 0; + MxS16 key; + if (p_key >= 'a' && p_key <= 'z') { + key = p_key - ' '; + } + else { + key = p_key; + } + + if ((key < 'A' || key > 'Z') && key != '\b') { + if (key == ' ') { + DeleteObjects(&m_atom, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + BackgroundAudioManager()->RaiseVolume(); + } + } + else if (key != '\b' && m_unk0x280.m_cursorPos < 7) { + m_name[0][m_unk0x280.m_cursorPos] = m_alphabet[key - 'A']->Clone(); + + if (m_name[0][m_unk0x280.m_cursorPos] != NULL) { + m_alphabet[key - 'A']->GetAction()->SetUnknown24(m_alphabet[key - 'A']->GetAction()->GetUnknown24() + 1); + m_name[0][m_unk0x280.m_cursorPos]->Enable(TRUE); + m_name[0][m_unk0x280.m_cursorPos]->SetTickleState(MxPresenter::e_repeating); + m_name[0][m_unk0x280.m_cursorPos]->SetPosition(m_unk0x280.m_cursorPos * 23 + 343, 121); + + if (m_unk0x280.m_cursorPos == 0) { + m_checkmark[0]->Enable(TRUE); + } + + m_unk0x280.m_letters[m_unk0x280.m_cursorPos] = key - 'A'; + m_unk0x280.m_cursorPos++; + } + } + else { + if (key == '\b' && m_unk0x280.m_cursorPos > 0) { + m_unk0x280.m_cursorPos--; + + m_name[0][m_unk0x280.m_cursorPos]->Enable(FALSE); + + delete m_name[0][m_unk0x280.m_cursorPos]; + m_name[0][m_unk0x280.m_cursorPos] = NULL; + + if (m_unk0x280.m_cursorPos == 0) { + m_checkmark[0]->Enable(FALSE); + } + + m_unk0x280.m_letters[m_unk0x280.m_cursorPos] = -1; + } + } + + return 1; } // FUNCTION: LEGO1 0x100774a0 @@ -342,14 +397,40 @@ inline void RegistrationBook::PlayAction(MxU32 p_objectId) Start(&action); } -// STUB: LEGO1 0x10077fd0 +// FUNCTION: LEGO1 0x10077fd0 MxResult RegistrationBook::Tickle() { if (!m_worldStarted) { LegoWorld::Tickle(); } else { - // TODO + MxLong time = Timer()->GetTime(); + if (m_registerDialogueTimer != 0x80000000 && m_registerDialogueTimer + 30000 <= time) { + m_registerDialogueTimer = 0x80000000; + PlayAction(RegbookScript::c_iic007in_PlayWav); + } + + if (g_checkboxBlinkTimer + 500 <= time) { + g_checkboxBlinkTimer = time; + + if (m_checkboxHilite) { + DDBLTFX op; + op.dwSize = sizeof(op); + op.dwROP = 0xcc0020; + + if (g_nextCheckbox) { + m_checkboxSurface->Blt(NULL, m_checkboxHilite, NULL, DDBLT_ROP, &op); + } + else { + m_checkboxSurface->Blt(NULL, m_checkboxNormal, NULL, DDBLT_ROP, &op); + } + } + else { + CreateSurface(); + } + + g_nextCheckbox = !g_nextCheckbox; + } } return SUCCESS; @@ -377,6 +458,38 @@ MxLong RegistrationBook::HandleNotification19(MxParam& p_param) return 0; } +// FUNCTION: LEGO1 0x10078350 +MxBool RegistrationBook::CreateSurface() +{ + MxCompositePresenterList* list = m_checkmark[0]->GetList(); + MxStillPresenter *presenter, *uninitialized; + + if (list) { + if (list->begin() != list->end()) { + presenter = (MxStillPresenter*) list->front(); + } + else { + presenter = uninitialized; // intentionally uninitialized variable + } + + if (presenter) { + m_checkboxSurface = presenter->VTable0x78(); + } + + presenter = (MxStillPresenter*) Find("MxStillPresenter", "CheckHiLite_Bitmap"); + if (presenter) { + m_checkboxHilite = presenter->VTable0x78(); + } + + if (m_checkboxSurface && m_checkboxHilite) { + m_checkboxNormal = MxDisplaySurface::CopySurface(m_checkboxSurface); + return TRUE; + } + } + + return FALSE; +} + // FUNCTION: LEGO1 0x100783e0 MxBool RegistrationBook::VTable0x64() { diff --git a/LEGO1/omni/include/mxcompositepresenter.h b/LEGO1/omni/include/mxcompositepresenter.h index a39507c0..2e5a6d95 100644 --- a/LEGO1/omni/include/mxcompositepresenter.h +++ b/LEGO1/omni/include/mxcompositepresenter.h @@ -47,7 +47,7 @@ class MxCompositePresenter : public MxPresenter { return TRUE; } // vtable+0x64 - inline MxCompositePresenterList& GetList() { return m_list; } + inline MxCompositePresenterList* GetList() { return &m_list; } protected: MxCompositePresenterList m_list; // 0x40 diff --git a/LEGO1/omni/src/common/mxutilities.cpp b/LEGO1/omni/src/common/mxutilities.cpp index 7030848c..26dd733b 100644 --- a/LEGO1/omni/src/common/mxutilities.cpp +++ b/LEGO1/omni/src/common/mxutilities.cpp @@ -119,7 +119,7 @@ MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* { for (MxCompositePresenterList::iterator it = p_presenterList.begin(); it != p_presenterList.end(); it++) { if (p_presenter == *it || ((*it)->IsA("MxCompositePresenter") && - ContainsPresenter(((MxCompositePresenter*) *it)->GetList(), p_presenter))) { + ContainsPresenter(*((MxCompositePresenter*) *it)->GetList(), p_presenter))) { return TRUE; } }