diff --git a/CMakeLists.txt b/CMakeLists.txt index 095c7711..09b7dc46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ endif() if (EMSCRIPTEN) add_compile_options(-pthread) - add_link_options(-sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sOFFSCREENCANVAS_SUPPORT=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1) + add_link_options(-sUSE_WEBGL2=1 -sMIN_WEBGL_VERSION=2 -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=2gb -sUSE_PTHREADS=1 -sPROXY_TO_PTHREAD=1 -sOFFSCREENCANVAS_SUPPORT=1 -sPTHREAD_POOL_SIZE_STRICT=0 -sFORCE_FILESYSTEM=1 -sWASMFS=1 -sEXIT_RUNTIME=1) set(SDL_PTHREADS ON CACHE BOOL "Enable SDL pthreads" FORCE) endif() @@ -184,6 +184,8 @@ target_include_directories(lego1 PUBLIC "$:DirectX5::DirectX5>) +# Allow unconditional include of miniwin/miniwind3d.h +target_link_libraries(lego1 PRIVATE miniwin-headers) if(WIN32) set_property(TARGET lego1 PROPERTY PREFIX "") endif() @@ -314,10 +316,10 @@ target_sources(lego1 PRIVATE LEGO1/omni/src/common/mxcompositepresenter.cpp LEGO1/omni/src/common/mxcore.cpp LEGO1/omni/src/common/mxdebug.cpp - LEGO1/omni/src/common/mxmediamanager.cpp LEGO1/omni/src/common/mxmediapresenter.cpp LEGO1/omni/src/common/mxmisc.cpp LEGO1/omni/src/common/mxobjectfactory.cpp + LEGO1/omni/src/common/mxpresentationmanager.cpp LEGO1/omni/src/common/mxpresenter.cpp LEGO1/omni/src/common/mxstring.cpp LEGO1/omni/src/common/mxticklemanager.cpp @@ -468,9 +470,6 @@ target_sources(lego1 PRIVATE LEGO1/lego/legoomni/src/race/raceskel.cpp LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp LEGO1/lego/legoomni/src/video/legoflctexturepresenter.cpp - LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp - LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp - LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp LEGO1/lego/legoomni/src/video/legopartpresenter.cpp diff --git a/CONFIG/MainDlg.cpp b/CONFIG/MainDlg.cpp index 3f69d096..5ae140c3 100644 --- a/CONFIG/MainDlg.cpp +++ b/CONFIG/MainDlg.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -54,15 +56,18 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent) this, &CMainDialog::OnRadiobuttonTextureHighQuality ); + + connect(m_ui->windowedRadioButton, &QRadioButton::toggled, this, &CMainDialog::OnRadioWindowed); + connect(m_ui->fullscreenRadioButton, &QRadioButton::toggled, this, &CMainDialog::OnRadioFullscreen); + connect(m_ui->exFullscreenRadioButton, &QRadioButton::toggled, this, &CMainDialog::OnRadioExclusiveFullscreen); connect(m_ui->devicesList, &QListWidget::currentRowChanged, this, &CMainDialog::OnList3DevicesSelectionChanged); 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); connect(m_ui->transitionTypeComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::TransitionTypeChanged); + connect(m_ui->exFullResComboBox, &QComboBox::currentIndexChanged, this, &CMainDialog::ExclusiveResolutionChanged); connect(m_ui->okButton, &QPushButton::clicked, this, &CMainDialog::accept); connect(m_ui->cancelButton, &QPushButton::clicked, this, &CMainDialog::reject); connect(m_ui->launchButton, &QPushButton::clicked, this, &CMainDialog::launch); @@ -81,6 +86,11 @@ 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->msaaSlider, &QSlider::valueChanged, this, &CMainDialog::MSAAChanged); + connect(m_ui->msaaSlider, &QSlider::sliderMoved, this, &CMainDialog::MSAAChanged); + connect(m_ui->AFSlider, &QSlider::valueChanged, this, &CMainDialog::AFChanged); + connect(m_ui->AFSlider, &QSlider::sliderMoved, this, &CMainDialog::AFChanged); + 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); @@ -164,6 +174,23 @@ bool CMainDialog::OnInitDialog() m_ui->maxActorsSlider->setValue(currentConfigApp->m_max_actors); m_ui->maxActorsNum->setNum(currentConfigApp->m_max_actors); + m_ui->exFullResComboBox->clear(); + + int displayModeCount; + displayModes = SDL_GetFullscreenDisplayModes(SDL_GetPrimaryDisplay(), &displayModeCount); + + for (int i = 0; i < displayModeCount; ++i) { + QString mode = + QString("%1x%2 @ %3Hz").arg(displayModes[i]->w).arg(displayModes[i]->h).arg(displayModes[i]->refresh_rate); + m_ui->exFullResComboBox->addItem(mode); + + if ((displayModes[i]->w == currentConfigApp->m_exf_x_res) && + (displayModes[i]->h == currentConfigApp->m_exf_y_res) && + (displayModes[i]->refresh_rate == currentConfigApp->m_exf_fps)) { + m_ui->exFullResComboBox->setCurrentIndex(i); + } + } + UpdateInterface(); return true; } @@ -258,18 +285,30 @@ void CMainDialog::UpdateInterface() else { m_ui->textureQualityHighRadioButton->setChecked(true); } + if (currentConfigApp->m_exclusive_full_screen) { + m_ui->exFullscreenRadioButton->setChecked(true); + m_ui->resolutionBox->setEnabled(false); + m_ui->exFullResContainer->setEnabled(true); + } + else { + m_ui->resolutionBox->setEnabled(true); + m_ui->exFullResContainer->setEnabled(false); + if (currentConfigApp->m_full_screen) { + m_ui->fullscreenRadioButton->setChecked(true); + } + else { + m_ui->windowedRadioButton->setChecked(true); + } + } 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); m_ui->dataPath->setText(QString::fromStdString(currentConfigApp->m_cd_path)); m_ui->savePath->setText(QString::fromStdString(currentConfigApp->m_save_path)); + m_ui->textureCheckBox->setChecked(currentConfigApp->m_texture_load); m_ui->texturePath->setText(QString::fromStdString(currentConfigApp->m_texture_path)); - m_ui->texturePath->setEnabled(currentConfigApp->m_texture_load); m_ui->texturePathOpen->setEnabled(currentConfigApp->m_texture_load); @@ -277,6 +316,15 @@ void CMainDialog::UpdateInterface() 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))); + + m_ui->maxLoDSlider->setValue((int) (currentConfigApp->m_max_lod * 10)); + m_ui->LoDNum->setNum(currentConfigApp->m_max_lod); + m_ui->maxActorsSlider->setValue(currentConfigApp->m_max_actors); + m_ui->maxActorsNum->setNum(currentConfigApp->m_max_actors); + m_ui->msaaSlider->setValue(log2(currentConfigApp->m_msaa)); + m_ui->msaaNum->setNum(currentConfigApp->m_msaa); + m_ui->AFSlider->setValue(log2(currentConfigApp->m_anisotropy)); + m_ui->AFNum->setNum(currentConfigApp->m_anisotropy); } // FUNCTION: CONFIG 0x004045e0 @@ -336,6 +384,42 @@ void CMainDialog::OnRadiobuttonTextureHighQuality(bool checked) } } +void CMainDialog::OnRadioWindowed(bool checked) +{ + if (checked) { + currentConfigApp->m_full_screen = false; + currentConfigApp->m_exclusive_full_screen = false; + m_ui->resolutionBox->setEnabled(true); + m_ui->exFullResContainer->setEnabled(false); + m_modified = true; + UpdateInterface(); + } +} + +void CMainDialog::OnRadioFullscreen(bool checked) +{ + if (checked) { + currentConfigApp->m_full_screen = true; + currentConfigApp->m_exclusive_full_screen = false; + m_ui->resolutionBox->setEnabled(true); + m_ui->exFullResContainer->setEnabled(false); + m_modified = true; + UpdateInterface(); + } +} + +void CMainDialog::OnRadioExclusiveFullscreen(bool checked) +{ + if (checked) { + currentConfigApp->m_full_screen = true; + currentConfigApp->m_exclusive_full_screen = true; + m_ui->resolutionBox->setEnabled(false); + m_ui->exFullResContainer->setEnabled(true); + m_modified = true; + UpdateInterface(); + } +} + // FUNCTION: CONFIG 0x004048c0 void CMainDialog::OnCheckboxMusic(bool checked) { @@ -344,21 +428,6 @@ void CMainDialog::OnCheckboxMusic(bool checked) UpdateInterface(); } -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(); -} - void CMainDialog::OnCheckboxRumble(bool checked) { currentConfigApp->m_haptic = checked; @@ -387,6 +456,15 @@ void CMainDialog::TransitionTypeChanged(int index) UpdateInterface(); } +void CMainDialog::ExclusiveResolutionChanged(int index) +{ + currentConfigApp->m_exf_x_res = displayModes[index]->w; + currentConfigApp->m_exf_y_res = displayModes[index]->h; + currentConfigApp->m_exf_fps = displayModes[index]->refresh_rate; + m_modified = true; + UpdateInterface(); +} + void CMainDialog::SelectDataPathDialog() { QString data_path = QString::fromStdString(currentConfigApp->m_cd_path); @@ -458,15 +536,29 @@ void CMainDialog::SavePathEdited() void CMainDialog::MaxLoDChanged(int value) { currentConfigApp->m_max_lod = static_cast(value) / 10.0f; - m_ui->LoDNum->setNum(value); m_modified = true; + UpdateInterface(); } void CMainDialog::MaxActorsChanged(int value) { currentConfigApp->m_max_actors = value; - m_ui->maxActorsNum->setNum(value); m_modified = true; + UpdateInterface(); +} + +void CMainDialog::MSAAChanged(int value) +{ + currentConfigApp->m_msaa = exp2(value); + m_modified = true; + UpdateInterface(); +} + +void CMainDialog::AFChanged(int value) +{ + currentConfigApp->m_anisotropy = exp2(value); + m_modified = true; + UpdateInterface(); } void CMainDialog::SelectTexturePathDialog() diff --git a/CONFIG/MainDlg.h b/CONFIG/MainDlg.h index ece4dbfd..0aaeeb12 100644 --- a/CONFIG/MainDlg.h +++ b/CONFIG/MainDlg.h @@ -7,6 +7,7 @@ #include #include +#include namespace Ui { @@ -29,6 +30,7 @@ class CMainDialog : public QDialog { bool m_modified = false; bool m_advanced = false; Ui::MainDialog* m_ui = nullptr; + SDL_DisplayMode** displayModes; void keyReleaseEvent(QKeyEvent* event) override; bool OnInitDialog(); @@ -40,13 +42,15 @@ private slots: void OnRadiobuttonModelHighQuality(bool checked); void OnRadiobuttonTextureLowQuality(bool checked); void OnRadiobuttonTextureHighQuality(bool checked); + void OnRadioWindowed(bool checked); + void OnRadioFullscreen(bool checked); + void OnRadioExclusiveFullscreen(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); void TransitionTypeChanged(int index); + void ExclusiveResolutionChanged(int index); void accept() override; void reject() override; void launch(); @@ -56,6 +60,8 @@ private slots: void SavePathEdited(); void MaxLoDChanged(int value); void MaxActorsChanged(int value); + void MSAAChanged(int value); + void AFChanged(int value); void SelectTexturePathDialog(); void TexturePathEdited(); void XResChanged(int i); diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp index d0f1dda6..766cecd4 100644 --- a/CONFIG/config.cpp +++ b/CONFIG/config.cpp @@ -68,8 +68,9 @@ bool CConfigApp::InitInstance() } SDL_DestroyWindow(window); m_aspect_ratio = 0; - m_x_res = 640; - m_y_res = 480; + m_exf_x_res = m_x_res = 640; + m_exf_y_res = m_y_res = 480; + m_exf_fps = 60.00f; m_frame_delta = 10.0f; m_driver = NULL; m_device = NULL; @@ -83,6 +84,8 @@ bool CConfigApp::InitInstance() m_3d_video_ram = FALSE; m_joystick_index = -1; m_display_bit_depth = 16; + m_msaa = 1; + m_anisotropy = 1; m_haptic = TRUE; m_touch_scheme = 2; m_texture_load = TRUE; @@ -181,11 +184,16 @@ bool CConfigApp::ReadRegisterSettings() m_joystick_index = iniparser_getint(dict, "isle:JoystickIndex", m_joystick_index); m_max_lod = iniparser_getdouble(dict, "isle:Max LOD", m_max_lod); m_max_actors = iniparser_getint(dict, "isle:Max Allowed Extras", m_max_actors); + m_msaa = iniparser_getint(dict, "isle:MSAA", m_msaa); + m_anisotropy = iniparser_getint(dict, "isle:Anisotropic", m_anisotropy); 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_exf_x_res = iniparser_getint(dict, "isle:Exclusive X Resolution", m_exf_x_res); + m_exf_y_res = iniparser_getint(dict, "isle:Exclusive Y Resolution", m_exf_y_res); + m_exf_fps = iniparser_getdouble(dict, "isle:Exclusive Framerate", m_exf_fps); m_frame_delta = iniparser_getdouble(dict, "isle:Frame Delta", m_frame_delta); iniparser_freedict(dict); return true; @@ -259,6 +267,34 @@ bool CConfigApp::ValidateSettings() m_touch_scheme = 2; is_modified = TRUE; } + if (m_exclusive_full_screen && !m_full_screen) { + m_full_screen = TRUE; + is_modified = TRUE; + } + if (!(m_msaa & (m_msaa - 1))) { // Check if MSAA is power of 2 (1, 2, 4, 8, etc) + m_msaa = exp2(round(log2(m_msaa))); // Closest power of 2 + is_modified = TRUE; + } + if (m_msaa > 16) { + m_msaa = 16; + is_modified = TRUE; + } + else if (m_msaa < 1) { + m_msaa = 1; + is_modified = TRUE; + } + if (!(m_anisotropy & (m_anisotropy - 1))) { // Check if anisotropy is power of 2 (1, 2, 4, 8, etc) + m_anisotropy = exp2(round(log2(m_anisotropy))); // Closest power of 2 + is_modified = TRUE; + } + if (m_anisotropy > 16) { + m_anisotropy = 16; + is_modified = TRUE; + } + else if (m_anisotropy < 1) { + m_anisotropy = 1; + is_modified = TRUE; + } return is_modified; } @@ -337,6 +373,8 @@ void CConfigApp::WriteRegisterSettings() const iniparser_set(dict, "isle:savepath", m_save_path.c_str()); SetIniInt(dict, "isle:Display Bit Depth", m_display_bit_depth); + SetIniInt(dict, "isle:MSAA", m_msaa); + SetIniInt(dict, "isle:Anisotropic", m_anisotropy); 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); @@ -367,6 +405,9 @@ void CConfigApp::WriteRegisterSettings() const SetIniInt(dict, "isle:Aspect Ratio", m_aspect_ratio); SetIniInt(dict, "isle:Horizontal Resolution", m_x_res); SetIniInt(dict, "isle:Vertical Resolution", m_y_res); + SetIniInt(dict, "isle:Exclusive X Resolution", m_exf_x_res); + SetIniInt(dict, "isle:Exclusive Y Resolution", m_exf_y_res); + iniparser_set(dict, "isle:Exclusive Framerate", std::to_string(m_exf_fps).c_str()); iniparser_set(dict, "isle:Frame Delta", std::to_string(m_frame_delta).c_str()); #undef SetIniBool diff --git a/CONFIG/config.h b/CONFIG/config.h index ad3321ac..c0dcb851 100644 --- a/CONFIG/config.h +++ b/CONFIG/config.h @@ -62,11 +62,16 @@ class CConfigApp { int m_aspect_ratio; int m_x_res; int m_y_res; + int m_exf_x_res; + int m_exf_y_res; + float m_exf_fps; float m_frame_delta; LegoDeviceEnumerate* m_device_enumerator; MxDriver* m_driver; Direct3DDeviceInfo* m_device; int m_display_bit_depth; + int m_msaa; + int m_anisotropy; bool m_flip_surfaces; bool m_full_screen; bool m_exclusive_full_screen; diff --git a/CONFIG/res/maindialog.ui b/CONFIG/res/maindialog.ui index 5a0d3b31..e395159b 100644 --- a/CONFIG/res/maindialog.ui +++ b/CONFIG/res/maindialog.ui @@ -56,6 +56,9 @@ false + + fullscreenRadioContainer_2 + @@ -353,12 +356,18 @@ A higher setting will cause higher quality textures to be drawn regardless of di - 15 + 20 0 + + + 20 + 16777215 + + - 35 + 3.5 @@ -533,10 +542,16 @@ The game will gradually increase the number of actors until this maximum is reac - 15 + 20 0 + + + 20 + 16777215 + + 20 @@ -602,8 +617,59 @@ The game will gradually increase the number of actors until this maximum is reac General - - + + + + + + 0 + 0 + + + + <html><head/><body><p><span style=" font-weight:700;">Windowed:</span> Runs in a window, the initial resolution of which is dictated by Windowed Resolution. </p><p><span style=" font-weight:700;">Fullscreen:</span> Runs in a borderless window that consumes the entire screen. </p><p><span style=" font-weight:700;">Exclusive Fullscreen:</span> Grants the app full control of the display for better performance and lower input lag. May cause slower alt-tabbing.</p></body></html> + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Windowed + + + + + + + Fullscreen + + + + + + + Exclusive Fullscreen + + + + + + + <html><head/><body><p>Maximum framerate. Values above 100fps are untested.</p></body></html> @@ -622,33 +688,6 @@ The game will gradually increase the number of actors until this maximum is reac - - - - - - 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 - - - - - @@ -765,17 +804,135 @@ The game will gradually increase the number of actors until this maximum is reac - - - Qt::Orientation::Vertical + + + false - - - 20 - 40 - + + Exclusive Fullscreen Resolution - + + + + + Resolution + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + MSAA + + + + + + 0 + + + 4 + + + 1 + + + Qt::Orientation::Horizontal + + + QSlider::TickPosition::TicksBothSides + + + 1 + + + + + + + + 16 + 0 + + + + 1 + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + + + Anisotropic Filtering + + + + + + 0 + + + 4 + + + 1 + + + Qt::Orientation::Horizontal + + + QSlider::TickPosition::TicksBothSides + + + 1 + + + + + + + + 16 + 0 + + + + 1 + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + @@ -860,7 +1017,7 @@ The game will gradually increase the number of actors until this maximum is reac Settings for Texture Loader extension. - Texture Loader Extension + Texture Loader @@ -1007,12 +1164,16 @@ The game will gradually increase the number of actors until this maximum is reac maxLoDSlider maxActorsSlider devicesList - fullscreenCheckBox - exclusiveFullscreenCheckbox + windowedRadioButton + fullscreenRadioButton + exFullscreenRadioButton framerateSpinBox aspectRatioComboBox xResSpinBox yResSpinBox + exFullResComboBox + msaaSlider + AFSlider touchComboBox rumbleCheckBox textureCheckBox diff --git a/ISLE/emscripten/events.cpp b/ISLE/emscripten/events.cpp index 5cf67e51..436c1b64 100644 --- a/ISLE/emscripten/events.cpp +++ b/ISLE/emscripten/events.cpp @@ -36,3 +36,11 @@ void Emscripten_SendPresenterProgress(MxDSAction* p_action, MxPresenter::TickleS Emscripten_SendEvent("presenterProgress", buf); } + +void Emscripten_SendExtensionProgress(const char* p_extension, MxU32 p_progress) +{ + char buf[128]; + SDL_snprintf(buf, sizeof(buf), "{\"name\": \"%s\", \"progress\": %d}", p_extension, p_progress); + + Emscripten_SendEvent("extensionProgress", buf); +} diff --git a/ISLE/emscripten/events.h b/ISLE/emscripten/events.h index fac59cad..a22d7b55 100644 --- a/ISLE/emscripten/events.h +++ b/ISLE/emscripten/events.h @@ -4,5 +4,6 @@ #include "mxpresenter.h" void Emscripten_SendPresenterProgress(MxDSAction* p_action, MxPresenter::TickleState p_tickleState); +void Emscripten_SendExtensionProgress(const char* p_extension, MxU32 p_progress); #endif // EMSCRIPTEN_EVENTS_H diff --git a/ISLE/emscripten/filesystem.cpp b/ISLE/emscripten/filesystem.cpp index 50cd9012..740802b8 100644 --- a/ISLE/emscripten/filesystem.cpp +++ b/ISLE/emscripten/filesystem.cpp @@ -1,5 +1,7 @@ #include "filesystem.h" +#include "events.h" +#include "extensions/textureloader.h" #include "legogamestate.h" #include "misc.h" #include "mxomni.h" @@ -13,6 +15,7 @@ static backend_t opfs = nullptr; static backend_t fetchfs = nullptr; extern const char* g_files[46]; +extern const char* g_textures[120]; bool Emscripten_OPFSDisabled() { @@ -41,7 +44,7 @@ bool Emscripten_SetupConfig(const char* p_iniConfig) void Emscripten_SetupFilesystem() { - fetchfs = wasmfs_create_fetch_backend((MxString(Emscripten_streamHost) + MxString("/LEGO")).GetData(), 512 * 1024); + fetchfs = wasmfs_create_fetch_backend((MxString(Emscripten_streamHost) + "/LEGO").GetData(), 512 * 1024); wasmfs_create_directory("/LEGO", 0644, fetchfs); wasmfs_create_directory("/LEGO/Scripts", 0644, fetchfs); @@ -71,10 +74,41 @@ void Emscripten_SetupFilesystem() } }; + const auto preloadFile = [](const char* p_path) -> bool { + size_t length = 0; + void* data = SDL_LoadFile(p_path, &length); + if (data) { + SDL_free(data); + } + return length > 0; + }; + for (const char* file : g_files) { registerFile(file); } +#ifdef EXTENSIONS + if (Extensions::TextureLoader::enabled) { + MxString directory = + MxString("/LEGO") + Extensions::TextureLoader::options["texture loader:texture path"].c_str(); + Extensions::TextureLoader::options["texture loader:texture path"] = directory.GetData(); + wasmfs_create_directory(directory.GetData(), 0644, fetchfs); + + MxU32 i = 0; + Emscripten_SendExtensionProgress("HD Textures", 0); + for (const char* file : g_textures) { + MxString path = directory + "/" + file + ".bmp"; + registerFile(path.GetData()); + + if (!preloadFile(path.GetData())) { + Extensions::TextureLoader::excludedFiles.emplace_back(file); + } + + Emscripten_SendExtensionProgress("HD Textures", (++i * 100) / sizeOfArray(g_textures)); + } + } +#endif + if (GameState()->GetSavePath() && *GameState()->GetSavePath() && !Emscripten_OPFSDisabled()) { if (!opfs) { opfs = wasmfs_create_opfs_backend(); diff --git a/ISLE/emscripten/window.cpp b/ISLE/emscripten/window.cpp index 6766490f..fd8b144c 100644 --- a/ISLE/emscripten/window.cpp +++ b/ISLE/emscripten/window.cpp @@ -84,7 +84,8 @@ void Emscripten_ConvertEventToRenderCoordinates(SDL_Event* event) } case SDL_EVENT_FINGER_MOTION: case SDL_EVENT_FINGER_DOWN: - case SDL_EVENT_FINGER_UP: { + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_CANCELED: { const float scale = std::min(g_fullWidth / g_targetWidth, g_fullHeight / g_targetHeight); const float widthRatio = (g_targetWidth * scale) / g_fullWidth; const float heightRatio = (g_targetHeight * scale) / g_fullHeight; diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 2cd65e2d..8e03f72d 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -185,8 +185,13 @@ IsleApp::IsleApp() m_haptic = TRUE; m_xRes = 640; m_yRes = 480; + m_exclusiveXRes = m_xRes; + m_exclusiveYRes = m_yRes; + m_exclusiveFrameRate = 60.00f; m_frameRate = 100.0f; m_exclusiveFullScreen = FALSE; + m_msaaSamples = 0; + m_anisotropic = 0.0f; } // FUNCTION: ISLE 0x4011a0 @@ -291,7 +296,7 @@ void IsleApp::SetupVideoFlags( m_videoParam.Flags().SetLacksLightSupport(!hasLightSupport); m_videoParam.Flags().SetF1bit7(param_7); m_videoParam.Flags().SetWideViewAngle(wideViewAngle); - m_videoParam.Flags().SetF2bit1(1); + m_videoParam.Flags().SetEnabled(TRUE); m_videoParam.SetDeviceName(deviceId); if (using8bit) { m_videoParam.Flags().Set16Bit(0); @@ -468,6 +473,7 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) case SDL_EVENT_FINGER_MOTION: case SDL_EVENT_FINGER_DOWN: case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_CANCELED: IDirect3DRMMiniwinDevice* device = GetD3DRMMiniwinDevice(); if (device && !device->ConvertEventToRenderCoordinates(event)) { SDL_Log("Failed to convert event coordinates: %s", SDL_GetError()); @@ -762,7 +768,8 @@ SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) ); } break; - case SDL_EVENT_FINGER_UP: { + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_CANCELED: { g_mousedown = FALSE; float x = SDL_clamp(event->tfinger.x, 0, 1) * g_targetWidth; @@ -919,11 +926,19 @@ MxResult IsleApp::SetupWindow() #endif window = SDL_CreateWindowWithProperties(props); + SDL_SetPointerProperty(SDL_GetWindowProperties(window), ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM, &m_videoParam); 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)) { + if (SDL_GetClosestFullscreenDisplayMode( + displayID, + m_exclusiveXRes, + m_exclusiveYRes, + m_exclusiveFrameRate, + true, + &closestMode + )) { SDL_SetWindowFullscreenMode(window, &closestMode); } } @@ -1101,6 +1116,9 @@ bool IsleApp::LoadConfig() 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:Exclusive X Resolution", SDL_itoa(m_exclusiveXRes, buf, 10)); + iniparser_set(dict, "isle:Exclusive Y Resolution", SDL_itoa(m_exclusiveYRes, buf, 10)); + iniparser_set(dict, "isle:Exclusive Framerate", SDL_itoa(m_exclusiveFrameRate, buf, 10)); iniparser_set(dict, "isle:Frame Delta", SDL_itoa(m_frameDelta, buf, 10)); #ifdef EXTENSIONS @@ -1175,11 +1193,16 @@ bool IsleApp::LoadConfig() 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); + m_exclusiveXRes = iniparser_getint(dict, "isle:Exclusive X Resolution", m_exclusiveXRes); + m_exclusiveYRes = iniparser_getint(dict, "isle:Exclusive Y Resolution", m_exclusiveXRes); + m_exclusiveFrameRate = iniparser_getdouble(dict, "isle:Exclusive Framerate", m_exclusiveFrameRate); 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))); + m_videoParam.SetMSAASamples((m_msaaSamples = iniparser_getint(dict, "isle:MSAA", m_msaaSamples))); + m_videoParam.SetAnisotropic((m_anisotropic = iniparser_getdouble(dict, "isle:Anisotropic", m_anisotropic))); const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL); if (deviceId != NULL) { diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 4a23ea23..66e8e6e1 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -109,8 +109,13 @@ class IsleApp { MxBool m_haptic; MxS32 m_xRes; MxS32 m_yRes; + MxS32 m_exclusiveXRes; + MxS32 m_exclusiveYRes; + MxFloat m_exclusiveFrameRate; MxFloat m_frameRate; MxBool m_exclusiveFullScreen; + MxU32 m_msaaSamples; + MxFloat m_anisotropic; }; extern IsleApp* g_isle; diff --git a/ISLE/islefiles.cpp b/ISLE/islefiles.cpp index 6e0bb482..c6f4566d 100644 --- a/ISLE/islefiles.cpp +++ b/ISLE/islefiles.cpp @@ -46,3 +46,24 @@ const char* g_files[46] = { "/LEGO/data/WORLD.WDB", "/LEGO/data/testinf.dta", }; + +const char* g_textures[120] = { + "bank01.gif", "beach.gif", "black.gif", "bowtie.gif", "brela_01.gif", "bth1chst.gif", "bth2chst.gif", + "capch.gif", "capdb.gif", "capjs.gif", "capmd.gif", "caprc.gif", "cave_24x.gif", "caverocx.gif", + "caverokx.gif", "cheker01.gif", "construct.gif", "copchest.gif", "dbfrfn.gif", "doctor.gif", "dogface.gif", + "dummy.gif", "e.gif", "flowers.gif", "fruit.gif", "gasroad.gif", "gdface.gif", "g.gif", + "grassx.gif", "infochst.gif", "infoface.gif", "jailpad.gif", "jfrnt.gif", "jsfrnt4.gif", "jsfrnt.gif", + "jside.gif", "jswnsh5.gif", "jswnsh.gif", "l6.gif", "l.gif", "mamachst.gif", "mamaface.gif", + "mamamap.gif", "mech.gif", "medic01.gif", "mitesx.gif", "mustache.gif", "nickchst.gif", "nickface.gif", + "nickmap.gif", "nopizza.gif", "norachst.gif", "noraface.gif", "noramap.gif", "nwcurve.gif", "octan01.gif", + "octsq01.gif", "o.gif", "papachst.gif", "papaface.gif", "papamap.gif", "pebblesx.gif", "pepperha.gif", + "peppizza.gif", "peppmap.gif", "peprchst.gif", "peprface.gif", "pianokys.gif", "pizcurve.gif", "pizza01.gif", + "pizza.gif", "polbar01.gif", "polbla01.gif", "polkadot.gif", "polwhi01.gif", "postchst.gif", "post.gif", + "rac1chst.gif", "rac2chst.gif", "radar.gif", "raddis01.gif", "rcback.gif", "rc-butn.gif", "rcfrnt5.gif", + "rcfrnt6.gif", "rcfrnt7.gif", "rcfrnt.gif", "rcside1.gif", "rcside2.gif", "rcside3.gif", "rctail.gif", + "redskul.gif", "relrel01.gif", "road1way.gif", "road3wa2.gif", "road3wa3.gif", "road3way.gif", "road4way.gif", + "roadstr8.gif", "rockx.gif", "roofpiz.gif", "sandredx.gif", "se_curve.gif", "shftchst.gif", "shftface2.gif", + "shftface.gif", "shldwn02.gif", "skull.gif", "smile.gif", "smileshd.gif", "supr2_01.gif", "tightcrv.gif", + "unkchst.gif", "val_02.gif", "vest.gif", "water2x.gif", "w_curve.gif", "wnbars.gif", "woman.gif", + "womanshd.gif" +}; diff --git a/LEGO1/lego/legoomni/include/ambulance.h b/LEGO1/lego/legoomni/include/ambulance.h index cb6a396a..4f0a0623 100644 --- a/LEGO1/lego/legoomni/include/ambulance.h +++ b/LEGO1/lego/legoomni/include/ambulance.h @@ -211,7 +211,7 @@ class Ambulance : public IslePathActor { MxS16 m_atPoliceTask; // 0x16c MxS16 m_atBeachTask; // 0x16e MxS16 m_taskState; // 0x170 - MxS16 m_unk0x172; // 0x172 + MxS16 m_enableRandomAudio; // 0x172 IsleScript::Script m_lastAction; // 0x174 IsleScript::Script m_lastAnimation; // 0x178 MxFloat m_fuel; // 0x17c diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 94bdc9fa..4b764d0b 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -304,4 +304,7 @@ class LegoAnimationManager : public MxCore { // TEMPLATE: LEGO1 0x10061750 // MxListCursor::MxListCursor +// TEMPLATE: BETA10 0x1004b5d0 +// MxListCursor::Next + #endif // LEGOANIMATIONMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index 802e8917..6e983144 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -2,6 +2,7 @@ #define LEGOANIMPRESENTER_H #include "legoroilist.h" +#include "legoroimaplist.h" #include "mxatom.h" #include "mxvideopresenter.h" @@ -147,14 +148,191 @@ class LegoAnimPresenter : public MxVideoPresenter { MxS16 m_unk0x9c; // 0x9c Matrix4* m_unk0xa0; // 0xa0 + // SYNTHETIC: LEGO1 0x10068650 + // LegoAnimPresenter::`scalar deleting destructor' + public: float m_unk0xa4; // 0xa4 Mx3DPointFloat m_unk0xa8; // 0xa8 }; +// VTABLE: LEGO1 0x100d4900 +// SIZE 0xc0 +class LegoLoopingAnimPresenter : public LegoAnimPresenter { +public: + // FUNCTION: BETA10 0x1005c6f0 + static const char* HandlerClassName() + { + // STRING: LEGO1 0x100f0700 + return "LegoLoopingAnimPresenter"; + } + + // FUNCTION: LEGO1 0x1000c9a0 + // FUNCTION: BETA10 0x1005c6c0 + const char* ClassName() const override // vtable+0x0c + { + return HandlerClassName(); + } + + // FUNCTION: LEGO1 0x1000c9b0 + MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); + } + + void StreamingTickle() override; // vtable+0x20 + void PutFrame() override; // vtable+0x6c + + // SYNTHETIC: LEGO1 0x1006d000 + // LegoLoopingAnimPresenter::~LegoLoopingAnimPresenter + + // SYNTHETIC: LEGO1 0x1000f440 + // LegoLoopingAnimPresenter::`scalar deleting destructor' + +private: + undefined4 m_unk0xbc; // 0xbc +}; + +class LegoAnimActor; + +// VTABLE: LEGO1 0x100d9170 +// SIZE 0xd8 +class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { +public: + LegoLocomotionAnimPresenter(); + ~LegoLocomotionAnimPresenter() override; + + // FUNCTION: BETA10 0x1005c4e0 + static const char* HandlerClassName() + { + // STRING: LEGO1 0x100f06e4 + return "LegoLocomotionAnimPresenter"; + } + + // FUNCTION: LEGO1 0x1006ce50 + // FUNCTION: BETA10 0x1005c4b0 + const char* ClassName() const override // vtable+0x0c + { + return HandlerClassName(); + } + + // FUNCTION: LEGO1 0x1006ce60 + MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || LegoLoopingAnimPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + MxResult CreateAnim(MxStreamChunk* p_chunk) override; // vtable+0x88 + + void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value); + + void DecrementUnknown0xd4() + { + if (m_unk0xd4) { + --m_unk0xd4; + } + } + + undefined2 GetUnknown0xd4() { return m_unk0xd4; } + + // SYNTHETIC: LEGO1 0x1006cfe0 + // LegoLocomotionAnimPresenter::`scalar deleting destructor' + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + + undefined4 m_unk0xc0; // 0xc0 + undefined4* m_unk0xc4; // 0xc4 + LegoROIMapList* m_roiMapList; // 0xc8 + MxS32 m_unk0xcc; // 0xcc + MxS32 m_unk0xd0; // 0xd0 + undefined2 m_unk0xd4; // 0xd4 +}; + +class LegoPathBoundary; + +struct LegoHideAnimStructComparator { + MxBool operator()(const char* const& p_a, const char* const& p_b) const { return strcmp(p_a, p_b) < 0; } +}; + +// SIZE 0x08 +struct LegoHideAnimStruct { + LegoPathBoundary* m_boundary; // 0x00 + MxU32 m_index; // 0x04 +}; + +typedef map LegoHideAnimStructMap; + +// VTABLE: LEGO1 0x100d9278 +// SIZE 0xc4 +class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { +public: + LegoHideAnimPresenter(); + ~LegoHideAnimPresenter() override; + + // FUNCTION: LEGO1 0x1006d860 + void VTable0x8c() override {} // vtable+0x8c + + // FUNCTION: LEGO1 0x1006d870 + void VTable0x90() override {} // vtable+0x90 + + // FUNCTION: BETA10 0x1005d4a0 + static const char* HandlerClassName() + { + // STRING: LEGO1 0x100f06cc + return "LegoHideAnimPresenter"; + } + + // FUNCTION: LEGO1 0x1006d880 + // FUNCTION: BETA10 0x1005d470 + const char* ClassName() const override // vtable+0x0c + { + return HandlerClassName(); + } + + // FUNCTION: LEGO1 0x1006d890 + MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x18 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + + void FUN_1006db40(LegoTime p_time); + + // SYNTHETIC: LEGO1 0x1006d9d0 + // LegoHideAnimPresenter::`scalar deleting destructor' + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + void FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time); + void FUN_1006dc10(); + void FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node); + void FUN_1006e470( + LegoHideAnimStructMap& p_map, + LegoAnimNodeData* p_data, + const char* p_name, + LegoPathBoundary* p_boundary + ); + + LegoPathBoundary** m_boundaryMap; // 0xc0 +}; + // clang-format off -// SYNTHETIC: LEGO1 0x10068650 -// LegoAnimPresenter::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100689c0 // map >::~map > @@ -212,6 +390,33 @@ class LegoAnimPresenter : public MxVideoPresenter { // GLOBAL: LEGO1 0x100f7688 // _Tree,map >::_Kfn,LegoAnimStructComparator,allocator >::_Nil + +// TEMPLATE: LEGO1 0x1006ddb0 +// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::~_Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x1006dec0 +// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::erase + +// TEMPLATE: LEGO1 0x1006e310 +// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::_Erase + +// TEMPLATE: LEGO1 0x1006e350 +// Map::~Map + +// TEMPLATE: LEGO1 0x1006e3a0 +// map >::~map > + +// TEMPLATE: LEGO1 0x1006e6d0 +// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::iterator::_Dec + +// TEMPLATE: LEGO1 0x1006e720 +// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::_Insert + +// GLOBAL: LEGO1 0x100f768c +// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::_Nil // clang-format on #endif // LEGOANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legocachesoundmanager.h b/LEGO1/lego/legoomni/include/legocachesoundmanager.h index 2f9f851b..642ef087 100644 --- a/LEGO1/lego/legoomni/include/legocachesoundmanager.h +++ b/LEGO1/lego/legoomni/include/legocachesoundmanager.h @@ -48,10 +48,13 @@ typedef set Set100d6b4c; typedef list List100d6b4c; // VTABLE: LEGO1 0x100d6b4c +// VTABLE: BETA10 0x101becac // SIZE 0x20 class LegoCacheSoundManager { public: + // FUNCTION: BETA10 0x100d0a60 LegoCacheSoundManager() {} + ~LegoCacheSoundManager(); virtual MxResult Tickle(); // vtable+0x00 @@ -68,6 +71,9 @@ class LegoCacheSoundManager { List100d6b4c m_list; // 0x14 }; +// SYNTHETIC: BETA10 0x100d06b0 +// LegoCacheSoundManager::`scalar deleting destructor' + // TODO: Function names subject to change. // clang-format off diff --git a/LEGO1/lego/legoomni/include/legocameracontroller.h b/LEGO1/lego/legoomni/include/legocameracontroller.h index 4dcb6c39..cf4e8f0a 100644 --- a/LEGO1/lego/legoomni/include/legocameracontroller.h +++ b/LEGO1/lego/legoomni/include/legocameracontroller.h @@ -38,17 +38,17 @@ class LegoCameraController : public LegoPointOfViewController { virtual MxResult Create(); // vtable+0x44 void SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up); - void FUN_10012290(float p_angle); - void FUN_10012320(float p_angle); - MxResult FUN_100123b0(Matrix4& p_matrix); - void FUN_100123e0(const Matrix4& p_transform, MxU32 p_und); + void RotateZ(float p_angle); + void RotateY(float p_angle); + MxResult GetPointOfView(Matrix4& p_matrix); + void TransformPointOfView(const Matrix4& p_transform, MxU32 p_multiply); Mx3DPointFloat GetWorldUp(); Mx3DPointFloat GetWorldLocation(); Mx3DPointFloat GetWorldDirection(); private: - MxMatrix m_matrix1; // 0x38 - MxMatrix m_matrix2; // 0x80 + MxMatrix m_currentTransform; // 0x38 + MxMatrix m_originalTransform; // 0x80 }; // SYNTHETIC: LEGO1 0x10011f50 diff --git a/LEGO1/lego/legoomni/include/legocharactermanager.h b/LEGO1/lego/legoomni/include/legocharactermanager.h index 9b4c5313..4443ca8a 100644 --- a/LEGO1/lego/legoomni/include/legocharactermanager.h +++ b/LEGO1/lego/legoomni/include/legocharactermanager.h @@ -48,6 +48,7 @@ struct LegoActorInfo; typedef map LegoCharacterMap; // VTABLE: LEGO1 0x100da878 +// VTABLE: BETA10 0x101bc028 // SIZE 0x24 class CustomizeAnimFileVariable : public MxVariable { public: diff --git a/LEGO1/lego/legoomni/include/legocontrolmanager.h b/LEGO1/lego/legoomni/include/legocontrolmanager.h index f962ee0c..680bef59 100644 --- a/LEGO1/lego/legoomni/include/legocontrolmanager.h +++ b/LEGO1/lego/legoomni/include/legocontrolmanager.h @@ -24,11 +24,11 @@ class LegoControlManagerNotificationParam : public LegoEventNotificationParam { void SetClickedObjectId(MxS32 p_clickedObjectId) { m_clickedObjectId = p_clickedObjectId; } void SetClickedAtom(const char* p_clickedAtom) { m_clickedAtom = p_clickedAtom; } - void SetUnknown0x28(MxS16 p_unk0x28) { m_unk0x28 = p_unk0x28; } + void SetEnabledChild(MxS16 p_enabledChild) { m_enabledChild = p_enabledChild; } MxS32 m_clickedObjectId; // 0x20 const char* m_clickedAtom; // 0x24 - MxS16 m_unk0x28; // 0x28 + MxS16 m_enabledChild; // 0x28 }; // SYNTHETIC: LEGO1 0x10028bf0 diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 28e5b47d..44d5bc27 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -30,6 +30,7 @@ struct InternationalCharacter { }; // VTABLE: LEGO1 0x100d74a8 +// VTABLE: BETA10 0x101bc4f0 // SIZE 0x30 class LegoBackgroundColor : public MxVariable { public: @@ -50,9 +51,11 @@ class LegoBackgroundColor : public MxVariable { }; // VTABLE: LEGO1 0x100d74b8 +// VTABLE: BETA10 0x101bc500 // SIZE 0x24 class LegoFullScreenMovie : public MxVariable { public: + LegoFullScreenMovie(); LegoFullScreenMovie(const char* p_key, const char* p_value); void SetValue(const char* p_option) override; // vtable+0x04 @@ -110,19 +113,19 @@ class LegoGameState { e_dunecarbuild, e_jetskibuild, e_racecarbuild, - e_unk40, + e_helicopterSpawn, e_unk41, e_unk42, - e_unk43, - e_unk44, - e_unk45, + e_dunebuggySpawn, + e_racecarSpawn, + e_jetskiSpawn, e_act2main, e_act3script, e_unk48, e_unk49, e_unk50, e_unk51, - e_unk52, + e_towTrackHookedUp, e_jukeboxw, e_jukeboxExterior, e_unk55, diff --git a/LEGO1/lego/legoomni/include/legohideanimpresenter.h b/LEGO1/lego/legoomni/include/legohideanimpresenter.h deleted file mode 100644 index b2bbb7b8..00000000 --- a/LEGO1/lego/legoomni/include/legohideanimpresenter.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef LEGOHIDEANIMPRESENTER_H -#define LEGOHIDEANIMPRESENTER_H - -#include "decomp.h" -#include "legoloopinganimpresenter.h" - -class LegoPathBoundary; - -struct LegoHideAnimStructComparator { - MxBool operator()(const char* const& p_a, const char* const& p_b) const { return strcmp(p_a, p_b) < 0; } -}; - -// SIZE 0x08 -struct LegoHideAnimStruct { - LegoPathBoundary* m_boundary; // 0x00 - MxU32 m_index; // 0x04 -}; - -typedef map LegoHideAnimStructMap; - -// VTABLE: LEGO1 0x100d9278 -// SIZE 0xc4 -class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { -public: - LegoHideAnimPresenter(); - ~LegoHideAnimPresenter() override; - - // FUNCTION: LEGO1 0x1006d860 - void VTable0x8c() override {} // vtable+0x8c - - // FUNCTION: LEGO1 0x1006d870 - void VTable0x90() override {} // vtable+0x90 - - // FUNCTION: BETA10 0x1005d4a0 - static const char* HandlerClassName() - { - // STRING: LEGO1 0x100f06cc - return "LegoHideAnimPresenter"; - } - - // FUNCTION: LEGO1 0x1006d880 - // FUNCTION: BETA10 0x1005d470 - const char* ClassName() const override // vtable+0x0c - { - return HandlerClassName(); - } - - // FUNCTION: LEGO1 0x1006d890 - MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); - } - - void ReadyTickle() override; // vtable+0x18 - void StartingTickle() override; // vtable+0x18 - MxResult AddToManager() override; // vtable+0x34 - void Destroy() override; // vtable+0x38 - void EndAction() override; // vtable+0x40 - void PutFrame() override; // vtable+0x6c - - void FUN_1006db40(LegoTime p_time); - -private: - void Init(); - void Destroy(MxBool p_fromDestructor); - void FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time); - void FUN_1006dc10(); - void FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node); - void FUN_1006e470( - LegoHideAnimStructMap& p_map, - LegoAnimNodeData* p_data, - const char* p_name, - LegoPathBoundary* p_boundary - ); - - LegoPathBoundary** m_boundaryMap; // 0xc0 -}; - -// clang-format off -// SYNTHETIC: LEGO1 0x1006d9d0 -// LegoHideAnimPresenter::`scalar deleting destructor' - -// TEMPLATE: LEGO1 0x1006ddb0 -// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::~_Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::iterator::_Inc - -// TEMPLATE: LEGO1 0x1006dec0 -// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::erase - -// TEMPLATE: LEGO1 0x1006e310 -// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::_Erase - -// TEMPLATE: LEGO1 0x1006e350 -// Map::~Map - -// TEMPLATE: LEGO1 0x1006e3a0 -// map >::~map > - -// TEMPLATE: LEGO1 0x1006e6d0 -// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::iterator::_Dec - -// TEMPLATE: LEGO1 0x1006e720 -// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::_Insert - -// GLOBAL: LEGO1 0x100f768c -// _Tree,map >::_Kfn,LegoHideAnimStructComparator,allocator >::_Nil -// clang-format on - -#endif // LEGOHIDEANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h deleted file mode 100644 index df2f872e..00000000 --- a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef LEGOLOCOMOTIONANIMPRESENTER_H -#define LEGOLOCOMOTIONANIMPRESENTER_H - -#include "legoloopinganimpresenter.h" -#include "legoroimaplist.h" - -class LegoAnimActor; - -// VTABLE: LEGO1 0x100d9170 -// SIZE 0xd8 -class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { -public: - LegoLocomotionAnimPresenter(); - ~LegoLocomotionAnimPresenter() override; - - // FUNCTION: BETA10 0x1005c4e0 - static const char* HandlerClassName() - { - // STRING: LEGO1 0x100f06e4 - return "LegoLocomotionAnimPresenter"; - } - - // FUNCTION: LEGO1 0x1006ce50 - // FUNCTION: BETA10 0x1005c4b0 - const char* ClassName() const override // vtable+0x0c - { - return HandlerClassName(); - } - - // FUNCTION: LEGO1 0x1006ce60 - MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ClassName()) || LegoLoopingAnimPresenter::IsA(p_name); - } - - void ReadyTickle() override; // vtable+0x18 - void StartingTickle() override; // vtable+0x1c - void StreamingTickle() override; // vtable+0x20 - MxResult AddToManager() override; // vtable+0x34 - void Destroy() override; // vtable+0x38 - void EndAction() override; // vtable+0x40 - void PutFrame() override; // vtable+0x6c - MxResult CreateAnim(MxStreamChunk* p_chunk) override; // vtable+0x88 - - // SYNTHETIC: LEGO1 0x1006cfe0 - // LegoLocomotionAnimPresenter::`scalar deleting destructor' - - void FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value); - - void DecrementUnknown0xd4() - { - if (m_unk0xd4) { - --m_unk0xd4; - } - } - - undefined2 GetUnknown0xd4() { return m_unk0xd4; } - -private: - void Init(); - void Destroy(MxBool p_fromDestructor); - - undefined4 m_unk0xc0; // 0xc0 - undefined4* m_unk0xc4; // 0xc4 - LegoROIMapList* m_roiMapList; // 0xc8 - MxS32 m_unk0xcc; // 0xcc - MxS32 m_unk0xd0; // 0xd0 - undefined2 m_unk0xd4; // 0xd4 -}; - -#endif // LEGOLOCOMOTIONANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h deleted file mode 100644 index 8952cbba..00000000 --- a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef LEGOLOOPINGANIMPRESENTER_H -#define LEGOLOOPINGANIMPRESENTER_H - -#include "legoanimpresenter.h" - -// VTABLE: LEGO1 0x100d4900 -// SIZE 0xc0 -class LegoLoopingAnimPresenter : public LegoAnimPresenter { -public: - // FUNCTION: BETA10 0x1005c6f0 - static const char* HandlerClassName() - { - // STRING: LEGO1 0x100f0700 - return "LegoLoopingAnimPresenter"; - } - - // FUNCTION: LEGO1 0x1000c9a0 - // FUNCTION: BETA10 0x1005c6c0 - const char* ClassName() const override // vtable+0x0c - { - return HandlerClassName(); - } - - // FUNCTION: LEGO1 0x1000c9b0 - MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); - } - - void StreamingTickle() override; // vtable+0x20 - void PutFrame() override; // vtable+0x6c - -private: - undefined4 m_unk0xbc; // 0xbc -}; - -// SYNTHETIC: LEGO1 0x1006d000 -// LegoLoopingAnimPresenter::~LegoLoopingAnimPresenter - -// SYNTHETIC: LEGO1 0x1000f440 -// LegoLoopingAnimPresenter::`scalar deleting destructor' - -#endif // LEGOLOOPINGANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legomain.h b/LEGO1/lego/legoomni/include/legomain.h index 90196e6a..7d4fd5b2 100644 --- a/LEGO1/lego/legoomni/include/legomain.h +++ b/LEGO1/lego/legoomni/include/legomain.h @@ -185,8 +185,8 @@ class LegoOmni : public MxOmni { // FUNCTION: BETA10 0x100d55c0 void SetExit(MxBool p_exit) { m_exit = p_exit; } - MxResult StartActionIfUnknown0x13c(MxDSAction& p_dsAction) { return m_unk0x13c ? Start(&p_dsAction) : SUCCESS; } - void SetUnknown13c(MxBool p_unk0x13c) { m_unk0x13c = p_unk0x13c; } + MxResult StartActionIfInitialized(MxDSAction& p_dsAction) { return m_initialized ? Start(&p_dsAction) : SUCCESS; } + void SetInitialized(MxBool p_unk0x13c) { m_initialized = p_unk0x13c; } void CloseMainWindow() { @@ -227,7 +227,7 @@ class LegoOmni : public MxOmni { MxBool m_version10; public: - MxBool m_unk0x13c; // 0x13c + MxBool m_initialized; // 0x13c }; #endif // LEGOMAIN_H diff --git a/LEGO1/lego/legoomni/include/legosoundmanager.h b/LEGO1/lego/legoomni/include/legosoundmanager.h index 9c03b06d..f503bf6e 100644 --- a/LEGO1/lego/legoomni/include/legosoundmanager.h +++ b/LEGO1/lego/legoomni/include/legosoundmanager.h @@ -17,15 +17,15 @@ class LegoSoundManager : public MxSoundManager { void Destroy() override; // vtable+0x18 MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x30 - // SYNTHETIC: LEGO1 0x10029920 - // SYNTHETIC: BETA10 0x100d0660 - // LegoSoundManager::`scalar deleting destructor' - void UpdateListener(const float* p_position, const float* p_direction, const float* p_up, const float* p_velocity); // FUNCTION: BETA10 0x1000f350 LegoCacheSoundManager* GetCacheSoundManager() { return m_cacheSoundManager; } + // SYNTHETIC: LEGO1 0x10029920 + // SYNTHETIC: BETA10 0x100d0660 + // LegoSoundManager::`scalar deleting destructor' + private: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/lego/legoomni/include/legotraninfolist.h b/LEGO1/lego/legoomni/include/legotraninfolist.h index 06cd2558..0bfe4bd8 100644 --- a/LEGO1/lego/legoomni/include/legotraninfolist.h +++ b/LEGO1/lego/legoomni/include/legotraninfolist.h @@ -28,9 +28,11 @@ class LegoTranInfoList : public MxPtrList { // class MxPtrListCursor // VTABLE: LEGO1 0x100d8d20 +// VTABLE: BETA10 0x101bad70 // SIZE 0x10 class LegoTranInfoListCursor : public MxPtrListCursor { public: + // FUNCTION: BETA10 0x100496d0 LegoTranInfoListCursor(LegoTranInfoList* p_list) : MxPtrListCursor(p_list) {} }; @@ -62,9 +64,14 @@ class LegoTranInfoListCursor : public MxPtrListCursor { // MxPtrList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100612f0 +// SYNTHETIC: BETA10 0x100498c0 // LegoTranInfoListCursor::`scalar deleting destructor' +// SYNTHETIC: BETA10 0x10049770 +// MxPtrListCursor::MxPtrListCursor + // FUNCTION: LEGO1 0x10061360 +// FUNCTION: BETA10 0x10049910 // MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x100613b0 @@ -77,6 +84,7 @@ class LegoTranInfoListCursor : public MxPtrListCursor { // MxListCursor::~MxListCursor // FUNCTION: LEGO1 0x100614e0 +// FUNCTION: BETA10 0x10049ab0 // LegoTranInfoListCursor::~LegoTranInfoListCursor #endif // LEGOTRANINFOLIST_H diff --git a/LEGO1/lego/legoomni/include/legovariables.h b/LEGO1/lego/legoomni/include/legovariables.h index 9447a5f9..873ef34c 100644 --- a/LEGO1/lego/legoomni/include/legovariables.h +++ b/LEGO1/lego/legoomni/include/legovariables.h @@ -17,41 +17,60 @@ extern const char* g_varVISIBILITY; extern const char* g_varCAMERALOCATION; extern const char* g_varCURSOR; extern const char* g_varWHOAMI; +extern const char* g_varDEBUG; // VTABLE: LEGO1 0x100d86c8 +// VTABLE: BETA10 0x101bc980 // SIZE 0x24 class VisibilityVariable : public MxVariable { public: + // FUNCTION: BETA10 0x10093470 VisibilityVariable() { m_key = g_varVISIBILITY; } void SetValue(const char* p_value) override; // vtable+0x04 }; // VTABLE: LEGO1 0x100d86b8 +// VTABLE: BETA10 0x101bc990 // SIZE 0x24 class CameraLocationVariable : public MxVariable { public: + // FUNCTION: BETA10 0x10093510 CameraLocationVariable() { m_key = g_varCAMERALOCATION; } void SetValue(const char* p_value) override; // vtable+0x04 }; // VTABLE: LEGO1 0x100d86a8 +// VTABLE: BETA10 0x101bc9a0 // SIZE 0x24 class CursorVariable : public MxVariable { public: + // FUNCTION: BETA10 0x100935b0 CursorVariable() { m_key = g_varCURSOR; } void SetValue(const char* p_value) override; // vtable+0x04 }; // VTABLE: LEGO1 0x100d8698 +// VTABLE: BETA10 0x101bc9b0 // SIZE 0x24 class WhoAmIVariable : public MxVariable { public: + // FUNCTION: BETA10 0x10093650 WhoAmIVariable() { m_key = g_varWHOAMI; } void SetValue(const char* p_value) override; // vtable+0x04 }; +// VTABLE: BETA10 0x101bc9c0 +// SIZE 0x24 +class DebugVariable : public MxVariable { +public: + // FUNCTION: BETA10 0x100936f0 + DebugVariable() { m_key = g_varDEBUG; } + + void SetValue(const char* p_value) override; // vtable+0x04 +}; + #endif // LEGOVARIABLES_H diff --git a/LEGO1/lego/legoomni/include/misc.h b/LEGO1/lego/legoomni/include/misc.h index 1df9fe37..8e294343 100644 --- a/LEGO1/lego/legoomni/include/misc.h +++ b/LEGO1/lego/legoomni/include/misc.h @@ -53,7 +53,7 @@ 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); -MxResult StartActionIfUnknown0x13c(MxDSAction& p_dsAction); +MxResult StartActionIfInitialized(MxDSAction& p_dsAction); void DeleteAction(); LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid); MxDSAction& GetCurrentAction(); diff --git a/LEGO1/lego/legoomni/src/actors/act3actors.cpp b/LEGO1/lego/legoomni/src/actors/act3actors.cpp index 63088156..2926466f 100644 --- a/LEGO1/lego/legoomni/src/actors/act3actors.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3actors.cpp @@ -4,9 +4,9 @@ #include "act3ammo.h" #include "anim/legoanim.h" #include "define.h" +#include "legoanimpresenter.h" #include "legobuildingmanager.h" #include "legocachesoundmanager.h" -#include "legolocomotionanimpresenter.h" #include "legopathedgecontainer.h" #include "legoplantmanager.h" #include "legoplants.h" diff --git a/LEGO1/lego/legoomni/src/actors/ambulance.cpp b/LEGO1/lego/legoomni/src/actors/ambulance.cpp index 23c9164d..0d2b89cc 100644 --- a/LEGO1/lego/legoomni/src/actors/ambulance.cpp +++ b/LEGO1/lego/legoomni/src/actors/ambulance.cpp @@ -44,7 +44,7 @@ Ambulance::Ambulance() m_atBeachTask = 0; m_taskState = Ambulance::e_none; m_lastAction = IsleScript::c_noneIsle; - m_unk0x172 = 0; + m_enableRandomAudio = 0; m_lastAnimation = IsleScript::c_noneIsle; m_fuel = 1.0; } @@ -176,7 +176,7 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param) m_state->m_state = AmbulanceMissionState::e_enteredAmbulance; CurrentWorld()->PlaceActor(UserActor()); HandleClick(); - m_unk0x172 = 0; + m_enableRandomAudio = 0; TickleManager()->RegisterClient(this, 40000); } else if (objectId == IsleScript::c_hpz047pe_RunAnim || objectId == IsleScript::c_hpz048pe_RunAnim || objectId == IsleScript::c_hpz049bd_RunAnim || objectId == IsleScript::c_hpz053pa_RunAnim) { @@ -201,7 +201,7 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param) CurrentWorld()->PlaceActor(UserActor()); HandleClick(); SpawnPlayer(LegoGameState::e_pizzeriaExterior, TRUE, 0); - m_unk0x172 = 0; + m_enableRandomAudio = 0; TickleManager()->RegisterClient(this, 40000); if (m_atPoliceTask != 0) { @@ -225,7 +225,7 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param) CurrentWorld()->PlaceActor(UserActor()); HandleClick(); SpawnPlayer(LegoGameState::e_policeExited, TRUE, 0); - m_unk0x172 = 0; + m_enableRandomAudio = 0; TickleManager()->RegisterClient(this, 40000); if (m_atBeachTask != 0) { @@ -440,7 +440,7 @@ MxLong Ambulance::HandleControl(LegoControlManagerNotificationParam& p_param) { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case IsleScript::c_AmbulanceArms_Ctl: Exit(); @@ -457,7 +457,7 @@ MxLong Ambulance::HandleControl(LegoControlManagerNotificationParam& p_param) case IsleScript::c_AmbulanceHorn_Ctl: MxSoundPresenter* presenter = (MxSoundPresenter*) CurrentWorld()->Find("MxSoundPresenter", "AmbulanceHorn_Sound"); - presenter->Enable(p_param.m_unk0x28); + presenter->Enable(p_param.m_enabledChild); break; } } @@ -516,8 +516,8 @@ void Ambulance::ActivateSceneActions() // FUNCTION: BETA10 0x100237df MxResult Ambulance::Tickle() { - if (m_unk0x172 == 0) { - m_unk0x172 = 1; + if (m_enableRandomAudio == 0) { + m_enableRandomAudio = 1; } else if (m_lastAction == IsleScript::c_noneIsle) { IsleScript::Script objectId; diff --git a/LEGO1/lego/legoomni/src/actors/bike.cpp b/LEGO1/lego/legoomni/src/actors/bike.cpp index fa9bedcb..fbdce39e 100644 --- a/LEGO1/lego/legoomni/src/actors/bike.cpp +++ b/LEGO1/lego/legoomni/src/actors/bike.cpp @@ -81,7 +81,7 @@ MxLong Bike::HandleControl(LegoControlManagerNotificationParam& p_param) { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case IsleScript::c_BikeArms_Ctl: Exit(); @@ -97,7 +97,7 @@ MxLong Bike::HandleControl(LegoControlManagerNotificationParam& p_param) case IsleScript::c_BikeHorn_Ctl: MxSoundPresenter* presenter = (MxSoundPresenter*) CurrentWorld()->Find("MxSoundPresenter", "BikeHorn_Sound"); - presenter->Enable(p_param.m_unk0x28); + presenter->Enable(p_param.m_enabledChild); break; } } diff --git a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp index 0c398393..5b701c46 100644 --- a/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp +++ b/LEGO1/lego/legoomni/src/actors/dunebuggy.cpp @@ -124,7 +124,7 @@ MxLong DuneBuggy::HandleControl(LegoControlManagerNotificationParam& p_param) { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case IsleScript::c_DuneCarArms_Ctl: Exit(); @@ -140,7 +140,7 @@ MxLong DuneBuggy::HandleControl(LegoControlManagerNotificationParam& p_param) case IsleScript::c_DuneCarHorn_Ctl: MxSoundPresenter* presenter = (MxSoundPresenter*) CurrentWorld()->Find("MxSoundPresenter", "DuneCarHorn_Sound"); - presenter->Enable(p_param.m_unk0x28); + presenter->Enable(p_param.m_enabledChild); break; } } diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index 46353585..fc2addb3 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -82,7 +82,7 @@ void Helicopter::Exit() if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { SpawnPlayer( - LegoGameState::e_unk40, + LegoGameState::e_helicopterSpawn, TRUE, IslePathActor::c_spawnBit1 | IslePathActor::c_playMusic | IslePathActor::c_spawnBit3 ); @@ -189,7 +189,7 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) break; } - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { MxU32 isPizza = FALSE; switch (p_param.m_clickedObjectId) { @@ -426,7 +426,7 @@ void Helicopter::Animate(float p_time) v2 *= f2; v2 += v1; - m_world->GetCameraController()->FUN_100123e0(mat, 0); + m_world->GetCameraController()->TransformPointOfView(mat, 0); } else { if (m_state->m_unk0x08 == 4) { @@ -459,7 +459,7 @@ void Helicopter::FUN_100042a0(const Matrix4& p_matrix) // the typecast makes this function match for unknown reasons Vector3 vec6((const float*) m_unk0x1a8[3]); // locala0 // esp+0x28 - m_world->GetCameraController()->FUN_100123b0(local48); + m_world->GetCameraController()->GetPointOfView(local48); m_unk0x1a8.SetIdentity(); local90 = p_matrix; diff --git a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp index 9d5a3a22..d366761e 100644 --- a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp @@ -355,7 +355,7 @@ void IslePathActor::RegisterSpawnLocations() JukeboxScript::c_PoliceStation_Music ); g_spawnLocations[16] = SpawnLocation( - LegoGameState::e_unk40, + LegoGameState::e_helicopterSpawn, g_isleScript, 0, "edg02_51", @@ -379,7 +379,7 @@ void IslePathActor::RegisterSpawnLocations() JukeboxScript::c_noneJukebox ); g_spawnLocations[18] = SpawnLocation( - LegoGameState::e_unk43, + LegoGameState::e_dunebuggySpawn, g_isleScript, 0, "edg02_35", @@ -391,7 +391,7 @@ void IslePathActor::RegisterSpawnLocations() JukeboxScript::c_noneJukebox ); g_spawnLocations[19] = SpawnLocation( - LegoGameState::e_unk44, + LegoGameState::e_racecarSpawn, g_isleScript, 0, "EDG03_01", @@ -403,7 +403,7 @@ void IslePathActor::RegisterSpawnLocations() JukeboxScript::c_noneJukebox ); g_spawnLocations[20] = SpawnLocation( - LegoGameState::e_unk45, + LegoGameState::e_jetskiSpawn, g_isleScript, 0, "edg10_70", @@ -475,7 +475,7 @@ void IslePathActor::RegisterSpawnLocations() JukeboxScript::c_noneJukebox ); g_spawnLocations[26] = SpawnLocation( - LegoGameState::e_unk52, + LegoGameState::e_towTrackHookedUp, g_isleScript, 0, "edg02_19", diff --git a/LEGO1/lego/legoomni/src/actors/jetski.cpp b/LEGO1/lego/legoomni/src/actors/jetski.cpp index 43c8040c..cdde06ee 100644 --- a/LEGO1/lego/legoomni/src/actors/jetski.cpp +++ b/LEGO1/lego/legoomni/src/actors/jetski.cpp @@ -69,7 +69,7 @@ void Jetski::Animate(float p_time) // FUNCTION: LEGO1 0x1007e6f0 void Jetski::Exit() { - SpawnPlayer(LegoGameState::e_unk45, FALSE, c_spawnBit1 | c_playMusic | c_spawnBit3); + SpawnPlayer(LegoGameState::e_jetskiSpawn, FALSE, c_spawnBit1 | c_playMusic | c_spawnBit3); IslePathActor::Exit(); GameState()->m_currentArea = LegoGameState::e_jetski; RemoveFromWorld(); @@ -139,7 +139,7 @@ void Jetski::RemoveFromWorld() // FUNCTION: LEGO1 0x1007e8e0 MxLong Jetski::HandleControl(LegoControlManagerNotificationParam& p_param) { - if (p_param.m_unk0x28 == 1 && CurrentWorld()->IsA("Isle")) { + if (p_param.m_enabledChild == 1 && CurrentWorld()->IsA("Isle")) { switch (p_param.m_clickedObjectId) { case IsleScript::c_JetskiArms_Ctl: Exit(); diff --git a/LEGO1/lego/legoomni/src/actors/motorcycle.cpp b/LEGO1/lego/legoomni/src/actors/motorcycle.cpp index 9d17be8d..3a4229b3 100644 --- a/LEGO1/lego/legoomni/src/actors/motorcycle.cpp +++ b/LEGO1/lego/legoomni/src/actors/motorcycle.cpp @@ -117,7 +117,7 @@ MxLong Motocycle::HandleControl(LegoControlManagerNotificationParam& p_param) { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case IsleScript::c_MotoBikeArms_Ctl: Exit(); diff --git a/LEGO1/lego/legoomni/src/actors/skateboard.cpp b/LEGO1/lego/legoomni/src/actors/skateboard.cpp index d47b2178..17730148 100644 --- a/LEGO1/lego/legoomni/src/actors/skateboard.cpp +++ b/LEGO1/lego/legoomni/src/actors/skateboard.cpp @@ -110,7 +110,7 @@ MxLong SkateBoard::HandleControl(LegoControlManagerNotificationParam& p_param) { MxU32 result = 0; - if (p_param.m_unk0x28 == 1 && p_param.m_clickedObjectId == IsleScript::c_SkateArms_Ctl) { + if (p_param.m_enabledChild == 1 && p_param.m_clickedObjectId == IsleScript::c_SkateArms_Ctl) { Exit(); GameState()->m_currentArea = LegoGameState::Area::e_vehicleExited; result = 1; diff --git a/LEGO1/lego/legoomni/src/actors/towtrack.cpp b/LEGO1/lego/legoomni/src/actors/towtrack.cpp index 462905d4..bf6b29bc 100644 --- a/LEGO1/lego/legoomni/src/actors/towtrack.cpp +++ b/LEGO1/lego/legoomni/src/actors/towtrack.cpp @@ -434,7 +434,7 @@ MxLong TowTrack::HandleClick() } if (m_state->m_state == TowTrackMissionState::e_hookedUp) { - SpawnPlayer(LegoGameState::e_unk52, TRUE, 0); + SpawnPlayer(LegoGameState::e_towTrackHookedUp, TRUE, 0); FindROI("rcred")->SetVisibility(FALSE); } else { @@ -485,7 +485,7 @@ MxLong TowTrack::HandleControl(LegoControlManagerNotificationParam& p_param) { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case IsleScript::c_TowTrackArms_Ctl: Exit(); @@ -501,7 +501,7 @@ MxLong TowTrack::HandleControl(LegoControlManagerNotificationParam& p_param) break; case IsleScript::c_TowHorn_Ctl: MxSoundPresenter* presenter = (MxSoundPresenter*) CurrentWorld()->Find("MxSoundPresenter", "TowHorn_Sound"); - presenter->Enable(p_param.m_unk0x28); + presenter->Enable(p_param.m_enabledChild); break; } } diff --git a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp index 34be4519..cd235b61 100644 --- a/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp @@ -7,6 +7,7 @@ DECOMP_SIZE_ASSERT(LegoCacheSoundEntry, 0x08) DECOMP_SIZE_ASSERT(LegoCacheSoundManager, 0x20) // FUNCTION: LEGO1 0x1003cf20 +// STUB: BETA10 0x100d0700 LegoCacheSoundManager::~LegoCacheSoundManager() { LegoCacheSound* sound; @@ -28,6 +29,7 @@ LegoCacheSoundManager::~LegoCacheSoundManager() } // FUNCTION: LEGO1 0x1003d050 +// STUB: BETA10 0x100652f0 MxResult LegoCacheSoundManager::Tickle() { #ifdef COMPAT_MODE diff --git a/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp index 8adb79df..a9b60d66 100644 --- a/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp +++ b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp @@ -98,7 +98,7 @@ void LegoLoadCacheSoundPresenter::DoneTickle() // FUNCTION: LEGO1 0x10018700 MxResult LegoLoadCacheSoundPresenter::PutData() { - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (m_currentTickleState == e_done) { m_cacheSound = SoundManager()->GetCacheSoundManager()->ManageSoundEntry(m_cacheSound); diff --git a/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp b/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp index 1d53e64d..d5bd05af 100644 --- a/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp @@ -9,24 +9,28 @@ DECOMP_SIZE_ASSERT(LegoSoundManager, 0x44) // FUNCTION: LEGO1 0x100298a0 +// FUNCTION: BETA10 0x100cffb0 LegoSoundManager::LegoSoundManager() { Init(); } // FUNCTION: LEGO1 0x10029940 +// FUNCTION: BETA10 0x100d0027 LegoSoundManager::~LegoSoundManager() { Destroy(TRUE); } // FUNCTION: LEGO1 0x100299a0 +// FUNCTION: BETA10 0x100d0099 void LegoSoundManager::Init() { m_cacheSoundManager = NULL; } // FUNCTION: LEGO1 0x100299b0 +// FUNCTION: BETA10 0x100d00c9 void LegoSoundManager::Destroy(MxBool p_fromDestructor) { delete m_cacheSoundManager; @@ -41,17 +45,19 @@ void LegoSoundManager::Destroy(MxBool p_fromDestructor) // FUNCTION: BETA10 0x100d0129 MxResult LegoSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) { - MxBool locked = FALSE; MxResult result = FAILURE; + MxBool locked = FALSE; - if (MxSoundManager::Create(10, FALSE) == SUCCESS) { - m_criticalSection.Enter(); - locked = TRUE; - m_cacheSoundManager = new LegoCacheSoundManager; - assert(m_cacheSoundManager); - result = SUCCESS; + if (MxSoundManager::Create(10, FALSE) != SUCCESS) { + goto done; } + ENTER(m_criticalSection); + locked = TRUE; + m_cacheSoundManager = new LegoCacheSoundManager; + assert(m_cacheSoundManager); + result = SUCCESS; + done: if (result != SUCCESS) { Destroy(); diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index da309660..ab456f39 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -956,7 +956,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; assert(m_buildState); - if (param->m_unk0x28) { + if (param->m_enabledChild) { switch (param->m_clickedObjectId) { // The enum values are all identical between CopterScript, DunecarScript, JetskiScript, and RacecarScript case CopterScript::c_Info_Ctl: @@ -1012,7 +1012,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) case CopterScript::c_Platform_Ctl: FUN_10024f50(); m_unk0xf8 = c_unknown8; - m_unk0xfc = param->m_unk0x28; + m_unk0xfc = param->m_enabledChild; result = 1; break; default: @@ -1054,7 +1054,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; assert(m_buildState); - if (param->m_unk0x28) { + if (param->m_enabledChild) { switch (param->m_clickedObjectId) { case CopterScript::c_Info_Ctl: m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_selected); @@ -1116,7 +1116,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) case CopterScript::c_Platform_Ctl: FUN_10024f50(); m_unk0xf8 = c_unknown8; - m_unk0xfc = param->m_unk0x28; + m_unk0xfc = param->m_enabledChild; result = 1; break; default: @@ -1233,7 +1233,7 @@ undefined4 LegoCarBuild::FUN_10024c20(MxNotificationParam* p_param) jukeboxScript = JukeboxScript::c_RaceCarBuild_Music; } - m_unk0x338 = SoundManager()->FUN_100aebd0(*g_jukeboxScript, jukeboxScript); + m_unk0x338 = SoundManager()->FindPresenter(*g_jukeboxScript, jukeboxScript); if (m_unk0x338) { BackgroundAudioManager()->SetPendingPresenter(m_unk0x338, 5, MxPresenter::e_repeating); diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index 665c6459..330b4179 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -11,7 +11,6 @@ #include "legoentitylist.h" #include "legoextraactor.h" #include "legogamestate.h" -#include "legolocomotionanimpresenter.h" #include "legomain.h" #include "legonavcontroller.h" #include "legoroilist.h" @@ -20,6 +19,7 @@ #include "legoworld.h" #include "misc.h" #include "mxbackgroundaudiomanager.h" +#include "mxdebug.h" #include "mxmisc.h" #include "mxnotificationmanager.h" #include "mxticklemanager.h" @@ -1021,7 +1021,7 @@ MxResult LegoAnimationManager::FUN_100605e0( action.SetUnknown24(-1); action.AppendExtra(strlen(buf) + 1, buf); - if (StartActionIfUnknown0x13c(action) == SUCCESS) { + if (StartActionIfInitialized(action) == SUCCESS) { BackgroundAudioManager()->LowerVolume(); tranInfo->m_flags |= LegoTranInfo::c_bit2; animInfo.m_unk0x22++; @@ -1088,7 +1088,7 @@ MxResult LegoAnimationManager::FUN_100609f0(MxU32 p_objectId, MxMatrix* p_matrix action.SetUnknown24(-1); action.AppendExtra(strlen(buf) + 1, buf); - if (StartActionIfUnknown0x13c(action) == SUCCESS) { + if (StartActionIfInitialized(action) == SUCCESS) { BackgroundAudioManager()->LowerVolume(); info->m_flags |= LegoTranInfo::c_bit2; m_animRunning = TRUE; @@ -1131,7 +1131,7 @@ MxResult LegoAnimationManager::StartEntityAction(MxDSAction& p_dsAction, LegoEnt } } - if (LegoOmni::GetInstance()->StartActionIfUnknown0x13c(p_dsAction) == SUCCESS) { + if (LegoOmni::GetInstance()->StartActionIfInitialized(p_dsAction) == SUCCESS) { result = SUCCESS; } @@ -1155,7 +1155,7 @@ MxResult LegoAnimationManager::FUN_10060dc0( MxResult result = FAILURE; MxBool found = FALSE; - if (!Lego()->m_unk0x13c) { + if (!Lego()->m_initialized) { return SUCCESS; } @@ -1192,7 +1192,7 @@ MxResult LegoAnimationManager::FUN_10060dc0( // FUNCTION: BETA10 0x1004206c void LegoAnimationManager::CameraTriggerFire(LegoPathActor* p_actor, MxBool, MxU32 p_location, MxBool p_bool) { - if (Lego()->m_unk0x13c && m_enableCamAnims && !m_animRunning) { + if (Lego()->m_initialized && m_enableCamAnims && !m_animRunning) { LegoLocation* location = LegoNavController::GetLocation(p_location); if (location != NULL) { @@ -1231,12 +1231,10 @@ void LegoAnimationManager::CameraTriggerFire(LegoPathActor* p_actor, MxBool, MxU } } -// FUNCTION: LEGO1 0x10061010 +#ifdef BETA10 // FUNCTION: BETA10 0x100422cc void LegoAnimationManager::FUN_10061010(MxBool p_und) { - MxBool unk0x39 = FALSE; - FUN_10064b50(-1); if (m_tranInfoList != NULL) { @@ -1244,17 +1242,47 @@ void LegoAnimationManager::FUN_10061010(MxBool p_und) LegoTranInfo* tranInfo; while (cursor.Next(tranInfo)) { - if (tranInfo->m_presenter != NULL) { - // TODO: Match - MxU32 flags = tranInfo->m_flags; + if (tranInfo->m_unk0x14 && tranInfo->m_location != -1) { + MxTrace("Releasing user from %d\n", tranInfo->m_objectId); + if (tranInfo->m_presenter != NULL) { + tranInfo->m_presenter->FUN_1004b8c0(); + } + + tranInfo->m_unk0x14 = FALSE; + } + else { + MxTrace("Stopping %d\n", tranInfo->m_objectId); + + if (tranInfo->m_presenter != NULL) { + tranInfo->m_presenter->FUN_1004b840(); + } + } + } + } + + m_animRunning = FALSE; + m_unk0x404 = Timer()->GetTime(); +} +#else +// FUNCTION: LEGO1 0x10061010 +void LegoAnimationManager::FUN_10061010(MxBool p_und) +{ + MxBool animRunning = FALSE; + FUN_10064b50(-1); + + if (m_tranInfoList != NULL) { + LegoTranInfoListCursor cursor(m_tranInfoList); + LegoTranInfo* tranInfo; + + while (cursor.Next(tranInfo)) { + if (tranInfo->m_presenter) { + // LINE: LEGO1 0x100610e6 if (tranInfo->m_unk0x14 && tranInfo->m_location != -1 && p_und) { - LegoAnim* anim; - - if (tranInfo->m_presenter->GetPresenter() != NULL && - (anim = tranInfo->m_presenter->GetPresenter()->GetAnimation()) != NULL && - anim->GetCamAnim() != NULL) { - if (flags & LegoTranInfo::c_bit2) { + if (tranInfo->m_presenter->GetPresenter() && + tranInfo->m_presenter->GetPresenter()->GetAnimation() && + tranInfo->m_presenter->GetPresenter()->GetAnimation()->GetCamAnim()) { + if (tranInfo->m_flags & LegoTranInfo::c_bit2) { BackgroundAudioManager()->RaiseVolume(); tranInfo->m_flags &= ~LegoTranInfo::c_bit2; } @@ -1263,37 +1291,43 @@ void LegoAnimationManager::FUN_10061010(MxBool p_und) tranInfo->m_unk0x14 = FALSE; } else { + MxTrace("Releasing user from %d\n", tranInfo->m_objectId); + // LINE: LEGO1 0x10061137 tranInfo->m_presenter->FUN_1004b8c0(); + animRunning = TRUE; tranInfo->m_unk0x14 = FALSE; - unk0x39 = TRUE; } } else { - if (flags & LegoTranInfo::c_bit2) { + if (tranInfo->m_flags & LegoTranInfo::c_bit2) { + // LINE: LEGO1 0x10061150 BackgroundAudioManager()->RaiseVolume(); tranInfo->m_flags &= ~LegoTranInfo::c_bit2; } + MxTrace("Stopping %d\n", tranInfo->m_objectId); tranInfo->m_presenter->FUN_1004b840(); } } else { if (m_tranInfoList2 != NULL) { LegoTranInfoListCursor cursor(m_tranInfoList2); - if (!cursor.Find(tranInfo)) { + // TODO: For some reason, the embedded `MxListEntry` constructor is not inlined. + // This may be the key for getting this function to match correctly. m_tranInfoList2->Append(tranInfo); } } - unk0x39 = TRUE; + animRunning = TRUE; } } } - m_animRunning = unk0x39; + m_animRunning = animRunning; m_unk0x404 = Timer()->GetTime(); } +#endif // FUNCTION: LEGO1 0x10061530 void LegoAnimationManager::FUN_10061530() diff --git a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp index ca6c2412..af32a238 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimmmpresenter.cpp @@ -425,6 +425,21 @@ MxBool LegoAnimMMPresenter::FUN_1004b6b0(MxLong p_time) // FUNCTION: BETA10 0x1004ce18 MxBool LegoAnimMMPresenter::FUN_1004b6d0(MxLong p_time) { +#ifdef BETA10 + switch (m_unk0x58) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + } +#endif + LegoROI* viewROI = VideoManager()->GetViewROI(); LegoPathActor* actor = UserActor(); @@ -455,9 +470,13 @@ MxBool LegoAnimMMPresenter::FUN_1004b6d0(MxLong p_time) m_world->PlaceActor(actor); } +#ifdef BETA10 + actor->VTable0xa8(); +#else if (m_tranInfo->m_unk0x29) { actor->VTable0xa8(); } +#endif } actor->SetActorState(LegoPathActor::c_initial); @@ -491,9 +510,11 @@ void LegoAnimMMPresenter::FUN_1004b840() FUN_1004b6d0(0); EndAction(); +#ifndef BETA10 if (action != NULL) { Streamer()->FUN_100b98f0(action); } +#endif } // FUNCTION: LEGO1 0x1004b8b0 diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp index adf442eb..180b8eec 100644 --- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp @@ -1092,6 +1092,7 @@ LegoROI* LegoCharacterManager::FUN_10085a80(const char* p_name, const char* p_lo } // FUNCTION: LEGO1 0x10085aa0 +// FUNCTION: BETA10 0x1007703d CustomizeAnimFileVariable::CustomizeAnimFileVariable(const char* p_key) { m_key = p_key; @@ -1099,6 +1100,7 @@ CustomizeAnimFileVariable::CustomizeAnimFileVariable(const char* p_key) } // FUNCTION: LEGO1 0x10085b50 +// FUNCTION: BETA10 0x100770c8 void CustomizeAnimFileVariable::SetValue(const char* p_value) { // STRING: LEGO1 0x100fc4f4 diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 4ba42020..6df31604 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -1349,6 +1349,11 @@ void LegoBackgroundColor::SetLightColor() SetLightColor(convertedR, convertedG, convertedB); } +// FUNCTION: BETA10 0x10086a87 +LegoFullScreenMovie::LegoFullScreenMovie() +{ +} + // FUNCTION: LEGO1 0x1003c500 // FUNCTION: BETA10 0x10086af6 LegoFullScreenMovie::LegoFullScreenMovie(const char* p_key, const char* p_value) diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp index 68a3b35a..b8514020 100644 --- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -10,7 +10,7 @@ #include "legoentity.h" #include "legopathactor.h" // The below header inclusions should be sound. -#include "legoloopinganimpresenter.h" +#include "legoanimpresenter.h" #include "mxcompositemediapresenter.h" #include "legoactorpresenter.h" #include "legomodelpresenter.h" @@ -71,10 +71,7 @@ #include "legoentity.h" #include "legoentitypresenter.h" #include "legoflctexturepresenter.h" -#include "legohideanimpresenter.h" #include "legoloadcachesoundpresenter.h" -#include "legolocomotionanimpresenter.h" -#include "legoloopinganimpresenter.h" #include "legometerpresenter.h" #include "legomodelpresenter.h" #include "legopalettepresenter.h" diff --git a/LEGO1/lego/legoomni/src/common/legovariables.cpp b/LEGO1/lego/legoomni/src/common/legovariables.cpp index 8269dfde..5d2d6cdb 100644 --- a/LEGO1/lego/legoomni/src/common/legovariables.cpp +++ b/LEGO1/lego/legoomni/src/common/legovariables.cpp @@ -6,6 +6,7 @@ #include "legonavcontroller.h" #include "legovideomanager.h" #include "misc.h" +#include "mxdebug.h" #include "roi/legoroi.h" #include @@ -103,6 +104,10 @@ const char* g_nick = "Nick"; // STRING: LEGO1 0x100f39e0 const char* g_laura = "Laura"; +// GLOBAL: BETA10 0x101f6ce4 +// STRING: BETA10 0x101f6d54 +const char* g_varDEBUG = "DEBUG"; + // FUNCTION: LEGO1 0x10037d00 // FUNCTION: BETA10 0x100d5620 void VisibilityVariable::SetValue(const char* p_value) @@ -132,6 +137,7 @@ void VisibilityVariable::SetValue(const char* p_value) } // FUNCTION: LEGO1 0x10037d80 +// FUNCTION: BETA10 0x100d56ee void CameraLocationVariable::SetValue(const char* p_value) { char buffer[256]; @@ -139,22 +145,25 @@ void CameraLocationVariable::SetValue(const char* p_value) strcpy(buffer, p_value); - char* location = strtok(buffer, ","); - NavController()->UpdateLocation(location); + char* token = strtok(buffer, ","); + assert(token); + NavController()->UpdateLocation(token); - location = strtok(NULL, ","); - if (location) { - MxFloat pov = (MxFloat) atof(location); + token = strtok(NULL, ","); + if (token) { + MxFloat pov = (MxFloat) atof(token); VideoManager()->Get3DManager()->SetFrustrum(pov, 0.1f, 250.0f); } } // FUNCTION: LEGO1 0x10037e30 +// FUNCTION: BETA10 0x100d57e2 void CursorVariable::SetValue(const char* p_value) { } // FUNCTION: LEGO1 0x10037e40 +// FUNCTION: BETA10 0x100d57fa void WhoAmIVariable::SetValue(const char* p_value) { MxVariable::SetValue(p_value); @@ -175,3 +184,10 @@ void WhoAmIVariable::SetValue(const char* p_value) GameState()->SetActorId(LegoActor::c_laura); } } + +// FUNCTION: BETA10 0x100d58fa +void DebugVariable::SetValue(const char* p_value) +{ + MxVariable::SetValue(p_value); + MxTrace("%s\n", p_value); +} diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 6b231b56..19ff0a21 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -172,9 +172,9 @@ void SetUserActor(LegoPathActor* p_userActor) // FUNCTION: LEGO1 0x10015890 // FUNCTION: BETA10 0x100e4d80 -MxResult StartActionIfUnknown0x13c(MxDSAction& p_dsAction) +MxResult StartActionIfInitialized(MxDSAction& p_dsAction) { - return LegoOmni::GetInstance()->StartActionIfUnknown0x13c(p_dsAction); + return LegoOmni::GetInstance()->StartActionIfInitialized(p_dsAction); } // FUNCTION: LEGO1 0x100158b0 diff --git a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp index 04437877..7c6a788d 100644 --- a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp @@ -27,6 +27,7 @@ MxCompositeMediaPresenter::~MxCompositeMediaPresenter() } // FUNCTION: LEGO1 0x10074090 +// FUNCTION: BETA10 0x100e9d37 MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { AUTOLOCK(m_criticalSection); diff --git a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp index bccfd6c7..ae11da97 100644 --- a/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcontrolpresenter.cpp @@ -157,7 +157,7 @@ MxBool MxControlPresenter::Notify(LegoControlManagerNotificationParam* p_param, p_param->SetClickedAtom(m_action->GetAtomId().GetInternal()); UpdateEnabledChild(0); p_param->SetNotification(c_notificationControl); - p_param->SetUnknown0x28(m_enabledChild); + p_param->SetEnabledChild(m_enabledChild); return TRUE; } break; @@ -167,7 +167,7 @@ MxBool MxControlPresenter::Notify(LegoControlManagerNotificationParam* p_param, p_param->SetClickedAtom(m_action->GetAtomId().GetInternal()); UpdateEnabledChild(m_stateOrCellIndex); p_param->SetNotification(c_notificationControl); - p_param->SetUnknown0x28(m_enabledChild); + p_param->SetEnabledChild(m_enabledChild); return TRUE; } break; diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index 6a7c59f7..cac7d66a 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -124,28 +124,28 @@ void LegoCameraController::OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) // FUNCTION: LEGO1 0x10012260 void LegoCameraController::SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up) { - CalcLocalTransform(p_at, p_dir, p_up, m_matrix1); - m_matrix2 = m_matrix1; + CalcLocalTransform(p_at, p_dir, p_up, m_currentTransform); + m_originalTransform = m_currentTransform; } // FUNCTION: LEGO1 0x10012290 // FUNCTION: BETA10 0x10068c34 -void LegoCameraController::FUN_10012290(float p_angle) +void LegoCameraController::RotateZ(float p_angle) { - m_matrix1 = m_matrix2; - m_matrix1.RotateZ(p_angle); + m_currentTransform = m_originalTransform; + m_currentTransform.RotateZ(p_angle); } // FUNCTION: LEGO1 0x10012320 // FUNCTION: BETA10 0x10068c73 -void LegoCameraController::FUN_10012320(float p_angle) +void LegoCameraController::RotateY(float p_angle) { - m_matrix1 = m_matrix2; - m_matrix1.RotateY(p_angle); + m_currentTransform = m_originalTransform; + m_currentTransform.RotateY(p_angle); } // FUNCTION: LEGO1 0x100123b0 -MxResult LegoCameraController::FUN_100123b0(Matrix4& p_matrix) +MxResult LegoCameraController::GetPointOfView(Matrix4& p_matrix) { if (m_lego3DView) { ViewROI* pov = m_lego3DView->GetPointOfView(); @@ -160,7 +160,7 @@ MxResult LegoCameraController::FUN_100123b0(Matrix4& p_matrix) // FUNCTION: LEGO1 0x100123e0 // FUNCTION: BETA10 0x10068cb2 -void LegoCameraController::FUN_100123e0(const Matrix4& p_transform, MxU32 p_und) +void LegoCameraController::TransformPointOfView(const Matrix4& p_transform, MxU32 p_multiply) { if (m_lego3DView != NULL) { ViewROI* pov = m_lego3DView->GetPointOfView(); @@ -168,8 +168,8 @@ void LegoCameraController::FUN_100123e0(const Matrix4& p_transform, MxU32 p_und) if (pov != NULL) { MxMatrix mat; - if (p_und) { - MXM4(mat, m_matrix1, p_transform); + if (p_multiply) { + MXM4(mat, m_currentTransform, p_transform); } else { mat = p_transform; diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index cce17c18..927d8125 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -197,7 +197,7 @@ void LegoEntity::FUN_10010c30() LegoWorld* world = CurrentWorld(); if (m_cameraFlag && world && world->GetCameraController() && m_roi) { - world->GetCameraController()->FUN_100123e0(m_roi->GetLocal2World(), 1); + world->GetCameraController()->TransformPointOfView(m_roi->GetLocal2World(), 1); } } diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 4308717a..c1cfc87a 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -555,7 +555,7 @@ MxResult LegoNavController::ProcessJoystickInput(MxBool& p_und) LegoWorld* world = CurrentWorld(); if (world && world->GetCameraController()) { - world->GetCameraController()->FUN_10012320(DTOR(povPosition)); + world->GetCameraController()->RotateY(DTOR(povPosition)); p_und = TRUE; } } @@ -902,7 +902,7 @@ MxLong LegoNavController::Notify(MxParam& p_param) break; case SDLK_A: if (g_animationCalcStep == 1) { - Lego()->m_unk0x13c = TRUE; + Lego()->m_initialized = TRUE; AnimationManager()->FUN_10060570(TRUE); g_animationCalcStep = 0; } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index b638f1e3..1ba828cb 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -9,7 +9,6 @@ #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" -#include "legolocomotionanimpresenter.h" #include "legonavcontroller.h" #include "legoplantmanager.h" #include "legosoundmanager.h" @@ -288,6 +287,7 @@ MxResult LegoWorld::PlaceActor( } // FUNCTION: LEGO1 0x1001fa70 +// FUNCTION: BETA10 0x100da328 MxResult LegoWorld::PlaceActor(LegoPathActor* p_actor) { LegoPathControllerListCursor cursor(&m_pathControllerList); @@ -303,6 +303,7 @@ MxResult LegoWorld::PlaceActor(LegoPathActor* p_actor) } // FUNCTION: LEGO1 0x1001fb70 +// FUNCTION: BETA10 0x100da3f1 MxResult LegoWorld::PlaceActor( LegoPathActor* p_actor, LegoAnimPresenter* p_presenter, diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index f7fef27e..61dfa9bc 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -612,6 +612,7 @@ MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touc case e_arrowKeys: switch (p_event->type) { case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_CANCELED: m_touchFlags.erase(event.fingerID); break; case SDL_EVENT_FINGER_DOWN: @@ -647,6 +648,7 @@ MxBool LegoInputManager::HandleTouchEvent(SDL_Event* p_event, TouchScheme p_touc } break; case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_CANCELED: if (event.fingerID == g_finger) { g_finger = 0; m_touchVirtualThumb = {0, 0}; @@ -795,6 +797,7 @@ void LegoInputManager::UpdateLastInputMethod(SDL_Event* p_event) case SDL_EVENT_FINGER_MOTION: case SDL_EVENT_FINGER_DOWN: case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_CANCELED: 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 78ddf033..e2105797 100644 --- a/LEGO1/lego/legoomni/src/main/legomain.cpp +++ b/LEGO1/lego/legoomni/src/main/legomain.cpp @@ -74,7 +74,7 @@ void LegoOmni::Init() m_animationManager = NULL; m_buildingManager = NULL; m_bkgAudioManager = NULL; - m_unk0x13c = TRUE; + m_initialized = TRUE; m_transitionManager = NULL; m_version10 = FALSE; } diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp index f6ca062c..0a1e6d98 100644 --- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp @@ -2,7 +2,7 @@ #include "anim/legoanim.h" #include "define.h" -#include "legolocomotionanimpresenter.h" +#include "legoanimpresenter.h" #include "legopathboundary.h" #include "legoworld.h" #include "misc.h" diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index 316d010b..04c551d0 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -1,8 +1,8 @@ #include "legoextraactor.h" #include "anim/legoanim.h" +#include "legoanimpresenter.h" #include "legocachesoundmanager.h" -#include "legolocomotionanimpresenter.h" #include "legosoundmanager.h" #include "legoworld.h" #include "misc.h" diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index c9ce7c6c..2e9ae767 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -440,7 +440,7 @@ void LegoPathActor::Animate(float p_time) LegoWorld* world = CurrentWorld(); if (world) { - world->GetCameraController()->FUN_10012290(DTOR(m_unk0x14c)); + world->GetCameraController()->RotateZ(DTOR(m_unk0x14c)); } } } diff --git a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp index f4d09f9e..31600f3e 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp @@ -2,7 +2,7 @@ #include "decomp.h" #include "geom/legoorientededge.h" -#include "legolocomotionanimpresenter.h" +#include "legoanimpresenter.h" #include "legopathactor.h" #include "legopathstruct.h" diff --git a/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp b/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp index e269f727..276b66ab 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp @@ -3,7 +3,7 @@ #include "isle.h" #include "jukebox.h" #include "jukebox_actions.h" -#include "legohideanimpresenter.h" +#include "legoanimpresenter.h" #include "legopathactor.h" #include "legoutils.h" #include "misc.h" diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp index 52315e79..33c740a1 100644 --- a/LEGO1/lego/legoomni/src/race/carrace.cpp +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -5,8 +5,8 @@ #include "isle.h" #include "jukebox_actions.h" #include "legoanimationmanager.h" +#include "legoanimpresenter.h" #include "legocontrolmanager.h" -#include "legohideanimpresenter.h" #include "legomain.h" #include "legonavcontroller.h" #include "legopathstruct.h" @@ -339,7 +339,7 @@ MxLong CarRace::HandlePathStruct(LegoPathStructNotificationParam& p_param) // FUNCTION: LEGO1 0x10017650 MxLong CarRace::HandleControl(LegoControlManagerNotificationParam& p_param) { - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case 3: InvokeAction(Extra::e_stop, *g_carraceScript, CarraceScript::c_irtx08ra_PlayWav, NULL); diff --git a/LEGO1/lego/legoomni/src/race/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp index edeb6aa2..f906c0d9 100644 --- a/LEGO1/lego/legoomni/src/race/jetskirace.cpp +++ b/LEGO1/lego/legoomni/src/race/jetskirace.cpp @@ -6,8 +6,8 @@ #include "jetski_actions.h" #include "jukebox_actions.h" #include "legoanimationmanager.h" +#include "legoanimpresenter.h" #include "legocontrolmanager.h" -#include "legohideanimpresenter.h" #include "legomain.h" #include "legopathstruct.h" #include "legoracers.h" @@ -126,7 +126,7 @@ MxLong JetskiRace::HandleControl(LegoControlManagerNotificationParam& p_param) { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case JetraceScript::c_JetskiArms_Ctl: m_act1State->m_state = Act1State::e_none; diff --git a/LEGO1/lego/legoomni/src/race/legoracemap.cpp b/LEGO1/lego/legoomni/src/race/legoracemap.cpp index bd0a04bd..9637114d 100644 --- a/LEGO1/lego/legoomni/src/race/legoracemap.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracemap.cpp @@ -129,7 +129,7 @@ MxLong LegoRaceMap::Notify(MxParam& p_param) if (param.GetNotification() == c_notificationControl && m_Map_Ctl->GetAction()->GetObjectId() == ((LegoControlManagerNotificationParam&) p_param).m_clickedObjectId) { - if (((LegoControlManagerNotificationParam&) p_param).m_unk0x28 == 1) { + if (((LegoControlManagerNotificationParam&) p_param).m_enabledChild == 1) { m_unk0x08 = TRUE; FUN_1005d4b0(); m_stillPresenter->Enable(TRUE); diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index d8e4dff5..d6b25088 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -340,10 +340,10 @@ void LegoRaceCar::KickCamera(float p_param) transformationMatrix.SetIdentity(); // Possible bug in the original code: The first argument is not initialized - a->GetAnimTreePtr()->GetCamAnim()->FUN_1009f490(deltaTime, transformationMatrix); + a->GetAnimTreePtr()->GetCamAnim()->CalculateCameraTransform(deltaTime, transformationMatrix); if (r->GetCameraController()) { - r->GetCameraController()->FUN_100123e0(transformationMatrix, 0); + r->GetCameraController()->TransformPointOfView(transformationMatrix, 0); } m_roi->SetLocal2World(transformationMatrix); diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 1ead351a..9e31e18b 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -3,6 +3,7 @@ #include "3dmanager/lego3dmanager.h" #include "anim/legoanim.h" #include "define.h" +#include "legoanimactor.h" #include "legoanimationmanager.h" #include "legoanimmmpresenter.h" #include "legocameracontroller.h" @@ -30,6 +31,10 @@ #include DECOMP_SIZE_ASSERT(LegoAnimPresenter, 0xbc) +DECOMP_SIZE_ASSERT(LegoLoopingAnimPresenter, 0xc0) +DECOMP_SIZE_ASSERT(LegoLocomotionAnimPresenter, 0xd8) +DECOMP_SIZE_ASSERT(LegoHideAnimPresenter, 0xc4) +DECOMP_SIZE_ASSERT(LegoHideAnimStruct, 0x08) // FUNCTION: LEGO1 0x10068420 // FUNCTION: BETA10 0x1004e5f0 @@ -936,10 +941,10 @@ void LegoAnimPresenter::FUN_1006b9a0(LegoAnim* p_anim, MxLong p_time, Matrix4* p if (p_anim->GetCamAnim() != NULL) { MxMatrix transform(mat); - p_anim->GetCamAnim()->FUN_1009f490(p_time, transform); + p_anim->GetCamAnim()->CalculateCameraTransform(p_time, transform); if (m_currentWorld != NULL && m_currentWorld->GetCameraController() != NULL) { - m_currentWorld->GetCameraController()->FUN_100123e0(transform, 0); + m_currentWorld->GetCameraController()->TransformPointOfView(transform, FALSE); } } @@ -1219,3 +1224,439 @@ MxResult LegoAnimPresenter::VTable0x98(LegoPathBoundary* p_boundary) return SUCCESS; } + +// FUNCTION: LEGO1 0x1006caa0 +// FUNCTION: BETA10 0x1005223d +void LegoLoopingAnimPresenter::StreamingTickle() +{ + if (m_subscriber->PeekData()) { + MxStreamChunk* chunk = m_subscriber->PopData(); + m_subscriber->FreeDataChunk(chunk); + } + + if (m_unk0x95) { + ProgressTickleState(e_done); + if (m_compositePresenter) { + if (m_compositePresenter->IsA("LegoAnimMMPresenter")) { + m_compositePresenter->VTable0x60(this); + } + } + } + else { + if (m_action->GetDuration() != -1) { + if (m_action->GetElapsedTime() > m_action->GetDuration() + m_action->GetStartTime()) { + m_unk0x95 = TRUE; + } + } + } +} + +// FUNCTION: LEGO1 0x1006cb40 +// FUNCTION: BETA10 0x1005239a +void LegoLoopingAnimPresenter::PutFrame() +{ + MxLong time; + + if (m_action->GetStartTime() <= m_action->GetElapsedTime()) { + time = (m_action->GetElapsedTime() - m_action->GetStartTime()) % m_anim->GetDuration(); + } + else { + time = 0; + } + + FUN_1006b9a0(m_anim, time, m_unk0x78); + + if (m_unk0x8c != NULL && m_currentWorld != NULL && m_currentWorld->GetCameraController() != NULL) { + for (MxS32 i = 0; i < m_unk0x94; i++) { + if (m_unk0x8c[i] != NULL) { + MxMatrix mat(m_unk0x8c[i]->GetLocal2World()); + + Vector3 pos(mat[0]); + Vector3 dir(mat[1]); + Vector3 up(mat[2]); + Vector3 und(mat[3]); + + float possqr = sqrt(pos.LenSquared()); + float dirsqr = sqrt(dir.LenSquared()); + float upsqr = sqrt(up.LenSquared()); + + up = und; + + up -= m_currentWorld->GetCameraController()->GetWorldLocation(); + dir /= dirsqr; + pos.EqualsCross(dir, up); + pos.Unitize(); + up.EqualsCross(pos, dir); + pos *= possqr; + dir *= dirsqr; + up *= upsqr; + + m_unk0x8c[i]->SetLocal2World(mat); + m_unk0x8c[i]->WrappedUpdateWorldData(); + } + } + } +} + +// FUNCTION: LEGO1 0x1006cdd0 +LegoLocomotionAnimPresenter::LegoLocomotionAnimPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x1006d050 +LegoLocomotionAnimPresenter::~LegoLocomotionAnimPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x1006d0b0 +void LegoLocomotionAnimPresenter::Init() +{ + m_unk0xc0 = 0; + m_unk0xc4 = NULL; + m_unk0xcc = -1; + m_unk0xd0 = -1; + m_roiMapList = NULL; + m_unk0xd4 = 0; +} + +// FUNCTION: LEGO1 0x1006d0e0 +void LegoLocomotionAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + ENTER(m_criticalSection); + + if (m_unk0xc4) { + delete[] m_unk0xc4; + } + + if (m_roiMapList) { + delete m_roiMapList; + } + + m_roiMap = NULL; + Init(); + + m_criticalSection.Leave(); + + if (!p_fromDestructor) { + LegoLoopingAnimPresenter::Destroy(); + } +} + +// FUNCTION: LEGO1 0x1006d140 +MxResult LegoLocomotionAnimPresenter::CreateAnim(MxStreamChunk* p_chunk) +{ + MxResult result = LegoAnimPresenter::CreateAnim(p_chunk); + return result == SUCCESS ? SUCCESS : result; +} + +// FUNCTION: LEGO1 0x1006d160 +// FUNCTION: BETA10 0x100528c7 +MxResult LegoLocomotionAnimPresenter::AddToManager() +{ + m_roiMapList = new LegoROIMapList(); + + if (m_roiMapList == NULL) { + return FAILURE; + } + + return LegoAnimPresenter::AddToManager(); +} + +// FUNCTION: LEGO1 0x1006d5b0 +void LegoLocomotionAnimPresenter::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x1006d5c0 +void LegoLocomotionAnimPresenter::PutFrame() +{ + // Empty +} + +// FUNCTION: LEGO1 0x1006d5d0 +void LegoLocomotionAnimPresenter::ReadyTickle() +{ + LegoLoopingAnimPresenter::ReadyTickle(); + + if (m_currentWorld != NULL && m_currentTickleState == e_starting) { + m_currentWorld->Add(this); + if (m_compositePresenter != NULL) { + SendToCompositePresenter(Lego()); + } + + m_unk0xd4++; + } +} + +// FUNCTION: LEGO1 0x1006d610 +// FUNCTION: BETA10 0x10052a34 +void LegoLocomotionAnimPresenter::StartingTickle() +{ + if (m_subscriber->PeekData()) { + MxStreamChunk* chunk = m_subscriber->PopData(); + m_subscriber->FreeDataChunk(chunk); + } + + if (m_roiMapList->GetNumElements() != 0) { + ProgressTickleState(e_streaming); + } +} + +// FUNCTION: LEGO1 0x1006d660 +void LegoLocomotionAnimPresenter::StreamingTickle() +{ + if (m_unk0xd4 == 0) { + EndAction(); + } +} + +// FUNCTION: LEGO1 0x1006d670 +void LegoLocomotionAnimPresenter::EndAction() +{ + if (m_action) { + MxVideoPresenter::EndAction(); + } +} + +// FUNCTION: LEGO1 0x1006d680 +// FUNCTION: BETA10 0x10052b3d +void LegoLocomotionAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value) +{ + // This asserts that LegoLocomotionAnimPresenter is contained in legoanimpresenter.cpp + AUTOLOCK(m_criticalSection); + + MxVariableTable* variableTable = VariableTable(); + + const char* key = ((LegoAnimNodeData*) m_anim->GetRoot()->GetData())->GetName(); + variableTable->SetVariable(key, p_actor->GetROI()->GetName()); + + FUN_100695c0(); + FUN_10069b10(); + + if (m_roiMap != NULL) { + m_roiMapList->Append(m_roiMap); + p_actor->FUN_1001c450(m_anim, p_value, m_roiMap, m_roiMapSize); + m_roiMap = NULL; + } + + variableTable->SetVariable(key, ""); + + if (m_sceneROIs != NULL) { + delete m_sceneROIs; + m_sceneROIs = NULL; + } +} + +// We do not have any hard evidence that `LegoHideAnimPresenter` is part of this file as well. +// However, since all of the other AnimPresenters are in the same file, it is reasonable to assume +// that the same holds here. + +// FUNCTION: LEGO1 0x1006d7e0 +LegoHideAnimPresenter::LegoHideAnimPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x1006d9f0 +LegoHideAnimPresenter::~LegoHideAnimPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x1006da50 +void LegoHideAnimPresenter::Init() +{ + m_boundaryMap = NULL; +} + +// FUNCTION: LEGO1 0x1006da60 +void LegoHideAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + ENTER(m_criticalSection); + + if (m_boundaryMap) { + delete[] m_boundaryMap; + } + Init(); + + m_criticalSection.Leave(); + + // This appears to be a bug, since it results in an endless loop + if (!p_fromDestructor) { + LegoHideAnimPresenter::Destroy(); + } +} + +// FUNCTION: LEGO1 0x1006dab0 +MxResult LegoHideAnimPresenter::AddToManager() +{ + return LegoAnimPresenter::AddToManager(); +} + +// FUNCTION: LEGO1 0x1006dac0 +void LegoHideAnimPresenter::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x1006dad0 +void LegoHideAnimPresenter::PutFrame() +{ +} + +// FUNCTION: LEGO1 0x1006dae0 +// FUNCTION: BETA10 0x100530f4 +void LegoHideAnimPresenter::ReadyTickle() +{ + LegoLoopingAnimPresenter::ReadyTickle(); + + if (m_currentWorld) { + if (m_currentTickleState == e_starting && m_compositePresenter != NULL) { + SendToCompositePresenter(Lego()); + } + + m_currentWorld->Add(this); + } +} + +// FUNCTION: LEGO1 0x1006db20 +// FUNCTION: BETA10 0x1005316b +void LegoHideAnimPresenter::StartingTickle() +{ + LegoLoopingAnimPresenter::StartingTickle(); + + if (m_currentTickleState == e_streaming) { + FUN_1006dc10(); + FUN_1006db40(0); + } +} + +// FUNCTION: LEGO1 0x1006db40 +// FUNCTION: BETA10 0x100531ab +void LegoHideAnimPresenter::FUN_1006db40(LegoTime p_time) +{ + FUN_1006db60(m_anim->GetRoot(), p_time); +} + +// FUNCTION: LEGO1 0x1006db60 +// FUNCTION: BETA10 0x100531de +void LegoHideAnimPresenter::FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time) +{ + LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData(); + MxBool newB = FALSE; + MxBool previousB = FALSE; + + if (m_roiMap != NULL) { + LegoROI* roi = m_roiMap[data->GetROIIndex()]; + + if (roi != NULL) { + newB = data->GetVisibility(p_time); + previousB = roi->GetVisibility(); + roi->SetVisibility(newB); + } + } + + if (m_boundaryMap != NULL) { + LegoPathBoundary* boundary = m_boundaryMap[data->GetBoundaryIndex()]; + + if (boundary != NULL) { + newB = data->GetVisibility(p_time); + previousB = boundary->GetFlag0x10(); + boundary->SetFlag0x10(newB); + } + } + + for (MxS32 i = 0; i < p_node->GetNumChildren(); i++) { + FUN_1006db60(p_node->GetChild(i), p_time); + } +} + +// FUNCTION: LEGO1 0x1006dc10 +// FUNCTION: BETA10 0x100532fd +void LegoHideAnimPresenter::FUN_1006dc10() +{ + LegoHideAnimStructMap anims; + + FUN_1006e3f0(anims, m_anim->GetRoot()); + + if (m_boundaryMap != NULL) { + delete[] m_boundaryMap; + } + + m_boundaryMap = new LegoPathBoundary*[anims.size() + 1]; + m_boundaryMap[0] = NULL; + + for (LegoHideAnimStructMap::iterator it = anims.begin(); !(it == anims.end()); it++) { + m_boundaryMap[(*it).second.m_index] = (*it).second.m_boundary; + delete[] const_cast((*it).first); + } +} + +// FUNCTION: LEGO1 0x1006e3f0 +// FUNCTION: BETA10 0x1005345e +void LegoHideAnimPresenter::FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node) +{ + LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData(); + const char* name = data->GetName(); + + if (name != NULL) { + LegoPathBoundary* boundary = m_currentWorld->FindPathBoundary(name); + + if (boundary != NULL) { + FUN_1006e470(p_map, data, name, boundary); + } + else { + data->SetBoundaryIndex(0); + } + } + + MxS32 count = p_node->GetNumChildren(); + for (MxS32 i = 0; i < count; i++) { + FUN_1006e3f0(p_map, p_node->GetChild(i)); + } +} + +// FUNCTION: LEGO1 0x1006e470 +// FUNCTION: BETA10 0x10053520 +void LegoHideAnimPresenter::FUN_1006e470( + LegoHideAnimStructMap& p_map, + LegoAnimNodeData* p_data, + const char* p_name, + LegoPathBoundary* p_boundary +) +{ + LegoHideAnimStructMap::iterator it; + + it = p_map.find(p_name); + if (it == p_map.end()) { + LegoHideAnimStruct animStruct; + animStruct.m_index = p_map.size() + 1; + animStruct.m_boundary = p_boundary; + + p_data->SetBoundaryIndex(animStruct.m_index); + + char* name = new char[strlen(p_name) + 1]; + strcpy(name, p_name); + + p_map[name] = animStruct; + } + else { + p_data->SetBoundaryIndex((*it).second.m_index); + } +} + +// FUNCTION: LEGO1 0x1006e9e0 +// FUNCTION: BETA10 0x100535ef +void LegoHideAnimPresenter::EndAction() +{ + if (m_action) { + MxVideoPresenter::EndAction(); + + if (m_currentWorld) { + m_currentWorld->Remove(this); + } + } +} diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp deleted file mode 100644 index 60f8dce5..00000000 --- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "legohideanimpresenter.h" - -#include "anim/legoanim.h" -#include "legomain.h" -#include "legoworld.h" -#include "misc.h" - -DECOMP_SIZE_ASSERT(LegoHideAnimPresenter, 0xc4) -DECOMP_SIZE_ASSERT(LegoHideAnimStruct, 0x08) - -// FUNCTION: LEGO1 0x1006d7e0 -LegoHideAnimPresenter::LegoHideAnimPresenter() -{ - Init(); -} - -// FUNCTION: LEGO1 0x1006d9f0 -LegoHideAnimPresenter::~LegoHideAnimPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1006da50 -void LegoHideAnimPresenter::Init() -{ - m_boundaryMap = NULL; -} - -// FUNCTION: LEGO1 0x1006da60 -void LegoHideAnimPresenter::Destroy(MxBool p_fromDestructor) -{ - m_criticalSection.Enter(); - - if (m_boundaryMap) { - delete[] m_boundaryMap; - } - Init(); - - m_criticalSection.Leave(); - - // This appears to be a bug, since it results in an endless loop - if (!p_fromDestructor) { - LegoHideAnimPresenter::Destroy(); - } -} - -// FUNCTION: LEGO1 0x1006dab0 -MxResult LegoHideAnimPresenter::AddToManager() -{ - return LegoAnimPresenter::AddToManager(); -} - -// FUNCTION: LEGO1 0x1006dac0 -void LegoHideAnimPresenter::Destroy() -{ - Destroy(FALSE); -} - -// FUNCTION: LEGO1 0x1006dad0 -void LegoHideAnimPresenter::PutFrame() -{ -} - -// FUNCTION: LEGO1 0x1006dae0 -// FUNCTION: BETA10 0x100530f4 -void LegoHideAnimPresenter::ReadyTickle() -{ - LegoLoopingAnimPresenter::ReadyTickle(); - - if (m_currentWorld) { - if (m_currentTickleState == e_starting && m_compositePresenter != NULL) { - SendToCompositePresenter(Lego()); - } - - m_currentWorld->Add(this); - } -} - -// FUNCTION: LEGO1 0x1006db20 -// FUNCTION: BETA10 0x1005316b -void LegoHideAnimPresenter::StartingTickle() -{ - LegoLoopingAnimPresenter::StartingTickle(); - - if (m_currentTickleState == e_streaming) { - FUN_1006dc10(); - FUN_1006db40(0); - } -} - -// FUNCTION: LEGO1 0x1006db40 -// FUNCTION: BETA10 0x100531ab -void LegoHideAnimPresenter::FUN_1006db40(LegoTime p_time) -{ - FUN_1006db60(m_anim->GetRoot(), p_time); -} - -// FUNCTION: LEGO1 0x1006db60 -// FUNCTION: BETA10 0x100531de -void LegoHideAnimPresenter::FUN_1006db60(LegoTreeNode* p_node, LegoTime p_time) -{ - LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData(); - MxBool newB = FALSE; - MxBool previousB = FALSE; - - if (m_roiMap != NULL) { - LegoROI* roi = m_roiMap[data->GetROIIndex()]; - - if (roi != NULL) { - newB = data->GetVisibility(p_time); - previousB = roi->GetVisibility(); - roi->SetVisibility(newB); - } - } - - if (m_boundaryMap != NULL) { - LegoPathBoundary* boundary = m_boundaryMap[data->GetBoundaryIndex()]; - - if (boundary != NULL) { - newB = data->GetVisibility(p_time); - previousB = boundary->GetFlag0x10(); - boundary->SetFlag0x10(newB); - } - } - - for (MxS32 i = 0; i < p_node->GetNumChildren(); i++) { - FUN_1006db60(p_node->GetChild(i), p_time); - } -} - -// FUNCTION: LEGO1 0x1006dc10 -// FUNCTION: BETA10 0x100532fd -void LegoHideAnimPresenter::FUN_1006dc10() -{ - LegoHideAnimStructMap anims; - - FUN_1006e3f0(anims, m_anim->GetRoot()); - - if (m_boundaryMap != NULL) { - delete[] m_boundaryMap; - } - - m_boundaryMap = new LegoPathBoundary*[anims.size() + 1]; - m_boundaryMap[0] = NULL; - - for (LegoHideAnimStructMap::iterator it = anims.begin(); !(it == anims.end()); it++) { - m_boundaryMap[(*it).second.m_index] = (*it).second.m_boundary; - delete[] const_cast((*it).first); - } -} - -// FUNCTION: LEGO1 0x1006e3f0 -// FUNCTION: BETA10 0x1005345e -void LegoHideAnimPresenter::FUN_1006e3f0(LegoHideAnimStructMap& p_map, LegoTreeNode* p_node) -{ - LegoAnimNodeData* data = (LegoAnimNodeData*) p_node->GetData(); - const char* name = data->GetName(); - - if (name != NULL) { - LegoPathBoundary* boundary = m_currentWorld->FindPathBoundary(name); - - if (boundary != NULL) { - FUN_1006e470(p_map, data, name, boundary); - } - else { - data->SetBoundaryIndex(0); - } - } - - MxS32 count = p_node->GetNumChildren(); - for (MxS32 i = 0; i < count; i++) { - FUN_1006e3f0(p_map, p_node->GetChild(i)); - } -} - -// FUNCTION: LEGO1 0x1006e470 -// FUNCTION: BETA10 0x10053520 -void LegoHideAnimPresenter::FUN_1006e470( - LegoHideAnimStructMap& p_map, - LegoAnimNodeData* p_data, - const char* p_name, - LegoPathBoundary* p_boundary -) -{ - LegoHideAnimStructMap::iterator it; - - it = p_map.find(p_name); - if (it == p_map.end()) { - LegoHideAnimStruct animStruct; - animStruct.m_index = p_map.size() + 1; - animStruct.m_boundary = p_boundary; - - p_data->SetBoundaryIndex(animStruct.m_index); - - char* name = new char[strlen(p_name) + 1]; - strcpy(name, p_name); - - p_map[name] = animStruct; - } - else { - p_data->SetBoundaryIndex((*it).second.m_index); - } -} - -// FUNCTION: LEGO1 0x1006e9e0 -// FUNCTION: BETA10 0x100535ef -void LegoHideAnimPresenter::EndAction() -{ - if (m_action) { - MxVideoPresenter::EndAction(); - - if (m_currentWorld) { - m_currentWorld->Remove(this); - } - } -} diff --git a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp deleted file mode 100644 index 90b98e91..00000000 --- a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "legolocomotionanimpresenter.h" - -#include "anim/legoanim.h" -#include "legoanimactor.h" -#include "legomain.h" -#include "legoworld.h" -#include "misc.h" -#include "mxautolock.h" -#include "mxdssubscriber.h" -#include "mxmisc.h" -#include "mxvariabletable.h" - -DECOMP_SIZE_ASSERT(LegoLocomotionAnimPresenter, 0xd8) - -// FUNCTION: LEGO1 0x1006cdd0 -LegoLocomotionAnimPresenter::LegoLocomotionAnimPresenter() -{ - Init(); -} - -// FUNCTION: LEGO1 0x1006d050 -LegoLocomotionAnimPresenter::~LegoLocomotionAnimPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1006d0b0 -void LegoLocomotionAnimPresenter::Init() -{ - m_unk0xc0 = 0; - m_unk0xc4 = NULL; - m_unk0xcc = -1; - m_unk0xd0 = -1; - m_roiMapList = NULL; - m_unk0xd4 = 0; -} - -// FUNCTION: LEGO1 0x1006d0e0 -void LegoLocomotionAnimPresenter::Destroy(MxBool p_fromDestructor) -{ - m_criticalSection.Enter(); - - if (m_unk0xc4) { - delete[] m_unk0xc4; - } - - if (m_roiMapList) { - delete m_roiMapList; - } - - m_roiMap = NULL; - Init(); - - m_criticalSection.Leave(); - - if (!p_fromDestructor) { - LegoLoopingAnimPresenter::Destroy(); - } -} - -// FUNCTION: LEGO1 0x1006d140 -MxResult LegoLocomotionAnimPresenter::CreateAnim(MxStreamChunk* p_chunk) -{ - MxResult result = LegoAnimPresenter::CreateAnim(p_chunk); - return result == SUCCESS ? SUCCESS : result; -} - -// FUNCTION: LEGO1 0x1006d160 -// FUNCTION: BETA10 0x100528c7 -MxResult LegoLocomotionAnimPresenter::AddToManager() -{ - m_roiMapList = new LegoROIMapList(); - - if (m_roiMapList == NULL) { - return FAILURE; - } - - return LegoAnimPresenter::AddToManager(); -} - -// FUNCTION: LEGO1 0x1006d5b0 -void LegoLocomotionAnimPresenter::Destroy() -{ - Destroy(FALSE); -} - -// FUNCTION: LEGO1 0x1006d5c0 -void LegoLocomotionAnimPresenter::PutFrame() -{ - // Empty -} - -// FUNCTION: LEGO1 0x1006d5d0 -void LegoLocomotionAnimPresenter::ReadyTickle() -{ - LegoLoopingAnimPresenter::ReadyTickle(); - - if (m_currentWorld != NULL && m_currentTickleState == e_starting) { - m_currentWorld->Add(this); - if (m_compositePresenter != NULL) { - SendToCompositePresenter(Lego()); - } - - m_unk0xd4++; - } -} - -// FUNCTION: LEGO1 0x1006d610 -// FUNCTION: BETA10 0x10052a34 -void LegoLocomotionAnimPresenter::StartingTickle() -{ - if (m_subscriber->PeekData()) { - MxStreamChunk* chunk = m_subscriber->PopData(); - m_subscriber->FreeDataChunk(chunk); - } - - if (m_roiMapList->GetNumElements() != 0) { - ProgressTickleState(e_streaming); - } -} - -// FUNCTION: LEGO1 0x1006d660 -void LegoLocomotionAnimPresenter::StreamingTickle() -{ - if (m_unk0xd4 == 0) { - EndAction(); - } -} - -// FUNCTION: LEGO1 0x1006d670 -void LegoLocomotionAnimPresenter::EndAction() -{ - if (m_action) { - MxVideoPresenter::EndAction(); - } -} - -// FUNCTION: LEGO1 0x1006d680 -// FUNCTION: BETA10 0x10052b3d -void LegoLocomotionAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p_value) -{ - AUTOLOCK(m_criticalSection); - - MxVariableTable* variableTable = VariableTable(); - - const char* key = ((LegoAnimNodeData*) m_anim->GetRoot()->GetData())->GetName(); - variableTable->SetVariable(key, p_actor->GetROI()->GetName()); - - FUN_100695c0(); - FUN_10069b10(); - - if (m_roiMap != NULL) { - m_roiMapList->Append(m_roiMap); - p_actor->FUN_1001c450(m_anim, p_value, m_roiMap, m_roiMapSize); - m_roiMap = NULL; - } - - variableTable->SetVariable(key, ""); - - if (m_sceneROIs != NULL) { - delete m_sceneROIs; - m_sceneROIs = NULL; - } -} diff --git a/LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp deleted file mode 100644 index cf75ce47..00000000 --- a/LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include "legoloopinganimpresenter.h" - -#include "anim/legoanim.h" -#include "legocameracontroller.h" -#include "legoworld.h" -#include "mxcompositepresenter.h" -#include "mxdsaction.h" -#include "mxdssubscriber.h" - -DECOMP_SIZE_ASSERT(LegoLoopingAnimPresenter, 0xc0) - -// FUNCTION: LEGO1 0x1006caa0 -// FUNCTION: BETA10 0x1005223d -void LegoLoopingAnimPresenter::StreamingTickle() -{ - if (m_subscriber->PeekData()) { - MxStreamChunk* chunk = m_subscriber->PopData(); - m_subscriber->FreeDataChunk(chunk); - } - - if (m_unk0x95) { - ProgressTickleState(e_done); - if (m_compositePresenter) { - if (m_compositePresenter->IsA("LegoAnimMMPresenter")) { - m_compositePresenter->VTable0x60(this); - } - } - } - else { - if (m_action->GetDuration() != -1) { - if (m_action->GetElapsedTime() > m_action->GetDuration() + m_action->GetStartTime()) { - m_unk0x95 = TRUE; - } - } - } -} - -// FUNCTION: LEGO1 0x1006cb40 -// FUNCTION: BETA10 0x1005239a -void LegoLoopingAnimPresenter::PutFrame() -{ - MxLong time; - - if (m_action->GetStartTime() <= m_action->GetElapsedTime()) { - time = (m_action->GetElapsedTime() - m_action->GetStartTime()) % m_anim->GetDuration(); - } - else { - time = 0; - } - - FUN_1006b9a0(m_anim, time, m_unk0x78); - - if (m_unk0x8c != NULL && m_currentWorld != NULL && m_currentWorld->GetCameraController() != NULL) { - for (MxS32 i = 0; i < m_unk0x94; i++) { - if (m_unk0x8c[i] != NULL) { - MxMatrix mat(m_unk0x8c[i]->GetLocal2World()); - - Vector3 pos(mat[0]); - Vector3 dir(mat[1]); - Vector3 up(mat[2]); - Vector3 und(mat[3]); - - float possqr = sqrt(pos.LenSquared()); - float dirsqr = sqrt(dir.LenSquared()); - float upsqr = sqrt(up.LenSquared()); - - up = und; - - up -= m_currentWorld->GetCameraController()->GetWorldLocation(); - dir /= dirsqr; - pos.EqualsCross(dir, up); - pos.Unitize(); - up.EqualsCross(pos, dir); - pos *= possqr; - dir *= dirsqr; - up *= upsqr; - - m_unk0x8c[i]->SetLocal2World(mat); - m_unk0x8c[i]->WrappedUpdateWorldData(); - } - } - } -} diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index 510c5928..25ec48a4 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -35,7 +35,7 @@ void LegoModelPresenter::configureLegoModelPresenter(MxS32 p_modelPresenterConfi // FUNCTION: LEGO1 0x1007f670 void LegoModelPresenter::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); m_roi = NULL; m_addedToView = FALSE; m_criticalSection.Leave(); diff --git a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp index ea5c7326..e76b90d9 100644 --- a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp @@ -31,7 +31,7 @@ void LegoPalettePresenter::Init() // FUNCTION: LEGO1 0x1007a0e0 void LegoPalettePresenter::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (m_palette) { delete m_palette; } diff --git a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp index 8686cb17..10b72caa 100644 --- a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp @@ -41,7 +41,7 @@ MxResult LegoPartPresenter::AddToManager() // FUNCTION: LEGO1 0x1007c9d0 void LegoPartPresenter::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); VideoManager()->UnregisterPresenter(*this); if (m_parts) { diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 383c6d35..53c79a5f 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -545,14 +545,14 @@ void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) m_palette = m_videoParam.GetPalette()->Clone(); OverrideSkyColor(FALSE); - m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); + m_displaySurface->GetVideoParam().Flags().SetDoubleScaling(p_scale); m_render3d = FALSE; m_fullScreenMovie = TRUE; } else { m_displaySurface->ClearScreen(); - m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); + m_displaySurface->GetVideoParam().Flags().SetDoubleScaling(FALSE); // restore previous pallete RealizePalette(m_palette); @@ -577,10 +577,10 @@ void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) } if (p_enable) { - m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); + m_displaySurface->GetVideoParam().Flags().SetDoubleScaling(p_scale); } else { - m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); + m_displaySurface->GetVideoParam().Flags().SetDoubleScaling(FALSE); } } diff --git a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp index 2a9c0772..6e1d484d 100644 --- a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp @@ -87,7 +87,7 @@ MxLong ElevatorBottom::HandleControl(LegoControlManagerNotificationParam& p_para { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case ElevbottScript::c_LeftArrow_Ctl: m_destLocation = LegoGameState::e_infodoor; diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp index 61a13858..d83c172d 100644 --- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp @@ -389,7 +389,7 @@ MxLong GasStation::HandleButtonDown(LegoControlManagerNotificationParam& p_param // FUNCTION: BETA10 0x10029445 MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param) { - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { MxDSAction action; switch (p_param.m_clickedObjectId) { diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp index 229e11f8..cd75e1a1 100644 --- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp +++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp @@ -555,7 +555,7 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param) // FUNCTION: LEGO1 0x10075f90 MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param) { - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case HospitalScript::c_Info_Ctl: BackgroundAudioManager()->RaiseVolume(); diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index bf5a29b4..141b8f85 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -948,7 +948,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) // FUNCTION: BETA10 0x1002ffd4 MxU8 Infocenter::HandleControl(LegoControlManagerNotificationParam& p_param) { - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { m_infoManDialogueTimer = 0; InfomainScript::Script actionToPlay = InfomainScript::c_noneInfomain; diff --git a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp index 8f92a323..8dc21750 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp @@ -96,7 +96,7 @@ MxLong InfocenterDoor::HandleControl(LegoControlManagerNotificationParam& p_para { MxLong result = 0; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { DeleteObjects(&m_atomId, InfodoorScript::c_iic037in_PlayWav, 510); switch (p_param.m_clickedObjectId) { diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 5e4f983f..718a8f2f 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -284,7 +284,7 @@ void Isle::ReadyWorld() // FUNCTION: LEGO1 0x10031030 MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param) { - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { MxDSAction action; switch (p_param.m_clickedObjectId) { @@ -577,7 +577,7 @@ void Isle::Enable(MxBool p_enable) if (UserActor() != NULL && UserActor()->IsA("Jetski")) { IslePathActor* actor = (IslePathActor*) UserActor(); actor->SpawnPlayer( - LegoGameState::e_unk45, + LegoGameState::e_jetskiSpawn, FALSE, IslePathActor::c_spawnBit1 | IslePathActor::c_playMusic | IslePathActor::c_spawnBit3 ); @@ -1633,7 +1633,7 @@ void Act1State::PlaceActors() if (m_helicopter != NULL) { if (!m_helicopterPlane.IsPresent()) { - m_helicopter->SpawnPlayer(LegoGameState::e_unk40, FALSE, 0); + m_helicopter->SpawnPlayer(LegoGameState::e_helicopterSpawn, FALSE, 0); } else { isle->PlaceActor(m_helicopter, m_helicopterPlane.GetName(), 0, 0.5f, 1, 0.5f); @@ -1673,7 +1673,7 @@ void Act1State::PlaceActors() if (m_jetski != NULL) { if (!m_jetskiPlane.IsPresent()) { - m_jetski->SpawnPlayer(LegoGameState::e_unk45, FALSE, 0); + m_jetski->SpawnPlayer(LegoGameState::e_jetskiSpawn, FALSE, 0); } else { isle->PlaceActor(m_jetski, m_jetskiPlane.GetName(), 0, 0.5f, 1, 0.5f); @@ -1703,7 +1703,7 @@ void Act1State::PlaceActors() if (m_dunebuggy != NULL) { if (!m_dunebuggyPlane.IsPresent()) { - m_dunebuggy->SpawnPlayer(LegoGameState::e_unk43, FALSE, 0); + m_dunebuggy->SpawnPlayer(LegoGameState::e_dunebuggySpawn, FALSE, 0); } else { isle->PlaceActor(m_dunebuggy, m_dunebuggyPlane.GetName(), 0, 0.5f, 1, 0.5f); @@ -1731,7 +1731,7 @@ void Act1State::PlaceActors() if (m_racecar != NULL) { if (!m_racecarPlane.IsPresent()) { - m_racecar->SpawnPlayer(LegoGameState::e_unk44, FALSE, 0); + m_racecar->SpawnPlayer(LegoGameState::e_racecarSpawn, FALSE, 0); } else { isle->PlaceActor(m_racecar, m_racecarPlane.GetName(), 0, 0.5f, 1, 0.5f); diff --git a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp index db244e00..aa8858cf 100644 --- a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp +++ b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp @@ -123,7 +123,7 @@ MxBool JukeBox::HandleControl(LegoControlManagerNotificationParam& p_param) { MxStillPresenter* presenter; - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case JukeboxwScript::c_Dback_Ctl: switch (m_state->m_music) { diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp index b3f92433..c04bbdbc 100644 --- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp @@ -7,10 +7,10 @@ #include "islepathactor.h" #include "jukebox_actions.h" #include "legoanimationmanager.h" +#include "legoanimpresenter.h" #include "legocachesoundmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" -#include "legolocomotionanimpresenter.h" #include "legomain.h" #include "legopathstruct.h" #include "legosoundmanager.h" @@ -1117,7 +1117,7 @@ MxResult LegoAct2::FUN_10052560( action.SetDirection(*p_direction); } - StartActionIfUnknown0x13c(action); + StartActionIfInitialized(action); } else { MxMatrix matrix; diff --git a/LEGO1/lego/legoomni/src/worlds/police.cpp b/LEGO1/lego/legoomni/src/worlds/police.cpp index 16297b76..e609b319 100644 --- a/LEGO1/lego/legoomni/src/worlds/police.cpp +++ b/LEGO1/lego/legoomni/src/worlds/police.cpp @@ -101,7 +101,7 @@ void Police::ReadyWorld() // FUNCTION: LEGO1 0x1005e550 MxLong Police::HandleControl(LegoControlManagerNotificationParam& p_param) { - if (p_param.m_unk0x28 == 1) { + if (p_param.m_enabledChild == 1) { switch (p_param.m_clickedObjectId) { case PoliceScript::c_LeftArrow_Ctl: case PoliceScript::c_RightArrow_Ctl: diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 709b338d..ddd3b7cf 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -241,7 +241,7 @@ MxLong RegistrationBook::HandleKeyPress(SDL_Keycode p_key) // FUNCTION: LEGO1 0x100774a0 MxLong RegistrationBook::HandleControl(LegoControlManagerNotificationParam& p_param) { - MxS16 buttonId = p_param.m_unk0x28; + MxS16 buttonId = p_param.m_enabledChild; const InternationalCharacter* intChar = NULL; for (int i = 0; i < sizeOfArray(m_intAlphabet); i++) { diff --git a/LEGO1/lego/legoomni/src/worlds/score.cpp b/LEGO1/lego/legoomni/src/worlds/score.cpp index 14b91a18..067f43e4 100644 --- a/LEGO1/lego/legoomni/src/worlds/score.cpp +++ b/LEGO1/lego/legoomni/src/worlds/score.cpp @@ -165,7 +165,7 @@ void Score::ReadyWorld() // FUNCTION: LEGO1 0x100016d0 MxLong Score::FUN_100016d0(LegoControlManagerNotificationParam& p_param) { - MxS16 unk0x28 = p_param.m_unk0x28; + MxS16 unk0x28 = p_param.m_enabledChild; if (unk0x28 == 1 || p_param.m_clickedObjectId == InfoscorScript::c_LegoBox_Ctl) { switch (p_param.m_clickedObjectId) { diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp index 9026c245..e0fb90b6 100644 --- a/LEGO1/lego/sources/anim/legoanim.cpp +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -10,20 +10,20 @@ DECOMP_SIZE_ASSERT(LegoTranslationKey, 0x14) DECOMP_SIZE_ASSERT(LegoRotationKey, 0x18) DECOMP_SIZE_ASSERT(LegoScaleKey, 0x14) DECOMP_SIZE_ASSERT(LegoMorphKey, 0x0c) -DECOMP_SIZE_ASSERT(LegoUnknownKey, 0x0c) +DECOMP_SIZE_ASSERT(LegoRotationZKey, 0x0c) DECOMP_SIZE_ASSERT(LegoAnimNodeData, 0x34) DECOMP_SIZE_ASSERT(LegoAnimActorEntry, 0x08) DECOMP_SIZE_ASSERT(LegoAnimScene, 0x24) DECOMP_SIZE_ASSERT(LegoAnim, 0x18) // FUNCTION: LEGO1 0x1009f000 -LegoUnknownKey::LegoUnknownKey() +LegoRotationZKey::LegoRotationZKey() { m_z = 0.0f; } // FUNCTION: LEGO1 0x1009f020 -LegoResult LegoUnknownKey::Read(LegoStorage* p_storage) +LegoResult LegoRotationZKey::Read(LegoStorage* p_storage) { LegoResult result; @@ -40,7 +40,7 @@ LegoResult LegoUnknownKey::Read(LegoStorage* p_storage) // FUNCTION: LEGO1 0x1009f060 // FUNCTION: BETA10 0x1018133f -LegoResult LegoUnknownKey::Write(LegoStorage* p_storage) +LegoResult LegoRotationZKey::Write(LegoStorage* p_storage) { LegoResult result; @@ -58,33 +58,33 @@ LegoResult LegoUnknownKey::Write(LegoStorage* p_storage) // FUNCTION: LEGO1 0x1009f0a0 LegoAnimScene::LegoAnimScene() { - m_unk0x00 = 0; - m_unk0x04 = NULL; - m_unk0x08 = 0; - m_unk0x0c = NULL; - m_unk0x10 = 0; - m_unk0x14 = NULL; - m_unk0x18 = 0; - m_unk0x1c = 0; - m_unk0x20 = 0; + m_translationKeysCount = 0; + m_translationKeys = NULL; + m_targetKeysCount = 0; + m_targetKeys = NULL; + m_rotationKeysCount = 0; + m_rotationKeys = NULL; + m_targetIndex = 0; + m_translationIndex = 0; + m_rotationIndex = 0; } // FUNCTION: LEGO1 0x1009f0d0 LegoAnimScene::~LegoAnimScene() { - if (m_unk0x04 != NULL) { - delete[] m_unk0x04; - m_unk0x04 = NULL; + if (m_translationKeys != NULL) { + delete[] m_translationKeys; + m_translationKeys = NULL; } - if (m_unk0x0c != NULL) { - delete[] m_unk0x0c; - m_unk0x0c = NULL; + if (m_targetKeys != NULL) { + delete[] m_targetKeys; + m_targetKeys = NULL; } - if (m_unk0x14 != NULL) { - delete[] m_unk0x14; - m_unk0x14 = NULL; + if (m_rotationKeys != NULL) { + delete[] m_rotationKeys; + m_rotationKeys = NULL; } } @@ -95,34 +95,34 @@ LegoResult LegoAnimScene::Write(LegoStorage* p_storage) LegoResult result; LegoS32 i; - if ((result = p_storage->Write(&m_unk0x00, sizeof(LegoU16))) != SUCCESS) { + if ((result = p_storage->Write(&m_translationKeysCount, sizeof(LegoU16))) != SUCCESS) { return result; } - if (m_unk0x00 != 0) { - for (i = 0; i < m_unk0x00; i++) { - if ((result = m_unk0x04[i].Write(p_storage)) != SUCCESS) { + if (m_translationKeysCount != 0) { + for (i = 0; i < m_translationKeysCount; i++) { + if ((result = m_translationKeys[i].Write(p_storage)) != SUCCESS) { return result; } } } - if ((result = p_storage->Write(&m_unk0x08, sizeof(LegoU16))) != SUCCESS) { + if ((result = p_storage->Write(&m_targetKeysCount, sizeof(LegoU16))) != SUCCESS) { return result; } - if (m_unk0x08 != 0) { - for (i = 0; i < m_unk0x08; i++) { - if ((result = m_unk0x0c[i].Write(p_storage)) != SUCCESS) { + if (m_targetKeysCount != 0) { + for (i = 0; i < m_targetKeysCount; i++) { + if ((result = m_targetKeys[i].Write(p_storage)) != SUCCESS) { return result; } } } - if ((result = p_storage->Write(&m_unk0x10, sizeof(LegoU16))) != SUCCESS) { + if ((result = p_storage->Write(&m_rotationKeysCount, sizeof(LegoU16))) != SUCCESS) { return result; } - if (m_unk0x10 != 0) { - for (i = 0; i < m_unk0x10; i++) { - if ((result = m_unk0x14[i].Write(p_storage)) != SUCCESS) { + if (m_rotationKeysCount != 0) { + for (i = 0; i < m_rotationKeysCount; i++) { + if ((result = m_rotationKeys[i].Write(p_storage)) != SUCCESS) { return result; } } @@ -137,37 +137,37 @@ LegoResult LegoAnimScene::Read(LegoStorage* p_storage) LegoResult result; LegoS32 i; - if ((result = p_storage->Read(&m_unk0x00, sizeof(LegoU16))) != SUCCESS) { + if ((result = p_storage->Read(&m_translationKeysCount, sizeof(LegoU16))) != SUCCESS) { return result; } - if (m_unk0x00 != 0) { - m_unk0x04 = new LegoTranslationKey[m_unk0x00]; - for (i = 0; i < m_unk0x00; i++) { - if ((result = m_unk0x04[i].Read(p_storage)) != SUCCESS) { + if (m_translationKeysCount != 0) { + m_translationKeys = new LegoTranslationKey[m_translationKeysCount]; + for (i = 0; i < m_translationKeysCount; i++) { + if ((result = m_translationKeys[i].Read(p_storage)) != SUCCESS) { goto done; } } } - if ((result = p_storage->Read(&m_unk0x08, sizeof(LegoU16))) != SUCCESS) { + if ((result = p_storage->Read(&m_targetKeysCount, sizeof(LegoU16))) != SUCCESS) { return result; } - if (m_unk0x08 != 0) { - m_unk0x0c = new LegoTranslationKey[m_unk0x08]; - for (i = 0; i < m_unk0x08; i++) { - if ((result = m_unk0x0c[i].Read(p_storage)) != SUCCESS) { + if (m_targetKeysCount != 0) { + m_targetKeys = new LegoTranslationKey[m_targetKeysCount]; + for (i = 0; i < m_targetKeysCount; i++) { + if ((result = m_targetKeys[i].Read(p_storage)) != SUCCESS) { goto done; } } } - if ((result = p_storage->Read(&m_unk0x10, sizeof(LegoU16))) != SUCCESS) { + if ((result = p_storage->Read(&m_rotationKeysCount, sizeof(LegoU16))) != SUCCESS) { return result; } - if (m_unk0x10 != 0) { - m_unk0x14 = new LegoUnknownKey[m_unk0x10]; - for (i = 0; i < m_unk0x10; i++) { - if ((result = m_unk0x14[i].Read(p_storage)) != SUCCESS) { + if (m_rotationKeysCount != 0) { + m_rotationKeys = new LegoRotationZKey[m_rotationKeysCount]; + for (i = 0; i < m_rotationKeysCount; i++) { + if ((result = m_rotationKeys[i].Read(p_storage)) != SUCCESS) { goto done; } } @@ -176,22 +176,22 @@ LegoResult LegoAnimScene::Read(LegoStorage* p_storage) return SUCCESS; done: - if (m_unk0x04 != NULL) { - delete[] m_unk0x04; - m_unk0x00 = 0; - m_unk0x04 = NULL; + if (m_translationKeys != NULL) { + delete[] m_translationKeys; + m_translationKeysCount = 0; + m_translationKeys = NULL; } - if (m_unk0x0c != NULL) { - delete[] m_unk0x0c; - m_unk0x08 = 0; - m_unk0x0c = NULL; + if (m_targetKeys != NULL) { + delete[] m_targetKeys; + m_targetKeysCount = 0; + m_targetKeys = NULL; } - if (m_unk0x14 != NULL) { - delete[] m_unk0x14; - m_unk0x10 = 0; - m_unk0x14 = NULL; + if (m_rotationKeys != NULL) { + delete[] m_rotationKeys; + m_rotationKeysCount = 0; + m_rotationKeys = NULL; } return result; @@ -199,82 +199,95 @@ LegoResult LegoAnimScene::Read(LegoStorage* p_storage) // FUNCTION: LEGO1 0x1009f490 // FUNCTION: BETA10 0x10181a83 -LegoResult LegoAnimScene::FUN_1009f490(LegoFloat p_time, Matrix4& p_matrix) +LegoResult LegoAnimScene::CalculateCameraTransform(LegoFloat p_time, Matrix4& p_matrix) { - MxMatrix localb0; - MxMatrix local4c; + MxMatrix tempMatrix; + MxMatrix original; - Vector3 local5c(localb0[0]); - Vector3 local68(localb0[1]); - Vector3 local54(localb0[2]); - Vector3 localb8(localb0[3]); + Vector3 column0(tempMatrix[0]); + Vector3 column1(tempMatrix[1]); + Vector3 column2(tempMatrix[2]); + Vector3 column3(tempMatrix[3]); - Mx3DPointFloat localcc; + Mx3DPointFloat tempTranslation; - localb0.SetIdentity(); + tempMatrix.SetIdentity(); - LegoU32 local60; - if (m_unk0x08 != 0) { - local60 = GetUnknown0x18(); - LegoAnimNodeData::GetTranslation(m_unk0x08, m_unk0x0c, p_time, localb0, local60); - SetUnknown0x18(local60); - localcc = localb8; - localb8.Clear(); + LegoU32 translationIndex; + if (m_targetKeysCount != 0) { + translationIndex = GetTargetIndex(); + LegoAnimNodeData::GetTranslation(m_targetKeysCount, m_targetKeys, p_time, tempMatrix, translationIndex); + SetTargetIndex(translationIndex); + tempTranslation = column3; + column3.Clear(); } - if (m_unk0x00 != 0) { - local60 = GetUnknown0x1c(); - LegoAnimNodeData::GetTranslation(m_unk0x00, m_unk0x04, p_time, localb0, local60); - SetUnknown0x1c(local60); + if (m_translationKeysCount != 0) { + translationIndex = GetTranslationIndex(); + LegoAnimNodeData::GetTranslation( + m_translationKeysCount, + m_translationKeys, + p_time, + tempMatrix, + translationIndex + ); + SetTranslationIndex(translationIndex); } - local54 = localcc; - local54 -= localb8; + column2 = tempTranslation; + column2 -= column3; - if (local54.Unitize() == 0) { - local5c.EqualsCross(local68, local54); + if (column2.Unitize() == 0) { + column0.EqualsCross(column1, column2); - if (local5c.Unitize() == 0) { - local68.EqualsCross(local54, local5c); + if (column0.Unitize() == 0) { + column1.EqualsCross(column2, column0); - localcc = p_matrix[3]; - localcc += localb0[3]; + tempTranslation = p_matrix[3]; + tempTranslation += tempMatrix[3]; - p_matrix[3][0] = p_matrix[3][1] = p_matrix[3][2] = localb0[3][0] = localb0[3][1] = localb0[3][2] = 0; + p_matrix[3][0] = p_matrix[3][1] = p_matrix[3][2] = tempMatrix[3][0] = tempMatrix[3][1] = tempMatrix[3][2] = + 0; - if (m_unk0x10 != 0) { - LegoU32 locald0 = -1; - LegoU32 locald8; - locald0 = GetUnknown0x20(); + if (m_rotationKeysCount != 0) { + LegoU32 old_index = -1; + LegoU32 i; + old_index = GetRotationIndex(); - LegoU32 localdc = - LegoAnimNodeData::FindKeys(p_time, m_unk0x10, m_unk0x14, sizeof(*m_unk0x14), locald8, locald0); + LegoU32 count = LegoAnimNodeData::FindKeys( + p_time, + m_rotationKeysCount, + m_rotationKeys, + sizeof(*m_rotationKeys), + i, + old_index + ); - SetUnknown0x20(locald0); + SetRotationIndex(old_index); - switch (localdc) { + switch (count) { case 1: - p_matrix.RotateZ(m_unk0x14[locald8].GetZ()); + p_matrix.RotateZ(m_rotationKeys[i].GetZ()); break; case 2: // Seems to be unused LegoFloat z = LegoAnimNodeData::Interpolate( p_time, - m_unk0x14[locald8], - m_unk0x14[locald8].GetZ(), - m_unk0x14[locald8 + 1], - m_unk0x14[locald8 + 1].GetZ() + m_rotationKeys[i], + m_rotationKeys[i].GetZ(), + m_rotationKeys[i + 1], + m_rotationKeys[i + 1].GetZ() ); - p_matrix.RotateZ(m_unk0x14[locald8].GetZ()); + p_matrix.RotateZ(m_rotationKeys[i].GetZ()); break; } } - local4c = p_matrix; - p_matrix.Product(local4c.GetData(), localb0.GetData()); - p_matrix[3][0] = localcc[0]; - p_matrix[3][1] = localcc[1]; - p_matrix[3][2] = localcc[2]; + original = p_matrix; + p_matrix.Product(original.GetData(), tempMatrix.GetData()); + p_matrix[3][0] = tempTranslation[0]; + p_matrix[3][1] = tempTranslation[1]; + p_matrix[3][2] = tempTranslation[2]; } } diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h index 7a03d99c..1c297c4d 100644 --- a/LEGO1/lego/sources/anim/legoanim.h +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -137,9 +137,9 @@ class LegoMorphKey : public LegoAnimKey { }; // SIZE 0x0c -class LegoUnknownKey : public LegoAnimKey { +class LegoRotationZKey : public LegoAnimKey { public: - LegoUnknownKey(); + LegoRotationZKey(); LegoResult Read(LegoStorage* p_storage); LegoResult Write(LegoStorage* p_storage); @@ -309,26 +309,26 @@ class LegoAnimScene { ~LegoAnimScene(); LegoResult Read(LegoStorage* p_storage); LegoResult Write(LegoStorage* p_storage); - LegoResult FUN_1009f490(LegoFloat p_time, Matrix4& p_matrix); + LegoResult CalculateCameraTransform(LegoFloat p_time, Matrix4& p_matrix); - LegoU32 GetUnknown0x18() { return m_unk0x18; } - LegoU32 GetUnknown0x1c() { return m_unk0x1c; } - LegoU32 GetUnknown0x20() { return m_unk0x20; } + LegoU32 GetTargetIndex() { return m_targetIndex; } + LegoU32 GetTranslationIndex() { return m_translationIndex; } + LegoU32 GetRotationIndex() { return m_rotationIndex; } - void SetUnknown0x18(LegoU32 p_unk0x18) { m_unk0x18 = p_unk0x18; } - void SetUnknown0x1c(LegoU32 p_unk0x1c) { m_unk0x1c = p_unk0x1c; } - void SetUnknown0x20(LegoU32 p_unk0x20) { m_unk0x20 = p_unk0x20; } + void SetTargetIndex(LegoU32 p_targetIndex) { m_targetIndex = p_targetIndex; } + void SetTranslationIndex(LegoU32 p_translationIndex) { m_translationIndex = p_translationIndex; } + void SetRotationIndex(LegoU32 p_rotationIndex) { m_rotationIndex = p_rotationIndex; } private: - LegoU16 m_unk0x00; // 0x00 - LegoTranslationKey* m_unk0x04; // 0x04 - LegoU16 m_unk0x08; // 0x08 - LegoTranslationKey* m_unk0x0c; // 0x0c - LegoU16 m_unk0x10; // 0x10 - LegoUnknownKey* m_unk0x14; // 0x14 - LegoU32 m_unk0x18; // 0x18 - LegoU32 m_unk0x1c; // 0x1c - LegoU32 m_unk0x20; // 0x20 + LegoU16 m_translationKeysCount; // 0x00 + LegoTranslationKey* m_translationKeys; // 0x04 + LegoU16 m_targetKeysCount; // 0x08 + LegoTranslationKey* m_targetKeys; // 0x0c + LegoU16 m_rotationKeysCount; // 0x10 + LegoRotationZKey* m_rotationKeys; // 0x14 + LegoU32 m_targetIndex; // 0x18 + LegoU32 m_translationIndex; // 0x1c + LegoU32 m_rotationIndex; // 0x20 }; // VTABLE: LEGO1 0x100db8d8 diff --git a/LEGO1/lego1_pch.h b/LEGO1/lego1_pch.h index 624a4be3..40c5db6c 100644 --- a/LEGO1/lego1_pch.h +++ b/LEGO1/lego1_pch.h @@ -87,13 +87,10 @@ #include "lego/legoomni/include/legoextraactor.h" #include "lego/legoomni/include/legoflctexturepresenter.h" #include "lego/legoomni/include/legogamestate.h" -#include "lego/legoomni/include/legohideanimpresenter.h" #include "lego/legoomni/include/legoinputmanager.h" #include "lego/legoomni/include/legoloadcachesoundpresenter.h" #include "lego/legoomni/include/legolocations.h" -#include "lego/legoomni/include/legolocomotionanimpresenter.h" #include "lego/legoomni/include/legolodlist.h" -#include "lego/legoomni/include/legoloopinganimpresenter.h" #include "lego/legoomni/include/legomain.h" #include "lego/legoomni/include/legometerpresenter.h" #include "lego/legoomni/include/legomodelpresenter.h" @@ -239,7 +236,6 @@ #include "omni/include/mxlist.h" #include "omni/include/mxloopingflcpresenter.h" #include "omni/include/mxloopingsmkpresenter.h" -#include "omni/include/mxmediamanager.h" #include "omni/include/mxmediapresenter.h" #include "omni/include/mxmemorypool.h" #include "omni/include/mxmisc.h" @@ -252,6 +248,7 @@ #include "omni/include/mxomnicreateparam.h" #include "omni/include/mxpalette.h" #include "omni/include/mxparam.h" +#include "omni/include/mxpresentationmanager.h" #include "omni/include/mxpresenter.h" #include "omni/include/mxpresenterlist.h" #include "omni/include/mxqueue.h" diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index 7f12d147..84ff77d3 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -1,7 +1,12 @@ +#ifndef MINIWIN +#include +#endif + #include "mxdirect3d.h" #include // for SDL_Log #include +#include DECOMP_SIZE_ASSERT(MxDirect3D, 0x894) @@ -44,6 +49,7 @@ BOOL MxDirect3D::Create( ) { BOOL success = FALSE; + IDirect3DMiniwin* miniwind3d = nullptr; assert(m_currentDeviceInfo); if (!MxDirectDraw::Create( @@ -64,6 +70,21 @@ BOOL MxDirect3D::Create( goto done; } + if (m_pDirect3d->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d) == DD_OK) { + MxVideoParam* videoParam = (MxVideoParam*) SDL_GetPointerProperty( + SDL_GetWindowProperties(reinterpret_cast(hWnd)), + ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM, + nullptr + ); +#ifndef MXDIRECTX_FOR_CONFIG + assert(videoParam); +#endif + if (videoParam) { + miniwind3d->RequestMSAA(videoParam->GetMSAASamples()); + miniwind3d->RequestAnisotropic(videoParam->GetAnisotropic()); + } + } + if (!D3DSetMode()) { goto done; } diff --git a/LEGO1/mxdirectx/mxdirectxinfo.cpp b/LEGO1/mxdirectx/mxdirectxinfo.cpp index 3451b8fc..765d32f7 100644 --- a/LEGO1/mxdirectx/mxdirectxinfo.cpp +++ b/LEGO1/mxdirectx/mxdirectxinfo.cpp @@ -1,7 +1,10 @@ #include "mxdirectxinfo.h" +#include "omni/include/mxvideoparam.h" + #include #include +#include #include // for vsprintf DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4) @@ -216,12 +219,29 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc LPDIRECTDRAW lpDD = NULL; MxDriver& newDevice = m_ddInfo.back(); HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); + IDirect3DMiniwin* miniwind3d = nullptr; if (result != DD_OK) { BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); goto done; } + result = lpDD->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d); + if (result == DD_OK) { + MxVideoParam* videoParam = (MxVideoParam*) SDL_GetPointerProperty( + SDL_GetWindowProperties(reinterpret_cast(m_hWnd)), + ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM, + nullptr + ); +#ifndef MXDIRECTX_FOR_CONFIG + assert(videoParam); +#endif + if (videoParam) { + miniwind3d->RequestMSAA(videoParam->GetMSAASamples()); + miniwind3d->RequestAnisotropic(videoParam->GetAnisotropic()); + } + } + result = lpDD->SetCooperativeLevel(m_hWnd, DDSCL_NORMAL); if (result != DD_OK) { BuildErrorString("SetCooperativeLevel failed: %s\n", EnumerateErrorToString(result)); diff --git a/LEGO1/omni/include/mxaudiomanager.h b/LEGO1/omni/include/mxaudiomanager.h index f962a16d..bab1f553 100644 --- a/LEGO1/omni/include/mxaudiomanager.h +++ b/LEGO1/omni/include/mxaudiomanager.h @@ -2,11 +2,12 @@ #define MXAUDIOMANAGER_H #include "decomp.h" -#include "mxmediamanager.h" +#include "mxpresentationmanager.h" // VTABLE: LEGO1 0x100dc6e0 +// VTABLE: BETA10 0x101c2348 // SIZE 0x30 -class MxAudioManager : public MxMediaManager { +class MxAudioManager : public MxPresentationManager { public: MxAudioManager(); ~MxAudioManager() override; @@ -15,11 +16,13 @@ class MxAudioManager : public MxMediaManager { void Destroy() override; // vtable+18 // FUNCTION: LEGO1 0x10029910 + // FUNCTION: BETA10 0x100d0630 virtual MxS32 GetVolume() { return m_volume; } // vtable+28 virtual void SetVolume(MxS32 p_volume); // vtable+2c // SYNTHETIC: LEGO1 0x100b8d70 + // SYNTHETIC: BETA10 0x10145110 // MxAudioManager::`scalar deleting destructor' private: diff --git a/LEGO1/omni/include/mxautolock.h b/LEGO1/omni/include/mxautolock.h index 8a2b3c35..6a26ba47 100644 --- a/LEGO1/omni/include/mxautolock.h +++ b/LEGO1/omni/include/mxautolock.h @@ -3,15 +3,27 @@ class MxCriticalSection; +#ifdef BETA10 +#define AUTOLOCK(CS) MxAutoLock lock(&CS, __FILE__, __LINE__) +#else #define AUTOLOCK(CS) MxAutoLock lock(&CS) +#endif class MxAutoLock { public: +#ifdef BETA10 + MxAutoLock(MxCriticalSection* p_criticalSection, const char* filename, int line); +#else MxAutoLock(MxCriticalSection* p_criticalSection); +#endif ~MxAutoLock(); private: MxCriticalSection* m_criticalSection; // 0x00 + +#ifdef BETA10 + unsigned long m_currentThreadId; // 0x04 +#endif }; #endif // MXAUTOLOCK_H diff --git a/LEGO1/omni/include/mxcriticalsection.h b/LEGO1/omni/include/mxcriticalsection.h index 9a5c85b6..81767fd9 100644 --- a/LEGO1/omni/include/mxcriticalsection.h +++ b/LEGO1/omni/include/mxcriticalsection.h @@ -11,7 +11,11 @@ class MxCriticalSection { static void SetDoMutex(); +#ifdef BETA10 + void Enter(unsigned long p_threadId, const char* filename, int line); +#else void Enter(); +#endif void Leave(); private: @@ -22,4 +26,11 @@ class MxCriticalSection { SDL_Mutex* m_mutex; }; +#ifdef BETA10 +// TODO: Not quite correct yet, the second argument becomes a relocated value +#define ENTER(criticalSection) criticalSection.Enter(-1, NULL, 0) +#else +#define ENTER(criticalSection) criticalSection.Enter() +#endif + #endif // MXCRITICALSECTION_H diff --git a/LEGO1/omni/include/mxeventmanager.h b/LEGO1/omni/include/mxeventmanager.h index b23a2ad0..f17f886d 100644 --- a/LEGO1/omni/include/mxeventmanager.h +++ b/LEGO1/omni/include/mxeventmanager.h @@ -2,11 +2,11 @@ #define MXEVENTMANAGER_H #include "decomp.h" -#include "mxmediamanager.h" +#include "mxpresentationmanager.h" // VTABLE: LEGO1 0x100dc900 // SIZE 0x2c -class MxEventManager : public MxMediaManager { +class MxEventManager : public MxPresentationManager { public: MxEventManager(); ~MxEventManager() override; diff --git a/LEGO1/omni/include/mxlist.h b/LEGO1/omni/include/mxlist.h index 6d46cb2a..3fe72d0f 100644 --- a/LEGO1/omni/include/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -254,11 +254,11 @@ inline MxBool MxListCursor::Next() template inline MxBool MxListCursor::Next(T& p_obj) { - if (!m_match) { - m_match = m_list->m_first; + if (m_match) { + m_match = m_match->GetNext(); } else { - m_match = m_match->GetNext(); + m_match = m_list->m_first; } if (m_match) { diff --git a/LEGO1/omni/include/mxmediamanager.h b/LEGO1/omni/include/mxpresentationmanager.h similarity index 71% rename from LEGO1/omni/include/mxmediamanager.h rename to LEGO1/omni/include/mxpresentationmanager.h index 38f611eb..f0740e6e 100644 --- a/LEGO1/omni/include/mxmediamanager.h +++ b/LEGO1/omni/include/mxpresentationmanager.h @@ -1,5 +1,5 @@ -#ifndef MXMEDIAMANGER_H -#define MXMEDIAMANGER_H +#ifndef MXPRESENTATIONMANAGER_H +#define MXPRESENTATIONMANAGER_H #include "mxcore.h" #include "mxcriticalsection.h" @@ -9,11 +9,12 @@ class MxThread; // VTABLE: LEGO1 0x100dc6b0 +// VTABLE: BETA10 0x101c2318 // SIZE 0x2c -class MxMediaManager : public MxCore { +class MxPresentationManager : public MxCore { public: - MxMediaManager(); - ~MxMediaManager() override; + MxPresentationManager(); + ~MxPresentationManager() override; MxResult Tickle() override; // vtable+08 virtual MxResult Create(); // vtable+14 @@ -25,7 +26,8 @@ class MxMediaManager : public MxCore { MxResult Init(); // SYNTHETIC: LEGO1 0x100b8540 - // MxMediaManager::`scalar deleting destructor' + // SYNTHETIC: BETA10 0x10144db0 + // MxPresentationManager::`scalar deleting destructor' protected: MxPresenterList* m_presenters; // 0x08 @@ -33,4 +35,4 @@ class MxMediaManager : public MxCore { MxCriticalSection m_criticalSection; // 0x10 }; -#endif // MXMEDIAMANGER_H +#endif // MXPRESENTATIONMANAGER_H diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index 0e8bd316..7d3000cc 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -5,12 +5,15 @@ #include "mxpresenter.h" // VTABLE: LEGO1 0x100d62f0 +// VTABLE: BETA10 0x101bf070 // class MxPtrList // VTABLE: LEGO1 0x100d6308 +// VTABLE: BETA10 0x101bf050 // SIZE 0x18 class MxPresenterList : public MxPtrList { public: + // FUNCTION: BETA10 0x100dc900 MxPresenterList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x1001cd00 @@ -35,6 +38,13 @@ class MxPresenterListCursor : public MxPtrListCursor { public: // FUNCTION: BETA10 0x1007d130 MxPresenterListCursor(MxPresenterList* p_list) : MxPtrListCursor(p_list) {} + + // SYNTHETIC: LEGO1 0x1001eed0 + // MxPresenterListCursor::`scalar deleting destructor' + + // SYNTHETIC: LEGO1 0x1001f0c0 + // SYNTHETIC: BETA10 0x1007d510 + // MxPresenterListCursor::~MxPresenterListCursor }; // VTABLE: LEGO1 0x100d6350 @@ -58,7 +68,11 @@ class MxPresenterListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x1001ce20 // MxList::~MxList +// TEMPLATE: BETA10 0x100dc9f0 +// MxPtrList::MxPtrList + // TEMPLATE: LEGO1 0x1001cf20 +// TEMPLATE: BETA10 0x100dce70 // MxPtrList::~MxPtrList // SYNTHETIC: LEGO1 0x1001cf70 @@ -73,10 +87,8 @@ class MxPresenterListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x1001d100 // MxPresenterList::~MxPresenterList -// SYNTHETIC: LEGO1 0x1001eed0 -// MxPresenterListCursor::`scalar deleting destructor' - // TEMPLATE: LEGO1 0x1001ef40 +// TEMPLATE: BETA10 0x1007d370 // MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x1001ef90 @@ -86,11 +98,9 @@ class MxPresenterListCursor : public MxPtrListCursor { // MxPtrListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x1001f070 +// TEMPLATE: BETA10 0x1007d490 // MxListCursor::~MxListCursor -// FUNCTION: LEGO1 0x1001f0c0 -// MxPresenterListCursor::~MxPresenterListCursor - // TEMPLATE: LEGO1 0x10020760 // MxListCursor::MxListCursor @@ -106,6 +116,18 @@ class MxPresenterListCursor : public MxPtrListCursor { // TEMPLATE: BETA10 0x1007d270 // MxListCursor::MxListCursor +// TEMPLATE: BETA10 0x1007dc60 +// MxListCursor::Next + +// TEMPLATE: BETA10 0x100d8f20 +// MxListCursor::Reset + +// TEMPLATE: BETA10 0x1007e070 +// MxListEntry::GetNext + +// TEMPLATE: BETA10 0x1007e0a0 +// MxListEntry::GetValue + // TEMPLATE: BETA10 0x100d9420 // ?Prev@?$MxListCursor@PAVMxPresenter@@@@QAEEAAPAVMxPresenter@@@Z diff --git a/LEGO1/omni/include/mxsemaphore.h b/LEGO1/omni/include/mxsemaphore.h index 1d43009a..fd8b60b0 100644 --- a/LEGO1/omni/include/mxsemaphore.h +++ b/LEGO1/omni/include/mxsemaphore.h @@ -6,17 +6,20 @@ #include // VTABLE: LEGO1 0x100dccf0 +// VTABLE: BETA10 0x101c28ac // SIZE 0x08 class MxSemaphore { public: MxSemaphore(); // FUNCTION: LEGO1 0x100c87e0 + // FUNCTION: BETA10 0x101592a9 ~MxSemaphore() { SDL_DestroySemaphore(m_semaphore); } virtual MxResult Init(MxU32 p_initialCount, MxU32 p_maxCount); - void Wait(); + void Acquire(); + void TryAcquire(); void Release(); private: diff --git a/LEGO1/omni/include/mxsoundmanager.h b/LEGO1/omni/include/mxsoundmanager.h index 062d3839..569a7ff1 100644 --- a/LEGO1/omni/include/mxsoundmanager.h +++ b/LEGO1/omni/include/mxsoundmanager.h @@ -26,7 +26,11 @@ class MxSoundManager : public MxAudioManager { float GetAttenuation(MxU32 p_volume); - MxPresenter* FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_objectId); + MxPresenter* FindPresenter(const MxAtomId& p_atomId, MxU32 p_objectId); + + // SYNTHETIC: LEGO1 0x100ae7b0 + // SYNTHETIC: BETA10 0x10133460 + // MxSoundManager::`scalar deleting destructor' protected: void Init(); @@ -49,7 +53,4 @@ class MxSoundManager : public MxAudioManager { undefined m_unk0x38[4]; }; -// SYNTHETIC: LEGO1 0x100ae7b0 -// MxSoundManager::`scalar deleting destructor' - #endif // MXSOUNDMANAGER_H diff --git a/LEGO1/omni/include/mxthread.h b/LEGO1/omni/include/mxthread.h index ba0d89fa..28732f0a 100644 --- a/LEGO1/omni/include/mxthread.h +++ b/LEGO1/omni/include/mxthread.h @@ -14,6 +14,7 @@ class MxCore; // VTABLE: LEGO1 0x100dc860 +// VTABLE: BETA10 0x101c23e8 // SIZE 0x1c class MxThread { public: @@ -25,9 +26,16 @@ class MxThread { void Terminate(); void Sleep(MxS32 p_milliseconds); + void ResumeThread(); + void SuspendThread(); + bool TerminateThread(MxU32 p_exitCode); + MxS32 GetThreadPriority(MxU16& p_priority); + bool SetThreadPriority(MxU16 p_priority); + MxBool IsRunning() { return m_running; } // SYNTHETIC: LEGO1 0x100bf580 + // SYNTHETIC: BETA10 0x10147880 // MxThread::`scalar deleting destructor' protected: diff --git a/LEGO1/omni/include/mxvariable.h b/LEGO1/omni/include/mxvariable.h index 8949833f..9eda281f 100644 --- a/LEGO1/omni/include/mxvariable.h +++ b/LEGO1/omni/include/mxvariable.h @@ -9,6 +9,7 @@ // SIZE 0x24 class MxVariable { public: + // FUNCTION: BETA10 0x1007b750 MxVariable() {} // FUNCTION: BETA10 0x1012a840 @@ -41,12 +42,16 @@ class MxVariable { // FUNCTION: BETA10 0x1012a7f0 const MxString* GetKey() const { return &m_key; } + // SYNTHETIC: BETA10 0x1007b8c0 + // MxVariable::`scalar deleting destructor' + protected: MxString m_key; // 0x04 MxString m_value; // 0x14 }; // SYNTHETIC: LEGO1 0x1003bf40 +// SYNTHETIC: BETA10 0x1007b910 // MxVariable::~MxVariable #endif // MXVARIABLE_H diff --git a/LEGO1/omni/include/mxvideomanager.h b/LEGO1/omni/include/mxvideomanager.h index 04855a10..08632f74 100644 --- a/LEGO1/omni/include/mxvideomanager.h +++ b/LEGO1/omni/include/mxvideomanager.h @@ -1,7 +1,7 @@ #ifndef MXVIDEOMANAGER_H #define MXVIDEOMANAGER_H -#include "mxmediamanager.h" +#include "mxpresentationmanager.h" #include "mxvideoparam.h" #ifdef MINIWIN @@ -15,8 +15,9 @@ class MxRect32; class MxRegion; // VTABLE: LEGO1 0x100dc810 +// VTABLE: BETA10 0x101c1bf8 // SIZE 0x64 -class MxVideoManager : public MxMediaManager { +class MxVideoManager : public MxPresentationManager { public: MxVideoManager(); ~MxVideoManager() override; @@ -52,6 +53,7 @@ class MxVideoManager : public MxMediaManager { MxRegion* GetRegion() { return this->m_region; } // SYNTHETIC: LEGO1 0x100be280 + // SYNTHETIC: BETA10 0x1012de00 // MxVideoManager::`scalar deleting destructor' protected: diff --git a/LEGO1/omni/include/mxvideoparam.h b/LEGO1/omni/include/mxvideoparam.h index ccc073ab..cd425ba9 100644 --- a/LEGO1/omni/include/mxvideoparam.h +++ b/LEGO1/omni/include/mxvideoparam.h @@ -15,6 +15,8 @@ class MxPalette; +#define ISLE_PROP_WINDOW_CREATE_VIDEO_PARAM "ISLE.window.create.videoParam" + // SIZE 0x24 class MxVideoParam { public: @@ -51,6 +53,12 @@ class MxVideoParam { // FUNCTION: BETA10 0x10141fe0 void SetBackBuffers(MxU32 p_backBuffers) { m_backBuffers = p_backBuffers; } + void SetMSAASamples(MxU32 p_msaaSamples) { m_msaaSamples = p_msaaSamples; } + MxU32 GetMSAASamples() { return m_msaaSamples; } + + void SetAnisotropic(MxFloat p_anisotropic) { m_anisotropic = p_anisotropic; } + MxFloat GetAnisotropic() { return m_anisotropic; } + private: MxRect32 m_rect; // 0x00 MxPalette* m_palette; // 0x10 @@ -58,6 +66,8 @@ class MxVideoParam { MxVideoParamFlags m_flags; // 0x18 int m_unk0x1c; // 0x1c char* m_deviceId; // 0x20 + MxU32 m_msaaSamples; + MxFloat m_anisotropic; }; #endif // MXVIDEOPARAM_H diff --git a/LEGO1/omni/include/mxvideoparamflags.h b/LEGO1/omni/include/mxvideoparamflags.h index 4fef2145..6158c4d7 100644 --- a/LEGO1/omni/include/mxvideoparamflags.h +++ b/LEGO1/omni/include/mxvideoparamflags.h @@ -24,7 +24,7 @@ class MxVideoParamFlags { void SetBackBuffers(MxBool p_e) { m_flags1.m_bit2 = p_e; } // FUNCTION: BETA10 0x100d9250 - void SetF1bit3(MxBool p_e) { m_flags1.m_bit3 = p_e; } + void SetDoubleScaling(MxBool p_e) { m_flags1.m_bit3 = p_e; } // inlined in ISLE void Set16Bit(MxBool p_e) { m_flags1.m_bit5 = p_e; } @@ -39,7 +39,7 @@ class MxVideoParamFlags { void SetLacksLightSupport(MxBool p_e) { m_flags2.m_bit0 = p_e; } // inlined in ISLE - void SetF2bit1(MxBool p_e) { m_flags2.m_bit1 = p_e; } + void SetEnabled(MxBool p_e) { m_flags2.m_bit1 = p_e; } // FUNCTION: BETA10 0x1009e770 MxBool GetFullScreen() { return m_flags1.m_bit0; } @@ -51,7 +51,7 @@ class MxVideoParamFlags { MxBool GetBackBuffers() { return m_flags1.m_bit2; } // FUNCTION: BETA10 0x10142010 - MxBool GetF1bit3() { return m_flags1.m_bit3; } + MxBool GetDoubleScaling() { return m_flags1.m_bit3; } // FUNCTION: BETA10 0x100d8150 MxBool Get16Bit() { return m_flags1.m_bit5; } @@ -63,7 +63,7 @@ class MxVideoParamFlags { MxBool GetLacksLightSupport() { return m_flags2.m_bit0; } // FUNCTION: BETA10 0x10142050 - MxBool GetF2bit1() { return m_flags2.m_bit1; } + MxBool GetEnabled() { return m_flags2.m_bit1; } private: FlagBitfield m_flags1; diff --git a/LEGO1/omni/src/audio/mxaudiomanager.cpp b/LEGO1/omni/src/audio/mxaudiomanager.cpp index 81b8922e..3cef829a 100644 --- a/LEGO1/omni/src/audio/mxaudiomanager.cpp +++ b/LEGO1/omni/src/audio/mxaudiomanager.cpp @@ -3,47 +3,84 @@ DECOMP_SIZE_ASSERT(MxAudioManager, 0x30); // GLOBAL: LEGO1 0x10102108 +// GLOBAL: BETA10 0x10203a60 MxS32 MxAudioManager::g_count = 0; // FUNCTION: LEGO1 0x100b8d00 +// FUNCTION: BETA10 0x10144e90 MxAudioManager::MxAudioManager() { Init(); } // FUNCTION: LEGO1 0x100b8d90 +// STUB: BETA10 0x10144f07 MxAudioManager::~MxAudioManager() { Destroy(TRUE); } // FUNCTION: LEGO1 0x100b8df0 +// FUNCTION: BETA10 0x10144f79 void MxAudioManager::Init() { m_volume = 100; } // FUNCTION: LEGO1 0x100b8e00 +// FUNCTION: BETA10 0x10144f9c void MxAudioManager::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); g_count--; Init(); m_criticalSection.Leave(); if (!p_fromDestructor) { - MxMediaManager::Destroy(); + MxPresentationManager::Destroy(); } } +#ifdef BETA10 +// FUNCTION: BETA10 0x10144ffe +MxResult MxAudioManager::Create() +{ + MxResult result = FAILURE; + MxBool success = FALSE; + + if (MxPresentationManager::Create() != SUCCESS) { + goto exit; + } + + ENTER(m_criticalSection); + success = TRUE; + + if (!g_count++) { + // This is correct. It was likely refactored later. + } + +exit: + result = SUCCESS; + + if (result) { + Destroy(); + } + + if (success) { + m_criticalSection.Leave(); + } + + return result; +} +#else // FUNCTION: LEGO1 0x100b8e40 MxResult MxAudioManager::Create() { MxResult result = FAILURE; MxBool success = FALSE; - if (MxMediaManager::Create() == SUCCESS) { - m_criticalSection.Enter(); + if (MxPresentationManager::Create() == SUCCESS) { + ENTER(m_criticalSection); success = TRUE; result = SUCCESS; g_count++; @@ -59,17 +96,20 @@ MxResult MxAudioManager::Create() return result; } +#endif // FUNCTION: LEGO1 0x100b8e90 +// FUNCTION: BETA10 0x101450a7 void MxAudioManager::Destroy() { Destroy(FALSE); } // FUNCTION: LEGO1 0x100b8ea0 +// FUNCTION: BETA10 0x101450c7 void MxAudioManager::SetVolume(MxS32 p_volume) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); m_volume = p_volume; m_criticalSection.Leave(); } diff --git a/LEGO1/omni/src/audio/mxsoundmanager.cpp b/LEGO1/omni/src/audio/mxsoundmanager.cpp index f865ebf0..dab79698 100644 --- a/LEGO1/omni/src/audio/mxsoundmanager.cpp +++ b/LEGO1/omni/src/audio/mxsoundmanager.cpp @@ -25,18 +25,21 @@ MxS32 g_volumeAttenuation[100] = {-6643, -5643, -5058, -4643, -4321, -4058, -383 -43, -29, -14, 0}; // FUNCTION: LEGO1 0x100ae740 +// FUNCTION: BETA10 0x10132c70 MxSoundManager::MxSoundManager() { Init(); } // FUNCTION: LEGO1 0x100ae7d0 +// FUNCTION: BETA10 0x10132ce7 MxSoundManager::~MxSoundManager() { Destroy(TRUE); } // FUNCTION: LEGO1 0x100ae830 +// FUNCTION: BETA10 0x10132d59 void MxSoundManager::Init() { SDL_zero(m_engine); @@ -44,6 +47,7 @@ void MxSoundManager::Init() } // FUNCTION: LEGO1 0x100ae840 +// FUNCTION: BETA10 0x10132d89 void MxSoundManager::Destroy(MxBool p_fromDestructor) { if (m_thread) { @@ -54,7 +58,7 @@ void MxSoundManager::Destroy(MxBool p_fromDestructor) TickleManager()->UnregisterClient(this); } - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (m_stream) { SDL_DestroyAudioStream(m_stream); @@ -82,7 +86,7 @@ MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) goto done; } - m_criticalSection.Enter(); + ENTER(m_criticalSection); locked = TRUE; engineConfig = ma_engine_config_init(); @@ -157,17 +161,19 @@ void MxSoundManager::AudioStreamCallback( } // FUNCTION: LEGO1 0x100aeab0 +// FUNCTION: BETA10 0x101331e3 void MxSoundManager::Destroy() { Destroy(FALSE); } // FUNCTION: LEGO1 0x100aeac0 +// FUNCTION: BETA10 0x10133203 void MxSoundManager::SetVolume(MxS32 p_volume) { MxAudioManager::SetVolume(p_volume); - m_criticalSection.Enter(); + ENTER(m_criticalSection); MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); @@ -180,7 +186,8 @@ void MxSoundManager::SetVolume(MxS32 p_volume) } // FUNCTION: LEGO1 0x100aebd0 -MxPresenter* MxSoundManager::FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_objectId) +// FUNCTION: BETA10 0x101332cf +MxPresenter* MxSoundManager::FindPresenter(const MxAtomId& p_atomId, MxU32 p_objectId) { AUTOLOCK(m_criticalSection); @@ -188,8 +195,7 @@ MxPresenter* MxSoundManager::FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_obje MxPresenterListCursor cursor(m_presenters); while (cursor.Next(presenter)) { - if (presenter->GetAction()->GetAtomId().GetInternal() == p_atomId.GetInternal() && - presenter->GetAction()->GetObjectId() == p_objectId) { + if (presenter->GetAction()->GetAtomId() == p_atomId && presenter->GetAction()->GetObjectId() == p_objectId) { return presenter; } } diff --git a/LEGO1/omni/src/audio/mxsoundpresenter.cpp b/LEGO1/omni/src/audio/mxsoundpresenter.cpp index 9d784532..3fa2cfaa 100644 --- a/LEGO1/omni/src/audio/mxsoundpresenter.cpp +++ b/LEGO1/omni/src/audio/mxsoundpresenter.cpp @@ -13,7 +13,7 @@ void MxSoundPresenter::Destroy(MxBool p_fromDestructor) MSoundManager()->UnregisterPresenter(*this); } - m_criticalSection.Enter(); + ENTER(m_criticalSection); MxMediaPresenter::Init(); m_criticalSection.Leave(); diff --git a/LEGO1/omni/src/audio/mxwavepresenter.cpp b/LEGO1/omni/src/audio/mxwavepresenter.cpp index 600d9b37..8601f44b 100644 --- a/LEGO1/omni/src/audio/mxwavepresenter.cpp +++ b/LEGO1/omni/src/audio/mxwavepresenter.cpp @@ -289,7 +289,7 @@ void MxWavePresenter::EndAction() // FUNCTION: LEGO1 0x100b2300 void MxWavePresenter::SetVolume(MxS32 p_volume) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); m_volume = p_volume; if (m_sound) { diff --git a/LEGO1/omni/src/common/mxcompositepresenter.cpp b/LEGO1/omni/src/common/mxcompositepresenter.cpp index 4e83d86c..b3d56875 100644 --- a/LEGO1/omni/src/common/mxcompositepresenter.cpp +++ b/LEGO1/omni/src/common/mxcompositepresenter.cpp @@ -25,7 +25,7 @@ MxCompositePresenter::~MxCompositePresenter() } // FUNCTION: LEGO1 0x100b6410 -// FUNCTION: BETA10 0x100e9d37 +// FUNCTION: BETA10 0x10137344 MxResult MxCompositePresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { AUTOLOCK(m_criticalSection); diff --git a/LEGO1/omni/src/common/mxmediapresenter.cpp b/LEGO1/omni/src/common/mxmediapresenter.cpp index c8b9abcd..11621f71 100644 --- a/LEGO1/omni/src/common/mxmediapresenter.cpp +++ b/LEGO1/omni/src/common/mxmediapresenter.cpp @@ -131,6 +131,7 @@ MxResult MxMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAct } // FUNCTION: LEGO1 0x100b5bc0 +// STUB: BETA10 0x1013623c void MxMediaPresenter::EndAction() { AUTOLOCK(m_criticalSection); diff --git a/LEGO1/omni/src/common/mxmediamanager.cpp b/LEGO1/omni/src/common/mxpresentationmanager.cpp similarity index 62% rename from LEGO1/omni/src/common/mxmediamanager.cpp rename to LEGO1/omni/src/common/mxpresentationmanager.cpp index cc1611ae..6ef8448e 100644 --- a/LEGO1/omni/src/common/mxmediamanager.cpp +++ b/LEGO1/omni/src/common/mxpresentationmanager.cpp @@ -1,4 +1,4 @@ -#include "mxmediamanager.h" +#include "mxpresentationmanager.h" #include "decomp.h" #include "mxautolock.h" @@ -6,24 +6,27 @@ #include "mxpresenter.h" #include "mxticklemanager.h" -DECOMP_SIZE_ASSERT(MxMediaManager, 0x2c); +DECOMP_SIZE_ASSERT(MxPresentationManager, 0x2c); DECOMP_SIZE_ASSERT(MxPresenterList, 0x18); DECOMP_SIZE_ASSERT(MxPresenterListCursor, 0x10); // FUNCTION: LEGO1 0x100b84c0 -MxMediaManager::MxMediaManager() +// FUNCTION: BETA10 0x10144680 +MxPresentationManager::MxPresentationManager() { Init(); } // FUNCTION: LEGO1 0x100b8560 -MxMediaManager::~MxMediaManager() +// FUNCTION: BETA10 0x10144712 +MxPresentationManager::~MxPresentationManager() { Destroy(); } // FUNCTION: LEGO1 0x100b85d0 -MxResult MxMediaManager::Init() +// FUNCTION: BETA10 0x1014479b +MxResult MxPresentationManager::Init() { this->m_presenters = NULL; this->m_thread = NULL; @@ -31,8 +34,10 @@ MxResult MxMediaManager::Init() } // FUNCTION: LEGO1 0x100b85e0 -MxResult MxMediaManager::Create() +// FUNCTION: BETA10 0x101447c5 +MxResult MxPresentationManager::Create() { + // This validates the name of the source code file (and hence also the name of the class) AUTOLOCK(m_criticalSection); this->m_presenters = new MxPresenterList; @@ -46,7 +51,8 @@ MxResult MxMediaManager::Create() } // FUNCTION: LEGO1 0x100b8710 -void MxMediaManager::Destroy() +// FUNCTION: BETA10 0x101448e4 +void MxPresentationManager::Destroy() { AUTOLOCK(m_criticalSection); @@ -58,7 +64,8 @@ void MxMediaManager::Destroy() } // FUNCTION: LEGO1 0x100b8790 -MxResult MxMediaManager::Tickle() +// FUNCTION: BETA10 0x10144993 +MxResult MxPresentationManager::Tickle() { AUTOLOCK(m_criticalSection); MxPresenter* presenter; @@ -78,7 +85,8 @@ MxResult MxMediaManager::Tickle() } // FUNCTION: LEGO1 0x100b88c0 -void MxMediaManager::RegisterPresenter(MxPresenter& p_presenter) +// FUNCTION: BETA10 0x10144a8b +void MxPresentationManager::RegisterPresenter(MxPresenter& p_presenter) { AUTOLOCK(m_criticalSection); @@ -86,7 +94,8 @@ void MxMediaManager::RegisterPresenter(MxPresenter& p_presenter) } // FUNCTION: LEGO1 0x100b8980 -void MxMediaManager::UnregisterPresenter(MxPresenter& p_presenter) +// FUNCTION: BETA10 0x10144b0c +void MxPresentationManager::UnregisterPresenter(MxPresenter& p_presenter) { AUTOLOCK(m_criticalSection); MxPresenterListCursor cursor(this->m_presenters); @@ -97,7 +106,8 @@ void MxMediaManager::UnregisterPresenter(MxPresenter& p_presenter) } // FUNCTION: LEGO1 0x100b8ac0 -void MxMediaManager::StopPresenters() +// FUNCTION: BETA10 0x10144bc3 +void MxPresentationManager::StopPresenters() { AUTOLOCK(m_criticalSection); MxPresenter* presenter; diff --git a/LEGO1/omni/src/event/mxeventmanager.cpp b/LEGO1/omni/src/event/mxeventmanager.cpp index 29b8aba0..91a22abb 100644 --- a/LEGO1/omni/src/event/mxeventmanager.cpp +++ b/LEGO1/omni/src/event/mxeventmanager.cpp @@ -35,7 +35,7 @@ void MxEventManager::Destroy(MxBool p_fromDestructor) } if (!p_fromDestructor) { - MxMediaManager::Destroy(); + MxPresentationManager::Destroy(); } } @@ -45,10 +45,10 @@ MxResult MxEventManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) MxResult status = FAILURE; MxBool locked = FALSE; - MxResult result = MxMediaManager::Create(); + MxResult result = MxPresentationManager::Create(); if (result == SUCCESS) { if (p_createThread) { - this->m_criticalSection.Enter(); + ENTER(this->m_criticalSection); locked = TRUE; this->m_thread = new MxTickleThread(this, p_frequencyMS); diff --git a/LEGO1/omni/src/event/mxeventpresenter.cpp b/LEGO1/omni/src/event/mxeventpresenter.cpp index f819b68c..8134465e 100644 --- a/LEGO1/omni/src/event/mxeventpresenter.cpp +++ b/LEGO1/omni/src/event/mxeventpresenter.cpp @@ -50,7 +50,7 @@ void MxEventPresenter::Destroy() EventManager()->UnregisterPresenter(*this); } - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (m_data) { delete[] m_data; diff --git a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp index 3cf753d6..49980ee1 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp @@ -161,10 +161,11 @@ void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) } // FUNCTION: LEGO1 0x100d1750 +// FUNCTION: BETA10 0x101632b8 MxResult MxDiskStreamProvider::WaitForWorkToComplete() { while (m_remainingWork) { - m_busySemaphore.Wait(); + m_busySemaphore.Acquire(); if (m_unk0x35) { PerformWork(); } diff --git a/LEGO1/omni/src/system/mxautolock.cpp b/LEGO1/omni/src/system/mxautolock.cpp index 4508663e..227085dd 100644 --- a/LEGO1/omni/src/system/mxautolock.cpp +++ b/LEGO1/omni/src/system/mxautolock.cpp @@ -2,8 +2,19 @@ #include "mxcriticalsection.h" -// FUNCTION: LEGO1 0x100b8ed0 +#ifdef BETA10 // FUNCTION: BETA10 0x101386f0 +MxAutoLock::MxAutoLock(MxCriticalSection* p_criticalSection, const char* filename, int line) +{ + m_criticalSection = p_criticalSection; + m_currentThreadId = GetCurrentThreadId(); + + if (m_criticalSection != NULL) { + m_criticalSection->Enter(m_currentThreadId, filename, line); + } +} +#else +// FUNCTION: LEGO1 0x100b8ed0 MxAutoLock::MxAutoLock(MxCriticalSection* p_criticalSection) { m_criticalSection = p_criticalSection; @@ -12,6 +23,7 @@ MxAutoLock::MxAutoLock(MxCriticalSection* p_criticalSection) m_criticalSection->Enter(); } } +#endif // FUNCTION: LEGO1 0x100b8ef0 // FUNCTION: BETA10 0x10138744 diff --git a/LEGO1/omni/src/system/mxcriticalsection.cpp b/LEGO1/omni/src/system/mxcriticalsection.cpp index 7b982bd6..e940c847 100644 --- a/LEGO1/omni/src/system/mxcriticalsection.cpp +++ b/LEGO1/omni/src/system/mxcriticalsection.cpp @@ -22,14 +22,43 @@ MxCriticalSection::~MxCriticalSection() } } -// FUNCTION: LEGO1 0x100b6d80 +#ifdef BETA10 // FUNCTION: BETA10 0x1013c725 +void MxCriticalSection::Enter(unsigned long p_threadId, const char* filename, int line) +{ + DWORD result; + FILE* file; + + if (m_mutex != NULL) { + result = WaitForSingleObject(m_mutex, 5000); + if (result == WAIT_FAILED) { + file = fopen("C:\\DEADLOCK.TXT", "a"); + if (file != NULL) { + fprintf(file, "mutex timeout occurred!\n"); + fprintf(file, "file: %s, line: %d\n", filename, line); + fclose(file); + } + + abort(); + } + } + else { + EnterCriticalSection(&m_criticalSection); + } + + // There is way more structure in here, and the MxCriticalSection class is much larger in BETA10. + // The LEGO1 compilation is very unlikely to profit from a further decompilation here. +} +#else +// FUNCTION: LEGO1 0x100b6d80 void MxCriticalSection::Enter() { SDL_LockMutex(m_mutex); } +#endif // FUNCTION: LEGO1 0x100b6de0 +// FUNCTION: BETA10 0x1013c7ef void MxCriticalSection::Leave() { SDL_UnlockMutex(m_mutex); diff --git a/LEGO1/omni/src/system/mxsemaphore.cpp b/LEGO1/omni/src/system/mxsemaphore.cpp index a4db127b..2cd2016e 100644 --- a/LEGO1/omni/src/system/mxsemaphore.cpp +++ b/LEGO1/omni/src/system/mxsemaphore.cpp @@ -6,32 +6,46 @@ DECOMP_SIZE_ASSERT(MxSemaphore, 0x08) // FUNCTION: LEGO1 0x100c87d0 +// FUNCTION: BETA10 0x10159260 MxSemaphore::MxSemaphore() { m_semaphore = NULL; } // FUNCTION: LEGO1 0x100c8800 +// FUNCTION: BETA10 0x101592d5 MxResult MxSemaphore::Init(MxU32 p_initialCount, MxU32 p_maxCount) { // [library:synchronization] No support for max count, but shouldn't be necessary MxResult result = FAILURE; - if ((m_semaphore = SDL_CreateSemaphore(p_initialCount))) { - result = SUCCESS; + m_semaphore = SDL_CreateSemaphore(p_initialCount); + if (!m_semaphore) { + goto done; } + result = SUCCESS; + +done: return result; } // FUNCTION: LEGO1 0x100c8830 -void MxSemaphore::Wait() +// FUNCTION: BETA10 0x10159332 +void MxSemaphore::Acquire() { // [library:synchronization] Removed timeout since only INFINITE is ever requested SDL_WaitSemaphore(m_semaphore); } +// FUNCTION: BETA10 0x10159385 +void MxSemaphore::TryAcquire() +{ + // unused +} + // FUNCTION: LEGO1 0x100c8850 +// FUNCTION: BETA10 0x101593aa void MxSemaphore::Release() { // [library:synchronization] Removed release count since only 1 is ever requested diff --git a/LEGO1/omni/src/system/mxthread.cpp b/LEGO1/omni/src/system/mxthread.cpp index 6c118d4d..1e0914c5 100644 --- a/LEGO1/omni/src/system/mxthread.cpp +++ b/LEGO1/omni/src/system/mxthread.cpp @@ -10,6 +10,7 @@ DECOMP_SIZE_ASSERT(MxThread, 0x1c) // FUNCTION: LEGO1 0x100bf510 +// FUNCTION: BETA10 0x10147540 MxThread::MxThread() { #ifdef PSP @@ -21,6 +22,7 @@ MxThread::MxThread() } // FUNCTION: LEGO1 0x100bf5a0 +// FUNCTION: BETA10 0x101475d0 MxThread::~MxThread() { if (m_thread) { @@ -35,10 +37,12 @@ MxThread::~MxThread() } // FUNCTION: LEGO1 0x100bf610 +// FUNCTION: BETA10 0x10147655 MxResult MxThread::Start(MxS32 p_stackSize, MxS32 p_flag) { MxResult result = FAILURE; + if (m_semaphore.Init(0, 1) == SUCCESS) { #ifdef PSP int thid = sceKernelCreateThread( @@ -58,34 +62,74 @@ MxResult MxThread::Start(MxS32 p_stackSize, MxS32 p_flag) m_thread = thid; // store thread ID if needed } } + } #else + goto done; + } const SDL_PropertiesID props = SDL_CreateProperties(); SDL_SetPointerProperty(props, SDL_PROP_THREAD_CREATE_ENTRY_FUNCTION_POINTER, (void*) MxThread::ThreadProc); SDL_SetPointerProperty(props, SDL_PROP_THREAD_CREATE_USERDATA_POINTER, this); SDL_SetNumberProperty(props, SDL_PROP_THREAD_CREATE_STACKSIZE_NUMBER, p_stackSize * 4); - if ((m_thread = SDL_CreateThreadWithProperties(props))) { - result = SUCCESS; + if (!(m_thread = SDL_CreateThreadWithProperties(props))) { + goto done; } SDL_DestroyProperties(props); #endif - } + result = SUCCESS; + +done: return result; } // FUNCTION: LEGO1 0x100bf660 +// FUNCTION: BETA10 0x101476ee void MxThread::Sleep(MxS32 p_milliseconds) { SDL_Delay(p_milliseconds); } +// FUNCTION: BETA10 0x10147710 +void MxThread::ResumeThread() +{ + // unused +} + +// FUNCTION: BETA10 0x10147733 +void MxThread::SuspendThread() +{ + // unused +} + +// FUNCTION: BETA10 0x10147756 +bool MxThread::TerminateThread(MxU32 p_exitCode) +{ + // unused + return false; +} + +// FUNCTION: BETA10 0x10147793 +MxS32 MxThread::GetThreadPriority(MxU16& p_priority) +{ + // unused + return -1; +} + +// FUNCTION: BETA10 0x101477c8 +bool MxThread::SetThreadPriority(MxU16 p_priority) +{ + // unused + return false; +} + // FUNCTION: LEGO1 0x100bf670 +// FUNCTION: BETA10 0x1014780a void MxThread::Terminate() { m_running = FALSE; - m_semaphore.Wait(); + m_semaphore.Acquire(); } #ifdef PSP @@ -96,6 +140,7 @@ int MxThread::ThreadProc(SceSize args, void* argp) } #else // FUNCTION: LEGO1 0x100bf680 +// FUNCTION: BETA10 0x1014783b int MxThread::ThreadProc(void* p_thread) { return static_cast(p_thread)->Run(); @@ -103,6 +148,7 @@ int MxThread::ThreadProc(void* p_thread) #endif // FUNCTION: LEGO1 0x100bf690 +// FUNCTION: BETA10 0x10147855 MxResult MxThread::Run() { m_semaphore.Release(); diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 2248a0ad..51a2f36b 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -482,7 +482,7 @@ void MxDisplaySurface::VTable0x28( tempSurface->Unlock(NULL); - if (m_videoParam.Flags().GetF1bit3()) { + if (m_videoParam.Flags().GetDoubleScaling()) { RECT destRect = {p_right, p_bottom, p_right + p_width * 2, p_bottom + p_height * 2}; m_ddSurface2->Blt(&destRect, tempSurface, NULL, DDBLT_WAIT | DDBLT_KEYSRC, NULL); } @@ -749,7 +749,7 @@ void MxDisplaySurface::DrawTransparentRLE( // FUNCTION: LEGO1 0x100bba50 void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height) { - if (m_videoParam.Flags().GetF2bit1()) { + if (m_videoParam.Flags().GetEnabled()) { if (m_videoParam.Flags().GetFlipSurfaces()) { if (g_unk0x1010215c < 2) { g_unk0x1010215c++; @@ -1012,7 +1012,7 @@ void MxDisplaySurface::VTable0x24( MxU8* data = p_bitmap->GetStart(p_left, p_top); - if (m_videoParam.Flags().GetF1bit3()) { + if (m_videoParam.Flags().GetDoubleScaling()) { p_bottom *= 2; p_right *= 2; diff --git a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp index a828296c..fb0e3134 100644 --- a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp @@ -29,7 +29,7 @@ void MxLoopingFlcPresenter::Init() // FUNCTION: LEGO1 0x100b4430 void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); Init(); m_criticalSection.Leave(); @@ -117,7 +117,7 @@ MxResult MxLoopingFlcPresenter::AddToManager() MxBool locked = FALSE; if (MxFlcPresenter::AddToManager() == SUCCESS) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); locked = TRUE; result = SUCCESS; } diff --git a/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp index e99533bd..b3705685 100644 --- a/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp @@ -29,7 +29,7 @@ void MxLoopingSmkPresenter::Init() // FUNCTION: LEGO1 0x100b49d0 void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); Init(); m_criticalSection.Leave(); diff --git a/LEGO1/omni/src/video/mxsmkpresenter.cpp b/LEGO1/omni/src/video/mxsmkpresenter.cpp index b530b2e2..2eadc6bf 100644 --- a/LEGO1/omni/src/video/mxsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxsmkpresenter.cpp @@ -34,7 +34,7 @@ void MxSmkPresenter::Init() // FUNCTION: LEGO1 0x100b3900 void MxSmkPresenter::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); MxSmk::Destroy(&m_mxSmk); Init(); diff --git a/LEGO1/omni/src/video/mxstillpresenter.cpp b/LEGO1/omni/src/video/mxstillpresenter.cpp index 7ff98788..2bcaea47 100644 --- a/LEGO1/omni/src/video/mxstillpresenter.cpp +++ b/LEGO1/omni/src/video/mxstillpresenter.cpp @@ -19,7 +19,7 @@ DECOMP_SIZE_ASSERT(MxStillPresenter, 0x6c); // FUNCTION: LEGO1 0x100b9c70 void MxStillPresenter::Destroy(MxBool p_fromDestructor) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (m_bitmapInfo) { delete[] ((MxU8*) m_bitmapInfo); diff --git a/LEGO1/omni/src/video/mxvideomanager.cpp b/LEGO1/omni/src/video/mxvideomanager.cpp index 8c75dc6a..e56cb48e 100644 --- a/LEGO1/omni/src/video/mxvideomanager.cpp +++ b/LEGO1/omni/src/video/mxvideomanager.cpp @@ -21,17 +21,20 @@ MxVideoManager::MxVideoManager() } // FUNCTION: LEGO1 0x100be270 +// FUNCTION: BETA10 0x1012dde0 void MxVideoManager::UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) { } // FUNCTION: LEGO1 0x100be2a0 +// FUNCTION: BETA10 0x1012cad8 MxVideoManager::~MxVideoManager() { Destroy(TRUE); } // FUNCTION: LEGO1 0x100be320 +// FUNCTION: BETA10 0x1012cb66 MxResult MxVideoManager::Init() { m_pDirectDraw = NULL; @@ -44,6 +47,7 @@ MxResult MxVideoManager::Init() } // FUNCTION: LEGO1 0x100be340 +// FUNCTION: BETA10 0x1012cbca void MxVideoManager::Destroy(MxBool p_fromDestructor) { if (m_thread) { @@ -54,7 +58,7 @@ void MxVideoManager::Destroy(MxBool p_fromDestructor) TickleManager()->UnregisterClient(this); } - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (m_displaySurface) { delete m_displaySurface; @@ -81,7 +85,7 @@ void MxVideoManager::Destroy(MxBool p_fromDestructor) m_criticalSection.Leave(); if (!p_fromDestructor) { - MxMediaManager::Destroy(); + MxPresentationManager::Destroy(); } } @@ -134,6 +138,7 @@ void MxVideoManager::SortPresenterList() } // FUNCTION: LEGO1 0x100be600 +// STUB: BETA10 0x1012cfbc MxResult MxVideoManager::VTable0x28( MxVideoParam& p_videoParam, LPDIRECTDRAW p_pDirectDraw, @@ -150,11 +155,11 @@ MxResult MxVideoManager::VTable0x28( m_unk0x60 = FALSE; - if (MxMediaManager::Create() != SUCCESS) { + if (MxPresentationManager::Create() != SUCCESS) { goto done; } - m_criticalSection.Enter(); + ENTER(m_criticalSection); locked = TRUE; m_videoParam = p_videoParam; @@ -216,6 +221,7 @@ MxResult MxVideoManager::VTable0x28( } // FUNCTION: LEGO1 0x100be820 +// STUB: BETA10 0x1012d3f1 MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) { MxBool locked = FALSE; @@ -224,12 +230,12 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, m_unk0x60 = TRUE; - if (MxMediaManager::Create() != SUCCESS) { - SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxMediaManager::Create failed"); + if (MxPresentationManager::Create() != SUCCESS) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "MxPresentationManager::Create failed"); goto done; } - m_criticalSection.Enter(); + ENTER(m_criticalSection); locked = TRUE; m_videoParam = p_videoParam; @@ -308,6 +314,7 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, } // FUNCTION: LEGO1 0x100bea50 +// FUNCTION: BETA10 0x1012d85f void MxVideoManager::Destroy() { Destroy(FALSE); @@ -316,7 +323,7 @@ void MxVideoManager::Destroy() // FUNCTION: LEGO1 0x100bea60 void MxVideoManager::InvalidateRect(MxRect32& p_rect) { - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (m_region) { m_region->AddRect(p_rect); @@ -326,6 +333,7 @@ void MxVideoManager::InvalidateRect(MxRect32& p_rect) } // FUNCTION: LEGO1 0x100bea90 +// FUNCTION: BETA10 0x1012d8e3 MxResult MxVideoManager::Tickle() { AUTOLOCK(m_criticalSection); @@ -356,7 +364,7 @@ MxResult MxVideoManager::RealizePalette(MxPalette* p_palette) { PALETTEENTRY paletteEntries[256]; - m_criticalSection.Enter(); + ENTER(m_criticalSection); if (p_palette && m_videoParam.GetPalette()) { p_palette->GetEntries(paletteEntries); diff --git a/LEGO1/omni/src/video/mxvideoparam.cpp b/LEGO1/omni/src/video/mxvideoparam.cpp index 9a095c4e..45a9a688 100644 --- a/LEGO1/omni/src/video/mxvideoparam.cpp +++ b/LEGO1/omni/src/video/mxvideoparam.cpp @@ -28,6 +28,8 @@ MxVideoParam::MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_bac m_flags = p_flags; m_unk0x1c = 0; m_deviceId = NULL; + m_msaaSamples = 0; + m_anisotropic = 0.0f; } // FUNCTION: LEGO1 0x100becf0 @@ -41,6 +43,8 @@ MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam) m_unk0x1c = p_videoParam.m_unk0x1c; m_deviceId = NULL; SetDeviceName(p_videoParam.m_deviceId); + m_msaaSamples = p_videoParam.m_msaaSamples; + m_anisotropic = p_videoParam.m_anisotropic; } // FUNCTION: LEGO1 0x100bed50 @@ -82,6 +86,8 @@ MxVideoParam& MxVideoParam::operator=(const MxVideoParam& p_videoParam) m_flags = p_videoParam.m_flags; m_unk0x1c = p_videoParam.m_unk0x1c; SetDeviceName(p_videoParam.m_deviceId); + m_msaaSamples = p_videoParam.m_msaaSamples; + m_anisotropic = p_videoParam.m_anisotropic; return *this; } diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp index 92c9ac9e..3c45e90f 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -153,6 +153,7 @@ void OrientableROI::UpdateWorldDataWithTransformAndChildren(const Matrix4& p_tra } // FUNCTION: LEGO1 0x100a5a30 +// FUNCTION: BETA10 0x10167d31 void OrientableROI::SetWorldVelocity(const Vector3& p_world_velocity) { m_world_velocity = p_world_velocity; diff --git a/extensions/include/extensions/textureloader.h b/extensions/include/extensions/textureloader.h index c476c7ff..a318c9b8 100644 --- a/extensions/include/extensions/textureloader.h +++ b/extensions/include/extensions/textureloader.h @@ -5,6 +5,7 @@ #include #include +#include namespace Extensions { @@ -14,10 +15,11 @@ class TextureLoader { static bool PatchTexture(LegoTextureInfo* p_textureInfo); static std::map options; + static std::vector excludedFiles; static bool enabled; static constexpr std::array, 1> defaults = { - {{"texture loader:texture path", "/textures/"}} + {{"texture loader:texture path", "/textures"}} }; private: diff --git a/extensions/src/textureloader.cpp b/extensions/src/textureloader.cpp index 07b53253..3fbf0f7d 100644 --- a/extensions/src/textureloader.cpp +++ b/extensions/src/textureloader.cpp @@ -3,6 +3,7 @@ using namespace Extensions; std::map TextureLoader::options; +std::vector TextureLoader::excludedFiles; bool TextureLoader::enabled = false; void TextureLoader::Initialize() @@ -97,13 +98,17 @@ bool TextureLoader::PatchTexture(LegoTextureInfo* p_textureInfo) SDL_Surface* TextureLoader::FindTexture(const char* p_name) { + if (std::find(excludedFiles.begin(), excludedFiles.end(), p_name) != excludedFiles.end()) { + return nullptr; + } + SDL_Surface* surface; const char* texturePath = options["texture loader:texture path"].c_str(); - MxString path = MxString(MxOmni::GetHD()) + texturePath + p_name + ".bmp"; + MxString path = MxString(MxOmni::GetHD()) + texturePath + "/" + p_name + ".bmp"; path.MapPathToFilesystem(); if (!(surface = SDL_LoadBMP(path.GetData()))) { - path = MxString(MxOmni::GetCD()) + texturePath + p_name + ".bmp"; + path = MxString(MxOmni::GetCD()) + texturePath + "/" + p_name + ".bmp"; path.MapPathToFilesystem(); surface = SDL_LoadBMP(path.GetData()); } diff --git a/miniwin/CMakeLists.txt b/miniwin/CMakeLists.txt index 3fe96ea3..615832cf 100644 --- a/miniwin/CMakeLists.txt +++ b/miniwin/CMakeLists.txt @@ -44,16 +44,16 @@ if(NOT WINDOWS_STORE) message(STATUS "🧩 OpenGL 1.x support not enabled — needs OpenGL") endif() - find_library(OPENGL_ES2_LIBRARY NAMES GLESv2) - if(EMSCRIPTEN OR OPENGL_ES2_LIBRARY) - message(STATUS "Found OpenGL: enabling OpenGL ES 2.x renderer") - target_sources(miniwin PRIVATE src/d3drm/backends/opengles2/renderer.cpp) - list(APPEND GRAPHICS_BACKENDS USE_OPENGLES2) - if(OPENGL_ES2_LIBRARY) - target_link_libraries(miniwin PRIVATE ${OPENGL_ES2_LIBRARY}) + find_library(OPENGL_ES3_LIBRARY NAMES GLESv2) + if(EMSCRIPTEN OR OPENGL_ES3_LIBRARY) + message(STATUS "Found OpenGL: enabling OpenGL ES 3.x renderer") + target_sources(miniwin PRIVATE src/d3drm/backends/opengles3/renderer.cpp) + list(APPEND GRAPHICS_BACKENDS USE_OPENGLES3) + if(OPENGL_ES3_LIBRARY) + target_link_libraries(miniwin PRIVATE ${OPENGL_ES3_LIBRARY}) endif() else() - message(STATUS "🧩 OpenGL ES 2.x support not enabled") + message(STATUS "🧩 OpenGL ES 3.x support not enabled") endif() endif() diff --git a/miniwin/include/miniwin/miniwind3d.h b/miniwin/include/miniwin/miniwind3d.h new file mode 100644 index 00000000..aea2e25c --- /dev/null +++ b/miniwin/include/miniwin/miniwind3d.h @@ -0,0 +1,10 @@ +#pragma once + +DEFINE_GUID(IID_IDirect3DMiniwin, 0xf8a97f2d, 0x9b3a, 0x4f1c, 0x9e, 0x8d, 0x6a, 0x5b, 0x4c, 0x3d, 0x2e, 0x1f); + +struct IDirect3DMiniwin : virtual public IUnknown { + virtual HRESULT RequestMSAA(DWORD msaaSamples) = 0; + virtual DWORD GetMSAASamples() const = 0; + virtual HRESULT RequestAnisotropic(float anisotropic) = 0; + virtual float GetAnisotropic() const = 0; +}; diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index b830fa6d..0ce14701 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -16,7 +16,7 @@ static_assert(sizeof(GL11_BridgeTexCoord) == sizeof(TexCoord), "GL11_BridgeTexCo static_assert(sizeof(GL11_BridgeSceneLight) == sizeof(SceneLight), "GL11_BridgeSceneLight is wrong size"); static_assert(sizeof(GL11_BridgeSceneVertex) == sizeof(D3DRMVERTEX), "GL11_BridgeSceneVertex is wrong size"); -Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height) +Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height, DWORD msaaSamples) { // We have to reset the attributes here after having enumerated the // OpenGL ES 2.0 renderer, or else SDL gets very confused by SDL_GL_DEPTH_SIZE @@ -30,6 +30,11 @@ Direct3DRMRenderer* OpenGL1Renderer::Create(DWORD width, DWORD height) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + if (msaaSamples > 1) { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaaSamples); + } + if (!DDWindow) { SDL_Log("No window handler"); return nullptr; diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles3/renderer.cpp similarity index 73% rename from miniwin/src/d3drm/backends/opengles2/renderer.cpp rename to miniwin/src/d3drm/backends/opengles3/renderer.cpp index e1c86a62..98cf6db5 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles3/renderer.cpp @@ -1,8 +1,8 @@ -#include "d3drmrenderer_opengles2.h" +#include "d3drmrenderer_opengles3.h" #include "meshutils.h" -#include #include +#include #include #include #include @@ -15,20 +15,29 @@ static GLuint CompileShader(GLenum type, const char* source) GLint success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { + GLint logLength = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + std::vector log(logLength); + glGetShaderInfoLog(shader, logLength, nullptr, log.data()); + SDL_Log("Shader compile error: %s", log.data()); + } + else { + SDL_Log("CompileShader (%s)", SDL_GetError()); + } glDeleteShader(shader); - SDL_Log("CompileShader (%s)", SDL_GetError()); return 0; } return shader; } -struct SceneLightGLES2 { +struct SceneLightGLES3 { float color[4]; float position[4]; float direction[4]; }; -Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) +Direct3DRMRenderer* OpenGLES3Renderer::Create(DWORD width, DWORD height, DWORD msaaSamples, float anisotropic) { // We have to reset the attributes here after having enumerated the // OpenGL ES 2.0 renderer, or else SDL gets very confused by SDL_GL_DEPTH_SIZE @@ -37,7 +46,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) // But ResetAttributes resets it to 16. SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); if (!DDWindow) { @@ -61,18 +70,20 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) glCullFace(GL_BACK); glFrontFace(GL_CW); - const char* vertexShaderSource = R"( - attribute vec3 a_position; - attribute vec3 a_normal; - attribute vec2 a_texCoord; + const char* vertexShaderSource = R"(#version 300 es + precision highp float; + + in vec3 a_position; + in vec3 a_normal; + in vec2 a_texCoord; uniform mat4 u_modelViewMatrix; uniform mat3 u_normalMatrix; uniform mat4 u_projectionMatrix; - varying vec3 v_viewPos; - varying vec3 v_normal; - varying vec2 v_texCoord; + out vec3 v_viewPos; + out vec3 v_normal; + out vec2 v_texCoord; void main() { vec4 viewPos = u_modelViewMatrix * vec4(a_position, 1.0); @@ -83,7 +94,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) } )"; - const char* fragmentShaderSource = R"( + const char* fragmentShaderSource = R"(#version 300 es precision mediump float; struct SceneLight { @@ -95,22 +106,22 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) uniform SceneLight u_lights[3]; uniform int u_lightCount; - varying vec3 v_viewPos; - varying vec3 v_normal; - varying vec2 v_texCoord; + in vec3 v_viewPos; + in vec3 v_normal; + in vec2 v_texCoord; uniform float u_shininess; uniform vec4 u_color; - uniform int u_useTexture; + uniform bool u_useTexture; uniform sampler2D u_texture; + out vec4 fragColor; + void main() { vec3 diffuse = vec3(0.0); vec3 specular = vec3(0.0); - for (int i = 0; i < 3; ++i) { - if (i >= u_lightCount) break; - + for (int i = 0; i < u_lightCount; ++i) { vec3 lightColor = u_lights[i].color.rgb; if (u_lights[i].position.w == 0.0 && u_lights[i].direction.w == 0.0) { @@ -134,7 +145,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) // Specular if (u_shininess > 0.0 && u_lights[i].direction.w == 1.0) { - vec3 viewVec = normalize(-v_viewPos); // Assuming camera at origin + vec3 viewVec = normalize(-v_viewPos); vec3 H = normalize(lightVec + viewVec); float dotNH = max(dot(v_normal, H), 0.0); float spec = pow(dotNH, u_shininess); @@ -145,13 +156,13 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) vec4 finalColor = u_color; finalColor.rgb = clamp(diffuse * u_color.rgb + specular, 0.0, 1.0); - if (u_useTexture != 0) { - vec4 texel = texture2D(u_texture, v_texCoord); + if (u_useTexture) { + vec4 texel = texture(u_texture, v_texCoord); finalColor.rgb = clamp(texel.rgb * finalColor.rgb, 0.0, 1.0); finalColor.a = texel.a; } - gl_FragColor = finalColor; + fragColor = finalColor; } )"; @@ -168,12 +179,12 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) glDeleteShader(vs); glDeleteShader(fs); - return new OpenGLES2Renderer(width, height, context, shaderProgram); + return new OpenGLES3Renderer(width, height, msaaSamples, anisotropic, context, shaderProgram); } -GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = false) +GLES3MeshCacheEntry OpenGLES3Renderer::GLES3UploadMesh(const MeshGroup& meshGroup, bool forceUV) { - GLES2MeshCacheEntry cache{&meshGroup, meshGroup.version}; + GLES3MeshCacheEntry cache{&meshGroup, meshGroup.version}; cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT; @@ -211,18 +222,27 @@ GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = f std::vector normals(vertices.size()); std::transform(vertices.begin(), vertices.end(), normals.begin(), [](const D3DRMVERTEX& v) { return v.normal; }); + glGenVertexArrays(1, &cache.vao); + glBindVertexArray(cache.vao); + glGenBuffers(1, &cache.vboPositions); glBindBuffer(GL_ARRAY_BUFFER, cache.vboPositions); glBufferData(GL_ARRAY_BUFFER, positions.size() * sizeof(D3DVECTOR), positions.data(), GL_STATIC_DRAW); + glEnableVertexAttribArray(m_posLoc); + glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glGenBuffers(1, &cache.vboNormals); glBindBuffer(GL_ARRAY_BUFFER, cache.vboNormals); glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(D3DVECTOR), normals.data(), GL_STATIC_DRAW); + glEnableVertexAttribArray(m_normLoc); + glVertexAttribPointer(m_normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); if (meshGroup.texture || forceUV) { glGenBuffers(1, &cache.vboTexcoords); glBindBuffer(GL_ARRAY_BUFFER, cache.vboTexcoords); glBufferData(GL_ARRAY_BUFFER, texcoords.size() * sizeof(TexCoord), texcoords.data(), GL_STATIC_DRAW); + glEnableVertexAttribArray(m_texLoc); + glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); } glGenBuffers(1, &cache.ibo); @@ -234,10 +254,12 @@ GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = f GL_STATIC_DRAW ); + glBindVertexArray(0); + return cache; } -bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) +bool OpenGLES3Renderer::UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) { SDL_Surface* surf = source; if (source->format != SDL_PIXELFORMAT_RGBA32) { @@ -262,11 +284,8 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - if (strstr((const char*) glGetString(GL_EXTENSIONS), "GL_EXT_texture_filter_anisotropic")) { - GLfloat maxAniso = 0.0f; - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); - GLfloat desiredAniso = fminf(8.0f, maxAniso); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, desiredAniso); + if (m_anisotropic > 1.0f) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_anisotropic); } glGenerateMipmap(GL_TEXTURE_2D); } @@ -278,12 +297,52 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) return true; } -OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram) - : m_context(context), m_shaderProgram(shaderProgram) +OpenGLES3Renderer::OpenGLES3Renderer( + DWORD width, + DWORD height, + DWORD msaaSamples, + float anisotropic, + SDL_GLContext context, + GLuint shaderProgram +) + : m_context(context), m_shaderProgram(shaderProgram), m_msaa(msaaSamples), m_anisotropic(anisotropic) { glGenFramebuffers(1, &m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + GLint maxSamples; + glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); + if (m_msaa > maxSamples) { + m_msaa = maxSamples; + } + SDL_Log( + "MSAA is %s. Requested samples: %d, active samples: %d, max samples: %d", + m_msaa > 1 ? "on" : "off", + msaaSamples, + m_msaa, + maxSamples + ); + + if (m_msaa > 1) { + glGenFramebuffers(1, &m_resolveFBO); + } + + bool anisoAvailable = SDL_GL_ExtensionSupported("GL_EXT_texture_filter_anisotropic"); + GLfloat maxAniso = 0.0f; + if (anisoAvailable) { + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); + } + if (m_anisotropic > maxAniso) { + m_anisotropic = maxAniso; + } + SDL_Log( + "Anisotropic is %s. Requested: %f, active: %f, max aniso: %f", + m_anisotropic > 1.0f ? "on" : "off", + anisotropic, + m_anisotropic, + maxAniso + ); + m_virtualWidth = width; m_virtualHeight = height; ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f}; @@ -310,14 +369,6 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co } SDL_DestroySurface(dummySurface); - m_uiMesh.vertices = { - {{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}}, - {{1.0f, 0.0f, 0.0f}, {0, 0, -1}, {1.0f, 0.0f}}, - {{1.0f, 1.0f, 0.0f}, {0, 0, -1}, {1.0f, 1.0f}}, - {{0.0f, 1.0f, 0.0f}, {0, 0, -1}, {0.0f, 1.0f}} - }; - m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; - m_uiMeshCache = GLES2UploadMesh(m_uiMesh, true); m_posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); m_normLoc = glGetAttribLocation(m_shaderProgram, "a_normal"); m_texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); @@ -336,17 +387,35 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co m_normalMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_normalMatrix"); m_projectionMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"); + m_uiMesh.vertices = { + {{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}}, + {{1.0f, 0.0f, 0.0f}, {0, 0, -1}, {1.0f, 0.0f}}, + {{1.0f, 1.0f, 0.0f}, {0, 0, -1}, {1.0f, 1.0f}}, + {{0.0f, 1.0f, 0.0f}, {0, 0, -1}, {0.0f, 1.0f}} + }; + m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; + m_uiMeshCache = GLES3UploadMesh(m_uiMesh, true); + glUseProgram(m_shaderProgram); } -OpenGLES2Renderer::~OpenGLES2Renderer() +OpenGLES3Renderer::~OpenGLES3Renderer() { SDL_DestroySurface(m_renderedImage); + glDeleteTextures(1, &m_dummyTexture); glDeleteProgram(m_shaderProgram); + glDeleteRenderbuffers(1, &m_colorTarget); + glDeleteRenderbuffers(1, &m_depthTarget); + glDeleteFramebuffers(1, &m_fbo); + if (m_msaa > 1) { + glDeleteRenderbuffers(1, &m_resolveColor); + glDeleteFramebuffers(1, &m_resolveFBO); + } + SDL_GL_DestroyContext(m_context); } -void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count) +void OpenGLES3Renderer::PushLights(const SceneLight* lightsArray, size_t count) { if (count > 3) { SDL_Log("Unsupported number of lights (%d)", static_cast(count)); @@ -356,21 +425,21 @@ void OpenGLES2Renderer::PushLights(const SceneLight* lightsArray, size_t count) m_lights.assign(lightsArray, lightsArray + count); } -void OpenGLES2Renderer::SetFrustumPlanes(const Plane* frustumPlanes) +void OpenGLES3Renderer::SetFrustumPlanes(const Plane* frustumPlanes) { } -void OpenGLES2Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) +void OpenGLES3Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) { memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D)); } struct TextureDestroyContextGLS2 { - OpenGLES2Renderer* renderer; + OpenGLES3Renderer* renderer; Uint32 textureId; }; -void OpenGLES2Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture) +void OpenGLES3Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture) { auto* ctx = new TextureDestroyContextGLS2{this, id}; texture->AddDestroyCallback( @@ -388,7 +457,7 @@ void OpenGLES2Renderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* ); } -Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) +Uint32 OpenGLES3Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, float scaleX, float scaleY) { SDL_GL_MakeCurrent(DDWindow, m_context); auto texture = static_cast(iTexture); @@ -432,42 +501,43 @@ Uint32 OpenGLES2Renderer::GetTextureId(IDirect3DRMTexture* iTexture, bool isUI, return (Uint32) (m_textures.size() - 1); } -struct GLES2MeshDestroyContext { - OpenGLES2Renderer* renderer; +struct GLES3MeshDestroyContext { + OpenGLES3Renderer* renderer; Uint32 id; }; -void OpenGLES2Renderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh) +void OpenGLES3Renderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh) { - auto* ctx = new GLES2MeshDestroyContext{this, id}; + auto* ctx = new GLES3MeshDestroyContext{this, id}; mesh->AddDestroyCallback( [](IDirect3DRMObject*, void* arg) { - auto* ctx = static_cast(arg); + auto* ctx = static_cast(arg); auto& cache = ctx->renderer->m_meshs[ctx->id]; cache.meshGroup = nullptr; glDeleteBuffers(1, &cache.vboPositions); glDeleteBuffers(1, &cache.vboNormals); glDeleteBuffers(1, &cache.vboTexcoords); glDeleteBuffers(1, &cache.ibo); + glDeleteVertexArrays(1, &cache.vao); delete ctx; }, ctx ); } -Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) +Uint32 OpenGLES3Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) { for (Uint32 i = 0; i < m_meshs.size(); ++i) { auto& cache = m_meshs[i]; if (cache.meshGroup == meshGroup) { if (cache.version != meshGroup->version) { - cache = std::move(GLES2UploadMesh(*meshGroup)); + cache = std::move(GLES3UploadMesh(*meshGroup)); } return i; } } - auto newCache = GLES2UploadMesh(*meshGroup); + auto newCache = GLES3UploadMesh(*meshGroup); for (Uint32 i = 0; i < m_meshs.size(); ++i) { auto& cache = m_meshs[i]; @@ -483,7 +553,7 @@ Uint32 OpenGLES2Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* mesh return (Uint32) (m_meshs.size() - 1); } -HRESULT OpenGLES2Renderer::BeginFrame() +HRESULT OpenGLES3Renderer::BeginFrame() { SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; @@ -495,7 +565,7 @@ HRESULT OpenGLES2Renderer::BeginFrame() glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); - SceneLightGLES2 lightData[3]; + SceneLightGLES3 lightData[3]; int lightCount = std::min(static_cast(m_lights.size()), 3); for (int i = 0; i < lightCount; ++i) { @@ -525,14 +595,14 @@ HRESULT OpenGLES2Renderer::BeginFrame() return DD_OK; } -void OpenGLES2Renderer::EnableTransparency() +void OpenGLES3Renderer::EnableTransparency() { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(GL_FALSE); } -void OpenGLES2Renderer::SubmitDraw( +void OpenGLES3Renderer::SubmitDraw( DWORD meshId, const D3DRMMATRIX4D& modelViewMatrix, const D3DRMMATRIX4D& worldMatrix, @@ -570,28 +640,12 @@ void OpenGLES2Renderer::SubmitDraw( glUniform1i(m_textureLoc, 0); } - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboPositions); - glEnableVertexAttribArray(m_posLoc); - glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboNormals); - glEnableVertexAttribArray(m_normLoc); - glVertexAttribPointer(m_normLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - if (appearance.textureId != NO_TEXTURE_ID) { - glBindBuffer(GL_ARRAY_BUFFER, mesh.vboTexcoords); - glEnableVertexAttribArray(m_texLoc); - glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo); + glBindVertexArray(mesh.vao); glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr); - - glDisableVertexAttribArray(m_normLoc); - glDisableVertexAttribArray(m_texLoc); + glBindVertexArray(0); } -HRESULT OpenGLES2Renderer::FinalizeFrame() +HRESULT OpenGLES3Renderer::FinalizeFrame() { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -599,7 +653,7 @@ HRESULT OpenGLES2Renderer::FinalizeFrame() return DD_OK; } -void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform) +void OpenGLES3Renderer::Resize(int width, int height, const ViewportTransform& viewportTransform) { SDL_GL_MakeCurrent(DDWindow, m_context); m_width = width; @@ -610,37 +664,65 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v } m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); + if (m_colorTarget) { + glDeleteRenderbuffers(1, &m_colorTarget); + m_colorTarget = 0; + } + if (m_resolveColor) { + glDeleteRenderbuffers(1, &m_resolveColor); + m_resolveColor = 0; + } + if (m_depthTarget) { + glDeleteRenderbuffers(1, &m_depthTarget); + m_depthTarget = 0; + } + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // Create color texture - glGenTextures(1, &m_colorTarget); - glBindTexture(GL_TEXTURE_2D, m_colorTarget); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorTarget, 0); + glGenRenderbuffers(1, &m_colorTarget); + glBindRenderbuffer(GL_RENDERBUFFER, m_colorTarget); + if (m_msaa > 1) { + glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaa, GL_RGBA8, width, height); + } + else { + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); + } + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorTarget); // Create depth renderbuffer glGenRenderbuffers(1, &m_depthTarget); glBindRenderbuffer(GL_RENDERBUFFER, m_depthTarget); - - if (SDL_GL_ExtensionSupported("GL_OES_depth24")) { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, width, height); - } - else if (SDL_GL_ExtensionSupported("GL_OES_depth32")) { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32_OES, width, height); + if (m_msaa > 1) { + glRenderbufferStorageMultisample(GL_RENDERBUFFER, m_msaa, GL_DEPTH_COMPONENT24, width, height); } else { - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); } glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthTarget); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + SDL_Log("FBO incomplete: 0x%X", status); + } + + if (m_msaa > 1) { + glBindFramebuffer(GL_FRAMEBUFFER, m_resolveFBO); + glGenRenderbuffers(1, &m_resolveColor); + glBindRenderbuffer(GL_RENDERBUFFER, m_resolveColor); + glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_resolveColor); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + SDL_Log("Resolve FBO incomplete: 0x%X", status); + } + } + + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glViewport(0, 0, m_width, m_height); } -void OpenGLES2Renderer::Clear(float r, float g, float b) +void OpenGLES3Renderer::Clear(float r, float g, float b) { SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; @@ -653,71 +735,33 @@ void OpenGLES2Renderer::Clear(float r, float g, float b) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } -void OpenGLES2Renderer::Flip() +void OpenGLES3Renderer::Flip() { SDL_GL_MakeCurrent(DDWindow, m_context); if (!m_dirty) { return; } - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - glDisable(GL_DEPTH_TEST); - glFrontFace(GL_CCW); - glDepthMask(GL_FALSE); - - glUniform4f(m_colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); - glUniform1f(m_shinLoc, 0.0f); - - float ambient[] = {1.0f, 1.0f, 1.0f, 1.0f}; - float blank[] = {0.0f, 0.0f, 0.0f, 0.0f}; - glUniform4fv(u_lightLocs[0][0], 1, ambient); - glUniform4fv(u_lightLocs[0][1], 1, blank); - glUniform4fv(u_lightLocs[0][2], 1, blank); - glUniform1i(m_lightCountLoc, 1); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_colorTarget); - glUniform1i(m_textureLoc, 0); - glUniform1i(m_useTextureLoc, 1); - - D3DRMMATRIX4D projection; - D3DRMMATRIX4D modelViewMatrix = { - {(float) m_width, 0.0f, 0.0f, 0.0f}, - {0.0f, (float) -m_height, 0.0f, 0.0f}, - {0.0f, 0.0f, 1.0f, 0.0f}, - {0.0f, (float) m_height, 0.0f, 1.0f} - }; - glUniformMatrix4fv(m_modelViewMatrixLoc, 1, GL_FALSE, &modelViewMatrix[0][0]); - Matrix3x3 identity = {{1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}}; - glUniformMatrix3fv(m_normalMatrixLoc, 1, GL_FALSE, &identity[0][0]); - CreateOrthographicProjection((float) m_width, (float) m_height, projection); - glUniformMatrix4fv(m_projectionMatrixLoc, 1, GL_FALSE, &projection[0][0]); + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + // This is a workaround for what is (presumably) a driver bug in some WebGL environments (Android Chrome) + // During transitions, the screen would sometimes (randomly) briefly be cleared / flicker black when using + // glBlitFramebuffer. Any write to the back buffer before that fixes this issue. The following should have minimal + // performance impact. + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, 1, 1); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboPositions); - glEnableVertexAttribArray(m_posLoc); - glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboTexcoords); - glEnableVertexAttribArray(m_texLoc); - glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiMeshCache.ibo); - glDrawElements(GL_TRIANGLES, static_cast(m_uiMeshCache.indices.size()), GL_UNSIGNED_SHORT, nullptr); - - glDisableVertexAttribArray(m_texLoc); + glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); SDL_GL_SwapWindow(DDWindow); - glFrontFace(GL_CW); m_dirty = false; } -void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect, FColor color) +void OpenGLES3Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, const SDL_Rect& dstRect, FColor color) { SDL_GL_MakeCurrent(DDWindow, m_context); m_dirty = true; @@ -739,7 +783,7 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c SDL_Rect expandedDstRect; if (textureId != NO_TEXTURE_ID) { - const GLES2TextureCacheEntry& texture = m_textures[textureId]; + const GLES3TextureCacheEntry& texture = m_textures[textureId]; float scaleX = static_cast(dstRect.w) / srcRect.w; float scaleY = static_cast(dstRect.h) / srcRect.h; expandedDstRect = { @@ -790,26 +834,27 @@ void OpenGLES2Renderer::Draw2DImage(Uint32 textureId, const SDL_Rect& srcRect, c static_cast(std::round(dstRect.h * m_viewportTransform.scale)) ); - glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboPositions); - glEnableVertexAttribArray(m_posLoc); - glVertexAttribPointer(m_posLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ARRAY_BUFFER, m_uiMeshCache.vboTexcoords); - glEnableVertexAttribArray(m_texLoc); - glVertexAttribPointer(m_texLoc, 2, GL_FLOAT, GL_FALSE, 0, nullptr); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_uiMeshCache.ibo); + glBindVertexArray(m_uiMeshCache.vao); glDrawElements(GL_TRIANGLES, static_cast(m_uiMeshCache.indices.size()), GL_UNSIGNED_SHORT, nullptr); + glBindVertexArray(0); - glDisableVertexAttribArray(m_texLoc); glDisable(GL_SCISSOR_TEST); } -void OpenGLES2Renderer::Download(SDL_Surface* target) +void OpenGLES3Renderer::Download(SDL_Surface* target) { glFinish(); - glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + if (m_msaa > 1) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolveFBO); + glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBindFramebuffer(GL_FRAMEBUFFER, m_resolveFBO); + } + else { + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + } + glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels); SDL_Rect srcRect = { @@ -839,7 +884,7 @@ void OpenGLES2Renderer::Download(SDL_Surface* target) SDL_DestroySurface(bufferClone); } -void OpenGLES2Renderer::SetDither(bool dither) +void OpenGLES3Renderer::SetDither(bool dither) { if (dither) { glEnable(GL_DITHER); diff --git a/miniwin/src/d3drm/d3drm.cpp b/miniwin/src/d3drm/d3drm.cpp index 7328d21c..3b4d5c9d 100644 --- a/miniwin/src/d3drm/d3drm.cpp +++ b/miniwin/src/d3drm/d3drm.cpp @@ -132,7 +132,11 @@ HRESULT Direct3DRMImpl::CreateDeviceFromSurface( DDSDesc.dwSize = sizeof(DDSURFACEDESC); surface->GetSurfaceDesc(&DDSDesc); - DDRenderer = CreateDirect3DRMRenderer(DDSDesc, guid); + IDirect3DMiniwin* miniwind3d = nullptr; + dd->QueryInterface(IID_IDirect3DMiniwin, (void**) &miniwind3d); + SDL_assert(miniwind3d); + + DDRenderer = CreateDirect3DRMRenderer(miniwind3d, DDSDesc, guid); if (!DDRenderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized"); return E_NOINTERFACE; diff --git a/miniwin/src/d3drm/d3drmdevice.cpp b/miniwin/src/d3drm/d3drmdevice.cpp index e3190692..2b062d50 100644 --- a/miniwin/src/d3drm/d3drmdevice.cpp +++ b/miniwin/src/d3drm/d3drmdevice.cpp @@ -185,7 +185,8 @@ bool Direct3DRMDevice2Impl::ConvertEventToRenderCoordinates(SDL_Event* event) } case SDL_EVENT_FINGER_MOTION: case SDL_EVENT_FINGER_DOWN: - case SDL_EVENT_FINGER_UP: { + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_CANCELED: { float x = (event->tfinger.x * m_windowWidth - m_viewportTransform.offsetX) / m_viewportTransform.scale; float y = (event->tfinger.y * m_windowHeight - m_viewportTransform.offsetY) / m_viewportTransform.scale; event->tfinger.x = x / m_virtualWidth; diff --git a/miniwin/src/d3drm/d3drmrenderer.cpp b/miniwin/src/d3drm/d3drmrenderer.cpp index ca9b5541..8fe210b5 100644 --- a/miniwin/src/d3drm/d3drmrenderer.cpp +++ b/miniwin/src/d3drm/d3drmrenderer.cpp @@ -2,8 +2,8 @@ #ifdef USE_OPENGL1 #include "d3drmrenderer_opengl1.h" #endif -#ifdef USE_OPENGLES2 -#include "d3drmrenderer_opengles2.h" +#ifdef USE_OPENGLES3 +#include "d3drmrenderer_opengles3.h" #endif #ifdef USE_CITRO3D #include "d3drmrenderer_citro3d.h" @@ -18,7 +18,11 @@ #include "d3drmrenderer_software.h" #endif -Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const GUID* guid) +Direct3DRMRenderer* CreateDirect3DRMRenderer( + const IDirect3DMiniwin* d3d, + const DDSURFACEDESC& DDSDesc, + const GUID* guid +) { #ifdef USE_SDL_GPU if (SDL_memcmp(guid, &SDL3_GPU_GUID, sizeof(GUID)) == 0) { @@ -30,14 +34,19 @@ Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const return new Direct3DRMSoftwareRenderer(DDSDesc.dwWidth, DDSDesc.dwHeight); } #endif -#ifdef USE_OPENGLES2 - if (SDL_memcmp(guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) { - return OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); +#ifdef USE_OPENGLES3 + if (SDL_memcmp(guid, &OpenGLES3_GUID, sizeof(GUID)) == 0) { + return OpenGLES3Renderer::Create( + DDSDesc.dwWidth, + DDSDesc.dwHeight, + d3d->GetMSAASamples(), + d3d->GetAnisotropic() + ); } #endif #ifdef USE_OPENGL1 if (SDL_memcmp(guid, &OpenGL1_GUID, sizeof(GUID)) == 0) { - return OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); + return OpenGL1Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight, d3d->GetMSAASamples()); } #endif #ifdef USE_CITRO3D @@ -53,16 +62,16 @@ Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const return nullptr; } -void Direct3DRMRenderer_EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) +void Direct3DRMRenderer_EnumDevices(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICESCALLBACK cb, void* ctx) { #ifdef USE_SDL_GPU Direct3DRMSDL3GPU_EnumDevice(cb, ctx); #endif -#ifdef USE_OPENGLES2 - OpenGLES2Renderer_EnumDevice(cb, ctx); +#ifdef USE_OPENGLES3 + OpenGLES3Renderer_EnumDevice(d3d, cb, ctx); #endif #ifdef USE_OPENGL1 - OpenGL1Renderer_EnumDevice(cb, ctx); + OpenGL1Renderer_EnumDevice(d3d, cb, ctx); #endif #ifdef USE_CITRO3D Citro3DRenderer_EnumDevice(cb, ctx); diff --git a/miniwin/src/ddraw/ddraw.cpp b/miniwin/src/ddraw/ddraw.cpp index 264ceeb1..b28a105b 100644 --- a/miniwin/src/ddraw/ddraw.cpp +++ b/miniwin/src/ddraw/ddraw.cpp @@ -29,6 +29,11 @@ HRESULT DirectDrawImpl::QueryInterface(const GUID& riid, void** ppvObject) *ppvObject = static_cast(this); return S_OK; } + if (SDL_memcmp(&riid, &IID_IDirect3DMiniwin, sizeof(GUID)) == 0) { + this->IUnknown::AddRef(); + *ppvObject = static_cast(this); + return S_OK; + } MINIWIN_NOT_IMPLEMENTED(); return E_NOINTERFACE; } @@ -220,7 +225,7 @@ void EnumDevice( HRESULT DirectDrawImpl::EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) { - Direct3DRMRenderer_EnumDevices(cb, ctx); + Direct3DRMRenderer_EnumDevices(this, cb, ctx); return S_OK; } @@ -317,7 +322,7 @@ HRESULT DirectDrawImpl::CreateDevice( DDSDesc.dwSize = sizeof(DDSURFACEDESC); pBackBuffer->GetSurfaceDesc(&DDSDesc); - DDRenderer = CreateDirect3DRMRenderer(DDSDesc, &guid); + DDRenderer = CreateDirect3DRMRenderer(this, DDSDesc, &guid); if (!DDRenderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Device GUID not recognized"); return E_NOINTERFACE; diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index 85b2d1b9..7c19a8b4 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -3,6 +3,7 @@ #include "d3drmmesh_impl.h" #include "mathutils.h" #include "miniwin/d3drm.h" +#include "miniwin/miniwind3d.h" #include "miniwin/miniwindevice.h" #include "structs.h" @@ -61,5 +62,9 @@ class Direct3DRMRenderer : public IDirect3DDevice2 { ViewportTransform m_viewportTransform; }; -Direct3DRMRenderer* CreateDirect3DRMRenderer(const DDSURFACEDESC& DDSDesc, const GUID* guid); -void Direct3DRMRenderer_EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx); +Direct3DRMRenderer* CreateDirect3DRMRenderer( + const IDirect3DMiniwin* d3d, + const DDSURFACEDESC& DDSDesc, + const GUID* guid +); +void Direct3DRMRenderer_EnumDevices(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICESCALLBACK cb, void* ctx); diff --git a/miniwin/src/internal/d3drmrenderer_opengl1.h b/miniwin/src/internal/d3drmrenderer_opengl1.h index 3d92b663..651b61d3 100644 --- a/miniwin/src/internal/d3drmrenderer_opengl1.h +++ b/miniwin/src/internal/d3drmrenderer_opengl1.h @@ -11,7 +11,7 @@ DEFINE_GUID(OpenGL1_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x class OpenGL1Renderer : public Direct3DRMRenderer { public: - static Direct3DRMRenderer* Create(DWORD width, DWORD height); + static Direct3DRMRenderer* Create(DWORD width, DWORD height, DWORD msaaSamples); OpenGL1Renderer(DWORD width, DWORD height, SDL_GLContext context); ~OpenGL1Renderer() override; @@ -54,10 +54,10 @@ class OpenGL1Renderer : public Direct3DRMRenderer { ViewportTransform m_viewportTransform; }; -inline static void OpenGL1Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) +inline static void OpenGL1Renderer_EnumDevice(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICESCALLBACK cb, void* ctx) { #ifndef __PSP__ - Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480); + Direct3DRMRenderer* device = OpenGL1Renderer::Create(640, 480, d3d->GetMSAASamples()); if (!device) { return; } diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles3.h similarity index 69% rename from miniwin/src/internal/d3drmrenderer_opengles2.h rename to miniwin/src/internal/d3drmrenderer_opengles3.h index d4985f32..e3f3f59d 100644 --- a/miniwin/src/internal/d3drmrenderer_opengles2.h +++ b/miniwin/src/internal/d3drmrenderer_opengles3.h @@ -4,13 +4,13 @@ #include "d3drmtexture_impl.h" #include "ddraw_impl.h" -#include +#include #include #include -DEFINE_GUID(OpenGLES2_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04); +DEFINE_GUID(OpenGLES3_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04); -struct GLES2TextureCacheEntry { +struct GLES3TextureCacheEntry { IDirect3DRMTexture* texture; Uint32 version; GLuint glTextureId; @@ -18,7 +18,7 @@ struct GLES2TextureCacheEntry { uint16_t height; }; -struct GLES2MeshCacheEntry { +struct GLES3MeshCacheEntry { const MeshGroup* meshGroup; int version; bool flat; @@ -28,13 +28,21 @@ struct GLES2MeshCacheEntry { GLuint vboNormals; GLuint vboTexcoords; GLuint ibo; + GLuint vao; }; -class OpenGLES2Renderer : public Direct3DRMRenderer { +class OpenGLES3Renderer : public Direct3DRMRenderer { public: - static Direct3DRMRenderer* Create(DWORD width, DWORD height); - OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram); - ~OpenGLES2Renderer() override; + static Direct3DRMRenderer* Create(DWORD width, DWORD height, DWORD msaaSamples, float anisotropic); + OpenGLES3Renderer( + DWORD width, + DWORD height, + DWORD msaaSamples, + float anisotropic, + SDL_GLContext context, + GLuint shaderProgram + ); + ~OpenGLES3Renderer() override; void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; @@ -62,18 +70,24 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { private: void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); + GLES3MeshCacheEntry GLES3UploadMesh(const MeshGroup& meshGroup, bool forceUV = false); + bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI); MeshGroup m_uiMesh; - GLES2MeshCacheEntry m_uiMeshCache; - std::vector m_textures; - std::vector m_meshs; + GLES3MeshCacheEntry m_uiMeshCache; + std::vector m_textures; + std::vector m_meshs; D3DRMMATRIX4D m_projection; SDL_Surface* m_renderedImage = nullptr; bool m_dirty = false; std::vector m_lights; SDL_GLContext m_context; + uint32_t m_msaa; + float m_anisotropic; GLuint m_fbo; + GLuint m_resolveFBO; GLuint m_colorTarget; + GLuint m_resolveColor = 0; GLuint m_depthTarget; GLuint m_shaderProgram; GLuint m_dummyTexture; @@ -92,35 +106,25 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { ViewportTransform m_viewportTransform; }; -inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) +inline static void OpenGLES3Renderer_EnumDevice(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICESCALLBACK cb, void* ctx) { - Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480); + Direct3DRMRenderer* device = OpenGLES3Renderer::Create(640, 480, d3d->GetMSAASamples(), d3d->GetAnisotropic()); if (!device) { return; } + delete device; + D3DDEVICEDESC halDesc = {}; halDesc.dcmColorModel = D3DCOLOR_RGB; halDesc.dwFlags = D3DDD_DEVICEZBUFFERBITDEPTH; - halDesc.dwDeviceZBufferBitDepth = DDBD_16; + halDesc.dwDeviceZBufferBitDepth = DDBD_24; halDesc.dwDeviceRenderBitDepth = DDBD_32; halDesc.dpcTriCaps.dwTextureCaps = D3DPTEXTURECAPS_PERSPECTIVE; halDesc.dpcTriCaps.dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND; halDesc.dpcTriCaps.dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR; - const char* extensions = (const char*) glGetString(GL_EXTENSIONS); - if (extensions) { - if (strstr(extensions, "GL_OES_depth24")) { - halDesc.dwDeviceZBufferBitDepth |= DDBD_24; - } - if (strstr(extensions, "GL_OES_depth32")) { - halDesc.dwDeviceZBufferBitDepth |= DDBD_32; - } - } - - delete device; - D3DDEVICEDESC helDesc = {}; - EnumDevice(cb, ctx, "OpenGL ES 2.0 HAL", &halDesc, &helDesc, OpenGLES2_GUID); + EnumDevice(cb, ctx, "OpenGL ES 3.0 HAL", &halDesc, &helDesc, OpenGLES3_GUID); } diff --git a/miniwin/src/internal/ddraw_impl.h b/miniwin/src/internal/ddraw_impl.h index 4adfb4a5..0da2d883 100644 --- a/miniwin/src/internal/ddraw_impl.h +++ b/miniwin/src/internal/ddraw_impl.h @@ -4,6 +4,7 @@ #include "framebuffer_impl.h" #include "miniwin/d3d.h" #include "miniwin/ddraw.h" +#include "miniwin/miniwind3d.h" #include @@ -15,7 +16,7 @@ inline static SDL_Rect ConvertRect(const RECT* r) return {r->left, r->top, r->right - r->left, r->bottom - r->top}; } -struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 { +struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2, public IDirect3DMiniwin { // IUnknown interface HRESULT QueryInterface(const GUID& riid, void** ppvObject) override; // IDirectDraw interface @@ -45,11 +46,26 @@ struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2 { HRESULT CreateDevice(const GUID& guid, IDirectDrawSurface* pBackBuffer, IDirect3DDevice2** ppDirect3DDevice) override; HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override; + // IDirect3DMiniwin interface + HRESULT RequestMSAA(DWORD msaaSamples) override + { + m_msaaSamples = msaaSamples; + return DD_OK; + } + DWORD GetMSAASamples() const override { return m_msaaSamples; } + HRESULT RequestAnisotropic(float anisotropic) override + { + m_anisotropic = anisotropic; + return DD_OK; + } + float GetAnisotropic() const override { return m_anisotropic; } private: FrameBufferImpl* m_frameBuffer; int m_virtualWidth = 0; int m_virtualHeight = 0; + DWORD m_msaaSamples = 0; + float m_anisotropic = 0.0f; }; HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);