Merge remote-tracking branch 'upstream'
2
.gitattributes
vendored
@ -9,3 +9,5 @@
|
||||
**/*.png binary
|
||||
**/*.svg text eol=lf
|
||||
**/*.desktop text eol=lf
|
||||
assets/widescreen/** filter=lfs diff=lfs merge=lfs -text
|
||||
assets/hdmusic/** filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
66
.github/workflows/ci.yml
vendored
@ -34,7 +34,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- { name: 'Linux', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: true, linux: true, werror: true, clang-tidy: true }
|
||||
- { name: 'Linux', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: true, linux: true, werror: true, clang-tidy: true, build-assets: true }
|
||||
- { name: 'Linux (Debug)', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: true, linux: true, werror: true, clang-tidy: true, debug: true }
|
||||
- { name: 'MSVC (x86)', os: 'windows-latest', generator: 'Ninja', dx5: true, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64_x86' }
|
||||
- { name: 'MSVC (x64)', os: 'windows-latest', generator: 'Ninja', dx5: false, config: true, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64' }
|
||||
@ -43,10 +43,11 @@ jobs:
|
||||
- { name: 'msys2 mingw32', os: 'windows-latest', generator: 'Ninja', dx5: false, config: false, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw32', msys-env: 'mingw-w64-i686', shell: 'msys2 {0}' }
|
||||
- { name: 'msys2 mingw64', os: 'windows-latest', generator: 'Ninja', dx5: false, config: true, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw64', msys-env: 'mingw-w64-x86_64', shell: 'msys2 {0}' }
|
||||
- { name: 'macOS', os: 'macos-latest', generator: 'Ninja', dx5: false, config: true, brew: true, werror: true, clang-tidy: false }
|
||||
- { name: 'iOS', os: 'macos-15', generator: 'Xcode', dx5: false, config: false, brew: true, werror: true, clang-tidy: false, cmake-args: '-DCMAKE_SYSTEM_NAME=iOS' }
|
||||
- { name: 'iOS', os: 'macos-15', generator: 'Xcode', dx5: false, config: false, brew: true, werror: true, clang-tidy: false, cmake-args: '-DCMAKE_SYSTEM_NAME=iOS', ios: true }
|
||||
- { name: 'Emscripten', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' }
|
||||
- { name: 'Nintendo 3DS', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, n3ds: true, werror: true, clang-tidy: false, container: 'devkitpro/devkitarm:latest', cmake-args: '-DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake' }
|
||||
- { name: 'Xbox One', os: 'windows-latest', generator: 'Visual Studio 17 2022', dx5: false, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64', cmake-args: '-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0', xbox-one: true}
|
||||
- { name: 'Android', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, android: true, werror: true, clang-tidy: false,}
|
||||
- { name: 'Vita', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, vita: true, werror: true, clang-tidy: false, cmake-args: '--preset vita'}
|
||||
steps:
|
||||
- name: Setup vcvars
|
||||
@ -94,8 +95,15 @@ jobs:
|
||||
if: ${{ matrix.brew }}
|
||||
run: |
|
||||
brew update
|
||||
brew uninstall cmake || true
|
||||
brew install cmake ninja llvm qt6
|
||||
echo "LLVM_ROOT=$(brew --prefix llvm)/bin" >> $GITHUB_ENV
|
||||
|
||||
- name: Use latest Xcode
|
||||
if: ${{ matrix.ios }}
|
||||
uses: maxim-lobanov/setup-xcode@v1.6.0
|
||||
with:
|
||||
xcode-version: latest-stable
|
||||
|
||||
- name: Setup Emscripten
|
||||
uses: mymindstorm/setup-emsdk@master
|
||||
@ -119,23 +127,64 @@ jobs:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout LFS
|
||||
if: ${{ matrix.build-assets }}
|
||||
run: |
|
||||
git lfs pull
|
||||
|
||||
- name: Setup Java (Android)
|
||||
if: ${{ matrix.android }}
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: Get CMake (Android)
|
||||
if: ${{ matrix.android }}
|
||||
uses: lukka/get-cmake@latest
|
||||
with:
|
||||
cmakeVersion: 3.30.5
|
||||
|
||||
- name: Build (Android)
|
||||
if: ${{ matrix.android }}
|
||||
env:
|
||||
SIGNING_KEY_ALIAS: ${{ secrets.keyAlias }}
|
||||
SIGNING_KEY_PASSWORD: ${{ secrets.keyPassword }}
|
||||
SIGNING_STORE_PASSWORD: ${{ secrets.keystorePassword }}
|
||||
SIGNING_STORE_FILE: ${{ github.workspace }}/release.keystore
|
||||
run: |
|
||||
echo "${{ secrets.keystore }}" | base64 -d > release.keystore
|
||||
cd android-project
|
||||
./gradlew $([ -n "$SIGNING_KEY_ALIAS" ] && echo packageRelease || echo assembleDebug ) \
|
||||
--info \
|
||||
-PcmakeArgs="-DCMAKE_BUILD_TYPE=Release \
|
||||
-DISLE_USE_DX5=${{ !!matrix.dx5 }} \
|
||||
-DISLE_BUILD_CONFIG=${{ !!matrix.config }} \
|
||||
-DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \
|
||||
-DISLE_WERROR=${{ !!matrix.werror }} \
|
||||
-DISLE_DEBUG=${{ matrix.debug || 'OFF' }} \
|
||||
-Werror=dev"
|
||||
|
||||
- name: Configure (CMake)
|
||||
if: ${{ !matrix.android }}
|
||||
run: |
|
||||
${{ matrix.cmake-wrapper || '' }} cmake -S . -B build -G "${{ matrix.generator }}" \
|
||||
${{ matrix.cmake-args || '' }} \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DISLE_USE_DX5=${{ !!matrix.dx5 }} \
|
||||
-DISLE_BUILD_CONFIG=${{ !!matrix.config }} \
|
||||
-DISLE_BUILD_ASSETS=${{ !!matrix.build-assets }} \
|
||||
-DENABLE_CLANG_TIDY=${{ !!matrix.clang-tidy }} \
|
||||
-DISLE_WERROR=${{ !!matrix.werror }} \
|
||||
-DISLE_DEBUG=${{ matrix.debug || 'OFF' }} \
|
||||
-Werror=dev
|
||||
|
||||
- name: Build (CMake)
|
||||
if: ${{ !matrix.android }}
|
||||
run: cmake --build build --verbose --config Release
|
||||
|
||||
- name: Package (CPack)
|
||||
if: ${{ !matrix.n3ds && !matrix.vita }}
|
||||
if: ${{ !matrix.n3ds && !matrix.android && !matrix.vita }}
|
||||
run: |
|
||||
cd build
|
||||
success=0
|
||||
@ -191,6 +240,16 @@ jobs:
|
||||
mkdir dist
|
||||
mv *.vpk dist/
|
||||
|
||||
- name: Package (Android)
|
||||
if: ${{ matrix.android }}
|
||||
run: |
|
||||
mkdir -p build/dist
|
||||
mv android-project/app/build/outputs/apk/*/*.apk build/dist/
|
||||
|
||||
- name: Package Assets Separately
|
||||
if: matrix.build-assets
|
||||
run: (cd build/assets && zip -r ../dist/isle-assets.zip .)
|
||||
|
||||
- name: Upload Build Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
@ -200,6 +259,7 @@ jobs:
|
||||
build/dist/*.AppImage
|
||||
build/dist/*.3dsx
|
||||
build/dist/*.cia
|
||||
build/dist/*.apk
|
||||
build/dist/*.vpk
|
||||
|
||||
flatpak:
|
||||
|
||||
2
.gitignore
vendored
@ -6,12 +6,14 @@ Release/
|
||||
/.idea
|
||||
.env
|
||||
.venv
|
||||
.gradle
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
VENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
local.properties
|
||||
/build/
|
||||
/build_debug/
|
||||
/legobin/
|
||||
|
||||
3
.gitmodules
vendored
@ -7,3 +7,6 @@
|
||||
[submodule "imgui"]
|
||||
path = 3rdparty/imgui
|
||||
url = https://github.com/ocornut/imgui
|
||||
[submodule "3rdparty/libweaver"]
|
||||
path = 3rdparty/libweaver
|
||||
url = https://github.com/isledecomp/SIEdit
|
||||
|
||||
2
.lfsconfig
Normal file
@ -0,0 +1,2 @@
|
||||
[lfs]
|
||||
url = https://f9622702b3bbcac0705052a10e62a5a5:31adabe20fe975a919bd1909a6f598f37b0d6486225efa84b38da1aaf27cbd35@assets.isle.pizza/a70a70ae5ebee06d2333bb1132711de1.r2.cloudflarestorage.com/assets
|
||||
21
3rdparty/CMakeLists.txt
vendored
@ -1,4 +1,5 @@
|
||||
set(CMAKE_C_CLANG_TIDY)
|
||||
set(CMAKE_CXX_CLANG_TIDY)
|
||||
|
||||
if(DOWNLOAD_DEPENDENCIES)
|
||||
include(FetchContent)
|
||||
@ -72,3 +73,23 @@ target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR})
|
||||
target_link_libraries(imgui PUBLIC SDL3::Headers)
|
||||
target_link_libraries(imgui PRIVATE SDL3::SDL3)
|
||||
set_property(TARGET imgui PROPERTY CXX_CLANG_TIDY "")
|
||||
|
||||
if(DOWNLOAD_DEPENDENCIES)
|
||||
include(FetchContent)
|
||||
FetchContent_Populate(
|
||||
libweaver
|
||||
URL https://github.com/isledecomp/SIEdit/archive/ae447259389f3bf8273c7e7a4844743faf7cbdb8.tar.gz
|
||||
URL_MD5 dee68424fde8db6d5cef3b9034a8151f
|
||||
)
|
||||
else()
|
||||
set(libweaver_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libweaver")
|
||||
endif()
|
||||
|
||||
add_library(libweaver STATIC
|
||||
${libweaver_SOURCE_DIR}/lib/core.cpp
|
||||
${libweaver_SOURCE_DIR}/lib/file.cpp
|
||||
${libweaver_SOURCE_DIR}/lib/interleaf.cpp
|
||||
${libweaver_SOURCE_DIR}/lib/object.cpp
|
||||
${libweaver_SOURCE_DIR}/lib/sitypes.cpp
|
||||
)
|
||||
target_include_directories(libweaver PUBLIC ${libweaver_SOURCE_DIR}/lib)
|
||||
|
||||
1
3rdparty/libweaver
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit ae447259389f3bf8273c7e7a4844743faf7cbdb8
|
||||
@ -42,13 +42,14 @@ find_program(SDL_SHADERCROSS_BIN NAMES "shadercross")
|
||||
find_package(Python3 3.12 COMPONENTS Interpreter)
|
||||
|
||||
option(ISLE_BUILD_APP "Build isle application" ON)
|
||||
option(ISLE_BUILD_ASSETS "Build assets from the /assets directory" OFF)
|
||||
option(ISLE_ASAN "Enable Address Sanitizer" OFF)
|
||||
option(ISLE_UBSAN "Enable Undefined Behavior Sanitizer" OFF)
|
||||
option(ISLE_WERROR "Treat warnings as errors" OFF)
|
||||
cmake_dependent_option(ISLE_DEBUG "Enable imgui debug" ON "NOT VITA" OFF)
|
||||
cmake_dependent_option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" "${NOT_MINGW}" "WIN32;CMAKE_SIZEOF_VOID_P EQUAL 4" OFF)
|
||||
cmake_dependent_option(ISLE_MINIWIN "Use miniwin" ON "NOT ISLE_USE_DX5" OFF)
|
||||
cmake_dependent_option(ISLE_EXTENSIONS "Use extensions" ON "NOT ISLE_USE_DX5" OFF)
|
||||
cmake_dependent_option(ISLE_EXTENSIONS "Use extensions" ON "NOT ISLE_USE_DX5;NOT WINDOWS_STORE" OFF)
|
||||
cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "MSVC OR ISLE_MINIWIN;NOT NINTENDO_3DS;NOT WINDOWS_STORE;NOT VITA" OFF)
|
||||
cmake_dependent_option(ISLE_COMPILE_SHADERS "Compile shaders" ON "SDL_SHADERCROSS_BIN;TARGET Python3::Interpreter" OFF)
|
||||
cmake_dependent_option(CMAKE_POSITION_INDEPENDENT_CODE "Build with -fPIC" ON "NOT VITA" OFF)
|
||||
@ -72,24 +73,29 @@ if (DOWNLOAD_DEPENDENCIES)
|
||||
# FetchContent downloads and configures dependencies
|
||||
message(STATUS "Fetching SDL3 and iniparser. This might take a while...")
|
||||
include(FetchContent)
|
||||
if (WINDOWS_STORE)
|
||||
FetchContent_Declare(
|
||||
SDL3
|
||||
GIT_REPOSITORY "https://github.com/Helloyunho/SDL3-uwp.git"
|
||||
GIT_TAG "main"
|
||||
UPDATE_DISCONNECTED TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
|
||||
if(ANDROID)
|
||||
# Built by Gradle
|
||||
find_package(SDL3 REQUIRED CONFIG COMPONENTS Shared)
|
||||
else()
|
||||
FetchContent_Declare(
|
||||
if (WINDOWS_STORE)
|
||||
FetchContent_Declare(
|
||||
SDL3
|
||||
GIT_REPOSITORY "https://github.com/Helloyunho/SDL3-uwp.git"
|
||||
GIT_TAG "main"
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
else()
|
||||
FetchContent_Declare(
|
||||
SDL3
|
||||
GIT_REPOSITORY "https://github.com/libsdl-org/SDL.git"
|
||||
GIT_TAG "main"
|
||||
UPDATE_DISCONNECTED TRUE
|
||||
EXCLUDE_FROM_ALL
|
||||
)
|
||||
)
|
||||
endif()
|
||||
FetchContent_MakeAvailable(SDL3)
|
||||
endif()
|
||||
FetchContent_MakeAvailable(SDL3)
|
||||
|
||||
FetchContent_Declare(
|
||||
iniparser
|
||||
@ -493,14 +499,23 @@ if (NOT ISLE_MINIWIN)
|
||||
endif()
|
||||
|
||||
if (ISLE_EXTENSIONS)
|
||||
target_link_libraries(lego1 PRIVATE libweaver)
|
||||
target_compile_definitions(lego1 PUBLIC EXTENSIONS)
|
||||
target_sources(lego1 PRIVATE
|
||||
extensions/src/extensions.cpp
|
||||
extensions/src/siloader.cpp
|
||||
extensions/src/textureloader.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ISLE_BUILD_APP)
|
||||
|
||||
if (ANDROID)
|
||||
function(add_executable TARGET PLATFORM)
|
||||
add_library(${TARGET} SHARED ${ARGN})
|
||||
endfunction()
|
||||
endif()
|
||||
|
||||
add_executable(isle WIN32
|
||||
ISLE/res/isle.rc
|
||||
ISLE/isleapp.cpp
|
||||
@ -580,6 +595,11 @@ if (ISLE_BUILD_APP)
|
||||
ISLE/ios/config.cpp
|
||||
)
|
||||
endif()
|
||||
if (ANDROID)
|
||||
target_sources(isle PRIVATE
|
||||
ISLE/android/config.cpp
|
||||
)
|
||||
endif()
|
||||
if(VITA)
|
||||
target_sources(isle PRIVATE
|
||||
ISLE/vita/config.cpp
|
||||
@ -653,6 +673,34 @@ if (ISLE_BUILD_CONFIG)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ISLE_BUILD_ASSETS)
|
||||
message(STATUS "Asset building is enabled")
|
||||
set(GENERATED_ASSETS_DIR "${CMAKE_BINARY_DIR}/assets")
|
||||
set(GENERATED_ASSETS_DEPFILE "${GENERATED_ASSETS_DIR}/assets.d")
|
||||
|
||||
add_executable(asset_generator EXCLUDE_FROM_ALL
|
||||
assets/main.cpp
|
||||
)
|
||||
target_link_libraries(asset_generator PRIVATE libweaver)
|
||||
target_include_directories(asset_generator PRIVATE "${CMAKE_SOURCE_DIR}/util" "${CMAKE_SOURCE_DIR}/LEGO1/omni/include" "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${GENERATED_ASSETS_DIR}/.stamp
|
||||
DEPFILE ${GENERATED_ASSETS_DEPFILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${GENERATED_ASSETS_DIR}
|
||||
COMMAND $<TARGET_FILE:asset_generator> ${GENERATED_ASSETS_DIR} ${GENERATED_ASSETS_DEPFILE}
|
||||
COMMAND ${CMAKE_COMMAND} -E touch ${GENERATED_ASSETS_DIR}/.stamp
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/assets
|
||||
DEPENDS asset_generator
|
||||
COMMENT "Generating assets into ${GENERATED_ASSETS_DIR}/"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(build_assets ALL
|
||||
DEPENDS ${GENERATED_ASSETS_DIR}/.stamp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (ISLE_MINIWIN)
|
||||
set_property(TARGET ${isle_targets} APPEND PROPERTY LINK_LIBRARIES "miniwin")
|
||||
endif()
|
||||
@ -682,6 +730,9 @@ if (MSVC)
|
||||
if (TARGET isle-config)
|
||||
target_compile_options(isle-config PRIVATE "-Zc:__cplusplus")
|
||||
endif()
|
||||
if (TARGET asset_generator)
|
||||
target_compile_options(asset_generator PRIVATE "-Zc:__cplusplus")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -717,7 +768,7 @@ endif()
|
||||
set(install_extra_targets)
|
||||
if(DOWNLOAD_DEPENDENCIES)
|
||||
get_property(sdl3_type TARGET SDL3::SDL3 PROPERTY TYPE)
|
||||
if(sdl3_type STREQUAL "SHARED_LIBRARY")
|
||||
if(sdl3_type STREQUAL "SHARED_LIBRARY" AND NOT ANDROID)
|
||||
list(APPEND install_extra_targets "SDL3-shared")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -7,12 +7,9 @@
|
||||
DECOMP_SIZE_ASSERT(CDialog, 0x60)
|
||||
DECOMP_SIZE_ASSERT(CAboutDialog, 0x60)
|
||||
|
||||
// FIXME: disable dialog resizing
|
||||
|
||||
// FUNCTION: CONFIG 0x00403c20
|
||||
CAboutDialog::CAboutDialog() : QDialog()
|
||||
{
|
||||
m_ui = new Ui::AboutDialog;
|
||||
m_ui->setupUi(this);
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
}
|
||||
|
||||
@ -65,6 +65,7 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent)
|
||||
connect(m_ui->sound3DCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckbox3DSound);
|
||||
connect(m_ui->rumbleCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxRumble);
|
||||
connect(m_ui->textureCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxTexture);
|
||||
connect(m_ui->customAssetsCheckBox, &QCheckBox::toggled, this, &CMainDialog::OnCheckboxCustomAssets);
|
||||
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);
|
||||
@ -81,6 +82,11 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent)
|
||||
connect(m_ui->texturePathOpen, &QPushButton::clicked, this, &CMainDialog::SelectTexturePathDialog);
|
||||
connect(m_ui->texturePath, &QLineEdit::editingFinished, this, &CMainDialog::TexturePathEdited);
|
||||
|
||||
connect(m_ui->addCustomAssetPath, &QPushButton::clicked, this, &CMainDialog::AddCustomAssetPath);
|
||||
connect(m_ui->removeCustomAssetPath, &QPushButton::clicked, this, &CMainDialog::RemoveCustomAssetPath);
|
||||
connect(m_ui->customAssetPaths, &QListWidget::currentRowChanged, this, &CMainDialog::SelectedPathChanged);
|
||||
connect(m_ui->customAssetPaths, &QListWidget::itemActivated, this, &CMainDialog::EditCustomAssetPath);
|
||||
|
||||
connect(m_ui->maxLoDSlider, &QSlider::valueChanged, this, &CMainDialog::MaxLoDChanged);
|
||||
connect(m_ui->maxLoDSlider, &QSlider::sliderMoved, this, &CMainDialog::MaxLoDChanged);
|
||||
connect(m_ui->maxActorsSlider, &QSlider::valueChanged, this, &CMainDialog::MaxActorsChanged);
|
||||
@ -96,8 +102,6 @@ CMainDialog::CMainDialog(QWidget* pParent) : QDialog(pParent)
|
||||
connect(m_ui->yResSpinBox, &QSpinBox::valueChanged, this, &CMainDialog::YResChanged);
|
||||
connect(m_ui->framerateSpinBox, &QSpinBox::valueChanged, this, &CMainDialog::FramerateChanged);
|
||||
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
if (currentConfigApp->m_ram_quality_limit != 0) {
|
||||
m_modified = true;
|
||||
const QString ramError = QString("Insufficient RAM!");
|
||||
@ -308,10 +312,29 @@ void CMainDialog::UpdateInterface()
|
||||
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));
|
||||
QString texture_path = QString::fromStdString(currentConfigApp->m_texture_path);
|
||||
if (texture_path.startsWith(QDir::separator())) {
|
||||
texture_path.remove(0, 1);
|
||||
}
|
||||
m_ui->texturePath->setText(texture_path);
|
||||
m_ui->texturePath->setEnabled(currentConfigApp->m_texture_load);
|
||||
m_ui->texturePathOpen->setEnabled(currentConfigApp->m_texture_load);
|
||||
|
||||
m_ui->customAssetsCheckBox->setChecked(currentConfigApp->m_custom_assets_enabled);
|
||||
m_ui->customAssetPathContainer->setEnabled(currentConfigApp->m_custom_assets_enabled);
|
||||
m_ui->customAssetPaths->setEnabled(currentConfigApp->m_custom_assets_enabled);
|
||||
m_ui->addCustomAssetPath->setEnabled(currentConfigApp->m_custom_assets_enabled);
|
||||
m_ui->removeCustomAssetPath->setEnabled(false);
|
||||
|
||||
m_ui->customAssetPaths->clear();
|
||||
assetPaths = QString::fromStdString(currentConfigApp->m_custom_asset_path).split(u',');
|
||||
for (QString& path : assetPaths) {
|
||||
if (path.startsWith(QDir::separator())) {
|
||||
path.remove(0, 1);
|
||||
}
|
||||
}
|
||||
m_ui->customAssetPaths->addItems(assetPaths);
|
||||
|
||||
m_ui->aspectRatioComboBox->setCurrentIndex(currentConfigApp->m_aspect_ratio);
|
||||
m_ui->xResSpinBox->setValue(currentConfigApp->m_x_res);
|
||||
m_ui->yResSpinBox->setValue(currentConfigApp->m_y_res);
|
||||
@ -442,6 +465,13 @@ void CMainDialog::OnCheckboxTexture(bool checked)
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::OnCheckboxCustomAssets(bool checked)
|
||||
{
|
||||
currentConfigApp->m_custom_assets_enabled = checked;
|
||||
m_modified = true;
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::TouchControlsChanged(int index)
|
||||
{
|
||||
currentConfigApp->m_touch_scheme = index;
|
||||
@ -475,14 +505,15 @@ void CMainDialog::SelectDataPathDialog()
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
|
||||
QDir data_dir = QDir(data_path);
|
||||
|
||||
if (data_dir.exists()) {
|
||||
currentConfigApp->m_cd_path = data_dir.absolutePath().toStdString();
|
||||
data_dir.cd(QString("DATA"));
|
||||
data_dir.cd(QString("disk"));
|
||||
currentConfigApp->m_base_path = data_dir.absolutePath().toStdString();
|
||||
m_modified = true;
|
||||
if (!data_path.isEmpty()) {
|
||||
QDir data_dir = QDir(data_path);
|
||||
if (data_dir.exists()) {
|
||||
currentConfigApp->m_cd_path = data_dir.absolutePath().toStdString();
|
||||
data_dir.cd(QString("DATA"));
|
||||
data_dir.cd(QString("disk"));
|
||||
currentConfigApp->m_base_path = data_dir.absolutePath().toStdString();
|
||||
m_modified = true;
|
||||
}
|
||||
}
|
||||
UpdateInterface();
|
||||
}
|
||||
@ -497,11 +528,12 @@ void CMainDialog::SelectSavePathDialog()
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
|
||||
QDir save_dir = QDir(save_path);
|
||||
|
||||
if (save_dir.exists()) {
|
||||
currentConfigApp->m_save_path = save_dir.absolutePath().toStdString();
|
||||
m_modified = true;
|
||||
if (!save_path.isEmpty()) {
|
||||
QDir save_dir = QDir(save_path);
|
||||
if (save_dir.exists()) {
|
||||
currentConfigApp->m_save_path = save_dir.absolutePath().toStdString();
|
||||
m_modified = true;
|
||||
}
|
||||
}
|
||||
UpdateInterface();
|
||||
}
|
||||
@ -517,13 +549,11 @@ void CMainDialog::DataPathEdited()
|
||||
currentConfigApp->m_base_path = data_dir.absolutePath().toStdString();
|
||||
m_modified = true;
|
||||
}
|
||||
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::SavePathEdited()
|
||||
{
|
||||
|
||||
QDir save_dir = QDir(m_ui->savePath->text());
|
||||
|
||||
if (save_dir.exists()) {
|
||||
@ -563,7 +593,12 @@ void CMainDialog::AFChanged(int value)
|
||||
|
||||
void CMainDialog::SelectTexturePathDialog()
|
||||
{
|
||||
QDir data_path = QDir(QString::fromStdString(currentConfigApp->m_cd_path));
|
||||
QString texture_path = QString::fromStdString(currentConfigApp->m_texture_path);
|
||||
if (texture_path.startsWith(QDir::separator())) {
|
||||
texture_path.remove(0, 1);
|
||||
}
|
||||
texture_path = data_path.absoluteFilePath(texture_path);
|
||||
texture_path = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
tr("Open Directory"),
|
||||
@ -571,10 +606,10 @@ void CMainDialog::SelectTexturePathDialog()
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
|
||||
QDir texture_dir = QDir(texture_path);
|
||||
|
||||
if (texture_dir.exists()) {
|
||||
currentConfigApp->m_texture_path = texture_dir.absolutePath().toStdString();
|
||||
if (!texture_path.isEmpty() && data_path.exists(texture_path)) {
|
||||
texture_path = data_path.relativeFilePath(texture_path);
|
||||
texture_path.prepend(QDir::separator());
|
||||
currentConfigApp->m_texture_path = texture_path.toStdString();
|
||||
m_modified = true;
|
||||
}
|
||||
UpdateInterface();
|
||||
@ -582,15 +617,83 @@ void CMainDialog::SelectTexturePathDialog()
|
||||
|
||||
void CMainDialog::TexturePathEdited()
|
||||
{
|
||||
QDir texture_dir = QDir(m_ui->texturePath->text());
|
||||
QString texture_path = m_ui->texturePath->text();
|
||||
QDir data_path = QDir(QString::fromStdString(currentConfigApp->m_cd_path));
|
||||
|
||||
if (texture_dir.exists()) {
|
||||
currentConfigApp->m_texture_path = texture_dir.absolutePath().toStdString();
|
||||
if (texture_path.startsWith(QDir::separator())) {
|
||||
texture_path.remove(0, 1);
|
||||
}
|
||||
if (data_path.exists(data_path.absoluteFilePath(texture_path))) {
|
||||
texture_path = data_path.relativeFilePath(texture_path);
|
||||
texture_path.prepend(QDir::separator());
|
||||
currentConfigApp->m_texture_path = texture_path.toStdString();
|
||||
m_modified = true;
|
||||
}
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::AddCustomAssetPath()
|
||||
{
|
||||
QDir data_path = QDir(QString::fromStdString(currentConfigApp->m_cd_path));
|
||||
QStringList new_files = QFileDialog::getOpenFileNames(
|
||||
this,
|
||||
"Select one or more files to open",
|
||||
data_path.absolutePath(),
|
||||
"Interleaf files (*.si)"
|
||||
);
|
||||
if (!new_files.isEmpty()) {
|
||||
for (QString& item : new_files) {
|
||||
item = data_path.relativeFilePath(item);
|
||||
}
|
||||
assetPaths += new_files;
|
||||
m_modified = true;
|
||||
}
|
||||
UpdateAssetPaths();
|
||||
}
|
||||
|
||||
void CMainDialog::RemoveCustomAssetPath()
|
||||
{
|
||||
assetPaths.removeAt(m_ui->customAssetPaths->currentRow());
|
||||
m_modified = true;
|
||||
UpdateAssetPaths();
|
||||
}
|
||||
|
||||
void CMainDialog::SelectedPathChanged(int currentRow)
|
||||
{
|
||||
m_ui->removeCustomAssetPath->setEnabled(currentRow != -1 ? true : false);
|
||||
}
|
||||
|
||||
void CMainDialog::EditCustomAssetPath()
|
||||
{
|
||||
QDir data_path = QDir(QString::fromStdString(currentConfigApp->m_cd_path));
|
||||
QString prev_asset_path = assetPaths[m_ui->customAssetPaths->currentRow()];
|
||||
QString new_file = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
"Open File",
|
||||
data_path.absoluteFilePath(prev_asset_path),
|
||||
"Interleaf files (*.si)"
|
||||
);
|
||||
if (!new_file.isEmpty()) {
|
||||
new_file = data_path.relativeFilePath(new_file);
|
||||
assetPaths[m_ui->customAssetPaths->currentRow()] = new_file;
|
||||
m_modified = true;
|
||||
}
|
||||
UpdateAssetPaths();
|
||||
}
|
||||
|
||||
void CMainDialog::UpdateAssetPaths()
|
||||
{
|
||||
assetPaths.removeDuplicates();
|
||||
|
||||
for (QString& path : assetPaths) {
|
||||
if (!path.startsWith(QDir::separator())) {
|
||||
path.prepend(QDir::separator());
|
||||
}
|
||||
}
|
||||
currentConfigApp->m_custom_asset_path = assetPaths.join(u',').toStdString();
|
||||
UpdateInterface();
|
||||
}
|
||||
|
||||
void CMainDialog::AspectRatioChanged(int index)
|
||||
{
|
||||
currentConfigApp->m_aspect_ratio = index;
|
||||
|
||||
@ -29,6 +29,7 @@ class CMainDialog : public QDialog {
|
||||
private:
|
||||
bool m_modified = false;
|
||||
bool m_advanced = false;
|
||||
QStringList assetPaths = QStringList();
|
||||
Ui::MainDialog* m_ui = nullptr;
|
||||
SDL_DisplayMode** displayModes;
|
||||
|
||||
@ -48,6 +49,7 @@ private slots:
|
||||
void OnCheckboxMusic(bool checked);
|
||||
void OnCheckboxRumble(bool checked);
|
||||
void OnCheckboxTexture(bool checked);
|
||||
void OnCheckboxCustomAssets(bool checked);
|
||||
void TouchControlsChanged(int index);
|
||||
void TransitionTypeChanged(int index);
|
||||
void ExclusiveResolutionChanged(int index);
|
||||
@ -64,6 +66,11 @@ private slots:
|
||||
void AFChanged(int value);
|
||||
void SelectTexturePathDialog();
|
||||
void TexturePathEdited();
|
||||
void AddCustomAssetPath();
|
||||
void RemoveCustomAssetPath();
|
||||
void SelectedPathChanged(int currentRow);
|
||||
void EditCustomAssetPath();
|
||||
void UpdateAssetPaths();
|
||||
void XResChanged(int i);
|
||||
void YResChanged(int i);
|
||||
void AspectRatioChanged(int index);
|
||||
|
||||
@ -89,7 +89,9 @@ bool CConfigApp::InitInstance()
|
||||
m_haptic = TRUE;
|
||||
m_touch_scheme = 2;
|
||||
m_texture_load = TRUE;
|
||||
m_texture_path = "/textures/";
|
||||
m_texture_path = "textures/";
|
||||
m_custom_assets_enabled = TRUE;
|
||||
m_custom_asset_path = "assets/widescreen.si";
|
||||
int totalRamMiB = SDL_GetSystemRAM();
|
||||
if (totalRamMiB < 12) {
|
||||
m_ram_quality_limit = 2;
|
||||
@ -188,6 +190,8 @@ bool CConfigApp::ReadRegisterSettings()
|
||||
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_custom_assets_enabled = iniparser_getboolean(dict, "extensions:si loader", m_custom_assets_enabled);
|
||||
m_custom_asset_path = iniparser_getstring(dict, "si loader:files", m_custom_asset_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);
|
||||
@ -365,6 +369,8 @@ void CConfigApp::WriteRegisterSettings() const
|
||||
iniparser_set(dict, "isle", NULL);
|
||||
iniparser_set(dict, "extensions", NULL);
|
||||
iniparser_set(dict, "texture loader", NULL);
|
||||
iniparser_set(dict, "si loader", NULL);
|
||||
|
||||
if (m_device_enumerator->FormatDeviceName(buffer, m_driver, m_device) >= 0) {
|
||||
iniparser_set(dict, "isle:3D Device ID", buffer);
|
||||
}
|
||||
@ -394,6 +400,9 @@ void CConfigApp::WriteRegisterSettings() const
|
||||
SetIniBool(dict, "extensions:texture loader", m_texture_load);
|
||||
iniparser_set(dict, "texture loader:texture path", m_texture_path.c_str());
|
||||
|
||||
SetIniBool(dict, "extensions:si loader", m_custom_assets_enabled);
|
||||
iniparser_set(dict, "si loader:files", m_custom_asset_path.c_str());
|
||||
|
||||
SetIniBool(dict, "isle:Back Buffers in Video RAM", m_3d_video_ram);
|
||||
|
||||
SetIniInt(dict, "isle:Island Quality", m_model_quality);
|
||||
@ -451,8 +460,8 @@ CConfigApp g_theApp;
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
QCoreApplication::setApplicationName("config");
|
||||
QCoreApplication::setApplicationVersion("1.0");
|
||||
QCoreApplication::setApplicationName("Isle-Config");
|
||||
QCoreApplication::setApplicationVersion("2.0");
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Configure LEGO Island");
|
||||
@ -470,7 +479,7 @@ int main(int argc, char* argv[])
|
||||
if (parser.isSet(iniOption)) {
|
||||
g_theApp.SetIniPath(parser.value(iniOption).toStdString());
|
||||
}
|
||||
qInfo() << "Ini path =" << QString::fromStdString(g_theApp.GetIniPath());
|
||||
qInfo() << "INI path =" << QString::fromStdString(g_theApp.GetIniPath());
|
||||
|
||||
int result = 1;
|
||||
if (g_theApp.InitInstance()) {
|
||||
|
||||
@ -87,7 +87,9 @@ class CConfigApp {
|
||||
int m_texture_quality;
|
||||
bool m_music;
|
||||
bool m_texture_load;
|
||||
bool m_custom_assets_enabled;
|
||||
std::string m_texture_path;
|
||||
std::string m_custom_asset_path;
|
||||
std::string m_iniPath;
|
||||
std::string m_base_path;
|
||||
std::string m_cd_path;
|
||||
|
||||
@ -14,6 +14,9 @@
|
||||
<string>About Configure LEGO© Island</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="houseIcon">
|
||||
<property name="sizePolicy">
|
||||
@ -36,14 +39,14 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="configureLabel">
|
||||
<property name="text">
|
||||
<string>Configure LEGO Island Version 1.0</string>
|
||||
<string>Configure LEGO Island Version 2.0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="copyrightLabel">
|
||||
<property name="text">
|
||||
<string>Copyright © 1997 mindscape</string>
|
||||
<string>Copyright © 2025</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -53,7 +56,7 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
46
CONFIG/qt/res/add.svg
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="add.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="21.496181"
|
||||
inkscape:cx="-4.2333101"
|
||||
inkscape:cy="11.141514"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1008"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<defs
|
||||
id="defs3051">
|
||||
<style
|
||||
type="text/css"
|
||||
id="current-color-scheme">
|
||||
.ColorScheme-Text {
|
||||
color:#232629;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path
|
||||
style="fill:#27ae60;fill-opacity:1;stroke:none;stroke-width:0.999911"
|
||||
d="M 7,3 V 8 H 2 v 1 h 5 v 5 H 8 V 9 h 5 V 8 H 8 V 3 Z"
|
||||
class="ColorScheme-Text"
|
||||
id="path1"
|
||||
sodipodi:nodetypes="ccccccccccccc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@ -1,7 +1,9 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>shark.png</file>
|
||||
<file>lego1.png</file>
|
||||
<file>lego2.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
<qresource prefix="/">
|
||||
<file>add.svg</file>
|
||||
<file>remove.svg</file>
|
||||
<file>shark.png</file>
|
||||
<file>lego1.png</file>
|
||||
<file>lego2.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<width>640</width>
|
||||
<height>480</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -24,6 +24,9 @@
|
||||
<normaloff>:/lego1.png</normaloff>:/lego1.png</iconset>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="sharkImageLabel">
|
||||
<property name="sizePolicy">
|
||||
@ -72,6 +75,12 @@
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>425</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -80,30 +89,6 @@
|
||||
<string>Game</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2">
|
||||
<layout class="QVBoxLayout" name="gameSettingsCheckBoxes">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="sound3DCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Enable 3D positional audio effects.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>3D Sound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="musicCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Enable in-game background music.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Music</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
@ -283,6 +268,32 @@ Set this to the CD image root.</string>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QWidget" name="gameSettingsCheckBoxes" native="true">
|
||||
<layout class="QVBoxLayout" name="layout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="sound3DCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Enable 3D positional audio effects.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>3D Sound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="musicCheckBox">
|
||||
<property name="toolTip">
|
||||
<string>Enable in-game background music.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Music</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="graphicsTab">
|
||||
@ -766,7 +777,10 @@ The game will gradually increase the number of actors until this maximum is reac
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
<string>✕</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::TextFormat::PlainText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
@ -1012,72 +1026,210 @@ The game will gradually increase the number of actors until this maximum is reac
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="textureLoader">
|
||||
<property name="toolTip">
|
||||
<string>Settings for Texture Loader extension.</string>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Texture Loader</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="textureCheckBox">
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="texturePath">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Path to texture replacements.</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>textures/</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="texturePathOpen">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>449</width>
|
||||
<height>369</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="textureLoader">
|
||||
<property name="toolTip">
|
||||
<string>Settings for Texture Loader extension.</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Texture Loader</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="textureCheckBox">
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="texturePath">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Path to texture replacements. Relative to the Data Path.</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>textures/</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="texturePathOpen">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="customAssets">
|
||||
<property name="toolTip">
|
||||
<string>Settings for Custom Assets.</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Custom Assets</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_12">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="customAssetsCheckBox">
|
||||
<property name="text">
|
||||
<string>Enabled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="customAssetPathContainer" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QPushButton" name="addCustomAssetPath">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add path.</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="config.qrc">
|
||||
<normaloff>:/add.svg</normaloff>:/add.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="3">
|
||||
<widget class="QListWidget" name="customAssetPaths">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Paths used by the SI Loader extension.
|
||||
|
||||
Double-click a path to edit it.</string>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QPushButton" name="removeCustomAssetPath">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>28</width>
|
||||
<height>28</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove path.</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="config.qrc">
|
||||
<normaloff>:/remove.svg</normaloff>:/remove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
@ -1176,9 +1328,14 @@ The game will gradually increase the number of actors until this maximum is reac
|
||||
<tabstop>AFSlider</tabstop>
|
||||
<tabstop>touchComboBox</tabstop>
|
||||
<tabstop>rumbleCheckBox</tabstop>
|
||||
<tabstop>scrollArea</tabstop>
|
||||
<tabstop>textureCheckBox</tabstop>
|
||||
<tabstop>texturePath</tabstop>
|
||||
<tabstop>texturePathOpen</tabstop>
|
||||
<tabstop>customAssetsCheckBox</tabstop>
|
||||
<tabstop>customAssetPaths</tabstop>
|
||||
<tabstop>addCustomAssetPath</tabstop>
|
||||
<tabstop>removeCustomAssetPath</tabstop>
|
||||
<tabstop>okButton</tabstop>
|
||||
<tabstop>launchButton</tabstop>
|
||||
<tabstop>cancelButton</tabstop>
|
||||
|
||||
10
CONFIG/qt/res/remove.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<style
|
||||
type="text/css"
|
||||
id="current-color-scheme">
|
||||
.ColorScheme-NegativeText {
|
||||
color:#da4453;
|
||||
}
|
||||
</style>
|
||||
<path class="ColorScheme-NegativeText" d="M 2.6992188,2 2,2.6992188 7.3007812,8 2,13.300781 C 2,13.300781 2.7082187,13.995 2.6992188,14 L 8,8.6992188 13.300781,14 C 13.291781,13.995 14,13.300781 14,13.300781 L 8.6992188,8 14,2.6992188 13.300781,2 8,7.3007812 Z" fill="currentColor"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 526 B |
@ -17,199 +17,204 @@ paf::Plugin* g_configPlugin;
|
||||
sce::AppSettings* g_appSettings;
|
||||
sce::AppSettings::Interface* g_appSetIf;
|
||||
|
||||
struct Config {
|
||||
paf::string m_base_path;
|
||||
paf::string m_cd_path;
|
||||
paf::string m_save_path;
|
||||
int m_transition_type;
|
||||
int m_texture_quality;
|
||||
int m_model_quality;
|
||||
int m_msaa;
|
||||
int m_touch_scheme;
|
||||
bool m_wide_view_angle;
|
||||
bool m_music;
|
||||
bool m_3d_sound;
|
||||
bool m_haptic;
|
||||
bool m_draw_cursor;
|
||||
bool m_texture_load;
|
||||
paf::string m_texture_path;
|
||||
float m_max_lod;
|
||||
int m_max_actors;
|
||||
float m_frame_delta;
|
||||
void merge_dicts(dictionary* dst, dictionary* src) {
|
||||
for(int i = 0; i < src->n; i++) {
|
||||
dictionary_set(dst, src->key[i], src->val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Init()
|
||||
struct setting_map {
|
||||
const char* key_ini;
|
||||
const char* key_app;
|
||||
const char type;
|
||||
};
|
||||
|
||||
// mapping from ini key to settings.xml key
|
||||
const setting_map key_map[] = {
|
||||
// Game
|
||||
{"isle:diskpath", "disk_path", 's'},
|
||||
{"isle:cdpath", "cd_path", 's'},
|
||||
{"isle:savepath", "save_path", 's'},
|
||||
{"isle:Transition Type", "transition_type", 'i'},
|
||||
{"isle:Music", "music", 'b'},
|
||||
{"isle:3DSound", "3d_sound", 'b'},
|
||||
|
||||
// Graphics
|
||||
{"isle:Island Texture", "island_texture_quality", 'i'},
|
||||
{"isle:Island Quality", "island_model_quality", 'i'},
|
||||
//{"isle:Max LOD", "max_lod", 'f'},
|
||||
//{"isle:Max Allowed Extras", "max_extras", 'i' },
|
||||
{"isle:MSAA", "msaa", 'i'},
|
||||
|
||||
// Controls
|
||||
{"isle:Touch Scheme", "touch_control_scheme", 'i'},
|
||||
{"isle:Haptic", "rumble", 'b'},
|
||||
|
||||
// Extensions
|
||||
{"extensions:texture loader", "texture_loader_extension", 'b'},
|
||||
{"texture loader:texture path", "texture_loader_path", 's'}
|
||||
};
|
||||
|
||||
struct Config {
|
||||
sce::AppSettings* settings;
|
||||
dictionary* dict;
|
||||
char buffer[128];
|
||||
|
||||
#define GetDictInt(x, name) x = iniparser_getint(this->dict, name, x)
|
||||
#define GetDictFloat(x, name) x = iniparser_getdouble(this->dict, name, x)
|
||||
#define GetDictString(x, name) { \
|
||||
const char* val = iniparser_getstring(this->dict, name, nullptr); \
|
||||
if (val != nullptr) { \
|
||||
x = val; \
|
||||
} \
|
||||
}
|
||||
#define GetDictBool(x, name) x = iniparser_getboolean(this->dict, name, x)
|
||||
|
||||
#define SetDictBool(NAME, VALUE) \
|
||||
{ \
|
||||
const char* v = VALUE ? "true" : "false"; \
|
||||
sceClibPrintf("SetIniBool(%s, %s)\n", NAME, v); \
|
||||
iniparser_set(this->dict, NAME, v); \
|
||||
}
|
||||
#define SetDictInt(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibSnprintf(buffer, sizeof(buffer), "%d", VALUE); \
|
||||
sceClibPrintf("SetIniInt(%s, %d)\n", NAME, VALUE); \
|
||||
iniparser_set(this->dict, NAME, buffer); \
|
||||
}
|
||||
#define SetDictFloat(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibSnprintf(buffer, sizeof(buffer), "%f", VALUE); \
|
||||
sceClibPrintf("SetIniFloat(%s, %f)\n", NAME, VALUE); \
|
||||
iniparser_set(this->dict, NAME, buffer); \
|
||||
}
|
||||
#define SetDictString(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibPrintf("SetString(%s, %s)\n", NAME, VALUE); \
|
||||
iniparser_set(this->dict, NAME, VALUE); \
|
||||
}
|
||||
|
||||
void Init(sce::AppSettings* settings)
|
||||
{
|
||||
m_frame_delta = 10.0f;
|
||||
m_transition_type = 3; // 3: Mosaic
|
||||
m_wide_view_angle = true;
|
||||
m_music = true;
|
||||
m_3d_sound = true;
|
||||
m_haptic = true;
|
||||
m_touch_scheme = 2;
|
||||
m_texture_load = true;
|
||||
m_texture_path = "/textures/";
|
||||
m_model_quality = 2;
|
||||
m_texture_quality = 1;
|
||||
m_msaa = 4;
|
||||
m_max_lod = 3.5f;
|
||||
m_max_actors = 20;
|
||||
this->settings = settings;
|
||||
dict = dictionary_new(0);
|
||||
|
||||
// set defaults
|
||||
SetDictInt("isle:Display Bit Depth", 32);
|
||||
SetDictBool("isle:Flip Surfaces", false);
|
||||
SetDictBool("isle:Full Screen", true);
|
||||
SetDictBool("isle:Exclusive Full Screen", true);
|
||||
SetDictBool("isle:Wide View Angle", true);
|
||||
|
||||
SetDictInt("isle:Transition Type", 3); // 3: Mosaic
|
||||
SetDictInt("isle:Touch Scheme", 2);
|
||||
|
||||
SetDictBool("isle:3DSound", true);
|
||||
SetDictBool("isle:Music", true);
|
||||
SetDictBool("isle:Haptic", true);
|
||||
|
||||
SetDictBool("isle:UseJoystick", true);
|
||||
SetDictInt("isle:JoystickIndex", 0);
|
||||
SetDictBool("isle:Draw Cursor", true);
|
||||
|
||||
SetDictBool("extensions:texture loader", false);
|
||||
SetDictString("texture loader:texture path", "textures/");
|
||||
|
||||
SetDictBool("isle:Back Buffers in Video RAM", true);
|
||||
|
||||
SetDictInt("isle:Island Quality", 2);
|
||||
SetDictInt("isle:Island Texture", 1);
|
||||
SetDictInt("isle:MSAA", 4);
|
||||
|
||||
SetDictFloat("isle:Max LOD", 3.5);
|
||||
SetDictInt("isle:Max Allowed Extras", 20);
|
||||
|
||||
SetDictInt("isle:Aspect Ratio", 0);
|
||||
SetDictInt("isle:Horizontal Resolution", 640);
|
||||
SetDictInt("isle:Vertical Resolution", 480);
|
||||
SetDictFloat("isle:Frame Delta", 10.0f);
|
||||
}
|
||||
|
||||
void LoadIni()
|
||||
{
|
||||
dictionary* dict = iniparser_load(g_iniPath);
|
||||
if (!dict) {
|
||||
dict = dictionary_new(0);
|
||||
dictionary* ini = iniparser_load(g_iniPath);
|
||||
if(ini) {
|
||||
merge_dicts(this->dict, ini);
|
||||
iniparser_freedict(ini);
|
||||
}
|
||||
|
||||
#define GET_INT(x, name) x = iniparser_getint(dict, name, x)
|
||||
#define GET_FLOAT(x, name) x = iniparser_getdouble(dict, name, x)
|
||||
#define GET_STRING(x, name) do { \
|
||||
const char* val = iniparser_getstring(dict, name, nullptr); \
|
||||
if(val != nullptr) x = val; \
|
||||
} while(0)
|
||||
#define GET_BOOLEAN(x, name) x = iniparser_getboolean(dict, name, x)
|
||||
|
||||
GET_STRING(m_base_path, "isle:diskpath");
|
||||
GET_STRING(m_cd_path, "isle:cdpath");
|
||||
GET_STRING(m_save_path, "isle:savepath");
|
||||
|
||||
// m_display_bit_depth = iniparser_getint(dict, "isle:Display Bit Depth", -1);
|
||||
// GET_BOOLEAN(m_flip_surfaces, "isle:Flip Surfaces");
|
||||
// GET_BOOLEAN(m_full_screen, "isle:Full Screen");
|
||||
// GET_BOOLEAN(m_exclusive_full_screen, "isle:Exclusive Full Screen");
|
||||
GET_INT(m_transition_type, "isle:Transition Type");
|
||||
GET_INT(m_touch_scheme, "isle:Touch Scheme");
|
||||
// GET_BOOLEAN(m_3d_video_ram, "isle:Back Buffers in Video RAM");
|
||||
GET_BOOLEAN(m_wide_view_angle, "isle:Wide View Angle");
|
||||
GET_BOOLEAN(m_3d_sound, "isle:3DSound");
|
||||
GET_BOOLEAN(m_draw_cursor, "isle:Draw Cursor");
|
||||
GET_INT(m_model_quality, "isle:Island Quality");
|
||||
GET_INT(m_texture_quality, "isle:Island Texture");
|
||||
GET_INT(m_msaa, "isle:MSAA");
|
||||
// GET_BOOLEAN(m_use_joystick, "isle:UseJoystick");
|
||||
GET_BOOLEAN(m_haptic, "isle:Haptic");
|
||||
GET_BOOLEAN(m_music, "isle:Music");
|
||||
// GET_INT(m_joystick_index, "isle:JoystickIndex");
|
||||
GET_FLOAT(m_max_lod, "isle:Max LOD");
|
||||
GET_INT(m_max_actors, "isle:Max Allowed Extras");
|
||||
GET_BOOLEAN(m_texture_load, "extensions:texture loader");
|
||||
GET_STRING(m_texture_path, "texture loader:texture path");
|
||||
// GET_INT(m_aspect_ratio, "isle:Aspect Ratio");
|
||||
// GET_INT(m_x_res, "isle:Horizontal Resolution");
|
||||
// GET_INT(m_y_res, "isle:Vertical Resolution");
|
||||
GET_FLOAT(m_frame_delta, "isle:Frame Delta");
|
||||
#undef GET_INT
|
||||
#undef GET_FLOAT
|
||||
#undef GET_STRING
|
||||
#undef GET_BOOLEAN
|
||||
iniparser_freedict(dict);
|
||||
}
|
||||
|
||||
bool SaveIni()
|
||||
{
|
||||
dictionary* dict = dictionary_new(0);
|
||||
|
||||
char buffer[128];
|
||||
#define SetIniBool(NAME, VALUE) iniparser_set(dict, NAME, VALUE ? "true" : "false")
|
||||
#define SetIniInt(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibPrintf(buffer, "%d", VALUE); \
|
||||
iniparser_set(dict, NAME, buffer); \
|
||||
}
|
||||
#define SetIniFloat(NAME, VALUE) \
|
||||
{ \
|
||||
sceClibPrintf(buffer, "%f", VALUE); \
|
||||
iniparser_set(dict, NAME, buffer); \
|
||||
}
|
||||
#define SetString(NAME, VALUE) iniparser_set(dict, NAME, VALUE)
|
||||
|
||||
SetIniInt("isle:Display Bit Depth", 32);
|
||||
SetIniBool("isle:Flip Surfaces", false);
|
||||
SetIniBool("isle:Full Screen", true);
|
||||
SetIniBool("isle:Exclusive Full Screen", true);
|
||||
SetIniBool("isle:Wide View Angle", true); // option?
|
||||
|
||||
SetIniInt("isle:Transition Type", m_transition_type);
|
||||
SetIniInt("isle:Touch Scheme", m_touch_scheme);
|
||||
|
||||
SetIniBool("isle:3DSound", m_3d_sound);
|
||||
SetIniBool("isle:Music", m_music);
|
||||
SetIniBool("isle:Haptic", m_haptic);
|
||||
|
||||
SetIniBool("isle:UseJoystick", true);
|
||||
SetIniInt("isle:JoystickIndex", 0);
|
||||
SetIniBool("isle:Draw Cursor", m_draw_cursor);
|
||||
|
||||
SetIniBool("extensions:texture loader", m_texture_load);
|
||||
SetString("texture loader:texture path", m_texture_path.c_str());
|
||||
|
||||
SetIniBool("isle:Back Buffers in Video RAM", true);
|
||||
|
||||
SetIniInt("isle:Island Quality", m_model_quality);
|
||||
SetIniInt("isle:Island Texture", m_texture_quality);
|
||||
SetIniInt("isle:MSAA", m_msaa);
|
||||
|
||||
SetIniFloat("isle:Max LOD", m_max_lod);
|
||||
SetIniInt("isle:Max Allowed Extras", m_max_actors);
|
||||
|
||||
SetIniInt("isle:Aspect Ratio", 0);
|
||||
SetIniInt("isle:Horizontal Resolution", 640);
|
||||
SetIniInt("isle:Vertical Resolution", 480);
|
||||
SetIniFloat("isle:Frame Delta", 10.0f);
|
||||
|
||||
#undef SetIniBool
|
||||
#undef SetIniInt
|
||||
#undef SetIniFloat
|
||||
#undef SetString
|
||||
|
||||
FILE* fd = fopen(g_iniPath, "w");
|
||||
if (fd) {
|
||||
iniparser_dump_ini(dict, fd);
|
||||
} else {
|
||||
iniparser_dump_ini(this->dict, fd);
|
||||
}
|
||||
else {
|
||||
sceClibPrintf("failed to write isle.ini\n");
|
||||
}
|
||||
iniparser_freedict(dict);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ToSettings(sce::AppSettings* appSettings)
|
||||
void ToSettings()
|
||||
{
|
||||
appSettings->SetString("data_path", this->m_base_path.c_str());
|
||||
appSettings->SetString("save_path", this->m_save_path.c_str());
|
||||
appSettings->SetInt("transition_type", this->m_transition_type);
|
||||
appSettings->SetBool("music", this->m_music);
|
||||
appSettings->SetBool("3d_sound", this->m_3d_sound);
|
||||
appSettings->SetInt("island_texture_quality", this->m_texture_quality);
|
||||
appSettings->SetInt("island_model_quality", this->m_model_quality);
|
||||
appSettings->SetInt("msaa", this->m_msaa);
|
||||
appSettings->SetInt("touch_control_scheme", this->m_touch_scheme);
|
||||
appSettings->SetBool("rumble", this->m_haptic);
|
||||
appSettings->SetBool("texture_loader_extension", this->m_texture_load);
|
||||
appSettings->SetString("texture_loader_path", this->m_texture_path.c_str());
|
||||
const int len = sizeof(key_map) / sizeof(key_map[0]);
|
||||
for(int i = 0; i < len; i++) {
|
||||
const setting_map m = key_map[i];
|
||||
switch(m.type) {
|
||||
case 'f': // float, AppSettings doesnt have float so just use string
|
||||
case 's': {
|
||||
const char* value = dictionary_get(this->dict, m.key_ini, "");
|
||||
this->settings->SetString(m.key_app, value);
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
int32_t value = iniparser_getint(this->dict, m.key_ini, 0);
|
||||
this->settings->SetInt(m.key_app, value);
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
bool value = iniparser_getboolean(this->dict, m.key_ini, 0) == 1;
|
||||
this->settings->SetBool(m.key_app, value);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sceClibPrintf("invalid setting map entry %s %s %c\n", m.key_app, m.key_ini, m.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FromSettings(sce::AppSettings* appSettings) {
|
||||
char text_buf[255];
|
||||
|
||||
#define GET_STRING(x, name) appSettings->GetString(name, text_buf, sizeof(text_buf), x.c_str()); x = text_buf;
|
||||
|
||||
GET_STRING(this->m_base_path, "data_path");
|
||||
GET_STRING(this->m_save_path, "save_path");
|
||||
appSettings->GetInt("transition_type", &this->m_transition_type, this->m_transition_type);
|
||||
printf("this->m_transition_type: %d\n", this->m_transition_type);
|
||||
appSettings->GetBool("music", &this->m_music, this->m_music);
|
||||
appSettings->GetBool("3d_sound", &this->m_3d_sound, this->m_3d_sound);
|
||||
appSettings->GetInt("island_texture_quality", &this->m_texture_quality, this->m_texture_quality);
|
||||
appSettings->GetInt("island_model_quality", &this->m_model_quality, this->m_model_quality);
|
||||
appSettings->GetInt("msaa", &this->m_msaa, this->m_msaa);
|
||||
appSettings->GetInt("touch_control_scheme", &this->m_touch_scheme, this->m_touch_scheme);
|
||||
appSettings->GetBool("rumble", &this->m_haptic, this->m_haptic);
|
||||
appSettings->GetBool("texture_loader_extension", &this->m_texture_load, this->m_texture_load);
|
||||
GET_STRING(this->m_texture_path, "texture_loader_path");
|
||||
|
||||
#undef GET_STRING
|
||||
void FromSettings()
|
||||
{
|
||||
const int len = sizeof(key_map) / sizeof(key_map[0]);
|
||||
for(int i = 0; i < len; i++) {
|
||||
const setting_map m = key_map[i];
|
||||
switch(m.type) {
|
||||
case 'f': // float, AppSettings doesnt have float so just use string
|
||||
case 's': {
|
||||
const char* def = dictionary_get(this->dict, m.key_ini, "");
|
||||
this->settings->GetString(m.key_app, this->buffer, sizeof(this->buffer), def);
|
||||
dictionary_set(this->dict, m.key_ini, buffer);
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
int32_t value = iniparser_getint(this->dict, m.key_ini, 0);
|
||||
this->settings->GetInt(m.key_app, &value, value);
|
||||
SetDictInt(m.key_ini, value);
|
||||
break;
|
||||
}
|
||||
case 'b': {
|
||||
bool value = iniparser_getboolean(this->dict, m.key_ini, 0) == 1;
|
||||
this->settings->GetBool(m.key_app, &value, value);
|
||||
SetDictBool(m.key_ini, value);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
sceClibPrintf("invalid setting map entry %s %s %c\n", m.key_app, m.key_ini, m.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -254,7 +259,7 @@ int exit_type = 0;
|
||||
|
||||
void save_and_exit()
|
||||
{
|
||||
g_config.FromSettings(g_appSettings);
|
||||
g_config.FromSettings();
|
||||
g_config.SaveIni();
|
||||
g_fw->RequestShutdown();
|
||||
exit_type = 1;
|
||||
@ -262,7 +267,7 @@ void save_and_exit()
|
||||
|
||||
void save_and_launch()
|
||||
{
|
||||
g_config.FromSettings(g_appSettings);
|
||||
g_config.FromSettings();
|
||||
g_config.SaveIni();
|
||||
g_fw->RequestShutdown();
|
||||
exit_type = 2;
|
||||
@ -319,7 +324,7 @@ int32_t CBOnPress2(const char* elementId, const char* newValue)
|
||||
|
||||
void CBOnTerm(int32_t result)
|
||||
{
|
||||
if(exit_type == 0) {
|
||||
if (exit_type == 0) {
|
||||
sceKernelExitProcess(0);
|
||||
}
|
||||
}
|
||||
@ -340,9 +345,9 @@ int32_t CBOnGetSurface(paf::graph::Surface** surf, const char* elementId)
|
||||
|
||||
void open_settings()
|
||||
{
|
||||
g_config.Init();
|
||||
g_config.Init(g_appSettings);
|
||||
g_config.LoadIni();
|
||||
g_config.ToSettings(g_appSettings);
|
||||
g_config.ToSettings();
|
||||
|
||||
sce::AppSettings::InterfaceCallbacks ifCb;
|
||||
ifCb.onStartPageTransitionCb = CBOnStartPageTransition;
|
||||
|
||||
29
ISLE/android/config.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "mxstring.h"
|
||||
|
||||
#include <SDL3/SDL_filesystem.h>
|
||||
#include <SDL3/SDL_log.h>
|
||||
#include <SDL3/SDL_system.h>
|
||||
#include <iniparser.h>
|
||||
|
||||
void Android_SetupDefaultConfigOverrides(dictionary* p_dictionary)
|
||||
{
|
||||
SDL_Log("Overriding default config for Android");
|
||||
|
||||
const char* data = SDL_GetAndroidExternalStoragePath();
|
||||
MxString savedata = MxString(data) + "/saves/";
|
||||
|
||||
if (!SDL_GetPathInfo(savedata.GetData(), NULL)) {
|
||||
SDL_CreateDirectory(savedata.GetData());
|
||||
}
|
||||
|
||||
iniparser_set(p_dictionary, "isle:diskpath", data);
|
||||
iniparser_set(p_dictionary, "isle:cdpath", data);
|
||||
iniparser_set(p_dictionary, "isle:mediapath", data);
|
||||
iniparser_set(p_dictionary, "isle:savepath", savedata.GetData());
|
||||
|
||||
// Default to Virtual Mouse
|
||||
char buf[16];
|
||||
iniparser_set(p_dictionary, "isle:Touch Scheme", SDL_itoa(0, buf, 10));
|
||||
}
|
||||
8
ISLE/android/config.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef ANDROID_CONFIG_H
|
||||
#define ANDROID_CONFIG_H
|
||||
|
||||
#include "dictionary.h"
|
||||
|
||||
void Android_SetupDefaultConfigOverrides(dictionary* p_dictionary);
|
||||
|
||||
#endif // ANDROID_CONFIG_H
|
||||
@ -1,6 +1,7 @@
|
||||
#include "filesystem.h"
|
||||
|
||||
#include "events.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "extensions/textureloader.h"
|
||||
#include "legogamestate.h"
|
||||
#include "misc.h"
|
||||
@ -107,6 +108,14 @@ void Emscripten_SetupFilesystem()
|
||||
Emscripten_SendExtensionProgress("HD Textures", (++i * 100) / sizeOfArray(g_textures));
|
||||
}
|
||||
}
|
||||
|
||||
if (Extensions::SiLoader::enabled) {
|
||||
wasmfs_create_directory("/LEGO/extra", 0644, fetchfs);
|
||||
|
||||
for (const auto& file : Extensions::SiLoader::files) {
|
||||
registerFile(file.c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GameState()->GetSavePath() && *GameState()->GetSavePath() && !Emscripten_OPFSDisabled()) {
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "mxstring.h"
|
||||
|
||||
#include <SDL3/SDL_filesystem.h>
|
||||
#include <SDL3/SDL_log.h>
|
||||
#include <iniparser.h>
|
||||
@ -11,15 +13,13 @@ void IOS_SetupDefaultConfigOverrides(dictionary* p_dictionary)
|
||||
// Use DevelopmentFiles path for disk and cd paths
|
||||
// It's good to use that path since user can easily
|
||||
// connect through SMB and copy the files
|
||||
const char* documentFolder = SDL_GetUserFolder(SDL_FOLDER_DOCUMENTS);
|
||||
char* diskPath = new char[strlen(documentFolder) + strlen("isle") + 1]();
|
||||
strcpy(diskPath, documentFolder);
|
||||
strcat(diskPath, "isle");
|
||||
MxString documentFolder = SDL_GetUserFolder(SDL_FOLDER_DOCUMENTS);
|
||||
documentFolder += "isle";
|
||||
|
||||
if (!SDL_GetPathInfo(diskPath, NULL)) {
|
||||
SDL_CreateDirectory(diskPath);
|
||||
if (!SDL_GetPathInfo(documentFolder.GetData(), NULL)) {
|
||||
SDL_CreateDirectory(documentFolder.GetData());
|
||||
}
|
||||
|
||||
iniparser_set(p_dictionary, "isle:diskpath", diskPath);
|
||||
iniparser_set(p_dictionary, "isle:cdpath", diskPath);
|
||||
iniparser_set(p_dictionary, "isle:diskpath", documentFolder.GetData());
|
||||
iniparser_set(p_dictionary, "isle:cdpath", documentFolder.GetData());
|
||||
}
|
||||
|
||||
119
ISLE/isleapp.cpp
@ -40,6 +40,7 @@
|
||||
#include <array>
|
||||
#include <extensions/extensions.h>
|
||||
#include <miniwin/miniwindevice.h>
|
||||
#include <type_traits>
|
||||
#include <vec.h>
|
||||
|
||||
#define SDL_MAIN_USE_CALLBACKS
|
||||
@ -72,6 +73,10 @@
|
||||
#include "ios/config.h"
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "android/config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __vita__
|
||||
#include "vita/config.h"
|
||||
#include "vita/messagebox.h"
|
||||
@ -176,6 +181,7 @@ IsleApp::IsleApp()
|
||||
|
||||
LegoOmni::CreateInstance();
|
||||
|
||||
m_mediaPath = NULL;
|
||||
m_iniPath = NULL;
|
||||
m_maxLod = RealtimeView::GetUserMaxLOD();
|
||||
m_maxAllowedExtras = m_islandQuality <= 1 ? 10 : 20;
|
||||
@ -202,25 +208,11 @@ IsleApp::~IsleApp()
|
||||
MxOmni::DestroyInstance();
|
||||
}
|
||||
|
||||
if (m_hdPath) {
|
||||
delete[] m_hdPath;
|
||||
}
|
||||
|
||||
if (m_cdPath) {
|
||||
delete[] m_cdPath;
|
||||
}
|
||||
|
||||
if (m_deviceId) {
|
||||
delete[] m_deviceId;
|
||||
}
|
||||
|
||||
if (m_savePath) {
|
||||
delete[] m_savePath;
|
||||
}
|
||||
|
||||
if (m_mediaPath) {
|
||||
delete[] m_mediaPath;
|
||||
}
|
||||
SDL_free(m_hdPath);
|
||||
SDL_free(m_cdPath);
|
||||
SDL_free(m_deviceId);
|
||||
SDL_free(m_savePath);
|
||||
SDL_free(m_mediaPath);
|
||||
}
|
||||
|
||||
// FUNCTION: ISLE 0x401260
|
||||
@ -1014,6 +1006,8 @@ MxResult IsleApp::SetupWindow()
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
Lego()->LoadSiLoader();
|
||||
|
||||
DetectGameVersion();
|
||||
GameState()->SerializePlayersInfo(LegoStorage::c_read);
|
||||
GameState()->SerializeScoreHistory(LegoStorage::c_read);
|
||||
@ -1066,33 +1060,33 @@ bool IsleApp::LoadConfig()
|
||||
{
|
||||
#ifdef IOS
|
||||
const char* prefPath = SDL_GetUserFolder(SDL_FOLDER_DOCUMENTS);
|
||||
#else
|
||||
char* prefPath = SDL_GetPrefPath("isledecomp", "isle");
|
||||
#endif
|
||||
char* iniConfig;
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#elif defined(ANDROID)
|
||||
MxString androidPath = MxString(SDL_GetAndroidExternalStoragePath()) + "/";
|
||||
const char* prefPath = androidPath.GetData();
|
||||
#elif defined(EMSCRIPTEN)
|
||||
if (m_iniPath && !Emscripten_SetupConfig(m_iniPath)) {
|
||||
m_iniPath = NULL;
|
||||
}
|
||||
char* prefPath = SDL_GetPrefPath("isledecomp", "isle");
|
||||
#else
|
||||
char* prefPath = SDL_GetPrefPath("isledecomp", "isle");
|
||||
#endif
|
||||
|
||||
MxString iniConfig;
|
||||
if (m_iniPath) {
|
||||
iniConfig = new char[strlen(m_iniPath) + 1];
|
||||
strcpy(iniConfig, m_iniPath);
|
||||
iniConfig = m_iniPath;
|
||||
}
|
||||
else if (prefPath) {
|
||||
iniConfig = new char[strlen(prefPath) + strlen("isle.ini") + 1]();
|
||||
strcat(iniConfig, prefPath);
|
||||
strcat(iniConfig, "isle.ini");
|
||||
iniConfig = prefPath;
|
||||
iniConfig += "isle.ini";
|
||||
}
|
||||
else {
|
||||
iniConfig = new char[strlen("isle.ini") + 1];
|
||||
strcpy(iniConfig, "isle.ini");
|
||||
iniConfig = "isle.ini";
|
||||
}
|
||||
SDL_Log("Reading configuration from \"%s\"", iniConfig);
|
||||
|
||||
dictionary* dict = iniparser_load(iniConfig);
|
||||
SDL_Log("Reading configuration from \"%s\"", iniConfig.GetData());
|
||||
|
||||
dictionary* dict = iniparser_load(iniConfig.GetData());
|
||||
|
||||
// [library:config]
|
||||
// Load sane defaults if dictionary failed to load
|
||||
@ -1103,20 +1097,20 @@ bool IsleApp::LoadConfig()
|
||||
}
|
||||
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Loading sane defaults");
|
||||
FILE* iniFP = fopen(iniConfig, "wb");
|
||||
FILE* iniFP = fopen(iniConfig.GetData(), "wb");
|
||||
|
||||
if (!iniFP) {
|
||||
SDL_LogError(
|
||||
SDL_LOG_CATEGORY_APPLICATION,
|
||||
"Failed to write config at '%s': %s",
|
||||
iniConfig,
|
||||
iniConfig.GetData(),
|
||||
strerror(errno)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
dict = iniparser_load(iniConfig);
|
||||
dict = iniparser_load(iniConfig.GetData());
|
||||
iniparser_set(dict, "isle", NULL);
|
||||
|
||||
iniparser_set(dict, "isle:diskpath", SDL_GetBasePath());
|
||||
@ -1168,11 +1162,15 @@ bool IsleApp::LoadConfig()
|
||||
#ifdef IOS
|
||||
IOS_SetupDefaultConfigOverrides(dict);
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
Android_SetupDefaultConfigOverrides(dict);
|
||||
#endif
|
||||
|
||||
#ifdef __vita__
|
||||
VITA_SetupDefaultConfigOverrides(dict);
|
||||
#endif
|
||||
iniparser_dump_ini(dict, iniFP);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "New config written at '%s'", iniConfig);
|
||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "New config written at '%s'", iniConfig.GetData());
|
||||
fclose(iniFP);
|
||||
}
|
||||
|
||||
@ -1180,20 +1178,10 @@ bool IsleApp::LoadConfig()
|
||||
Emscripten_SetupDefaultConfigOverrides(dict);
|
||||
#endif
|
||||
|
||||
const char* hdPath = iniparser_getstring(dict, "isle:diskpath", SDL_GetBasePath());
|
||||
m_hdPath = new char[strlen(hdPath) + 1];
|
||||
strcpy(m_hdPath, hdPath);
|
||||
MxOmni::SetHD(m_hdPath);
|
||||
|
||||
const char* cdPath = iniparser_getstring(dict, "isle:cdpath", MxOmni::GetCD());
|
||||
m_cdPath = new char[strlen(cdPath) + 1];
|
||||
strcpy(m_cdPath, cdPath);
|
||||
MxOmni::SetCD(m_cdPath);
|
||||
|
||||
const char* mediaPath = iniparser_getstring(dict, "isle:mediapath", hdPath);
|
||||
m_mediaPath = new char[strlen(mediaPath) + 1];
|
||||
strcpy(m_mediaPath, mediaPath);
|
||||
|
||||
MxOmni::SetHD((m_hdPath = SDL_strdup(iniparser_getstring(dict, "isle:diskpath", SDL_GetBasePath()))));
|
||||
MxOmni::SetCD((m_cdPath = SDL_strdup(iniparser_getstring(dict, "isle:cdpath", MxOmni::GetCD()))));
|
||||
m_savePath = SDL_strdup(iniparser_getstring(dict, "isle:savepath", prefPath));
|
||||
m_mediaPath = SDL_strdup(iniparser_getstring(dict, "isle:mediapath", m_hdPath));
|
||||
m_flipSurfaces = iniparser_getboolean(dict, "isle:Flip Surfaces", m_flipSurfaces);
|
||||
m_fullScreen = iniparser_getboolean(dict, "isle:Full Screen", m_fullScreen);
|
||||
m_exclusiveFullScreen = iniparser_getboolean(dict, "isle:Exclusive Full Screen", m_exclusiveFullScreen);
|
||||
@ -1240,17 +1228,9 @@ bool IsleApp::LoadConfig()
|
||||
|
||||
const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL);
|
||||
if (deviceId != NULL) {
|
||||
m_deviceId = new char[strlen(deviceId) + 1];
|
||||
strcpy(m_deviceId, deviceId);
|
||||
m_deviceId = SDL_strdup(deviceId);
|
||||
}
|
||||
|
||||
// [library:config]
|
||||
// The original game does not save any data if no savepath is given.
|
||||
// Instead, we use SDLs prefPath as a default fallback and always save data.
|
||||
const char* savePath = iniparser_getstring(dict, "isle:savepath", prefPath);
|
||||
m_savePath = new char[strlen(savePath) + 1];
|
||||
strcpy(m_savePath, savePath);
|
||||
|
||||
#ifdef EXTENSIONS
|
||||
for (const char* key : Extensions::availableExtensions) {
|
||||
if (iniparser_getboolean(dict, key, 0)) {
|
||||
@ -1270,11 +1250,12 @@ bool IsleApp::LoadConfig()
|
||||
#endif
|
||||
|
||||
iniparser_freedict(dict);
|
||||
delete[] iniConfig;
|
||||
#ifndef IOS
|
||||
SDL_free(prefPath);
|
||||
#endif
|
||||
|
||||
[](auto path) {
|
||||
if constexpr (std::is_same_v<decltype(path), char*>) {
|
||||
SDL_free(path);
|
||||
}
|
||||
}(prefPath);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1433,12 +1414,12 @@ SDL_AppResult IsleApp::ParseArguments(int argc, char** argv)
|
||||
consumed = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "--help") == 0) {
|
||||
DisplayArgumentHelp();
|
||||
DisplayArgumentHelp(argv[0]);
|
||||
return SDL_APP_SUCCESS;
|
||||
}
|
||||
if (consumed <= 0) {
|
||||
SDL_Log("Invalid argument(s): %s", argv[i]);
|
||||
DisplayArgumentHelp();
|
||||
DisplayArgumentHelp(argv[0]);
|
||||
return SDL_APP_FAILURE;
|
||||
}
|
||||
}
|
||||
@ -1446,9 +1427,9 @@ SDL_AppResult IsleApp::ParseArguments(int argc, char** argv)
|
||||
return SDL_APP_CONTINUE;
|
||||
}
|
||||
|
||||
void IsleApp::DisplayArgumentHelp()
|
||||
void IsleApp::DisplayArgumentHelp(const char* p_execName)
|
||||
{
|
||||
SDL_Log("Usage: isle [options]");
|
||||
SDL_Log("Usage: %s [options]", p_execName);
|
||||
SDL_Log("Options:");
|
||||
SDL_Log(" --ini <path> Set custom path to .ini config");
|
||||
#ifdef ISLE_DEBUG
|
||||
|
||||
@ -99,9 +99,9 @@ class IsleApp {
|
||||
const CursorBitmap* m_cursorCurrentBitmap;
|
||||
char* m_mediaPath;
|
||||
MxFloat m_cursorSensitivity;
|
||||
void DisplayArgumentHelp();
|
||||
void DisplayArgumentHelp(const char* p_execName);
|
||||
|
||||
char* m_iniPath;
|
||||
const char* m_iniPath;
|
||||
MxFloat m_maxLod;
|
||||
MxU32 m_maxAllowedExtras;
|
||||
MxTransitionManager::TransitionType m_transitionType;
|
||||
|
||||
@ -68,10 +68,10 @@ class DebugViewer {
|
||||
static void InsideBuildingManager()
|
||||
{
|
||||
auto buildingManager = Lego()->GetBuildingManager();
|
||||
ImGui::Text("nextVariant: %d", buildingManager->m_nextVariant);
|
||||
ImGui::Text("nextVariant: %u", buildingManager->m_nextVariant);
|
||||
ImGui::Text("m_boundariesDetermined: %d", buildingManager->m_boundariesDetermined);
|
||||
ImGui::Text("m_hideAfterAnimation: %d", buildingManager->m_hideAfterAnimation);
|
||||
ImGui::Text("#Animated Entries", buildingManager->m_numEntries);
|
||||
ImGui::Text("#Animated Entries: %d", buildingManager->m_numEntries);
|
||||
if (buildingManager->m_numEntries) {
|
||||
if (ImGui::BeginTable("Animated Entries", 6, ImGuiTableFlags_Borders)) {
|
||||
ImGui::TableSetupColumn("ROI Name");
|
||||
@ -293,7 +293,7 @@ void IsleDebug_Render()
|
||||
ImGui::Text("Current act: %d", gameState->GetCurrentAct());
|
||||
ImGui::Text("Loaded act: %d", gameState->GetLoadedAct());
|
||||
ImGui::Text("Previous area: %d", gameState->m_previousArea);
|
||||
ImGui::Text("Unknown 0x42c: %d", gameState->m_unk0x42c);
|
||||
ImGui::Text("Saved previous area: %d", gameState->m_savedPreviousArea);
|
||||
ImGui::Value("Player count", gameState->m_playerCount);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
@ -8,6 +8,13 @@
|
||||
// SIZE 0x194
|
||||
class Act2Brick : public LegoPathActor {
|
||||
public:
|
||||
enum {
|
||||
e_removed = 0,
|
||||
e_created = 1,
|
||||
e_placed = 2,
|
||||
e_atRest = 3,
|
||||
};
|
||||
|
||||
Act2Brick();
|
||||
~Act2Brick() override; // vtable+0x00
|
||||
|
||||
@ -35,7 +42,7 @@ class Act2Brick : public LegoPathActor {
|
||||
|
||||
MxResult Create(MxS32 p_index);
|
||||
void Remove();
|
||||
void FUN_1007a670(MxMatrix& p_param1, MxMatrix& p_param2, LegoPathBoundary* p_boundary);
|
||||
void Place(MxMatrix& p_localToWorld, MxMatrix& p_endLocalToWorld, LegoPathBoundary* p_boundary);
|
||||
void PlayWhistleSound();
|
||||
void StopWhistleSound();
|
||||
void Mute(MxBool p_muted);
|
||||
@ -44,12 +51,12 @@ class Act2Brick : public LegoPathActor {
|
||||
static const LegoChar* g_lodNames[];
|
||||
static MxLong g_lastHitActorTime;
|
||||
|
||||
LegoCacheSound* m_whistleSound; // 0x154
|
||||
undefined m_unk0x158[0x0c]; // 0x158
|
||||
undefined4 m_unk0x164; // 0x164
|
||||
Mx3DPointFloat m_unk0x168; // 0x168
|
||||
Mx3DPointFloat m_unk0x17c; // 0x17c
|
||||
MxS32 m_unk0x190; // 0x190
|
||||
LegoCacheSound* m_whistleSound; // 0x154
|
||||
undefined m_unk0x158[0x0c]; // 0x158
|
||||
MxU32 m_state; // 0x164
|
||||
Mx3DPointFloat m_localToWorldMovementStep; // 0x168
|
||||
Mx3DPointFloat m_endLocalToWorld; // 0x17c
|
||||
MxS32 m_step; // 0x190
|
||||
};
|
||||
|
||||
#endif // ACT2BRICK_H
|
||||
|
||||
@ -18,14 +18,20 @@ class MxQuaternionTransformer;
|
||||
|
||||
// SIZE 0x0c
|
||||
struct Act3ListElement {
|
||||
MxU32 m_objectId; // 0x00
|
||||
undefined4 m_unk0x04; // 0x04
|
||||
MxBool m_hasStarted; // 0x08
|
||||
enum InsertMode {
|
||||
e_replaceAction = 1,
|
||||
e_queueAction = 2,
|
||||
e_onlyIfEmpty = 3
|
||||
};
|
||||
|
||||
MxU32 m_objectId; // 0x00
|
||||
InsertMode m_insertMode; // 0x04
|
||||
MxBool m_hasStarted; // 0x08
|
||||
|
||||
Act3ListElement() {}
|
||||
|
||||
Act3ListElement(MxU32 p_objectId, undefined4 p_unk0x04, MxBool p_hasStarted)
|
||||
: m_objectId(p_objectId), m_unk0x04(p_unk0x04), m_hasStarted(p_hasStarted)
|
||||
Act3ListElement(MxU32 p_objectId, InsertMode p_insertMode, MxBool p_hasStarted)
|
||||
: m_objectId(p_objectId), m_insertMode(p_insertMode), m_hasStarted(p_hasStarted)
|
||||
{
|
||||
}
|
||||
|
||||
@ -36,21 +42,15 @@ struct Act3ListElement {
|
||||
// SIZE 0x10
|
||||
class Act3List : private list<Act3ListElement> {
|
||||
public:
|
||||
enum InsertMode {
|
||||
e_replaceAction = 1,
|
||||
e_queueAction = 2,
|
||||
e_onlyIfEmpty = 3
|
||||
};
|
||||
Act3List() { m_cleared = FALSE; }
|
||||
|
||||
Act3List() { m_unk0x0c = 0; }
|
||||
|
||||
void Insert(MxS32 p_objectId, InsertMode p_option);
|
||||
void Insert(MxS32 p_objectId, Act3ListElement::InsertMode p_option);
|
||||
void DeleteActionWrapper();
|
||||
void Clear();
|
||||
void RemoveByObjectIdOrFirst(MxU32 p_objectId);
|
||||
|
||||
private:
|
||||
undefined4 m_unk0x0c; // 0x0c
|
||||
MxU32 m_cleared; // 0x0c
|
||||
};
|
||||
|
||||
// VTABLE: LEGO1 0x100d4fc8
|
||||
@ -58,7 +58,14 @@ class Act3List : private list<Act3ListElement> {
|
||||
// SIZE 0x0c
|
||||
class Act3State : public LegoState {
|
||||
public:
|
||||
Act3State() { m_unk0x08 = 0; }
|
||||
enum {
|
||||
e_initial = 0,
|
||||
e_ready = 1,
|
||||
e_goodEnding = 2,
|
||||
e_badEnding = 3,
|
||||
};
|
||||
|
||||
Act3State() { m_state = Act3State::e_initial; }
|
||||
|
||||
// FUNCTION: LEGO1 0x1000e2f0
|
||||
MxBool IsSerializable() override { return FALSE; }
|
||||
@ -80,11 +87,11 @@ class Act3State : public LegoState {
|
||||
// SYNTHETIC: LEGO1 0x1000e3c0
|
||||
// Act3State::`scalar deleting destructor'
|
||||
|
||||
undefined4 GetUnknown0x08() { return m_unk0x08; }
|
||||
MxU32 GetState() { return m_state; }
|
||||
|
||||
// TODO: Most likely getters/setters are not used according to BETA.
|
||||
|
||||
undefined4 m_unk0x08; // 0x08
|
||||
MxU32 m_state; // 0x08
|
||||
};
|
||||
|
||||
// VTABLE: LEGO1 0x100d9628
|
||||
|
||||
@ -119,25 +119,6 @@ struct InfocenterMapEntry {
|
||||
// SIZE 0x1d8
|
||||
class Infocenter : public LegoWorld {
|
||||
public:
|
||||
enum Cutscene {
|
||||
e_noIntro = -1,
|
||||
e_legoMovie,
|
||||
e_mindscapeMovie,
|
||||
e_introMovie,
|
||||
e_outroMovie,
|
||||
e_badEndMovie,
|
||||
e_goodEndMovie
|
||||
};
|
||||
|
||||
enum Character {
|
||||
e_noCharacter = 0,
|
||||
e_pepper,
|
||||
e_mama,
|
||||
e_papa,
|
||||
e_nick,
|
||||
e_laura
|
||||
};
|
||||
|
||||
Infocenter();
|
||||
~Infocenter() override;
|
||||
|
||||
@ -180,7 +161,7 @@ class Infocenter : public LegoWorld {
|
||||
void UpdateFrameHot(MxBool p_display);
|
||||
void Reset();
|
||||
|
||||
void PlayCutscene(Cutscene p_entityId, MxBool p_scale);
|
||||
void PlayCutscene(IntroScript::Script p_entityId, MxBool p_scale);
|
||||
void StopCutscene();
|
||||
|
||||
void UpdateEnabledGlowControl(MxS32 p_x, MxS32 p_y);
|
||||
@ -198,7 +179,7 @@ class Infocenter : public LegoWorld {
|
||||
MxS16 m_selectedCharacter; // 0xfc
|
||||
InfocenterState* m_infocenterState; // 0x100
|
||||
LegoGameState::Area m_destLocation; // 0x104
|
||||
Cutscene m_currentCutscene; // 0x108
|
||||
IntroScript::Script m_currentCutscene; // 0x108
|
||||
Radio m_radio; // 0x10c
|
||||
MxStillPresenter* m_dragPresenter; // 0x11c
|
||||
InfocenterMapEntry m_glowInfo[7]; // 0x120
|
||||
|
||||
@ -75,11 +75,11 @@ class Act1State : public LegoState {
|
||||
|
||||
MxU32 GetState() { return m_state; }
|
||||
ElevatorFloor GetElevatorFloor() { return (ElevatorFloor) m_elevFloor; }
|
||||
MxU8 GetUnknown21() { return m_unk0x021; }
|
||||
MxBool IsSpawnInInfocenter() { return m_spawnInInfocenter; }
|
||||
|
||||
void SetState(MxU32 p_state) { m_state = p_state; }
|
||||
void SetElevatorFloor(ElevatorFloor p_elevFloor) { m_elevFloor = p_elevFloor; }
|
||||
void SetUnknown21(MxU8 p_unk0x21) { m_unk0x021 = p_unk0x21; }
|
||||
void SetSpawnInInfocenter(MxBool p_spawnInInfocenter) { m_spawnInInfocenter = p_spawnInInfocenter; }
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10033960
|
||||
// Act1State::`scalar deleting destructor'
|
||||
@ -90,11 +90,11 @@ class Act1State : public LegoState {
|
||||
IsleScript::Script m_currentCptClickDialogue; // 0x014
|
||||
MxU32 m_state; // 0x018
|
||||
MxS16 m_elevFloor; // 0x01c
|
||||
MxBool m_unk0x01e; // 0x01e
|
||||
MxBool m_unk0x01f; // 0x01f
|
||||
MxBool m_playingFloor2Animation; // 0x01e
|
||||
MxBool m_switchedToArea; // 0x01f
|
||||
MxBool m_planeActive; // 0x020
|
||||
undefined m_unk0x021; // 0x021
|
||||
MxBool m_unk0x022; // 0x022
|
||||
MxBool m_spawnInInfocenter; // 0x021
|
||||
MxBool m_playedExitExplanation; // 0x022
|
||||
undefined m_unk0x023; // 0x023
|
||||
LegoNamedPlane m_motocyclePlane; // 0x024
|
||||
LegoNamedPlane m_bikePlane; // 0x070
|
||||
|
||||
@ -15,9 +15,13 @@ class MxEndActionNotificationParam;
|
||||
// SIZE 0x10
|
||||
class LegoAct2State : public LegoState {
|
||||
public:
|
||||
enum {
|
||||
c_badEnding = 104
|
||||
};
|
||||
|
||||
LegoAct2State()
|
||||
{
|
||||
m_unk0x08 = 0;
|
||||
m_state = 0;
|
||||
m_enabled = FALSE;
|
||||
}
|
||||
~LegoAct2State() override {}
|
||||
@ -43,14 +47,14 @@ class LegoAct2State : public LegoState {
|
||||
// LegoAct2State::`scalar deleting destructor'
|
||||
|
||||
// FUNCTION: BETA10 0x100151b0
|
||||
void SetUnknown0x08(undefined4 p_unk0x08) { m_unk0x08 = p_unk0x08; }
|
||||
void SetState(MxU32 p_state) { m_state = p_state; }
|
||||
|
||||
undefined4 GetUnknown0x08() { return m_unk0x08; }
|
||||
MxU32 GetState() { return m_state; }
|
||||
|
||||
// TODO: Most likely getters/setters are not used according to BETA. (?)
|
||||
|
||||
undefined4 m_unk0x08; // 0x08
|
||||
MxBool m_enabled; // 0x0c
|
||||
MxU32 m_state; // 0x08
|
||||
MxBool m_enabled; // 0x0c
|
||||
};
|
||||
|
||||
// VTABLE: LEGO1 0x100d82e0
|
||||
|
||||
@ -8,13 +8,13 @@ class LegoAnim;
|
||||
|
||||
// SIZE 0x20
|
||||
struct LegoAnimActorStruct {
|
||||
LegoAnimActorStruct(float p_unk0x00, LegoAnim* p_AnimTreePtr, LegoROI** p_roiMap, MxU32 p_numROIs);
|
||||
LegoAnimActorStruct(float p_worldSpeed, LegoAnim* p_AnimTreePtr, LegoROI** p_roiMap, MxU32 p_numROIs);
|
||||
~LegoAnimActorStruct();
|
||||
|
||||
float GetDuration();
|
||||
|
||||
// FUNCTION: BETA10 0x1000fb10
|
||||
float GetUnknown0x00() { return m_unk0x00; }
|
||||
float GetWorldSpeed() { return m_worldSpeed; }
|
||||
|
||||
// FUNCTION: BETA10 0x10012210
|
||||
LegoAnim* GetAnimTreePtr() { return m_AnimTreePtr; }
|
||||
@ -23,7 +23,7 @@ struct LegoAnimActorStruct {
|
||||
LegoROI** GetROIMap() { return m_roiMap; }
|
||||
|
||||
// TODO: Possibly private
|
||||
float m_unk0x00; // 0x00
|
||||
float m_worldSpeed; // 0x00
|
||||
LegoAnim* m_AnimTreePtr; // 0x04
|
||||
LegoROI** m_roiMap; // 0x08
|
||||
MxU32 m_numROIs; // 0x0c
|
||||
@ -47,9 +47,14 @@ class LegoAnimActor : public virtual LegoPathActor {
|
||||
void Animate(float p_time) override; // vtable+0x70
|
||||
void VTable0x74(Matrix4& p_transform) override; // vtable+0x74
|
||||
|
||||
virtual MxResult FUN_1001c1f0(float& p_und);
|
||||
virtual MxResult FUN_1001c360(float, Matrix4& p_transform);
|
||||
virtual MxResult FUN_1001c450(LegoAnim* p_AnimTreePtr, float p_unk0x00, LegoROI** p_roiMap, MxU32 p_numROIs);
|
||||
virtual MxResult GetTimeInCycle(float& p_timeInCycle);
|
||||
virtual MxResult AnimateWithTransform(float p_time, Matrix4& p_transform);
|
||||
virtual MxResult CreateAnimActorStruct(
|
||||
LegoAnim* p_AnimTreePtr,
|
||||
float p_worldSpeed,
|
||||
LegoROI** p_roiMap,
|
||||
MxU32 p_numROIs
|
||||
);
|
||||
virtual void ClearMaps();
|
||||
|
||||
// FUNCTION: LEGO1 0x1000fba0
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
class LegoCacheSound : public MxCore {
|
||||
public:
|
||||
LegoCacheSound();
|
||||
LegoCacheSound(LegoCacheSound& p_sound);
|
||||
~LegoCacheSound() override; // vtable+0x00
|
||||
|
||||
// FUNCTION: LEGO1 0x10006580
|
||||
@ -49,6 +50,8 @@ class LegoCacheSound : public MxCore {
|
||||
void SetDistance(MxS32 p_min, MxS32 p_max);
|
||||
void MuteSilence(MxBool p_muted);
|
||||
void MuteStop(MxBool p_mute);
|
||||
LegoCacheSound& operator=(LegoCacheSound& p_sound);
|
||||
void CopyFrom(LegoCacheSound& p_sound);
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10006610
|
||||
// SYNTHETIC: BETA10 0x100675b0
|
||||
|
||||
@ -76,9 +76,9 @@ class LegoEntity : public MxEntity {
|
||||
virtual void SwitchColor(LegoROI* p_roi); // vtable+0x48
|
||||
virtual void SwitchMood(); // vtable+0x4c
|
||||
|
||||
void FUN_10010c30();
|
||||
void TransformPointOfView();
|
||||
void SetType(MxU8 p_type);
|
||||
void SetLocation(const Vector3& p_location, const Vector3& p_direction, const Vector3& p_up, MxBool p_und);
|
||||
void SetLocation(const Vector3& p_location, const Vector3& p_direction, const Vector3& p_up, MxBool p_updateCamera);
|
||||
Mx3DPointFloat GetWorldDirection();
|
||||
Mx3DPointFloat GetWorldUp();
|
||||
Mx3DPointFloat GetWorldPosition();
|
||||
|
||||
@ -179,7 +179,7 @@ class LegoGameState {
|
||||
History();
|
||||
void WriteScoreHistory();
|
||||
MxResult Serialize(LegoStorage* p_storage);
|
||||
ScoreItem* FindPlayerInScoreHistory(Username* p_player, MxS16 p_unk0x24, MxS32& p_unk0x2c);
|
||||
ScoreItem* FindPlayerInScoreHistory(Username* p_player, MxS16 p_playerId, MxS32& p_playerScoreHistoryIndex);
|
||||
|
||||
// FUNCTION: BETA10 0x1002c2b0
|
||||
MxS16 GetCount() { return m_count; }
|
||||
@ -269,7 +269,7 @@ class LegoGameState {
|
||||
MxBool m_isDirty; // 0x420
|
||||
Area m_currentArea; // 0x424
|
||||
Area m_previousArea; // 0x428
|
||||
Area m_unk0x42c; // 0x42c
|
||||
Area m_savedPreviousArea; // 0x42c
|
||||
|
||||
static const InternationalCharacter g_intCharacters[8];
|
||||
};
|
||||
|
||||
@ -208,6 +208,7 @@ class LegoOmni : public MxOmni {
|
||||
|
||||
void SetVersion10(MxBool p_version10) { m_version10 = p_version10; }
|
||||
MxBool IsVersion10() { return m_version10; }
|
||||
LEGO1_EXPORT void LoadSiLoader();
|
||||
|
||||
// SYNTHETIC: LEGO1 0x10058b30
|
||||
// SYNTHETIC: BETA10 0x1008f8d0
|
||||
|
||||
@ -72,7 +72,12 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id);
|
||||
void EnableAnimations(MxBool p_enable);
|
||||
void SetAppCursor(Cursor p_cursor);
|
||||
MxBool CanExit();
|
||||
MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_worldAtom, MxS32 p_worldEntityId);
|
||||
MxBool RemoveFromWorld(
|
||||
const MxAtomId& p_entityAtom,
|
||||
MxS32 p_entityId,
|
||||
const MxAtomId& p_worldAtom,
|
||||
MxS32 p_worldEntityId
|
||||
);
|
||||
MxS32 UpdateLightPosition(MxS32 p_increase);
|
||||
void SetLightPosition(MxS32 p_index);
|
||||
LegoNamedTexture* ReadNamedTexture(LegoStorage* p_storage);
|
||||
|
||||
@ -48,6 +48,7 @@ class MxBackgroundAudioManager : public MxCore {
|
||||
virtual MxResult Create(MxAtomId& p_script, MxU32 p_frequencyMS);
|
||||
|
||||
void Init();
|
||||
void Update(MxS32 p_targetVolume, MxS32 p_speed, MxPresenter::TickleState p_tickleState);
|
||||
void Stop();
|
||||
void LowerVolume();
|
||||
void RaiseVolume();
|
||||
|
||||
@ -15,7 +15,7 @@ class RaceSkel : public LegoAnimActor {
|
||||
|
||||
void ParseAction(char* p_extra) override; // vtable+0x20
|
||||
|
||||
MxResult FUN_1001c360(float p_und, Matrix4& p_transform) override;
|
||||
MxResult AnimateWithTransform(float p_time, Matrix4& p_transform) override;
|
||||
|
||||
virtual void FUN_10071c80(Vector3& p_vec);
|
||||
|
||||
|
||||
@ -57,39 +57,39 @@ MxBool g_unk0x100f0f28 = FALSE;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f0f30
|
||||
// GLOBAL: BETA10 0x101dbe48
|
||||
MxS32 g_unk0x100f0f30[] = {2, 23, 32, 66, 71, 72, 73, -1};
|
||||
MxS32 g_stage0Plants[] = {2, 23, 32, 66, 71, 72, 73, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f0f50
|
||||
// GLOBAL: BETA10 0x101dbe68
|
||||
MxS32 g_unk0x100f0f50[] = {0, 7, 16, 18, 20, 21, 34, 49, 58, 59, 63, 65, 69, 74, -1};
|
||||
MxS32 g_stage1Plants[] = {0, 7, 16, 18, 20, 21, 34, 49, 58, 59, 63, 65, 69, 74, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f0f90
|
||||
// GLOBAL: BETA10 0x101dbea8
|
||||
MxS32 g_unk0x100f0f90[] = {12, 19, 24, 48, 60, -1};
|
||||
MxS32 g_stage2Plants[] = {12, 19, 24, 48, 60, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f0fa8
|
||||
// GLOBAL: BETA10 0x101dbec0
|
||||
MxS32 g_unk0x100f0fa8[] = {8, 15, 46, -1};
|
||||
MxS32 g_stage3Plants[] = {8, 15, 46, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f0fb8
|
||||
// GLOBAL: BETA10 0x101dbed0
|
||||
MxS32 g_unk0x100f0fb8[] = {25, 26, 28, 29, 38, 39, 42, 50, 51, 56, -1};
|
||||
MxS32 g_stage4Plants[] = {25, 26, 28, 29, 38, 39, 42, 50, 51, 56, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f0fe8
|
||||
// GLOBAL: BETA10 0x101dbf00
|
||||
MxS32 g_unk0x100f0fe8[] = {3, 40, 53, 55, -1};
|
||||
MxS32 g_stage5Plants[] = {3, 40, 53, 55, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f1000
|
||||
// GLOBAL: BETA10 0x101dbf18
|
||||
MxS32 g_unk0x100f1000[] = {22, 33, 41, 45, 67, -1};
|
||||
MxS32 g_stage6Plants[] = {22, 33, 41, 45, 67, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f1018
|
||||
// GLOBAL: BETA10 0x101dbf30
|
||||
MxS32 g_unk0x100f1018[] = {13, 30, 31, 62, -1};
|
||||
MxS32 g_stage7Plants[] = {13, 30, 31, 62, -1};
|
||||
|
||||
// GLOBAL: LEGO1 0x100f1030
|
||||
// GLOBAL: BETA10 0x101dbf48
|
||||
MxS32 g_unk0x100f1030[] = {1, 27, 37, 44, 47, 54, 61, 64, -1};
|
||||
MxS32 g_stage8Plants[] = {1, 27, 37, 44, 47, 54, 61, 64, -1};
|
||||
|
||||
// --- End of indices into g_plantInfo ---
|
||||
|
||||
@ -144,7 +144,7 @@ void Act2Actor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2)
|
||||
void Act2Actor::FUN_10018980()
|
||||
{
|
||||
for (MxS32 i = 0; i < m_animMaps.size(); i++) {
|
||||
if (m_animMaps[i]->GetUnknown0x00() == -1.0f) {
|
||||
if (m_animMaps[i]->GetWorldSpeed() == -1.0f) {
|
||||
m_shootAnim = m_animMaps[i];
|
||||
}
|
||||
}
|
||||
@ -727,9 +727,9 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f0f30[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f0f30[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f0f30[i]].m_entity;
|
||||
for (i = 0; g_stage0Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage0Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage0Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -741,9 +741,9 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f0f50[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f0f50[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f0f50[i]].m_entity;
|
||||
for (i = 0; g_stage1Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage1Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage1Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -759,9 +759,9 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f0f90[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f0f90[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f0f90[i]].m_entity;
|
||||
for (i = 0; g_stage2Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage2Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage2Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -781,9 +781,9 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f0fa8[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f0fa8[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f0fa8[i]].m_entity;
|
||||
for (i = 0; g_stage3Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage3Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage3Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -799,9 +799,9 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f0fb8[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f0fb8[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f0fb8[i]].m_entity;
|
||||
for (i = 0; g_stage4Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage4Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage4Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -813,9 +813,9 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f0fe8[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f0fe8[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f0fe8[i]].m_entity;
|
||||
for (i = 0; g_stage5Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage5Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage5Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -827,9 +827,9 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f1000[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f1000[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f1000[i]].m_entity;
|
||||
for (i = 0; g_stage6Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage6Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage6Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -841,18 +841,18 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
|
||||
*p_param = TRUE;
|
||||
}
|
||||
else {
|
||||
for (i = 0; g_unk0x100f1018[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f1018[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f1018[i]].m_entity;
|
||||
for (i = 0; g_stage7Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage7Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage7Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
for (i = 0; g_unk0x100f1030[i] != -1; i++) {
|
||||
if (plantInfo[g_unk0x100f1030[i]].m_counter) {
|
||||
result = plantInfo[g_unk0x100f1030[i]].m_entity;
|
||||
for (i = 0; g_stage8Plants[i] != -1; i++) {
|
||||
if (plantInfo[g_stage8Plants[i]].m_counter) {
|
||||
result = plantInfo[g_stage8Plants[i]].m_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,7 +271,7 @@ void Act3Cop::ParseAction(char* p_extra)
|
||||
}
|
||||
|
||||
for (i = 0; i < m_animMaps.size(); i++) {
|
||||
if (m_animMaps[i]->GetUnknown0x00() == -1.0f) {
|
||||
if (m_animMaps[i]->GetWorldSpeed() == -1.0f) {
|
||||
m_eatAnim = m_animMaps[i];
|
||||
}
|
||||
}
|
||||
@ -559,7 +559,7 @@ void Act3Brickster::ParseAction(char* p_extra)
|
||||
((Act3*) m_world)->SetBrickster(this);
|
||||
|
||||
for (MxS32 i = 0; i < m_animMaps.size(); i++) {
|
||||
if (m_animMaps[i]->GetUnknown0x00() == -1.0f) {
|
||||
if (m_animMaps[i]->GetWorldSpeed() == -1.0f) {
|
||||
m_shootAnim = m_animMaps[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,8 +111,8 @@ void Bike::ActivateSceneActions()
|
||||
PlayMusic(JukeboxScript::c_InformationCenter_Music);
|
||||
|
||||
Act1State* act1state = (Act1State*) GameState()->GetState("Act1State");
|
||||
if (!act1state->m_unk0x022) {
|
||||
act1state->m_unk0x022 = TRUE;
|
||||
if (!act1state->m_playedExitExplanation) {
|
||||
act1state->m_playedExitExplanation = TRUE;
|
||||
|
||||
MxMatrix mat(UserActor()->GetROI()->GetLocal2World());
|
||||
mat.TranslateBy(mat[2][0] * 2.5, mat[2][1] + 0.7, mat[2][2] * 2.5);
|
||||
|
||||
@ -195,8 +195,8 @@ void DuneBuggy::ActivateSceneActions()
|
||||
PlayMusic(JukeboxScript::c_GarageArea_Music);
|
||||
|
||||
Act1State* act1state = (Act1State*) GameState()->GetState("Act1State");
|
||||
if (!act1state->m_unk0x022) {
|
||||
act1state->m_unk0x022 = TRUE;
|
||||
if (!act1state->m_playedExitExplanation) {
|
||||
act1state->m_playedExitExplanation = TRUE;
|
||||
|
||||
MxMatrix mat(UserActor()->GetROI()->GetLocal2World());
|
||||
mat.TranslateBy(mat[2][0] * 2.5, mat[2][1] + 0.7, mat[2][2] * 2.5);
|
||||
|
||||
@ -342,7 +342,7 @@ MxLong Helicopter::HandleEndAnim(LegoEndAnimNotificationParam& p_param)
|
||||
|
||||
assert(m_world && m_world->GetCameraController());
|
||||
m_world->GetCameraController()->SetWorldTransform(at, dir, up);
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
@ -388,13 +388,13 @@ void Helicopter::VTable0x74(Matrix4& p_transform)
|
||||
{
|
||||
if (m_userNavFlag) {
|
||||
m_roi->UpdateTransformationRelativeToParent(p_transform);
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
else {
|
||||
m_roi->SetLocal2World(p_transform);
|
||||
m_roi->WrappedUpdateWorldData();
|
||||
if (m_cameraFlag) {
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ void IslePathActor::Enter()
|
||||
|
||||
SetUserActor(this);
|
||||
FUN_1001b660();
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ void IslePathActor::Exit()
|
||||
}
|
||||
|
||||
FUN_1001b660();
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
ResetViewVelocity();
|
||||
}
|
||||
|
||||
@ -633,7 +633,7 @@ void IslePathActor::VTable0xec(MxMatrix p_transform, LegoPathBoundary* p_boundar
|
||||
m_roi->SetLocal2World(p_transform);
|
||||
if (m_cameraFlag) {
|
||||
ResetViewVelocity();
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -165,11 +165,11 @@ void Jetski::ActivateSceneActions()
|
||||
|
||||
Act1State* act1state = (Act1State*) GameState()->GetState("Act1State");
|
||||
if (!act1state->m_state) {
|
||||
if (act1state->m_unk0x022) {
|
||||
if (act1state->m_playedExitExplanation) {
|
||||
PlayCamAnim(this, FALSE, 68, TRUE);
|
||||
}
|
||||
else {
|
||||
act1state->m_unk0x022 = TRUE;
|
||||
act1state->m_playedExitExplanation = TRUE;
|
||||
|
||||
LegoPathActor* user = UserActor();
|
||||
if (user != NULL) {
|
||||
|
||||
@ -153,8 +153,8 @@ void Motocycle::ActivateSceneActions()
|
||||
PlayMusic(JukeboxScript::c_PoliceStation_Music);
|
||||
|
||||
Act1State* act1state = (Act1State*) GameState()->GetState("Act1State");
|
||||
if (!act1state->m_unk0x022) {
|
||||
act1state->m_unk0x022 = TRUE;
|
||||
if (!act1state->m_playedExitExplanation) {
|
||||
act1state->m_playedExitExplanation = TRUE;
|
||||
|
||||
MxMatrix mat(UserActor()->GetROI()->GetLocal2World());
|
||||
mat.TranslateBy(mat[2][0] * 2.5, mat[2][1] + 0.7, mat[2][2] * 2.5);
|
||||
|
||||
@ -151,8 +151,8 @@ void SkateBoard::ActivateSceneActions()
|
||||
if (m_act1state->m_state != Act1State::e_pizza) {
|
||||
PlayMusic(JukeboxScript::c_BeachBlvd_Music);
|
||||
|
||||
if (!m_act1state->m_unk0x022) {
|
||||
m_act1state->m_unk0x022 = TRUE;
|
||||
if (!m_act1state->m_playedExitExplanation) {
|
||||
m_act1state->m_playedExitExplanation = TRUE;
|
||||
|
||||
MxMatrix mat(UserActor()->GetROI()->GetLocal2World());
|
||||
mat.TranslateBy(mat[2][0] * 2.5, mat[2][1] + 0.2, mat[2][2] * 2.5);
|
||||
|
||||
@ -272,6 +272,29 @@ void LegoCacheSound::MuteStop(MxBool p_muted)
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x10066fa9
|
||||
LegoCacheSound::LegoCacheSound(LegoCacheSound& p_sound)
|
||||
{
|
||||
CopyFrom(p_sound);
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x10067062
|
||||
LegoCacheSound& LegoCacheSound::operator=(LegoCacheSound& p_sound)
|
||||
{
|
||||
if (this == &p_sound) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
CopyFrom(p_sound);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x1006709d
|
||||
void LegoCacheSound::CopyFrom(LegoCacheSound& p_sound)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10006d80
|
||||
// FUNCTION: BETA10 0x100670e7
|
||||
MxString LegoCacheSound::GetBaseFilename(MxString& p_path)
|
||||
|
||||
@ -119,7 +119,12 @@ void MxBackgroundAudioManager::FadeInPendingPresenter()
|
||||
MxS32 compare, volume;
|
||||
|
||||
if (m_activePresenter == NULL) {
|
||||
if (m_pendingPresenter) {
|
||||
if (m_pendingPresenter && m_pendingPresenter->GetCurrentTickleState() >= MxPresenter::e_streaming) {
|
||||
if (!m_pendingPresenter->IsEnabled()) {
|
||||
m_pendingPresenter->Enable(TRUE);
|
||||
m_pendingPresenter->SetTickleState(MxPresenter::e_streaming);
|
||||
}
|
||||
|
||||
if (m_volumeSuppressionAmount != 0) {
|
||||
compare = 30;
|
||||
}
|
||||
@ -221,6 +226,12 @@ void MxBackgroundAudioManager::StartAction(MxParam& p_param)
|
||||
m_action2.SetObjectId(m_pendingPresenter->GetAction()->GetObjectId());
|
||||
m_targetVolume = ((MxDSSound*) (m_pendingPresenter->GetAction()))->GetVolume();
|
||||
m_pendingPresenter->SetVolume(0);
|
||||
|
||||
// Disabling the action here and starting it later once the actively presented music has been faded out.
|
||||
// This was not necessary in retail because the streaming layer would implicitly not start another action
|
||||
// before the previous one has ended (since it's all coming from JUKEBOX.SI), however since we now
|
||||
// allow loading music from multiple SI files this would cause the new music to start immediately.
|
||||
m_pendingPresenter->GetAction()->SetFlags(m_pendingPresenter->GetAction()->GetFlags() & ~MxDSAction::c_enabled);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f200
|
||||
@ -254,7 +265,8 @@ MxResult MxBackgroundAudioManager::PlayMusic(
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (m_action2.GetObjectId() == -1 && m_action1.GetObjectId() != p_action.GetObjectId()) {
|
||||
if (m_action2.GetObjectId() == -1 &&
|
||||
(m_action1.GetObjectId() != p_action.GetObjectId() || m_action1.GetAtomId() != p_action.GetAtomId())) {
|
||||
MxDSAction action;
|
||||
action.SetAtomId(GetCurrentAction().GetAtomId());
|
||||
action.SetObjectId(GetCurrentAction().GetObjectId());
|
||||
@ -275,6 +287,10 @@ MxResult MxBackgroundAudioManager::PlayMusic(
|
||||
m_tickleState = p_tickleState;
|
||||
m_speed = p_speed;
|
||||
}
|
||||
else {
|
||||
m_action2.SetAtomId(MxAtomId());
|
||||
m_action2.SetObjectId(-1);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -282,6 +298,17 @@ MxResult MxBackgroundAudioManager::PlayMusic(
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x100e92ec
|
||||
void MxBackgroundAudioManager::Update(MxS32 p_targetVolume, MxS32 p_speed, MxPresenter::TickleState p_tickleState)
|
||||
{
|
||||
assert(p_targetVolume >= 0 && p_targetVolume <= 100);
|
||||
assert(p_speed > 0);
|
||||
|
||||
m_tickleState = p_tickleState;
|
||||
m_speed = p_speed;
|
||||
m_targetVolume = p_targetVolume;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007f470
|
||||
// FUNCTION: BETA10 0x100e9388
|
||||
void MxBackgroundAudioManager::Stop()
|
||||
|
||||
@ -167,7 +167,7 @@ LegoGameState::LegoGameState()
|
||||
m_jukeboxMusic = JukeboxScript::c_noneJukebox;
|
||||
m_currentArea = e_undefined;
|
||||
m_previousArea = e_undefined;
|
||||
m_unk0x42c = e_undefined;
|
||||
m_savedPreviousArea = e_undefined;
|
||||
m_playerCount = 0;
|
||||
m_isDirty = FALSE;
|
||||
m_loadedAct = e_actNotFound;
|
||||
@ -326,7 +326,7 @@ MxResult LegoGameState::Save(MxULong p_slot)
|
||||
}
|
||||
}
|
||||
|
||||
area = m_unk0x42c;
|
||||
area = m_savedPreviousArea;
|
||||
storage.WriteU16(area);
|
||||
SerializeScoreHistory(LegoFile::c_write);
|
||||
m_isDirty = FALSE;
|
||||
@ -445,10 +445,10 @@ MxResult LegoGameState::Load(MxULong p_slot)
|
||||
storage.ReadS16(actArea);
|
||||
|
||||
if (m_currentAct == e_act1) {
|
||||
m_unk0x42c = e_undefined;
|
||||
m_savedPreviousArea = e_undefined;
|
||||
}
|
||||
else {
|
||||
m_unk0x42c = (Area) actArea;
|
||||
m_savedPreviousArea = (Area) actArea;
|
||||
}
|
||||
|
||||
result = SUCCESS;
|
||||
@ -1205,7 +1205,7 @@ void LegoGameState::Init()
|
||||
}
|
||||
}
|
||||
|
||||
m_unk0x42c = e_undefined;
|
||||
m_savedPreviousArea = e_undefined;
|
||||
}
|
||||
|
||||
// FUNCTION: BETA10 0x10086510
|
||||
@ -1584,18 +1584,18 @@ void LegoGameState::History::WriteScoreHistory()
|
||||
// FUNCTION: BETA10 0x1008732a
|
||||
LegoGameState::ScoreItem* LegoGameState::History::FindPlayerInScoreHistory(
|
||||
LegoGameState::Username* p_player,
|
||||
MxS16 p_unk0x24,
|
||||
MxS32& p_unk0x2c
|
||||
MxS16 p_playerId,
|
||||
MxS32& p_playerScoreHistoryIndex
|
||||
)
|
||||
{
|
||||
MxS32 i = 0;
|
||||
for (; i < m_count; i++) {
|
||||
if (!memcmp(p_player, &m_scores[i].m_name, sizeof(*p_player)) && m_scores[i].m_playerId == p_unk0x24) {
|
||||
if (!memcmp(p_player, &m_scores[i].m_name, sizeof(*p_player)) && m_scores[i].m_playerId == p_playerId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p_unk0x2c = i;
|
||||
p_playerScoreHistoryIndex = i;
|
||||
|
||||
if (i >= m_count) {
|
||||
return NULL;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "3dmanager/lego3dmanager.h"
|
||||
#include "anim/legoanim.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "isle.h"
|
||||
#include "isle_actions.h"
|
||||
#include "islepathactor.h"
|
||||
@ -37,6 +38,8 @@
|
||||
#include <string.h>
|
||||
#include <vec.h>
|
||||
|
||||
using namespace Extensions;
|
||||
|
||||
// FUNCTION: LEGO1 0x1003dd70
|
||||
// FUNCTION: BETA10 0x100d3410
|
||||
LegoROI* PickROI(MxLong p_x, MxLong p_y)
|
||||
@ -500,6 +503,12 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id)
|
||||
{
|
||||
LegoWorld* world = CurrentWorld();
|
||||
|
||||
auto result =
|
||||
Extension<SiLoader>::Call(HandleRemove, SiLoader::StreamObject{p_atomId, p_id}, world).value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
if (world) {
|
||||
MxCore* object = world->Find(p_atomId, p_id);
|
||||
|
||||
@ -525,10 +534,21 @@ MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id)
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1003ee80
|
||||
MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_worldAtom, MxS32 p_worldEntityId)
|
||||
MxBool RemoveFromWorld(
|
||||
const MxAtomId& p_entityAtom,
|
||||
MxS32 p_entityId,
|
||||
const MxAtomId& p_worldAtom,
|
||||
MxS32 p_worldEntityId
|
||||
)
|
||||
{
|
||||
LegoWorld* world = FindWorld(p_worldAtom, p_worldEntityId);
|
||||
|
||||
auto result = Extension<SiLoader>::Call(HandleRemove, SiLoader::StreamObject{p_entityAtom, p_entityId}, world)
|
||||
.value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
if (world) {
|
||||
MxCore* object = world->Find(p_entityAtom, p_entityId);
|
||||
|
||||
|
||||
@ -630,7 +630,6 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc)
|
||||
// Setup display surface
|
||||
if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::c_bit5) != 0) {
|
||||
MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface();
|
||||
MxBool und = FALSE;
|
||||
displaySurface->VTable0x2c(
|
||||
p_ddsc,
|
||||
m_waitIndicator->GetBitmap(),
|
||||
@ -639,8 +638,7 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc)
|
||||
m_waitIndicator->GetLocation().GetX(),
|
||||
m_waitIndicator->GetLocation().GetY(),
|
||||
m_waitIndicator->GetWidth(),
|
||||
m_waitIndicator->GetHeight(),
|
||||
und
|
||||
m_waitIndicator->GetHeight()
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -31,7 +31,7 @@ MxLong Act2Brick::g_lastHitActorTime = 0;
|
||||
Act2Brick::Act2Brick()
|
||||
{
|
||||
m_whistleSound = NULL;
|
||||
m_unk0x164 = 0;
|
||||
m_state = Act2Brick::e_removed;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007a470
|
||||
@ -72,7 +72,7 @@ MxResult Act2Brick::Create(MxS32 p_index)
|
||||
|
||||
m_roi->SetEntity(this);
|
||||
CurrentWorld()->Add(this);
|
||||
m_unk0x164 = 1;
|
||||
m_state = Act2Brick::e_created;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@ -88,27 +88,27 @@ void Act2Brick::Remove()
|
||||
m_roi = NULL;
|
||||
}
|
||||
|
||||
m_unk0x164 = 0;
|
||||
m_state = Act2Brick::e_removed;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1007a670
|
||||
// FUNCTION: BETA10 0x10012c04
|
||||
void Act2Brick::FUN_1007a670(MxMatrix& p_param1, MxMatrix& p_param2, LegoPathBoundary* p_boundary)
|
||||
void Act2Brick::Place(MxMatrix& p_localToWorld, MxMatrix& p_endLocalToWorld, LegoPathBoundary* p_boundary)
|
||||
{
|
||||
m_unk0x17c = p_param2[3];
|
||||
m_unk0x168 = p_param2[3];
|
||||
m_unk0x168 -= p_param1[3];
|
||||
m_unk0x168 /= 8.0f;
|
||||
m_endLocalToWorld = p_endLocalToWorld[3];
|
||||
m_localToWorldMovementStep = p_endLocalToWorld[3];
|
||||
m_localToWorldMovementStep -= p_localToWorld[3];
|
||||
m_localToWorldMovementStep /= 8.0f;
|
||||
|
||||
m_unk0x190 = 0;
|
||||
m_step = 0;
|
||||
TickleManager()->RegisterClient(this, 20);
|
||||
|
||||
m_unk0x164 = 2;
|
||||
m_state = Act2Brick::e_placed;
|
||||
CurrentWorld()->PlaceActor(this);
|
||||
p_boundary->AddActor(this);
|
||||
|
||||
SetActorState(c_disabled);
|
||||
m_roi->SetLocal2World(p_param1);
|
||||
m_roi->SetLocal2World(p_localToWorld);
|
||||
m_roi->WrappedUpdateWorldData();
|
||||
m_roi->SetVisibility(TRUE);
|
||||
}
|
||||
@ -136,15 +136,15 @@ MxResult Act2Brick::HitActor(LegoPathActor* p_actor, MxBool)
|
||||
MxResult Act2Brick::Tickle()
|
||||
{
|
||||
MxMatrix local2world(m_roi->GetLocal2World());
|
||||
m_unk0x190++;
|
||||
m_step++;
|
||||
|
||||
if (m_unk0x190 >= 8) {
|
||||
local2world.SetTranslation(m_unk0x17c[0], m_unk0x17c[1], m_unk0x17c[2]);
|
||||
m_unk0x164 = 3;
|
||||
if (m_step >= 8) {
|
||||
local2world.SetTranslation(m_endLocalToWorld[0], m_endLocalToWorld[1], m_endLocalToWorld[2]);
|
||||
m_state = Act2Brick::e_atRest;
|
||||
TickleManager()->UnregisterClient(this);
|
||||
}
|
||||
else {
|
||||
VPV3(local2world[3], local2world[3], m_unk0x168);
|
||||
VPV3(local2world[3], local2world[3], m_localToWorldMovementStep);
|
||||
}
|
||||
|
||||
m_roi->SetLocal2World(local2world);
|
||||
@ -165,7 +165,7 @@ MxLong Act2Brick::Notify(MxParam& p_param)
|
||||
StopWhistleSound();
|
||||
}
|
||||
|
||||
MxNotificationParam param(c_notificationType22, this);
|
||||
MxNotificationParam param(c_notificationAct2Brick, this);
|
||||
NotificationManager()->Send(CurrentWorld(), param);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -158,7 +158,12 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2)
|
||||
|
||||
// FUNCTION: LEGO1 0x100109b0
|
||||
// FUNCTION: BETA10 0x1007e8b8
|
||||
void LegoEntity::SetLocation(const Vector3& p_location, const Vector3& p_direction, const Vector3& p_up, MxBool p_und)
|
||||
void LegoEntity::SetLocation(
|
||||
const Vector3& p_location,
|
||||
const Vector3& p_direction,
|
||||
const Vector3& p_up,
|
||||
MxBool p_updateCamera
|
||||
)
|
||||
{
|
||||
Mx3DPointFloat direction;
|
||||
Mx3DPointFloat up;
|
||||
@ -185,14 +190,14 @@ void LegoEntity::SetLocation(const Vector3& p_location, const Vector3& p_directi
|
||||
m_roi->UpdateTransformationRelativeToParent(mat);
|
||||
VideoManager()->Get3DManager()->Moved(*m_roi);
|
||||
|
||||
if (p_und) {
|
||||
FUN_10010c30();
|
||||
if (p_updateCamera) {
|
||||
TransformPointOfView();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10010c30
|
||||
void LegoEntity::FUN_10010c30()
|
||||
void LegoEntity::TransformPointOfView()
|
||||
{
|
||||
LegoWorld* world = CurrentWorld();
|
||||
|
||||
|
||||
@ -870,7 +870,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
|
||||
}
|
||||
|
||||
GameState()->SetCurrentAct(LegoGameState::e_act3);
|
||||
act3State->m_unk0x08 = 2;
|
||||
act3State->m_state = Act3State::e_goodEnding;
|
||||
GameState()->m_currentArea = LegoGameState::e_act3script;
|
||||
GameState()->SwitchArea(LegoGameState::e_infomain);
|
||||
break;
|
||||
@ -884,7 +884,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
|
||||
}
|
||||
|
||||
GameState()->SetCurrentAct(LegoGameState::e_act3);
|
||||
act3State->m_unk0x08 = 3;
|
||||
act3State->m_state = Act3State::e_badEnding;
|
||||
GameState()->m_currentArea = LegoGameState::e_act3script;
|
||||
GameState()->SwitchArea(LegoGameState::e_infomain);
|
||||
break;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "legoworld.h"
|
||||
|
||||
#include "anim/legoanim.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legoanimpresenter.h"
|
||||
#include "legobuildingmanager.h"
|
||||
@ -32,6 +33,8 @@ DECOMP_SIZE_ASSERT(LegoEntityListCursor, 0x10)
|
||||
DECOMP_SIZE_ASSERT(LegoCacheSoundList, 0x18)
|
||||
DECOMP_SIZE_ASSERT(LegoCacheSoundListCursor, 0x10)
|
||||
|
||||
using namespace Extensions;
|
||||
|
||||
// FUNCTION: LEGO1 0x1001ca40
|
||||
LegoWorld::LegoWorld() : m_pathControllerList(TRUE)
|
||||
{
|
||||
@ -636,6 +639,12 @@ MxCore* LegoWorld::Find(const char* p_class, const char* p_name)
|
||||
// FUNCTION: BETA10 0x100db3de
|
||||
MxCore* LegoWorld::Find(const MxAtomId& p_atom, MxS32 p_entityId)
|
||||
{
|
||||
auto result =
|
||||
Extension<SiLoader>::Call(HandleFind, SiLoader::StreamObject{p_atom, p_entityId}, this).value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
LegoEntityListCursor entityCursor(m_entityList);
|
||||
LegoEntity* entity;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include "legomain.h"
|
||||
|
||||
#include "3dmanager/lego3dmanager.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "islepathactor.h"
|
||||
#include "legoanimationmanager.h"
|
||||
#include "legobuildingmanager.h"
|
||||
@ -40,6 +41,8 @@ DECOMP_SIZE_ASSERT(LegoOmni::WorldContainer, 0x1c)
|
||||
DECOMP_SIZE_ASSERT(LegoWorldList, 0x18)
|
||||
DECOMP_SIZE_ASSERT(LegoWorldListCursor, 0x10)
|
||||
|
||||
using namespace Extensions;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f6718
|
||||
// GLOBAL: BETA10 0x101ee748
|
||||
// STRING: LEGO1 0x100f6710
|
||||
@ -404,6 +407,8 @@ LegoOmni* LegoOmni::GetInstance()
|
||||
void LegoOmni::AddWorld(LegoWorld* p_world)
|
||||
{
|
||||
m_worldList->Append(p_world);
|
||||
|
||||
Extension<SiLoader>::Call(HandleWorld, p_world);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1005adb0
|
||||
@ -471,6 +476,11 @@ LegoWorld* LegoOmni::FindWorld(const MxAtomId& p_atom, MxS32 p_entityid)
|
||||
// STUB: BETA10 0x1008e93e
|
||||
void LegoOmni::DeleteObject(MxDSAction& p_dsAction)
|
||||
{
|
||||
auto result = Extension<SiLoader>::Call(HandleDelete, p_dsAction).value_or(std::nullopt);
|
||||
if (result && result.value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_dsAction.GetAtomId().GetInternal() != NULL) {
|
||||
LegoWorld* world = FindWorld(p_dsAction.GetAtomId(), p_dsAction.GetObjectId());
|
||||
if (world) {
|
||||
@ -660,6 +670,13 @@ void LegoOmni::CreateBackgroundAudio()
|
||||
// FUNCTION: BETA10 0x1008f7e0
|
||||
MxResult LegoOmni::Start(MxDSAction* p_dsAction)
|
||||
{
|
||||
{
|
||||
auto result = Extension<SiLoader>::Call(HandleStart, *p_dsAction).value_or(std::nullopt);
|
||||
if (result) {
|
||||
return result.value();
|
||||
}
|
||||
}
|
||||
|
||||
MxResult result = MxOmni::Start(p_dsAction);
|
||||
#ifdef BETA10
|
||||
this->m_action = *p_dsAction;
|
||||
@ -714,3 +731,8 @@ void LegoOmni::Resume()
|
||||
MxOmni::Resume();
|
||||
SetAppCursor(e_cursorArrow);
|
||||
}
|
||||
|
||||
void LegoOmni::LoadSiLoader()
|
||||
{
|
||||
Extension<SiLoader>::Call(Load);
|
||||
}
|
||||
|
||||
@ -13,9 +13,14 @@ DECOMP_SIZE_ASSERT(LegoAnimActorStruct, 0x20)
|
||||
|
||||
// FUNCTION: LEGO1 0x1001bf80
|
||||
// FUNCTION: BETA10 0x1003dc10
|
||||
LegoAnimActorStruct::LegoAnimActorStruct(float p_unk0x00, LegoAnim* p_AnimTreePtr, LegoROI** p_roiMap, MxU32 p_numROIs)
|
||||
LegoAnimActorStruct::LegoAnimActorStruct(
|
||||
float p_worldSpeed,
|
||||
LegoAnim* p_AnimTreePtr,
|
||||
LegoROI** p_roiMap,
|
||||
MxU32 p_numROIs
|
||||
)
|
||||
{
|
||||
m_unk0x00 = p_unk0x00;
|
||||
m_worldSpeed = p_worldSpeed;
|
||||
m_AnimTreePtr = p_AnimTreePtr;
|
||||
m_roiMap = p_roiMap;
|
||||
m_numROIs = p_numROIs;
|
||||
@ -50,22 +55,22 @@ LegoAnimActor::~LegoAnimActor()
|
||||
|
||||
// FUNCTION: LEGO1 0x1001c1f0
|
||||
// FUNCTION: BETA10 0x1003f240
|
||||
MxResult LegoAnimActor::FUN_1001c1f0(float& p_und)
|
||||
MxResult LegoAnimActor::GetTimeInCycle(float& p_timeInCycle)
|
||||
{
|
||||
float duration = (float) m_animMaps[m_curAnim]->m_AnimTreePtr->GetDuration();
|
||||
p_und = m_actorTime - duration * ((MxS32) (m_actorTime / duration));
|
||||
p_timeInCycle = m_actorTime - duration * ((MxS32) (m_actorTime / duration));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x1001c240
|
||||
void LegoAnimActor::VTable0x74(Matrix4& p_transform)
|
||||
{
|
||||
float und;
|
||||
float timeInCycle;
|
||||
LegoPathActor::VTable0x74(p_transform);
|
||||
|
||||
if (m_curAnim >= 0) {
|
||||
FUN_1001c1f0(und);
|
||||
FUN_1001c360(und, p_transform);
|
||||
GetTimeInCycle(timeInCycle);
|
||||
AnimateWithTransform(timeInCycle, p_transform);
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,10 +86,10 @@ void LegoAnimActor::Animate(float p_time)
|
||||
|
||||
if (m_actorState == c_initial && !m_userNavFlag && m_worldSpeed <= 0) {
|
||||
if (m_curAnim >= 0) {
|
||||
MxMatrix matrix(m_unk0xec);
|
||||
float f;
|
||||
FUN_1001c1f0(f);
|
||||
FUN_1001c360(f, matrix);
|
||||
MxMatrix transform(m_unk0xec);
|
||||
float timeInCycle;
|
||||
GetTimeInCycle(timeInCycle);
|
||||
AnimateWithTransform(timeInCycle, transform);
|
||||
}
|
||||
|
||||
m_lastTime = m_actorTime = p_time;
|
||||
@ -96,9 +101,9 @@ void LegoAnimActor::Animate(float p_time)
|
||||
|
||||
// FUNCTION: LEGO1 0x1001c360
|
||||
// FUNCTION: BETA10 0x1003e2d3
|
||||
MxResult LegoAnimActor::FUN_1001c360(float p_und, Matrix4& p_transform)
|
||||
MxResult LegoAnimActor::AnimateWithTransform(float p_time, Matrix4& p_transform)
|
||||
{
|
||||
if (p_und >= 0) {
|
||||
if (p_time >= 0) {
|
||||
assert((m_curAnim >= 0) && (m_curAnim < m_animMaps.size()));
|
||||
|
||||
LegoROI** roiMap = m_animMaps[m_curAnim]->m_roiMap;
|
||||
@ -133,11 +138,11 @@ MxResult LegoAnimActor::FUN_1001c360(float p_und, Matrix4& p_transform)
|
||||
}
|
||||
|
||||
for (MxS32 j = 0; j < n->GetNumChildren(); j++) {
|
||||
LegoROI::ApplyAnimationTransformation(n->GetChild(j), p_transform, p_und, roiMap);
|
||||
LegoROI::ApplyAnimationTransformation(n->GetChild(j), p_transform, p_time, roiMap);
|
||||
}
|
||||
|
||||
if (m_cameraFlag) {
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,15 +155,20 @@ MxResult LegoAnimActor::FUN_1001c360(float p_und, Matrix4& p_transform)
|
||||
|
||||
// FUNCTION: LEGO1 0x1001c450
|
||||
// FUNCTION: BETA10 0x1003e590
|
||||
MxResult LegoAnimActor::FUN_1001c450(LegoAnim* p_AnimTreePtr, float p_unk0x00, LegoROI** p_roiMap, MxU32 p_numROIs)
|
||||
MxResult LegoAnimActor::CreateAnimActorStruct(
|
||||
LegoAnim* p_AnimTreePtr,
|
||||
float p_worldSpeed,
|
||||
LegoROI** p_roiMap,
|
||||
MxU32 p_numROIs
|
||||
)
|
||||
{
|
||||
// the capitalization of `p_AnimTreePtr` was taken from BETA10
|
||||
assert(p_AnimTreePtr && p_roiMap);
|
||||
|
||||
LegoAnimActorStruct* laas = new LegoAnimActorStruct(p_unk0x00, p_AnimTreePtr, p_roiMap, p_numROIs);
|
||||
LegoAnimActorStruct* laas = new LegoAnimActorStruct(p_worldSpeed, p_AnimTreePtr, p_roiMap, p_numROIs);
|
||||
|
||||
for (vector<LegoAnimActorStruct*>::iterator it = m_animMaps.begin(); it != m_animMaps.end(); it++) {
|
||||
if (p_unk0x00 < (*it)->m_unk0x00) {
|
||||
if (p_worldSpeed < (*it)->m_worldSpeed) {
|
||||
m_animMaps.insert(it, laas);
|
||||
SetWorldSpeed(m_worldSpeed);
|
||||
return SUCCESS;
|
||||
@ -196,12 +206,12 @@ void LegoAnimActor::SetWorldSpeed(MxFloat p_worldSpeed)
|
||||
if (m_animMaps.size() > 0) {
|
||||
m_curAnim = 0;
|
||||
|
||||
if (m_worldSpeed >= m_animMaps[m_animMaps.size() - 1]->m_unk0x00) {
|
||||
if (m_worldSpeed >= m_animMaps[m_animMaps.size() - 1]->m_worldSpeed) {
|
||||
m_curAnim = m_animMaps.size() - 1;
|
||||
}
|
||||
else {
|
||||
for (MxU32 i = 0; i < m_animMaps.size(); i++) {
|
||||
if (m_worldSpeed <= m_animMaps[i]->m_unk0x00) {
|
||||
if (m_worldSpeed <= m_animMaps[i]->m_worldSpeed) {
|
||||
m_curAnim = i;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ inline void LegoExtraActor::FUN_1002ad8a()
|
||||
m_assAnimP->FUN_1006d680(this, -20.0f);
|
||||
|
||||
for (MxS32 i = 0; i < m_animMaps.size(); i++) {
|
||||
if (m_animMaps[i]->GetUnknown0x00() == -20.0f) {
|
||||
if (m_animMaps[i]->GetWorldSpeed() == -20.0f) {
|
||||
m_assAnim = new LegoAnimActorStruct(*m_animMaps[i]);
|
||||
break;
|
||||
}
|
||||
@ -181,7 +181,7 @@ inline void LegoExtraActor::FUN_1002ad8a()
|
||||
m_disAnimP->FUN_1006d680(this, -21.0f);
|
||||
|
||||
for (MxS32 i = 0; i < m_animMaps.size(); i++) {
|
||||
if (m_animMaps[i]->GetUnknown0x00() == -21.0f) {
|
||||
if (m_animMaps[i]->GetWorldSpeed() == -21.0f) {
|
||||
m_disAnim = new LegoAnimActorStruct(*m_animMaps[i]);
|
||||
break;
|
||||
}
|
||||
@ -416,7 +416,7 @@ void LegoExtraActor::VTable0xc4()
|
||||
if (b) {
|
||||
float duration = m_animMaps[m_curAnim]->GetDuration();
|
||||
MxMatrix matrix(m_unk0xec);
|
||||
LegoAnimActor::FUN_1001c360(duration, matrix);
|
||||
LegoAnimActor::AnimateWithTransform(duration, matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ MxResult LegoPathActor::VTable0x88(
|
||||
}
|
||||
else {
|
||||
m_boundary->AddActor(this);
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
|
||||
m_unk0xec = m_roi->GetLocal2World();
|
||||
@ -223,7 +223,7 @@ MxResult LegoPathActor::VTable0x84(
|
||||
|
||||
if (m_cameraFlag && m_userNavFlag) {
|
||||
m_boundary->AddActor(this);
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
else {
|
||||
p5.EqualsCross(*p_boundary->GetUp(), p3);
|
||||
@ -393,14 +393,14 @@ void LegoPathActor::VTable0x74(Matrix4& p_transform)
|
||||
{
|
||||
if (m_userNavFlag) {
|
||||
m_roi->WrappedSetLocal2WorldWithWorldDataUpdate(p_transform);
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
else {
|
||||
m_roi->WrappedSetLocal2WorldWithWorldDataUpdate(p_transform);
|
||||
m_roi->WrappedUpdateWorldData();
|
||||
|
||||
if (m_cameraFlag) {
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -746,7 +746,7 @@ void LegoPathActor::VTable0xa8()
|
||||
|
||||
if (m_userNavFlag) {
|
||||
m_roi->WrappedSetLocal2WorldWithWorldDataUpdate(m_unk0xec);
|
||||
FUN_10010c30();
|
||||
TransformPointOfView();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -271,10 +271,10 @@ void LegoRaceCar::ParseAction(char* p_extra)
|
||||
MxS32 i;
|
||||
|
||||
for (i = 0; i < m_animMaps.size(); i++) {
|
||||
if (m_animMaps[i]->GetUnknown0x00() == -1.0f) {
|
||||
if (m_animMaps[i]->GetWorldSpeed() == -1.0f) {
|
||||
m_skelKick1Anim = m_animMaps[i];
|
||||
}
|
||||
else if (m_animMaps[i]->GetUnknown0x00() == -2.0f) {
|
||||
else if (m_animMaps[i]->GetWorldSpeed() == -2.0f) {
|
||||
m_skelKick2Anim = m_animMaps[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,15 +22,15 @@ RaceSkel::~RaceSkel()
|
||||
|
||||
// FUNCTION: LEGO1 0x10071b50
|
||||
// FUNCTION: BETA10 0x100f13cf
|
||||
MxResult RaceSkel::FUN_1001c360(float p_und, Matrix4& p_transform)
|
||||
MxResult RaceSkel::AnimateWithTransform(float p_time, Matrix4& p_transform)
|
||||
{
|
||||
p_transform[3][0] = -630.0f;
|
||||
p_transform[3][1] = -4.688f;
|
||||
p_transform[3][2] = 323.0f;
|
||||
|
||||
m_animPosition = p_und;
|
||||
m_animPosition = p_time;
|
||||
|
||||
return LegoAnimActor::FUN_1001c360(p_und, p_transform);
|
||||
return LegoAnimActor::AnimateWithTransform(p_time, p_transform);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10071b90
|
||||
|
||||
@ -1438,7 +1438,7 @@ void LegoLocomotionAnimPresenter::FUN_1006d680(LegoAnimActor* p_actor, MxFloat p
|
||||
|
||||
if (m_roiMap != NULL) {
|
||||
m_roiMapList->Append(m_roiMap);
|
||||
p_actor->FUN_1001c450(m_anim, p_value, m_roiMap, m_roiMapSize);
|
||||
p_actor->CreateAnimActorStruct(m_anim, p_value, m_roiMap, m_roiMapSize);
|
||||
m_roiMap = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -852,7 +852,7 @@ void LegoVideoManager::SetCursorBitmap(const CursorBitmap* p_cursorBitmap)
|
||||
m_cursorRect.bottom = p_cursorBitmap->height;
|
||||
m_cursorRect.right = p_cursorBitmap->width;
|
||||
|
||||
m_cursorSurface = MxDisplaySurface::CreateCursorSurface(p_cursorBitmap);
|
||||
m_cursorSurface = MxDisplaySurface::CreateCursorSurface(p_cursorBitmap, m_videoParam.GetPalette());
|
||||
|
||||
if (m_cursorSurface == NULL) {
|
||||
m_drawCursor = FALSE;
|
||||
|
||||
@ -110,14 +110,14 @@ Act3Script::Script g_unk0x100d95e8[] =
|
||||
{Act3Script::c_tlp053in_RunAnim, Act3Script::c_tlp064la_RunAnim, Act3Script::c_tlp068in_RunAnim};
|
||||
|
||||
// FUNCTION: LEGO1 0x10071d40
|
||||
void Act3List::Insert(MxS32 p_objectId, InsertMode p_option)
|
||||
void Act3List::Insert(MxS32 p_objectId, Act3ListElement::InsertMode p_option)
|
||||
{
|
||||
if (m_unk0x0c) {
|
||||
if (m_cleared) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (p_option) {
|
||||
case InsertMode::e_replaceAction:
|
||||
case Act3ListElement::InsertMode::e_replaceAction:
|
||||
if (!empty()) {
|
||||
DeleteActionWrapper();
|
||||
push_back(Act3ListElement(p_objectId, p_option, FALSE));
|
||||
@ -127,7 +127,7 @@ void Act3List::Insert(MxS32 p_objectId, InsertMode p_option)
|
||||
push_back(Act3ListElement(p_objectId, p_option, TRUE));
|
||||
}
|
||||
break;
|
||||
case InsertMode::e_queueAction:
|
||||
case Act3ListElement::InsertMode::e_queueAction:
|
||||
if (empty()) {
|
||||
push_back(Act3ListElement(p_objectId, p_option, TRUE));
|
||||
InvokeAction(Extra::e_start, *g_act3Script, p_objectId, NULL);
|
||||
@ -136,7 +136,7 @@ void Act3List::Insert(MxS32 p_objectId, InsertMode p_option)
|
||||
push_back(Act3ListElement(p_objectId, p_option, FALSE));
|
||||
}
|
||||
break;
|
||||
case InsertMode::e_onlyIfEmpty:
|
||||
case Act3ListElement::InsertMode::e_onlyIfEmpty:
|
||||
if (empty()) {
|
||||
push_back(Act3ListElement(p_objectId, p_option, TRUE));
|
||||
InvokeAction(Extra::e_start, *g_act3Script, p_objectId, NULL);
|
||||
@ -154,7 +154,7 @@ void Act3List::DeleteActionWrapper()
|
||||
// FUNCTION: LEGO1 0x10071fb0
|
||||
void Act3List::Clear()
|
||||
{
|
||||
m_unk0x0c = 1;
|
||||
m_cleared = TRUE;
|
||||
BackgroundAudioManager()->Stop();
|
||||
|
||||
if (empty()) {
|
||||
@ -177,7 +177,7 @@ void Act3List::Clear()
|
||||
// FUNCTION: LEGO1 0x100720d0
|
||||
void Act3List::RemoveByObjectIdOrFirst(MxU32 p_objectId)
|
||||
{
|
||||
if (m_unk0x0c) {
|
||||
if (m_cleared) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ void Act3List::RemoveByObjectIdOrFirst(MxU32 p_objectId)
|
||||
it++;
|
||||
|
||||
while (it != end()) {
|
||||
if ((*it).m_unk0x04 == 1) {
|
||||
if ((*it).m_insertMode == Act3ListElement::e_replaceAction) {
|
||||
for (Act3List::iterator it2 = begin(); it2 != it; erase(it2++)) {
|
||||
if ((*it2).m_hasStarted) {
|
||||
DeleteActionWrapper();
|
||||
@ -469,14 +469,14 @@ void Act3::TriggerHitSound(undefined4 p_param1)
|
||||
m_bricksterDonutSound = 0;
|
||||
}
|
||||
|
||||
m_unk0x4220.Insert(g_bricksterDonutSounds[m_bricksterDonutSound++], Act3List::e_replaceAction);
|
||||
m_unk0x4220.Insert(g_bricksterDonutSounds[m_bricksterDonutSound++], Act3ListElement::e_replaceAction);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
m_unk0x4220.Insert(objectId, Act3List::e_onlyIfEmpty);
|
||||
m_unk0x4220.Insert(objectId, Act3ListElement::e_onlyIfEmpty);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10072c30
|
||||
@ -633,22 +633,22 @@ MxLong Act3::Notify(MxParam& p_param)
|
||||
break;
|
||||
}
|
||||
case c_notificationKeyPress:
|
||||
if (m_state->m_unk0x08 == 1 && ((LegoEventNotificationParam&) p_param).GetKey() == ' ') {
|
||||
if (m_state->m_state == Act3State::e_ready && ((LegoEventNotificationParam&) p_param).GetKey() == ' ') {
|
||||
AnimationManager()->FUN_10061010(FALSE);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case c_notificationButtonUp:
|
||||
case c_notificationButtonDown:
|
||||
if (m_state->m_unk0x08 == 1) {
|
||||
if (m_state->m_state == Act3State::e_ready) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case c_notificationEndAnim:
|
||||
if (m_state->m_unk0x08 == 1) {
|
||||
if (m_state->m_state == Act3State::e_ready) {
|
||||
assert(m_copter && m_brickster && m_cop1 && m_cop2);
|
||||
m_unk0x4220.RemoveByObjectIdOrFirst(0);
|
||||
m_state->m_unk0x08 = 0;
|
||||
m_state->m_state = Act3State::e_initial;
|
||||
Disable(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen);
|
||||
m_copter->HandleClick();
|
||||
m_copter->m_state->m_unk0x08 = 1;
|
||||
@ -687,7 +687,7 @@ void Act3::ReadyWorld()
|
||||
AnimationManager()
|
||||
->FUN_10060dc0(m_unk0x426c, NULL, TRUE, LegoAnimationManager::e_unk0, NULL, TRUE, FALSE, FALSE, FALSE);
|
||||
|
||||
m_state->m_unk0x08 = 1;
|
||||
m_state->m_state = Act3State::e_ready;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10073300
|
||||
@ -759,7 +759,7 @@ void Act3::SetBrickster(Act3Brickster* p_brickster)
|
||||
// FUNCTION: LEGO1 0x10073400
|
||||
void Act3::FUN_10073400()
|
||||
{
|
||||
m_state->m_unk0x08 = 2;
|
||||
m_state->m_state = Act3State::e_goodEnding;
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
@ -767,7 +767,7 @@ void Act3::FUN_10073400()
|
||||
// FUNCTION: LEGO1 0x10073430
|
||||
void Act3::FUN_10073430()
|
||||
{
|
||||
m_state->m_unk0x08 = 3;
|
||||
m_state->m_state = Act3State::e_badEnding;
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
}
|
||||
@ -797,7 +797,7 @@ void Act3::GoodEnding(const Matrix4& p_destination)
|
||||
|
||||
EmitGameEvent(e_goodEnding);
|
||||
#else
|
||||
m_state->m_unk0x08 = 2;
|
||||
m_state->m_state = Act3State::e_goodEnding;
|
||||
GameState()->SwitchArea(LegoGameState::Area::e_infomain);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -2,8 +2,10 @@
|
||||
|
||||
#include "act3.h"
|
||||
#include "credits_actions.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "helicopter.h"
|
||||
#include "infomain_actions.h"
|
||||
#include "intro_actions.h"
|
||||
#include "jukebox.h"
|
||||
#include "jukebox_actions.h"
|
||||
#include "legoact2.h"
|
||||
@ -35,6 +37,8 @@ DECOMP_SIZE_ASSERT(Infocenter, 0x1d8)
|
||||
DECOMP_SIZE_ASSERT(InfocenterMapEntry, 0x18)
|
||||
DECOMP_SIZE_ASSERT(InfocenterState, 0x94)
|
||||
|
||||
using namespace Extensions;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f76a0
|
||||
const char* g_object2x4red = "2x4red";
|
||||
|
||||
@ -128,13 +132,13 @@ InfomainScript::Script g_bricksterDialogue[2] = {
|
||||
// FUNCTION: LEGO1 0x1006ea20
|
||||
Infocenter::Infocenter()
|
||||
{
|
||||
m_selectedCharacter = e_noCharacter;
|
||||
m_selectedCharacter = LegoActor::c_none;
|
||||
m_dragPresenter = NULL;
|
||||
m_infocenterState = NULL;
|
||||
m_frame = NULL;
|
||||
m_destLocation = LegoGameState::e_undefined;
|
||||
m_currentInfomainScript = InfomainScript::c_noneInfomain;
|
||||
m_currentCutscene = e_noIntro;
|
||||
m_currentCutscene = IntroScript::c_noneIntro;
|
||||
|
||||
memset(&m_glowInfo, 0, sizeof(m_glowInfo));
|
||||
|
||||
@ -220,7 +224,7 @@ MxResult Infocenter::Create(MxDSAction& p_dsAction)
|
||||
|
||||
if (m_infocenterState->m_state == InfocenterState::e_selectedSave) {
|
||||
LegoGameState* state = GameState();
|
||||
state->m_previousArea = GameState()->m_unk0x42c;
|
||||
state->m_previousArea = GameState()->m_savedPreviousArea;
|
||||
}
|
||||
|
||||
InputManager()->Register(this);
|
||||
@ -312,19 +316,19 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
GameState()->SetActor(m_selectedCharacter);
|
||||
|
||||
switch (m_selectedCharacter) {
|
||||
case e_pepper:
|
||||
case LegoActor::c_pepper:
|
||||
PlayAction(InfomainScript::c_avo901in_RunAnim);
|
||||
break;
|
||||
case e_mama:
|
||||
case LegoActor::c_mama:
|
||||
PlayAction(InfomainScript::c_avo902in_RunAnim);
|
||||
break;
|
||||
case e_papa:
|
||||
case LegoActor::c_papa:
|
||||
PlayAction(InfomainScript::c_avo903in_RunAnim);
|
||||
break;
|
||||
case e_nick:
|
||||
case LegoActor::c_nick:
|
||||
PlayAction(InfomainScript::c_avo904in_RunAnim);
|
||||
break;
|
||||
case e_laura:
|
||||
case LegoActor::c_laura:
|
||||
PlayAction(InfomainScript::c_avo905in_RunAnim);
|
||||
break;
|
||||
default:
|
||||
@ -338,7 +342,8 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
|
||||
MxLong result = m_radio.Notify(p_param);
|
||||
|
||||
if (result || (action->GetAtomId() != m_atomId && action->GetAtomId() != *g_introScript)) {
|
||||
if (result || (action->GetAtomId() != m_atomId && action->GetAtomId() != *g_introScript &&
|
||||
!Extension<SiLoader>::Call(ReplacedIn, *action, m_atomId, *g_introScript).value_or(std::nullopt))) {
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -350,23 +355,23 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
switch (m_infocenterState->m_state) {
|
||||
case InfocenterState::e_playCutscene:
|
||||
switch (m_currentCutscene) {
|
||||
case e_legoMovie:
|
||||
PlayCutscene(e_mindscapeMovie, FALSE);
|
||||
case IntroScript::c_Lego_Movie:
|
||||
PlayCutscene(IntroScript::c_Mindscape_Movie, FALSE);
|
||||
return 1;
|
||||
case e_mindscapeMovie:
|
||||
PlayCutscene(e_introMovie, TRUE);
|
||||
case IntroScript::c_Mindscape_Movie:
|
||||
PlayCutscene(IntroScript::c_Intro_Movie, TRUE);
|
||||
return 1;
|
||||
case e_badEndMovie:
|
||||
case IntroScript::c_BadEnd_Movie:
|
||||
StopCutscene();
|
||||
m_infocenterState->m_state = InfocenterState::e_welcomeAnimation;
|
||||
PlayAction(InfomainScript::c_tic092in_RunAnim);
|
||||
m_currentCutscene = e_noIntro;
|
||||
m_currentCutscene = IntroScript::c_noneIntro;
|
||||
return 1;
|
||||
case e_goodEndMovie:
|
||||
case IntroScript::c_GoodEnd_Movie:
|
||||
StopCutscene();
|
||||
m_infocenterState->m_state = InfocenterState::e_welcomeAnimation;
|
||||
PlayAction(InfomainScript::c_tic089in_RunAnim);
|
||||
m_currentCutscene = e_noIntro;
|
||||
m_currentCutscene = IntroScript::c_noneIntro;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -374,7 +379,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
StopCutscene();
|
||||
m_infocenterState->m_state = InfocenterState::e_welcomeAnimation;
|
||||
PlayAction(InfomainScript::c_iic001in_RunAnim);
|
||||
m_currentCutscene = e_noIntro;
|
||||
m_currentCutscene = IntroScript::c_noneIntro;
|
||||
|
||||
if (!m_infocenterState->HasRegistered()) {
|
||||
m_bookAnimationTimer = 1;
|
||||
@ -385,17 +390,17 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
m_infocenterState->m_state = InfocenterState::e_welcomeAnimation;
|
||||
|
||||
switch (m_currentCutscene) {
|
||||
case e_badEndMovie:
|
||||
case IntroScript::c_BadEnd_Movie:
|
||||
PlayAction(InfomainScript::c_tic092in_RunAnim);
|
||||
break;
|
||||
case e_goodEndMovie:
|
||||
case IntroScript::c_GoodEnd_Movie:
|
||||
PlayAction(InfomainScript::c_tic089in_RunAnim);
|
||||
break;
|
||||
default:
|
||||
PlayAction(InfomainScript::c_iic001in_RunAnim);
|
||||
}
|
||||
|
||||
m_currentCutscene = e_noIntro;
|
||||
m_currentCutscene = IntroScript::c_noneIntro;
|
||||
return 1;
|
||||
case InfocenterState::e_notRegistered:
|
||||
SetROIVisible(g_object2x4red, FALSE);
|
||||
@ -412,7 +417,7 @@ MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
break;
|
||||
case InfocenterState::e_selectedCharacterAndDestination:
|
||||
if (action->GetObjectId() == m_currentInfomainScript) {
|
||||
if (GameState()->GetCurrentAct() != LegoGameState::e_act3 && m_selectedCharacter != e_noCharacter) {
|
||||
if (GameState()->GetCurrentAct() != LegoGameState::e_act3 && m_selectedCharacter != LegoActor::c_none) {
|
||||
GameState()->SetActor(m_selectedCharacter);
|
||||
}
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
@ -462,7 +467,7 @@ void Infocenter::ReadyWorld()
|
||||
|
||||
switch (m_infocenterState->m_state) {
|
||||
case InfocenterState::e_newState:
|
||||
PlayCutscene(e_legoMovie, TRUE);
|
||||
PlayCutscene(IntroScript::c_Lego_Movie, TRUE);
|
||||
m_infocenterState->m_state = InfocenterState::e_playCutscene;
|
||||
return;
|
||||
case InfocenterState::e_selectedSave:
|
||||
@ -523,9 +528,9 @@ void Infocenter::ReadyWorld()
|
||||
LegoAct2State* state = (LegoAct2State*) GameState()->GetState("LegoAct2State");
|
||||
GameState()->FindLoadedAct();
|
||||
|
||||
if (state && state->GetUnknown0x08() == 0x68) {
|
||||
if (state && state->GetState() == LegoAct2State::c_badEnding) {
|
||||
bg->Enable(TRUE);
|
||||
PlayCutscene(e_badEndMovie, TRUE);
|
||||
PlayCutscene(IntroScript::c_BadEnd_Movie, TRUE);
|
||||
m_infocenterState->m_state = InfocenterState::e_playCutscene;
|
||||
return;
|
||||
}
|
||||
@ -568,16 +573,16 @@ void Infocenter::ReadyWorld()
|
||||
Act3State* state = (Act3State*) GameState()->GetState("Act3State");
|
||||
GameState()->FindLoadedAct();
|
||||
|
||||
if (state && state->GetUnknown0x08() == 3) {
|
||||
if (state && state->GetState() == Act3State::e_badEnding) {
|
||||
bg->Enable(TRUE);
|
||||
PlayCutscene(e_badEndMovie, TRUE);
|
||||
PlayCutscene(IntroScript::c_BadEnd_Movie, TRUE);
|
||||
m_infocenterState->m_state = InfocenterState::e_playCutscene;
|
||||
return;
|
||||
}
|
||||
|
||||
if (state && state->GetUnknown0x08() == 2) {
|
||||
if (state && state->GetState() == Act3State::e_goodEnding) {
|
||||
bg->Enable(TRUE);
|
||||
PlayCutscene(e_goodEndMovie, TRUE);
|
||||
PlayCutscene(IntroScript::c_GoodEnd_Movie, TRUE);
|
||||
m_infocenterState->m_state = InfocenterState::e_playCutscene;
|
||||
return;
|
||||
}
|
||||
@ -759,19 +764,19 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
|
||||
switch (m_dragPresenter->GetAction()->GetObjectId()) {
|
||||
case InfomainScript::c_PepperHot_Bitmap:
|
||||
m_selectedCharacter = e_pepper;
|
||||
m_selectedCharacter = LegoActor::c_pepper;
|
||||
break;
|
||||
case InfomainScript::c_MamaHot_Bitmap:
|
||||
m_selectedCharacter = e_mama;
|
||||
m_selectedCharacter = LegoActor::c_mama;
|
||||
break;
|
||||
case InfomainScript::c_PapaHot_Bitmap:
|
||||
m_selectedCharacter = e_papa;
|
||||
m_selectedCharacter = LegoActor::c_papa;
|
||||
break;
|
||||
case InfomainScript::c_NickHot_Bitmap:
|
||||
m_selectedCharacter = e_nick;
|
||||
m_selectedCharacter = LegoActor::c_nick;
|
||||
break;
|
||||
case InfomainScript::c_LauraHot_Bitmap:
|
||||
m_selectedCharacter = e_laura;
|
||||
m_selectedCharacter = LegoActor::c_laura;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -780,7 +785,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
|
||||
switch (control->GetAction()->GetObjectId()) {
|
||||
case InfomainScript::c_Pepper_Ctl:
|
||||
if (m_selectedCharacter == e_pepper) {
|
||||
if (m_selectedCharacter == LegoActor::c_pepper) {
|
||||
m_radio.Stop();
|
||||
BackgroundAudioManager()->Stop();
|
||||
PlayAction(InfomainScript::c_Pepper_All_Movie);
|
||||
@ -788,7 +793,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
}
|
||||
break;
|
||||
case InfomainScript::c_Mama_Ctl:
|
||||
if (m_selectedCharacter == e_mama) {
|
||||
if (m_selectedCharacter == LegoActor::c_mama) {
|
||||
m_radio.Stop();
|
||||
BackgroundAudioManager()->Stop();
|
||||
PlayAction(InfomainScript::c_Mama_All_Movie);
|
||||
@ -796,7 +801,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
}
|
||||
break;
|
||||
case InfomainScript::c_Papa_Ctl:
|
||||
if (m_selectedCharacter == e_papa) {
|
||||
if (m_selectedCharacter == LegoActor::c_papa) {
|
||||
m_radio.Stop();
|
||||
BackgroundAudioManager()->Stop();
|
||||
PlayAction(InfomainScript::c_Papa_All_Movie);
|
||||
@ -804,7 +809,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
}
|
||||
break;
|
||||
case InfomainScript::c_Nick_Ctl:
|
||||
if (m_selectedCharacter == e_nick) {
|
||||
if (m_selectedCharacter == LegoActor::c_nick) {
|
||||
m_radio.Stop();
|
||||
BackgroundAudioManager()->Stop();
|
||||
PlayAction(InfomainScript::c_Nick_All_Movie);
|
||||
@ -812,7 +817,7 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
}
|
||||
break;
|
||||
case InfomainScript::c_Laura_Ctl:
|
||||
if (m_selectedCharacter == e_laura) {
|
||||
if (m_selectedCharacter == LegoActor::c_laura) {
|
||||
m_radio.Stop();
|
||||
BackgroundAudioManager()->Stop();
|
||||
PlayAction(InfomainScript::c_Laura_All_Movie);
|
||||
@ -830,19 +835,19 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
GameState()->SetActor(m_selectedCharacter);
|
||||
|
||||
switch (m_selectedCharacter) {
|
||||
case e_pepper:
|
||||
case LegoActor::c_pepper:
|
||||
PlayAction(InfomainScript::c_avo901in_RunAnim);
|
||||
break;
|
||||
case e_mama:
|
||||
case LegoActor::c_mama:
|
||||
PlayAction(InfomainScript::c_avo902in_RunAnim);
|
||||
break;
|
||||
case e_papa:
|
||||
case LegoActor::c_papa:
|
||||
PlayAction(InfomainScript::c_avo903in_RunAnim);
|
||||
break;
|
||||
case e_nick:
|
||||
case LegoActor::c_nick:
|
||||
PlayAction(InfomainScript::c_avo904in_RunAnim);
|
||||
break;
|
||||
case e_laura:
|
||||
case LegoActor::c_laura:
|
||||
PlayAction(InfomainScript::c_avo905in_RunAnim);
|
||||
break;
|
||||
}
|
||||
@ -901,23 +906,23 @@ MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
|
||||
}
|
||||
else {
|
||||
switch (m_selectedCharacter) {
|
||||
case e_pepper:
|
||||
case LegoActor::c_pepper:
|
||||
dialogueToPlay = InfomainScript::c_avo901in_RunAnim;
|
||||
GameState()->SetActorId(m_selectedCharacter);
|
||||
break;
|
||||
case e_mama:
|
||||
case LegoActor::c_mama:
|
||||
dialogueToPlay = InfomainScript::c_avo902in_RunAnim;
|
||||
GameState()->SetActorId(m_selectedCharacter);
|
||||
break;
|
||||
case e_papa:
|
||||
case LegoActor::c_papa:
|
||||
dialogueToPlay = InfomainScript::c_avo903in_RunAnim;
|
||||
GameState()->SetActorId(m_selectedCharacter);
|
||||
break;
|
||||
case e_nick:
|
||||
case LegoActor::c_nick:
|
||||
dialogueToPlay = InfomainScript::c_avo904in_RunAnim;
|
||||
GameState()->SetActorId(m_selectedCharacter);
|
||||
break;
|
||||
case e_laura:
|
||||
case LegoActor::c_laura:
|
||||
dialogueToPlay = InfomainScript::c_avo905in_RunAnim;
|
||||
GameState()->SetActorId(m_selectedCharacter);
|
||||
break;
|
||||
@ -1089,7 +1094,7 @@ MxU8 Infocenter::HandleControl(LegoControlManagerNotificationParam& p_param)
|
||||
actionToPlay = GameState()->GetCurrentAct() != LegoGameState::e_act1 ? InfomainScript::c_GoTo_RegBook_Red
|
||||
: InfomainScript::c_GoTo_RegBook;
|
||||
m_radio.Stop();
|
||||
GameState()->m_unk0x42c = GameState()->m_previousArea;
|
||||
GameState()->m_savedPreviousArea = GameState()->m_previousArea;
|
||||
InputManager()->DisableInputProcessing();
|
||||
break;
|
||||
case InfomainScript::c_Mama_Ctl:
|
||||
@ -1262,7 +1267,7 @@ MxResult Infocenter::Tickle()
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x10070c20
|
||||
void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale)
|
||||
void Infocenter::PlayCutscene(IntroScript::Script p_entityId, MxBool p_scale)
|
||||
{
|
||||
m_currentCutscene = p_entityId;
|
||||
|
||||
@ -1272,9 +1277,9 @@ void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale)
|
||||
SetAppCursor(e_cursorNone);
|
||||
VideoManager()->GetDisplaySurface()->ClearScreen();
|
||||
|
||||
if (m_currentCutscene != e_noIntro) {
|
||||
if (m_currentCutscene != IntroScript::c_noneIntro) {
|
||||
// check if the cutscene is an ending
|
||||
if (m_currentCutscene >= e_badEndMovie && m_currentCutscene <= e_goodEndMovie) {
|
||||
if (m_currentCutscene >= IntroScript::c_BadEnd_Movie && m_currentCutscene <= IntroScript::c_GoodEnd_Movie) {
|
||||
Reset();
|
||||
}
|
||||
|
||||
@ -1285,7 +1290,7 @@ void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale)
|
||||
// FUNCTION: LEGO1 0x10070cb0
|
||||
void Infocenter::StopCutscene()
|
||||
{
|
||||
if (m_currentCutscene != e_noIntro) {
|
||||
if (m_currentCutscene != IntroScript::c_noneIntro) {
|
||||
InvokeAction(Extra::ActionType::e_close, *g_introScript, m_currentCutscene, NULL);
|
||||
}
|
||||
|
||||
@ -1399,12 +1404,12 @@ void Infocenter::Reset()
|
||||
CharacterManager()->ReleaseAllActors();
|
||||
GameState()->SetCurrentAct(LegoGameState::e_act1);
|
||||
GameState()->m_previousArea = LegoGameState::e_undefined;
|
||||
GameState()->m_unk0x42c = LegoGameState::e_undefined;
|
||||
GameState()->m_savedPreviousArea = LegoGameState::e_undefined;
|
||||
|
||||
InitializeBitmaps();
|
||||
m_selectedCharacter = e_pepper;
|
||||
m_selectedCharacter = LegoActor::c_pepper;
|
||||
|
||||
GameState()->SetActor(e_pepper);
|
||||
GameState()->SetActor(LegoActor::c_pepper);
|
||||
|
||||
HelicopterState* state = (HelicopterState*) GameState()->GetState("HelicopterState");
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
#include "bike.h"
|
||||
#include "carrace.h"
|
||||
#include "dunebuggy.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "helicopter.h"
|
||||
#include "isle_actions.h"
|
||||
#include "islepathactor.h"
|
||||
@ -42,6 +43,8 @@ DECOMP_SIZE_ASSERT(Act1State, 0x26c)
|
||||
DECOMP_SIZE_ASSERT(LegoNamedPlane, 0x4c)
|
||||
DECOMP_SIZE_ASSERT(Isle, 0x140)
|
||||
|
||||
using namespace Extensions;
|
||||
|
||||
// GLOBAL: LEGO1 0x100f1198
|
||||
MxU32 g_isleFlags = 0x7f;
|
||||
|
||||
@ -213,6 +216,14 @@ MxLong Isle::HandleEndAction(MxEndActionNotificationParam& p_param)
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
else if (auto replacedObject = Extension<SiLoader>::Call(ReplacedIn, *p_param.GetAction(), *g_jukeboxScript).value_or(std::nullopt)) {
|
||||
MxS32 script = replacedObject->second;
|
||||
|
||||
if (script >= JukeboxScript::c_JBMusic1 && script <= JukeboxScript::c_JBMusic6) {
|
||||
m_jukebox->StopAction((JukeboxScript::Script) script);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
else if (m_act1state->m_planeActive) {
|
||||
MxS32 script = p_param.GetAction()->GetObjectId();
|
||||
|
||||
@ -244,15 +255,15 @@ void Isle::HandleElevatorEndAction()
|
||||
m_act1state->m_state = Act1State::e_none;
|
||||
break;
|
||||
case Act1State::c_floor2:
|
||||
if (m_act1state->m_unk0x01e) {
|
||||
m_act1state->m_unk0x01e = FALSE;
|
||||
if (m_act1state->m_playingFloor2Animation) {
|
||||
m_act1state->m_playingFloor2Animation = FALSE;
|
||||
m_act1state->m_state = Act1State::e_none;
|
||||
InputManager()->EnableInputProcessing();
|
||||
}
|
||||
else {
|
||||
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_Floor2, NULL);
|
||||
InputManager()->EnableInputProcessing();
|
||||
m_act1state->m_unk0x01e = TRUE;
|
||||
m_act1state->m_playingFloor2Animation = TRUE;
|
||||
}
|
||||
break;
|
||||
case Act1State::c_floor3:
|
||||
@ -268,10 +279,10 @@ void Isle::ReadyWorld()
|
||||
{
|
||||
LegoWorld::ReadyWorld();
|
||||
|
||||
if (m_act1state->GetUnknown21()) {
|
||||
if (m_act1state->IsSpawnInInfocenter()) {
|
||||
GameState()->SwitchArea(LegoGameState::e_infomain);
|
||||
m_act1state->SetState(Act1State::e_none);
|
||||
m_act1state->SetUnknown21(0);
|
||||
m_act1state->SetSpawnInInfocenter(FALSE);
|
||||
}
|
||||
else if (GameState()->GetLoadedAct() != LegoGameState::e_act1) {
|
||||
EnableAnimations(TRUE);
|
||||
@ -318,7 +329,7 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param)
|
||||
break;
|
||||
case Act1State::c_floor2:
|
||||
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_Floor2, NULL);
|
||||
m_act1state->m_unk0x01e = TRUE;
|
||||
m_act1state->m_playingFloor2Animation = TRUE;
|
||||
break;
|
||||
case Act1State::c_floor3:
|
||||
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_Elev3_2_Ride, NULL);
|
||||
@ -907,7 +918,7 @@ MxLong Isle::HandleTransitionEnd()
|
||||
m_destLocation = LegoGameState::e_undefined;
|
||||
break;
|
||||
case LegoGameState::e_elevride:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
VariableTable()->SetVariable("VISIBILITY", "Hide infocen");
|
||||
TransitionToOverlay(
|
||||
IsleScript::c_ElevRide_Background_Bitmap,
|
||||
@ -961,7 +972,7 @@ MxLong Isle::HandleTransitionEnd()
|
||||
);
|
||||
break;
|
||||
case LegoGameState::e_garadoor:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
VariableTable()->SetVariable("VISIBILITY", "Hide Gas");
|
||||
TransitionToOverlay(IsleScript::c_GaraDoor_Background_Bitmap, JukeboxScript::c_JBMusic2, "LCAMZG1,90", FALSE);
|
||||
break;
|
||||
@ -986,7 +997,7 @@ MxLong Isle::HandleTransitionEnd()
|
||||
SetIsWorldActive(TRUE);
|
||||
break;
|
||||
case LegoGameState::e_polidoor:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
VariableTable()->SetVariable("VISIBILITY", "Hide Policsta");
|
||||
TransitionToOverlay(
|
||||
IsleScript::c_PoliDoor_Background_Bitmap,
|
||||
@ -996,61 +1007,61 @@ MxLong Isle::HandleTransitionEnd()
|
||||
);
|
||||
break;
|
||||
case LegoGameState::e_bike:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
TransitionToOverlay(IsleScript::c_BikeDashboard_Bitmap, JukeboxScript::c_MusicTheme1, NULL, TRUE);
|
||||
|
||||
if (!m_act1state->m_unk0x01f) {
|
||||
if (!m_act1state->m_switchedToArea) {
|
||||
m_bike->ActivateSceneActions();
|
||||
}
|
||||
break;
|
||||
case LegoGameState::e_dunecar:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
TransitionToOverlay(IsleScript::c_DuneCarFuelMeter, JukeboxScript::c_MusicTheme1, NULL, TRUE);
|
||||
|
||||
if (!m_act1state->m_unk0x01f) {
|
||||
if (!m_act1state->m_switchedToArea) {
|
||||
m_dunebuggy->ActivateSceneActions();
|
||||
}
|
||||
break;
|
||||
case LegoGameState::e_motocycle:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
TransitionToOverlay(IsleScript::c_MotoBikeDashboard_Bitmap, JukeboxScript::c_MusicTheme1, NULL, TRUE);
|
||||
|
||||
if (!m_act1state->m_unk0x01f) {
|
||||
if (!m_act1state->m_switchedToArea) {
|
||||
m_motocycle->ActivateSceneActions();
|
||||
}
|
||||
break;
|
||||
case LegoGameState::e_copter:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
TransitionToOverlay(IsleScript::c_HelicopterDashboard_Bitmap, JukeboxScript::c_MusicTheme1, NULL, TRUE);
|
||||
break;
|
||||
case LegoGameState::e_skateboard:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
TransitionToOverlay(IsleScript::c_SkatePizza_Bitmap, JukeboxScript::c_MusicTheme1, NULL, TRUE);
|
||||
|
||||
if (!m_act1state->m_unk0x01f) {
|
||||
if (!m_act1state->m_switchedToArea) {
|
||||
m_skateboard->ActivateSceneActions();
|
||||
}
|
||||
break;
|
||||
case LegoGameState::e_ambulance:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
m_act1state->m_state = Act1State::e_ambulance;
|
||||
TransitionToOverlay(IsleScript::c_AmbulanceFuelMeter, JukeboxScript::c_MusicTheme1, NULL, TRUE);
|
||||
|
||||
if (!m_act1state->m_unk0x01f) {
|
||||
if (!m_act1state->m_switchedToArea) {
|
||||
m_ambulance->ActivateSceneActions();
|
||||
}
|
||||
break;
|
||||
case LegoGameState::e_towtrack:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
m_act1state->m_state = Act1State::e_towtrack;
|
||||
TransitionToOverlay(IsleScript::c_TowFuelMeter, JukeboxScript::c_MusicTheme1, NULL, TRUE);
|
||||
|
||||
if (!m_act1state->m_unk0x01f) {
|
||||
if (!m_act1state->m_switchedToArea) {
|
||||
m_towtrack->ActivateSceneActions();
|
||||
}
|
||||
break;
|
||||
case LegoGameState::e_jetski:
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
TransitionToOverlay(
|
||||
(IsleScript::Script) m_jetski->GetJetskiDashboardStreamId(),
|
||||
JukeboxScript::c_MusicTheme1,
|
||||
@ -1058,7 +1069,7 @@ MxLong Isle::HandleTransitionEnd()
|
||||
TRUE
|
||||
);
|
||||
|
||||
if (!m_act1state->m_unk0x01f) {
|
||||
if (!m_act1state->m_switchedToArea) {
|
||||
m_jetski->ActivateSceneActions();
|
||||
}
|
||||
break;
|
||||
@ -1078,7 +1089,7 @@ void Isle::TransitionToOverlay(
|
||||
MxBool p_setCamera
|
||||
)
|
||||
{
|
||||
if (m_act1state->m_unk0x01f) {
|
||||
if (m_act1state->m_switchedToArea) {
|
||||
MxPresenter* presenter = (MxPresenter*) Find(m_atomId, p_script);
|
||||
|
||||
if (presenter != NULL && presenter->GetCurrentTickleState() == MxPresenter::e_repeating) {
|
||||
@ -1100,7 +1111,7 @@ void Isle::TransitionToOverlay(
|
||||
Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen);
|
||||
SetAppCursor(e_cursorArrow);
|
||||
m_destLocation = LegoGameState::e_undefined;
|
||||
m_act1state->m_unk0x01f = FALSE;
|
||||
m_act1state->m_switchedToArea = FALSE;
|
||||
}
|
||||
else {
|
||||
NotificationManager()->Send(this, MxNotificationParam(c_notificationTransitioned, NULL));
|
||||
@ -1110,7 +1121,7 @@ void Isle::TransitionToOverlay(
|
||||
GameState()->SwitchArea(m_destLocation);
|
||||
GameState()->StopArea(LegoGameState::e_previousArea);
|
||||
NotificationManager()->Send(this, MxNotificationParam(c_notificationTransitioned, NULL));
|
||||
m_act1state->m_unk0x01f = TRUE;
|
||||
m_act1state->m_switchedToArea = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1229,9 +1240,9 @@ MxBool Isle::Escape()
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_act1state->m_unk0x01e == TRUE) {
|
||||
if (m_act1state->m_playingFloor2Animation == TRUE) {
|
||||
InvokeAction(Extra::e_stop, *g_isleScript, IsleScript::c_Floor2, NULL);
|
||||
m_act1state->m_unk0x01e = FALSE;
|
||||
m_act1state->m_playingFloor2Animation = FALSE;
|
||||
}
|
||||
|
||||
m_act1state->m_elevFloor = Act1State::c_floor1;
|
||||
@ -1309,18 +1320,18 @@ Act1State::Act1State()
|
||||
{
|
||||
m_elevFloor = Act1State::c_floor1;
|
||||
m_state = Act1State::e_initial;
|
||||
m_unk0x01e = FALSE;
|
||||
m_playingFloor2Animation = FALSE;
|
||||
m_cptClickDialogue = Playlist((MxU32*) g_cptClickDialogue, sizeOfArray(g_cptClickDialogue), Playlist::e_loop);
|
||||
m_unk0x01f = FALSE;
|
||||
m_switchedToArea = FALSE;
|
||||
m_planeActive = FALSE;
|
||||
m_currentCptClickDialogue = IsleScript::c_noneIsle;
|
||||
m_unk0x022 = FALSE;
|
||||
m_playedExitExplanation = FALSE;
|
||||
m_helicopterWindshield = NULL;
|
||||
m_helicopterJetLeft = NULL;
|
||||
m_helicopterJetRight = NULL;
|
||||
m_helicopter = NULL;
|
||||
m_jetskiFront = NULL;
|
||||
m_unk0x021 = 1;
|
||||
m_spawnInInfocenter = 1;
|
||||
m_jetskiWindshield = NULL;
|
||||
m_jetski = NULL;
|
||||
m_dunebuggyFront = NULL;
|
||||
@ -1419,7 +1430,7 @@ MxResult Act1State::Serialize(LegoStorage* p_storage)
|
||||
}
|
||||
|
||||
p_storage->WriteS16(m_cptClickDialogue.m_nextIndex);
|
||||
p_storage->WriteU8(m_unk0x022);
|
||||
p_storage->WriteU8(m_playedExitExplanation);
|
||||
}
|
||||
else if (p_storage->IsReadMode()) {
|
||||
if (strcmp(m_helicopterPlane.m_name.GetData(), "")) {
|
||||
@ -1467,7 +1478,7 @@ MxResult Act1State::Serialize(LegoStorage* p_storage)
|
||||
}
|
||||
|
||||
p_storage->ReadS16(m_cptClickDialogue.m_nextIndex);
|
||||
p_storage->ReadU8(m_unk0x022);
|
||||
p_storage->ReadU8(m_playedExitExplanation);
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
@ -1500,7 +1511,7 @@ MxBool Act1State::Reset()
|
||||
m_motocyclePlane.m_name = "";
|
||||
m_bikePlane.m_name = "";
|
||||
m_skateboardPlane.m_name = "";
|
||||
m_unk0x022 = FALSE;
|
||||
m_playedExitExplanation = FALSE;
|
||||
|
||||
m_helicopterPlane.m_name = "";
|
||||
if (m_helicopterWindshield) {
|
||||
|
||||
@ -127,7 +127,7 @@ MxResult LegoAct2::Create(MxDSAction& p_dsAction)
|
||||
}
|
||||
|
||||
m_gameState = state;
|
||||
m_gameState->m_unk0x08 = 0;
|
||||
m_gameState->m_state = 0;
|
||||
|
||||
switch (GameState()->GetLoadedAct()) {
|
||||
case LegoGameState::e_act2:
|
||||
@ -294,7 +294,7 @@ MxLong LegoAct2::Notify(MxParam& p_param)
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
case c_notificationType22:
|
||||
case c_notificationAct2Brick:
|
||||
SoundManager()->GetCacheSoundManager()->Play("28bng", NULL, FALSE);
|
||||
|
||||
m_unk0x10c1++;
|
||||
@ -647,7 +647,7 @@ MxLong LegoAct2::HandlePathStruct(LegoPathStructNotificationParam& p_param)
|
||||
local2world[3][1] += 1.5;
|
||||
local2world2[3][1] -= 0.1;
|
||||
|
||||
m_bricks[m_nextBrick - 1].FUN_1007a670(local2world, local2world2, boundary);
|
||||
m_bricks[m_nextBrick - 1].Place(local2world, local2world2, boundary);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -671,7 +671,7 @@ MxResult LegoAct2::FUN_100516b0()
|
||||
local2world[3][1] += 1.3;
|
||||
local2world2[3][1] -= 0.1;
|
||||
|
||||
brick.FUN_1007a670(local2world, local2world2, boundary);
|
||||
brick.Place(local2world, local2world2, boundary);
|
||||
m_nextBrick++;
|
||||
m_unk0x10c4 = 9;
|
||||
m_unk0x10d0 = 0;
|
||||
@ -933,7 +933,7 @@ MxResult LegoAct2::BadEnding()
|
||||
LegoPathActor* actor = m_unk0x1138;
|
||||
actor->SetActorState(LegoPathActor::c_disabled);
|
||||
|
||||
m_gameState->SetUnknown0x08(104);
|
||||
m_gameState->SetState(LegoAct2State::c_badEnding);
|
||||
m_destLocation = LegoGameState::e_infomain;
|
||||
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
|
||||
|
||||
|
||||
@ -61,8 +61,7 @@ class MxDisplaySurface : public MxCore {
|
||||
MxS32 p_right,
|
||||
MxS32 p_bottom,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height,
|
||||
MxBool p_RLE
|
||||
MxS32 p_height
|
||||
); // vtable+0x2c
|
||||
virtual void VTable0x30(
|
||||
MxBitmap* p_bitmap,
|
||||
@ -71,8 +70,7 @@ class MxDisplaySurface : public MxCore {
|
||||
MxS32 p_right,
|
||||
MxS32 p_bottom,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height,
|
||||
MxBool p_RLE
|
||||
MxS32 p_height
|
||||
); // vtable+0x30
|
||||
virtual void Display(
|
||||
MxS32 p_left,
|
||||
@ -92,23 +90,12 @@ class MxDisplaySurface : public MxCore {
|
||||
); // vtable+0x44
|
||||
|
||||
void ClearScreen();
|
||||
static LPDIRECTDRAWSURFACE CreateCursorSurface(const CursorBitmap* p_cursorBitmap);
|
||||
static LPDIRECTDRAWSURFACE CreateCursorSurface(const CursorBitmap* p_cursorBitmap, MxPalette* p_palette);
|
||||
static LPDIRECTDRAWSURFACE CopySurface(LPDIRECTDRAWSURFACE p_src);
|
||||
|
||||
LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return m_ddSurface1; }
|
||||
LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return m_ddSurface2; }
|
||||
MxVideoParam& GetVideoParam() { return m_videoParam; }
|
||||
|
||||
void DrawTransparentRLE(
|
||||
MxU8*& p_bitmapData,
|
||||
MxU8*& p_surfaceData,
|
||||
MxU32 p_bitmapSize,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height,
|
||||
MxLong p_pitch,
|
||||
MxU8 p_bpp
|
||||
);
|
||||
|
||||
LPDIRECTDRAWSURFACE FUN_100bc8b0(MxS32 p_width, MxS32 p_height);
|
||||
|
||||
private:
|
||||
|
||||
@ -91,6 +91,12 @@ class MxDSBuffer : public MxCore {
|
||||
|
||||
void SetUnk30(MxDSStreamingAction* p_unk0x30) { m_unk0x30 = p_unk0x30; }
|
||||
|
||||
void SetSourceBuffer(MxDSBuffer* p_sourceBuffer)
|
||||
{
|
||||
m_sourceBuffer = p_sourceBuffer;
|
||||
m_sourceBuffer->AddRef(NULL);
|
||||
}
|
||||
|
||||
// SYNTHETIC: LEGO1 0x100c6510
|
||||
// SYNTHETIC: BETA10 0x10158530
|
||||
// MxDSBuffer::`scalar deleting destructor'
|
||||
@ -107,6 +113,7 @@ class MxDSBuffer : public MxCore {
|
||||
MxU32 m_writeOffset; // 0x28
|
||||
MxU32 m_bytesRemaining; // 0x2c
|
||||
MxDSStreamingAction* m_unk0x30; // 0x30
|
||||
MxDSBuffer* m_sourceBuffer;
|
||||
};
|
||||
|
||||
#endif // MXDSBUFFER_H
|
||||
|
||||
@ -29,7 +29,7 @@ enum NotificationId {
|
||||
c_notificationPathStruct = 19, // 100d6230
|
||||
c_notificationType20 = 20,
|
||||
c_notificationNewPresenter = 21,
|
||||
c_notificationType22 = 22,
|
||||
c_notificationAct2Brick = 22,
|
||||
c_notificationType23 = 23,
|
||||
c_notificationTransitioned = 24
|
||||
};
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
// SIZE 0x10
|
||||
class MxString : public MxCore {
|
||||
public:
|
||||
MxString();
|
||||
LEGO1_EXPORT MxString();
|
||||
MxString(const MxString& p_str);
|
||||
LEGO1_EXPORT MxString(const char* p_str);
|
||||
MxString(const char* p_str, MxU16 p_maxlen);
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "compat.h"
|
||||
#include "decomp.h"
|
||||
#include "extensions/siloader.h"
|
||||
#include "mxautolock.h"
|
||||
#include "mxmisc.h"
|
||||
#include "mxnotificationparam.h"
|
||||
@ -12,6 +13,8 @@
|
||||
DECOMP_SIZE_ASSERT(MxNotification, 0x08);
|
||||
DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40);
|
||||
|
||||
using namespace Extensions;
|
||||
|
||||
// FUNCTION: LEGO1 0x100ac220
|
||||
MxNotification::MxNotification(MxCore* p_target, const MxNotificationParam& p_param)
|
||||
{
|
||||
@ -105,6 +108,11 @@ MxResult MxNotificationManager::Tickle()
|
||||
while (m_sendList->size() != 0) {
|
||||
MxNotification* notif = m_sendList->front();
|
||||
m_sendList->pop_front();
|
||||
|
||||
if (notif->GetParam()->GetNotification() == c_notificationEndAction) {
|
||||
Extension<SiLoader>::Call(HandleEndAction, (MxEndActionNotificationParam&) *notif->GetParam());
|
||||
}
|
||||
|
||||
notif->GetTarget()->Notify(*notif->GetParam());
|
||||
delete notif;
|
||||
}
|
||||
@ -159,6 +167,11 @@ void MxNotificationManager::FlushPending(MxCore* p_listener)
|
||||
while (pending.size() != 0) {
|
||||
notif = pending.front();
|
||||
pending.pop_front();
|
||||
|
||||
if (notif->GetParam()->GetNotification() == c_notificationEndAction) {
|
||||
Extension<SiLoader>::Call(HandleEndAction, (MxEndActionNotificationParam&) *notif->GetParam());
|
||||
}
|
||||
|
||||
notif->GetTarget()->Notify(*notif->GetParam());
|
||||
delete notif;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ MxResult MxDiskStreamProviderThread::Run()
|
||||
MxResult MxDiskStreamProviderThread::StartWithTarget(MxDiskStreamProvider* p_target)
|
||||
{
|
||||
m_target = p_target;
|
||||
return Start(0x1000, 0);
|
||||
return Start(0, 0);
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100d0f70
|
||||
|
||||
@ -28,6 +28,7 @@ MxDSBuffer::MxDSBuffer()
|
||||
m_bytesRemaining = 0;
|
||||
m_mode = e_preallocated;
|
||||
m_unk0x30 = 0;
|
||||
m_sourceBuffer = NULL;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6530
|
||||
@ -36,6 +37,10 @@ MxDSBuffer::~MxDSBuffer()
|
||||
{
|
||||
assert(m_referenceCount == 0);
|
||||
|
||||
if (m_sourceBuffer) {
|
||||
m_sourceBuffer->ReleaseRef(NULL);
|
||||
}
|
||||
|
||||
if (m_pBuffer != NULL) {
|
||||
switch (m_mode) {
|
||||
case e_allocate:
|
||||
@ -267,6 +272,28 @@ MxResult MxDSBuffer::ParseChunk(
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
// START FIX: Ref-Counting Backpressure for Split Chunks
|
||||
//
|
||||
// PROBLEM: When a `DS_CHUNK_SPLIT` is found, the temporary `MxStreamChunk`
|
||||
// header that holds a reference to the source buffer is immediately
|
||||
// destroyed. This prematurely releases the reference, causing the source
|
||||
// buffer's ref-count to drop to zero.
|
||||
//
|
||||
// EFFECT: The source buffer is freed immediately instead of being kept
|
||||
// alive on the m_list0x74 "keep-alive" list. This breaks the natural
|
||||
// ref-counting backpressure mechanism, as the controller is blind to the
|
||||
// downstream workload and keeps reading new data from the stream at full
|
||||
// speed, eventually leading to a memory leak.
|
||||
//
|
||||
// SOLUTION: We explicitly link the new reassembly buffer to the original
|
||||
// source buffer. We then add an artificial reference to the source buffer.
|
||||
// This reference is designed to be released by the reassembly buffer's
|
||||
// destructor, ensuring the source buffer is kept alive for the correct
|
||||
// duration and that the backpressure system functions as intended.
|
||||
if (p_header->GetBuffer()) {
|
||||
buffer->SetSourceBuffer(p_header->GetBuffer());
|
||||
}
|
||||
|
||||
MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer());
|
||||
*flags = p_header->GetChunkFlags() & ~DS_CHUNK_SPLIT;
|
||||
|
||||
@ -409,9 +436,7 @@ MxU8 MxDSBuffer::ReleaseRef(MxDSChunk*)
|
||||
// FUNCTION: LEGO1 0x100c6ee0
|
||||
void MxDSBuffer::AddRef(MxDSChunk* p_chunk)
|
||||
{
|
||||
if (p_chunk) {
|
||||
m_referenceCount++;
|
||||
}
|
||||
m_referenceCount++;
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100c6ef0
|
||||
|
||||
@ -66,7 +66,7 @@ MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType)
|
||||
|
||||
MxStreamController* stream = NULL;
|
||||
|
||||
if (GetOpenStream(p_name)) {
|
||||
if ((stream = GetOpenStream(p_name))) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
@ -327,6 +327,7 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MINIWIN
|
||||
MxS32 bitCount = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount;
|
||||
if (bitCount == 8) {
|
||||
return;
|
||||
@ -378,6 +379,7 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette)
|
||||
m_32bitPal[i] = red | green | blue | alpha;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bacc0
|
||||
@ -412,7 +414,13 @@ void MxDisplaySurface::VTable0x28(
|
||||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
|
||||
ddsd.dwWidth = p_width;
|
||||
ddsd.dwHeight = p_height;
|
||||
#ifdef MINIWIN
|
||||
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
|
||||
ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
|
||||
#else
|
||||
ddsd.ddpfPixelFormat = m_surfaceDesc.ddpfPixelFormat;
|
||||
#endif
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
||||
|
||||
LPDIRECTDRAWSURFACE tempSurface = nullptr;
|
||||
@ -422,6 +430,25 @@ void MxDisplaySurface::VTable0x28(
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MINIWIN
|
||||
MxBITMAPINFO* bmi = p_bitmap->GetBitmapInfo();
|
||||
if (bmi) {
|
||||
PALETTEENTRY pe[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
pe[i].peRed = bmi->m_bmiColors[i].rgbRed;
|
||||
pe[i].peGreen = bmi->m_bmiColors[i].rgbGreen;
|
||||
pe[i].peBlue = bmi->m_bmiColors[i].rgbBlue;
|
||||
pe[i].peFlags = PC_NONE;
|
||||
}
|
||||
|
||||
LPDIRECTDRAWPALETTE palette = nullptr;
|
||||
if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &palette, NULL) == DD_OK && palette) {
|
||||
tempSurface->SetPalette(palette);
|
||||
palette->Release();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount != 32) {
|
||||
DDCOLORKEY colorKey;
|
||||
if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount == 8) {
|
||||
@ -450,7 +477,7 @@ void MxDisplaySurface::VTable0x28(
|
||||
|
||||
MxU8* data = p_bitmap->GetStart(p_left, p_top);
|
||||
|
||||
MxS32 bytesPerPixel = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
MxS32 bytesPerPixel = tempDesc.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
MxU8* surface = (MxU8*) tempDesc.lpSurface;
|
||||
|
||||
MxLong stride = (bytesPerPixel == 1) ? GetAdjustedStride(p_bitmap) : -p_width + GetAdjustedStride(p_bitmap);
|
||||
@ -502,8 +529,7 @@ void MxDisplaySurface::VTable0x30(
|
||||
MxS32 p_right,
|
||||
MxS32 p_bottom,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height,
|
||||
MxBool p_RLE
|
||||
MxS32 p_height
|
||||
)
|
||||
{
|
||||
if (!GetRectIntersection(
|
||||
@ -526,7 +552,13 @@ void MxDisplaySurface::VTable0x30(
|
||||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
|
||||
ddsd.dwWidth = p_width;
|
||||
ddsd.dwHeight = p_height;
|
||||
#ifdef MINIWIN
|
||||
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
|
||||
ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
|
||||
#else
|
||||
ddsd.ddpfPixelFormat = m_surfaceDesc.ddpfPixelFormat;
|
||||
#endif
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
||||
|
||||
LPDIRECTDRAW draw = MVideoManager()->GetDirectDraw();
|
||||
@ -535,6 +567,25 @@ void MxDisplaySurface::VTable0x30(
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MINIWIN
|
||||
MxBITMAPINFO* bmi = p_bitmap->GetBitmapInfo();
|
||||
if (bmi) {
|
||||
PALETTEENTRY pe[256];
|
||||
for (int i = 1; i < 256; i++) {
|
||||
pe[i].peRed = bmi->m_bmiColors[i].rgbRed;
|
||||
pe[i].peGreen = bmi->m_bmiColors[i].rgbGreen;
|
||||
pe[i].peBlue = bmi->m_bmiColors[i].rgbBlue;
|
||||
pe[i].peFlags = PC_NONE;
|
||||
}
|
||||
|
||||
LPDIRECTDRAWPALETTE palette = nullptr;
|
||||
if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &palette, NULL) == DD_OK && palette) {
|
||||
tempSurface->SetPalette(palette);
|
||||
palette->Release();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DDCOLORKEY colorKey;
|
||||
colorKey.dwColorSpaceLowValue = colorKey.dwColorSpaceHighValue = 0;
|
||||
tempSurface->SetColorKey(DDCKEY_SRCBLT, &colorKey);
|
||||
@ -550,38 +601,32 @@ void MxDisplaySurface::VTable0x30(
|
||||
|
||||
MxU8* data = p_bitmap->GetStart(p_left, p_top);
|
||||
|
||||
MxS32 bytesPerPixel = m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
MxS32 bytesPerPixel = tempDesc.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
MxU8* surface = (MxU8*) tempDesc.lpSurface;
|
||||
|
||||
if (p_RLE) {
|
||||
MxS32 size = p_bitmap->GetBmiHeader()->biSizeImage;
|
||||
DrawTransparentRLE(data, surface, size, p_width, p_height, tempDesc.lPitch, bytesPerPixel * 8);
|
||||
}
|
||||
else {
|
||||
MxLong stride = -p_width + GetAdjustedStride(p_bitmap);
|
||||
MxLong length = -bytesPerPixel * p_width + tempDesc.lPitch;
|
||||
MxLong stride = -p_width + GetAdjustedStride(p_bitmap);
|
||||
MxLong length = -bytesPerPixel * p_width + tempDesc.lPitch;
|
||||
|
||||
for (MxS32 i = 0; i < p_height; i++) {
|
||||
for (MxS32 j = 0; j < p_width; j++) {
|
||||
if (*data != 0) {
|
||||
switch (bytesPerPixel) {
|
||||
case 1:
|
||||
*surface = *data;
|
||||
break;
|
||||
case 2:
|
||||
*(MxU16*) surface = m_16bitPal[*data];
|
||||
break;
|
||||
default:
|
||||
*(MxU32*) surface = m_32bitPal[*data];
|
||||
break;
|
||||
}
|
||||
for (MxS32 i = 0; i < p_height; i++) {
|
||||
for (MxS32 j = 0; j < p_width; j++) {
|
||||
if (*data != 0) {
|
||||
switch (bytesPerPixel) {
|
||||
case 1:
|
||||
*surface = *data;
|
||||
break;
|
||||
case 2:
|
||||
*(MxU16*) surface = m_16bitPal[*data];
|
||||
break;
|
||||
default:
|
||||
*(MxU32*) surface = m_32bitPal[*data];
|
||||
break;
|
||||
}
|
||||
data++;
|
||||
surface += bytesPerPixel;
|
||||
}
|
||||
data += stride;
|
||||
surface += length;
|
||||
data++;
|
||||
surface += bytesPerPixel;
|
||||
}
|
||||
data += stride;
|
||||
surface += length;
|
||||
}
|
||||
|
||||
tempSurface->Unlock(NULL);
|
||||
@ -591,161 +636,6 @@ void MxDisplaySurface::VTable0x30(
|
||||
tempSurface->Release();
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bb500
|
||||
// FUNCTION: BETA10 0x10140cd6
|
||||
void MxDisplaySurface::DrawTransparentRLE(
|
||||
MxU8*& p_bitmapData,
|
||||
MxU8*& p_surfaceData,
|
||||
MxU32 p_bitmapSize,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height,
|
||||
MxLong p_pitch,
|
||||
MxU8 p_bpp
|
||||
)
|
||||
{
|
||||
/* Assumes partial RLE for the bitmap: only the skipped pixels are compressed.
|
||||
The drawn pixels are uncompressed. The procedure is:
|
||||
1. Read 3 bytes from p_bitmapData. Skip this many pixels on the surface.
|
||||
2. Read 3 bytes from p_bitmapData. Draw this many pixels on the surface.
|
||||
3. Repeat until the end of p_bitmapData is reached. */
|
||||
|
||||
MxU8* end = p_bitmapData + p_bitmapSize;
|
||||
MxU8* surfCopy = p_surfaceData; // unused?
|
||||
|
||||
// The total number of pixels drawn or skipped
|
||||
MxU32 count = 0;
|
||||
|
||||
// Used in both 8 and 16 bit branches
|
||||
MxU32 skipCount;
|
||||
MxU32 drawCount;
|
||||
MxU32 t;
|
||||
|
||||
if (p_bpp == 16) {
|
||||
// DECOMP: why goto?
|
||||
goto sixteen_bit;
|
||||
}
|
||||
|
||||
while (p_bitmapData < end) {
|
||||
skipCount = *p_bitmapData++;
|
||||
t = *p_bitmapData++;
|
||||
skipCount += t << 8;
|
||||
t = *p_bitmapData++;
|
||||
skipCount += t << 16;
|
||||
|
||||
MxS32 rowRemainder = p_width - count % p_width;
|
||||
count += skipCount;
|
||||
|
||||
if (skipCount >= rowRemainder) {
|
||||
p_surfaceData += rowRemainder; // skip the rest of this row
|
||||
skipCount -= rowRemainder;
|
||||
p_surfaceData += p_pitch - p_width; // seek to start of next row
|
||||
p_surfaceData += p_pitch * (skipCount / p_width); // skip entire rows if any
|
||||
}
|
||||
|
||||
// skip any pixels at the start of this row
|
||||
p_surfaceData += skipCount % p_width;
|
||||
if (p_bitmapData >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
drawCount = *p_bitmapData++;
|
||||
t = *p_bitmapData++;
|
||||
drawCount += t << 8;
|
||||
t = *p_bitmapData++;
|
||||
drawCount += t << 16;
|
||||
|
||||
rowRemainder = p_width - count % p_width;
|
||||
count += drawCount;
|
||||
|
||||
if (drawCount >= rowRemainder) {
|
||||
memcpy(p_surfaceData, p_bitmapData, rowRemainder);
|
||||
p_surfaceData += rowRemainder;
|
||||
p_bitmapData += rowRemainder;
|
||||
|
||||
drawCount -= rowRemainder;
|
||||
|
||||
// seek to start of bitmap on this screen row
|
||||
p_surfaceData += p_pitch - p_width;
|
||||
MxS32 rows = drawCount / p_width;
|
||||
|
||||
for (MxU32 i = 0; i < rows; i++) {
|
||||
memcpy(p_surfaceData, p_bitmapData, p_width);
|
||||
p_bitmapData += p_width;
|
||||
p_surfaceData += p_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
MxS32 tail = drawCount % p_width;
|
||||
memcpy(p_surfaceData, p_bitmapData, tail);
|
||||
p_surfaceData += tail;
|
||||
p_bitmapData += tail;
|
||||
}
|
||||
return;
|
||||
|
||||
sixteen_bit:
|
||||
while (p_bitmapData < end) {
|
||||
skipCount = *p_bitmapData++;
|
||||
t = *p_bitmapData++;
|
||||
skipCount += t << 8;
|
||||
t = *p_bitmapData++;
|
||||
skipCount += t << 16;
|
||||
|
||||
MxS32 rowRemainder = p_width - count % p_width;
|
||||
count += skipCount;
|
||||
|
||||
if (skipCount >= rowRemainder) {
|
||||
p_surfaceData += 2 * rowRemainder;
|
||||
skipCount -= rowRemainder;
|
||||
p_surfaceData += p_pitch - 2 * p_width;
|
||||
p_surfaceData += p_pitch * (skipCount / p_width);
|
||||
}
|
||||
|
||||
p_surfaceData += 2 * (skipCount % p_width);
|
||||
if (p_bitmapData >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
drawCount = *p_bitmapData++;
|
||||
t = *p_bitmapData++;
|
||||
drawCount += t << 8;
|
||||
t = *p_bitmapData++;
|
||||
drawCount += t << 16;
|
||||
|
||||
rowRemainder = p_width - count % p_width;
|
||||
count += drawCount;
|
||||
|
||||
if (drawCount >= rowRemainder) {
|
||||
// memcpy
|
||||
for (MxU32 j = 0; j < rowRemainder; j++) {
|
||||
*((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++];
|
||||
p_surfaceData += 2;
|
||||
}
|
||||
|
||||
drawCount -= rowRemainder;
|
||||
|
||||
p_surfaceData += p_pitch - 2 * p_width;
|
||||
MxS32 rows = drawCount / p_width;
|
||||
|
||||
for (MxU32 i = 0; i < rows; i++) {
|
||||
// memcpy
|
||||
for (MxS32 j = 0; j < p_width; j++) {
|
||||
*((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++];
|
||||
p_surfaceData += 2;
|
||||
}
|
||||
|
||||
p_surfaceData += p_pitch - 2 * p_width;
|
||||
}
|
||||
}
|
||||
|
||||
MxS32 tail = drawCount % p_width;
|
||||
// memcpy
|
||||
for (MxS32 j = 0; j < tail; j++) {
|
||||
*((MxU16*) p_surfaceData) = m_16bitPal[*p_bitmapData++];
|
||||
p_surfaceData += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FUNCTION: LEGO1 0x100bba50
|
||||
void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height)
|
||||
{
|
||||
@ -829,7 +719,13 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(
|
||||
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
||||
ddsd.dwWidth = p_bitmap->GetBmiWidth();
|
||||
ddsd.dwHeight = p_bitmap->GetBmiHeightAbs();
|
||||
#ifdef MINIWIN
|
||||
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
|
||||
ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
|
||||
#else
|
||||
ddsd.ddpfPixelFormat = m_surfaceDesc.ddpfPixelFormat;
|
||||
#endif
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
||||
*p_ret = 0;
|
||||
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
||||
@ -852,6 +748,29 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(
|
||||
}
|
||||
|
||||
if (surface) {
|
||||
#ifdef MINIWIN
|
||||
MxBITMAPINFO* bmi = p_bitmap->GetBitmapInfo();
|
||||
if (bmi) {
|
||||
PALETTEENTRY pe[256];
|
||||
for (int i = 0; i < 256; i++) {
|
||||
pe[i].peRed = bmi->m_bmiColors[i].rgbRed;
|
||||
pe[i].peGreen = bmi->m_bmiColors[i].rgbGreen;
|
||||
pe[i].peBlue = bmi->m_bmiColors[i].rgbBlue;
|
||||
pe[i].peFlags = PC_NONE;
|
||||
}
|
||||
if (p_transparent) {
|
||||
pe[0].peRed = 0;
|
||||
pe[0].peGreen = 0;
|
||||
pe[0].peBlue = 0;
|
||||
}
|
||||
LPDIRECTDRAWPALETTE palette = nullptr;
|
||||
if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &palette, NULL) == DD_OK && palette) {
|
||||
surface->SetPalette(palette);
|
||||
palette->Release();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
@ -971,6 +890,21 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CopySurface(LPDIRECTDRAWSURFACE p_src)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef MINIWIN
|
||||
LPDIRECTDRAWPALETTE srcPalette = nullptr;
|
||||
if (p_src->GetPalette(&srcPalette) == DD_OK && srcPalette) {
|
||||
PALETTEENTRY pe[256];
|
||||
if (srcPalette->GetEntries(0, 0, 256, pe) == DD_OK) {
|
||||
LPDIRECTDRAWPALETTE newPalette = nullptr;
|
||||
if (draw->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &newPalette, NULL) == DD_OK) {
|
||||
newSurface->SetPalette(newPalette);
|
||||
newPalette->Release();
|
||||
}
|
||||
}
|
||||
srcPalette->Release();
|
||||
}
|
||||
#endif
|
||||
|
||||
RECT rect = {0, 0, (LONG) ddsd.dwWidth, (LONG) ddsd.dwHeight};
|
||||
|
||||
if (newSurface->BltFast(0, 0, p_src, &rect, DDBLTFAST_WAIT) != DD_OK) {
|
||||
@ -1084,8 +1018,7 @@ void MxDisplaySurface::VTable0x2c(
|
||||
MxS32 p_right,
|
||||
MxS32 p_bottom,
|
||||
MxS32 p_width,
|
||||
MxS32 p_height,
|
||||
MxBool p_RLE
|
||||
MxS32 p_height
|
||||
)
|
||||
{
|
||||
// DECOMP: Almost an exact copy of VTable0x28, except that it uses the argument DDSURFACEDESC
|
||||
@ -1111,38 +1044,25 @@ void MxDisplaySurface::VTable0x2c(
|
||||
MxLong destStride = p_desc->lPitch;
|
||||
MxU8* dest = (MxU8*) p_desc->lpSurface + bytesPerPixel * p_right + (p_bottom * destStride);
|
||||
|
||||
if (p_RLE) {
|
||||
DrawTransparentRLE(
|
||||
src,
|
||||
dest,
|
||||
p_bitmap->GetBmiHeader()->biSizeImage,
|
||||
p_width,
|
||||
p_height,
|
||||
destStride,
|
||||
m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount
|
||||
);
|
||||
}
|
||||
else {
|
||||
MxLong srcStride = GetAdjustedStride(p_bitmap);
|
||||
MxLong srcSkip = srcStride - p_width;
|
||||
MxLong destSkip = destStride - bytesPerPixel * p_width;
|
||||
for (MxS32 i = 0; i < p_height; i++, src += srcSkip, dest += destSkip) {
|
||||
for (MxS32 j = 0; j < p_width; j++, src++) {
|
||||
if (*src != 0) {
|
||||
switch (bytesPerPixel) {
|
||||
case 1:
|
||||
*dest = *src;
|
||||
break;
|
||||
case 2:
|
||||
*(MxU16*) dest = m_16bitPal[*src];
|
||||
break;
|
||||
default:
|
||||
*(MxU32*) dest = m_32bitPal[*src];
|
||||
break;
|
||||
}
|
||||
MxLong srcStride = GetAdjustedStride(p_bitmap);
|
||||
MxLong srcSkip = srcStride - p_width;
|
||||
MxLong destSkip = destStride - bytesPerPixel * p_width;
|
||||
for (MxS32 i = 0; i < p_height; i++, src += srcSkip, dest += destSkip) {
|
||||
for (MxS32 j = 0; j < p_width; j++, src++) {
|
||||
if (*src != 0) {
|
||||
switch (bytesPerPixel) {
|
||||
case 1:
|
||||
*dest = *src;
|
||||
break;
|
||||
case 2:
|
||||
*(MxU16*) dest = m_16bitPal[*src];
|
||||
break;
|
||||
default:
|
||||
*(MxU32*) dest = m_32bitPal[*src];
|
||||
break;
|
||||
}
|
||||
dest += bytesPerPixel;
|
||||
}
|
||||
dest += bytesPerPixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1183,11 +1103,10 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::FUN_100bc8b0(MxS32 p_width, MxS32 p_height
|
||||
return surface;
|
||||
}
|
||||
|
||||
LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_cursorBitmap)
|
||||
LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_cursorBitmap, MxPalette* p_palette)
|
||||
{
|
||||
LPDIRECTDRAWSURFACE newSurface = NULL;
|
||||
IDirectDraw* draw = MVideoManager()->GetDirectDraw();
|
||||
MVideoManager();
|
||||
|
||||
DDSURFACEDESC ddsd;
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
@ -1197,14 +1116,19 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
MxBool isAlphaAvailable = ((ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == DDPF_ALPHAPIXELS) &&
|
||||
(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask != 0);
|
||||
|
||||
ddsd.dwWidth = p_cursorBitmap->width;
|
||||
ddsd.dwHeight = p_cursorBitmap->height;
|
||||
ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||||
ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN;
|
||||
#ifdef MINIWIN
|
||||
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
||||
ddsd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8 | DDPF_RGB;
|
||||
ddsd.ddpfPixelFormat.dwRGBBitCount = 8;
|
||||
#endif
|
||||
|
||||
MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8;
|
||||
MxBool isAlphaAvailable = ((ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == DDPF_ALPHAPIXELS) &&
|
||||
(ddsd.ddpfPixelFormat.dwRGBAlphaBitMask != 0);
|
||||
|
||||
if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) {
|
||||
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
||||
@ -1215,6 +1139,10 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MINIWIN
|
||||
newSurface->SetPalette(p_palette->CreateNativePalette());
|
||||
#endif
|
||||
|
||||
memset(&ddsd, 0, sizeof(ddsd));
|
||||
ddsd.dwSize = sizeof(ddsd);
|
||||
|
||||
@ -1242,6 +1170,8 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_
|
||||
else {
|
||||
pixel = isBlack ? 0 : 0xff;
|
||||
}
|
||||
surface[x + y * p_cursorBitmap->width] = pixel;
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
MxU16* surface = (MxU16*) ddsd.lpSurface;
|
||||
@ -1284,8 +1214,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface(const CursorBitmap* p_
|
||||
switch (bytesPerPixel) {
|
||||
case 1: {
|
||||
DDCOLORKEY colorkey;
|
||||
colorkey.dwColorSpaceHighValue = 0x10;
|
||||
colorkey.dwColorSpaceLowValue = 0x10;
|
||||
colorkey.dwColorSpaceHighValue = colorkey.dwColorSpaceLowValue = 0x10;
|
||||
newSurface->SetColorKey(DDCKEY_SRCBLT, &colorkey);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -200,22 +200,6 @@ inline MxS32 MxVideoPresenter::PrepareRects(RECT& p_rectDest, RECT& p_rectSrc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (p_rectDest.bottom > 480) {
|
||||
p_rectDest.bottom = 480;
|
||||
}
|
||||
|
||||
if (p_rectDest.right > 640) {
|
||||
p_rectDest.right = 640;
|
||||
}
|
||||
|
||||
if (p_rectSrc.bottom > 480) {
|
||||
p_rectSrc.bottom = 480;
|
||||
}
|
||||
|
||||
if (p_rectSrc.right > 640) {
|
||||
p_rectSrc.right = 640;
|
||||
}
|
||||
|
||||
int height, width;
|
||||
if ((height = (p_rectDest.bottom - p_rectDest.top) + 1) <= 1 ||
|
||||
(width = (p_rectDest.right - p_rectDest.left) + 1) <= 1) {
|
||||
@ -269,8 +253,7 @@ void MxVideoPresenter::PutFrame()
|
||||
rect.GetLeft(),
|
||||
rect.GetTop(),
|
||||
m_frameBitmap->GetBmiWidth(),
|
||||
m_frameBitmap->GetBmiHeightAbs(),
|
||||
TRUE
|
||||
m_frameBitmap->GetBmiHeightAbs()
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -296,7 +279,7 @@ void MxVideoPresenter::PutFrame()
|
||||
}
|
||||
}
|
||||
else {
|
||||
displaySurface->VTable0x30(m_frameBitmap, 0, 0, GetX(), GetY(), GetWidth(), GetHeight(), FALSE);
|
||||
displaySurface->VTable0x30(m_frameBitmap, 0, 0, GetX(), GetY(), GetWidth(), GetHeight());
|
||||
}
|
||||
}
|
||||
else if (m_surface) {
|
||||
|
||||
@ -17,6 +17,8 @@ Please note: this project is primarily dedicated to achieving platform independe
|
||||
| Nintendo 3DS | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
| Xbox One | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
| iOS | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
| Android | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
| Playstation Vita | [](https://github.com/isledecomp/isle-portable/actions/workflows/ci.yml) |
|
||||
|
||||
We are actively working to support more platforms. If you have experience with a particular platform, we encourage you to contribute to `isle-portable`. You can find a [list of ongoing efforts](https://github.com/isledecomp/isle-portable/wiki/Work%E2%80%90in%E2%80%90progress-ports) in our Wiki.
|
||||
|
||||
@ -43,7 +45,7 @@ To achieve our goal of platform independence, we need to replace any Windows-onl
|
||||
| WinMM, DirectSound (Audio) | [SDL3](https://www.libsdl.org/), [miniaudio](https://miniaud.io/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Aaudio%5D%22&type=code) |
|
||||
| DirectDraw (2D video) | [SDL3](https://www.libsdl.org/) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3A2d%5D%22&type=code) |
|
||||
| [Smacker](https://github.com/isledecomp/isle/tree/master/3rdparty/smacker) | [libsmacker](https://github.com/foxtacles/libsmacker) | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable%20%22%2F%2F%20%5Blibrary%3Alibsmacker%5D%22&type=code) |
|
||||
| Direct3D (3D video) | [SDL3 (Vulkan, Metal, D3D12)](https://www.libsdl.org/), D3D9, OpenGL, OpenGL ES, Software | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3A3d%5D%22&type=code) |
|
||||
| Direct3D (3D video) | [SDL3 (Vulkan, Metal, D3D12)](https://www.libsdl.org/), D3D9, OpenGL 1.1, OpenGL ES 2.0, OpenGL ES 3.0, Software | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3A3d%5D%22&type=code) |
|
||||
| Direct3D Retained Mode | Custom re-implementation | ✅ | [Remarks](https://github.com/search?q=repo%3Aisledecomp%2Fisle-portable+%22%2F%2F+%5Blibrary%3Aretained%5D%22&type=code) |
|
||||
| [SmartHeap](https://github.com/isledecomp/isle/tree/master/3rdparty/smartheap) | Default memory allocator | - | - |
|
||||
|
||||
|
||||
5
android-project/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.cxx
|
||||
.gradle
|
||||
local.properties
|
||||
build
|
||||
*.aar
|
||||
101
android-project/app/build.gradle
Normal file
@ -0,0 +1,101 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
}
|
||||
def androidProject = projectDir.parentFile
|
||||
|
||||
android {
|
||||
namespace "org.legoisland.isle"
|
||||
compileSdk 35
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'org.legoisland.isle'
|
||||
minSdk 21
|
||||
targetSdk 35
|
||||
versionCode 1
|
||||
versionName '1.0'
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
arguments '-DANDROID_STL=c++_shared', "-DFETCHCONTENT_BASE_DIR=${androidProject}/build/_deps"
|
||||
if (project.hasProperty('cmakeArgs')) {
|
||||
project.cmakeArgs.split(" ").each {arg -> arguments arg}
|
||||
}
|
||||
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
||||
}
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version "3.30.5"
|
||||
path '../../CMakeLists.txt'
|
||||
}
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
register("release") {
|
||||
enableV4Signing = true
|
||||
keyAlias = System.getenv("SIGNING_KEY_ALIAS")
|
||||
keyPassword = System.getenv("SIGNING_KEY_PASSWORD")
|
||||
System.getenv("SIGNING_STORE_FILE")?.with { storeFile = file(it) }
|
||||
storePassword = System.getenv("SIGNING_STORE_PASSWORD")
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled true
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
buildFeatures {
|
||||
prefab true
|
||||
}
|
||||
}
|
||||
|
||||
afterEvaluate {
|
||||
def androidPath = System.getenv("ANDROID_HOME") ?: android.sdkDirectory
|
||||
def ndkPath = System.getenv("ANDROID_NDK_HOME") ?: android.ndkDirectory
|
||||
|
||||
tasks.named('compileSDL3AndroidArchive').configure {
|
||||
environment "ANDROID_HOME", androidPath
|
||||
environment "ANDROID_NDK_HOME", ndkPath
|
||||
}
|
||||
}
|
||||
|
||||
def aarDest = project.providers.provider { file("${projectDir}/libs/SDL3.aar") }
|
||||
tasks.register('downloadSDL3', Exec) {
|
||||
workingDir = androidProject
|
||||
commandLine 'cmake', '-P', 'downloadSDL3.cmake'
|
||||
}
|
||||
tasks.register('compileSDL3AndroidArchive', Exec) {
|
||||
workingDir = androidProject
|
||||
dependsOn(downloadSDL3)
|
||||
|
||||
def sdl3Dir = "build/_deps/sdl3-src"
|
||||
commandLine 'python', "${sdl3Dir}/build-scripts/build-release.py",
|
||||
'--actions', 'android',
|
||||
'--fast', '--force',
|
||||
"--root=${sdl3Dir}", "--android-api=${android.defaultConfig.minSdk}"
|
||||
|
||||
doLast {
|
||||
def aarFile = file("${androidProject}/${sdl3Dir}/build-android").listFiles().find {
|
||||
it.name.endsWith(".aar")
|
||||
}
|
||||
aarDest.get().parentFile.mkdirs()
|
||||
aarFile.renameTo(aarDest.get())
|
||||
}
|
||||
}
|
||||
tasks.register('ensureSDL3') {
|
||||
// if DOWNLOAD_DEPENDENCIES=OFF download the version appropriate
|
||||
// 'devel android zip' and place the .aar at `aarDest`
|
||||
if (aarDest.get().exists()) { return false }
|
||||
dependsOn(compileSDL3AndroidArchive)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation files('libs/SDL3.aar').builtBy(ensureSDL3)
|
||||
}
|
||||
60
android-project/app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- OpenGL ES 3.0 -->
|
||||
<uses-feature
|
||||
android:glEsVersion="0x00030000"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Touchscreen support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Game controller support -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.gamepad"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.usb.host"
|
||||
android:required="false" />
|
||||
|
||||
<!-- External mouse input events -->
|
||||
<uses-feature
|
||||
android:name="android.hardware.type.pc"
|
||||
android:required="false" />
|
||||
|
||||
<!-- Allow access to the vibrator -->
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:hardwareAccelerated="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name="org.legoisland.isle.IsleActivity"
|
||||
android:exported="true"
|
||||
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
|
||||
android:preferMinimalPostProcessing="true"
|
||||
android:screenOrientation="landscape"
|
||||
android:launchMode="singleInstance">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
BIN
android-project/app/src/main/ic_launcher-playstore.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
@ -0,0 +1,9 @@
|
||||
package org.legoisland.isle;
|
||||
|
||||
import org.libsdl.app.SDLActivity;
|
||||
|
||||
public class IsleActivity extends SDLActivity {
|
||||
protected String[] getLibraries() {
|
||||
return new String[] { "SDL3", "lego1", "isle" };
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,141 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="180"
|
||||
android:viewportHeight="180">
|
||||
<group android:scaleX="0.47"
|
||||
android:scaleY="0.47"
|
||||
android:translateX="47.7"
|
||||
android:translateY="47.7">
|
||||
<path
|
||||
android:pathData="M16.09,16.09m-16.09,0a16.09,16.09 0,1 1,32.18 0a16.09,16.09 0,1 1,-32.18 0"
|
||||
android:strokeWidth="6.09858"
|
||||
android:fillColor="#ffff00"/>
|
||||
<path
|
||||
android:pathData="M9.23,38.09L9.23,65.53"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="9.15"
|
||||
android:fillColor="#ffff00"
|
||||
android:strokeColor="#ffff00"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m66.61,9.11l-27.44,0"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="9.15"
|
||||
android:fillColor="#ffff00"
|
||||
android:strokeColor="#ffff00"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M21.86,39.44 L29.29,61.95"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="9.15"
|
||||
android:fillColor="#ffff00"
|
||||
android:strokeColor="#ffff00"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m33.06,32.76 l19.56,13.39"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="9.15"
|
||||
android:fillColor="#ffff00"
|
||||
android:strokeColor="#ffff00"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m38.74,20.71 l22.48,7.51"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="9.15"
|
||||
android:fillColor="#ffff00"
|
||||
android:strokeColor="#ffff00"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M31.84,157.94l131.47,0l0,18.05l-131.47,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="8.01"
|
||||
android:fillColor="#ffff00"
|
||||
android:strokeColor="#ffff00"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M31.84,79.75l131.47,0l0,18.05l-131.47,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="8.01"
|
||||
android:fillColor="#ffff00"
|
||||
android:strokeColor="#ffff00"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M31.84,131.88l131.47,0l0,18.05l-131.47,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="8.01"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#ff0000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M31.84,105.81l131.47,0l0,18.05l-131.47,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="8.01"
|
||||
android:fillColor="#0000ff"
|
||||
android:strokeColor="#0000ff"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M70.06,80.85l55.04,0l0,68.99l-55.04,0z"
|
||||
android:strokeLineJoin="miter"
|
||||
android:strokeWidth="8.91"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M72.74,85.31l20.36,0l0,24.52l-20.36,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3.04"
|
||||
android:fillColor="#00ffff"
|
||||
android:strokeColor="#00ffff"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M101.96,85.31l20.36,0l0,24.52l-20.36,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3.04"
|
||||
android:fillColor="#00ffff"
|
||||
android:strokeColor="#00ffff"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M72.89,116.22l20.06,0l0,30.02l-20.06,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3.34"
|
||||
android:fillColor="#00ffff"
|
||||
android:strokeColor="#00ffff"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M102.11,116.22l20.06,0l0,30.02l-20.06,0z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3.34"
|
||||
android:fillColor="#00ffff"
|
||||
android:strokeColor="#00ffff"
|
||||
android:strokeLineCap="butt"/>
|
||||
<path
|
||||
android:pathData="M131.19,7.33L131.19,55.6"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4.57"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m111.99,3.21 l38.38,29.26"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4.57"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="m115.82,19.64 l30.2,23.02"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="4.57"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#000000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M19.99,75.94H173.06L150.4,51.32h-7.63l-5.02,6.19h-7.47l-4.27,-8.06h-7.59l-4.57,8.06h-8l-4.69,-8.06h-7.44l-4.18,8.06h-8.45l-3.9,-8.06h-7.23l-4.36,8.06h-8.61l-5.45,-6.19h-6.08z"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="3.04929"
|
||||
android:fillColor="#ff0000"
|
||||
android:strokeColor="#ff0000"
|
||||
android:strokeLineCap="butt"/>
|
||||
</group>
|
||||
</vector>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
BIN
android-project/app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
BIN
android-project/app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
BIN
android-project/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
BIN
android-project/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
BIN
android-project/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#39A0D9</color>
|
||||
</resources>
|
||||
3
android-project/app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Lego Island</string>
|
||||
</resources>
|
||||