diff --git a/.pylintrc b/.pylintrc index ab83fceb..68704fad 100644 --- a/.pylintrc +++ b/.pylintrc @@ -88,7 +88,7 @@ persistent=yes # Minimum Python version to use for version dependent checks. Will default to # the version used to run pylint. -py-version=3.11 +py-version=3.12 # Discover python modules and packages in the file system subtree. recursive=no diff --git a/CMakeLists.txt b/CMakeLists.txt index 85b14530..095c7711 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ else() endif() find_program(SDL_SHADERCROSS_BIN NAMES "shadercross") -find_package(Python3 3.11 COMPONENTS Interpreter) +find_package(Python3 3.12 COMPONENTS Interpreter) option(ISLE_BUILD_APP "Build isle application" ON) option(ISLE_ASAN "Enable Address Sanitizer" OFF) @@ -569,6 +569,7 @@ if (ISLE_BUILD_APP) ISLE/emscripten/config.cpp ISLE/emscripten/events.cpp ISLE/emscripten/filesystem.cpp + ISLE/emscripten/haptic.cpp ISLE/emscripten/messagebox.cpp ISLE/emscripten/window.cpp ) diff --git a/CONFIG/MainDlg.cpp b/CONFIG/MainDlg.cpp index dfba47ea..3f69d096 100644 --- a/CONFIG/MainDlg.cpp +++ b/CONFIG/MainDlg.cpp @@ -58,6 +58,7 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent) connect(m_ui->musicCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxMusic); connect(m_ui->sound3DCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckbox3DSound); connect(m_ui->fullscreenCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxFullscreen); + connect(m_ui->exclusiveFullscreenCheckbox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxExclusiveFullscreen); connect(m_ui->rumbleCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxRumble); connect(m_ui->textureCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxTexture); connect(m_ui->touchComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::TouchControlsChanged); @@ -80,7 +81,44 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent) connect(m_ui->maxActorsSlider, &QSlider::valueChanged, this, &CMainDialog::MaxActorsChanged); connect(m_ui->maxActorsSlider, &QSlider::sliderMoved, this, &CMainDialog::MaxActorsChanged); + connect(m_ui->aspectRatioComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::AspectRatioChanged); + connect(m_ui->xResSpinBox, &QSpinBox::valueChanged, this, &CMainDialog::XResChanged); + connect(m_ui->yResSpinBox, &QSpinBox::valueChanged, this, &CMainDialog::YResChanged); + connect(m_ui->framerateSpinBox, &QSpinBox::valueChanged, this, &CMainDialog::FramerateChanged); + layout()->setSizeConstraint(QLayout::SetFixedSize); + + if (currentConfigApp->m_ram_quality_limit != 0) { + m_modified = true; + const QString ramError = QString("Insufficient RAM!"); + m_ui->sound3DCheckBox->setChecked(false); + m_ui->sound3DCheckBox->setEnabled(false); + m_ui->sound3DCheckBox->setToolTip(ramError); + m_ui->modelQualityHighRadioButton->setEnabled(false); + m_ui->modelQualityHighRadioButton->setToolTip(ramError); + m_ui->modelQualityLowRadioButton->setEnabled(true); + if (currentConfigApp->m_ram_quality_limit == 2) { + m_ui->modelQualityLowRadioButton->setChecked(true); + m_ui->modelQualityMediumRadioButton->setEnabled(false); + m_ui->modelQualityMediumRadioButton->setToolTip(ramError); + m_ui->maxLoDSlider->setMaximum(30); + m_ui->maxActorsSlider->setMaximum(15); + } + else { + m_ui->modelQualityMediumRadioButton->setChecked(true); + m_ui->modelQualityMediumRadioButton->setEnabled(true); + m_ui->maxLoDSlider->setMaximum(40); + m_ui->maxActorsSlider->setMaximum(30); + } + } + else { + m_ui->sound3DCheckBox->setEnabled(true); + m_ui->modelQualityLowRadioButton->setEnabled(true); + m_ui->modelQualityMediumRadioButton->setEnabled(true); + m_ui->modelQualityHighRadioButton->setEnabled(true); + m_ui->maxLoDSlider->setMaximum(60); + m_ui->maxActorsSlider->setMaximum(40); + } } CMainDialog::~CMainDialog() @@ -98,7 +136,7 @@ bool CMainDialog::OnInitDialog() int device_i = 0; int selected = 0; char device_name[256]; - const list& driver_list = enumerator->GetDriverList(); + const list& driver_list = enumerator->m_ddInfo; for (list::const_iterator it_driver = driver_list.begin(); it_driver != driver_list.end(); it_driver++) { const MxDriver& driver = *it_driver; for (list::const_iterator it_device = driver.m_devices.begin(); @@ -125,6 +163,7 @@ bool CMainDialog::OnInitDialog() m_ui->LoDNum->setNum((int) currentConfigApp->m_max_lod * 10); m_ui->maxActorsSlider->setValue(currentConfigApp->m_max_actors); m_ui->maxActorsNum->setNum(currentConfigApp->m_max_actors); + UpdateInterface(); return true; } @@ -221,6 +260,8 @@ void CMainDialog::UpdateInterface() } m_ui->musicCheckBox->setChecked(currentConfigApp->m_music); m_ui->fullscreenCheckBox->setChecked(currentConfigApp->m_full_screen); + m_ui->exclusiveFullscreenCheckbox->setEnabled(currentConfigApp->m_full_screen); + m_ui->exclusiveFullscreenCheckbox->setChecked(currentConfigApp->m_exclusive_full_screen); m_ui->rumbleCheckBox->setChecked(currentConfigApp->m_haptic); m_ui->touchComboBox->setCurrentIndex(currentConfigApp->m_touch_scheme); m_ui->transitionTypeComboBox->setCurrentIndex(currentConfigApp->m_transition_type); @@ -231,6 +272,11 @@ void CMainDialog::UpdateInterface() m_ui->texturePath->setEnabled(currentConfigApp->m_texture_load); m_ui->texturePathOpen->setEnabled(currentConfigApp->m_texture_load); + + m_ui->aspectRatioComboBox->setCurrentIndex(currentConfigApp->m_aspect_ratio); + m_ui->xResSpinBox->setValue(currentConfigApp->m_x_res); + m_ui->yResSpinBox->setValue(currentConfigApp->m_y_res); + m_ui->framerateSpinBox->setValue(static_cast(std::round(1000.0f / currentConfigApp->m_frame_delta))); } // FUNCTION: CONFIG 0x004045e0 @@ -301,6 +347,14 @@ void CMainDialog::OnCheckboxMusic(bool checked) void CMainDialog::OnCheckboxFullscreen(bool checked) { currentConfigApp->m_full_screen = checked; + m_ui->exclusiveFullscreenCheckbox->setEnabled(checked); + m_modified = true; + UpdateInterface(); +} + +void CMainDialog::OnCheckboxExclusiveFullscreen(bool checked) +{ + currentConfigApp->m_exclusive_full_screen = checked; m_modified = true; UpdateInterface(); } @@ -444,3 +498,59 @@ void CMainDialog::TexturePathEdited() } UpdateInterface(); } + +void CMainDialog::AspectRatioChanged(int index) +{ + currentConfigApp->m_aspect_ratio = index; + EnsureAspectRatio(); + m_modified = true; + UpdateInterface(); +} + +void CMainDialog::XResChanged(int i) +{ + currentConfigApp->m_x_res = i; + m_modified = true; + UpdateInterface(); +} + +void CMainDialog::YResChanged(int i) +{ + currentConfigApp->m_y_res = i; + EnsureAspectRatio(); + m_modified = true; + UpdateInterface(); +} + +void CMainDialog::EnsureAspectRatio() +{ + if (currentConfigApp->m_aspect_ratio != 3) { + m_ui->xResSpinBox->setReadOnly(true); + switch (currentConfigApp->m_aspect_ratio) { + case 0: { + float standardAspect = 4.0f / 3.0f; + currentConfigApp->m_x_res = static_cast(std::round((currentConfigApp->m_y_res) * standardAspect)); + break; + } + case 1: { + float wideAspect = 16.0f / 9.0f; + currentConfigApp->m_x_res = static_cast(std::round((currentConfigApp->m_y_res) * wideAspect)); + break; + } + case 2: { + currentConfigApp->m_x_res = currentConfigApp->m_y_res; + break; + } + } + } + else { + m_ui->xResSpinBox->setReadOnly(false); + } +} + +void CMainDialog::FramerateChanged(int i) +{ + currentConfigApp->m_frame_delta = (1000.0f / static_cast(i)); + m_modified = true; + UpdateInterface(); +} diff --git a/CONFIG/MainDlg.h b/CONFIG/MainDlg.h index 40156790..ece4dbfd 100644 --- a/CONFIG/MainDlg.h +++ b/CONFIG/MainDlg.h @@ -42,6 +42,7 @@ private slots: void OnRadiobuttonTextureHighQuality(bool checked); void OnCheckboxMusic(bool checked); void OnCheckboxFullscreen(bool checked); + void OnCheckboxExclusiveFullscreen(bool checked); void OnCheckboxRumble(bool checked); void OnCheckboxTexture(bool checked); void TouchControlsChanged(int index); @@ -57,6 +58,11 @@ private slots: void MaxActorsChanged(int value); void SelectTexturePathDialog(); void TexturePathEdited(); + void XResChanged(int i); + void YResChanged(int i); + void AspectRatioChanged(int index); + void EnsureAspectRatio(); + void FramerateChanged(int i); }; // SYNTHETIC: CONFIG 0x00403de0 diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp index c88f779b..d0f1dda6 100644 --- a/CONFIG/config.cpp +++ b/CONFIG/config.cpp @@ -67,9 +67,14 @@ bool CConfigApp::InitInstance() return FALSE; } SDL_DestroyWindow(window); + m_aspect_ratio = 0; + m_x_res = 640; + m_y_res = 480; + m_frame_delta = 10.0f; m_driver = NULL; m_device = NULL; m_full_screen = TRUE; + m_exclusive_full_screen = FALSE; m_transition_type = 3; // 3: Mosaic m_wide_view_angle = TRUE; m_use_joystick = TRUE; @@ -84,6 +89,7 @@ bool CConfigApp::InitInstance() m_texture_path = "/textures/"; int totalRamMiB = SDL_GetSystemRAM(); if (totalRamMiB < 12) { + m_ram_quality_limit = 2; m_3d_sound = FALSE; m_model_quality = 0; m_texture_quality = 1; @@ -91,6 +97,7 @@ bool CConfigApp::InitInstance() m_max_actors = 5; } else if (totalRamMiB < 20) { + m_ram_quality_limit = 1; m_3d_sound = FALSE; m_model_quality = 1; m_texture_quality = 1; @@ -98,6 +105,7 @@ bool CConfigApp::InitInstance() m_max_actors = 10; } else { + m_ram_quality_limit = 0; m_model_quality = 2; m_3d_sound = TRUE; m_texture_quality = 1; @@ -126,7 +134,7 @@ D3DCOLORMODEL CConfigApp::GetHardwareDeviceColorModel() const // FUNCTION: CONFIG 0x00403410 bool CConfigApp::IsPrimaryDriver() const { - return m_driver == &m_device_enumerator->GetDriverList().front(); + return m_driver == &m_device_enumerator->m_ddInfo.front(); } // FUNCTION: CONFIG 0x00403430 @@ -158,6 +166,7 @@ bool CConfigApp::ReadRegisterSettings() m_display_bit_depth = iniparser_getint(dict, "isle:Display Bit Depth", -1); m_flip_surfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flip_surfaces); m_full_screen = iniparser_getboolean(dict, "isle:Full Screen", m_full_screen); + m_exclusive_full_screen = iniparser_getboolean(dict, "isle:Exclusive Full Screen", m_exclusive_full_screen); m_transition_type = iniparser_getint(dict, "isle:Transition Type", m_transition_type); m_touch_scheme = iniparser_getint(dict, "isle:Touch Scheme", m_touch_scheme); m_3d_video_ram = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", m_3d_video_ram); @@ -174,6 +183,10 @@ bool CConfigApp::ReadRegisterSettings() m_max_actors = iniparser_getint(dict, "isle:Max Allowed Extras", m_max_actors); m_texture_load = iniparser_getboolean(dict, "extensions:texture loader", m_texture_load); m_texture_path = iniparser_getstring(dict, "texture loader:texture path", m_texture_path.c_str()); + m_aspect_ratio = iniparser_getint(dict, "isle:Aspect Ratio", m_aspect_ratio); + m_x_res = iniparser_getint(dict, "isle:Horizontal Resolution", m_x_res); + m_y_res = iniparser_getint(dict, "isle:Vertical Resolution", m_y_res); + m_frame_delta = iniparser_getdouble(dict, "isle:Frame Delta", m_frame_delta); iniparser_freedict(dict); return true; } @@ -230,7 +243,7 @@ bool CConfigApp::ValidateSettings() is_modified = TRUE; } - if (m_max_lod < 0.0f || m_max_lod > 5.0f) { + if (m_max_lod < 0.0f || m_max_lod > 6.0f) { m_max_lod = 3.5f; is_modified = TRUE; } @@ -326,6 +339,7 @@ void CConfigApp::WriteRegisterSettings() const SetIniInt(dict, "isle:Display Bit Depth", m_display_bit_depth); SetIniBool(dict, "isle:Flip Surfaces", m_flip_surfaces); SetIniBool(dict, "isle:Full Screen", m_full_screen); + SetIniBool(dict, "isle:Exclusive Full Screen", m_exclusive_full_screen); SetIniBool(dict, "isle:Wide View Angle", m_wide_view_angle); SetIniInt(dict, "isle:Transition Type", m_transition_type); @@ -350,6 +364,11 @@ void CConfigApp::WriteRegisterSettings() const iniparser_set(dict, "isle:Max LOD", std::to_string(m_max_lod).c_str()); SetIniInt(dict, "isle:Max Allowed Extras", m_max_actors); + SetIniInt(dict, "isle:Aspect Ratio", m_aspect_ratio); + SetIniInt(dict, "isle:Horizontal Resolution", m_x_res); + SetIniInt(dict, "isle:Vertical Resolution", m_y_res); + iniparser_set(dict, "isle:Frame Delta", std::to_string(m_frame_delta).c_str()); + #undef SetIniBool #undef SetIniInt diff --git a/CONFIG/config.h b/CONFIG/config.h index 796a5659..ad3321ac 100644 --- a/CONFIG/config.h +++ b/CONFIG/config.h @@ -59,12 +59,17 @@ class CConfigApp { // DECLARE_MESSAGE_MAP() public: + int m_aspect_ratio; + int m_x_res; + int m_y_res; + float m_frame_delta; LegoDeviceEnumerate* m_device_enumerator; MxDriver* m_driver; Direct3DDeviceInfo* m_device; int m_display_bit_depth; bool m_flip_surfaces; bool m_full_screen; + bool m_exclusive_full_screen; int m_transition_type; bool m_3d_video_ram; bool m_wide_view_angle; @@ -85,6 +90,7 @@ class CConfigApp { float m_max_lod; int m_max_actors; int m_touch_scheme; + int m_ram_quality_limit; }; extern CConfigApp g_theApp; diff --git a/CONFIG/res/maindialog.ui b/CONFIG/res/maindialog.ui index 526c31d8..5a0d3b31 100644 --- a/CONFIG/res/maindialog.ui +++ b/CONFIG/res/maindialog.ui @@ -6,8 +6,8 @@ 0 0 - 550 - 700 + 600 + 480 @@ -68,654 +68,861 @@ - - - - 0 - 0 - + + + 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 50 - 16777215 - - - - Open - - - - - - - - 0 - 0 - - - - - 50 - 16777215 - - - - Open - - - - - - - - 0 - 0 - - - - Save Path: - - - Qt::PlainText - - - - - - - Path to the game data files. -Set this to the CD image root. - - - - - - - Folder where save files are kept. - - - - - - - - 0 - 0 - - - - Data Path: - - - Qt::PlainText - - - - - - - - - - - 0 - 80 - - - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Maximum number of LEGO actors to exist in the world at a time. -The game will gradually increase the number of actors until this maximum is reached and while performance is acceptable. - - - Maximum Actors (5..40) - - + + + Game + + + + - - - - 0 - 0 - - - - 5 - - - 40 - - - 5 - - - 20 - - - 20 - - - false - - - Qt::Horizontal - - - QSlider::NoTicks - - - 5 - - - - - - - - 0 - 0 - - - - - 15 - 0 - - - - 20 - - - - - - - - - - - 0 - 0 - - - - - 0 - 70 - - - - Maximum Level of Detail (LOD). -A higher setting will cause higher quality textures to be drawn regardless of distance. - - - Maximum LOD - - - - - - - 0 - 0 - - - - 50 - - - 5 - - - 10 - - - 35 - - - false - - - Qt::Horizontal - - - QSlider::NoTicks - - - 10 - - - - - - - - 0 - 0 - - - - - 15 - 0 - - - - 35 - - - - - - - - - - - 0 - 0 - - - - Set 3D model detail level. - - - Island Model Quality - - - - + - Broken, not recommended. - - - color: rgb(255, 0, 0); + Enable 3D positional audio effects. - Low - BROKEN! + 3D Sound - - - Medium + + + Enable in-game background music. - - - - - High + Music - - - - - - true - - - - 0 - 0 - - - - Set texture detail level. - - - Island Texture Quality - - - false - - - - 0 + + + + + Qt::Orientation::Vertical - - 0 + + + 20 + 40 + - - - - Fast - - - - - - - High - - - - - - - - - - - - - - 0 - 0 - - - - - 0 - - - 0 - - - - - Enable 3D positional audio effects. - - - 3D Sound - - - - - - - Enable in-game background music. - - - Music - - - - - - - Toggle fullscreen display mode. - - - Fullscreen - - - - - - - true - - - Enable controller rumble. - - - Rumble - - - true - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Sets the transition effect to be used in game. - - - Transition Type - - - - - - Mosaic - - - 3 - - - - Idle - Broken - - - - - No Animation - - - - - Dissolve - - - - + + + + + + + 0 + 0 + + + + Sets the transition effect to be used in game. + + + Transition Type + + + + + Mosaic - - - - Wipe Down + + 3 - - - - Windows + + + Idle - Broken + + + + + No Animation + + + + + Dissolve + + + + + Mosaic + + + + + Wipe Down + + + + + Windows + + + + + Unknown - Broken + + + + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + + + Folder where save files are kept. - - - - Unknown - Broken + + + + + + Path to the game data files. +Set this to the CD image root. - - - - - - - - - - <html><head/><body><p><span style=" font-weight:600;">Virtual Gamepad (Recommended):</span> Slide your finger to move and turn.</p><p><span style=" font-weight:600;">Virtual Arrow Keys:</span> Tap screen areas to move. The top moves forward, the bottom turns or moves back.</p><p><span style=" font-weight:600;">Virtual Mouse:</span> Emulates classic mouse controls with touch.</p></body></html> - - - Touch Control Scheme - - - - - - 2 - - - - Virtual Mouse + + + + + + + 0 + 0 + - - - Virtual Arrow Keys + Data Path: + + + Qt::TextFormat::PlainText + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + - - - Virtual Gamepad + Open - - - - - - - - - - - - - Texture Loader Extension - - - - - - false - - - Path to texture replacements. - - - textures/ - - - - - - - false - - - - 0 - 0 - - - - - 50 - 16777215 - - - - Open - - - - - - - Enabled - - - - - - - - - - - 0 - 0 - - - - 3D graphics device used to render the game. - - - Graphics Devices - - - false - - - - 6 - - - 6 - - - 6 - - - 6 - - - - - true - - - - 0 - 0 - - - - - 16777215 - 100 - - - - QAbstractItemView::NoEditTriggers - - - true - - - QAbstractItemView::SelectItems - - - - + + + + + + + 0 + 0 + + + + Save Path: + + + Qt::TextFormat::PlainText + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Open + + + + + + + + + + + Graphics + + + + + + + 0 + 0 + + + + + 0 + 70 + + + + Maximum Level of Detail (LOD). +A higher setting will cause higher quality textures to be drawn regardless of distance. + + + Maximum LOD + + + + + + + 0 + 0 + + + + 60 + + + 5 + + + 10 + + + 35 + + + false + + + Qt::Orientation::Horizontal + + + QSlider::TickPosition::NoTicks + + + 10 + + + + + + + + 0 + 0 + + + + + 15 + 0 + + + + 35 + + + + + + + + + + + 0 + 0 + + + + 3D graphics device used to render the game. + + + Graphics Devices + + + false + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + true + + + + 0 + 0 + + + + + 16777215 + 100 + + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + true + + + QAbstractItemView::SelectionBehavior::SelectItems + + + + + + + + + + true + + + + 0 + 0 + + + + Set texture detail level. + + + Island Texture Quality + + + false + + + + 0 + + + 0 + + + + + Fast + + + + + + + High + + + + + + + + + + + 0 + 0 + + + + Maximum number of LEGO actors to exist in the world at a time. +The game will gradually increase the number of actors until this maximum is reached and while performance is acceptable. + + + Maximum Actors + + + + + + + 0 + 0 + + + + 5 + + + 40 + + + 5 + + + 20 + + + 20 + + + false + + + Qt::Orientation::Horizontal + + + QSlider::TickPosition::NoTicks + + + 5 + + + + + + + + 0 + 0 + + + + + 15 + 0 + + + + 20 + + + + + + + + + + + 0 + 0 + + + + Set 3D model detail level. + + + Island Model Quality + + + + + + Broken, not recommended. + + + color: rgb(255, 0, 0); + + + Low - BROKEN! + + + + + + + Medium + + + + + + + High + + + + + + + + + + + Display + + + + + + General + + + + + + <html><head/><body><p>Maximum framerate. Values above 100fps are untested.</p></body></html> + + + fps + + + Max Framerate: + + + 200 + + + 100 + + + + + + + + + Toggle fullscreen display mode. + + + Fullscreen + + + + + + + false + + + Grants the app full control of the display for better performance and lower input lag. May cause slower alt-tabbing. + + + Exclusive Fullscreen + + + + + + + + + + + + Windowed Resolution + + + + + + <html><head/><body><p>The aspect ratio you intend to use.<br/>Select <span style=" font-weight:700;">Custom</span> to define your own width and height.<br/>Has no effect on the game itself.</p></body></html> + + + 0 + + + + Standard (4:3) + + + + + Widescreen (16:9) + + + + + Square (1:1) + + + + + Custom + + + + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Horizontal resolution. </p><p>Locked to aspect ratio, unless <span style=" font-weight:700;">Custom</span> is select as the aspect ratio.</p></body></html> + + + Qt::AlignmentFlag::AlignCenter + + + true + + + 10000 + + + 640 + + + 10 + + + + + + + + 0 + 0 + + + + x + + + Qt::AlignmentFlag::AlignCenter + + + + + + + true + + + + 0 + 0 + + + + <html><head/><body><p>Vertical resolution. </p><p>If an aspect ratio other than <span style=" font-weight:700;">Custom</span> is selected, this directly affects the horizontal resolution.</p></body></html> + + + Qt::AlignmentFlag::AlignCenter + + + 10000 + + + 480 + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + Controls + + + + + + <html><head/><body><p><span style=" font-weight:600;">Virtual Gamepad (Recommended):</span> Slide your finger to move and turn.</p><p><span style=" font-weight:600;">Virtual Arrow Keys:</span> Tap screen areas to move. The top moves forward, the bottom turns or moves back.</p><p><span style=" font-weight:600;">Virtual Mouse:</span> Emulates classic mouse controls with touch.</p></body></html> + + + Touch Control Scheme + + + + + + 2 + + + + Virtual Mouse + + + + + Virtual Arrow Keys + + + + + Virtual Gamepad + + + + + + + + + + + true + + + Enable controller rumble. + + + Rumble + + + true + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + Extensions + + + + + + Settings for Texture Loader extension. + + + Texture Loader Extension + + + + + + Enabled + + + + + + + false + + + Path to texture replacements. + + + textures/ + + + + + + + false + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Open + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + @@ -784,10 +991,14 @@ A higher setting will cause higher quality textures to be drawn regardless of di + tabWidget dataPath dataPathOpen savePath savePathOpen + transitionTypeComboBox + sound3DCheckBox + musicCheckBox textureQualityFastRadioButton textureQualityHighRadioButton modelQualityLowRadioButton @@ -795,9 +1006,18 @@ A higher setting will cause higher quality textures to be drawn regardless of di modelQualityHighRadioButton maxLoDSlider maxActorsSlider - sound3DCheckBox - musicCheckBox devicesList + fullscreenCheckBox + exclusiveFullscreenCheckbox + framerateSpinBox + aspectRatioComboBox + xResSpinBox + yResSpinBox + touchComboBox + rumbleCheckBox + textureCheckBox + texturePath + texturePathOpen okButton launchButton cancelButton diff --git a/ISLE/emscripten/haptic.cpp b/ISLE/emscripten/haptic.cpp new file mode 100644 index 00000000..4a7244e5 --- /dev/null +++ b/ISLE/emscripten/haptic.cpp @@ -0,0 +1,55 @@ +#include "haptic.h" + +#include "compat.h" +#include "lego/sources/misc/legoutil.h" +#include "legoinputmanager.h" +#include "misc.h" + +#include + +void Emscripten_HandleRumbleEvent(float p_lowFrequencyRumble, float p_highFrequencyRumble, MxU32 p_milliseconds) +{ + std::visit( + overloaded{ + [](LegoInputManager::SDL_KeyboardID_v p_id) {}, + [](LegoInputManager::SDL_MouseID_v p_id) {}, + [p_lowFrequencyRumble, p_highFrequencyRumble, p_milliseconds](LegoInputManager::SDL_JoystickID_v p_id) { + const char* name = SDL_GetJoystickNameForID((SDL_JoystickID) p_id); + if (name) { + MAIN_THREAD_EM_ASM( + { + const name = UTF8ToString($0); + const gamepads = navigator.getGamepads(); + for (const gamepad of gamepads) { + if (gamepad && gamepad.connected && gamepad.id == name && gamepad.vibrationActuator) { + gamepad.vibrationActuator.playEffect("dual-rumble", { + startDelay : 0, + weakMagnitude : $1, + strongMagnitude : $2, + duration : $3, + }); + break; + } + } + }, + name, + SDL_clamp(p_lowFrequencyRumble, 0, 1), + SDL_clamp(p_highFrequencyRumble, 0, 1), + p_milliseconds + ); + } + }, + [p_milliseconds](LegoInputManager::SDL_TouchID_v p_id) { + MAIN_THREAD_EM_ASM( + { + if (navigator.vibrate) { + navigator.vibrate($0); + } + }, + p_milliseconds + ); + } + }, + InputManager()->GetLastInputMethod() + ); +} diff --git a/ISLE/emscripten/haptic.h b/ISLE/emscripten/haptic.h new file mode 100644 index 00000000..51605128 --- /dev/null +++ b/ISLE/emscripten/haptic.h @@ -0,0 +1,8 @@ +#ifndef EMSCRIPTEN_HAPTIC_H +#define EMSCRIPTEN_HAPTIC_H + +#include "mxtypes.h" + +void Emscripten_HandleRumbleEvent(float p_lowFrequencyRumble, float p_highFrequencyRumble, MxU32 p_milliseconds); + +#endif // EMSCRIPTEN_HAPTIC_H diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 6edfa261..2cd65e2d 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -54,6 +54,7 @@ #include "emscripten/config.h" #include "emscripten/events.h" #include "emscripten/filesystem.h" +#include "emscripten/haptic.h" #include "emscripten/messagebox.h" #include "emscripten/window.h" #endif @@ -141,8 +142,6 @@ IsleApp::IsleApp() m_drawCursor = FALSE; m_use3dSound = TRUE; m_useMusic = TRUE; - m_useJoystick = TRUE; - m_joystickIndex = 0; m_wideViewAngle = TRUE; m_islandQuality = 2; m_islandTexture = 1; @@ -184,6 +183,10 @@ IsleApp::IsleApp() m_cursorSensitivity = 4; m_touchScheme = LegoInputManager::e_gamepad; m_haptic = TRUE; + m_xRes = 640; + m_yRes = 480; + m_frameRate = 100.0f; + m_exclusiveFullScreen = FALSE; } // FUNCTION: ISLE 0x4011a0 @@ -305,7 +308,7 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0"); SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) { + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC)) { char buffer[256]; SDL_snprintf( buffer, @@ -324,7 +327,8 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) // Create global app instance g_isle = new IsleApp(); - if (g_isle->ParseArguments(argc, argv) != SUCCESS) { + switch (g_isle->ParseArguments(argc, argv)) { + case SDL_APP_FAILURE: Any_ShowSimpleMessageBox( SDL_MESSAGEBOX_ERROR, "LEGO® Island Error", @@ -332,6 +336,10 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) window ); return SDL_APP_FAILURE; + case SDL_APP_SUCCESS: + return SDL_APP_SUCCESS; + case SDL_APP_CONTINUE: + break; } // Create window @@ -348,6 +356,23 @@ SDL_AppResult SDL_AppInit(void** appstate, int argc, char** argv) // Get reference to window *appstate = g_isle->GetWindowHandle(); + // Currently, SDL doesn't send SDL_EVENT_MOUSE_ADDED at startup (unlike for gamepads) + // This will probably be fixed in the future: https://github.com/libsdl-org/SDL/issues/12815 + { + int count; + SDL_MouseID* mice = SDL_GetMice(&count); + + if (mice) { + for (int i = 0; i < count; i++) { + if (InputManager()) { + InputManager()->AddMouse(mice[i]); + } + } + + SDL_free(mice); + } + } + #ifdef __EMSCRIPTEN__ SDL_AddEventWatch( [](void* userdata, SDL_Event* event) -> bool { @@ -431,6 +456,10 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) return SDL_APP_CONTINUE; } + if (InputManager()) { + InputManager()->UpdateLastInputMethod(event); + } + switch (event->type) { case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: case SDL_EVENT_MOUSE_MOTION: @@ -467,6 +496,7 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) } break; case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + case SDL_EVENT_QUIT: if (!g_closed) { delete g_isle; g_isle = NULL; @@ -490,13 +520,36 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) } break; } - case SDL_EVENT_GAMEPAD_ADDED: - case SDL_EVENT_GAMEPAD_REMOVED: { + case SDL_EVENT_KEYBOARD_ADDED: if (InputManager()) { - InputManager()->GetJoystick(); + InputManager()->AddKeyboard(event->kdevice.which); + } + break; + case SDL_EVENT_KEYBOARD_REMOVED: + if (InputManager()) { + InputManager()->RemoveKeyboard(event->kdevice.which); + } + break; + case SDL_EVENT_MOUSE_ADDED: + if (InputManager()) { + InputManager()->AddMouse(event->mdevice.which); + } + break; + case SDL_EVENT_MOUSE_REMOVED: + if (InputManager()) { + InputManager()->RemoveMouse(event->mdevice.which); + } + break; + case SDL_EVENT_GAMEPAD_ADDED: + if (InputManager()) { + InputManager()->AddJoystick(event->jdevice.which); + } + break; + case SDL_EVENT_GAMEPAD_REMOVED: + if (InputManager()) { + InputManager()->RemoveJoystick(event->jdevice.which); } break; - } case SDL_EVENT_GAMEPAD_BUTTON_DOWN: { switch (event->gbutton.button) { case SDL_GAMEPAD_BUTTON_DPAD_UP: @@ -723,9 +776,6 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) } break; } - case SDL_EVENT_QUIT: - return SDL_APP_SUCCESS; - break; } if (event->user.type == g_legoSdlEvents.m_windowsMessage) { @@ -764,9 +814,31 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) SDL_Log("Game started"); } } - else if (event->user.type == g_legoSdlEvents.m_hitActor && g_isle->GetHaptic()) { - if (InputManager()) { - InputManager()->HandleRumbleEvent(); + else if (event->user.type == g_legoSdlEvents.m_gameEvent) { + auto rumble = [](float p_strength, float p_lowFrequencyRumble, float p_highFrequencyRumble, MxU32 p_milliseconds + ) { + if (g_isle->GetHaptic() && + !InputManager() + ->HandleRumbleEvent(p_strength, p_lowFrequencyRumble, p_highFrequencyRumble, p_milliseconds)) { +// Platform-specific handling +#ifdef __EMSCRIPTEN__ + Emscripten_HandleRumbleEvent(p_lowFrequencyRumble, p_highFrequencyRumble, p_milliseconds); +#endif + } + }; + + switch (event->user.code) { + case e_hitActor: + rumble(0.5f, 0.5f, 0.5f, 700); + break; + case e_skeletonKick: + rumble(0.8f, 0.8f, 0.8f, 2500); + break; + case e_raceFinished: + case e_goodEnding: + case e_badEnding: + rumble(1.0f, 1.0f, 1.0f, 3000); + break; } } @@ -847,6 +919,15 @@ MxResult IsleApp::SetupWindow() #endif window = SDL_CreateWindowWithProperties(props); + + if (m_exclusiveFullScreen && m_fullScreen) { + SDL_DisplayMode closestMode; + SDL_DisplayID displayID = SDL_GetDisplayForWindow(window); + if (SDL_GetClosestFullscreenDisplayMode(displayID, m_xRes, m_yRes, m_frameRate, true, &closestMode)) { + SDL_SetWindowFullscreenMode(window, &closestMode); + } + } + #ifdef MINIWIN m_windowHandle = reinterpret_cast(window); #else @@ -913,10 +994,6 @@ MxResult IsleApp::SetupWindow() MxTransitionManager::configureMxTransitionManager(m_transitionType); RealtimeView::SetUserMaxLOD(m_maxLod); if (LegoOmni::GetInstance()) { - if (LegoOmni::GetInstance()->GetInputManager()) { - LegoOmni::GetInstance()->GetInputManager()->SetUseJoystick(m_useJoystick); - LegoOmni::GetInstance()->GetInputManager()->SetJoystickIndex(m_joystickIndex); - } if (LegoOmni::GetInstance()->GetVideoManager()) { LegoOmni::GetInstance()->GetVideoManager()->SetCursorBitmap(m_cursorCurrentBitmap); } @@ -1003,13 +1080,12 @@ bool IsleApp::LoadConfig() iniparser_set(dict, "isle:Flip Surfaces", m_flipSurfaces ? "true" : "false"); iniparser_set(dict, "isle:Full Screen", m_fullScreen ? "true" : "false"); + iniparser_set(dict, "isle:Exclusive Full Screen", m_exclusiveFullScreen ? "true" : "false"); iniparser_set(dict, "isle:Wide View Angle", m_wideViewAngle ? "true" : "false"); iniparser_set(dict, "isle:3DSound", m_use3dSound ? "true" : "false"); iniparser_set(dict, "isle:Music", m_useMusic ? "true" : "false"); - iniparser_set(dict, "isle:UseJoystick", m_useJoystick ? "true" : "false"); - iniparser_set(dict, "isle:JoystickIndex", SDL_itoa(m_joystickIndex, buf, 10)); SDL_snprintf(buf, sizeof(buf), "%f", m_cursorSensitivity); iniparser_set(dict, "isle:Cursor Sensitivity", buf); @@ -1023,6 +1099,9 @@ bool IsleApp::LoadConfig() iniparser_set(dict, "isle:Transition Type", SDL_itoa(m_transitionType, buf, 10)); iniparser_set(dict, "isle:Touch Scheme", SDL_itoa(m_touchScheme, buf, 10)); iniparser_set(dict, "isle:Haptic", m_haptic ? "true" : "false"); + iniparser_set(dict, "isle:Horizontal Resolution", SDL_itoa(m_xRes, buf, 10)); + iniparser_set(dict, "isle:Vertical Resolution", SDL_itoa(m_yRes, buf, 10)); + iniparser_set(dict, "isle:Frame Delta", SDL_itoa(m_frameDelta, buf, 10)); #ifdef EXTENSIONS iniparser_set(dict, "extensions", NULL); @@ -1065,11 +1144,10 @@ bool IsleApp::LoadConfig() m_flipSurfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flipSurfaces); m_fullScreen = iniparser_getboolean(dict, "isle:Full Screen", m_fullScreen); + m_exclusiveFullScreen = iniparser_getboolean(dict, "isle:Exclusive Full Screen", m_exclusiveFullScreen); m_wideViewAngle = iniparser_getboolean(dict, "isle:Wide View Angle", m_wideViewAngle); m_use3dSound = iniparser_getboolean(dict, "isle:3DSound", m_use3dSound); m_useMusic = iniparser_getboolean(dict, "isle:Music", m_useMusic); - m_useJoystick = iniparser_getboolean(dict, "isle:UseJoystick", m_useJoystick); - m_joystickIndex = iniparser_getint(dict, "isle:JoystickIndex", m_joystickIndex); m_cursorSensitivity = iniparser_getdouble(dict, "isle:Cursor Sensitivity", m_cursorSensitivity); MxS32 backBuffersInVRAM = iniparser_getboolean(dict, "isle:Back Buffers in Video RAM", -1); @@ -1095,6 +1173,13 @@ bool IsleApp::LoadConfig() (MxTransitionManager::TransitionType) iniparser_getint(dict, "isle:Transition Type", m_transitionType); m_touchScheme = (LegoInputManager::TouchScheme) iniparser_getint(dict, "isle:Touch Scheme", m_touchScheme); m_haptic = iniparser_getboolean(dict, "isle:Haptic", m_haptic); + m_xRes = iniparser_getint(dict, "isle:Horizontal Resolution", m_xRes); + m_yRes = iniparser_getint(dict, "isle:Vertical Resolution", m_yRes); + if (!m_fullScreen) { + m_videoParam.GetRect() = MxRect32(0, 0, (m_xRes - 1), (m_yRes - 1)); + } + m_frameRate = (1000.0f / iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta)); + m_frameDelta = static_cast(std::round(iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta))); const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL); if (deviceId != NULL) { @@ -1273,7 +1358,7 @@ void IsleApp::SetupCursor(Cursor p_cursor) } } -MxResult IsleApp::ParseArguments(int argc, char** argv) +SDL_AppResult IsleApp::ParseArguments(int argc, char** argv) { for (int i = 1, consumed; i < argc; i += consumed) { consumed = -1; @@ -1290,13 +1375,29 @@ MxResult IsleApp::ParseArguments(int argc, char** argv) #endif consumed = 1; } + else if (strcmp(argv[i], "--help") == 0) { + DisplayArgumentHelp(); + return SDL_APP_SUCCESS; + } if (consumed <= 0) { SDL_Log("Invalid argument(s): %s", argv[i]); - return FAILURE; + DisplayArgumentHelp(); + return SDL_APP_FAILURE; } } - return SUCCESS; + return SDL_APP_CONTINUE; +} + +void IsleApp::DisplayArgumentHelp() +{ + SDL_Log("Usage: isle [options]"); + SDL_Log("Options:"); + SDL_Log(" --ini Set custom path to .ini config"); +#ifdef ISLE_DEBUG + SDL_Log(" --debug Launch in debug mode"); +#endif + SDL_Log(" --help Show this help message"); } MxResult IsleApp::VerifyFilesystem() diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 4bec7dd6..4a23ea23 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -61,7 +61,7 @@ class IsleApp { void SetGameStarted(MxS32 p_gameStarted) { m_gameStarted = p_gameStarted; } void SetDrawCursor(MxS32 p_drawCursor) { m_drawCursor = p_drawCursor; } - MxResult ParseArguments(int argc, char** argv); + SDL_AppResult ParseArguments(int argc, char** argv); MxResult VerifyFilesystem(); void DetectGameVersion(); void MoveVirtualMouseViaJoystick(); @@ -72,7 +72,7 @@ class IsleApp { char* m_cdPath; // 0x04 char* m_deviceId; // 0x08 char* m_savePath; // 0x0c - MxS32 m_fullScreen; // 0x10 + MxBool m_fullScreen; // 0x10 MxS32 m_flipSurfaces; // 0x14 MxS32 m_backBuffersInVram; // 0x18 MxS32 m_using8bit; // 0x1c @@ -80,8 +80,6 @@ class IsleApp { MxS32 m_hasLightSupport; // 0x24 MxS32 m_use3dSound; // 0x28 MxS32 m_useMusic; // 0x2c - MxS32 m_useJoystick; // 0x30 - MxS32 m_joystickIndex; // 0x34 MxS32 m_wideViewAngle; // 0x38 MxS32 m_islandQuality; // 0x3c MxS32 m_islandTexture; // 0x40 @@ -101,6 +99,7 @@ class IsleApp { const CursorBitmap* m_cursorCurrentBitmap; char* m_mediaPath; MxFloat m_cursorSensitivity; + void DisplayArgumentHelp(); char* m_iniPath; MxFloat m_maxLod; @@ -108,6 +107,10 @@ class IsleApp { MxTransitionManager::TransitionType m_transitionType; LegoInputManager::TouchScheme m_touchScheme; MxBool m_haptic; + MxS32 m_xRes; + MxS32 m_yRes; + MxFloat m_frameRate; + MxBool m_exclusiveFullScreen; }; extern IsleApp* g_isle; diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h index 38e2876e..28129b4b 100644 --- a/LEGO1/lego/legoomni/include/act3.h +++ b/LEGO1/lego/legoomni/include/act3.h @@ -20,12 +20,12 @@ class MxQuaternionTransformer; struct Act3ListElement { MxU32 m_objectId; // 0x00 undefined4 m_unk0x04; // 0x04 - undefined m_unk0x08; // 0x08 + MxBool m_hasStarted; // 0x08 Act3ListElement() {} - Act3ListElement(MxU32 p_objectId, undefined4 p_unk0x04, undefined p_unk0x08) - : m_objectId(p_objectId), m_unk0x04(p_unk0x04), m_unk0x08(p_unk0x08) + Act3ListElement(MxU32 p_objectId, undefined4 p_unk0x04, MxBool p_hasStarted) + : m_objectId(p_objectId), m_unk0x04(p_unk0x04), m_hasStarted(p_hasStarted) { } @@ -36,12 +36,18 @@ struct Act3ListElement { // SIZE 0x10 class Act3List : private list { public: + enum InsertMode { + e_replaceAction = 1, + e_queueAction = 2, + e_onlyIfEmpty = 3 + }; + Act3List() { m_unk0x0c = 0; } - void Insert(MxS32 p_objectId, MxS32 p_option); - void FUN_10071fa0(); + void Insert(MxS32 p_objectId, InsertMode p_option); + void DeleteActionWrapper(); void Clear(); - void FUN_100720d0(MxU32 p_objectId); + void RemoveByObjectIdOrFirst(MxU32 p_objectId); private: undefined4 m_unk0x0c; // 0x0c diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index 2c6c8091..53edd931 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -34,6 +34,21 @@ class Act1State : public LegoState { c_floor3 }; + enum { + e_none = 0, + e_initial = 1, + e_elevator = 2, + e_pizza = 3, + e_helicopter = 4, + e_transitionToJetski = 5, + e_transitionToRacecar = 6, + e_transitionToTowtrack = 7, + e_towtrack = 8, + e_transitionToAmbulance = 9, + e_ambulance = 10, + e_jukebox = 11, + }; + Act1State(); // FUNCTION: LEGO1 0x100338a0 @@ -58,11 +73,11 @@ class Act1State : public LegoState { void RemoveActors(); void PlaceActors(); - MxU32 GetUnknown18() { return m_unk0x018; } + MxU32 GetState() { return m_state; } ElevatorFloor GetElevatorFloor() { return (ElevatorFloor) m_elevFloor; } MxU8 GetUnknown21() { return m_unk0x021; } - void SetUnknown18(MxU32 p_unk0x18) { m_unk0x018 = p_unk0x18; } + void SetState(MxU32 p_state) { m_state = p_state; } void SetElevatorFloor(ElevatorFloor p_elevFloor) { m_elevFloor = p_elevFloor; } void SetUnknown21(MxU8 p_unk0x21) { m_unk0x021 = p_unk0x21; } @@ -73,7 +88,7 @@ class Act1State : public LegoState { Playlist m_cptClickDialogue; // 0x008 IsleScript::Script m_currentCptClickDialogue; // 0x014 - MxU32 m_unk0x018; // 0x018 + MxU32 m_state; // 0x018 MxS16 m_elevFloor; // 0x01c MxBool m_unk0x01e; // 0x01e MxBool m_unk0x01f; // 0x01f diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index a3d6cd60..802e8917 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -92,7 +92,11 @@ class LegoAnimPresenter : public MxVideoPresenter { const char* GetActionObjectName(); void SetCurrentWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } + + // FUNCTION: BETA10 0x1005aad0 void SetUnknown0x0cTo1() { m_unk0x9c = 1; } + + // FUNCTION: BETA10 0x1005ab00 void SetUnknown0xa0(Matrix4* p_unk0xa0) { m_unk0xa0 = p_unk0xa0; } LegoAnim* GetAnimation() { return m_anim; } diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index ee87b50a..04ac7294 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -8,6 +8,7 @@ #include "mxpresenter.h" #include "mxqueue.h" +#include #include #include #include @@ -19,6 +20,7 @@ #endif #include +#include class LegoCameraController; class LegoControlManager; @@ -92,6 +94,7 @@ class LegoInputManager : public MxPresenter { }; enum TouchScheme { + e_none = -1, e_mouse = 0, e_arrowKeys, e_gamepad, @@ -129,9 +132,8 @@ class LegoInputManager : public MxPresenter { void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; } void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; } void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; } - void SetUseJoystick(MxBool p_useJoystick) { m_useJoystick = p_useJoystick; } - void SetJoystickIndex(MxS32 p_joystickIndex) { m_joystickIndex = p_joystickIndex; } + // FUNCTION: BETA10 0x1002e290 void DisableInputProcessing() { m_unk0x88 = TRUE; @@ -152,13 +154,31 @@ class LegoInputManager : public MxPresenter { void GetKeyboardState(); MxResult GetNavigationKeyStates(MxU32& p_keyFlags); MxResult GetNavigationTouchStates(MxU32& p_keyFlags); + LEGO1_EXPORT void AddKeyboard(SDL_KeyboardID p_keyboardID); + LEGO1_EXPORT void RemoveKeyboard(SDL_KeyboardID p_keyboardID); + LEGO1_EXPORT void AddMouse(SDL_MouseID p_mouseID); + LEGO1_EXPORT void RemoveMouse(SDL_MouseID p_mouseID); + LEGO1_EXPORT void AddJoystick(SDL_JoystickID p_joystickID); + LEGO1_EXPORT void RemoveJoystick(SDL_JoystickID p_joystickID); LEGO1_EXPORT MxBool HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme); - LEGO1_EXPORT MxBool HandleRumbleEvent(); + LEGO1_EXPORT MxBool + HandleRumbleEvent(float p_strength, float p_lowFrequencyRumble, float p_highFrequencyRumble, MxU32 p_milliseconds); + LEGO1_EXPORT void UpdateLastInputMethod(SDL_Event* p_event); + const auto& GetLastInputMethod() { return m_lastInputMethod; } + + // clang-format off + enum class SDL_KeyboardID_v : SDL_KeyboardID {}; + enum class SDL_MouseID_v : SDL_MouseID {}; + enum class SDL_JoystickID_v : SDL_JoystickID {}; + enum class SDL_TouchID_v : SDL_TouchID {}; + // clang-format on // SYNTHETIC: LEGO1 0x1005b8d0 // LegoInputManager::`scalar deleting destructor' private: + void InitializeHaptics(); + MxCriticalSection m_criticalSection; // 0x58 LegoNotifyList* m_keyboardNotifyList; // 0x5c LegoCameraController* m_camera; // 0x60 @@ -175,16 +195,18 @@ class LegoInputManager : public MxPresenter { MxBool m_unk0x88; // 0x88 const bool* m_keyboardState; MxBool m_unk0x195; // 0x195 - SDL_JoystickID* m_joyids; - SDL_Gamepad* m_joystick; - MxS32 m_joystickIndex; // 0x19c - MxBool m_useJoystick; // 0x334 - MxBool m_unk0x335; // 0x335 - MxBool m_unk0x336; // 0x336 + MxBool m_unk0x335; // 0x335 + MxBool m_unk0x336; // 0x336 - std::map m_touchOrigins; + TouchScheme m_touchScheme = e_none; + SDL_Point m_touchVirtualThumb = {0, 0}; + SDL_FPoint m_touchVirtualThumbOrigin; std::map m_touchFlags; - std::map> m_touchLastMotion; + std::map> m_keyboards; + std::map> m_mice; + std::map> m_joysticks; + std::map m_otherHaptics; + std::variant m_lastInputMethod; }; // TEMPLATE: LEGO1 0x10028850 diff --git a/LEGO1/lego/legoomni/include/legomain.h b/LEGO1/lego/legoomni/include/legomain.h index c27be280..90196e6a 100644 --- a/LEGO1/lego/legoomni/include/legomain.h +++ b/LEGO1/lego/legoomni/include/legomain.h @@ -134,7 +134,7 @@ class LegoOmni : public MxOmni { LegoROI* FindROI(const char* p_name); void AddWorld(LegoWorld* p_world); void DeleteWorld(LegoWorld* p_world); - void FUN_1005b4f0(MxBool p_disable, MxU16 p_flags); + void Disable(MxBool p_disable, MxU16 p_flags); LEGO1_EXPORT void CreateBackgroundAudio(); LEGO1_EXPORT void RemoveWorld(const MxAtomId& p_atom, MxLong p_objectId); MxResult RegisterWorlds(); diff --git a/LEGO1/lego/legoomni/include/legopartpresenter.h b/LEGO1/lego/legoomni/include/legopartpresenter.h index 7ff7692d..3c3fc2f1 100644 --- a/LEGO1/lego/legoomni/include/legopartpresenter.h +++ b/LEGO1/lego/legoomni/include/legopartpresenter.h @@ -4,6 +4,7 @@ #include "lego1_export.h" #include "legonamedpartlist.h" #include "mxmediapresenter.h" +#include "viewmanager/viewlodlist.h" // VTABLE: LEGO1 0x100d4df0 // SIZE 0x54 @@ -50,10 +51,21 @@ class LegoPartPresenter : public MxMediaPresenter { MxResult Read(MxDSChunk& p_chunk); void Store(); + static void Release() + { + for (auto* lodList : g_lodLists) { + lodList->Release(); + } + + g_lodLists.clear(); + } + private: void Destroy(MxBool p_fromDestructor); LegoNamedPartList* m_parts; // 0x50 + + static vector g_lodLists; }; #endif // LEGOPARTPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legophonemepresenter.h b/LEGO1/lego/legoomni/include/legophonemepresenter.h index e470f6b7..4a6a3c05 100644 --- a/LEGO1/lego/legoomni/include/legophonemepresenter.h +++ b/LEGO1/lego/legoomni/include/legophonemepresenter.h @@ -42,9 +42,9 @@ class LegoPhonemePresenter : public MxFlcPresenter { MxS32 m_rectCount; // 0x68 LegoTextureInfo* m_textureInfo; // 0x6c - MxBool m_unk0x70; // 0x70 + MxBool m_reusedPhoneme; // 0x70 MxString m_roiName; // 0x74 - MxBool m_unk0x84; // 0x84 + MxBool m_isPartOfAnimMM; // 0x84 }; // TEMPLATE: LEGO1 0x1004eb20 diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index b29a336c..849662df 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -32,6 +32,14 @@ enum Cursor { e_cursorNone }; +enum GameEvent { + e_hitActor, + e_skeletonKick, + e_raceFinished, + e_badEnding, + e_goodEnding +}; + class BoundingSphere; class MxAtomId; class LegoEntity; @@ -71,7 +79,7 @@ LegoNamedTexture* ReadNamedTexture(LegoStorage* p_storage); void WriteDefaultTexture(LegoStorage* p_storage, const char* p_name); void WriteNamedTexture(LegoStorage* p_storage, LegoNamedTexture* p_namedTexture); void LoadFromNamedTexture(LegoNamedTexture* p_namedTexture); -void HitActorEvent(); +void EmitGameEvent(GameEvent p_event); // FUNCTION: BETA10 0x100260a0 inline void StartIsleAction(IsleScript::Script p_objectId) diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index ba96541c..ff5f9ae3 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -70,7 +70,9 @@ class LegoVideoManager : public MxVideoManager { MxBool GetRender3D() { return m_render3d; } double GetElapsedSeconds() { return m_elapsedSeconds; } + // FUNCTION: BETA10 0x1002e290 void SetRender3D(MxBool p_render3d) { m_render3d = p_render3d; } + void SetUnk0x554(MxBool p_unk0x554) { m_unk0x554 = p_unk0x554; } private: diff --git a/LEGO1/lego/legoomni/include/misc.h b/LEGO1/lego/legoomni/include/misc.h index b9f0fb5f..1df9fe37 100644 --- a/LEGO1/lego/legoomni/include/misc.h +++ b/LEGO1/lego/legoomni/include/misc.h @@ -49,7 +49,7 @@ LegoPlantManager* PlantManager(); LegoBuildingManager* BuildingManager(); LegoTextureContainer* TextureContainer(); ViewLODListManager* GetViewLODListManager(); -void FUN_10015820(MxBool p_disable, MxU16 p_flags); +void Disable(MxBool p_disable, MxU16 p_flags); LegoROI* FindROI(const char* p_name); void SetROIVisible(const char* p_name, MxBool p_visible); void SetUserActor(LegoPathActor* p_userActor); diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h index 812751bf..e9e41418 100644 --- a/LEGO1/lego/legoomni/include/towtrack.h +++ b/LEGO1/lego/legoomni/include/towtrack.h @@ -12,6 +12,13 @@ class MxEndActionNotificationParam; // SIZE 0x28 class TowTrackMissionState : public LegoState { public: + enum { + e_none = 0, + e_started = 1, + e_hookedUp = 2, + e_hookingUp = 3, + }; + TowTrackMissionState(); // FUNCTION: LEGO1 0x1004dde0 @@ -126,19 +133,19 @@ class TowTrackMissionState : public LegoState { // SYNTHETIC: LEGO1 0x1004e060 // TowTrackMissionState::`scalar deleting destructor' - undefined4 m_unk0x08; // 0x08 - MxLong m_startTime; // 0x0c - MxBool m_unk0x10; // 0x10 - MxS16 m_peScore; // 0x12 - MxS16 m_maScore; // 0x14 - MxS16 m_paScore; // 0x16 - MxS16 m_niScore; // 0x18 - MxS16 m_laScore; // 0x1a - MxS16 m_peHighScore; // 0x1c - MxS16 m_maHighScore; // 0x1e - MxS16 m_paHighScore; // 0x20 - MxS16 m_niHighScore; // 0x22 - MxS16 m_laHighScore; // 0x24 + MxU32 m_state; // 0x08 + MxLong m_startTime; // 0x0c + MxBool m_takingTooLong; // 0x10 + MxS16 m_peScore; // 0x12 + MxS16 m_maScore; // 0x14 + MxS16 m_paScore; // 0x16 + MxS16 m_niScore; // 0x18 + MxS16 m_laScore; // 0x1a + MxS16 m_peHighScore; // 0x1c + MxS16 m_maHighScore; // 0x1e + MxS16 m_paHighScore; // 0x20 + MxS16 m_niHighScore; // 0x22 + MxS16 m_laHighScore; // 0x24 }; // VTABLE: LEGO1 0x100d7ee0 @@ -174,10 +181,10 @@ class TowTrack : public IslePathActor { virtual MxLong HandleEndAction(MxEndActionNotificationParam& p_param); // vtable+0xf0 void CreateState(); - void FUN_1004dab0(); + void Init(); void ActivateSceneActions(); void StopActions(); - void FUN_1004dbe0(); + void Reset(); // SYNTHETIC: LEGO1 0x1004c950 // TowTrack::`scalar deleting destructor' @@ -192,8 +199,8 @@ class TowTrack : public IslePathActor { TowTrackMissionState* m_state; // 0x164 MxS16 m_unk0x168; // 0x168 MxS16 m_actorId; // 0x16a - MxS16 m_unk0x16c; // 0x16c - MxS16 m_unk0x16e; // 0x16e + MxS16 m_treeBlockageTriggered; // 0x16c + MxS16 m_speedComplaintTriggered; // 0x16e IsleScript::Script m_lastAction; // 0x170 IsleScript::Script m_lastAnimation; // 0x174 MxFloat m_fuel; // 0x178 diff --git a/LEGO1/lego/legoomni/src/actors/act2actor.cpp b/LEGO1/lego/legoomni/src/actors/act2actor.cpp index 726f3838..799b196a 100644 --- a/LEGO1/lego/legoomni/src/actors/act2actor.cpp +++ b/LEGO1/lego/legoomni/src/actors/act2actor.cpp @@ -631,7 +631,7 @@ MxU32 Act2Actor::FUN_10019700(MxFloat p_param) MxFloat time = p_param - (m_unk0x2c - m_shootAnim->GetDuration()); for (MxS32 i = 0; i < root->GetNumChildren(); i++) { - LegoROI::FUN_100a8e80(root->GetChild(i), matrix, time, m_shootAnim->GetROIMap()); + LegoROI::ApplyAnimationTransformation(root->GetChild(i), matrix, time, m_shootAnim->GetROIMap()); } return FALSE; diff --git a/LEGO1/lego/legoomni/src/actors/act3actors.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp index 89bdc5fc..63088156 100644 --- a/LEGO1/lego/legoomni/src/actors/act3actors.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp @@ -639,7 +639,7 @@ void Act3Brickster::Animate(float p_time) float time = p_time - (m_unk0x50 - m_shootAnim->GetDuration()); for (MxS32 i = 0; i < root->GetNumChildren(); i++) { - LegoROI::FUN_100a8e80(root->GetChild(i), local70, time, m_shootAnim->GetROIMap()); + LegoROI::ApplyAnimationTransformation(root->GetChild(i), local70, time, m_shootAnim->GetROIMap()); } } @@ -686,7 +686,7 @@ void Act3Brickster::Animate(float p_time) float time = p_time - (m_unk0x50 - m_shootAnim->GetDuration()); for (MxS32 i = 0; i < root->GetNumChildren(); i++) { - LegoROI::FUN_100a8e80(root->GetChild(i), locale4, time, m_shootAnim->GetROIMap()); + LegoROI::ApplyAnimationTransformation(root->GetChild(i), locale4, time, m_shootAnim->GetROIMap()); } } @@ -1187,7 +1187,7 @@ void Act3Shark::Animate(float p_time) vec = m_unk0x3c; LegoTreeNode* node = m_unk0x34->GetAnimTreePtr()->GetRoot(); - LegoROI::FUN_100a8e80(node, mat, duration, m_unk0x34->GetROIMap()); + LegoROI::ApplyAnimationTransformation(node, mat, duration, m_unk0x34->GetROIMap()); } else { roiMap[1] = m_unk0x38; diff --git a/LEGO1/lego/legoomni/src/actors/ambulance.cpp b/LEGO1/lego/legoomni/src/actors/ambulance.cpp index ff87c657..23c9164d 100644 --- a/LEGO1/lego/legoomni/src/actors/ambulance.cpp +++ b/LEGO1/lego/legoomni/src/actors/ambulance.cpp @@ -367,7 +367,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructNotificationParam& p_param) // FUNCTION: BETA10 0x10023506 MxLong Ambulance::HandleClick() { - if (((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 != 10) { + if (((Act1State*) GameState()->GetState("Act1State"))->m_state != Act1State::e_ambulance) { return 1; } @@ -375,7 +375,7 @@ MxLong Ambulance::HandleClick() return 1; } - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_ambulance); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); @@ -578,7 +578,7 @@ void Ambulance::Reset() { StopAction(m_lastAction); BackgroundAudioManager()->RaiseVolume(); - ((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0; + ((Act1State*) GameState()->GetState("Act1State"))->m_state = Act1State::e_none; m_state->m_state = AmbulanceMissionState::e_ready; m_atBeachTask = 0; m_atPoliceTask = 0; diff --git a/LEGO1/lego/legoomni/src/actors/bike.cpp b/LEGO1/lego/legoomni/src/actors/bike.cpp index 6c82cb0d..fa9bedcb 100644 --- a/LEGO1/lego/legoomni/src/actors/bike.cpp +++ b/LEGO1/lego/legoomni/src/actors/bike.cpp @@ -54,7 +54,7 @@ MxLong Bike::HandleClick() { if (CanExit()) { Act1State* state = (Act1State*) GameState()->GetState("Act1State"); - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::Area::e_bike); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, TRUE); diff --git a/LEGO1/lego/legoomni/src/actors/buildings.cpp b/LEGO1/lego/legoomni/src/actors/buildings.cpp index 833287bc..b9e736c4 100644 --- a/LEGO1/lego/legoomni/src/actors/buildings.cpp +++ b/LEGO1/lego/legoomni/src/actors/buildings.cpp @@ -53,7 +53,7 @@ MxLong InfoCenterEntity::HandleClick(LegoEventNotificationParam& p_param) isle->SetDestLocation(LegoGameState::Area::e_infomain); Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); - act1state->SetUnknown18(0); + act1state->SetState(Act1State::e_none); break; } case LegoGameState::Act::e_act2: { @@ -83,8 +83,8 @@ MxLong GasStationEntity::HandleClick(LegoEventNotificationParam& p_param) if (CanExit()) { Act1State* state = (Act1State*) GameState()->GetState("Act1State"); - if (state->GetUnknown18() != 8) { - state->SetUnknown18(0); + if (state->GetState() != Act1State::e_towtrack) { + state->SetState(Act1State::e_none); if (UserActor()->GetActorId() != GameState()->GetActorId()) { ((IslePathActor*) UserActor())->Exit(); @@ -107,8 +107,8 @@ MxLong HospitalEntity::HandleClick(LegoEventNotificationParam& p_param) if (CanExit()) { Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); - if (act1State->GetUnknown18() != 10) { - act1State->SetUnknown18(0); + if (act1State->GetState() != Act1State::e_ambulance) { + act1State->SetState(Act1State::e_none); if (UserActor()->GetActorId() != GameState()->GetActorId()) { ((IslePathActor*) UserActor())->Exit(); @@ -131,8 +131,8 @@ MxLong PoliceEntity::HandleClick(LegoEventNotificationParam& p_param) if (CanExit()) { Act1State* state = (Act1State*) GameState()->GetState("Act1State"); - if (state->GetUnknown18() != 10) { - state->SetUnknown18(0); + if (state->GetState() != Act1State::e_ambulance) { + state->SetState(Act1State::e_none); if (UserActor()->GetActorId() != GameState()->GetActorId()) { ((IslePathActor*) UserActor())->Exit(); @@ -154,7 +154,7 @@ MxLong BeachHouseEntity::HandleClick(LegoEventNotificationParam& p_param) { if (CanExit()) { Act1State* state = (Act1State*) GameState()->GetState("Act1State"); - state->SetUnknown18(0); + state->SetState(Act1State::e_none); if (UserActor()->GetActorId() != GameState()->GetActorId()) { ((IslePathActor*) UserActor())->Exit(); @@ -175,7 +175,7 @@ MxLong RaceStandsEntity::HandleClick(LegoEventNotificationParam& p_param) { if (CanExit()) { Act1State* state = (Act1State*) GameState()->GetState("Act1State"); - state->SetUnknown18(0); + state->SetState(Act1State::e_none); if (UserActor()->GetActorId() != GameState()->GetActorId()) { ((IslePathActor*) UserActor())->Exit(); diff --git a/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp b/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp index 371e4257..03c93f7b 100644 --- a/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp +++ b/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp @@ -45,7 +45,7 @@ MxLong BumpBouy::Notify(MxParam& p_param) Act1State* isleState = (Act1State*) GameState()->GetState("Act1State"); assert(isleState); - isleState->m_unk0x018 = 5; + isleState->m_state = Act1State::e_transitionToJetski; Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle); assert(isle); diff --git a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp index 59bac080..0c398393 100644 --- a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp +++ b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp @@ -95,7 +95,7 @@ MxLong DuneBuggy::HandleClick() return 1; } - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::Area::e_dunecar); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, TRUE); diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index c8c465f7..46353585 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -148,7 +148,7 @@ MxLong Helicopter::HandleClick() IslePathActor::c_spawnBit1 | IslePathActor::c_playMusic | IslePathActor::c_spawnBit3 ); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_copter); - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, TRUE); SetActorState(c_disabled); PlayMusic(JukeboxScript::c_Jail_Music); @@ -214,7 +214,7 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); assert(act1State); if (m_state->m_unk0x08 == 0) { - act1State->m_unk0x018 = 4; + act1State->m_state = Act1State::e_helicopter; m_state->m_unk0x08 = 1; m_world->RemoveActor(this); InvokeAction(Extra::ActionType::e_start, script, IsleScript::c_HelicopterTakeOff_Anim, NULL); @@ -318,7 +318,7 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param) if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); assert(act1State); - act1State->m_unk0x018 = 4; + act1State->m_state = Act1State::e_helicopter; SpawnPlayer( LegoGameState::e_unk42, TRUE, @@ -359,7 +359,7 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param) if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); assert(act1State); - act1State->m_unk0x018 = 0; + act1State->m_state = Act1State::e_none; SpawnPlayer( LegoGameState::e_unk41, TRUE, diff --git a/LEGO1/lego/legoomni/src/actors/jetski.cpp b/LEGO1/lego/legoomni/src/actors/jetski.cpp index 2ef3a547..43c8040c 100644 --- a/LEGO1/lego/legoomni/src/actors/jetski.cpp +++ b/LEGO1/lego/legoomni/src/actors/jetski.cpp @@ -87,7 +87,7 @@ MxLong Jetski::HandleClick() return 1; } - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::Area::e_jetski); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, TRUE); @@ -164,7 +164,7 @@ void Jetski::ActivateSceneActions() PlayMusic(JukeboxScript::c_JetskiRace_Music); Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); - if (!act1state->m_unk0x018) { + if (!act1state->m_state) { if (act1state->m_unk0x022) { PlayCamAnim(this, FALSE, 68, TRUE); } diff --git a/LEGO1/lego/legoomni/src/actors/motorcycle.cpp b/LEGO1/lego/legoomni/src/actors/motorcycle.cpp index eaaa90be..9d17be8d 100644 --- a/LEGO1/lego/legoomni/src/actors/motorcycle.cpp +++ b/LEGO1/lego/legoomni/src/actors/motorcycle.cpp @@ -90,7 +90,7 @@ MxLong Motocycle::HandleClick() return 1; } - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::Area::e_motocycle); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, TRUE); diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 18da7fca..422cf87f 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -182,7 +182,7 @@ void Pizza::FUN_10038220(IsleScript::Script p_objectId) AnimationManager()->FUN_10064740(NULL); m_mission = m_state->GetMission(GameState()->GetActorId()); m_state->m_unk0x0c = 1; - m_act1state->m_unk0x018 = 3; + m_act1state->m_state = Act1State::e_pizza; m_mission->m_startTime = INT_MIN; g_isleFlags &= ~Isle::c_playMusic; AnimationManager()->EnableCamAnims(FALSE); @@ -200,7 +200,7 @@ void Pizza::FUN_100382b0() InvokeAction(Extra::e_stop, *g_isleScript, m_speechAction, NULL); } - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; m_state->m_unk0x0c = 0; UserActor()->SetActorState(LegoPathActor::c_initial); g_isleFlags |= Isle::c_playMusic; @@ -245,7 +245,7 @@ MxLong Pizza::HandleClick() } if (m_state->m_unk0x0c == 2) { - m_act1state->m_unk0x018 = 3; + m_act1state->m_state = Act1State::e_pizza; if (m_skateBoard == NULL) { m_skateBoard = (SkateBoard*) m_world->Find(m_atomId, IsleScript::c_SkateBoard_Actor); @@ -558,7 +558,7 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param) break; case 8: if (m_state->GetPlayedAction() == objectId) { - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; m_state->m_unk0x0c = 0; GameState()->m_currentArea = LegoGameState::e_isle; TickleManager()->UnregisterClient(this); diff --git a/LEGO1/lego/legoomni/src/actors/skateboard.cpp b/LEGO1/lego/legoomni/src/actors/skateboard.cpp index 0998ba58..d47b2178 100644 --- a/LEGO1/lego/legoomni/src/actors/skateboard.cpp +++ b/LEGO1/lego/legoomni/src/actors/skateboard.cpp @@ -56,7 +56,7 @@ MxResult SkateBoard::Create(MxDSAction& p_dsAction) // FUNCTION: LEGO1 0x10010050 void SkateBoard::Exit() { - if (m_act1state->m_unk0x018 == 3) { + if (m_act1state->m_state == Act1State::e_pizza) { Pizza* pizza = (Pizza*) CurrentWorld()->Find(*g_isleScript, IsleScript::c_Pizza_Actor); pizza->StopActions(); pizza->FUN_100382b0(); @@ -75,11 +75,11 @@ MxLong SkateBoard::HandleClick() { Act1State* state = (Act1State*) GameState()->GetState("Act1State"); - if (!CanExit() && state->m_unk0x018 != 3) { + if (!CanExit() && state->m_state != Act1State::e_pizza) { return 1; } - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::Area::e_skateboard); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, TRUE); @@ -148,7 +148,7 @@ MxLong SkateBoard::HandleNotification0() // FUNCTION: LEGO1 0x10010510 void SkateBoard::ActivateSceneActions() { - if (m_act1state->m_unk0x018 != 3) { + if (m_act1state->m_state != Act1State::e_pizza) { PlayMusic(JukeboxScript::c_BeachBlvd_Music); if (!m_act1state->m_unk0x022) { diff --git a/LEGO1/lego/legoomni/src/actors/towtrack.cpp b/LEGO1/lego/legoomni/src/actors/towtrack.cpp index 6143ccf8..462905d4 100644 --- a/LEGO1/lego/legoomni/src/actors/towtrack.cpp +++ b/LEGO1/lego/legoomni/src/actors/towtrack.cpp @@ -34,9 +34,9 @@ TowTrack::TowTrack() m_unk0x168 = 0; m_actorId = -1; m_state = NULL; - m_unk0x16c = 0; + m_treeBlockageTriggered = 0; m_lastAction = IsleScript::c_noneIsle; - m_unk0x16e = 0; + m_speedComplaintTriggered = 0; m_lastAnimation = IsleScript::c_noneIsle; m_maxLinearVel = 40.0; m_fuel = 1.0; @@ -64,7 +64,7 @@ MxResult TowTrack::Create(MxDSAction& p_dsAction) m_state = (TowTrackMissionState*) GameState()->GetState("TowTrackMissionState"); if (!m_state) { m_state = new TowTrackMissionState(); - m_state->m_unk0x08 = 0; + m_state->m_state = TowTrackMissionState::e_none; GameState()->RegisterState(m_state); } } @@ -98,9 +98,10 @@ void TowTrack::Animate(float p_time) sprintf(buf, "%g", m_fuel); VariableTable()->SetVariable(g_varTOWFUEL, buf); - if (p_time - m_state->m_startTime > 100000.0f && m_state->m_unk0x08 == 1 && !m_state->m_unk0x10) { + if (p_time - m_state->m_startTime > 100000.0f && m_state->m_state == TowTrackMissionState::e_started && + !m_state->m_takingTooLong) { PlayAction(IsleScript::c_Avo909In_PlayWav); - m_state->m_unk0x10 = TRUE; + m_state->m_takingTooLong = TRUE; } } } @@ -190,7 +191,7 @@ MxLong TowTrack::HandleEndAction(MxEndActionNotificationParam& p_param) } } else if (objectId == IsleScript::c_wrt074sl_RunAnim || objectId == IsleScript::c_wrt075rh_RunAnim || objectId == IsleScript::c_wrt076df_RunAnim || objectId == IsleScript::c_wrt078ni_RunAnim) { - m_state->m_unk0x08 = 2; + m_state->m_state = TowTrackMissionState::e_hookedUp; CurrentWorld()->PlaceActor(UserActor()); HandleClick(); } @@ -274,7 +275,7 @@ MxLong TowTrack::HandleEndAction(MxEndActionNotificationParam& p_param) m_state->UpdateScore(LegoState::e_yellow, m_actorId); } else if (objectId == IsleScript::c_wgs098nu_RunAnim || objectId == IsleScript::c_wgs099nu_RunAnim || objectId == IsleScript::c_wgs100nu_RunAnim || objectId == IsleScript::c_wgs101nu_RunAnim || objectId == IsleScript::c_wgs102nu_RunAnim || objectId == IsleScript::c_wgs085nu_RunAnim || objectId == IsleScript::c_wgs086nu_RunAnim || objectId == IsleScript::c_wgs087nu_RunAnim || objectId == IsleScript::c_wgs088nu_RunAnim || objectId == IsleScript::c_wgs089nu_RunAnim || objectId == IsleScript::c_wgs091nu_RunAnim || objectId == IsleScript::c_wgs092nu_RunAnim || objectId == IsleScript::c_wgs093nu_RunAnim || objectId == IsleScript::c_wgs094nu_RunAnim || objectId == IsleScript::c_wgs095nu_RunAnim) { - ((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0; + ((Act1State*) GameState()->GetState("Act1State"))->m_state = Act1State::e_none; AnimationManager()->FUN_1005f6d0(TRUE); g_isleFlags |= Isle::c_playMusic; AnimationManager()->EnableCamAnims(TRUE); @@ -299,10 +300,10 @@ MxLong TowTrack::HandlePathStruct(LegoPathStructNotificationParam& p_param) return 0; } - if (m_state->m_unk0x08 == 2 && + if (m_state->m_state == TowTrackMissionState::e_hookedUp && ((p_param.GetTrigger() == LegoPathStruct::c_camAnim && (p_param.GetData() == 9 || p_param.GetData() == 8)) || (p_param.GetTrigger() == LegoPathStruct::c_w && p_param.GetData() == 0x169))) { - m_state->m_unk0x08 = 0; + m_state->m_state = TowTrackMissionState::e_none; MxLong time = Timer()->GetTime() - m_state->m_startTime; Leave(); @@ -317,8 +318,8 @@ MxLong TowTrack::HandlePathStruct(LegoPathStructNotificationParam& p_param) PlayFinalAnimation(IsleScript::c_wgs097nu_RunAnim); } } - else if (m_state->m_unk0x08 == 1 && p_param.GetTrigger() == LegoPathStruct::c_camAnim && p_param.GetData() == 0x37) { - m_state->m_unk0x08 = 3; + else if (m_state->m_state == TowTrackMissionState::e_started && p_param.GetTrigger() == LegoPathStruct::c_camAnim && p_param.GetData() == 0x37) { + m_state->m_state = TowTrackMissionState::e_hookingUp; StopActions(); if (m_lastAction != IsleScript::c_noneIsle) { @@ -328,20 +329,20 @@ MxLong TowTrack::HandlePathStruct(LegoPathStructNotificationParam& p_param) Leave(); PlayFinalAnimation(IsleScript::c_wrt060bm_RunAnim); } - else if (p_param.GetTrigger() == LegoPathStruct::c_w && m_state->m_unk0x08 == 1) { + else if (p_param.GetTrigger() == LegoPathStruct::c_w && m_state->m_state == TowTrackMissionState::e_started) { if (p_param.GetData() == 0x15f) { - if (m_unk0x16c == 0) { - m_unk0x16c = 1; + if (m_treeBlockageTriggered == 0) { + m_treeBlockageTriggered = 1; InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns050p1_RunAnim, NULL); } } else if (p_param.GetData() == 0x160) { - if (m_unk0x16e == 0) { - m_unk0x16e = 1; + if (m_speedComplaintTriggered == 0) { + m_speedComplaintTriggered = 1; InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns046mg_RunAnim, NULL); } - if (!m_state->m_unk0x10 && m_lastAction == IsleScript::c_noneIsle) { + if (!m_state->m_takingTooLong && m_lastAction == IsleScript::c_noneIsle) { if (m_actorId < LegoActor::c_pepper || m_actorId > LegoActor::c_laura) { m_actorId = LegoActor::c_laura; } @@ -405,15 +406,15 @@ MxLong TowTrack::HandlePathStruct(LegoPathStructNotificationParam& p_param) // FUNCTION: LEGO1 0x1004d690 MxLong TowTrack::HandleClick() { - if (((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 != 8) { + if (((Act1State*) GameState()->GetState("Act1State"))->m_state != Act1State::e_towtrack) { return 1; } - if (m_state->m_unk0x08 == 3) { + if (m_state->m_state == TowTrackMissionState::e_hookingUp) { return 1; } - FUN_10015820(TRUE, 0); + Disable(TRUE, 0); ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_towtrack); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); @@ -428,11 +429,11 @@ MxLong TowTrack::HandleClick() InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_TowTrackDashboard, NULL); ControlManager()->Register(this); - if (m_state->m_unk0x08 == 0) { + if (m_state->m_state == TowTrackMissionState::e_none) { return 1; } - if (m_state->m_unk0x08 == 2) { + if (m_state->m_state == TowTrackMissionState::e_hookedUp) { SpawnPlayer(LegoGameState::e_unk52, TRUE, 0); FindROI("rcred")->SetVisibility(FALSE); } @@ -441,7 +442,7 @@ MxLong TowTrack::HandleClick() m_lastAction = IsleScript::c_noneIsle; m_lastAnimation = IsleScript::c_noneIsle; m_state->m_startTime = Timer()->GetTime(); - m_state->m_unk0x10 = FALSE; + m_state->m_takingTooLong = FALSE; InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns057rd_RunAnim, NULL); InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns048p1_RunAnim, NULL); InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns049p1_RunAnim, NULL); @@ -459,7 +460,7 @@ void TowTrack::Exit() { GameState()->m_currentArea = LegoGameState::e_garageExterior; StopActions(); - FUN_1004dbe0(); + Reset(); Leave(); } @@ -509,9 +510,9 @@ MxLong TowTrack::HandleControl(LegoControlManagerNotificationParam& p_param) } // FUNCTION: LEGO1 0x1004dab0 -void TowTrack::FUN_1004dab0() +void TowTrack::Init() { - m_state->m_unk0x08 = 1; + m_state->m_state = TowTrackMissionState::e_started; HandleClick(); } @@ -520,8 +521,8 @@ void TowTrack::ActivateSceneActions() { PlayMusic(JukeboxScript::c_JBMusic2); - if (m_state->m_unk0x08 != 0) { - if (m_state->m_unk0x08 == 2) { + if (m_state->m_state != TowTrackMissionState::e_none) { + if (m_state->m_state == TowTrackMissionState::e_hookedUp) { PlayAction(IsleScript::c_wrt082na_PlayWav); } else { @@ -545,22 +546,22 @@ void TowTrack::StopActions() } // FUNCTION: LEGO1 0x1004dbe0 -void TowTrack::FUN_1004dbe0() +void TowTrack::Reset() { if (m_lastAction != -1) { InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL); } - ((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0; - m_state->m_unk0x08 = 0; + ((Act1State*) GameState()->GetState("Act1State"))->m_state = Act1State::e_none; + m_state->m_state = TowTrackMissionState::e_none; g_isleFlags |= Isle::c_playMusic; AnimationManager()->EnableCamAnims(TRUE); AnimationManager()->FUN_1005f6d0(TRUE); m_state->m_startTime = INT_MIN; - m_state->m_unk0x10 = FALSE; + m_state->m_takingTooLong = FALSE; m_state = NULL; - m_unk0x16c = 0; - m_unk0x16e = 0; + m_treeBlockageTriggered = 0; + m_speedComplaintTriggered = 0; } // FUNCTION: LEGO1 0x1004dc80 @@ -595,9 +596,9 @@ void TowTrack::PlayAction(IsleScript::Script p_objectId) // FUNCTION: LEGO1 0x1004dd30 TowTrackMissionState::TowTrackMissionState() { - m_unk0x08 = 0; + m_state = TowTrackMissionState::e_none; m_startTime = 0; - m_unk0x10 = FALSE; + m_takingTooLong = FALSE; m_peScore = 0; m_maScore = 0; m_paScore = 0; diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 124442e0..da309660 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1256,7 +1256,7 @@ void LegoCarBuild::FUN_10024ef0() m_buildState->m_animationState = LegoVehicleBuildState::e_cutscene; FUN_10025720(FUN_10025d70()); m_buildState->m_unk0x4c += 1; - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x10024f30 diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 93665ee3..4ba42020 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -866,7 +866,7 @@ void LegoGameState::SwitchArea(Area p_area) m_previousArea = m_currentArea; m_currentArea = p_area; - FUN_10015820(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d); + Disable(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d); BackgroundAudioManager()->Stop(); AnimationManager()->Suspend(); VideoManager()->SetUnk0x554(FALSE); @@ -967,7 +967,7 @@ void LegoGameState::SwitchArea(Area p_area) Act1State* state = (Act1State*) GameState()->GetState("Act1State"); LoadIsle(); - if (state->GetUnknown18() == 7) { + if (state->GetState() == Act1State::e_transitionToTowtrack) { VideoManager()->Get3DManager()->SetFrustrum(90, 0.1f, 250.0f); } else { diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index 0a07a7c0..fdc6755a 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -591,9 +591,10 @@ MxBool CanExit() GameState()->m_currentArea != LegoGameState::e_polidoor) { if (UserActor() == NULL || !UserActor()->IsA("TowTrack")) { if (UserActor() == NULL || !UserActor()->IsA("Ambulance")) { - MxU32 unk0x18 = act1State->GetUnknown18(); + MxU32 mission = act1State->GetState(); - if (unk0x18 != 10 && unk0x18 != 8 && unk0x18 != 3) { + if (mission != Act1State::e_ambulance && mission != Act1State::e_towtrack && + mission != Act1State::e_pizza) { return TRUE; } } @@ -783,9 +784,10 @@ void LoadFromNamedTexture(LegoNamedTexture* p_namedTexture) } } -void HitActorEvent() +void EmitGameEvent(GameEvent p_event) { SDL_Event event; - event.user.type = g_legoSdlEvents.m_hitActor; + event.user.type = g_legoSdlEvents.m_gameEvent; + event.user.code = p_event; SDL_PushEvent(&event); } diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 08072b7c..6b231b56 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -140,10 +140,10 @@ ViewLODListManager* GetViewLODListManager() // FUNCTION: LEGO1 0x10015820 // FUNCTION: BETA10 0x100e4c92 -void FUN_10015820(MxBool p_disable, MxU16 p_flags) +void Disable(MxBool p_disable, MxU16 p_flags) { assert(LegoOmni::GetInstance()); - LegoOmni::GetInstance()->FUN_1005b4f0(p_disable, p_flags); + LegoOmni::GetInstance()->Disable(p_disable, p_flags); } // FUNCTION: LEGO1 0x10015840 diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp index 16e72fbb..bccfd6c7 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -80,10 +80,7 @@ MxBool MxControlPresenter::CheckButtonDown(MxS32 p_x, MxS32 p_y, MxPresenter* p_ { assert(p_presenter); MxVideoPresenter* presenter = dynamic_cast(p_presenter); - if (!presenter) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid presenter"); - return FALSE; - } + assert(presenter); if (m_style == e_map) { MxStillPresenter* map = (MxStillPresenter*) m_list.front(); diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index 3e977d5b..6a7c59f7 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -175,7 +175,7 @@ void LegoCameraController::FUN_100123e0(const Matrix4& p_transform, MxU32 p_und) mat = p_transform; } - ((TimeROI*) pov)->FUN_100a9b40(mat, Timer()->GetTime()); + ((TimeROI*) pov)->CalculateWorldVelocity(mat, Timer()->GetTime()); pov->WrappedSetLocal2WorldWithWorldDataUpdate(mat); m_lego3DView->Moved(*pov); diff --git a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp index 7541e98b..fc823c60 100644 --- a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp @@ -153,7 +153,7 @@ MxResult LegoPointOfViewController::Tickle() MxMatrix mat; CalcLocalTransform(newPos, newDir, pov->GetWorldUp(), mat); - ((TimeROI*) pov)->FUN_100a9b40(mat, Timer()->GetTime()); + ((TimeROI*) pov)->CalculateWorldVelocity(mat, Timer()->GetTime()); pov->WrappedSetLocal2WorldWithWorldDataUpdate(mat); m_lego3DView->Moved(*pov); diff --git a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp index b2f79568..abf6c32a 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp @@ -63,7 +63,7 @@ LegoWorldPresenter::~LegoWorldPresenter() } if (result == FALSE) { - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } if (m_entity) { @@ -260,8 +260,12 @@ MxResult LegoWorldPresenter::LoadWorld(char* p_worldName, LegoWorld* p_world) ModelDbPart* part; while (cursor.Next(part)) { - if (GetViewLODListManager()->Lookup(part->m_roiName.GetData()) == NULL && - LoadWorldPart(*part, wdbFile) != SUCCESS) { + ViewLODList* lodList = GetViewLODListManager()->Lookup(part->m_roiName.GetData()); + if (lodList) { + lodList->Release(); + } + + if (lodList == NULL && LoadWorldPart(*part, wdbFile) != SUCCESS) { return FAILURE; } } diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 7c80e78e..f7fef27e 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -11,6 +11,8 @@ #include "mxdebug.h" #include "roi/legoroi.h" +#include + DECOMP_SIZE_ASSERT(LegoInputManager, 0x338) DECOMP_SIZE_ASSERT(LegoNotifyList, 0x18) DECOMP_SIZE_ASSERT(LegoNotifyListCursor, 0x10) @@ -40,10 +42,6 @@ LegoInputManager::LegoInputManager() m_unk0x81 = FALSE; m_unk0x88 = FALSE; m_unk0x195 = 0; - m_joyids = NULL; - m_joystickIndex = -1; - m_joystick = NULL; - m_useJoystick = FALSE; m_unk0x335 = FALSE; m_unk0x336 = FALSE; m_unk0x74 = 0x19; @@ -71,8 +69,6 @@ MxResult LegoInputManager::Create(HWND p_hwnd) m_eventQueue = new LegoEventQueue; } - GetJoystick(); - if (!m_keyboardNotifyList || !m_eventQueue) { Destroy(); result = FAILURE; @@ -98,7 +94,23 @@ void LegoInputManager::Destroy() delete m_controlManager; } - SDL_free(m_joyids); + for (const auto& [id, joystick] : m_joysticks) { + if (joystick.second) { + SDL_CloseHaptic(joystick.second); + } + + SDL_CloseGamepad(joystick.first); + } + + for (const auto& [id, mouse] : m_mice) { + if (mouse.second) { + SDL_CloseHaptic(mouse.second); + } + } + + for (const auto& [id, haptic] : m_otherHaptics) { + SDL_CloseHaptic(haptic); + } } // FUNCTION: LEGO1 0x1005c0f0 @@ -145,74 +157,39 @@ MxResult LegoInputManager::GetNavigationKeyStates(MxU32& p_keyFlags) return SUCCESS; } -// FUNCTION: LEGO1 0x1005c240 -MxResult LegoInputManager::GetJoystick() -{ - if (m_joystick != NULL && SDL_GamepadConnected(m_joystick) == TRUE) { - return SUCCESS; - } - - MxS32 numJoysticks = 0; - if (m_joyids != NULL) { - SDL_free(m_joyids); - m_joyids = NULL; - } - m_joyids = SDL_GetGamepads(&numJoysticks); - - if (m_useJoystick != FALSE && numJoysticks != 0) { - MxS32 joyid = m_joystickIndex; - if (joyid >= 0) { - m_joystick = SDL_OpenGamepad(m_joyids[joyid]); - if (m_joystick != NULL) { - return SUCCESS; - } - } - - for (joyid = 0; joyid < numJoysticks; joyid++) { - m_joystick = SDL_OpenGamepad(m_joyids[joyid]); - if (m_joystick != NULL) { - return SUCCESS; - } - } - } - - return FAILURE; -} - // FUNCTION: LEGO1 0x1005c320 MxResult LegoInputManager::GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, MxU32* p_povPosition) { - if (m_useJoystick != FALSE) { - if (GetJoystick() == -1) { - if (m_joystick != NULL) { - // GetJoystick() failed but handle to joystick is still open, close it - SDL_CloseGamepad(m_joystick); - m_joystick = NULL; - } + if (!std::holds_alternative(m_lastInputMethod) && + !(std::holds_alternative(m_lastInputMethod) && m_touchScheme == e_gamepad)) { + return FAILURE; + } - return FAILURE; - } - - MxS16 xPos = SDL_GetGamepadAxis(m_joystick, SDL_GAMEPAD_AXIS_LEFTX); - MxS16 yPos = SDL_GetGamepadAxis(m_joystick, SDL_GAMEPAD_AXIS_LEFTY); + MxS16 xPos, yPos = 0; + for (const auto& [id, joystick] : m_joysticks) { + xPos = SDL_GetGamepadAxis(joystick.first, SDL_GAMEPAD_AXIS_LEFTX); + yPos = SDL_GetGamepadAxis(joystick.first, SDL_GAMEPAD_AXIS_LEFTY); if (xPos > -8000 && xPos < 8000) { - // Ignore small axis values xPos = 0; } if (yPos > -8000 && yPos < 8000) { - // Ignore small axis values yPos = 0; } - // normalize values acquired from joystick axes - *p_joystickX = ((xPos + 32768) * 100) / 65535; - *p_joystickY = ((yPos + 32768) * 100) / 65535; - *p_povPosition = -1; - - return SUCCESS; + if (xPos || yPos) { + break; + } } - return FAILURE; + if (!xPos && !yPos) { + xPos = m_touchVirtualThumb.x; + yPos = m_touchVirtualThumb.y; + } + + *p_joystickX = ((xPos + 32768) * 100) / 65535; + *p_joystickY = ((yPos + 32768) * 100) / 65535; + *p_povPosition = -1; + return SUCCESS; } // FUNCTION: LEGO1 0x1005c470 @@ -528,27 +505,105 @@ void LegoInputManager::EnableInputProcessing() MxResult LegoInputManager::GetNavigationTouchStates(MxU32& p_keyStates) { - for (auto& [fingerID, touchFlags] : m_touchFlags) { - p_keyStates |= touchFlags; - - // We need to clear these as they are not meant to be persistent in e_gamepad mode. - if (m_touchOrigins.count(fingerID) && m_touchLastMotion.count(fingerID)) { - const MxU32 inactivityThreshold = 3; - - if (m_touchLastMotion[fingerID].first++ > inactivityThreshold) { - touchFlags &= ~c_left; - touchFlags &= ~c_right; - m_touchOrigins[fingerID].x = m_touchLastMotion[fingerID].second.x; - } + if (m_touchScheme == e_arrowKeys) { + for (auto& [fingerID, touchFlags] : m_touchFlags) { + p_keyStates |= touchFlags; } } return SUCCESS; } +void LegoInputManager::AddKeyboard(SDL_KeyboardID p_keyboardID) +{ + if (m_keyboards.count(p_keyboardID)) { + return; + } + + m_keyboards[p_keyboardID] = {nullptr, nullptr}; +} + +void LegoInputManager::RemoveKeyboard(SDL_KeyboardID p_keyboardID) +{ + if (!m_keyboards.count(p_keyboardID)) { + return; + } + + m_keyboards.erase(p_keyboardID); +} + +void LegoInputManager::AddMouse(SDL_MouseID p_mouseID) +{ + if (m_mice.count(p_mouseID)) { + return; + } + + // Currently no way to get an individual haptic device for a mouse. + SDL_Haptic* haptic = SDL_OpenHapticFromMouse(); + if (haptic) { + if (!SDL_InitHapticRumble(haptic)) { + SDL_CloseHaptic(haptic); + haptic = nullptr; + } + } + + m_mice[p_mouseID] = {nullptr, haptic}; +} + +void LegoInputManager::RemoveMouse(SDL_MouseID p_mouseID) +{ + if (!m_mice.count(p_mouseID)) { + return; + } + + if (m_mice[p_mouseID].second) { + SDL_CloseHaptic(m_mice[p_mouseID].second); + } + + m_mice.erase(p_mouseID); +} + +void LegoInputManager::AddJoystick(SDL_JoystickID p_joystickID) +{ + if (m_joysticks.count(p_joystickID)) { + return; + } + + SDL_Gamepad* joystick = SDL_OpenGamepad(p_joystickID); + if (joystick) { + SDL_Haptic* haptic = SDL_OpenHapticFromJoystick(SDL_GetGamepadJoystick(joystick)); + if (haptic) { + if (!SDL_InitHapticRumble(haptic)) { + SDL_CloseHaptic(haptic); + haptic = nullptr; + } + } + + m_joysticks[p_joystickID] = {joystick, haptic}; + } + else { + SDL_Log("Failed to open gamepad: %s", SDL_GetError()); + } +} + +void LegoInputManager::RemoveJoystick(SDL_JoystickID p_joystickID) +{ + if (!m_joysticks.count(p_joystickID)) { + return; + } + + if (m_joysticks[p_joystickID].second) { + SDL_CloseHaptic(m_joysticks[p_joystickID].second); + } + + SDL_CloseGamepad(m_joysticks[p_joystickID].first); + m_joysticks.erase(p_joystickID); +} + MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touchScheme) { const SDL_TouchFingerEvent& event = p_event->tfinger; + m_touchScheme = p_touchScheme; switch (p_touchScheme) { case e_mouse: @@ -580,64 +635,167 @@ MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touc break; } break; - case e_gamepad: + case e_gamepad: { + static SDL_FingerID g_finger = (SDL_FingerID) 0; + switch (p_event->type) { case SDL_EVENT_FINGER_DOWN: - m_touchOrigins[event.fingerID] = {event.x, event.y}; + if (!g_finger) { + g_finger = event.fingerID; + m_touchVirtualThumb = {0, 0}; + m_touchVirtualThumbOrigin = {event.x, event.y}; + } break; case SDL_EVENT_FINGER_UP: - m_touchOrigins.erase(event.fingerID); - m_touchFlags.erase(event.fingerID); + if (event.fingerID == g_finger) { + g_finger = 0; + m_touchVirtualThumb = {0, 0}; + m_touchVirtualThumbOrigin = {0, 0}; + } break; case SDL_EVENT_FINGER_MOTION: - if (m_touchOrigins.count(event.fingerID)) { - const float activationThreshold = 0.03f; - m_touchFlags[event.fingerID] &= ~c_down; - m_touchFlags[event.fingerID] &= ~c_up; + if (event.fingerID == g_finger) { + const float thumbstickRadius = 0.25f; + const float deltaX = + SDL_clamp(event.x - m_touchVirtualThumbOrigin.x, -thumbstickRadius, thumbstickRadius); + const float deltaY = + SDL_clamp(event.y - m_touchVirtualThumbOrigin.y, -thumbstickRadius, thumbstickRadius); - const float deltaY = event.y - m_touchOrigins[event.fingerID].y; - if (SDL_fabsf(deltaY) > activationThreshold) { - if (deltaY > 0) { - m_touchFlags[event.fingerID] |= c_down; - } - else if (deltaY < 0) { - m_touchFlags[event.fingerID] |= c_up; - } - } - - const float deltaX = event.x - m_touchOrigins[event.fingerID].x; - if (SDL_fabsf(deltaX) > activationThreshold && event.dx) { - if (event.dx > 0) { - m_touchFlags[event.fingerID] |= c_right; - m_touchFlags[event.fingerID] &= ~c_left; - } - else if (event.dx < 0) { - m_touchFlags[event.fingerID] |= c_left; - m_touchFlags[event.fingerID] &= ~c_right; - } - - m_touchLastMotion[event.fingerID] = {0, {event.x, event.y}}; - } + m_touchVirtualThumb = { + (int) (deltaX / thumbstickRadius * 32767.0f), + (int) (deltaY / thumbstickRadius * 32767.0f), + }; } break; } break; } + } return TRUE; } -MxBool LegoInputManager::HandleRumbleEvent() +MxBool LegoInputManager::HandleRumbleEvent( + float p_strength, + float p_lowFrequencyRumble, + float p_highFrequencyRumble, + MxU32 p_milliseconds +) { - if (m_joystick != NULL && SDL_GamepadConnected(m_joystick) == TRUE) { - const Uint16 frequency = 65535 / 2; - const Uint32 durationMs = 700; - SDL_RumbleGamepad(m_joystick, frequency, frequency, durationMs); - } - else { - return FALSE; + static bool g_hapticsInitialized = false; + + if (!g_hapticsInitialized) { + InitializeHaptics(); + g_hapticsInitialized = true; } - // Add support for SDL Haptic API - return TRUE; + SDL_Haptic* haptic = nullptr; + std::visit( + overloaded{ + [](SDL_KeyboardID_v p_id) {}, + [&haptic, this](SDL_MouseID_v p_id) { + if (m_mice.count((SDL_MouseID) p_id)) { + haptic = m_mice[(SDL_MouseID) p_id].second; + } + }, + [&haptic, this](SDL_JoystickID_v p_id) { + if (m_joysticks.count((SDL_JoystickID) p_id)) { + haptic = m_joysticks[(SDL_JoystickID) p_id].second; + } + }, + [&haptic, this](SDL_TouchID_v p_id) { + // We can't currently correlate Touch devices with Haptic devices + if (!m_otherHaptics.empty()) { + haptic = m_otherHaptics.begin()->second; + } + } + }, + m_lastInputMethod + ); + + if (haptic) { + return SDL_PlayHapticRumble(haptic, p_strength, p_milliseconds); + } + + // A joystick isn't necessarily a haptic device; try basic rumble instead + if (const SDL_JoystickID_v* joystick = std::get_if(&m_lastInputMethod)) { + if (m_joysticks.count((SDL_JoystickID) *joystick)) { + return SDL_RumbleGamepad( + m_joysticks[(SDL_JoystickID) *joystick].first, + SDL_clamp(p_lowFrequencyRumble, 0, 1) * USHRT_MAX, + SDL_clamp(p_highFrequencyRumble, 0, 1) * USHRT_MAX, + p_milliseconds + ); + } + } + + return FALSE; +} + +void LegoInputManager::InitializeHaptics() +{ + // We don't get added/removed events for haptic devices that are not joysticks or mice, + // so we initialize "otherHaptics" once at this point. + std::vector existingHaptics; + + for (const auto& [id, mouse] : m_mice) { + if (mouse.second) { + existingHaptics.push_back(SDL_GetHapticID(mouse.second)); + } + } + + for (const auto& [id, joystick] : m_joysticks) { + if (joystick.second) { + existingHaptics.push_back(SDL_GetHapticID(joystick.second)); + } + } + + int count; + SDL_HapticID* haptics = SDL_GetHaptics(&count); + if (haptics) { + for (int i = 0; i < count; i++) { + if (std::find(existingHaptics.begin(), existingHaptics.end(), haptics[i]) == existingHaptics.end()) { + SDL_Haptic* haptic = SDL_OpenHaptic(haptics[i]); + if (haptic) { + if (SDL_InitHapticRumble(haptic)) { + m_otherHaptics[haptics[i]] = haptic; + } + else { + SDL_CloseHaptic(haptic); + } + } + } + } + + SDL_free(haptics); + } +} + +void LegoInputManager::UpdateLastInputMethod(SDL_Event* p_event) +{ + switch (p_event->type) { + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + m_lastInputMethod = SDL_KeyboardID_v{p_event->key.which}; + break; + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: + m_lastInputMethod = SDL_MouseID_v{p_event->button.which}; + break; + case SDL_EVENT_MOUSE_MOTION: + m_lastInputMethod = SDL_MouseID_v{p_event->motion.which}; + break; + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: + case SDL_EVENT_GAMEPAD_BUTTON_UP: + m_lastInputMethod = SDL_JoystickID_v{p_event->gbutton.which}; + break; + case SDL_EVENT_GAMEPAD_AXIS_MOTION: + m_lastInputMethod = SDL_JoystickID_v{p_event->gaxis.which}; + break; + case SDL_EVENT_FINGER_MOTION: + case SDL_EVENT_FINGER_DOWN: + case SDL_EVENT_FINGER_UP: + m_lastInputMethod = SDL_TouchID_v{p_event->tfinger.touchID}; + break; + } } diff --git a/LEGO1/lego/legoomni/src/main/legomain.cpp b/LEGO1/lego/legoomni/src/main/legomain.cpp index 1695e1c3..78ddf033 100644 --- a/LEGO1/lego/legoomni/src/main/legomain.cpp +++ b/LEGO1/lego/legoomni/src/main/legomain.cpp @@ -122,6 +122,8 @@ void LegoOmni::Destroy() m_textureContainer = NULL; } + LegoPartPresenter::Release(); + if (m_viewLODListManager) { delete m_viewLODListManager; m_viewLODListManager = NULL; @@ -543,26 +545,36 @@ LegoOmni::World LegoOmni::GetWorldId(const char* p_key) } // FUNCTION: LEGO1 0x1005b4f0 -void LegoOmni::FUN_1005b4f0(MxBool p_disable, MxU16 p_flags) +// FUNCTION: BETA10 0x1008eeec +void LegoOmni::Disable(MxBool p_disable, MxU16 p_flags) { - if (p_disable) { - if (p_flags & c_disableInput) { - m_inputManager->DisableInputProcessing(); - } +#ifdef BETA10 + if (this->m_paused != p_disable) { + // This is probably a different variable, but this code was mostly added for structural matching + m_paused = p_disable; +#endif - if (p_flags & c_disable3d) { - ((LegoVideoManager*) m_videoManager)->SetRender3D(FALSE); - } + if (p_disable) { + if (p_flags & c_disableInput) { + m_inputManager->DisableInputProcessing(); + } - if (p_flags & c_clearScreen) { - m_videoManager->GetDisplaySurface()->ClearScreen(); + if (p_flags & c_disable3d) { + ((LegoVideoManager*) m_videoManager)->SetRender3D(FALSE); + } + + if (p_flags & c_clearScreen) { + m_videoManager->GetDisplaySurface()->ClearScreen(); + } } + else { + m_inputManager->EnableInputProcessing(); + ((LegoVideoManager*) m_videoManager)->SetRender3D(TRUE); + ((LegoVideoManager*) m_videoManager)->UpdateView(0, 0, 0, 0); + } +#ifdef BETA10 } - else { - m_inputManager->EnableInputProcessing(); - ((LegoVideoManager*) m_videoManager)->SetRender3D(TRUE); - ((LegoVideoManager*) m_videoManager)->UpdateView(0, 0, 0, 0); - } +#endif } // FUNCTION: LEGO1 0x1005b560 diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp index 182945d5..f6ca062c 100644 --- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp @@ -133,7 +133,7 @@ MxResult LegoAnimActor::FUN_1001c360(float p_und, Matrix4& p_transform) } for (MxS32 j = 0; j < n->GetNumChildren(); j++) { - LegoROI::FUN_100a8e80(n->GetChild(j), p_transform, p_und, roiMap); + LegoROI::ApplyAnimationTransformation(n->GetChild(j), p_transform, p_und, roiMap); } if (m_cameraFlag) { diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index 7f640326..316d010b 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -235,7 +235,9 @@ MxResult LegoExtraActor::HitActor(LegoPathActor* p_actor, MxBool p_bool) assert(m_roi); assert(SoundManager()->GetCacheSoundManager()); SoundManager()->GetCacheSoundManager()->Play("crash5", m_roi->GetName(), FALSE); - HitActorEvent(); + if (p_actor->GetUserNavFlag()) { + EmitGameEvent(e_hitActor); + } m_scheduledTime = Timer()->GetTime() + m_disAnim->GetDuration(); m_prevWorldSpeed = GetWorldSpeed(); VTable0xc4(); @@ -249,7 +251,9 @@ MxResult LegoExtraActor::HitActor(LegoPathActor* p_actor, MxBool p_bool) LegoROI* roi = GetROI(); assert(roi); SoundManager()->GetCacheSoundManager()->Play("crash5", m_roi->GetName(), FALSE); - HitActorEvent(); + if (p_actor->GetUserNavFlag()) { + EmitGameEvent(e_hitActor); + } VTable0xc4(); SetActorState(c_two | c_noCollide); Mx3DPointFloat dir = p_actor->GetWorldDirection(); @@ -375,7 +379,7 @@ void LegoExtraActor::Animate(float p_time) MxS32 count = root->GetNumChildren(); for (MxS32 i = 0; i < count; i++) { - LegoROI::FUN_100a8e80(root->GetChild(i), matrix, duration2, laas->m_roiMap); + LegoROI::ApplyAnimationTransformation(root->GetChild(i), matrix, duration2, laas->m_roiMap); } } } diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp index c59cd6de..52315e79 100644 --- a/LEGO1/lego/legoomni/src/race/carrace.cpp +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -97,7 +97,7 @@ MxResult CarRace::Create(MxDSAction& p_dsAction) m_raceState = raceState; - m_act1State->m_unk0x018 = 6; + m_act1State->m_state = Act1State::e_transitionToRacecar; m_unk0x144 = -1; m_unk0x148 = -1; m_unk0x14c = -1; @@ -126,7 +126,7 @@ void CarRace::ReadyWorld() BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); AnimationManager()->Resume(); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); m_unk0x144 = g_unk0x100d5d10[SDL_rand(8)]; @@ -181,7 +181,7 @@ MxLong CarRace::HandlePathStruct(LegoPathStructNotificationParam& p_param) { MxLong result = 0; - if (p_param.GetTrigger() == 68) { + if (p_param.GetTrigger() == LegoPathStruct::c_d) { MxEntity* sender = (MxEntity*) p_param.GetSender(); MxS32 paramData = p_param.GetData(); @@ -267,6 +267,8 @@ MxLong CarRace::HandlePathStruct(LegoPathStructNotificationParam& p_param) FALSE, TRUE ); + + EmitGameEvent(e_raceFinished); } result = 1; @@ -341,7 +343,7 @@ MxLong CarRace::HandleControl(LegoControlManagerNotificationParam& p_param) switch (p_param.m_clickedObjectId) { case 3: InvokeAction(Extra::e_stop, *g_carraceScript, CarraceScript::c_irtx08ra_PlayWav, NULL); - m_act1State->m_unk0x018 = 0; + m_act1State->m_state = Act1State::e_none; VariableTable()->SetVariable(g_raceState, ""); VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); NavController()->SetDeadZone(NavController()->GetDefaultDeadZone()); @@ -353,7 +355,7 @@ MxLong CarRace::HandleControl(LegoControlManagerNotificationParam& p_param) break; case 98: InvokeAction(Extra::e_stop, *g_carraceScript, CarraceScript::c_irtx08ra_PlayWav, NULL); - m_act1State->m_unk0x018 = 0; + m_act1State->m_state = Act1State::e_none; VariableTable()->SetVariable(g_raceState, ""); VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); NavController()->SetDeadZone(NavController()->GetDefaultDeadZone()); @@ -415,7 +417,7 @@ MxBool CarRace::Escape() AnimationManager()->FUN_10061010(FALSE); DeleteObjects(&m_atomId, 500, 999); - m_act1State->m_unk0x018 = 0; + m_act1State->m_state = Act1State::e_none; VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); VariableTable()->SetVariable(g_raceState, ""); diff --git a/LEGO1/lego/legoomni/src/race/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp index 6ea02f86..edeb6aa2 100644 --- a/LEGO1/lego/legoomni/src/race/jetskirace.cpp +++ b/LEGO1/lego/legoomni/src/race/jetskirace.cpp @@ -97,7 +97,7 @@ void JetskiRace::ReadyWorld() m_unk0x12c = (MxStillPresenter*) Find("MxPresenter", "JetskiLocator3"); m_unk0x12c->SetPosition(m_unk0x130.GetLeft(), m_unk0x130.GetTop()); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); VariableTable()->SetVariable("DISTANCE", "0.036"); @@ -129,7 +129,7 @@ MxLong JetskiRace::HandleControl(LegoControlManagerNotificationParam& p_param) if (p_param.m_unk0x28 == 1) { switch (p_param.m_clickedObjectId) { case JetraceScript::c_JetskiArms_Ctl: - m_act1State->m_unk0x018 = 0; + m_act1State->m_state = Act1State::e_none; VariableTable()->SetVariable(g_raceState, ""); VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); LegoRaceCar::InitYouCantStopSound(); @@ -137,7 +137,7 @@ MxLong JetskiRace::HandleControl(LegoControlManagerNotificationParam& p_param) TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); break; case JetraceScript::c_JetskiInfo_Ctl: - m_act1State->m_unk0x018 = 0; + m_act1State->m_state = Act1State::e_none; VariableTable()->SetVariable(g_raceState, ""); VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); LegoRaceCar::InitYouCantStopSound(); @@ -160,7 +160,7 @@ MxLong JetskiRace::HandlePathStruct(LegoPathStructNotificationParam& p_param) MxLong result = 0; MxEntity* sender = (MxEntity*) p_param.GetSender(); - if (p_param.GetTrigger() == 68) { + if (p_param.GetTrigger() == LegoPathStruct::c_d) { MxS32 paramData = p_param.GetData(); switch (sender->GetEntityId()) { @@ -206,6 +206,7 @@ MxLong JetskiRace::HandlePathStruct(LegoPathStructNotificationParam& p_param) m_destLocation = LegoGameState::e_jetrace2; TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + EmitGameEvent(e_raceFinished); } result = 1; @@ -290,7 +291,7 @@ MxBool JetskiRace::Escape() { AnimationManager()->FUN_10061010(FALSE); DeleteObjects(&m_atomId, 500, 999); - m_act1State->m_unk0x018 = 0; + m_act1State->m_state = Act1State::e_none; VariableTable()->SetVariable(g_raceState, ""); VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); m_destLocation = LegoGameState::e_infomain; diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index 74fd9f9a..d8e4dff5 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -392,6 +392,7 @@ MxU32 LegoRaceCar::HandleSkeletonKicks(float p_param1) m_kickStart = p_param1; SoundManager()->GetCacheSoundManager()->Play(g_soundSkel3, NULL, FALSE); + EmitGameEvent(e_skeletonKick); return TRUE; } @@ -528,6 +529,9 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool) } } } + else { + EmitGameEvent(e_hitActor); + } return SUCCESS; } @@ -726,6 +730,9 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool) } } } + else { + EmitGameEvent(e_hitActor); + } return SUCCESS; } diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index ebf0c1ad..1ead351a 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -706,11 +706,14 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi) if (p_roi == NULL) { return FAILURE; } +#ifdef BETA10 + MxMatrix unused_matrix; +#endif Matrix4* mn = new MxMatrix(); assert(mn); - MxMatrix local58; + MxMatrix inverse; const Matrix4& local2world = p_roi->GetLocal2World(); MxMatrix* local5c; MxU32 i; @@ -721,7 +724,7 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi) for (i = 1; i <= m_roiMapSize; i++) { if (m_roiMap[i] == p_roi) { - if (local5c[i].BETA_1005a590(local58) != SUCCESS) { + if (local5c[i].Invert(inverse) != SUCCESS) { goto done; } @@ -730,7 +733,7 @@ MxResult LegoAnimPresenter::FUN_1006b140(LegoROI* p_roi) } { - mn->Product(local58, local2world); + mn->Product(inverse, local2world); SetUnknown0xa0(mn); delete[] local5c; SetUnknown0x0cTo1(); @@ -906,7 +909,7 @@ void LegoAnimPresenter::FUN_1006b900(LegoAnim* p_anim, MxLong p_time, Matrix4* p } } - LegoROI::FUN_100a8fd0(root, mat, p_time, m_roiMap); + LegoROI::ApplyTransform(root, mat, p_time, m_roiMap); } // FUNCTION: LEGO1 0x1006b9a0 @@ -940,7 +943,7 @@ void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p } } - LegoROI::FUN_100a8e80(root, mat, p_time, m_roiMap); + LegoROI::ApplyAnimationTransformation(root, mat, p_time, m_roiMap); } // FUNCTION: LEGO1 0x1006bac0 diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp index 89768b3e..60f8dce5 100644 --- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp @@ -114,7 +114,7 @@ void LegoHideAnimPresenter::FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time) } if (m_boundaryMap != NULL) { - LegoPathBoundary* boundary = m_boundaryMap[data->GetUnknown0x22()]; + LegoPathBoundary* boundary = m_boundaryMap[data->GetBoundaryIndex()]; if (boundary != NULL) { newB = data->GetVisibility(p_time); @@ -163,7 +163,7 @@ void LegoHideAnimPresenter::FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeN FUN_1006e470(p_map, data, name, boundary); } else { - data->SetUnknown0x22(0); + data->SetBoundaryIndex(0); } } @@ -190,7 +190,7 @@ void LegoHideAnimPresenter::FUN_1006e470( animStruct.m_index = p_map.size() + 1; animStruct.m_boundary = p_boundary; - p_data->SetUnknown0x22(animStruct.m_index); + p_data->SetBoundaryIndex(animStruct.m_index); char* name = new char[strlen(p_name) + 1]; strcpy(name, p_name); @@ -198,7 +198,7 @@ void LegoHideAnimPresenter::FUN_1006e470( p_map[name] = animStruct; } else { - p_data->SetUnknown0x22((*it).second.m_index); + p_data->SetBoundaryIndex((*it).second.m_index); } } diff --git a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp index 4849e747..8686cb17 100644 --- a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp @@ -22,6 +22,8 @@ MxS32 g_partPresenterConfig1 = 1; // GLOBAL: LEGO1 0x100f7aa4 MxS32 g_partPresenterConfig2 = 100; +vector LegoPartPresenter::g_lodLists; + // FUNCTION: LEGO1 0x1007c990 void LegoPartPresenter::configureLegoPartPresenter(MxS32 p_partPresenterConfig1, MxS32 p_partPresenterConfig2) { @@ -261,6 +263,8 @@ void LegoPartPresenter::Store() lodCursor.Detach(); lodList->PushBack(lod); } + + g_lodLists.push_back(lodList); } else { lodList->Release(); diff --git a/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp b/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp index 353480fc..6ea4d36d 100644 --- a/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp @@ -25,8 +25,8 @@ void LegoPhonemePresenter::Init() { m_rectCount = 0; m_textureInfo = NULL; - m_unk0x70 = FALSE; - m_unk0x84 = FALSE; + m_reusedPhoneme = FALSE; + m_isPartOfAnimMM = FALSE; } // FUNCTION: LEGO1 0x1004e3d0 @@ -49,7 +49,7 @@ void LegoPhonemePresenter::StartingTickle() if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoAnimMMPresenter")) { entityROI = FindROI(m_roiName.GetData()); - m_unk0x84 = TRUE; + m_isPartOfAnimMM = TRUE; } else { entityROI = CharacterManager()->GetActorROI(m_roiName.GetData(), TRUE); @@ -81,7 +81,7 @@ void LegoPhonemePresenter::StartingTickle() phoneme->SetCount(phoneme->GetCount() + 1); cursor.SetValue(phoneme); - m_unk0x70 = TRUE; + m_reusedPhoneme = TRUE; } } } @@ -139,7 +139,7 @@ void LegoPhonemePresenter::EndAction() if (phoneme->GetCount() == 1) { LegoROI* roi; - if (m_unk0x84) { + if (m_isPartOfAnimMM) { roi = FindROI(m_roiName.GetData()); } else { @@ -150,7 +150,7 @@ void LegoPhonemePresenter::EndAction() CharacterManager()->SetHeadTexture(roi, NULL); } - if (!m_unk0x84) { + if (!m_isPartOfAnimMM) { CharacterManager()->ReleaseActor(m_roiName.GetData()); } @@ -163,7 +163,7 @@ void LegoPhonemePresenter::EndAction() cursor.SetValue(phoneme); } - if (!m_unk0x84) { + if (!m_isPartOfAnimMM) { CharacterManager()->ReleaseActor(m_roiName.GetData()); } } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index cdb20197..383c6d35 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -587,13 +587,13 @@ void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) // FUNCTION: LEGO1 0x1007c440 void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue) { - PALETTEENTRY colorStrucure; + PALETTEENTRY colorStructure; - colorStrucure.peRed = (p_red * 255.0f); - colorStrucure.peGreen = (p_green * 255.0f); - colorStrucure.peBlue = (p_blue * 255.0f); - colorStrucure.peFlags = D3DPAL_RESERVED | PC_NOCOLLAPSE; - m_videoParam.GetPalette()->SetSkyColor(&colorStrucure); + colorStructure.peRed = (p_red * 255.0f); + colorStructure.peGreen = (p_green * 255.0f); + colorStructure.peBlue = (p_blue * 255.0f); + colorStructure.peFlags = D3DPAL_RESERVED | PC_NOCOLLAPSE; + m_videoParam.GetPalette()->SetSkyColor(&colorStructure); m_videoParam.GetPalette()->SetOverrideSkyColor(TRUE); m_3dManager->GetLego3DView()->GetView()->SetBackgroundColor(p_red, p_green, p_blue); } diff --git a/LEGO1/lego/legoomni/src/worlds/act3.cpp b/LEGO1/lego/legoomni/src/worlds/act3.cpp index 344584a6..8e839e3c 100644 --- a/LEGO1/lego/legoomni/src/worlds/act3.cpp +++ b/LEGO1/lego/legoomni/src/worlds/act3.cpp @@ -110,16 +110,16 @@ Act3Script::Script g_unk0x100d95e8[] = {Act3Script::c_tlp053in_RunAnim, Act3Script::c_tlp064la_RunAnim, Act3Script::c_tlp068in_RunAnim}; // FUNCTION: LEGO1 0x10071d40 -void Act3List::Insert(MxS32 p_objectId, MxS32 p_option) +void Act3List::Insert(MxS32 p_objectId, InsertMode p_option) { if (m_unk0x0c) { return; } switch (p_option) { - case 1: + case InsertMode::e_replaceAction: if (!empty()) { - FUN_10071fa0(); + DeleteActionWrapper(); push_back(Act3ListElement(p_objectId, p_option, FALSE)); } else { @@ -127,7 +127,7 @@ void Act3List::Insert(MxS32 p_objectId, MxS32 p_option) push_back(Act3ListElement(p_objectId, p_option, TRUE)); } break; - case 2: + case InsertMode::e_queueAction: if (empty()) { push_back(Act3ListElement(p_objectId, p_option, TRUE)); InvokeAction(Extra::e_start, *g_act3Script, p_objectId, NULL); @@ -136,7 +136,7 @@ void Act3List::Insert(MxS32 p_objectId, MxS32 p_option) push_back(Act3ListElement(p_objectId, p_option, FALSE)); } break; - case 3: + case InsertMode::e_onlyIfEmpty: if (empty()) { push_back(Act3ListElement(p_objectId, p_option, TRUE)); InvokeAction(Extra::e_start, *g_act3Script, p_objectId, NULL); @@ -146,7 +146,7 @@ void Act3List::Insert(MxS32 p_objectId, MxS32 p_option) } // FUNCTION: LEGO1 0x10071fa0 -void Act3List::FUN_10071fa0() +void Act3List::DeleteActionWrapper() { DeleteAction(); } @@ -162,7 +162,7 @@ void Act3List::Clear() } for (Act3List::iterator it = begin(); it != end();) { - if ((*it).m_unk0x08) { + if ((*it).m_hasStarted) { MxDSAction ds; ds.SetAtomId(*g_act3Script); ds.SetObjectId((*it).m_objectId); @@ -173,50 +173,64 @@ void Act3List::Clear() } } +// Removes the element with the given objectId from the list, or the first if `p_objectId` is zero. // FUNCTION: LEGO1 0x100720d0 -void Act3List::FUN_100720d0(MxU32 p_objectId) +void Act3List::RemoveByObjectIdOrFirst(MxU32 p_objectId) { - if (m_unk0x0c == 0) { - MxU32 removed = FALSE; + if (m_unk0x0c) { + return; + } - if (!empty()) { - if (p_objectId != 0) { - for (Act3List::iterator it = begin(); it != end(); it++) { - if ((*it).m_unk0x08 && (*it).m_objectId == p_objectId) { - erase(it); - removed = TRUE; - break; - } - } - } - else { - pop_front(); + MxU32 removed = FALSE; + Act3List::iterator it; + // This iterator appears to be unnecessary - maybe left in by accident, or it was used for assertions. + // Removing it decreases the match percentage. + Act3List::iterator unusedIterator; + + if (empty()) { + return; + } + + if (!p_objectId) { + pop_front(); + removed = TRUE; + } + else { + for (it = begin(); it != end(); it++) { + // Removing this variable decreases the match, but replacing `*it` by `unused` below also does. + Act3ListElement& unused = *it; + + if ((*it).m_hasStarted && (*it).m_objectId == p_objectId) { + erase(it); removed = TRUE; + break; } + } + } - if (removed && size() > 0) { - // TODO: Match - Act3List::iterator it = begin(); - Act3ListElement& item = *(it++); + if (removed && size() > 0) { + it = begin(); + unusedIterator = it; + Act3ListElement& firstItem = front(); + it++; - for (; it != end(); it++) { - if ((*it).m_unk0x04 == 1) { - for (Act3List::iterator it2 = begin(); it2 != it;) { - if ((*it2).m_unk0x08) { - FUN_10071fa0(); - return; - } - - it2 = erase(it2); - } + while (it != end()) { + if ((*it).m_unk0x04 == 1) { + for (Act3List::iterator it2 = begin(); it2 != it; erase(it2++)) { + if ((*it2).m_hasStarted) { + DeleteActionWrapper(); + return; } } - - if (!item.m_unk0x08) { - item.m_unk0x08 = TRUE; - InvokeAction(Extra::e_start, *g_act3Script, item.m_objectId, NULL); - } } + + it++; + unusedIterator++; + } + + if (!firstItem.m_hasStarted) { + firstItem.m_hasStarted = TRUE; + InvokeAction(Extra::e_start, *g_act3Script, firstItem.m_objectId, NULL); } } } @@ -455,14 +469,14 @@ void Act3::TriggerHitSound(undefined4 p_param1) m_bricksterDonutSound = 0; } - m_unk0x4220.Insert(g_bricksterDonutSounds[m_bricksterDonutSound++], 1); + m_unk0x4220.Insert(g_bricksterDonutSounds[m_bricksterDonutSound++], Act3List::e_replaceAction); return; } default: return; } - m_unk0x4220.Insert(objectId, 3); + m_unk0x4220.Insert(objectId, Act3List::e_onlyIfEmpty); } // FUNCTION: LEGO1 0x10072c30 @@ -553,7 +567,7 @@ MxLong Act3::Notify(MxParam& p_param) if (param.GetAction() != NULL && param.GetAction()->GetAtomId() == *g_act3Script) { if (param.GetAction()->GetObjectId() == Act3Script::c_HelicopterDashboard) { MxDSAction action; - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); SetAppCursor(e_cursorArrow); VideoManager()->Get3DManager()->SetFrustrum(45.0f, 0.1f, 125.0f); @@ -613,7 +627,7 @@ MxLong Act3::Notify(MxParam& p_param) } while (length < (MxS32) sizeOfArray(m_helicopterDots)); } else { - m_unk0x4220.FUN_100720d0(param.GetAction()->GetObjectId()); + m_unk0x4220.RemoveByObjectIdOrFirst(param.GetAction()->GetObjectId()); } } break; @@ -633,9 +647,9 @@ MxLong Act3::Notify(MxParam& p_param) case c_notificationEndAnim: if (m_state->m_unk0x08 == 1) { assert(m_copter && m_brickster && m_cop1 && m_cop2); - m_unk0x4220.FUN_100720d0(0); + m_unk0x4220.RemoveByObjectIdOrFirst(0); m_state->m_unk0x08 = 0; - FUN_10015820(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); m_copter->HandleClick(); m_copter->m_state->m_unk0x08 = 1; m_copter->HandleEndAnim((LegoEndAnimNotificationParam&) param); @@ -686,7 +700,7 @@ MxResult Act3::Tickle() if (m_unk0x426c != (Act3Script::Script) 0) { if (AnimationManager()->FUN_10064ee0(m_unk0x426c)) { - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); TickleManager()->UnregisterClient(this); m_unk0x426c = (Act3Script::Script) 0; } @@ -779,6 +793,8 @@ void Act3::GoodEnding(const Matrix4& p_destination) m_copter->m_unk0x1a8, m_copter->m_unk0x1f4 ); + + EmitGameEvent(e_goodEnding); } // FUNCTION: LEGO1 0x10073500 @@ -858,6 +874,8 @@ void Act3::BadEnding(const Matrix4& p_destination) m_copter->m_unk0x1a8, m_copter->m_unk0x1f4 ); + + EmitGameEvent(e_badEnding); } // FUNCTION: LEGO1 0x10073a60 @@ -881,7 +899,7 @@ void Act3::Enable(MxBool p_enable) GameState()->StopArea(LegoGameState::e_infomain); } - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); PlayMusic(JukeboxScript::c_Act3Music); GameState()->m_isDirty = TRUE; diff --git a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp index 7affe1c8..2a9c0772 100644 --- a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp @@ -79,7 +79,7 @@ void ElevatorBottom::ReadyWorld() { LegoWorld::ReadyWorld(); PlayMusic(JukeboxScript::c_InformationCenter_Music); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x100181d0 diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp index 155a839b..61a13858 100644 --- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp @@ -267,7 +267,7 @@ void GasStation::ReadyWorld() break; } - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x10005590 @@ -330,7 +330,7 @@ MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param) break; case GasStationState::e_afterAcceptingQuest: m_state->m_state = GasStationState::e_beforeExitingForQuest; - ((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 7; + ((Act1State*) GameState()->GetState("Act1State"))->m_state = Act1State::e_transitionToTowtrack; m_destLocation = LegoGameState::e_garageExited; m_radio.Stop(); BackgroundAudioManager()->Stop(); diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp index 4a8fa8ac..229e11f8 100644 --- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp +++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp @@ -216,7 +216,7 @@ void Hospital::ReadyWorld() m_setWithCurrentAction = 1; } - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x10074dd0 @@ -367,7 +367,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param) case HospitalState::e_afterAcceptingQuest: m_hospitalState->m_state = HospitalState::e_beforeEnteringAmbulance; act1State = (Act1State*) GameState()->GetState("Act1State"); - act1State->SetUnknown18(9); + act1State->SetState(Act1State::e_transitionToAmbulance); case HospitalState::e_exitToFront: if (m_exited == FALSE) { m_exited = TRUE; @@ -421,7 +421,7 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param) Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); assert(act1State); - act1State->m_unk0x018 = 9; + act1State->m_state = Act1State::e_transitionToAmbulance; m_destLocation = LegoGameState::e_hospitalExited; DeleteObjects( diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index a350199b..bf5a29b4 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -472,7 +472,7 @@ void Infocenter::ReadyWorld() PlayAction(InfomainScript::c_iicx18in_RunAnim); PlayMusic(JukeboxScript::c_InformationCenter_Music); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; case 5: default: { @@ -485,7 +485,7 @@ void Infocenter::ReadyWorld() m_bigInfoBlinkTimer = 1; } - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); if (!m_infocenterState->HasRegistered()) { m_bookAnimationTimer = 1; @@ -496,7 +496,7 @@ void Infocenter::ReadyWorld() case 8: PlayMusic(JukeboxScript::c_InformationCenter_Music); PlayAction(InfomainScript::c_iic043in_RunAnim); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; case 0xf: m_infocenterState->m_unk0x74 = 2; @@ -506,7 +506,7 @@ void Infocenter::ReadyWorld() PlayAction(InfomainScript::c_iicx17in_RunAnim); PlayMusic(JukeboxScript::c_InformationCenter_Music); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; } break; @@ -515,7 +515,7 @@ void Infocenter::ReadyWorld() PlayMusic(JukeboxScript::c_InformationCenter_Music); bgRed->Enable(TRUE); PlayAction(InfomainScript::c_iic043in_RunAnim); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; } @@ -545,7 +545,7 @@ void Infocenter::ReadyWorld() PlayAction(script); InputManager()->DisableInputProcessing(); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; } @@ -560,7 +560,7 @@ void Infocenter::ReadyWorld() PlayMusic(JukeboxScript::c_InformationCenter_Music); bgRed->Enable(TRUE); PlayAction(InfomainScript::c_iic043in_RunAnim); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; } @@ -597,7 +597,7 @@ void Infocenter::ReadyWorld() PlayAction(script); InputManager()->DisableInputProcessing(); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; } @@ -610,7 +610,7 @@ void Infocenter::ReadyWorld() } m_infocenterState->m_unk0x74 = 11; - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x1006f9a0 @@ -1291,7 +1291,7 @@ void Infocenter::StopCutscene() VideoManager()->EnableFullScreenMovie(FALSE); InputManager()->SetUnknown335(FALSE); SetAppCursor(e_cursorArrow); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x10070d00 diff --git a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp index c546744a..8f92a323 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp @@ -88,7 +88,7 @@ void InfocenterDoor::ReadyWorld() { LegoWorld::ReadyWorld(); PlayMusic(JukeboxScript::c_InformationCenter_Music); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x10037a90 diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index f275430c..5e4f983f 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -142,11 +142,11 @@ MxLong Isle::Notify(MxParam& p_param) break; case c_notificationButtonUp: case c_notificationButtonDown: - switch (m_act1state->m_unk0x018) { - case 3: + switch (m_act1state->m_state) { + case Act1State::e_pizza: result = m_pizza->Notify(p_param); break; - case 10: + case Act1State::e_ambulance: result = m_ambulance->Notify(p_param); break; } @@ -155,14 +155,14 @@ MxLong Isle::Notify(MxParam& p_param) result = HandleControl((LegoControlManagerNotificationParam&) p_param); break; case c_notificationEndAnim: - switch (m_act1state->m_unk0x018) { - case 4: + switch (m_act1state->m_state) { + case Act1State::e_helicopter: result = UserActor()->Notify(p_param); break; - case 8: + case Act1State::e_towtrack: result = m_towtrack->Notify(p_param); break; - case 10: + case Act1State::e_ambulance: result = m_ambulance->Notify(p_param); break; } @@ -187,18 +187,18 @@ MxLong Isle::HandleEndAction(MxEndActionNotificationParam& p_param) { MxLong result; - switch (m_act1state->m_unk0x018) { - case 2: + switch (m_act1state->m_state) { + case Act1State::e_elevator: HandleElevatorEndAction(); result = 1; break; - case 3: + case Act1State::e_pizza: result = m_pizza->Notify(p_param); break; - case 8: + case Act1State::e_towtrack: result = m_towtrack->Notify(p_param); break; - case 10: + case Act1State::e_ambulance: result = m_ambulance->Notify(p_param); break; default: @@ -241,12 +241,12 @@ void Isle::HandleElevatorEndAction() case Act1State::c_floor1: m_destLocation = LegoGameState::e_infomain; TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; break; case Act1State::c_floor2: if (m_act1state->m_unk0x01e) { m_act1state->m_unk0x01e = FALSE; - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; InputManager()->EnableInputProcessing(); } else { @@ -258,7 +258,7 @@ void Isle::HandleElevatorEndAction() case Act1State::c_floor3: m_destLocation = LegoGameState::e_elevopen; TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; break; } } @@ -270,14 +270,14 @@ void Isle::ReadyWorld() if (m_act1state->GetUnknown21()) { GameState()->SwitchArea(LegoGameState::e_infomain); - m_act1state->SetUnknown18(0); + m_act1state->SetState(Act1State::e_none); m_act1state->SetUnknown21(0); } else if (GameState()->GetLoadedAct() != LegoGameState::e_act1) { EnableAnimations(TRUE); FUN_10032620(); m_act1state->PlaceActors(); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } } @@ -289,7 +289,7 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param) switch (p_param.m_clickedObjectId) { case IsleScript::c_ElevRide_Info_Ctl: - m_act1state->m_unk0x018 = 2; + m_act1state->m_state = Act1State::e_elevator; switch (m_act1state->m_elevFloor) { case Act1State::c_floor1: @@ -309,7 +309,7 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param) m_act1state->m_elevFloor = Act1State::c_floor1; break; case IsleScript::c_ElevRide_Two_Ctl: - m_act1state->m_unk0x018 = 2; + m_act1state->m_state = Act1State::e_elevator; switch (m_act1state->m_elevFloor) { case Act1State::c_floor1: @@ -329,7 +329,7 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param) m_act1state->m_elevFloor = Act1State::c_floor2; break; case IsleScript::c_ElevRide_Three_Ctl: - m_act1state->m_unk0x018 = 2; + m_act1state->m_state = Act1State::e_elevator; switch (m_act1state->m_elevFloor) { case Act1State::c_floor1: @@ -478,14 +478,14 @@ MxLong Isle::HandlePathStruct(LegoPathStructNotificationParam& p_param) } } - switch (m_act1state->m_unk0x018) { - case 3: + switch (m_act1state->m_state) { + case Act1State::e_pizza: result = m_pizza->Notify(p_param); break; - case 8: + case Act1State::e_towtrack: result = m_towtrack->Notify(p_param); break; - case 10: + case Act1State::e_ambulance: result = m_ambulance->Notify(p_param); break; } @@ -502,7 +502,7 @@ MxLong Isle::HandlePathStruct(LegoPathStructNotificationParam& p_param) result = 1; break; case 0x131: - if (m_act1state->m_unk0x018 != 10) { + if (m_act1state->m_state != Act1State::e_ambulance) { AnimationManager()->FUN_10064740(NULL); } result = 1; @@ -558,7 +558,7 @@ void Isle::Enable(MxBool p_enable) EnableAnimations(TRUE); - if (m_act1state->m_unk0x018 == 0) { + if (m_act1state->m_state == Act1State::e_none) { MxS32 locations[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; for (MxU32 i = 0; i < 5; i++) { @@ -595,7 +595,7 @@ void Isle::Enable(MxBool p_enable) break; case LegoGameState::e_jetrace2: if (((JetskiRaceState*) GameState()->GetState("JetskiRaceState"))->m_unk0x28 == 2) { - m_act1state->m_unk0x018 = 5; + m_act1state->m_state = Act1State::e_transitionToJetski; } PlaceActor(UserActor()); @@ -704,10 +704,10 @@ void Isle::Enable(MxBool p_enable) break; } - switch (m_act1state->m_unk0x018) { - case 0: - case 1: - m_act1state->m_unk0x018 = 0; + switch (m_act1state->m_state) { + case Act1State::e_none: + case Act1State::e_initial: + m_act1state->m_state = Act1State::e_none; if (GameState()->m_currentArea == LegoGameState::e_pizzeriaExterior) { AnimationManager()->FUN_10064740(NULL); @@ -728,7 +728,7 @@ void Isle::Enable(MxBool p_enable) } } break; - case 5: { + case Act1State::e_transitionToJetski: { ((IslePathActor*) UserActor()) ->SpawnPlayer( LegoGameState::e_jetrace2, @@ -756,12 +756,12 @@ void Isle::Enable(MxBool p_enable) ->FUN_10060dc0(script, NULL, TRUE, LegoAnimationManager::e_unk1, NULL, FALSE, FALSE, TRUE, FALSE); } - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; EnableAnimations(FALSE); AnimationManager()->FUN_10064670(NULL); break; } - case 6: { + case Act1State::e_transitionToRacecar: { GameState()->m_currentArea = LegoGameState::e_carraceExterior; ((IslePathActor*) UserActor()) ->SpawnPlayer( @@ -790,21 +790,21 @@ void Isle::Enable(MxBool p_enable) ->FUN_10060dc0(script, NULL, TRUE, LegoAnimationManager::e_unk1, NULL, FALSE, FALSE, TRUE, FALSE); } - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; EnableAnimations(TRUE); break; } - case 7: - m_act1state->m_unk0x018 = 8; + case Act1State::e_transitionToTowtrack: + m_act1state->m_state = Act1State::e_towtrack; AnimationManager()->FUN_1005f6d0(FALSE); AnimationManager()->EnableCamAnims(FALSE); g_isleFlags &= ~c_playMusic; - m_towtrack->FUN_1004dab0(); + m_towtrack->Init(); break; - case 9: - m_act1state->m_unk0x018 = 10; + case Act1State::e_transitionToAmbulance: + m_act1state->m_state = Act1State::e_ambulance; AnimationManager()->FUN_1005f6d0(FALSE); AnimationManager()->EnableCamAnims(FALSE); @@ -813,7 +813,7 @@ void Isle::Enable(MxBool p_enable) m_ambulance->Init(); break; case 11: - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; ((IslePathActor*) UserActor()) ->SpawnPlayer( LegoGameState::e_jukeboxExterior, @@ -828,18 +828,18 @@ void Isle::Enable(MxBool p_enable) SetAppCursor(e_cursorArrow); - if (m_act1state->m_unk0x018 != 8 && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_elevride) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_polidoor) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_garadoor) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_bike) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_dunecar) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_motocycle) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_copter) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_jetski) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_skateboard) && - (m_act1state->m_unk0x018 != 0 || GameState()->m_currentArea != LegoGameState::e_jetrace2)) { - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + if (m_act1state->m_state != Act1State::e_towtrack && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_elevride) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_polidoor) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_garadoor) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_bike) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_dunecar) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_motocycle) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_copter) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_jetski) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_skateboard) && + (m_act1state->m_state != Act1State::e_none || GameState()->m_currentArea != LegoGameState::e_jetrace2)) { + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } SetROIVisible("stretch", FALSE); @@ -897,7 +897,7 @@ MxLong Isle::HandleTransitionEnd() DeleteObjects(&m_atomId, IsleScript::c_Avo900Ps_PlayWav, IsleScript::c_Avo907Ps_PlayWav); if (m_destLocation != LegoGameState::e_skateboard) { - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; } switch (m_destLocation) { @@ -961,7 +961,7 @@ MxLong Isle::HandleTransitionEnd() m_destLocation = LegoGameState::e_undefined; VariableTable()->SetVariable("VISIBILITY", "Show Gas"); AnimationManager()->Resume(); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); SetAppCursor(e_cursorArrow); SetIsWorldActive(TRUE); break; @@ -971,7 +971,7 @@ MxLong Isle::HandleTransitionEnd() m_destLocation = LegoGameState::e_undefined; VariableTable()->SetVariable("VISIBILITY", "Show Policsta"); AnimationManager()->Resume(); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); SetAppCursor(e_cursorArrow); SetIsWorldActive(TRUE); break; @@ -1023,7 +1023,7 @@ MxLong Isle::HandleTransitionEnd() break; case LegoGameState::e_ambulance: m_act1state->m_unk0x01f = TRUE; - m_act1state->m_unk0x018 = 10; + m_act1state->m_state = Act1State::e_ambulance; FUN_10032d30(IsleScript::c_AmbulanceFuelMeter, JukeboxScript::c_MusicTheme1, NULL, TRUE); if (!m_act1state->m_unk0x01f) { @@ -1032,7 +1032,7 @@ MxLong Isle::HandleTransitionEnd() break; case LegoGameState::e_towtrack: m_act1state->m_unk0x01f = TRUE; - m_act1state->m_unk0x018 = 8; + m_act1state->m_state = Act1State::e_towtrack; FUN_10032d30(IsleScript::c_TowFuelMeter, JukeboxScript::c_MusicTheme1, NULL, TRUE); if (!m_act1state->m_unk0x01f) { @@ -1082,7 +1082,7 @@ void Isle::FUN_10032d30( VariableTable()->SetVariable(g_varCAMERALOCATION, p_cameraLocation); } - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); SetAppCursor(e_cursorArrow); m_destLocation = LegoGameState::e_undefined; m_act1state->m_unk0x01f = FALSE; @@ -1167,7 +1167,7 @@ void Isle::CreateState() m_act1state = (Act1State*) GameState()->GetState("Act1State"); if (!m_act1state) { m_act1state = (Act1State*) GameState()->CreateState("Act1State"); - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; } m_radio.CreateState(); @@ -1193,20 +1193,20 @@ MxBool Isle::Escape() m_radio.Stop(); BackgroundAudioManager()->Stop(); - switch (m_act1state->m_unk0x018) { - case 3: + switch (m_act1state->m_state) { + case Act1State::e_pizza: if (UserActor() != NULL) { m_pizza->StopActions(); m_pizza->FUN_100382b0(); } break; - case 8: + case Act1State::e_towtrack: if (UserActor() != NULL && !UserActor()->IsA("TowTrack")) { m_towtrack->StopActions(); - m_towtrack->FUN_1004dbe0(); + m_towtrack->Reset(); } break; - case 10: + case Act1State::e_ambulance: if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) { m_ambulance->StopActions(); m_ambulance->Reset(); @@ -1239,7 +1239,7 @@ MxBool Isle::Escape() VariableTable()->SetVariable("VISIBILITY", "Show Gas"); } - m_act1state->m_unk0x018 = 0; + m_act1state->m_state = Act1State::e_none; m_destLocation = LegoGameState::e_infomain; return TRUE; } @@ -1247,21 +1247,21 @@ MxBool Isle::Escape() // FUNCTION: LEGO1 0x10033350 void Isle::FUN_10033350() { - if (m_act1state->m_unk0x018 == 10) { + if (m_act1state->m_state == Act1State::e_ambulance) { if (UserActor() != NULL && !UserActor()->IsA("Ambulance")) { m_ambulance->StopActions(); m_ambulance->Reset(); } } - if (m_act1state->m_unk0x018 == 8) { + if (m_act1state->m_state == Act1State::e_towtrack) { if (UserActor() != NULL && !UserActor()->IsA("TowTrack")) { m_towtrack->StopActions(); - m_towtrack->FUN_1004dbe0(); + m_towtrack->Reset(); } } - if (m_act1state->m_unk0x018 == 3) { + if (m_act1state->m_state == Act1State::e_pizza) { if (UserActor() != NULL) { m_pizza->StopActions(); m_pizza->FUN_100382b0(); @@ -1293,7 +1293,7 @@ void Isle::FUN_10033350() Act1State::Act1State() { m_elevFloor = Act1State::c_floor1; - m_unk0x018 = 1; + m_state = Act1State::e_initial; m_unk0x01e = FALSE; m_cptClickDialogue = Playlist((MxU32*) g_cptClickDialogue, sizeOfArray(g_cptClickDialogue), Playlist::e_loop); m_unk0x01f = FALSE; diff --git a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp index a92f493d..db244e00 100644 --- a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp +++ b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp @@ -211,7 +211,7 @@ MxBool JukeBox::HandleControl(LegoControlManagerNotificationParam& p_param) break; case JukeboxwScript::c_Note_Ctl: Act1State* act1State = (Act1State*) GameState()->GetState("Act1State"); - act1State->m_unk0x018 = 11; + act1State->m_state = Act1State::e_jukebox; m_destLocation = LegoGameState::Area::e_jukeboxExterior; TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, 0, FALSE); break; @@ -247,7 +247,7 @@ MxResult JukeBox::Tickle() if (m_unk0x100 == 1) { m_unk0x100 = 0; - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp index 094bdac9..b3f92433 100644 --- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp @@ -192,7 +192,7 @@ MxResult LegoAct2::Tickle() case 2: if (g_unk0x100f4474) { if (AnimationManager()->FUN_10064ee0(g_unk0x100f4474)) { - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); g_unk0x100f4474 = (Act2mainScript::Script) 0; } } @@ -200,7 +200,7 @@ MxResult LegoAct2::Tickle() m_unk0x10d0 += 50; break; case 3: - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); m_unk0x10d0 = 0; m_unk0x10c4 = 4; FUN_10052560(Act2mainScript::c_tja009ni_RunAnim, TRUE, TRUE, NULL, NULL, NULL); @@ -540,7 +540,7 @@ void LegoAct2::Enable(MxBool p_enable) GameState()->StopArea(LegoGameState::e_infomain); } - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); if (m_unk0x10c4 != 6 && m_unk0x10c4 != 12) { PlayMusic(m_music); @@ -939,6 +939,7 @@ MxResult LegoAct2::BadEnding() MxTrace("Bad End of Act2\n"); m_unk0x10c4 = 14; + EmitGameEvent(e_badEnding); return SUCCESS; } diff --git a/LEGO1/lego/legoomni/src/worlds/police.cpp b/LEGO1/lego/legoomni/src/worlds/police.cpp index 64992771..16297b76 100644 --- a/LEGO1/lego/legoomni/src/worlds/police.cpp +++ b/LEGO1/lego/legoomni/src/worlds/police.cpp @@ -95,7 +95,7 @@ void Police::ReadyWorld() { LegoWorld::ReadyWorld(); PlayMusic(JukeboxScript::c_PoliceStation_Music); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x1005e550 diff --git a/LEGO1/lego/legoomni/src/worlds/score.cpp b/LEGO1/lego/legoomni/src/worlds/score.cpp index 69b4305a..14b91a18 100644 --- a/LEGO1/lego/legoomni/src/worlds/score.cpp +++ b/LEGO1/lego/legoomni/src/worlds/score.cpp @@ -159,7 +159,7 @@ void Score::ReadyWorld() PlayMusic(JukeboxScript::c_InformationCenter_Music); } - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x100016d0 diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index 8ec3ee2d..9026c245 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -524,7 +524,7 @@ LegoAnimNodeData::LegoAnimNodeData() m_translationKeys = NULL; m_roiIndex = 0; m_rotationKeys = NULL; - m_unk0x22 = 0; + m_boundaryIndex = 0; m_scaleKeys = NULL; m_morphKeys = NULL; m_translationIndex = 0; diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index 372128b5..7a03d99c 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -190,7 +190,7 @@ class LegoAnimNodeData : public LegoTreeNodeData { LegoU16 GetROIIndex() { return m_roiIndex; } // FUNCTION: BETA10 0x1005d5c0 - LegoU16 GetUnknown0x22() { return m_unk0x22; } + LegoU16 GetBoundaryIndex() { return m_boundaryIndex; } // FUNCTION: BETA10 0x10073b80 LegoRotationKey* GetRotationKey(MxS32 index) { return &m_rotationKeys[index]; } @@ -217,7 +217,7 @@ class LegoAnimNodeData : public LegoTreeNodeData { void SetROIIndex(LegoU16 p_roiIndex) { m_roiIndex = p_roiIndex; } // FUNCTION: BETA10 0x1005f2e0 - void SetUnknown0x22(LegoU16 p_unk0x22) { m_unk0x22 = p_unk0x22; } + void SetBoundaryIndex(LegoU16 p_boundaryIndex) { m_boundaryIndex = p_boundaryIndex; } LegoResult CreateLocalTransform(LegoTime p_time, Matrix4& p_matrix) { @@ -280,7 +280,7 @@ class LegoAnimNodeData : public LegoTreeNodeData { LegoScaleKey* m_scaleKeys; // 0x18 LegoMorphKey* m_morphKeys; // 0x1c LegoU16 m_roiIndex; // 0x20 - LegoU16 m_unk0x22; // 0x22 + LegoU16 m_boundaryIndex; // 0x22 LegoU32 m_translationIndex; // 0x24 LegoU32 m_rotationIndex; // 0x28 LegoU32 m_scaleIndex; // 0x2c diff --git a/LEGO1/lego/sources/misc/legoutil.h b/LEGO1/lego/sources/misc/legoutil.h index 871a9b72..78f52d0f 100644 --- a/LEGO1/lego/sources/misc/legoutil.h +++ b/LEGO1/lego/sources/misc/legoutil.h @@ -59,4 +59,12 @@ inline T RToD(T p_r) return p_r * 180.0F / 3.1416F; } +template +struct overloaded : Ts... { + using Ts::operator()...; +}; + +template +overloaded(Ts...) -> overloaded; + #endif // __LEGOUTIL_H diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index 7b02dd01..260e51e5 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -115,7 +115,7 @@ LegoROI::~LegoROI() // FUNCTION: LEGO1 0x100a84a0 // FUNCTION: BETA10 0x10189b99 LegoResult LegoROI::Read( - OrientableROI* p_unk0xd4, + OrientableROI* p_parentROI, Tgl::Renderer* p_renderer, ViewLODListManager* p_viewLODListManager, LegoTextureContainer* p_textureContainer, @@ -135,7 +135,7 @@ LegoResult LegoROI::Read( LegoSphere sphere; LegoBox box; - m_parentROI = p_unk0xd4; + m_parentROI = p_parentROI; if (p_storage->Read(&length, sizeof(LegoU32)) != SUCCESS) { goto done; @@ -178,11 +178,11 @@ LegoResult LegoROI::Read( textureName = NULL; } - if (p_storage->Read(&m_unk0x100, sizeof(undefined)) != SUCCESS) { + if (p_storage->Read(&m_sharedLodList, sizeof(LegoBool)) != SUCCESS) { goto done; } - if (m_unk0x100) { + if (m_sharedLodList) { for (roiLength = strlen(m_name); roiLength; roiLength--) { if (m_name[roiLength - 1] < '0' || m_name[roiLength - 1] > '9') { break; @@ -390,7 +390,7 @@ LegoROI* LegoROI::FindChildROI(const LegoChar* p_name, LegoROI* p_roi) // FUNCTION: LEGO1 0x100a8da0 // FUNCTION: BETA10 0x1018a9fb -LegoResult LegoROI::ApplyAnimationTransformation( +LegoResult LegoROI::ApplyChildAnimationTransformation( LegoTreeNode* p_node, const Matrix4& p_matrix, LegoTime p_time, @@ -411,11 +411,11 @@ LegoResult LegoROI::ApplyAnimationTransformation( roi->m_local2world.Product(mat, p_matrix); roi->UpdateWorldData(); - LegoBool und = data->GetVisibility(p_time); - roi->SetVisibility(und); + LegoBool visibility = data->GetVisibility(p_time); + roi->SetVisibility(visibility); for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { - ApplyAnimationTransformation(p_node->GetChild(i), roi->m_local2world, p_time, roi); + ApplyChildAnimationTransformation(p_node->GetChild(i), roi->m_local2world, p_time, roi); } } else { @@ -427,7 +427,7 @@ LegoResult LegoROI::ApplyAnimationTransformation( // FUNCTION: LEGO1 0x100a8e80 // FUNCTION: BETA10 0x1018ab3a -void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap) +void LegoROI::ApplyAnimationTransformation(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap) { MxMatrix mat; @@ -439,11 +439,11 @@ void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t roi->m_local2world.Product(mat, p_matrix); roi->UpdateWorldData(); - LegoBool und = data->GetVisibility(p_time); - roi->SetVisibility(und); + LegoBool visiblity = data->GetVisibility(p_time); + roi->SetVisibility(visiblity); for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { - FUN_100a8e80(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap); + ApplyAnimationTransformation(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap); } } else { @@ -451,14 +451,14 @@ void LegoROI::FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t local2world.Product(mat, p_matrix); for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { - FUN_100a8e80(p_node->GetChild(i), local2world, p_time, p_roiMap); + ApplyAnimationTransformation(p_node->GetChild(i), local2world, p_time, p_roiMap); } } } // FUNCTION: LEGO1 0x100a8fd0 // FUNCTION: BETA10 0x1018ac81 -void LegoROI::FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap) +void LegoROI::ApplyTransform(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap) { MxMatrix mat; @@ -470,7 +470,7 @@ void LegoROI::FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t roi->m_local2world.Product(mat, p_matrix); for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { - FUN_100a8fd0(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap); + ApplyTransform(p_node->GetChild(i), roi->m_local2world, p_time, p_roiMap); } } else { @@ -478,7 +478,7 @@ void LegoROI::FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_t local2world.Product(mat, p_matrix); for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { - FUN_100a8fd0(p_node->GetChild(i), local2world, p_time, p_roiMap); + ApplyTransform(p_node->GetChild(i), local2world, p_time, p_roiMap); } } } @@ -493,7 +493,7 @@ LegoResult LegoROI::SetFrame(LegoAnim* p_anim, LegoTime p_time) mat = m_local2world; mat.SetIdentity(); // this clears the matrix, assignment above is redundant - return ApplyAnimationTransformation(root, mat, p_time, this); + return ApplyChildAnimationTransformation(root, mat, p_time, this); } // FUNCTION: LEGO1 0x100a9170 @@ -756,7 +756,7 @@ TimeROI::TimeROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, LegoTime p_t // FUNCTION: LEGO1 0x100a9b40 // FUNCTION: BETA10 0x1018bbf0 -void TimeROI::FUN_100a9b40(Matrix4& p_matrix, LegoTime p_time) +void TimeROI::CalculateWorldVelocity(Matrix4& p_matrix, LegoTime p_time) { LegoTime time = p_time - m_time; diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index bef2c580..00452334 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -27,21 +27,26 @@ class LegoROI : public ViewROI { ~LegoROI() override; LegoResult Read( - OrientableROI* p_unk0xd4, + OrientableROI* p_parentROI, Tgl::Renderer* p_renderer, ViewLODListManager* p_viewLODListManager, LegoTextureContainer* p_textureContainer, LegoStorage* p_storage ); LegoROI* FindChildROI(const LegoChar* p_name, LegoROI* p_roi); - LegoResult ApplyAnimationTransformation( + LegoResult ApplyChildAnimationTransformation( LegoTreeNode* p_node, const Matrix4& p_matrix, LegoTime p_time, LegoROI* p_roi ); - static void FUN_100a8e80(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap); - static void FUN_100a8fd0(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap); + static void ApplyAnimationTransformation( + LegoTreeNode* p_node, + Matrix4& p_matrix, + LegoTime p_time, + LegoROI** p_roiMap + ); + static void ApplyTransform(LegoTreeNode* p_node, Matrix4& p_matrix, LegoTime p_time, LegoROI** p_roiMap); LegoResult SetFrame(LegoAnim* p_anim, LegoTime p_time); LegoResult SetLodColor(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult SetTextureInfo(LegoTextureInfo* p_textureInfo); @@ -92,10 +97,10 @@ class LegoROI : public ViewROI { // LegoROI::`scalar deleting destructor' private: - LegoChar* m_name; // 0xe4 - BoundingSphere m_sphere; // 0xe8 - undefined m_unk0x100; // 0x100 - LegoEntity* m_entity; // 0x104 + LegoChar* m_name; // 0xe4 + BoundingSphere m_sphere; // 0xe8 + LegoBool m_sharedLodList; // 0x100 + LegoEntity* m_entity; // 0x104 friend class DebugViewer; }; @@ -107,7 +112,7 @@ class TimeROI : public LegoROI { public: TimeROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, LegoTime p_time); - void FUN_100a9b40(Matrix4& p_matrix, LegoTime p_time); + void CalculateWorldVelocity(Matrix4& p_matrix, LegoTime p_time); // SYNTHETIC: LEGO1 0x100a9ad0 // SYNTHETIC: BETA10 0x1018c540 diff --git a/LEGO1/mxdirectx/legodxinfo.cpp b/LEGO1/mxdirectx/legodxinfo.cpp index 3cc66b56..ff404b90 100644 --- a/LEGO1/mxdirectx/legodxinfo.cpp +++ b/LEGO1/mxdirectx/legodxinfo.cpp @@ -56,7 +56,7 @@ int LegoDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) GUID4 deviceGuid; memcpy(&deviceGuid, &p_guid, sizeof(GUID4)); - for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + for (list::iterator it = m_ddInfo.begin(); it != m_ddInfo.end(); it++, i++) { if (p_deviceNum >= 0 && p_deviceNum < i) { return -1; } @@ -91,7 +91,7 @@ int LegoDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3 int i = 0; - for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { + for (list::iterator it = m_ddInfo.begin(); it != m_ddInfo.end(); it++) { p_driver = &*it; for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); @@ -115,7 +115,7 @@ int LegoDeviceEnumerate::FormatDeviceName(char* p_buffer, const MxDriver* p_ddIn int number = 0; assert(p_ddInfo && p_d3dInfo); - for (list::const_iterator it = m_list.begin(); it != m_list.end(); it++, number++) { + for (list::const_iterator it = m_ddInfo.begin(); it != m_ddInfo.end(); it++, number++) { if (&(*it) == p_ddInfo) { GUID4 guid; memcpy(&guid, p_d3dInfo->m_guid, sizeof(GUID4)); @@ -138,7 +138,7 @@ int LegoDeviceEnumerate::BETA_1011cc65(int p_idx, char* p_buffer) int i = 0; int j = 0; - for (list::iterator it = m_list.begin(); it != m_list.end(); it++, i++) { + for (list::iterator it = m_ddInfo.begin(); it != m_ddInfo.end(); it++, i++) { MxDriver& driver = *it; for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { @@ -165,14 +165,14 @@ int LegoDeviceEnumerate::GetBestDevice() return -1; } - if (m_list.size() == 0) { + if (m_ddInfo.size() == 0) { return -1; } int j = 0; int k = -1; - for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { + for (list::iterator it = m_ddInfo.begin(); it != m_ddInfo.end(); it++) { MxDriver& driver = *it; for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { @@ -199,7 +199,7 @@ int LegoDeviceEnumerate::FUN_1009d210() return -1; } - for (list::iterator it = m_list.begin(); it != m_list.end();) { + for (list::iterator it = m_ddInfo.begin(); it != m_ddInfo.end();) { MxDriver& driver = *it; for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { @@ -212,14 +212,14 @@ int LegoDeviceEnumerate::FUN_1009d210() } if (!driver.m_devices.size()) { - m_list.erase(it++); + m_ddInfo.erase(it++); } else { it++; } } - if (!m_list.size()) { + if (!m_ddInfo.size()) { return -1; } @@ -231,7 +231,7 @@ int LegoDeviceEnumerate::FUN_1009d210() // FUNCTION: BETA10 0x1011d235 unsigned char LegoDeviceEnumerate::FUN_1009d3d0(Direct3DDeviceInfo& p_device) { - if (m_list.size() <= 0) { + if (m_ddInfo.size() <= 0) { return FALSE; } @@ -246,7 +246,7 @@ unsigned char LegoDeviceEnumerate::FUN_1009d3d0(Direct3DDeviceInfo& p_device) } } - MxDriver& front = m_list.front(); + MxDriver& front = m_ddInfo.front(); for (list::iterator it = front.m_devices.begin(); it != front.m_devices.end(); it++) { if ((&*it) == &p_device) { return TRUE; diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index 0dae36e1..7f12d147 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -234,7 +234,7 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri assert(d); int i = 0; - for (list::iterator it = p_deviceEnumerate.m_list.begin(); it != p_deviceEnumerate.m_list.end(); + for (list::iterator it = p_deviceEnumerate.m_ddInfo.begin(); it != p_deviceEnumerate.m_ddInfo.end(); it++, i++) { MxDriver& driver = *it; diff --git a/LEGO1/mxdirectx/mxdirectxinfo.cpp b/LEGO1/mxdirectx/mxdirectxinfo.cpp index 639a2864..3451b8fc 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.cpp +++ b/LEGO1/mxdirectx/mxdirectxinfo.cpp @@ -30,13 +30,12 @@ MxAssignedDevice::~MxAssignedDevice() } // FUNCTION: BETA10 0x1011d7f0 -MxDriver::MxDriver(LPGUID p_guid) +MxDriver::MxDriver() { m_guid = NULL; m_driverDesc = NULL; m_driverName = NULL; memset(&m_ddCaps, 0, sizeof(m_ddCaps)); - // TODO: ret vs ret 4 } // FUNCTION: CONFIG 0x00401180 @@ -99,6 +98,12 @@ void MxDriver::Init(LPGUID p_guid, LPCSTR p_driverDesc, LPCSTR p_driverName) } } +// FUNCTION: BETA10 0x1011dba4 +Direct3DDeviceInfo::Direct3DDeviceInfo() +{ + memset(this, 0, sizeof(*this)); +} + // FUNCTION: CONFIG 0x401420 // FUNCTION: LEGO1 0x1009bd20 // FUNCTION: BETA10 0x1011dbd0 @@ -198,7 +203,7 @@ MxDeviceEnumerate::~MxDeviceEnumerate() BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { MxDriver driver(p_guid, p_driverDesc, p_driverName); - m_list.push_back(driver); + m_ddInfo.push_back(driver); // Must be zeroed because held resources are copied by pointer only // and should not be freed at the end of this function @@ -209,46 +214,47 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc LPDIRECT3D2 lpDirect3d2 = NULL; LPDIRECTDRAW lpDD = NULL; - MxDriver& newDevice = m_list.back(); + MxDriver& newDevice = m_ddInfo.back(); HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); if (result != DD_OK) { BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); - } - else { - result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); - if (result != DD_OK) { - BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result)); - } - else { - newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); - result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); - - if (result != DD_OK) { - BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); - } - else { - result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); - - if (result != DD_OK) { - BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); - } - else { - result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); - - if (result != DD_OK) { - BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); - } - else { - if (!newDevice.m_devices.size()) { - m_list.pop_back(); - } - } - } - } - } + goto done; } + result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); + if (result != DD_OK) { + BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result)); + goto done; + } + + newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); + result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); + + if (result != DD_OK) { + BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); + goto done; + } + + result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); + + if (result != DD_OK) { + BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); + goto done; + } + + result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + + if (result != DD_OK) { + BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + goto done; + } + + if (!newDevice.m_devices.size()) { + m_ddInfo.pop_back(); + } + +done: if (lpDirect3d2) { lpDirect3d2->Release(); } @@ -281,15 +287,14 @@ HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( LPSTR p_deviceName, LPD3DDEVICEDESC p_HWDesc, LPD3DDEVICEDESC p_HELDesc, - LPVOID p_context + LPVOID p_d ) { - if (p_context == NULL) { + if (p_d == NULL) { assert(0); } - return ((MxDeviceEnumerate*) p_context) - ->EnumDevicesCallback(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); + return ((MxDeviceEnumerate*) p_d)->EnumDevicesCallback(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); } // FUNCTION: CONFIG 0x00401cd0 @@ -304,7 +309,7 @@ HRESULT MxDeviceEnumerate::EnumDevicesCallback( ) { Direct3DDeviceInfo device(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); - m_list.back().m_devices.push_back(device); + m_ddInfo.back().m_devices.push_back(device); memset(&device, 0, sizeof(device)); return DDENUMRET_OK; } @@ -334,13 +339,10 @@ int MxDeviceEnumerate::DoEnumerate(HWND hWnd) // FUNCTION: LEGO1 0x1009c710 // FUNCTION: BETA10 0x1011e476 BOOL CALLBACK -MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context) +MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_d) { - if (p_context == NULL) { - assert(0); - } - - return ((MxDeviceEnumerate*) p_context)->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); + assert(p_d); + return ((MxDeviceEnumerate*) p_d)->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); } // FUNCTION: CONFIG 0x00401e30 @@ -351,79 +353,123 @@ const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) switch (p_error) { case DD_OK: return "No error."; - case DDERR_GENERIC: - return "Generic failure."; - case DDERR_UNSUPPORTED: - return "Action not supported."; - case DDERR_INVALIDPARAMS: - return "One or more of the parameters passed to the function are incorrect."; - case DDERR_OUTOFMEMORY: - return "DirectDraw does not have enough memory to perform the operation."; - case DDERR_CANNOTATTACHSURFACE: - return "This surface can not be attached to the requested surface."; case DDERR_ALREADYINITIALIZED: return "This object is already initialized."; - case DDERR_CURRENTLYNOTAVAIL: - return "Support is currently not available."; + case DDERR_BLTFASTCANTCLIP: + return "Return if a clipper object is attached to the source surface passed into a BltFast call."; + case DDERR_CANNOTATTACHSURFACE: + return "This surface can not be attached to the requested surface."; case DDERR_CANNOTDETACHSURFACE: return "This surface can not be detached from the requested surface."; - case DDERR_HEIGHTALIGN: - return "Height of rectangle provided is not a multiple of reqd alignment."; + case DDERR_CANTCREATEDC: + return "Windows can not create any more DCs."; + case DDERR_CANTDUPLICATE: + return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."; + case DDERR_CLIPPERISUSINGHWND: + return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."; + case DDERR_COLORKEYNOTSET: + return "No src color key specified for this operation."; + case DDERR_CURRENTLYNOTAVAIL: + return "Support is currently not available."; + case DDERR_DIRECTDRAWALREADYCREATED: + return "A DirectDraw object representing this driver has already been created for this process."; case DDERR_EXCEPTION: return "An exception was encountered while performing the requested operation."; - case DDERR_INVALIDCAPS: - return "One or more of the caps bits passed to the callback are incorrect."; + case DDERR_EXCLUSIVEMODEALREADYSET: + return "An attempt was made to set the cooperative level when it was already set to exclusive."; + case DDERR_GENERIC: + return "Generic failure."; + case DDERR_HEIGHTALIGN: + return "Height of rectangle provided is not a multiple of reqd alignment."; + case DDERR_HWNDALREADYSET: + return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or " + "palettes created."; + case DDERR_HWNDSUBCLASSED: + return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring " + "state."; + case DDERR_IMPLICITLYCREATED: + return "This surface can not be restored because it is an implicitly created surface."; case DDERR_INCOMPATIBLEPRIMARY: return "Unable to match primary surface creation request with existing primary surface."; - case DDERR_INVALIDMODE: - return "DirectDraw does not support the requested mode."; + case DDERR_INVALIDCAPS: + return "One or more of the caps bits passed to the callback are incorrect."; case DDERR_INVALIDCLIPLIST: return "DirectDraw does not support the provided cliplist."; - case DDERR_INVALIDPIXELFORMAT: - return "The pixel format was invalid as specified."; + case DDERR_INVALIDDIRECTDRAWGUID: + return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."; + case DDERR_INVALIDMODE: + return "DirectDraw does not support the requested mode."; case DDERR_INVALIDOBJECT: return "DirectDraw received a pointer that was an invalid DIRECTDRAW object."; - case DDERR_LOCKEDSURFACES: - return "Operation could not be carried out because one or more surfaces are locked."; + case DDERR_INVALIDPARAMS: + return "One or more of the parameters passed to the function are incorrect."; + case DDERR_INVALIDPIXELFORMAT: + return "The pixel format was invalid as specified."; + case DDERR_INVALIDPOSITION: + return "Returned when the position of the overlay on the destination is no longer legal for that " + "destination."; case DDERR_INVALIDRECT: return "Rectangle provided was invalid."; + case DDERR_LOCKEDSURFACES: + return "Operation could not be carried out because one or more surfaces are locked."; + case DDERR_NO3D: + return "There is no 3D present."; case DDERR_NOALPHAHW: return "Operation could not be carried out because there is no alpha accleration hardware present or " "available."; - case DDERR_NO3D: - return "There is no 3D present."; - case DDERR_NOCOLORCONVHW: - return "Operation could not be carried out because there is no color conversion hardware present or available."; + case DDERR_NOBLTHW: + return "No blitter hardware present."; case DDERR_NOCLIPLIST: return "No cliplist available."; + case DDERR_NOCLIPPERATTACHED: + return "No clipper object attached to surface object."; + case DDERR_NOCOLORCONVHW: + return "Operation could not be carried out because there is no color conversion hardware present or " + "available."; case DDERR_NOCOLORKEY: return "Surface doesn't currently have a color key"; + case DDERR_NOCOLORKEYHW: + return "Operation could not be carried out because there is no hardware support of the destination color " + "key."; case DDERR_NOCOOPERATIVELEVELSET: return "Create function called without DirectDraw object method SetCooperativeLevel being called."; + case DDERR_NODC: + return "No DC was ever created for this surface."; + case DDERR_NODDROPSHW: + return "No DirectDraw ROP hardware."; + case DDERR_NODIRECTDRAWHW: + return "A hardware-only DirectDraw object creation was attempted but the driver did not support any " + "hardware."; + case DDERR_NOEMULATION: + return "Software emulation not available."; case DDERR_NOEXCLUSIVEMODE: return "Operation requires the application to have exclusive mode but the application does not have exclusive " "mode."; - case DDERR_NOCOLORKEYHW: - return "Operation could not be carried out because there is no hardware support of the destination color key."; - case DDERR_NOGDI: - return "There is no GDI present."; case DDERR_NOFLIPHW: return "Flipping visible surfaces is not supported."; - case DDERR_NOTFOUND: - return "Requested item was not found."; + case DDERR_NOGDI: + return "There is no GDI present."; + case DDERR_NOHWND: + return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel " + "HWND."; case DDERR_NOMIRRORHW: return "Operation could not be carried out because there is no hardware present or available."; + case DDERR_NOOVERLAYDEST: + return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on " + "to establish a destination."; + case DDERR_NOOVERLAYHW: + return "Operation could not be carried out because there is no overlay hardware present or available."; + case DDERR_NOPALETTEATTACHED: + return "No palette object attached to this surface."; + case DDERR_NOPALETTEHW: + return "No hardware support for 16 or 256 color palettes."; case DDERR_NORASTEROPHW: return "Operation could not be carried out because there is no appropriate raster op hardware present or " "available."; - case DDERR_NOOVERLAYHW: - return "Operation could not be carried out because there is no overlay hardware present or available."; - case DDERR_NOSTRETCHHW: - return "Operation could not be carried out because there is no hardware support for stretching."; case DDERR_NOROTATIONHW: return "Operation could not be carried out because there is no rotation hardware present or available."; - case DDERR_NOTEXTUREHW: - return "Operation could not be carried out because there is no texture mapping hardware present or available."; + case DDERR_NOSTRETCHHW: + return "Operation could not be carried out because there is no hardware support for stretching."; case DDERR_NOT4BITCOLOR: return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color " "palette."; @@ -432,118 +478,80 @@ const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) "index palette."; case DDERR_NOT8BITCOLOR: return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color."; - case DDERR_NOZBUFFERHW: - return "Operation could not be carried out because there is no hardware support for zbuffer blitting."; + case DDERR_NOTAOVERLAYSURFACE: + return "Returned when an overlay member is called for a non-overlay surface."; + case DDERR_NOTEXTUREHW: + return "Operation could not be carried out because there is no texture mapping hardware present or " + "available."; + case DDERR_NOTFLIPPABLE: + return "An attempt has been made to flip a surface that is not flippable."; + case DDERR_NOTFOUND: + return "Requested item was not found."; + case DDERR_NOTLOCKED: + return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this " + "process, has been attempted."; + case DDERR_NOTPALETTIZED: + return "The surface being used is not a palette-based surface."; case DDERR_NOVSYNCHW: return "Operation could not be carried out because there is no hardware support for vertical blank " "synchronized operations."; - case DDERR_OUTOFCAPS: - return "The hardware needed for the requested operation has already been allocated."; + case DDERR_NOZBUFFERHW: + return "Operation could not be carried out because there is no hardware support for zbuffer blitting."; case DDERR_NOZOVERLAYHW: return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support " "z layering of overlays."; - case DDERR_COLORKEYNOTSET: - return "No src color key specified for this operation."; + case DDERR_OUTOFCAPS: + return "The hardware needed for the requested operation has already been allocated."; + case DDERR_OUTOFMEMORY: + return "DirectDraw does not have enough memory to perform the operation."; case DDERR_OUTOFVIDEOMEMORY: return "DirectDraw does not have enough memory to perform the operation."; case DDERR_OVERLAYCANTCLIP: return "The hardware does not support clipped overlays."; case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: return "Can only have ony color key active at one time for overlays."; + case DDERR_OVERLAYNOTVISIBLE: + return "Returned when GetOverlayPosition is called on a hidden overlay."; case DDERR_PALETTEBUSY: return "Access to this palette is being refused because the palette is already locked by another thread."; - case DDERR_SURFACEALREADYDEPENDENT: - return "This surface is already a dependency of the surface it is being made a dependency of."; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + return "This process already has created a primary surface."; + case DDERR_REGIONTOOSMALL: + return "Region passed to Clipper::GetClipList is too small."; case DDERR_SURFACEALREADYATTACHED: return "This surface is already attached to the surface it is being attached to."; - case DDERR_SURFACEISOBSCURED: - return "Access to surface refused because the surface is obscured."; + case DDERR_SURFACEALREADYDEPENDENT: + return "This surface is already a dependency of the surface it is being made a dependency of."; case DDERR_SURFACEBUSY: return "Access to this surface is being refused because the surface is already locked by another thread."; - case DDERR_SURFACENOTATTACHED: - return "The requested surface is not attached."; + case DDERR_SURFACEISOBSCURED: + return "Access to surface refused because the surface is obscured."; case DDERR_SURFACELOST: return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface " "object representing this surface should have Restore called on it."; - case DDERR_TOOBIGSIZE: - return "Size requested by DirectDraw is too large, but the individual height and width are OK."; + case DDERR_SURFACENOTATTACHED: + return "The requested surface is not attached."; case DDERR_TOOBIGHEIGHT: return "Height requested by DirectDraw is too large."; - case DDERR_UNSUPPORTEDFORMAT: - return "FOURCC format requested is unsupported by DirectDraw."; + case DDERR_TOOBIGSIZE: + return "Size requested by DirectDraw is too large, but the individual height and width are OK."; case DDERR_TOOBIGWIDTH: return "Width requested by DirectDraw is too large."; - case DDERR_VERTICALBLANKINPROGRESS: - return "Vertical blank is in progress."; + case DDERR_UNSUPPORTED: + return "Action not supported."; + case DDERR_UNSUPPORTEDFORMAT: + return "FOURCC format requested is unsupported by DirectDraw."; case DDERR_UNSUPPORTEDMASK: return "Bitmask in the pixel format requested is unsupported by DirectDraw."; - case DDERR_XALIGN: - return "Rectangle provided was not horizontally aligned on required boundary."; + case DDERR_VERTICALBLANKINPROGRESS: + return "Vertical blank is in progress."; case DDERR_WASSTILLDRAWING: return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is " "incomplete."; - case DDERR_INVALIDDIRECTDRAWGUID: - return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."; - case DDERR_DIRECTDRAWALREADYCREATED: - return "A DirectDraw object representing this driver has already been created for this process."; - case DDERR_NODIRECTDRAWHW: - return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware."; - case DDERR_PRIMARYSURFACEALREADYEXISTS: - return "This process already has created a primary surface."; - case DDERR_NOEMULATION: - return "Software emulation not available."; - case DDERR_REGIONTOOSMALL: - return "Region passed to Clipper::GetClipList is too small."; - case DDERR_CLIPPERISUSINGHWND: - return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."; - case DDERR_NOCLIPPERATTACHED: - return "No clipper object attached to surface object."; - case DDERR_NOHWND: - return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND."; - case DDERR_HWNDSUBCLASSED: - return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring " - "state."; - case DDERR_HWNDALREADYSET: - return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or " - "palettes created."; - case DDERR_NOPALETTEATTACHED: - return "No palette object attached to this surface."; - case DDERR_NOPALETTEHW: - return "No hardware support for 16 or 256 color palettes."; - case DDERR_BLTFASTCANTCLIP: - return "Return if a clipper object is attached to the source surface passed into a BltFast call."; - case DDERR_NOBLTHW: - return "No blitter hardware present."; - case DDERR_NODDROPSHW: - return "No DirectDraw ROP hardware."; - case DDERR_OVERLAYNOTVISIBLE: - return "Returned when GetOverlayPosition is called on a hidden overlay."; - case DDERR_NOOVERLAYDEST: - return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on " - "to establish a destination."; - case DDERR_INVALIDPOSITION: - return "Returned when the position of the overlay on the destination is no longer legal for that destination."; - case DDERR_NOTAOVERLAYSURFACE: - return "Returned when an overlay member is called for a non-overlay surface."; - case DDERR_EXCLUSIVEMODEALREADYSET: - return "An attempt was made to set the cooperative level when it was already set to exclusive."; - case DDERR_NOTFLIPPABLE: - return "An attempt has been made to flip a surface that is not flippable."; - case DDERR_CANTDUPLICATE: - return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."; - case DDERR_NOTLOCKED: - return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this " - "process, has been attempted."; - case DDERR_CANTCREATEDC: - return "Windows can not create any more DCs."; - case DDERR_NODC: - return "No DC was ever created for this surface."; case DDERR_WRONGMODE: return "This surface can not be restored because it was created in a different mode."; - case DDERR_IMPLICITLYCREATED: - return "This surface can not be restored because it is an implicitly created surface."; - case DDERR_NOTPALETTIZED: - return "The surface being used is not a palette-based surface."; + case DDERR_XALIGN: + return "Rectangle provided was not horizontally aligned on required boundary."; default: return "Unrecognized error value."; } diff --git a/LEGO1/mxdirectx/mxdirectxinfo.h b/LEGO1/mxdirectx/mxdirectxinfo.h index 9bc480de..e3491891 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.h +++ b/LEGO1/mxdirectx/mxdirectxinfo.h @@ -66,7 +66,7 @@ class MxAssignedDevice { // SIZE 0x1a4 struct Direct3DDeviceInfo { - Direct3DDeviceInfo() {} + Direct3DDeviceInfo(); ~Direct3DDeviceInfo(); Direct3DDeviceInfo( LPGUID p_guid, @@ -115,9 +115,8 @@ struct MxDisplayMode { // SIZE 0x190 struct MxDriver { - MxDriver() {} + MxDriver(); ~MxDriver(); - MxDriver(LPGUID p_guid); MxDriver(LPGUID p_guid, LPCSTR p_driverDesc, LPCSTR p_driverName); void Init(LPGUID p_guid, LPCSTR p_driverDesc, LPCSTR p_driverName); @@ -206,20 +205,19 @@ class MxDeviceEnumerate { ); const char* EnumerateErrorToString(HRESULT p_error); static void BuildErrorString(const char*, ...); - static BOOL CALLBACK - DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context); + static BOOL CALLBACK DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_d); static HRESULT CALLBACK DevicesEnumerateCallback( LPGUID p_guid, LPSTR p_deviceDesc, LPSTR p_deviceName, LPD3DDEVICEDESC p_HWDesc, LPD3DDEVICEDESC p_HELDesc, - LPVOID p_context + LPVOID p_d ); friend class MxDirect3D; - - const list& GetDriverList() const { return m_list; } + friend class CConfigApp; + friend class CMainDialog; // SIZE 0x10 struct GUID4 { @@ -240,7 +238,7 @@ class MxDeviceEnumerate { unsigned char IsInitialized() const { return m_initialized; } protected: - list m_list; // 0x04 + list m_ddInfo; // 0x04 unsigned char m_initialized; // 0x10 HWND m_hWnd; }; diff --git a/LEGO1/omni/include/mxutilities.h b/LEGO1/omni/include/mxutilities.h index 33754f3c..7ea9fed5 100644 --- a/LEGO1/omni/include/mxutilities.h +++ b/LEGO1/omni/include/mxutilities.h @@ -10,7 +10,7 @@ struct LegoSdlEvents { Uint32 m_windowsMessage; Uint32 m_presenterProgress; - Uint32 m_hitActor; + Uint32 m_gameEvent; }; LEGO1_EXPORT extern LegoSdlEvents g_legoSdlEvents; diff --git a/LEGO1/omni/include/mxvideomanager.h b/LEGO1/omni/include/mxvideomanager.h index 5826cb64..04855a10 100644 --- a/LEGO1/omni/include/mxvideomanager.h +++ b/LEGO1/omni/include/mxvideomanager.h @@ -45,7 +45,10 @@ class MxVideoManager : public MxMediaManager { MxVideoParam& GetVideoParam() { return this->m_videoParam; } LPDIRECTDRAW GetDirectDraw() { return this->m_pDirectDraw; } + + // FUNCTION: BETA10 0x1002e290 MxDisplaySurface* GetDisplaySurface() { return this->m_displaySurface; } + MxRegion* GetRegion() { return this->m_region; } // SYNTHETIC: LEGO1 0x100be280 diff --git a/LEGO1/omni/src/main/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp index b6081b16..c314c7a8 100644 --- a/LEGO1/omni/src/main/mxomni.cpp +++ b/LEGO1/omni/src/main/mxomni.cpp @@ -166,7 +166,7 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) Uint32 event = SDL_RegisterEvents(3); g_legoSdlEvents.m_windowsMessage = event + 0; g_legoSdlEvents.m_presenterProgress = event + 1; - g_legoSdlEvents.m_hitActor = event + 2; + g_legoSdlEvents.m_gameEvent = event + 2; } result = SUCCESS; diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index f676dd0a..2248a0ad 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -46,16 +46,18 @@ void MxDisplaySurface::Init() } // FUNCTION: LEGO1 0x100ba640 +// FUNCTION: BETA10 0x1013f506 void MxDisplaySurface::ClearScreen() { + MxS32 i; MxS32 backBuffers; DDSURFACEDESC desc; - if (!m_videoParam.Flags().GetFlipSurfaces()) { - backBuffers = 2; + if (m_videoParam.Flags().GetFlipSurfaces()) { + backBuffers = m_videoParam.GetBackBuffers() + 1; } else { - backBuffers = m_videoParam.GetBackBuffers() + 1; + backBuffers = 2; } MxS32 width = m_videoParam.GetRect().GetWidth(); @@ -1196,6 +1198,8 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_ } MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8; + MxBool isAlphaAvailable = ((ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == DDPF_ALPHAPIXELS) && + (ddsd.ddpfPixelFormat.dwRGBAlphaBitMask != 0); ddsd.dwWidth = p_cursorBitmap->width; ddsd.dwHeight = p_cursorBitmap->height; @@ -1258,7 +1262,12 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_ MxS32 pixel; if (!isOpaque) { - pixel = RGB8888_CREATE(0xff, 0, 0xff, 0); // Transparent pixel + if (isAlphaAvailable) { + pixel = RGB8888_CREATE(0, 0, 0, 0); + } + else { + pixel = RGB8888_CREATE(0xff, 0, 0xff, 0); + } // Transparent pixel } else { pixel = isBlack ? RGB8888_CREATE(0, 0, 0, 0xff) : RGB8888_CREATE(0xff, 0xff, 0xff, 0xff); @@ -1288,10 +1297,12 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_ break; } default: { - DDCOLORKEY colorkey; - colorkey.dwColorSpaceHighValue = RGB8888_CREATE(0xff, 0, 0xff, 0); - colorkey.dwColorSpaceLowValue = RGB8888_CREATE(0xff, 0, 0xff, 0); - newSurface->SetColorKey(DDCKEY_SRCBLT, &colorkey); + if (!isAlphaAvailable) { + DDCOLORKEY colorkey; + colorkey.dwColorSpaceHighValue = RGB8888_CREATE(0xff, 0, 0xff, 0); + colorkey.dwColorSpaceLowValue = RGB8888_CREATE(0xff, 0, 0xff, 0); + newSurface->SetColorKey(DDCKEY_SRCBLT, &colorkey); + } break; } } diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index ceadf97f..1b8d1fdb 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -47,7 +47,7 @@ class Matrix4 { inline void RotateX(const float& p_angle); inline void RotateY(const float& p_angle); inline void RotateZ(const float& p_angle); - inline int BETA_1005a590(Matrix4& p_mat); + inline int Invert(Matrix4& p_mat); inline void Swap(int p_d1, int p_d2); // FUNCTION: BETA10 0x1001c670 diff --git a/LEGO1/realtime/matrix4d.inl.h b/LEGO1/realtime/matrix4d.inl.h index b8bba5a3..c1643f76 100644 --- a/LEGO1/realtime/matrix4d.inl.h +++ b/LEGO1/realtime/matrix4d.inl.h @@ -288,75 +288,83 @@ void Matrix4::RotateZ(const float& p_angle) } // FUNCTION: BETA10 0x1005a590 -int Matrix4::BETA_1005a590(Matrix4& p_mat) +int Matrix4::Invert(Matrix4& p_mat) { - float local5c[4][4]; - Matrix4 localc(local5c); - localc = *this; + // Inlined at LEGO1 0x1006b2d3 + + float copyData[4][4]; + Matrix4 copy(copyData); + copy = *this; p_mat.SetIdentity(); for (int i = 0; i < 4; i++) { - int local1c = i; - int local10; + int pivotColumn = i; + int column; - for (local10 = i + 1; local10 < 4; local10++) { - if (fabs(localc[local1c][i]) < fabs(localc[local10][i])) { - local1c = local10; + for (column = i + 1; column < 4; column++) { + if (fabs(copy[pivotColumn][i]) < fabs(copy[column][i])) { + pivotColumn = column; } } - if (local1c != i) { - localc.Swap(local1c, i); - p_mat.Swap(local1c, i); + if (pivotColumn != i) { + copy.Swap(pivotColumn, i); + p_mat.Swap(pivotColumn, i); } - if (localc[i][i] < 0.001f && localc[i][i] > -0.001f) { + if (copy[i][i] < 0.001f && copy[i][i] > -0.001f) { + // FAILURE from mxtypes.h return -1; } - float local60 = localc[i][i]; - int local18; + float pivotValue = copy[i][i]; + int k; - for (local18 = 0; local18 < 4; local18++) { - p_mat[i][local18] /= local60; + for (k = 0; k < 4; k++) { + p_mat[i][k] /= pivotValue; } - for (local18 = 0; local18 < 4; local18++) { - localc[i][local18] /= local60; + for (k = 0; k < 4; k++) { + copy[i][k] /= pivotValue; } - for (local10 = 0; local10 < 4; local10++) { - if (i != local10) { - float afStack70[4]; + for (column = 0; column < 4; column++) { + if (i != column) { + float tempColumn[4]; - for (local18 = 0; local18 < 4; local18++) { - afStack70[local18] = p_mat[i][local18] * localc[local10][i]; + for (k = 0; k < 4; k++) { + tempColumn[k] = p_mat[i][k] * copy[column][i]; } - for (local18 = 0; local18 < 4; local18++) { - p_mat[local10][local18] -= afStack70[local18]; + for (k = 0; k < 4; k++) { + p_mat[column][k] -= tempColumn[k]; } - for (local18 = 0; local18 < 4; local18++) { - afStack70[local18] = localc[i][local18] * localc[local10][i]; + for (k = 0; k < 4; k++) { + tempColumn[k] = copy[i][k] * copy[column][i]; } - for (local18 = 0; local18 < 4; local18++) { - localc[local10][local18] -= afStack70[local18]; + for (k = 0; k < 4; k++) { + copy[column][k] -= tempColumn[k]; } } } } + // SUCCESS from mxtypes.h return 0; } // FUNCTION: LEGO1 0x1006b500 +// FUNCTION: BETA10 0x1005aa20 void Matrix4::Swap(int p_d1, int p_d2) { - for (int i = 0; i < 4; i++) { - float e = m_data[p_d1][i]; + // This function is affected by entropy even in debug builds + int i; + float e; + for (i = 0; i < 4; i++) { + e = m_data[p_d1][i]; m_data[p_d1][i] = m_data[p_d2][i]; m_data[p_d2][i] = e; } diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp index fd0d4a84..a6f4aaba 100644 --- a/LEGO1/viewmanager/viewmanager.cpp +++ b/LEGO1/viewmanager/viewmanager.cpp @@ -235,7 +235,7 @@ inline void ViewManager::ManageVisibilityAndDetailRecursively(ViewROI* p_from, i if (p_from->GetWorldBoundingSphere().Radius() > 0.001F) { float projectedSize = ProjectedSize(p_from->GetWorldBoundingSphere()); - if (projectedSize < seconds_allowed * g_viewDistance) { + if (RealtimeView::GetUserMaxLOD() <= 5.0f && projectedSize < seconds_allowed * g_viewDistance) { if (p_from->GetLodLevel() != ViewROI::c_lodLevelInvisible) { ManageVisibilityAndDetailRecursively(p_from, ViewROI::c_lodLevelInvisible); } @@ -361,7 +361,7 @@ inline int ViewManager::CalculateLODLevel(float p_maximumScale, float p_initialS assert(from); if (GetFirstLODIndex(from) != 0) { - if (p_maximumScale < g_minLODThreshold) { + if (RealtimeView::GetUserMaxLOD() <= 5.0f && p_maximumScale < g_minLODThreshold) { return 0; } else { diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index 08b54444..b830fa6d 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -177,6 +177,7 @@ static Uint32 UploadTextureData(SDL_Surface* src, bool useNPOT, bool isUI, float Uint32 OpenGL1Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { + SDL_GL_MakeCurrent(DDWindow, m_context); auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -316,6 +317,7 @@ Uint32 OpenGL1Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGr HRESULT OpenGL1Renderer::BeginFrame() { + SDL_GL_MakeCurrent(DDWindow, m_context); GL11_BeginFrame((Matrix4x4*) &m_projection[0][0]); int lightIdx = 0; @@ -363,6 +365,7 @@ HRESULT OpenGL1Renderer::FinalizeFrame() void OpenGL1Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform) { + SDL_GL_MakeCurrent(DDWindow, m_context); m_width = width; m_height = height; m_viewportTransform = viewportTransform; @@ -373,12 +376,14 @@ void OpenGL1Renderer::Resize(int width, int height, const ViewportTransform& vie void OpenGL1Renderer::Clear(float r, float g, float b) { + SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; GL11_Clear(r, g, b); } void OpenGL1Renderer::Flip() { + SDL_GL_MakeCurrent(DDWindow, m_context); if (m_dirty) { SDL_GL_SwapWindow(DDWindow); m_dirty = false; @@ -387,6 +392,7 @@ void OpenGL1Renderer::Flip() void OpenGL1Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect, FColor color) { + SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; float left = -m_viewportTransform.offsetX / m_viewportTransform.scale; diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index 50e43d02..e1c86a62 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -390,6 +390,7 @@ void OpenGLES2Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { + SDL_GL_MakeCurrent(DDWindow, m_context); auto texture = static_cast(iTexture); auto surface = static_cast(texture->m_surface); @@ -484,6 +485,7 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh HRESULT OpenGLES2Renderer::BeginFrame() { + SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); @@ -599,6 +601,7 @@ HRESULT OpenGLES2Renderer::FinalizeFrame() void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform) { + SDL_GL_MakeCurrent(DDWindow, m_context); m_width = width; m_height = height; m_viewportTransform = viewportTransform; @@ -639,6 +642,7 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v void OpenGLES2Renderer::Clear(float r, float g, float b) { + SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); @@ -651,6 +655,7 @@ void OpenGLES2Renderer::Clear(float r, float g, float b) void OpenGLES2Renderer::Flip() { + SDL_GL_MakeCurrent(DDWindow, m_context); if (!m_dirty) { return; } @@ -714,6 +719,7 @@ void OpenGLES2Renderer::Flip() void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect, FColor color) { + SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index c5ceef72..322cded0 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -74,3 +74,7 @@ cksize: "Re-defined Windows name" fccType: "Re-defined Windows name" dwDataOffset: "Re-defined Windows name" fccType: "Re-defined Windows name" +SDL_KeyboardID_v: "SDL-based name" +SDL_MouseID_v: "SDL-based name" +SDL_JoystickID_v: "SDL-based name" +SDL_TouchID_v: "SDL-based name" \ No newline at end of file