diff --git a/.clang-format b/.clang-format index 19e35762..5d97094c 100644 --- a/.clang-format +++ b/.clang-format @@ -30,6 +30,7 @@ QualifierOrder: - const - volatile - type +RemoveSemicolon: true SpaceAfterCStyleCast: true TabWidth: 4 UseTab: ForContinuationAndIndentation diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..189ddf5a --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,6 @@ +Checks: > + -*, + readability-braces-around-statements, + modernize-use-override +WarningsAsErrors: '-*,readability-braces-around-statements,modernize-use-override' +HeaderFilterRegex: ".*" diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index 01b85f47..8e903cc1 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -4,31 +4,23 @@ on: [push, pull_request] jobs: decomplint-isle: - name: 'ISLE annotations' + name: '${{ matrix.who }} annotations' runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + who: + - CONFIG + - ISLE + - LEGO1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install python libraries run: | - pip install -r tools/requirements.txt + python -m pip install -r tools/requirements.txt - name: Run decomplint.py run: | - python3 tools/decomplint/decomplint.py ISLE --module ISLE --warnfail - - decomplint-lego1: - name: 'LEGO1 annotations' - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Install python libraries - run: | - pip install -r tools/requirements.txt - - - name: Run decomplint.py - run: | - python3 tools/decomplint/decomplint.py LEGO1 --module LEGO1 --warnfail + tools/decomplint/decomplint.py ${{ matrix.who }} --module ${{ matrix.who }} --warnfail diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51b0759f..d5085268 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,10 @@ name: Build on: [push, pull_request] jobs: + fetch-deps: + name: Download original binaries + uses: ./.github/workflows/legobin.yml + build-current-toolchain: name: 'Current ${{ matrix.toolchain.name }}' runs-on: windows-latest @@ -14,18 +18,20 @@ jobs: matrix: toolchain: - { name: 'MSVC', shell: 'sh', setup-cmake: true, setup-ninja: true, setup-msvc: true } - - { name: 'msys2 mingw32', shell: 'msys2 {0}', setup-msys2: true } + - { name: 'msys2 mingw32', shell: 'msys2 {0}', msystem: mingw32, msys-env: mingw-w64-i686, clang-tidy: true, werror: true } + - { name: 'msys2 clang32', shell: 'msys2 {0}', msystem: clang32, msys-env: mingw-w64-clang-i686, clang-tidy: true, werror: true, no-dx5-libs: true } steps: - name: Set up MSYS2 - if: matrix.toolchain.setup-msys2 + if: ${{ !!matrix.toolchain.msystem }} uses: msys2/setup-msys2@v2 with: - msystem: mingw32 + msystem: ${{ matrix.toolchain.msystem }} install: >- - mingw-w64-i686-cc - mingw-w64-i686-cmake - mingw-w64-i686-ninja + ${{ matrix.toolchain.msys-env }}-cc + ${{ matrix.toolchain.msys-env }}-cmake + ${{ matrix.toolchain.msys-env }}-ninja + ${{ matrix.toolchain.msys-env }}-clang-tools-extra - name: Setup cmake if: matrix.toolchain.setup-cmake @@ -41,21 +47,26 @@ jobs: with: arch: amd64_x86 # Use the 64-bit x64-native cross tools to build 32-bit x86 code - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Build run: | - cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -GNinja -Werror=dev - cmake --build build + cmake -S . -B build -GNinja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DISLE_USE_DX5_LIBS=${{ !matrix.toolchain.no-dx5-libs }} \ + -DENABLE_CLANG_TIDY=${{ !!matrix.toolchain.clang-tidy }} \ + -DISLE_WERROR=${{ !!matrix.toolchain.werror }} \ + -Werror=dev + cmake --build build -- -k0 build: name: 'MSVC 4.20' runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'itsmattkc/msvc420' path: msvc420 @@ -64,11 +75,11 @@ jobs: uses: jwlawson/actions-setup-cmake@v1.13 with: # Use minimum supported version - cmake-version: '3.13.x' + cmake-version: '3.15.x' - name: Patch MSVC 4.2 run: | - python tools/patch_c2.py msvc420/bin/C2.EXE + tools/patch_c2.py msvc420/bin/C2.EXE - name: Build shell: cmd @@ -82,6 +93,8 @@ jobs: with: name: Win32 path: | + build/CONFIG.EXE + build/CONFIG.PDB build/ISLE.EXE build/ISLE.PDB build/LEGO1.DLL @@ -89,7 +102,7 @@ jobs: compare: name: 'Compare with master' - needs: build + needs: [build, fetch-deps] runs-on: windows-latest steps: - uses: actions/checkout@master @@ -103,19 +116,7 @@ jobs: id: cache-original-binaries uses: actions/cache/restore@v3 with: - path: legobin - key: legobin - - - name: Download original island binares - if: ${{ !steps.cache-original-binaries.outputs.cache-hit }} - run: | - C:\msys64\usr\bin\wget.exe https://legoisland.org/download/ISLE.EXE --directory-prefix=legobin - C:\msys64\usr\bin\wget.exe https://legoisland.org/download/LEGO1.DLL --directory-prefix=legobin - - - name: Cache original binaries - if: ${{ !steps.cache-original-binaries.outputs.cache-hit }} - uses: actions/cache/save@v3 - with: + enableCrossOsArchive: true path: legobin key: legobin @@ -127,6 +128,7 @@ jobs: - name: Summarize Accuracy shell: bash run: | + python3 tools/reccmp/reccmp.py -S CONFIGPROGRESS.SVG --svg-icon tools/reccmp/config.png -H CONFIGPROGRESS.HTML legobin/CONFIG.EXE build/CONFIG.EXE build/CONFIG.PDB . | tee CONFIGPROGRESS.TXT python3 tools/reccmp/reccmp.py -S ISLEPROGRESS.SVG --svg-icon tools/reccmp/isle.png -H ISLEPROGRESS.HTML legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB . | tee ISLEPROGRESS.TXT python3 tools/reccmp/reccmp.py -S LEGO1PROGRESS.SVG -T 4252 --svg-icon tools/reccmp/lego1.png -H LEGO1PROGRESS.HTML legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB . | tee LEGO1PROGRESS.TXT @@ -134,20 +136,23 @@ jobs: shell: bash run: | # Compare with current master - curl -fLSs -o ISLEPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/ISLEPROGRESS.TXT - curl -fLSs -o LEGO1PROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/LEGO1PROGRESS.TXT + curl -fLSs -o CONFIGPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/CONFIGPROGRESS.TXT || echo "" >CONFIGPROGRESS-OLD.TXT + curl -fLSs -o ISLEPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/ISLEPROGRESS.TXT || echo "" >ISLEPROGRESS-OLD.TXT + curl -fLSs -o LEGO1PROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/LEGO1PROGRESS.TXT || echo "" >LEGO1PROGRESS-OLD.TXT + diff -u0 CONFIGPROGRESS-OLD.TXT CONFIGPROGRESS.TXT || true diff -u0 ISLEPROGRESS-OLD.TXT ISLEPROGRESS.TXT || true diff -u0 LEGO1PROGRESS-OLD.TXT LEGO1PROGRESS.TXT || true - name: Test Exports shell: bash run: | - python3 tools/verexp/verexp.py legobin/LEGO1.DLL build/LEGO1.DLL + tools/verexp/verexp.py legobin/LEGO1.DLL build/LEGO1.DLL - name: Check Vtables shell: bash run: | + python3 tools/vtable/vtable.py legobin/CONFIG.EXE build/CONFIG.EXE build/CONFIG.PDB . python3 tools/vtable/vtable.py legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB . python3 tools/vtable/vtable.py legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB . @@ -156,6 +161,7 @@ jobs: with: name: Accuracy Report path: | + CONFIGPROGRESS.* ISLEPROGRESS.* LEGO1PROGRESS.* @@ -165,7 +171,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'isledecomp/isle' }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'probonopd/uploadtool' @@ -184,10 +190,13 @@ jobs: UPLOAD_KEY: ${{ secrets.UPLOAD_KEY }} run: | ./upload.sh \ + build/CONFIG.EXE \ build/ISLE.EXE \ build/LEGO1.DLL \ + CONFIGPROGRESS.* \ ISLEPROGRESS.* \ LEGO1PROGRESS.* + curl -X POST -F key=$UPLOAD_KEY -F 'file=@CONFIGPROGRESS.SVG' https://legoisland.org/progress/ curl -X POST -F key=$UPLOAD_KEY -F 'file=@ISLEPROGRESS.SVG' https://legoisland.org/progress/ curl -X POST -F key=$UPLOAD_KEY -F 'file=@LEGO1PROGRESS.SVG' https://legoisland.org/progress/ diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index ccec2b50..9432beb0 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -8,28 +8,27 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run clang-format run: | - find LEGO1 ISLE -iname '*.h' -o -iname '*.cpp' | xargs \ + find CONFIG LEGO1 ISLE -iname '*.h' -o -iname '*.cpp' | xargs \ pipx run "clang-format>=17,<18" \ - --Werror \ - --dry-run \ --style=file \ -i + git diff --exit-code python-format: name: 'Python' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install python libraries shell: bash run: | - pip install black pylint pytest -r tools/requirements.txt + pip install black==23.* pylint==3.* pytest==7.* -r tools/requirements.txt - name: Run pylint and black shell: bash diff --git a/.github/workflows/legobin.yml b/.github/workflows/legobin.yml new file mode 100644 index 00000000..d9b42bc2 --- /dev/null +++ b/.github/workflows/legobin.yml @@ -0,0 +1,32 @@ +name: Download legobin + +on: + workflow_call: + +jobs: + fetch: + runs-on: ubuntu-latest + steps: + + - name: Restore cached original binaries + id: cache-original-binaries + uses: actions/cache/restore@v3 + with: + enableCrossOsArchive: true + path: legobin + key: legobin + + - name: Download original island binaries + if: ${{ !steps.cache-original-binaries.outputs.cache-hit }} + run: | + wget https://legoisland.org/download/CONFIG.EXE --directory-prefix=legobin + wget https://legoisland.org/download/ISLE.EXE --directory-prefix=legobin + wget https://legoisland.org/download/LEGO1.DLL --directory-prefix=legobin + + - name: Cache original binaries + if: ${{ !steps.cache-original-binaries.outputs.cache-hit }} + uses: actions/cache/save@v3 + with: + enableCrossOsArchive: true + path: legobin + key: legobin diff --git a/.github/workflows/naming.yml b/.github/workflows/naming.yml index a23275e1..b010e69f 100644 --- a/.github/workflows/naming.yml +++ b/.github/workflows/naming.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v1 diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index 612ae3ae..b1dee943 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -3,12 +3,25 @@ name: Test on: [push, pull_request] jobs: + fetch-deps: + name: Download original binaries + uses: ./.github/workflows/legobin.yml + pytest-win: name: 'Python Windows' runs-on: windows-latest + needs: fetch-deps steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + + - name: Restore cached original binaries + id: cache-original-binaries + uses: actions/cache/restore@v3 + with: + enableCrossOsArchive: true + path: legobin + key: legobin - name: Install python libraries shell: bash @@ -18,14 +31,23 @@ jobs: - name: Run python unit tests (Windows) shell: bash run: | - pytest tools/isledecomp + pytest tools/isledecomp --lego1=legobin/LEGO1.DLL pytest-ubuntu: name: 'Python Linux' runs-on: ubuntu-latest + needs: fetch-deps steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 + + - name: Restore cached original binaries + id: cache-original-binaries + uses: actions/cache/restore@v3 + with: + enableCrossOsArchive: true + path: legobin + key: legobin - name: Install python libraries shell: bash @@ -35,4 +57,4 @@ jobs: - name: Run python unit tests (Ubuntu) shell: bash run: | - pytest tools/isledecomp + pytest tools/isledecomp --lego1=legobin/LEGO1.DLL diff --git a/CMakeLists.txt b/CMakeLists.txt index 30f43618..87e23acb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,22 @@ -cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +# MSVC runtime library flags are selected by an abstraction +cmake_policy(SET CMP0091 NEW) project(isle CXX) +include(CheckCXXSourceCompiles) +include(CMakeDependentOption) +include(CMakePushCheckState) + +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) +option(ENABLE_CLANG_TIDY "Enable clang-tidy") +if (ENABLE_CLANG_TIDY) + find_program(CLANG_TIDY_BIN NAMES "clang-tidy") + set(CMAKE_C_CLANG_TIDY "${CLANG_TIDY_BIN}") + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN}") +endif() + math(EXPR bits "8 * ${CMAKE_SIZEOF_VOID_P}") message(STATUS "Building ${bits}-bit LEGO Island") if (NOT bits EQUAL 32) @@ -16,11 +31,239 @@ if (MSVC) endif() endif() +set(lego1_targets) +macro(register_lego1_target __target) + list(APPEND lego1_targets ${__target}) +endmacro() + +function(add_cxx_warning WARNING) + if(ISLE_WERROR) + set(compiler_option "-Werror=${WARNING}") + else() + set(compiler_option "-W${WARNING}") + endif() + string(MAKE_C_IDENTIFIER "COMPILER_SUPPORTS${compiler_option}" varname) + + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_FLAGS "${compiler_option} ") + if(MSVC) + string(APPEND CMAKE_REQUIRED_FLAGS "/WX") + else() + string(APPEND CMAKE_REQUIRED_FLAGS "-Werror") + endif() + check_cxx_source_compiles("int main() { return 0; }" ${varname}) + cmake_pop_check_state() + + if(${varname}) + add_compile_options(${compiler_option}) + endif() +endfunction() + message(STATUS "MSVC for decompilation: ${MSVC_FOR_DECOMP}") +option(ISLE_WERROR "Treat warnings as errors" OFF) option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) +cmake_dependent_option(ISLE_BUILD_CONFIG "Build CONFIG.EXE application" ON "NOT MINGW" OFF) option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC_FOR_DECOMP}) option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" ON) +cmake_dependent_option(ISLE_USE_DX5_LIBS "Build with internal DirectX 5 SDK Libraries" ON ISLE_USE_DX5 OFF) + +add_cxx_warning(parentheses) + +add_library(DirectX5::DirectX5 INTERFACE IMPORTED) +target_include_directories(DirectX5::DirectX5 INTERFACE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/inc") +if(ISLE_USE_DX5_LIBS) + target_link_directories(DirectX5::DirectX5 INTERFACE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/lib") +endif() + +add_library(Smacker::Smacker STATIC IMPORTED) +set_property(TARGET Smacker::Smacker PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/smacker/smack.lib") +set_property(TARGET Smacker::Smacker PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/smacker") + +add_library(FLIC::FLIC STATIC IMPORTED) +set_property(TARGET FLIC::FLIC PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/flic/flic.lib") +set_property(TARGET FLIC::FLIC PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/flic") + +add_library(Vec::Vec INTERFACE IMPORTED) +target_include_directories(Vec::Vec INTERFACE "${CMAKE_SOURCE_DIR}/3rdparty/vec") + +add_library(SmartHeap::SmartHeap STATIC IMPORTED) +set_property(TARGET SmartHeap::SmartHeap PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SHLW32MT.LIB") +set_property(TARGET SmartHeap::SmartHeap PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/smartheap") +set_property(TARGET SmartHeap::SmartHeap PROPERTY INTERFACE_COMPILE_OPTIONS "/FI${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SMRTHEAP.HPP") + +add_library(tglrl STATIC + LEGO1/tgl/d3drm/camera.cpp + LEGO1/tgl/d3drm/device.cpp + LEGO1/tgl/d3drm/group.cpp + LEGO1/tgl/d3drm/light.cpp + LEGO1/tgl/d3drm/mesh.cpp + LEGO1/tgl/d3drm/renderer.cpp + LEGO1/tgl/d3drm/texture.cpp + LEGO1/tgl/d3drm/unk.cpp + LEGO1/tgl/d3drm/view.cpp +) +register_lego1_target(tglrl) +set_property(TARGET tglrl PROPERTY ARCHIVE_OUTPUT_NAME "tglrl40$<$:d>") +target_include_directories(tglrl PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(tglrl PRIVATE d3drm) + +add_library(realtime STATIC + LEGO1/realtime/matrix.cpp + LEGO1/realtime/orientableroi.cpp + LEGO1/realtime/realtime.cpp + LEGO1/realtime/realtimeview.cpp + LEGO1/realtime/vector.cpp +) +register_lego1_target(realtime) +set_property(TARGET realtime PROPERTY ARCHIVE_OUTPUT_NAME "realtime$<$:d>") +target_include_directories(realtime PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(realtime PRIVATE Vec::Vec) + +add_library(viewmanager STATIC + LEGO1/viewmanager/viewlodlist.cpp + LEGO1/viewmanager/viewmanager.cpp + LEGO1/viewmanager/viewroi.cpp +) +register_lego1_target(viewmanager) +set_property(TARGET viewmanager PROPERTY ARCHIVE_OUTPUT_NAME "viewmanager$<$:d>") +target_include_directories(viewmanager PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(viewmanager PRIVATE Vec::Vec) + +add_library(mxdirectx STATIC + LEGO1/mxdirectx/mxdirect3d.cpp + LEGO1/mxdirectx/mxdirectdraw.cpp +) +register_lego1_target(mxdirectx) +set_property(TARGET mxdirectx PROPERTY ARCHIVE_OUTPUT_NAME "MxDirectX$<$:d>") +target_include_directories(mxdirectx PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(mxdirectx PRIVATE ddraw) + +add_library(roi STATIC + LEGO1/lego/sources/roi/legoroi.cpp +) +register_lego1_target(roi) +set_property(TARGET roi PROPERTY ARCHIVE_OUTPUT_NAME "roi$<$:d>") +target_include_directories(roi PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(roi PRIVATE) + +add_library(anim STATIC + LEGO1/lego/sources/anim/legoanim.cpp +) +register_lego1_target(anim) +set_property(TARGET anim PROPERTY ARCHIVE_OUTPUT_NAME "anim$<$:d>") +target_include_directories(anim PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include" "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(anim PRIVATE) + +add_library(misc STATIC + LEGO1/lego/sources/misc/legocontainer.cpp + LEGO1/lego/sources/misc/legoimage.cpp + LEGO1/lego/sources/misc/legostorage.cpp + LEGO1/lego/sources/misc/legotexture.cpp + LEGO1/lego/sources/misc/legotree.cpp +) +register_lego1_target(misc) +set_property(TARGET misc PROPERTY ARCHIVE_OUTPUT_NAME "misc$<$:d>") +target_include_directories(misc PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include" "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(misc PRIVATE) + +add_library(3dmanager STATIC + LEGO1/lego/sources/3dmanager/lego3dmanager.cpp + LEGO1/lego/sources/3dmanager/lego3dview.cpp + LEGO1/lego/sources/3dmanager/legoview1.cpp + LEGO1/lego/sources/3dmanager/tglsurface.cpp +) +register_lego1_target(3dmanager) +set_property(TARGET 3dmanager PROPERTY ARCHIVE_OUTPUT_NAME "3dmanager$<$:d>") +target_include_directories(3dmanager PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(3dmanager PRIVATE Vec::Vec) + +add_library(omni STATIC + LEGO1/omni/src/action/mxdsaction.cpp + LEGO1/omni/src/action/mxdsanim.cpp + LEGO1/omni/src/action/mxdsevent.cpp + LEGO1/omni/src/action/mxdsmediaaction.cpp + LEGO1/omni/src/action/mxdsmultiaction.cpp + LEGO1/omni/src/action/mxdsobjectaction.cpp + LEGO1/omni/src/action/mxdsobject.cpp + LEGO1/omni/src/action/mxdsparallelaction.cpp + LEGO1/omni/src/action/mxdsselectaction.cpp + LEGO1/omni/src/action/mxdsserialaction.cpp + LEGO1/omni/src/action/mxdssound.cpp + LEGO1/omni/src/action/mxdsstill.cpp + LEGO1/omni/src/action/mxdsstreamingaction.cpp + LEGO1/omni/src/audio/mxaudiomanager.cpp + LEGO1/omni/src/audio/mxaudiopresenter.cpp + LEGO1/omni/src/audio/mxloopingmidipresenter.cpp + LEGO1/omni/src/audio/mxmidipresenter.cpp + LEGO1/omni/src/audio/mxmusicmanager.cpp + LEGO1/omni/src/audio/mxmusicpresenter.cpp + LEGO1/omni/src/audio/mxsoundmanager.cpp + LEGO1/omni/src/audio/mxsoundpresenter.cpp + LEGO1/omni/src/audio/mxwavepresenter.cpp + LEGO1/omni/src/common/mxatomidcounter.cpp + LEGO1/omni/src/common/mxatomid.cpp + LEGO1/omni/src/common/mxcompositepresenter.cpp + LEGO1/omni/src/common/mxcore.cpp + LEGO1/omni/src/common/mxmediamanager.cpp + LEGO1/omni/src/common/mxmediapresenter.cpp + LEGO1/omni/src/common/mxobjectfactory.cpp + LEGO1/omni/src/common/mxpresenter.cpp + LEGO1/omni/src/common/mxstring.cpp + LEGO1/omni/src/common/mxticklemanager.cpp + LEGO1/omni/src/common/mxtimer.cpp + LEGO1/omni/src/common/mxutil.cpp + LEGO1/omni/src/common/mxvariable.cpp + LEGO1/omni/src/common/mxvariabletable.cpp + LEGO1/omni/src/entity/mxentity.cpp + LEGO1/omni/src/event/mxeventmanager.cpp + LEGO1/omni/src/event/mxeventpresenter.cpp + LEGO1/omni/src/main/mxomni.cpp + LEGO1/omni/src/main/mxomnicreateflags.cpp + LEGO1/omni/src/main/mxomnicreateparam.cpp + LEGO1/omni/src/notify/mxactionnotificationparam.cpp + LEGO1/omni/src/notify/mxnotificationmanager.cpp + LEGO1/omni/src/notify/mxnotificationparam.cpp + LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp + LEGO1/omni/src/stream/mxdiskstreamprovider.cpp + LEGO1/omni/src/stream/mxdsbuffer.cpp + LEGO1/omni/src/stream/mxdschunk.cpp + LEGO1/omni/src/stream/mxdsfile.cpp + LEGO1/omni/src/stream/mxdssource.cpp + LEGO1/omni/src/stream/mxdssubscriber.cpp + LEGO1/omni/src/stream/mxioinfo.cpp + LEGO1/omni/src/stream/mxramstreamcontroller.cpp + LEGO1/omni/src/stream/mxramstreamprovider.cpp + LEGO1/omni/src/stream/mxstreamchunk.cpp + LEGO1/omni/src/stream/mxstreamcontroller.cpp + LEGO1/omni/src/stream/mxstreamer.cpp + LEGO1/omni/src/stream/mxstreamlist.cpp + LEGO1/omni/src/stream/mxstreamprovider.cpp + LEGO1/omni/src/system/mxautolocker.cpp + LEGO1/omni/src/system/mxcriticalsection.cpp + LEGO1/omni/src/system/mxscheduler.cpp + LEGO1/omni/src/system/mxsemaphore.cpp + LEGO1/omni/src/system/mxthread.cpp + LEGO1/omni/src/video/mxbitmap.cpp + LEGO1/omni/src/video/mxdisplaysurface.cpp + LEGO1/omni/src/video/mxflcpresenter.cpp + LEGO1/omni/src/video/mxloopingflcpresenter.cpp + LEGO1/omni/src/video/mxloopingsmkpresenter.cpp + LEGO1/omni/src/video/mxpalette.cpp + LEGO1/omni/src/video/mxregion.cpp + LEGO1/omni/src/video/mxregioncursor.cpp + LEGO1/omni/src/video/mxsmack.cpp + LEGO1/omni/src/video/mxsmkpresenter.cpp + LEGO1/omni/src/video/mxstillpresenter.cpp + LEGO1/omni/src/video/mxvideomanager.cpp + LEGO1/omni/src/video/mxvideoparam.cpp + LEGO1/omni/src/video/mxvideoparamflags.cpp + LEGO1/omni/src/video/mxvideopresenter.cpp +) +register_lego1_target(omni) +set_property(TARGET omni PROPERTY ARCHIVE_OUTPUT_NAME "omni$<$:d>") +target_include_directories(omni PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include" "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(omni PRIVATE dsound winmm FLIC::FLIC Smacker::Smacker) add_library(lego1 SHARED LEGO1/define.cpp @@ -36,6 +279,8 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/audio/legocachesound.cpp LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp + LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp + LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp LEGO1/lego/legoomni/src/build/buildingentity.cpp LEGO1/lego/legoomni/src/build/dunebuggy.cpp @@ -47,7 +292,6 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp LEGO1/lego/legoomni/src/build/racecar.cpp LEGO1/lego/legoomni/src/common/animstate.cpp - LEGO1/lego/legoomni/src/common/gifmanager.cpp LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp @@ -55,9 +299,10 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp LEGO1/lego/legoomni/src/common/legoplantmanager.cpp LEGO1/lego/legoomni/src/common/legostate.cpp - LEGO1/lego/legoomni/src/common/legostream.cpp + LEGO1/lego/legoomni/src/common/legotextureinfo.cpp LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp LEGO1/lego/legoomni/src/common/legoutil.cpp + LEGO1/lego/legoomni/src/common/legovariables.cpp LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp @@ -144,153 +389,37 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp LEGO1/lego/legoomni/src/video/legovideomanager.cpp LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp - LEGO1/lego/sources/3dmanager/lego3dmanager.cpp - LEGO1/lego/sources/3dmanager/lego3dview.cpp - LEGO1/lego/sources/3dmanager/legoview1.cpp - LEGO1/lego/sources/3dmanager/tglsurface.cpp - LEGO1/lego/sources/roi/legoroi.cpp LEGO1/main.cpp - LEGO1/mxdirectx/mxdirect3d.cpp - LEGO1/mxdirectx/mxdirectdraw.cpp - LEGO1/mxgeometry/mxgeometry3d.cpp - LEGO1/mxgeometry/mxmatrix.cpp - LEGO1/omni/src/action/mxdsaction.cpp - LEGO1/omni/src/action/mxdsanim.cpp - LEGO1/omni/src/action/mxdsevent.cpp - LEGO1/omni/src/action/mxdsmediaaction.cpp - LEGO1/omni/src/action/mxdsmultiaction.cpp - LEGO1/omni/src/action/mxdsobjectaction.cpp - LEGO1/omni/src/action/mxdsobject.cpp - LEGO1/omni/src/action/mxdsparallelaction.cpp - LEGO1/omni/src/action/mxdsselectaction.cpp - LEGO1/omni/src/action/mxdsserialaction.cpp - LEGO1/omni/src/action/mxdssound.cpp - LEGO1/omni/src/action/mxdsstill.cpp - LEGO1/omni/src/action/mxdsstreamingaction.cpp - LEGO1/omni/src/audio/mxaudiomanager.cpp - LEGO1/omni/src/audio/mxaudiopresenter.cpp - LEGO1/omni/src/audio/mxloopingmidipresenter.cpp - LEGO1/omni/src/audio/mxmidipresenter.cpp - LEGO1/omni/src/audio/mxmusicmanager.cpp - LEGO1/omni/src/audio/mxmusicpresenter.cpp - LEGO1/omni/src/audio/mxsoundmanager.cpp - LEGO1/omni/src/audio/mxsoundpresenter.cpp - LEGO1/omni/src/audio/mxwavepresenter.cpp - LEGO1/omni/src/common/mxatomidcounter.cpp - LEGO1/omni/src/common/mxatomid.cpp - LEGO1/omni/src/common/mxcompositepresenter.cpp - LEGO1/omni/src/common/mxcore.cpp - LEGO1/omni/src/common/mxmediamanager.cpp - LEGO1/omni/src/common/mxmediapresenter.cpp - LEGO1/omni/src/common/mxobjectfactory.cpp - LEGO1/omni/src/common/mxpresenter.cpp - LEGO1/omni/src/common/mxstring.cpp - LEGO1/omni/src/common/mxticklemanager.cpp - LEGO1/omni/src/common/mxtimer.cpp - LEGO1/omni/src/common/mxutil.cpp - LEGO1/omni/src/common/mxvariable.cpp - LEGO1/omni/src/common/mxvariabletable.cpp - LEGO1/omni/src/entity/mxentity.cpp - LEGO1/omni/src/event/mxeventmanager.cpp - LEGO1/omni/src/event/mxeventpresenter.cpp - LEGO1/omni/src/main/mxomni.cpp - LEGO1/omni/src/main/mxomnicreateflags.cpp - LEGO1/omni/src/main/mxomnicreateparam.cpp - LEGO1/omni/src/notify/mxactionnotificationparam.cpp - LEGO1/omni/src/notify/mxnotificationmanager.cpp - LEGO1/omni/src/notify/mxnotificationparam.cpp - LEGO1/omni/src/notify/mxtype17notificationparam.cpp - LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp - LEGO1/omni/src/stream/mxdiskstreamprovider.cpp - LEGO1/omni/src/stream/mxdsbuffer.cpp - LEGO1/omni/src/stream/mxdschunk.cpp - LEGO1/omni/src/stream/mxdsfile.cpp - LEGO1/omni/src/stream/mxdssource.cpp - LEGO1/omni/src/stream/mxdssubscriber.cpp - LEGO1/omni/src/stream/mxioinfo.cpp - LEGO1/omni/src/stream/mxramstreamcontroller.cpp - LEGO1/omni/src/stream/mxramstreamprovider.cpp - LEGO1/omni/src/stream/mxstreamchunk.cpp - LEGO1/omni/src/stream/mxstreamcontroller.cpp - LEGO1/omni/src/stream/mxstreamer.cpp - LEGO1/omni/src/stream/mxstreamlist.cpp - LEGO1/omni/src/stream/mxstreamprovider.cpp - LEGO1/omni/src/system/mxautolocker.cpp - LEGO1/omni/src/system/mxcriticalsection.cpp - LEGO1/omni/src/system/mxscheduler.cpp - LEGO1/omni/src/system/mxsemaphore.cpp - LEGO1/omni/src/system/mxthread.cpp - LEGO1/omni/src/video/mxbitmap.cpp - LEGO1/omni/src/video/mxdisplaysurface.cpp - LEGO1/omni/src/video/mxflcpresenter.cpp - LEGO1/omni/src/video/mxloopingflcpresenter.cpp - LEGO1/omni/src/video/mxloopingsmkpresenter.cpp - LEGO1/omni/src/video/mxpalette.cpp - LEGO1/omni/src/video/mxregion.cpp - LEGO1/omni/src/video/mxregioncursor.cpp - LEGO1/omni/src/video/mxsmack.cpp - LEGO1/omni/src/video/mxsmkpresenter.cpp - LEGO1/omni/src/video/mxstillpresenter.cpp - LEGO1/omni/src/video/mxvideomanager.cpp - LEGO1/omni/src/video/mxvideoparam.cpp - LEGO1/omni/src/video/mxvideoparamflags.cpp - LEGO1/omni/src/video/mxvideopresenter.cpp - LEGO1/realtime/matrix.cpp - LEGO1/realtime/orientableroi.cpp - LEGO1/realtime/realtime.cpp - LEGO1/realtime/realtimeview.cpp - LEGO1/realtime/vector.cpp - LEGO1/tgl/d3drm/camera.cpp - LEGO1/tgl/d3drm/device.cpp - LEGO1/tgl/d3drm/group.cpp - LEGO1/tgl/d3drm/light.cpp - LEGO1/tgl/d3drm/mesh.cpp - LEGO1/tgl/d3drm/renderer.cpp - LEGO1/tgl/d3drm/texture.cpp - LEGO1/tgl/d3drm/unk.cpp - LEGO1/tgl/d3drm/view.cpp - LEGO1/viewmanager/viewlodlist.cpp - LEGO1/viewmanager/viewmanager.cpp - LEGO1/viewmanager/viewroi.cpp - LEGO1/flic.cpp ) +register_lego1_target(lego1) if (MINGW) target_compile_definitions(lego1 PRIVATE DIRECTINPUT_VERSION=0x0500) endif() -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/util") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/lego/legoomni/include") - -# Additional include directories -target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/3rdparty/vec") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/flic") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smacker") - -if (ISLE_USE_SMARTHEAP) - add_library(SmartHeap::SmartHeap STATIC IMPORTED) - set_target_properties(SmartHeap::SmartHeap PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SHLW32MT.LIB" - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/smartheap" - INTERFACE_COMPILE_OPTIONS "/FI${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SMRTHEAP.HPP") - - target_link_libraries(lego1 PRIVATE SmartHeap::SmartHeap) +if (MSVC) + target_sources(lego1 PRIVATE LEGO1/LegoOmni.def) +else() + target_sources(lego1 PRIVATE LEGO1/LegoOmni.mingw.def) endif() -# Use internal DirectX 5 if required -if (ISLE_USE_DX5) - target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/inc") - target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/lib") -endif() - -target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smacker") -target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/flic") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/util") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1/omni/include") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1/lego/legoomni/include") # Link libraries -target_link_libraries(lego1 PRIVATE ddraw dsound dinput dxguid winmm d3drm smack flic) +target_link_libraries(lego1 PRIVATE tglrl viewmanager realtime mxdirectx roi anim FLIC::FLIC Vec::Vec dinput dxguid misc 3dmanager omni) + +if (ISLE_USE_SMARTHEAP) + foreach(tgt IN LISTS lego1_targets) + target_link_libraries(${tgt} PRIVATE SmartHeap::SmartHeap) + endforeach() +endif() +foreach(tgt IN LISTS lego1_targets) + target_link_libraries(${tgt} PRIVATE $<$:DirectX5::DirectX5>) +endforeach() # Make sure filenames are ALL CAPS set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1) @@ -301,22 +430,12 @@ if (ISLE_BUILD_APP) add_executable(isle WIN32 ISLE/res/isle.rc ISLE/isleapp.cpp - ISLE/define.cpp ) target_compile_definitions(isle PRIVATE ISLE_APP) - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/util") - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1") - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include") - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources") - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/lego/legoomni/include") - # Use internal DirectX 5 if required - if (ISLE_USE_DX5) - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/inc") - target_link_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/lib") - endif() + target_link_libraries(isle PRIVATE $<$:DirectX5::DirectX5>) if (ISLE_USE_SMARTHEAP) target_link_libraries(isle PRIVATE SmartHeap::SmartHeap) @@ -330,26 +449,63 @@ if (ISLE_BUILD_APP) set_property(TARGET isle PROPERTY SUFFIX ".EXE") endif() +if (ISLE_BUILD_CONFIG) + add_executable(config WIN32 + LEGO1/mxdirectx/mxdirect3d.cpp + CONFIG/config.cpp + CONFIG/ConfigCommandLineInfo.cpp + CONFIG/AboutDlg.cpp + CONFIG/MainDlg.cpp + CONFIG/detectdx5.cpp + CONFIG/StdAfx.cpp + CONFIG/res/config.rc + ) + target_compile_definitions(config PRIVATE _AFXDLL MXDIRECTX_FOR_CONFIG) + target_include_directories(config PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/util" "${CMAKE_CURRENT_SOURCE_DIR}/LEGO1") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) + target_link_libraries(config PRIVATE DirectX5::DirectX5) + endif() + target_compile_definitions(config PRIVATE DIRECT3D_VERSION=0x500) + target_link_libraries(config PRIVATE ddraw dxguid) + set_property(TARGET config PROPERTY OUTPUT_NAME "CONFIG") + set_property(TARGET config PROPERTY SUFFIX ".EXE") + set_property(TARGET config PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>DLL) +endif() + if (MSVC) if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "15") - target_compile_definitions(lego1 PRIVATE _CRT_SECURE_NO_WARNINGS) - if (ISLE_BUILD_APP) + set_property(TARGET ${lego1_targets} APPEND PROPERTY COMPILE_DEFINITIONS "_CRT_SECURE_NO_WARNINGS") + if (TARGET isle) target_compile_definitions(isle PRIVATE "_CRT_SECURE_NO_WARNINGS") endif() + if (TARGET config) + target_compile_definitions(config PRIVATE "_CRT_SECURE_NO_WARNINGS") + endif() endif() # Visual Studio 2017 version 15.7 needs "/Zc:__cplusplus" for __cplusplus if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.14.26428") - target_compile_options(lego1 PRIVATE "-Zc:__cplusplus") - if (ISLE_BUILD_APP) + foreach(tgt IN LISTS lego1_targets) + target_compile_options(${tgt} PRIVATE "-Zc:__cplusplus") + endforeach() + if (TARGET isle) target_compile_options(isle PRIVATE "-Zc:__cplusplus") endif() + if (TARGET config) + target_compile_options(config PRIVATE "-Zc:__cplusplus") + endif() endif() endif() if (MSVC_FOR_DECOMP) - target_compile_definitions(lego1 PRIVATE "ENABLE_DECOMP_ASSERTS") - if (ISLE_BUILD_APP) - target_compile_definitions(isle PRIVATE "ENABLE_DECOMP_ASSERTS") + foreach(tgt IN LISTS lego1_targets) + target_compile_definitions(${tgt} PRIVATE "ENABLE_DECOMP_ASSERTS") + endforeach() + + if (TARGET isle) + target_compile_definitions(isle PRIVATE "ENABLE_DECOMP_ASSERTS") + endif() + if (TARGET config) + target_compile_definitions(config PRIVATE "ENABLE_DECOMP_ASSERTS") endif() endif() @@ -359,8 +515,11 @@ if (MSVC_FOR_DECOMP) # They ensure a recompilation that can be byte/instruction accurate to the original binaries. if (ISLE_BUILD_APP) target_compile_options(isle PRIVATE "/MT$<$:d>") + target_link_options(isle PRIVATE "/OPT:REF") endif() - target_compile_options(lego1 PRIVATE "/MT$<$:d>") + + # Equivalent to target_compile_options(... PRIVATE "/MT$<$:d>") + set_property(TARGET lego1 ${lego1_targets} PROPERTY MSVC_RUNTIME_LIBRARY MultiThreaded$<$:Debug>) set(CMAKE_CXX_FLAGS "/W3 /GX /D \"WIN32\" /D \"_WINDOWS\"") set(CMAKE_CXX_FLAGS_DEBUG "/Gm /Zi /Od /D \"_DEBUG\"") @@ -374,6 +533,8 @@ if (MSVC_FOR_DECOMP) set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/incremental:no /debug") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "/incremental:no") + set(CMAKE_STATIC_LINKER_FLAGS "/machine:I386") + set(CMAKE_SHARED_LINKER_FLAGS "/machine:I386") set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/incremental:yes /debug") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/incremental:no") @@ -382,12 +543,17 @@ if (MSVC_FOR_DECOMP) # Older MSVC versions don't support building in parallel. # Force non-parallel builds of isle and lego1 by putting them in a pool with 1 available job. - if(CMAKE_CXX_COMPILER_ID VERSION_LESS 12) - set_property(GLOBAL PROPERTY JOB_POOLS "msvc_lego=1;msvc_lego1=1") - set_property(TARGET isle PROPERTY JOB_POOL_COMPILE msvc_lego) - set_property(TARGET isle PROPERTY JOB_POOL_LINK msvc_lego) - set_property(TARGET lego1 PROPERTY JOB_POOL_COMPILE msvc_lego1) - set_property(TARGET lego1 PROPERTY JOB_POOL_LINK msvc_lego1) + if (CMAKE_CXX_COMPILER_ID VERSION_LESS 12) + foreach(tgt IN LISTS lego1_targets) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_${tgt}=1;msvc_lego1=1") + set_property(TARGET ${tgt} PROPERTY JOB_POOL_COMPILE msvc_${tgt}) + set_property(TARGET ${tgt} PROPERTY JOB_POOL_LINK msvc_${tgt}) + endforeach() + if (TARGET isle) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_isle=1") + set_property(TARGET isle PROPERTY JOB_POOL_COMPILE msvc_isle) + set_property(TARGET isle PROPERTY JOB_POOL_LINK msvc_isle) + endif() endif() endif() diff --git a/CONFIG/AboutDlg.cpp b/CONFIG/AboutDlg.cpp new file mode 100644 index 00000000..9585d1c1 --- /dev/null +++ b/CONFIG/AboutDlg.cpp @@ -0,0 +1,19 @@ +#include "AboutDlg.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(CDialog, 0x60) +DECOMP_SIZE_ASSERT(CAboutDialog, 0x60) + +// FUNCTION: CONFIG 0x00403c20 +CAboutDialog::CAboutDialog() : CDialog(IDD) +{ +} + +// FUNCTION: CONFIG 0x00403d20 +void CAboutDialog::DoDataExchange(CDataExchange* pDX) +{ +} + +BEGIN_MESSAGE_MAP(CAboutDialog, CDialog) +END_MESSAGE_MAP() diff --git a/CONFIG/AboutDlg.h b/CONFIG/AboutDlg.h new file mode 100644 index 00000000..d959f82e --- /dev/null +++ b/CONFIG/AboutDlg.h @@ -0,0 +1,36 @@ +#if !defined(AFX_ABOUTDLG_H) +#define AFX_ABOUTDLG_H + +#include "StdAfx.h" +#include "compat.h" +#include "res/resource.h" + +// VTABLE: CONFIG 0x00406308 +// SIZE 0x60 +class CAboutDialog : public CDialog { +public: + CAboutDialog(); + enum { + IDD = IDD_ABOUT + }; + +protected: + void DoDataExchange(CDataExchange* pDX) override; + +protected: + DECLARE_MESSAGE_MAP() +}; + +// SYNTHETIC: CONFIG 0x00403cb0 +// CAboutDialog::`scalar deleting destructor' + +// FUNCTION: CONFIG 0x00403d40 +// CAboutDialog::GetMessageMap + +// GLOBAL: CONFIG 0x00406100 +// CAboutDialog::messageMap + +// GLOBAL: CONFIG 0x00406108 +// CAboutDialog::_messageEntries + +#endif // !defined(AFX_ABOUTDLG_H) diff --git a/CONFIG/ConfigCommandLineInfo.cpp b/CONFIG/ConfigCommandLineInfo.cpp new file mode 100644 index 00000000..0e376e6d --- /dev/null +++ b/CONFIG/ConfigCommandLineInfo.cpp @@ -0,0 +1,22 @@ +#include "ConfigCommandLineInfo.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(CCommandLineInfo, 0x24) +DECOMP_SIZE_ASSERT(CConfigCommandLineInfo, 0x24) + +// FUNCTION: CONFIG 0x00403b10 +CConfigCommandLineInfo::CConfigCommandLineInfo() +{ + currentConfigApp->m_run_config_dialog = FALSE; +} + +// FUNCTION: CONFIG 0x00403bf0 +void CConfigCommandLineInfo::ParseParam(LPCSTR pszParam, BOOL bFlag, BOOL bLast) +{ + if (bFlag) { + if (lstrcmpiA(pszParam, "config") == 0) { + currentConfigApp->m_run_config_dialog = TRUE; + } + } +} diff --git a/CONFIG/ConfigCommandLineInfo.h b/CONFIG/ConfigCommandLineInfo.h new file mode 100644 index 00000000..82510df1 --- /dev/null +++ b/CONFIG/ConfigCommandLineInfo.h @@ -0,0 +1,21 @@ +#if !defined(AFX_CONFIGCOMMANDLINEINFO_H) +#define AFX_CONFIGCOMMANDLINEINFO_H + +#include "StdAfx.h" +#include "compat.h" +#include "config.h" +#include "decomp.h" + +// VTABLE: CONFIG 0x004060e8 +// SIZE 0x24 +class CConfigCommandLineInfo : public CCommandLineInfo { +public: + CConfigCommandLineInfo(); + + void ParseParam(LPCSTR pszParam, BOOL bFlag, BOOL bLast) override; +}; + +// SYNTHETIC: CONFIG 0x00403b80 +// CConfigCommandLineInfo::`scalar deleting destructor' + +#endif // !defined(AFX_CONFIGCOMMANDLINEINFO_H) diff --git a/CONFIG/MainDlg.cpp b/CONFIG/MainDlg.cpp new file mode 100644 index 00000000..84083892 --- /dev/null +++ b/CONFIG/MainDlg.cpp @@ -0,0 +1,345 @@ +#include "MainDlg.h" + +#include "AboutDlg.h" +#include "config.h" +#include "res/resource.h" + +#include + +DECOMP_SIZE_ASSERT(CDialog, 0x60) +DECOMP_SIZE_ASSERT(CMainDialog, 0x70) + +// FUNCTION: CONFIG 0x00403d50 +CMainDialog::CMainDialog(CWnd* pParent) : CDialog(IDD, pParent) +{ + afxCurrentWinApp; + m_icon = LoadIconA(AfxFindResourceHandle(MAKEINTRESOURCE(IDI_CONFIG), RT_GROUP_ICON), MAKEINTRESOURCE(IDI_CONFIG)); +} + +// FUNCTION: CONFIG 0x00403e50 +void CMainDialog::DoDataExchange(CDataExchange* pDX) +{ +} + +BEGIN_MESSAGE_MAP(CMainDialog, CDialog) +ON_WM_SYSCOMMAND() +ON_WM_PAINT() +ON_WM_QUERYDRAGICON() +ON_COMMAND(IDC_CHK_FLIP_VIDEO_MEM_PAGES, OnCheckboxFlipVideoMemPages) +ON_LBN_SELCHANGE(IDC_LIST_3DDEVICES, OnList3DevicesSelectionChanged) +ON_COMMAND(IDC_RAD_PALETTE_16BIT, OnRadiobuttonPalette16bit) +ON_COMMAND(IDC_RAD_PALETTE_256, OnRadiobuttonPalette256) +ON_COMMAND(IDC_CHK_3D_VIDEO_MEMORY, OnCheckbox3DVideoMemory) +ON_WM_DESTROY() // FIXME: CONFIG.EXE calls Default +ON_COMMAND(IDABORT, OnButtonCancel) +ON_COMMAND(IDC_CHK_3DSOUND, OnCheckbox3DSound) +ON_COMMAND(IDC_RAD_MODEL_QUALITY_LOW, OnRadiobuttonModelLowQuality) +ON_COMMAND(IDC_RAD_MODEL_QUALITY_HIGH, OnRadiobuttonModelHighQuality) +ON_COMMAND(IDC_RAD_TEXTURE_QUALITY_LOW, OnRadiobuttonTextureLowQuality) +ON_COMMAND(IDC_RAD_TEXTURE_QUALITY_HIGH, OnRadiobuttonTextureHighQuality) +ON_COMMAND(IDC_CHK_JOYSTICK, OnCheckboxJoystick) +ON_COMMAND(IDC_BTN_ADVANCED, OnButtonAdvanced) +ON_COMMAND(IDC_CHK_DRAW_CURSOR, OnCheckboxDrawCursor) +ON_COMMAND(IDC_CHK_MUSIC, OnCheckboxMusic) +END_MESSAGE_MAP() + +// FUNCTION: CONFIG 0x00403e80 +BOOL CMainDialog::OnInitDialog() +{ + CDialog::OnInitDialog(); + SwitchToAdvanced(FALSE); + CMenu* system_menu = CMenu::FromHandle(::GetSystemMenu(m_hWnd, FALSE)); + CString about_text; + about_text.LoadString(IDS_ABOUT); + if (system_menu) { + AppendMenuA(system_menu->m_hMenu, MF_SEPARATOR, 0, NULL); + AppendMenuA(system_menu->m_hMenu, MF_STRING, 16, (LPCTSTR) about_text); + } + SendMessage(WM_SETICON, ICON_BIG, (LPARAM) m_icon); + SendMessage(WM_SETICON, ICON_SMALL, (LPARAM) m_icon); + MxDeviceEnumerate* enumerator = currentConfigApp->m_device_enumerator; + enumerator->FUN_1009d210(); + m_modified = currentConfigApp->ReadRegisterSettings(); + CWnd* list_3d_devices = GetDlgItem(IDC_LIST_3DDEVICES); + int driver_i = 0; + int device_i = 0; + int selected = 0; + char device_name[256]; + const list& driver_list = enumerator->GetDriverList(); + for (list::const_iterator it_driver = driver_list.begin(); it_driver != driver_list.end(); it_driver++) { + const MxDriver& driver = *it_driver; + for (list::const_iterator it_device = driver.m_devices.begin(); + it_device != driver.m_devices.end(); + it_device++) { + const Direct3DDeviceInfo& device = *it_device; + if (&device == currentConfigApp->m_device) { + selected = device_i; + } + device_i += 1; + sprintf( + device_name, + driver_i == 0 ? "%s ( Primary Device )" : "%s ( Secondary Device )", + device.m_deviceName + ); + ::SendMessage(list_3d_devices->m_hWnd, LB_ADDSTRING, 0, (LPARAM) device_name); + } + driver_i += 1; + } + ::SendMessage(list_3d_devices->m_hWnd, LB_SETCURSEL, selected, 0); + UpdateInterface(); + return TRUE; +} + +// FUNCTION: CONFIG 0x00404080 +void CMainDialog::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xfff0) == 0x10) { + CAboutDialog about_dialog; + about_dialog.DoModal(); + } + else { + Default(); + } +} + +// FUNCTION: CONFIG 0x00404150 +void CMainDialog::OnPaint() +{ + if (IsIconic()) { + CPaintDC painter(this); + ::SendMessage(m_hWnd, WM_ICONERASEBKGND, (WPARAM) painter.m_hDC, 0); + RECT dim; + GetClientRect(&dim); + DrawIcon( + painter.m_hDC, + (dim.right - dim.left - GetSystemMetrics(SM_CXICON) + 1) / 2, + (dim.bottom - dim.top - GetSystemMetrics(SM_CYICON) + 1) / 2, + m_icon + ); + } + else { + Default(); + } +} + +// FUNCTION: CONFIG 0x00404230 +HCURSOR CMainDialog::OnQueryDragIcon() +{ + return m_icon; +} + +// FUNCTION: CONFIG 0x00404240 +void CMainDialog::OnList3DevicesSelectionChanged() +{ + MxDeviceEnumerate* device_enumerator = currentConfigApp->m_device_enumerator; + int selected = ::SendMessage(GetDlgItem(IDC_LIST_3DDEVICES)->m_hWnd, LB_GETCURSEL, 0, 0); + device_enumerator->GetDevice(selected, currentConfigApp->m_driver, currentConfigApp->m_device); + if (currentConfigApp->GetHardwareDeviceColorModel()) { + GetDlgItem(IDC_CHK_DRAW_CURSOR)->EnableWindow(TRUE); + } + else { + currentConfigApp->m_3d_video_ram = FALSE; + currentConfigApp->m_flip_surfaces = FALSE; + CheckDlgButton(IDC_CHK_3D_VIDEO_MEMORY, currentConfigApp->m_3d_video_ram); + CheckDlgButton(IDC_CHK_FLIP_VIDEO_MEM_PAGES, currentConfigApp->m_flip_surfaces); + } + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404320 +void CMainDialog::OnCancel() +{ + CDialog::OnCancel(); +} + +// FUNCTION: CONFIG 0x00404330 +void CMainDialog::OnDestroy() +{ + CDialog::Default(); +} + +// FUNCTION: CONFIG 0x00404340 +void CMainDialog::OnButtonCancel() +{ + if (m_modified) { + currentConfigApp->WriteRegisterSettings(); + } + OnCancel(); +} + +// FUNCTION: CONFIG 0x00404360 +void CMainDialog::UpdateInterface() +{ + currentConfigApp->ValidateSettings(); + GetDlgItem(IDC_CHK_3D_VIDEO_MEMORY) + ->EnableWindow(!currentConfigApp->m_flip_surfaces && !currentConfigApp->GetHardwareDeviceColorModel()); + CheckDlgButton(IDC_CHK_FLIP_VIDEO_MEM_PAGES, currentConfigApp->m_flip_surfaces); + CheckDlgButton(IDC_CHK_3D_VIDEO_MEMORY, currentConfigApp->m_3d_video_ram); + BOOL full_screen = currentConfigApp->m_full_screen; + currentConfigApp->FUN_00403810(); + if (currentConfigApp->GetHardwareDeviceColorModel()) { + CheckDlgButton(IDC_CHK_DRAW_CURSOR, TRUE); + } + else { + CheckDlgButton(IDC_CHK_DRAW_CURSOR, FALSE); + currentConfigApp->m_draw_cursor = FALSE; + GetDlgItem(IDC_CHK_DRAW_CURSOR)->EnableWindow(FALSE); + } + if (full_screen) { + CheckRadioButton( + IDC_RAD_PALETTE_256, + IDC_RAD_PALETTE_16BIT, + currentConfigApp->m_display_bit_depth == 8 ? IDC_RAD_PALETTE_256 : IDC_RAD_PALETTE_16BIT + ); + } + else { + CheckDlgButton(IDC_RAD_PALETTE_256, 0); + CheckDlgButton(IDC_RAD_PALETTE_16BIT, 0); + currentConfigApp->m_display_bit_depth = 0; + } + GetDlgItem(IDC_RAD_PALETTE_256)->EnableWindow(full_screen && currentConfigApp->FUN_004037a0()); + GetDlgItem(IDC_RAD_PALETTE_16BIT)->EnableWindow(full_screen && currentConfigApp->FUN_004037e0()); + CheckDlgButton(IDC_CHK_3DSOUND, currentConfigApp->m_3d_sound); + CheckDlgButton(IDC_CHK_DRAW_CURSOR, currentConfigApp->m_draw_cursor); + switch (currentConfigApp->m_model_quality) { + case 1: + CheckRadioButton(IDC_RAD_MODEL_QUALITY_LOW, IDC_RAD_MODEL_QUALITY_HIGH, IDC_RAD_MODEL_QUALITY_LOW); + break; + case 2: + CheckRadioButton(IDC_RAD_MODEL_QUALITY_LOW, IDC_RAD_MODEL_QUALITY_HIGH, IDC_RAD_MODEL_QUALITY_HIGH); + break; + } + CheckRadioButton( + IDC_RAD_TEXTURE_QUALITY_LOW, + IDC_RAD_TEXTURE_QUALITY_HIGH, + currentConfigApp->m_texture_quality == 0 ? IDC_RAD_TEXTURE_QUALITY_LOW : IDC_RAD_TEXTURE_QUALITY_HIGH + ); + CheckDlgButton(IDC_CHK_JOYSTICK, currentConfigApp->m_use_joystick); + CheckDlgButton(IDC_CHK_MUSIC, currentConfigApp->m_music); +} + +// FUNCTION: CONFIG 0x004045e0 +void CMainDialog::OnCheckbox3DSound() +{ + currentConfigApp->m_3d_sound = IsDlgButtonChecked(IDC_CHK_3DSOUND); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404610 +void CMainDialog::OnCheckbox3DVideoMemory() +{ + currentConfigApp->m_3d_video_ram = IsDlgButtonChecked(IDC_CHK_3D_VIDEO_MEMORY); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404640 +void CMainDialog::OnRadiobuttonPalette16bit() +{ + currentConfigApp->m_display_bit_depth = 16; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404670 +void CMainDialog::OnRadiobuttonPalette256() +{ + currentConfigApp->m_display_bit_depth = 8; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004046a0 +void CMainDialog::OnCheckboxFlipVideoMemPages() +{ + currentConfigApp->m_flip_surfaces = IsDlgButtonChecked(IDC_CHK_FLIP_VIDEO_MEM_PAGES); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004046d0 +void CMainDialog::OnRadiobuttonModelLowQuality() +{ + currentConfigApp->m_model_quality = 1; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404700 +void CMainDialog::OnRadiobuttonModelHighQuality() +{ + currentConfigApp->m_model_quality = 2; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404730 +void CMainDialog::OnRadiobuttonTextureLowQuality() +{ + currentConfigApp->m_texture_quality = 0; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404760 +void CMainDialog::OnRadiobuttonTextureHighQuality() +{ + currentConfigApp->m_texture_quality = 1; + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x00404790 +void CMainDialog::OnCheckboxJoystick() +{ + currentConfigApp->m_use_joystick = IsDlgButtonChecked(IDC_CHK_JOYSTICK); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004047c0 +void CMainDialog::OnButtonAdvanced() +{ + SwitchToAdvanced(!m_advanced); +} + +// FUNCTION: CONFIG 0x004047d0 +void CMainDialog::SwitchToAdvanced(BOOL p_advanced) +{ + RECT dialog_rect; + RECT grp_advanced_rect; + ::GetWindowRect(m_hWnd, &dialog_rect); + ::GetWindowRect(GetDlgItem(IDC_GRP_ADVANCED)->m_hWnd, &grp_advanced_rect); + CWnd* button_advanced = GetDlgItem(IDC_BTN_ADVANCED); + m_advanced = p_advanced; + int height; + if (p_advanced) { + height = grp_advanced_rect.bottom - dialog_rect.top + 10; + GetDlgItem(IDC_BMP_SHARK)->EnableWindow(TRUE); + button_advanced->SetWindowText("Basic"); + } + else { + height = grp_advanced_rect.top - dialog_rect.top; + GetDlgItem(IDC_BMP_SHARK)->EnableWindow(FALSE); + button_advanced->SetWindowText("Advanced"); + } + SetWindowPos(&wndTop, 0, 0, dialog_rect.right - dialog_rect.left, height, SWP_NOMOVE); +} + +// FUNCTION: CONFIG 0x00404890 +void CMainDialog::OnCheckboxDrawCursor() +{ + currentConfigApp->m_draw_cursor = IsDlgButtonChecked(IDC_CHK_DRAW_CURSOR); + m_modified = TRUE; + UpdateInterface(); +} + +// FUNCTION: CONFIG 0x004048c0 +void CMainDialog::OnCheckboxMusic() +{ + currentConfigApp->m_music = IsDlgButtonChecked(IDC_CHK_MUSIC); + m_modified = TRUE; + UpdateInterface(); +} diff --git a/CONFIG/MainDlg.h b/CONFIG/MainDlg.h new file mode 100644 index 00000000..e5a696c0 --- /dev/null +++ b/CONFIG/MainDlg.h @@ -0,0 +1,67 @@ +#if !defined(AFX_MAINDLG_H) +#define AFX_MAINDLG_H + +#include "StdAfx.h" +#include "compat.h" +#include "decomp.h" +#include "res/resource.h" + +// VTABLE: CONFIG 0x004063e0 +// SIZE 0x70 +class CMainDialog : public CDialog { +public: + CMainDialog(CWnd* pParent); + enum { + IDD = IDD_MAIN + }; + +protected: + void DoDataExchange(CDataExchange* pDX) override; + void UpdateInterface(); + void SwitchToAdvanced(BOOL p_advanced); + + undefined m_unk0x60[4]; // 0x60 + HCURSOR m_icon; // 0x64 + BOOL m_modified; // 0x68 + BOOL m_advanced; // 0x6c + // Implementation + +protected: + BOOL OnInitDialog() override; + void OnSysCommand(UINT nID, LPARAM lParam); + void OnPaint(); + HCURSOR OnQueryDragIcon(); + void OnList3DevicesSelectionChanged(); + void OnCancel(); + void OnDestroy(); + void OnButtonCancel(); + void OnCheckbox3DSound(); + void OnCheckbox3DVideoMemory(); + void OnRadiobuttonPalette16bit(); + void OnRadiobuttonPalette256(); + void OnCheckboxFlipVideoMemPages(); + void OnRadiobuttonModelLowQuality(); + void OnRadiobuttonModelHighQuality(); + void OnRadiobuttonTextureLowQuality(); + void OnRadiobuttonTextureHighQuality(); + void OnCheckboxJoystick(); + void OnButtonAdvanced(); + void OnCheckboxDrawCursor(); + void OnCheckboxMusic(); + + DECLARE_MESSAGE_MAP() +}; + +// SYNTHETIC: CONFIG 0x00403de0 +// CMainDialog::`scalar deleting destructor' + +// FUNCTION: CONFIG 0x00403e70 +// CMainDialog::GetMessageMap + +// GLOBAL: CONFIG 0x00406120 +// CMainDialog::messageMap + +// GLOBAL: CONFIG 0x00406128 +// CMainDialog::_messageEntries + +#endif // !defined(AFX_MAINDLG_H) diff --git a/CONFIG/StdAfx.cpp b/CONFIG/StdAfx.cpp new file mode 100644 index 00000000..3e0b3d04 --- /dev/null +++ b/CONFIG/StdAfx.cpp @@ -0,0 +1,5 @@ +// stdafx.cpp : source file that includes just the standard includes +// simple.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/CONFIG/StdAfx.h b/CONFIG/StdAfx.h new file mode 100644 index 00000000..39243b3b --- /dev/null +++ b/CONFIG/StdAfx.h @@ -0,0 +1,31 @@ +#if !defined(AFX_STDAFX_H) +#define AFX_STDAFX_H + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC extensions +#include // MFC core and standard components +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#if 0 + +// FUNCTION: CONFIG 0x402ca0 +// CObject::Serialize + +// FUNCTION: CONFIG 0x402cb0 +// CObject::AssertValid + +// FUNCTION: CONFIG 0x402cc0 +// CObject::Dump + +// FUNCTION: CONFIG 0x00403c90 +// CWnd::BeginModalState + +// FUNCTION: CONFIG 0x00403ca0 +// CWnd::EndModalState + +#endif + +#endif // !defined(AFX_STDAFX_H) diff --git a/CONFIG/config.cpp b/CONFIG/config.cpp new file mode 100644 index 00000000..78c6b6c2 --- /dev/null +++ b/CONFIG/config.cpp @@ -0,0 +1,434 @@ +#include "config.h" + +#include "ConfigCommandLineInfo.h" +#include "MainDlg.h" +#include "detectdx5.h" + +#include // _chdir +#include +#include // _spawnl + +DECOMP_SIZE_ASSERT(CWinApp, 0xc4) +DECOMP_SIZE_ASSERT(CConfigApp, 0x108) + +DECOMP_STATIC_ASSERT(offsetof(CConfigApp, m_display_bit_depth) == 0xd0) + +BEGIN_MESSAGE_MAP(CConfigApp, CWinApp) +ON_COMMAND(ID_HELP, OnHelp) +END_MESSAGE_MAP() + +// FUNCTION: CONFIG 0x00402c40 +CConfigApp::CConfigApp() +{ +} + +#define MiB (1024 * 1024) + +// FUNCTION: CONFIG 0x00402dc0 +BOOL CConfigApp::InitInstance() +{ + if (!IsLegoNotRunning()) { + return FALSE; + } + if (!DetectDirectX5()) { + AfxMessageBox( + "\"LEGO\xae Island\" is not detecting DirectX 5 or later. Please quit all other applications and try " + "again." + ); + return FALSE; + } +#ifdef _AFXDLL + Enable3dControls(); +#else + Enable3dControlsStatic(); +#endif + CConfigCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + if (_stricmp(afxCurrentAppName, "config") == 0) { + m_run_config_dialog = TRUE; + } + m_device_enumerator = new MxDeviceEnumerate; + if (m_device_enumerator->DoEnumerate()) { + return FALSE; + } + m_driver = NULL; + m_device = NULL; + m_full_screen = TRUE; + m_wide_view_angle = TRUE; + m_use_joystick = FALSE; + m_music = TRUE; + m_flip_surfaces = FALSE; + m_3d_video_ram = FALSE; + m_joystick_index = -1; + m_display_bit_depth = 16; + MEMORYSTATUS memory_status; + memory_status.dwLength = sizeof(memory_status); + GlobalMemoryStatus(&memory_status); + if (memory_status.dwTotalPhys < 12 * MiB) { + m_3d_sound = FALSE; + m_model_quality = 0; + m_texture_quality = 1; + } + else if (memory_status.dwTotalPhys < 20 * MiB) { + m_3d_sound = FALSE; + m_model_quality = 1; + m_texture_quality = 1; + } + else { + m_model_quality = 2; + m_3d_sound = TRUE; + m_texture_quality = 1; + } + if (!m_run_config_dialog) { + ReadRegisterSettings(); + ValidateSettings(); + WriteRegisterSettings(); + delete m_device_enumerator; + m_device_enumerator = NULL; + m_driver = NULL; + m_device = NULL; + char password[256]; + ReadReg("password", password, sizeof(password)); + const char* exe = _stricmp("ogel", password) == 0 ? "isled.exe" : "isle.exe"; + char diskpath[1024]; + if (ReadReg("diskpath", diskpath, sizeof(diskpath))) { + _chdir(diskpath); + } + _spawnl(_P_NOWAIT, exe, exe, "/diskstream", "/script", "\\lego\\scripts\\isle\\isle.si", NULL); + return FALSE; + } + CMainDialog main_dialog(NULL); + main_dialog.DoModal(); + return FALSE; +} + +// FUNCTION: CONFIG 0x00403100 +BOOL CConfigApp::IsLegoNotRunning() +{ + HWND hWnd = FindWindowA("Lego Island MainNoM App", "LEGO\xae"); + if (_stricmp(afxCurrentAppName, "config") == 0 || !hWnd) { + return TRUE; + } + if (SetForegroundWindow(hWnd)) { + ShowWindow(hWnd, SW_RESTORE); + } + return FALSE; +} + +// FUNCTION: CONFIG 0x004031b0 +BOOL CConfigApp::WriteReg(const char* p_key, const char* p_value) const +{ + HKEY hKey; + DWORD pos; + + if (RegCreateKeyExA( + HKEY_LOCAL_MACHINE, + "SOFTWARE\\Mindscape\\LEGO Island", + 0, + "string", + 0, + KEY_READ | KEY_WRITE, + NULL, + &hKey, + &pos + ) == ERROR_SUCCESS) { + if (RegSetValueExA(hKey, p_key, 0, REG_SZ, (LPBYTE) p_value, strlen(p_value)) == ERROR_SUCCESS) { + if (RegCloseKey(hKey) == ERROR_SUCCESS) { + return TRUE; + } + } + else { + RegCloseKey(hKey); + } + } + return FALSE; +} + +// FUNCTION: CONFIG 0x00403240 +BOOL CConfigApp::ReadReg(LPCSTR p_key, LPCSTR p_value, DWORD p_size) const +{ + HKEY hKey; + DWORD valueType; + + BOOL out = FALSE; + DWORD size = p_size; + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Mindscape\\LEGO Island", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + if (RegQueryValueExA(hKey, p_key, NULL, &valueType, (LPBYTE) p_value, &size) == ERROR_SUCCESS) { + if (RegCloseKey(hKey) == ERROR_SUCCESS) { + out = TRUE; + } + } + } + return out; +} + +// FUNCTION: CONFIG 0x004032b0 +BOOL CConfigApp::ReadRegBool(LPCSTR p_key, BOOL* p_bool) const +{ + char buffer[256]; + + BOOL read = ReadReg(p_key, buffer, sizeof(buffer)); + if (read) { + if (strcmp("YES", buffer) == 0) { + *p_bool = TRUE; + return read; + } + + if (strcmp("NO", buffer) == 0) { + *p_bool = FALSE; + return read; + } + + read = FALSE; + } + return read; +} + +// FUNCTION: CONFIG 0x00403380 +BOOL CConfigApp::ReadRegInt(LPCSTR p_key, int* p_value) const +{ + char buffer[256]; + + BOOL read = ReadReg(p_key, buffer, sizeof(buffer)); + if (read) { + *p_value = atoi(buffer); + } + + return read; +} + +// FUNCTION: CONFIG 0x004033d0 +BOOL CConfigApp::FUN_004033d0() const +{ + /* + * BUG: should be: + * return !GetHardwareDeviceColorModel() && (m_device->m_HELDesc.dcmColorModel & D3DCOLOR_RGB); + */ + return !GetHardwareDeviceColorModel() && m_device->m_HELDesc.dcmColorModel == D3DCOLOR_RGB; +} + +// FUNCTION: CONFIG 0x00403400 +D3DCOLORMODEL CConfigApp::GetHardwareDeviceColorModel() const +{ + return m_device->m_HWDesc.dcmColorModel; +} + +// FUNCTION: CONFIG 0x00403410 +BOOL CConfigApp::IsPrimaryDriver() const +{ + return m_driver == &m_device_enumerator->GetDriverList().front(); +} + +// FUNCTION: CONFIG 0x00403430 +BOOL CConfigApp::ReadRegisterSettings() +{ + char buffer[256]; + BOOL is_modified = FALSE; + int tmp = -1; + + if (ReadReg("3D Device ID", buffer, sizeof(buffer))) { + tmp = m_device_enumerator->ParseDeviceName(buffer); + if (tmp >= 0) { + tmp = m_device_enumerator->GetDevice(tmp, m_driver, m_device); + } + } + if (tmp != 0) { + is_modified = TRUE; + m_device_enumerator->FUN_1009d210(); + tmp = m_device_enumerator->FUN_1009d0d0(); + m_device_enumerator->GetDevice(tmp, m_driver, m_device); + } + if (!ReadRegInt("Display Bit Depth", &m_display_bit_depth)) { + is_modified = TRUE; + } + if (!ReadRegBool("Flip Surfaces", &m_flip_surfaces)) { + is_modified = TRUE; + } + if (!ReadRegBool("Full Screen", &m_full_screen)) { + is_modified = TRUE; + } + if (!ReadRegBool("Back Buffers in Video RAM", &m_3d_video_ram)) { + is_modified = TRUE; + } + if (!ReadRegBool("Wide View Angle", &m_wide_view_angle)) { + is_modified = TRUE; + } + if (!ReadRegBool("3DSound", &m_3d_sound)) { + is_modified = TRUE; + } + if (!ReadRegBool("Draw Cursor", &m_draw_cursor)) { + is_modified = TRUE; + } + if (!ReadRegInt("Island Quality", &m_model_quality)) { + is_modified = TRUE; + } + if (!ReadRegInt("Island Texture", &m_texture_quality)) { + is_modified = TRUE; + } + if (!ReadRegBool("UseJoystick", &m_use_joystick)) { + is_modified = TRUE; + } + if (!ReadRegBool("Music", &m_music)) { + is_modified = TRUE; + } + if (!ReadRegInt("JoystickIndex", &m_joystick_index)) { + is_modified = TRUE; + } + return is_modified; +} + +// FUNCTION: CONFIG 0x00403630 +BOOL CConfigApp::ValidateSettings() +{ + BOOL is_modified = FALSE; + + if (!IsPrimaryDriver() && !m_full_screen) { + m_full_screen = TRUE; + is_modified = TRUE; + } + if (FUN_004033d0()) { + if (m_3d_video_ram) { + m_3d_video_ram = FALSE; + is_modified = TRUE; + } + if (m_flip_surfaces) { + m_flip_surfaces = FALSE; + is_modified = TRUE; + } + if (m_display_bit_depth != 16) { + m_display_bit_depth = 16; + is_modified = TRUE; + } + } + if (!GetHardwareDeviceColorModel()) { + m_draw_cursor = FALSE; + is_modified = TRUE; + } + else { + if (!m_3d_video_ram) { + m_3d_video_ram = TRUE; + is_modified = TRUE; + } + if (m_full_screen && !m_flip_surfaces) { + m_flip_surfaces = TRUE; + is_modified = TRUE; + } + } + if (m_flip_surfaces) { + if (!m_3d_video_ram) { + m_3d_video_ram = TRUE; + is_modified = TRUE; + } + if (!m_full_screen) { + m_full_screen = TRUE; + is_modified = TRUE; + } + } + if ((m_display_bit_depth != 8 && m_display_bit_depth != 16) && (m_display_bit_depth != 0 || m_full_screen)) { + m_display_bit_depth = 8; + is_modified = TRUE; + } + if (m_model_quality < 0 || m_model_quality > 2) { + m_model_quality = 1; + is_modified = TRUE; + } + if (m_texture_quality < 0 || m_texture_quality > 1) { + m_texture_quality = 0; + is_modified = TRUE; + } + return is_modified; +} + +// FUNCTION: CONFIG 0x004037a0 +DWORD CConfigApp::FUN_004037a0() const +{ + if (FUN_004033d0()) { + return 0; + } + if (GetHardwareDeviceColorModel()) { + return 0; + } + return m_device->m_HELDesc.dwDeviceRenderBitDepth & 0x800; +} + +// FUNCTION: CONFIG 0x004037e0 +DWORD CConfigApp::FUN_004037e0() const +{ + if (GetHardwareDeviceColorModel()) { + return m_device->m_HWDesc.dwDeviceRenderBitDepth & 0x400; + } + else { + return m_device->m_HELDesc.dwDeviceRenderBitDepth & 0x400; + } +} + +// FUNCTION: CONFIG 0x00403810 +BOOL CConfigApp::FUN_00403810() +{ + if (m_display_bit_depth == 8) { + if (FUN_004037a0()) { + return FALSE; + } + } + if (m_display_bit_depth == 16) { + if (FUN_004037e0()) { + return FALSE; + } + } + if (FUN_004037a0()) { + m_display_bit_depth = 8; + return TRUE; + } + if (FUN_004037e0()) { + m_display_bit_depth = 16; + return TRUE; + } + m_display_bit_depth = 8; + return TRUE; +} + +// FUNCTION: CONFIG 00403890 +void CConfigApp::WriteRegisterSettings() const + +{ + char buffer[128]; + +#define WriteRegBool(NAME, VALUE) WriteReg(NAME, VALUE ? "YES" : "NO") +#define WriteRegInt(NAME, VALUE) \ + do { \ + sprintf(buffer, "%d", VALUE); \ + WriteReg(NAME, buffer); \ + } while (0) + + m_device_enumerator->FormatDeviceName(buffer, m_driver, m_device); + WriteReg("3D Device ID", buffer); + WriteReg("3D Device Name", m_device->m_deviceName); + WriteRegInt("Display Bit Depth", m_display_bit_depth); + WriteRegBool("Flip Surfaces", m_flip_surfaces); + WriteRegBool("Full Screen", m_full_screen); + WriteRegBool("Back Buffers in Video RAM", m_3d_video_ram); + WriteRegBool("Wide View Angle", m_wide_view_angle); + WriteRegBool("3DSound", m_3d_sound); + WriteRegBool("Draw Cursor", m_draw_cursor); + WriteRegInt("Island Quality", m_model_quality); + WriteRegInt("Island Texture", m_texture_quality); + WriteRegBool("UseJoystick", m_use_joystick); + WriteRegBool("Music", m_music); + WriteRegInt("JoystickIndex", m_joystick_index); + +#undef WriteRegBool +#undef WriteRegInt +} + +// FUNCTION: CONFIG 0x00403a90 +int CConfigApp::ExitInstance() +{ + if (m_device_enumerator) { + delete m_device_enumerator; + m_device_enumerator = NULL; + } + return CWinApp::ExitInstance(); +} + +// GLOBAL: CONFIG 0x00408e50 +CConfigApp g_theApp; diff --git a/CONFIG/config.h b/CONFIG/config.h new file mode 100644 index 00000000..9c633ac4 --- /dev/null +++ b/CONFIG/config.h @@ -0,0 +1,88 @@ +#if !defined(AFX_CONFIG_H) +#define AFX_CONFIG_H + +#include "StdAfx.h" +#include "compat.h" +#include "decomp.h" + +#include + +class MxDeviceEnumerate; +struct Direct3DDeviceInfo; +struct MxDriver; + +#define currentConfigApp ((CConfigApp*) afxCurrentWinApp) + +// VTABLE: CONFIG 0x00406040 +// SIZE 0x108 +class CConfigApp : public CWinApp { +public: + CConfigApp(); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CConfigApp) + +public: + BOOL InitInstance() override; + int ExitInstance() override; + //}}AFX_VIRTUAL + + // Implementation + + BOOL WriteReg(const char* p_key, const char* p_value) const; + BOOL ReadReg(LPCSTR p_key, LPCSTR p_value, DWORD p_size) const; + BOOL ReadRegBool(LPCSTR p_key, BOOL* p_bool) const; + BOOL ReadRegInt(LPCSTR p_key, int* p_value) const; + BOOL FUN_004033d0() const; + D3DCOLORMODEL GetHardwareDeviceColorModel() const; + BOOL IsPrimaryDriver() const; + BOOL ReadRegisterSettings(); + BOOL ValidateSettings(); + DWORD FUN_004037a0() const; + DWORD FUN_004037e0() const; + BOOL FUN_00403810(); + void CConfigApp::WriteRegisterSettings() const; + + //{{AFX_MSG(CConfigApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +private: + BOOL IsLegoNotRunning(); + +public: + MxDeviceEnumerate* m_device_enumerator; // 0x0c4 + MxDriver* m_driver; // 0x0c8 + Direct3DDeviceInfo* m_device; // 0x0cc + int m_display_bit_depth; // 0x0d0 + BOOL m_flip_surfaces; // 0x0d4 + BOOL m_full_screen; // 0x0d8 + BOOL m_3d_video_ram; // 0x0dc + BOOL m_wide_view_angle; // 0x0e0 + BOOL m_3d_sound; // 0x0e4 + BOOL m_draw_cursor; // 0x0e8 + BOOL m_use_joystick; // 0x0ec + int m_joystick_index; // 0x0f0 + BOOL m_run_config_dialog; // 0x0f4 + int m_model_quality; // 0x0f8 + int m_texture_quality; // 0x0fc + undefined m_unk0x100[4]; // 0x100 + BOOL m_music; // 0x104 +}; + +// SYNTHETIC: CONFIG 0x00402cd0 +// CConfigApp::`scalar deleting destructor' + +// FUNCTION: CONFIG 0x402c30 +// CConfigApp::GetMessageMap + +// GLOBAL: CONFIG 0x406008 +// CConfigApp::messageMap + +// GLOBAL: CONFIG 0x406010 +// CConfigApp::_messageEntries + +#endif // !defined(AFX_CONFIG_H) diff --git a/CONFIG/detectdx5.cpp b/CONFIG/detectdx5.cpp new file mode 100644 index 00000000..546f0dbd --- /dev/null +++ b/CONFIG/detectdx5.cpp @@ -0,0 +1,142 @@ +#include "detectdx5.h" + +#include +#include + +typedef HRESULT WINAPI DirectDrawCreate_fn(GUID FAR* lpGUID, LPDIRECTDRAW FAR* lplpDD, IUnknown FAR* pUnkOuter); +typedef HRESULT WINAPI +DirectInputCreateA_fn(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUTA* ppDI, LPUNKNOWN punkOuter); + +// FUNCTION: CONFIG 0x004048f0 +BOOL DetectDirectX5() +{ + unsigned int version; + BOOL found; + DetectDirectX(&version, &found); + return version >= 0x500; +} + +// FUNCTION: CONFIG 0x00404920 +void DetectDirectX(unsigned int* p_version, BOOL* p_found) +{ + OSVERSIONINFOA os_version; + + os_version.dwOSVersionInfoSize = sizeof(os_version); + if (!GetVersionExA(&os_version)) { + *p_version = 0; + *p_found = 0; + return; + } + if (os_version.dwPlatformId == 2) { + *p_found = 2; + if (os_version.dwMajorVersion < 4) { + *p_found = 0; + return; + } + if (os_version.dwMajorVersion != 4) { + *p_version = 0x501; + return; + } + *p_version = 0x200; + HMODULE dinput_module = LoadLibraryA("DINPUT.DLL"); + if (!dinput_module) { + OutputDebugStringA("Couldn't LoadLibrary DInput\r\n"); + return; + } + DirectInputCreateA_fn* func_DirectInputCreateA = + (DirectInputCreateA_fn*) GetProcAddress(dinput_module, "DirectInputCreateA"); + FreeLibrary(dinput_module); + if (!func_DirectInputCreateA) { + OutputDebugStringA("Couldn't GetProcAddress DInputCreate\r\n"); + return; + } + *p_version = 0x300; + return; + } + *p_found = 1; + if (LOWORD(os_version.dwBuildNumber) >= 0x550) { + *p_version = 0x501; + return; + } + HMODULE ddraw_module = LoadLibraryA("DDRAW.DLL"); + if (!ddraw_module) { + *p_version = 0; + *p_found = 0; + FreeLibrary(ddraw_module); + return; + } + DirectDrawCreate_fn* func_DirectDrawCreate = + (DirectDrawCreate_fn*) GetProcAddress(ddraw_module, "DirectDrawCreate"); + if (!func_DirectDrawCreate) { + *p_version = 0; + *p_found = 0; + FreeLibrary(ddraw_module); + OutputDebugStringA("Couldn't LoadLibrary DDraw\r\n"); + return; + } + LPDIRECTDRAW ddraw; + if (FAILED(func_DirectDrawCreate(NULL, &ddraw, NULL))) { + *p_version = 0; + *p_found = 0; + FreeLibrary(ddraw_module); + OutputDebugStringA("Couldn't create DDraw\r\n"); + return; + } + *p_version = 0x100; + LPDIRECTDRAW2 ddraw2; + if (FAILED(ddraw->QueryInterface(IID_IDirectDraw2, (LPVOID*) &ddraw2))) { + ddraw->Release(); + FreeLibrary(ddraw_module); + OutputDebugStringA("Couldn't QI DDraw2\r\n"); + return; + } + ddraw->Release(); + *p_version = 0x200; + HMODULE dinput_module = LoadLibraryA("DINPUT.DLL"); + if (!dinput_module) { + OutputDebugStringA("Couldn't LoadLibrary DInput\r\n"); + ddraw2->Release(); + FreeLibrary(ddraw_module); + return; + } + DirectInputCreateA_fn* func_DirectInputCreateA = + (DirectInputCreateA_fn*) GetProcAddress(dinput_module, "DirectInputCreateA"); + FreeLibrary(dinput_module); + if (!func_DirectInputCreateA) { + FreeLibrary(ddraw_module); + ddraw2->Release(); + OutputDebugStringA("Couldn't GetProcAddress DInputCreate\r\n"); + return; + } + *p_version = 0x300; + DDSURFACEDESC surface_desc; + memset(&surface_desc, 0, sizeof(surface_desc)); + surface_desc.dwSize = sizeof(surface_desc); + surface_desc.dwFlags = DDSD_CAPS; + surface_desc.ddsCaps.dwCaps = DDCAPS2_NONLOCALVIDMEM; + if (FAILED(ddraw2->SetCooperativeLevel(NULL, DISCL_BACKGROUND))) { + ddraw2->Release(); + FreeLibrary(ddraw_module); + *p_version = 0; + OutputDebugStringA("Couldn't Set coop level\r\n"); + return; + } + LPDIRECTDRAWSURFACE surface; + if (FAILED(ddraw2->CreateSurface(&surface_desc, &surface, NULL))) { + ddraw2->Release(); + FreeLibrary(ddraw_module); + *p_version = 0; + OutputDebugStringA("Couldn't CreateSurface\r\n"); + return; + } + LPDIRECTDRAWSURFACE3 surface3; + if (FAILED(surface->QueryInterface(IID_IDirectDrawSurface3, (LPVOID*) &surface3))) { + ddraw2->Release(); + FreeLibrary(ddraw_module); + return; + } + *p_version = 0x500; + surface3->Release(); + ddraw2->Release(); + FreeLibrary(ddraw_module); +} diff --git a/CONFIG/detectdx5.h b/CONFIG/detectdx5.h new file mode 100644 index 00000000..6f45837c --- /dev/null +++ b/CONFIG/detectdx5.h @@ -0,0 +1,10 @@ +#if !defined(AFX_DETECTDX5_H) +#define AFX_DETECTDX5_H + +#include + +extern BOOL DetectDirectX5(); + +extern void DetectDirectX(unsigned int* p_version, BOOL* p_found); + +#endif // !defined(AFX_DETECTDX5_H) diff --git a/CONFIG/res/config.rc b/CONFIG/res/config.rc new file mode 100644 index 00000000..a6164bfa --- /dev/null +++ b/CONFIG/res/config.rc @@ -0,0 +1,82 @@ +#include "resource.h" +#include "afxres.h" + +IDI_CONFIG ICON "lego.ico" + +IDB_SHARK BITMAP "shark.bmp" + +IDD_ABOUT DIALOG 0, 0, 217, 55 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About Configure LEGO\xAE Island" +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +FONT 8, "MS Sans Serif" +BEGIN + CONTROL IDI_CONFIG, -1, "STATIC", SS_ICON | WS_CHILD | WS_VISIBLE, 11, 17, 18, 20 + CONTROL "Configure LEGO Island Version 1.0", -1, "STATIC", SS_LEFT | SS_NOPREFIX | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 10, 119, 8 + CONTROL "Copyright \xA9 1997 mindscape", -1, "STATIC", SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 40, 25, 119, 8 + CONTROL "OK", IDOK, "BUTTON", BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 178, 7, 32, 14 +END + +STRINGTABLE +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +BEGIN + IDS_ABOUT, "&About Config..." +END + +IDD_MAIN DIALOGEX 0, 0, 289, 247 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Configure LEGO Island" +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "OK", IDABORT, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 172, 125, 44, 14 + CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 238, 125, 44, 14 + CONTROL "Fast", IDC_RAD_MODEL_QUALITY_LOW, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 124, 18, 42, 10 + CONTROL "High", IDC_RAD_MODEL_QUALITY_HIGH, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 192, 18, 69, 10 + CONTROL "Fast", IDC_RAD_TEXTURE_QUALITY_LOW, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 124, 49, 43, 10 + CONTROL "High", IDC_RAD_TEXTURE_QUALITY_HIGH, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 192, 49, 69, 10 + CONTROL "256 Color", IDC_RAD_PALETTE_256, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 124, 80, 50, 10 + CONTROL "High Color(16 bit)", IDC_RAD_PALETTE_16BIT, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE, 192, 80, 76, 10 + CONTROL "Use Joystick", IDC_CHK_JOYSTICK, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 192, 104, 60, 10 + CONTROL "", IDC_LIST_3DDEVICES, "LISTBOX", LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL, 115, 168, 161, 36 , WS_EX_TRANSPARENT + CONTROL "Flip Video Memory Pages", IDC_CHK_FLIP_VIDEO_MEM_PAGES, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 116, 224, 96, 15 + CONTROL "Draw 3D to Video Memory", IDC_CHK_3D_VIDEO_MEMORY, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 116, 210, 99, 10 + CONTROL "Color Palette", -1, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 69, 175, 26 + CONTROL "Direct 3D Devices", -1, "STATIC", SS_CENTER | WS_CHILD | WS_VISIBLE | WS_GROUP, 123, 158, 143, 10 + CONTROL "3D Sound", IDC_CHK_3DSOUND, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 220, 210, 45, 10 + CONTROL "Island Model Quality", -1, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 7, 175, 26 + CONTROL "Island Texture Quality", -1, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 38, 175, 26 + CONTROL "Advanced Settings", IDC_GRP_ADVANCED, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 107, 147, 175, 93 + CONTROL "Advanced", IDC_BTN_ADVANCED, "BUTTON", BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE, 109, 124, 44, 14 + CONTROL IDB_SHARK, IDC_BMP_SHARK, "STATIC", SS_BITMAP | WS_CHILD | WS_VISIBLE, 7, 7, 83, 249 + CONTROL "Draw Cursor", IDC_CHK_DRAW_CURSOR, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE, 219, 227, 54, 10 + CONTROL "Music", IDC_CHK_MUSIC, "BUTTON", BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 124, 104, 35, 10 +END + +1 VERSIONINFO +FILEVERSION 1,1,0,0 +PRODUCTVERSION 1,1,0,0 +FILEOS 0x4 +FILETYPE 0x1 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Mindscape, Inc." + VALUE "FileDescription", "LEGOIsland & Configuration application" + VALUE "FileVersion", "1, 1, 0, 0" + VALUE "InternalName", "LEGOISLE.EXE" + VALUE "LegalCopyright", "Copyright \xA9 1997" + VALUE "OriginalFilename", "CONFIG.EXE" + VALUE "ProductName", "LEGO Island" + VALUE "ProductVersion", "1, 1, 0, 0" + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 0x04B0 // U.S. English, Unicode + END +END diff --git a/CONFIG/res/lego.ico b/CONFIG/res/lego.ico new file mode 100644 index 00000000..7db1421d Binary files /dev/null and b/CONFIG/res/lego.ico differ diff --git a/CONFIG/res/resource.h b/CONFIG/res/resource.h new file mode 100644 index 00000000..4c72eaa1 --- /dev/null +++ b/CONFIG/res/resource.h @@ -0,0 +1,25 @@ +#define IDI_CONFIG 128 + +#define IDD_ABOUT 100 +#define IDS_ABOUT 101 + +#define IDD_MAIN 102 + +#define IDC_LIST_3DDEVICES 1000 +#define IDC_CHK_FLIP_VIDEO_MEM_PAGES 1001 +#define IDC_CHK_3D_VIDEO_MEMORY 1003 +#define IDC_RAD_PALETTE_256 1004 +#define IDC_RAD_PALETTE_16BIT 1005 +#define IDC_CHK_3DSOUND 1006 +#define IDC_CHK_DRAW_CURSOR 1008 +#define IDC_RAD_MODEL_QUALITY_LOW 1010 +#define IDC_RAD_MODEL_QUALITY_HIGH 1011 +#define IDC_RAD_TEXTURE_QUALITY_LOW 1013 +#define IDC_RAD_TEXTURE_QUALITY_HIGH 1014 +#define IDC_CHK_JOYSTICK 1015 +#define IDC_GRP_ADVANCED 1017 +#define IDC_BTN_ADVANCED 1020 +#define IDC_BMP_SHARK 1023 +#define IDC_CHK_MUSIC 1024 + +#define IDB_SHARK 135 diff --git a/CONFIG/res/shark.bmp b/CONFIG/res/shark.bmp new file mode 100644 index 00000000..0829a1d1 Binary files /dev/null and b/CONFIG/res/shark.bmp differ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0d2c6894..23e25faf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,10 @@ # Contributing -## Learning Decompilation +## Important Note -Generally, decompilation is a fairly advanced skill. If you aren't already familiar with it, it will likely take you months, or even years, to learn the skills necessary to do it (depending on your current proficiency with C/C++ and x86 assembly). If you're still interested, [part 1 of the decompilation vlog](https://www.youtube.com/watch?v=MToTEqoVv3I) covers the overall process and should give you a starting point that you can dive in from. +While we're thrilled that there is so much interest in reverse engineering LEGO Island and are happy to accept contributions from anyone who would like to help progress us further to our goal of a complete codebase, proposed changes to this repository must adhere to a certain degree of engineering quality. While the established contributors here are more than happy to provide code reviews and constructive criticism, it is not their job to teach potential contributors C++ or decompilation fundamentals. As a project that is largely an artifact of the free time of its contributors, the more of that (often scarce) resource that can be dedicated to efficient work, the faster the decompilation will progress. Unfortunately, this results in well-intentioned but poorly constructed contributions actually hurting progress in the long-term. While we are greatly appreciative of the sentiment, if you aren't very confident in your decompilation abilities, it is generally in the project's best interest that you return when you have a better grasp over the process. + +Generally, decompilation is a fairly advanced skill. Depending on your current proficiency with C/C++ and x86 assembly, it could take you months or even years to learn the skills necessary to do it adequately. If you're still interested in learning, [part 1 of the decompilation vlog](https://www.youtube.com/watch?v=MToTEqoVv3I) covers the overall process and should give you a starting point that you can dive in from. Once again, please make yourself familiar with this process before attempting to contribute code to this project. ## Ghidra Server @@ -15,7 +17,7 @@ To access the Ghidra repository, use the following details: ## General Guidelines -If you have contributions, feel free to create a pull request! Someone will review and merge it (or provide feedback) as soon as possible. +If you feel fit to contribute, feel free to create a pull request! Someone will review and merge it (or provide feedback) as soon as possible. Please keep your pull requests small and understandable; you may be able to shoot ahead and make a lot of progress in a short amount of time, but this is a collaborative project, so you must allow others to catch up and follow along. Large pull requests become significantly more unwieldy to review, and as such make it exponentially more likely for a mistake or error to go undetected. They also make it harder to merge other pull requests because the more files you modify, the more likely it is for a merge conflict to occur. A general guideline is to keep submissions limited to one class at a time. Sometimes two or more classes may be too interlinked for this to be feasible, so this is not a hard rule, however if your PR is starting to modify more than 10 or so files, it's probably getting too big. diff --git a/ISLE/define.cpp b/ISLE/define.cpp deleted file mode 100644 index c1f020fa..00000000 --- a/ISLE/define.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "define.h" - -// GLOBAL: ISLE 0x410030 -IsleApp* g_isle = 0; - -// GLOBAL: ISLE 0x410034 -unsigned char g_mousedown = 0; - -// GLOBAL: ISLE 0x410038 -unsigned char g_mousemoved = 0; - -// GLOBAL: ISLE 0x41003c -int g_closed = 0; - -// GLOBAL: ISLE 0x410040 -RECT g_windowRect = {0, 0, 640, 480}; - -// GLOBAL: ISLE 0x410050 -int g_rmDisabled = 0; - -// GLOBAL: ISLE 0x410054 -int g_waitingForTargetDepth = 1; - -// GLOBAL: ISLE 0x410058 -int g_targetWidth = 640; - -// GLOBAL: ISLE 0x41005c -int g_targetHeight = 480; - -// GLOBAL: ISLE 0x410060 -int g_targetDepth = 16; - -// GLOBAL: ISLE 0x410064 -int g_reqEnableRMDevice = 0; - -// GLOBAL: ISLE 0x4101bc -int g_startupDelay = 200; - -// GLOBAL: ISLE 0x4101c0 -MxLong g_lastFrameTime = 0; diff --git a/ISLE/define.h b/ISLE/define.h deleted file mode 100644 index 3f92244b..00000000 --- a/ISLE/define.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef DEFINE_H -#define DEFINE_H - -#include -#include - -class IsleApp; - -extern IsleApp* g_isle; -extern int g_closed; -// STRING: ISLE 0x4101c4 -#define WNDCLASS_NAME "Lego Island MainNoM App" -// STRING: ISLE 0x4101dc -#define WINDOW_TITLE "LEGO\xAE" -extern unsigned char g_mousedown; -extern unsigned char g_mousemoved; -extern RECT g_windowRect; -extern int g_rmDisabled; -extern int g_waitingForTargetDepth; -extern int g_targetWidth; -extern int g_targetHeight; -extern int g_targetDepth; -extern int g_reqEnableRMDevice; -extern int g_startupDelay; -extern MxLong g_lastFrameTime; - -#endif // DEFINE_H diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 4a2a840b..95bc6f62 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -1,6 +1,6 @@ #include "isleapp.h" -#include "define.h" +#include "decomp.h" #include "legoanimationmanager.h" #include "legobuildingmanager.h" #include "legogamestate.h" @@ -23,9 +23,50 @@ #include +DECOMP_SIZE_ASSERT(IsleApp, 0x8c) + +// GLOBAL: ISLE 0x410030 +IsleApp* g_isle = NULL; + +// GLOBAL: ISLE 0x410034 +unsigned char g_mousedown = 0; + +// GLOBAL: ISLE 0x410038 +unsigned char g_mousemoved = 0; + +// GLOBAL: ISLE 0x41003c +BOOL g_closed = FALSE; + +// GLOBAL: ISLE 0x410040 +RECT g_windowRect = {0, 0, 640, 480}; + +// GLOBAL: ISLE 0x410050 +BOOL g_rmDisabled = FALSE; + +// GLOBAL: ISLE 0x410054 +BOOL g_waitingForTargetDepth = TRUE; + +// GLOBAL: ISLE 0x410058 +int g_targetWidth = 640; + +// GLOBAL: ISLE 0x41005c +int g_targetHeight = 480; + +// GLOBAL: ISLE 0x410060 +int g_targetDepth = 16; + +// GLOBAL: ISLE 0x410064 +BOOL g_reqEnableRMDevice = FALSE; + +// STRING: ISLE 0x4101c4 +#define WNDCLASS_NAME "Lego Island MainNoM App" + +// STRING: ISLE 0x4101dc +#define WINDOW_TITLE "LEGO\xAE" + // Might be static functions of IsleApp -BOOL FindExistingInstance(void); -BOOL StartDirectSound(void); +BOOL FindExistingInstance(); +BOOL StartDirectSound(); // FUNCTION: ISLE 0x401000 IsleApp::IsleApp() @@ -34,25 +75,33 @@ IsleApp::IsleApp() m_cdPath = NULL; m_deviceId = NULL; m_savePath = NULL; - m_fullScreen = 1; - m_flipSurfaces = 0; - m_backBuffersInVram = 1; - m_using8bit = 0; - m_using16bit = 1; + m_fullScreen = TRUE; + m_flipSurfaces = FALSE; + m_backBuffersInVram = TRUE; + m_using8bit = FALSE; + m_using16bit = TRUE; m_unk0x24 = 0; - m_drawCursor = 0; - m_use3dSound = 1; - m_useMusic = 1; - m_useJoystick = 0; + m_drawCursor = FALSE; + m_use3dSound = TRUE; + m_useMusic = TRUE; + m_useJoystick = FALSE; m_joystickIndex = 0; - m_wideViewAngle = 1; + m_wideViewAngle = TRUE; m_islandQuality = 1; m_islandTexture = 1; - m_gameStarted = 0; + m_gameStarted = FALSE; m_frameDelta = 10; - m_windowActive = 1; + m_windowActive = TRUE; +#ifdef COMPAT_MODE + { + MxRect32 r(0, 0, 639, 479); + MxVideoParamFlags flags; + m_videoParam = MxVideoParam(r, NULL, 1, flags); + } +#else m_videoParam = MxVideoParam(MxRect32(0, 0, 639, 479), NULL, 1, MxVideoParamFlags()); +#endif m_videoParam.Flags().Set16Bit(MxDirectDraw::GetPrimaryBitDepth() == 16); m_windowHandle = NULL; @@ -227,8 +276,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine // Get reference to window HWND window; - if (g_isle->m_windowHandle) { - window = g_isle->m_windowHandle; + if (g_isle->GetWindowHandle()) { + window = g_isle->GetWindowHandle(); } // Load accelerators (this call actually achieves nothing - there is no "AppAccel" resource in the original - but @@ -258,16 +307,16 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } MSG nextMsg; - if (!g_isle || !g_isle->m_windowHandle || msg.message != WM_MOUSEMOVE || + if (!g_isle || !g_isle->GetWindowHandle() || msg.message != WM_MOUSEMOVE || !PeekMessageA(&nextMsg, NULL, 0, 0, PM_NOREMOVE) || nextMsg.message != WM_MOUSEMOVE) { TranslateMessage(&msg); DispatchMessageA(&msg); } if (g_reqEnableRMDevice) { - g_reqEnableRMDevice = 0; + g_reqEnableRMDevice = FALSE; VideoManager()->EnableRMDevice(); - g_rmDisabled = 0; + g_rmDisabled = FALSE; Lego()->StopTimer(); } @@ -291,7 +340,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } // FUNCTION: ISLE 0x401ca0 -BOOL FindExistingInstance(void) +BOOL FindExistingInstance() { HWND hWnd = FindWindowA(WNDCLASS_NAME, WINDOW_TITLE); if (hWnd) { @@ -304,7 +353,7 @@ BOOL FindExistingInstance(void) } // FUNCTION: ISLE 0x401ce0 -BOOL StartDirectSound(void) +BOOL StartDirectSound() { LPDIRECTSOUND lpDS = NULL; HRESULT ret = DirectSoundCreate(NULL, &lpDS, NULL); @@ -333,7 +382,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return DefWindowProcA(hWnd, uMsg, wParam, lParam); case WM_ACTIVATEAPP: if (g_isle) { - if ((wParam != 0) && (g_isle->m_fullScreen)) { + if ((wParam != 0) && (g_isle->GetFullScreen())) { MoveWindow( hWnd, g_windowRect.left, @@ -343,7 +392,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) TRUE ); } - g_isle->m_windowActive = wParam; + g_isle->SetWindowActive(wParam); } return DefWindowProcA(hWnd, uMsg, wParam, lParam); case WM_CLOSE: @@ -368,41 +417,41 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (wParam == SC_SCREENSAVE) { return 0; } - if (wParam == SC_CLOSE && g_closed == 0) { + if (wParam == SC_CLOSE && g_closed == FALSE) { if (g_isle) { if (g_rmDisabled) { - ShowWindow(g_isle->m_windowHandle, SW_RESTORE); + ShowWindow(g_isle->GetWindowHandle(), SW_RESTORE); } - PostMessageA(g_isle->m_windowHandle, WM_CLOSE, 0, 0); + PostMessageA(g_isle->GetWindowHandle(), WM_CLOSE, 0, 0); return 0; } } - else if (g_isle && g_isle->m_fullScreen && (wParam == SC_MOVE || wParam == SC_KEYMENU)) { + else if (g_isle && g_isle->GetFullScreen() && (wParam == SC_MOVE || wParam == SC_KEYMENU)) { return 0; } return DefWindowProcA(hWnd, uMsg, wParam, lParam); case WM_EXITMENULOOP: return DefWindowProcA(hWnd, uMsg, wParam, lParam); case WM_MOVING: - if (g_isle && g_isle->m_fullScreen) { + if (g_isle && g_isle->GetFullScreen()) { GetWindowRect(hWnd, (LPRECT) lParam); return 0; } return DefWindowProcA(hWnd, uMsg, wParam, lParam); case WM_NCPAINT: - if (g_isle && g_isle->m_fullScreen) { + if (g_isle && g_isle->GetFullScreen()) { return 0; } return DefWindowProcA(hWnd, uMsg, wParam, lParam); case WM_DISPLAYCHANGE: - if (g_isle && VideoManager() && g_isle->m_fullScreen && VideoManager()->GetDirect3D()) { - if (VideoManager()->GetDirect3D()->GetAssignedDevice()) { + if (g_isle && VideoManager() && g_isle->GetFullScreen() && VideoManager()->GetDirect3D()) { + if (VideoManager()->GetDirect3D()->AssignedDevice()) { int targetDepth = wParam; int targetWidth = LOWORD(lParam); int targetHeight = HIWORD(lParam); if (g_waitingForTargetDepth) { - g_waitingForTargetDepth = 0; + g_waitingForTargetDepth = FALSE; g_targetDepth = targetDepth; } else { @@ -415,11 +464,11 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (g_rmDisabled) { if (valid) { - g_reqEnableRMDevice = 1; + g_reqEnableRMDevice = TRUE; } } else if (!valid) { - g_rmDisabled = 1; + g_rmDisabled = TRUE; Lego()->StartTimer(); VideoManager()->DisableRMDevice(); } @@ -458,9 +507,9 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } break; case WM_SETCURSOR: - if (g_isle && (g_isle->m_cursorCurrent == g_isle->m_cursorBusy || - g_isle->m_cursorCurrent == g_isle->m_cursorNo || !g_isle->m_cursorCurrent)) { - SetCursor(g_isle->m_cursorCurrent); + if (g_isle && (g_isle->GetCursorCurrent() == g_isle->GetCursorBusy() || + g_isle->GetCursorCurrent() == g_isle->GetCursorNo() || !g_isle->GetCursorCurrent())) { + SetCursor(g_isle->GetCursorCurrent()); return 0; } break; @@ -472,7 +521,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (InputManager()) { InputManager()->QueueEvent(type, wParam, LOWORD(lParam), HIWORD(lParam), keyCode); } - if (g_isle && g_isle->m_drawCursor && type == c_notificationMouseMove) { + if (g_isle && g_isle->GetDrawCursor() && type == c_notificationMouseMove) { int x = LOWORD(lParam); int y = HIWORD(lParam); if (x >= 640) { @@ -654,7 +703,7 @@ BOOL IsleApp::ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize) } // FUNCTION: ISLE 0x4027b0 -int IsleApp::ReadRegBool(LPCSTR name, BOOL* out) +BOOL IsleApp::ReadRegBool(LPCSTR name, BOOL* out) { char buffer[256]; @@ -676,7 +725,7 @@ int IsleApp::ReadRegBool(LPCSTR name, BOOL* out) } // FUNCTION: ISLE 0x402880 -int IsleApp::ReadRegInt(LPCSTR name, int* out) +BOOL IsleApp::ReadRegInt(LPCSTR name, int* out) { char buffer[256]; @@ -757,24 +806,33 @@ void IsleApp::LoadConfig() // FUNCTION: ISLE 0x402c20 inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) { - if (!this->m_windowActive) { + // GLOBAL: ISLE 0x4101c0 + static MxLong g_lastFrameTime = 0; + + // GLOBAL: ISLE 0x4101bc + static int g_startupDelay = 200; + + if (!m_windowActive) { Sleep(0); return; } - if (!Lego()) + if (!Lego()) { return; - if (!TickleManager()) + } + if (!TickleManager()) { return; - if (!Timer()) + } + if (!Timer()) { return; + } MxLong currentTime = Timer()->GetRealTime(); if (currentTime < g_lastFrameTime) { - g_lastFrameTime = -this->m_frameDelta; + g_lastFrameTime = -m_frameDelta; } - if (this->m_frameDelta + g_lastFrameTime < currentTime) { + if (m_frameDelta + g_lastFrameTime < currentTime) { if (!Lego()->IsTimerRunning()) { TickleManager()->Tickle(); } @@ -817,11 +875,12 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) if (Start(&ds) != SUCCESS) { return; } - this->m_gameStarted = 1; + m_gameStarted = TRUE; } } - else if (sleepIfNotNextFrame != 0) + else if (sleepIfNotNextFrame != 0) { Sleep(0); + } } // FUNCTION: ISLE 0x402e80 diff --git a/ISLE/isleapp.h b/ISLE/isleapp.h index 5abc3a22..9fcd5df6 100644 --- a/ISLE/isleapp.h +++ b/ISLE/isleapp.h @@ -6,6 +6,7 @@ #include +// SIZE 0x8c class IsleApp { public: IsleApp(); @@ -28,56 +29,51 @@ class IsleApp { MxResult SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine); BOOL ReadReg(LPCSTR name, LPSTR outValue, DWORD outSize); - int ReadRegBool(LPCSTR name, BOOL* out); - int ReadRegInt(LPCSTR name, int* out); + BOOL ReadRegBool(LPCSTR name, BOOL* out); + BOOL ReadRegInt(LPCSTR name, int* out); void LoadConfig(); void Tick(BOOL sleepIfNotNextFrame); void SetupCursor(WPARAM wParam); - // private: - // 0 - LPSTR m_hdPath; - LPSTR m_cdPath; - LPSTR m_deviceId; - LPSTR m_savePath; + inline HWND GetWindowHandle() { return m_windowHandle; } + inline MxLong GetFrameDelta() { return m_frameDelta; } + inline BOOL GetFullScreen() { return m_fullScreen; } + inline HCURSOR GetCursorCurrent() { return m_cursorCurrent; } + inline HCURSOR GetCursorBusy() { return m_cursorBusy; } + inline HCURSOR GetCursorNo() { return m_cursorNo; } + inline BOOL GetDrawCursor() { return m_drawCursor; } - // 10 - BOOL m_fullScreen; - BOOL m_flipSurfaces; - BOOL m_backBuffersInVram; - BOOL m_using8bit; + inline void SetWindowActive(BOOL p_windowActive) { m_windowActive = p_windowActive; } - // 20 - BOOL m_using16bit; - int m_unk0x24; - BOOL m_use3dSound; - BOOL m_useMusic; - - // 30 - BOOL m_useJoystick; - int m_joystickIndex; - BOOL m_wideViewAngle; - int m_islandQuality; - - // 40 - int m_islandTexture; - int m_gameStarted; - MxLong m_frameDelta; - - // 4c - MxVideoParam m_videoParam; - - // 70 - BOOL m_windowActive; - HWND m_windowHandle; - BOOL m_drawCursor; - HCURSOR m_cursorArrow; - - // 80 - HCURSOR m_cursorBusy; - HCURSOR m_cursorNo; - HCURSOR m_cursorCurrent; +private: + LPSTR m_hdPath; // 0x00 + LPSTR m_cdPath; // 0x04 + LPSTR m_deviceId; // 0x08 + LPSTR m_savePath; // 0x0c + BOOL m_fullScreen; // 0x10 + BOOL m_flipSurfaces; // 0x14 + BOOL m_backBuffersInVram; // 0x18 + BOOL m_using8bit; // 0x1c + BOOL m_using16bit; // 0x20 + int m_unk0x24; // 0x24 + BOOL m_use3dSound; // 0x28 + BOOL m_useMusic; // 0x2c + BOOL m_useJoystick; // 0x30 + int m_joystickIndex; // 0x34 + BOOL m_wideViewAngle; // 0x38 + int m_islandQuality; // 0x3c + int m_islandTexture; // 0x40 + BOOL m_gameStarted; // 0x44 + MxLong m_frameDelta; // 0x48 + MxVideoParam m_videoParam; // 0x4c + BOOL m_windowActive; // 0x70 + HWND m_windowHandle; // 0x74 + BOOL m_drawCursor; // 0x78 + HCURSOR m_cursorArrow; // 0x7c + HCURSOR m_cursorBusy; // 0x80 + HCURSOR m_cursorNo; // 0x84 + HCURSOR m_cursorCurrent; // 0x88 }; #endif // ISLEAPP_H diff --git a/LEGO1/LegoOmni.def b/LEGO1/LegoOmni.def new file mode 100644 index 00000000..a3bbfe66 --- /dev/null +++ b/LEGO1/LegoOmni.def @@ -0,0 +1,138 @@ +; LegoOmni.def : Declares the module paarameters for the LEGO1.DLL. + +DESCRIPTION "Lego OMNI Windows Dynamic Link Library" + +EXPORTS + +; EXPORTs really required only. + +??0LegoBackgroundColor@@QAE@PBD0@Z +??0LegoGameState@@QAE@XZ +??0LegoWorld@@QAE@XZ +??0MxAtomId@@QAE@PBDW4LookupMode@@@Z +??0MxBitmap@@QAE@XZ +??0MxCore@@QAE@XZ +??0MxCriticalSection@@QAE@XZ +??0MxDSAction@@QAE@XZ +??0MxDSFile@@QAE@PBDK@Z +??0MxOmniCreateFlags@@QAE@XZ +??0MxOmniCreateParam@@QAE@PBDPAUHWND__@@AAVMxVideoParam@@VMxOmniCreateFlags@@@Z +??0MxString@@QAE@ABV0@@Z +??0MxVideoParam@@QAE@AAV0@@Z +??0MxVideoParam@@QAE@AAVMxRect32@@PAVMxPalette@@KAAVMxVideoParamFlags@@@Z +??0MxVideoParam@@QAE@XZ +??0MxVideoParamFlags@@QAE@XZ +??1LegoEntity@@UAE@XZ +??1LegoGameState@@QAE@XZ +??1LegoWorld@@UAE@XZ +??1MXIOINFO@@QAE@XZ +??1MxAtomId@@QAE@XZ +??1MxBitmap@@UAE@XZ +??1MxCore@@UAE@XZ +??1MxCriticalSection@@QAE@XZ +??1MxDSAction@@UAE@XZ +??1MxDSFile@@UAE@XZ +??1MxPresenter@@UAE@XZ +??1MxString@@UAE@XZ +??1MxVideoParam@@QAE@XZ +??4MxAtomId@@QAEAAV0@ABV0@@Z +??4MxString@@QAEABV0@PBD@Z +??4MxVideoParam@@QAEAAV0@ABV0@@Z +??8MxPalette@@QAEEAAV0@@Z +?BackgroundAudioManager@@YAPAVMxBackgroundAudioManager@@XZ +?Close@MxDSFile@@UAEJXZ +?Close@MxStreamer@@QAEJPBD@Z +?CreateBackgroundAudio@LegoOmni@@QAEXXZ +?CreateInstance@LegoOmni@@SAXXZ +?CreatePalette@MxBitmap@@UAEPAVMxPalette@@XZ +?CreateStreamObject@@YAPAVMxDSObject@@PAVMxDSFile@@F@Z +?DestroyInstance@MxOmni@@SAXXZ +?Detach@MxPalette@@QAEXXZ +?DisableRMDevice@LegoVideoManager@@QAEHXZ +?DoneTickle@MxPresenter@@MAEXXZ +?Enable@MxBackgroundAudioManager@@QAEXE@Z +?Enable@MxPresenter@@UAEXE@Z +?EnableFullScreenMovie@LegoVideoManager@@QAEXEE@Z +?EnableRMDevice@LegoVideoManager@@QAEHXZ +?EndAction@MxPresenter@@UAEXXZ +?EventManager@@YAPAVMxEventManager@@XZ +?FlipToGDISurface@MxDirectDraw@@QAEHXZ +?GameState@@YAPAVLegoGameState@@XZ +?GetBufferSize@MxDSFile@@UAEKXZ +?GetCD@MxOmni@@SAPBDXZ +?GetCurrPathInfo@LegoOmni@@SAHPAPAVLegoPathBoundary@@AAH@Z +?GetDefaults@LegoNavController@@SAXPAHPAM11111111PAE@Z +?GetHD@MxOmni@@SAPBDXZ +?GetInstance@LegoOmni@@SAPAV1@XZ +?GetInstance@MxOmni@@SAPAV1@XZ +?GetInstance@MxScheduler@@SAPAV1@XZ +?GetNoCD_SourceName@@YAPBDXZ +?GetPartsThreshold@RealtimeView@@SAMXZ +?GetPrimaryBitDepth@MxDirectDraw@@SAHXZ +?GetRealTime@MxTimer@@QAEJXZ +?GetStreamBuffersNum@MxDSFile@@UAEKXZ +?GetUserMaxLOD@RealtimeView@@SAMXZ +?GetVariable@MxVariableTable@@QAEPBDPBD@Z +?Init@MxPresenter@@IAEXXZ +?InputManager@@YAPAVLegoInputManager@@XZ +?InvalidateRect@MxVideoManager@@QAEXAAVMxRect32@@@Z +?IsSound3D@MxOmni@@SAEXZ +?Lego@@YAPAVLegoOmni@@XZ +?Load@LegoGameState@@QAEJK@Z +?MSoundManager@@YAPAVMxSoundManager@@XZ +?MakeSourceName@@YAXPADPBD@Z +?MoveCursor@LegoVideoManager@@QAEXHH@Z +?MusicManager@@YAPAVMxMusicManager@@XZ +?NotificationManager@@YAPAVMxNotificationManager@@XZ +?Notify@MxCore@@UAEJAAVMxParam@@@Z +?Open@MxDSFile@@UAEJK@Z +?Open@MxStreamer@@QAEPAVMxStreamController@@PBDG@Z +?ParseExtra@MxPresenter@@MAEXXZ +?Pause@MxDirectDraw@@QAEHH@Z +?PickEntity@@YAPAVLegoEntity@@JJ@Z +?PickROI@@YAPAVLegoROI@@JJ@Z +?QueueEvent@LegoInputManager@@QAEXW4NotificationId@@EJJE@Z +?Read@MxBitmap@@UAEJPBD@Z +?Read@MxDSFile@@UAEJPAEK@Z +?RealizePalette@MxVideoManager@@UAEJPAVMxPalette@@@Z +?Register@LegoInputManager@@QAEXPAVMxCore@@@Z +?RemoveAll@ViewManager@@QAEXPAVViewROI@@@Z +?RemoveWorld@LegoOmni@@QAEXABVMxAtomId@@J@Z +?Save@LegoGameState@@QAEJK@Z +?Seek@MxDSFile@@UAEJJH@Z +?SerializePlayersInfo@LegoGameState@@QAEXF@Z +?SerializeScoreHistory@LegoGameState@@QAEXF@Z +?SetCD@MxOmni@@SAXPBD@Z +?SetDefaults@LegoNavController@@SAXHMMMMMMMMME@Z +?SetDeviceName@MxVideoParam@@QAEXPAD@Z +?SetDisplayBB@LegoROI@@QAEXH@Z +?SetDoMutex@MxCriticalSection@@SAXXZ +?SetHD@MxOmni@@SAXPBD@Z +?SetObjectName@MxDSObject@@QAEXPBD@Z +?SetOmniUserMessage@@YAXP6AXPBDH@Z@Z +?SetPartsThreshold@RealtimeView@@SAXM@Z +?SetSavePath@LegoGameState@@QAEXPAD@Z +?SetSound3D@MxOmni@@SAXE@Z +?SetUserMaxLOD@RealtimeView@@SAXM@Z +?SetVariable@MxVariableTable@@QAEXPAVMxVariable@@@Z +?SetVariable@MxVariableTable@@QAEXPBD0@Z +?SetWaitIndicator@MxTransitionManager@@QAEXPAVMxVideoPresenter@@@Z +?SoundManager@@YAPAVLegoSoundManager@@XZ +?Start@@YAJPAVMxDSAction@@@Z +?StartAction@MxPresenter@@UAEJPAVMxStreamController@@PAVMxDSAction@@@Z +?StartMultiTasking@MxScheduler@@QAEXK@Z +?Streamer@@YAPAVMxStreamer@@XZ +?Tickle@MxPresenter@@UAEJXZ +?TickleManager@@YAPAVMxTickleManager@@XZ +?Timer@@YAPAVMxTimer@@XZ +?TransitionManager@@YAPAVMxTransitionManager@@XZ +?UnRegister@LegoInputManager@@QAEXPAVMxCore@@@Z +?VariableTable@@YAPAVMxVariableTable@@XZ +?VideoManager@@YAPAVLegoVideoManager@@XZ +?configureLegoAnimationManager@LegoAnimationManager@@SAXH@Z +?configureLegoBuildingManager@LegoBuildingManager@@SAXH@Z +?configureLegoModelPresenter@LegoModelPresenter@@SAXH@Z +?configureLegoPartPresenter@LegoPartPresenter@@SAXHH@Z +?configureLegoROI@LegoROI@@SAXH@Z +?configureLegoWorldPresenter@LegoWorldPresenter@@SAXH@Z +_DllMain@12 diff --git a/LEGO1/LegoOmni.mingw.def b/LEGO1/LegoOmni.mingw.def new file mode 100644 index 00000000..e2c4ce5f --- /dev/null +++ b/LEGO1/LegoOmni.mingw.def @@ -0,0 +1,164 @@ +; LegoOmni.def : Declares the module paarameters for the LEGO1.DLL. + +; DESCRIPTION " Lego OMNI Windows Dynamic Link Library" + +EXPORTS + +; EXPORTs really required only. + +_ZN13LegoGameState11SetSavePathEPc +_ZN13LegoGameState20SerializePlayersInfoEs +_ZN13LegoGameState21SerializeScoreHistoryEs +_ZN13LegoGameState4SaveEj +_ZN13LegoGameStateC1Ev +_ZN13LegoGameStateC2Ev +_ZN13LegoGameStateD1Ev +_ZN13LegoGameStateD2Ev +_ZN9LegoWorldC1Ev +_ZN9LegoWorldC2Ev +_ZN9LegoWorldD0Ev +_ZN9LegoWorldD1Ev +_ZN9LegoWorldD2Ev +DllMain@12 +_Z10PickEntityii +_Z12EventManagerv +_Z12InputManagerv +_Z12MusicManagerv +_Z12SoundManagerv +_Z12VideoManagerv +_Z13MSoundManagerv +_Z13TickleManagerv +_Z13VariableTablev +_Z14MakeSourceNamePcPKc +_Z17TransitionManagerv +_Z18CreateStreamObjectP8MxDSFiles +_Z18GetNoCD_SourceNamev +_Z18SetOmniUserMessagePFvPKciE +_Z19NotificationManagerv +_Z22BackgroundAudioManagerv +_Z4Legov +_Z5StartP10MxDSAction +_Z5Timerv +_Z7PickROIii +_Z8Streamerv +_Z9GameStatev +_ZN10MxDSActionC1Ev +_ZN10MxDSActionC2Ev +_ZN10MxDSActionD0Ev +_ZN10MxDSActionD1Ev +_ZN10MxDSActionD2Ev +_ZN10MxDSObject13SetObjectNameEPKc +_ZN10MxStreamer4OpenEPKct +_ZN10MxStreamer5CloseEPKc +_ZN11MxPresenter10DoneTickleEv +_ZN11MxPresenter10ParseExtraEv +_ZN11MxPresenter11StartActionEP18MxStreamControllerP10MxDSAction +_ZN11MxPresenter4InitEv +_ZN11MxPresenter6EnableEh +_ZN11MxPresenter6TickleEv +_ZN11MxPresenter9EndActionEv +_ZN11MxScheduler11GetInstanceEv +_ZN11MxScheduler17StartMultiTaskingEj +_ZN11ViewManager9RemoveAllEP7ViewROI +_ZN12MxDirectDraw16FlipToGDISurfaceEv +_ZN12MxDirectDraw18GetPrimaryBitDepthEv +_ZN12MxDirectDraw5PauseEi +_ZN12MxVideoParam13SetDeviceNameEPc +_ZN12MxVideoParamC1ERS_ +_ZN12MxVideoParamC1Ev +_ZN12MxVideoParamC2ERS_ +_ZN12MxVideoParamC2Ev +_ZN12MxVideoParamD1Ev +_ZN12MxVideoParamD2Ev +_ZN12MxVideoParamaSERKS_ +_ZN12RealtimeView13GetUserMaxLODEv +_ZN12RealtimeView13SetUserMaxLODEf +_ZN12RealtimeView17GetPartsThresholdEv +_ZN12RealtimeView17SetPartsThresholdEf +_ZN14MxVideoManager14InvalidateRectER8MxRect32 +_ZN14MxVideoManager14RealizePaletteEP9MxPalette +_ZN15MxVariableTable11GetVariableEPKc +_ZN15MxVariableTable11SetVariableEP10MxVariable +_ZN15MxVariableTable11SetVariableEPKcS1_ = _ZN15MxVariableTable11SetVariableEPKcS1_ +;_ZN16LegoInputManager10QueueEventE14NotificationIdhiih +_ZN16LegoInputManager10QueueEventE14NotificationIdhiih +_ZN16LegoInputManager10UnRegisterEP6MxCore +_ZN16LegoInputManager8RegisterEP6MxCore +_ZN16LegoVideoManager10MoveCursorEii +_ZN16LegoVideoManager14EnableRMDeviceEv +_ZN16LegoVideoManager15DisableRMDeviceEv +_ZN16LegoVideoManager21EnableFullScreenMovieEhh +_ZN17LegoNavController11GetDefaultsEPiPfS1_S1_S1_S1_S1_S1_S1_S1_Ph +_ZN17LegoNavController11SetDefaultsEifffffffffh +_ZN17LegoPartPresenter26configureLegoPartPresenterEii +_ZN17MxCriticalSection10SetDoMutexEv +_ZN17MxCriticalSectionC1Ev +_ZN17MxCriticalSectionC2Ev +_ZN17MxCriticalSectionD1Ev +_ZN17MxCriticalSectionD2Ev +_ZN17MxOmniCreateFlagsC1Ev +_ZN17MxOmniCreateFlagsC2Ev +_ZN17MxOmniCreateParamC1EPKcP6HWND__R12MxVideoParam17MxOmniCreateFlags +_ZN17MxVideoParamFlagsC1Ev +_ZN17MxVideoParamFlagsC2Ev +_ZN18LegoModelPresenter27configureLegoModelPresenterEi +_ZN18LegoWorldPresenter27configureLegoWorldPresenterEi +_ZN19LegoBuildingManager28configureLegoBuildingManagerEi +_ZN19MxTransitionManager16SetWaitIndicatorEP16MxVideoPresenter +_ZN20LegoAnimationManager29configureLegoAnimationManagerEi +_ZN24MxBackgroundAudioManager6EnableEh +_ZN6MxCore6NotifyER7MxParam +_ZN6MxCoreC1Ev +_ZN6MxCoreC2Ev +_ZN6MxCoreD0Ev +_ZN6MxCoreD1Ev +_ZN6MxCoreD2Ev +_ZN6MxOmni10SetSound3DEh +_ZN6MxOmni11GetInstanceEv +_ZN6MxOmni15DestroyInstanceEv +_ZN6MxOmni5GetCDEv +_ZN6MxOmni5GetHDEv +_ZN6MxOmni5SetCDEPKc +_ZN6MxOmni5SetHDEPKc +_ZN6MxOmni9IsSound3DEv +_ZN7LegoROI12SetDisplayBBEi +_ZN7LegoROI16configureLegoROIEi +_ZN7MxTimer11GetRealTimeEv +_ZN8LegoOmni11GetInstanceEv +_ZN8LegoOmni11RemoveWorldERK8MxAtomIdi +_ZN8LegoOmni14CreateInstanceEv +_ZN8LegoOmni15GetCurrPathInfoEPP16LegoPathBoundaryRi +_ZN8LegoOmni21CreateBackgroundAudioEv +_ZN8MXIOINFOD1Ev +_ZN8MXIOINFOD2Ev +_ZN8MxAtomIdC1EPKc10LookupMode +_ZN8MxAtomIdC2EPKc10LookupMode +_ZN8MxAtomIdD1Ev +_ZN8MxAtomIdD2Ev +_ZN8MxAtomIdaSERKS_ +_ZN8MxBitmap13CreatePaletteEv +_ZN8MxBitmap4ReadEPKc +_ZN8MxBitmapC1Ev +_ZN8MxBitmapC2Ev +_ZN8MxBitmapD0Ev +_ZN8MxBitmapD1Ev +_ZN8MxBitmapD2Ev +_ZN8MxDSFile13GetBufferSizeEv +_ZN8MxDSFile19GetStreamBuffersNumEv +_ZN8MxDSFile4OpenEj +_ZN8MxDSFile4ReadEPhj +_ZN8MxDSFile4SeekEii +_ZN8MxDSFile5CloseEv +_ZN8MxDSFileC1EPKcj +_ZN8MxDSFileC2EPKcj +_ZN8MxDSFileD0Ev +_ZN8MxDSFileD1Ev +_ZN8MxDSFileD2Ev +_ZN8MxStringC1ERKS_ +_ZN8MxStringC2ERKS_ +_ZN8MxStringD0Ev +_ZN8MxStringD1Ev +_ZN8MxStringD2Ev +_ZN8MxStringaSEPKc +_ZN9MxPalette6DetachEv +_ZN9MxPaletteeqERS_ diff --git a/LEGO1/lego/legoomni/include/act1state.h b/LEGO1/lego/legoomni/include/act1state.h index 4babf08a..8b1a09b1 100644 --- a/LEGO1/lego/legoomni/include/act1state.h +++ b/LEGO1/lego/legoomni/include/act1state.h @@ -2,49 +2,124 @@ #define ACT1STATE_H #include "legostate.h" +#include "legoutil.h" +#include "roi/legoroi.h" // VTABLE: LEGO1 0x100d7028 // SIZE 0x26c class Act1State : public LegoState { public: + enum { + e_unk953 = 953, + e_unk954 = 954, + e_unk955 = 955, + }; + Act1State(); // FUNCTION: LEGO1 0x100338a0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0154 return "Act1State"; - }; + } // FUNCTION: LEGO1 0x100338b0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act1State::ClassName()) || LegoState::IsA(p_name); - }; + } - virtual MxBool SetFlag() override; // vtable+0x18 - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxBool SetFlag() override; // vtable+0x18 + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c - inline void SetUnknown18(MxU32 p_unk0x18) { m_unk0x18 = p_unk0x18; } - inline MxU32 GetUnknown18() { return m_unk0x18; } - inline void SetUnknown21(MxS16 p_unk0x21) { m_unk0x21 = p_unk0x21; } - inline MxS16 GetUnknown21() { return m_unk0x21; } + inline void SetUnknown18(MxU32 p_unk0x18) { m_unk0x018 = p_unk0x18; } + inline MxU32 GetUnknown18() { return m_unk0x018; } + inline MxU32 GetUnknown1c() { return m_unk0x01c; } + inline MxS16 GetUnknown21() { return m_unk0x021; } + + inline void SetUnknown1c(MxU32 p_unk0x1c) { m_unk0x01c = p_unk0x1c; } + inline void SetUnknown21(MxS16 p_unk0x21) { m_unk0x021 = p_unk0x21; } void FUN_10034d00(); // SYNTHETIC: LEGO1 0x10033960 // Act1State::`scalar deleting destructor' + // SIZE 0x4c + class NamedPlane { + public: + // FUNCTION: LEGO1 0x10033800 + NamedPlane() {} + + inline void SetName(const char* p_name) { m_name = p_name; } + inline const MxString* GetName() const { return &m_name; } + + // FUNCTION: LEGO1 0x100344d0 + MxResult Serialize(LegoFile* p_file) + { + if (p_file->IsWriteMode()) { + p_file->FUN_10006030(m_name); + p_file->WriteVector3(m_point1); + p_file->WriteVector3(m_point2); + p_file->WriteVector3(m_point3); + } + else if (p_file->IsReadMode()) { + p_file->ReadString(m_name); + p_file->ReadVector3(m_point1); + p_file->ReadVector3(m_point2); + p_file->ReadVector3(m_point3); + } + + return SUCCESS; + } + + private: + MxString m_name; // 0x00 + Mx3DPointFloat m_point1; // 0x10 + Mx3DPointFloat m_point2; // 0x24 + Mx3DPointFloat m_point3; // 0x38 + }; + protected: - undefined m_unk0x8[0x10]; // 0x8 - MxU32 m_unk0x18; // 0x18 - undefined2 m_unk0x1c; // 0x1c - undefined m_unk0x1e; // 0x1e - undefined m_unk0x1f; // 0x1f - undefined m_unk0x20; // 0x20 - MxBool m_unk0x21; // 0x21 - undefined m_unk0x22; // 0x22 - // TODO + MxS32* m_unk0x008; // 0x008 + // FIXME: count for m_unk0x008 + MxS16 m_unk0x00c; // 0x00c + undefined2 m_unk0x00e; // 0x00e + undefined2 m_unk0x010; // 0x010 + undefined m_unk0x012; // 0x012 + MxS32 m_unk0x014; // 0x014 + MxU32 m_unk0x018; // 0x018 + MxU16 m_unk0x01c; // 0x01c + undefined m_unk0x01e; // 0x01e + undefined m_unk0x01f; // 0x01f + undefined m_unk0x020; // 0x020 + undefined m_unk0x021; // 0x021 + undefined m_unk0x022; // 0x022 + undefined m_unk0x023; // 0x023 + NamedPlane m_unk0x024; // 0x024 + NamedPlane m_unk0x070; // 0x070 + NamedPlane m_unk0x0bc; // 0x0bc + NamedPlane m_unk0x108; // 0x108 + NamedTexture* m_unk0x154; // 0x154 + NamedTexture* m_unk0x158; // 0x158 + NamedTexture* m_unk0x15c; // 0x15c + MxCore* m_unk0x160; // 0x160 + NamedPlane m_unk0x164; // 0x164 + NamedTexture* m_unk0x1b0; // 0x1b0 + NamedTexture* m_unk0x1b4; // 0x1b4 + MxCore* m_unk0x1b8; // 0x1b8 + NamedPlane m_unk0x1bc; // 0x1bc + NamedTexture* m_unk0x208; // 0x208 + MxCore* m_unk0x20c; // 0x20c + NamedPlane m_unk0x210; // 0x210 + NamedTexture* m_unk0x25c; // 0x25c + NamedTexture* m_unk0x260; // 0x260 + NamedTexture* m_unk0x264; // 0x264 + MxCore* m_unk0x268; // 0x268 }; +// FUNCTION: LEGO1 0x10033a70 +// Act1State::NamedPlane::~NamedPlane + #endif // ACT1STATE_H diff --git a/LEGO1/lego/legoomni/include/act2brick.h b/LEGO1/lego/legoomni/include/act2brick.h index e9f771ad..32856732 100644 --- a/LEGO1/lego/legoomni/include/act2brick.h +++ b/LEGO1/lego/legoomni/include/act2brick.h @@ -8,25 +8,25 @@ class Act2Brick : public LegoPathActor { public: Act2Brick(); - virtual ~Act2Brick() override; // vtable+0x0 + ~Act2Brick() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x08 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1007a360 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0438 return "Act2Brick"; } // FUNCTION: LEGO1 0x1007a370 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act2Brick::ClassName()) || LegoEntity::IsA(p_name); } - virtual MxS32 VTable0x94() override; // vtable+0x94 + MxS32 VTable0x94() override; // vtable+0x94 // SYNTHETIC: LEGO1 0x1007a450 // Act2Brick::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/act2policestation.h b/LEGO1/lego/legoomni/include/act2policestation.h index 4746236f..02d95e5b 100644 --- a/LEGO1/lego/legoomni/include/act2policestation.h +++ b/LEGO1/lego/legoomni/include/act2policestation.h @@ -7,17 +7,17 @@ // SIZE 0x68 class Act2PoliceStation : public LegoEntity { public: - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1000e200 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03fc return "Act2PoliceStation"; } // FUNCTION: LEGO1 0x1000e210 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act2PoliceStation::ClassName()) || LegoEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h index b693663f..46ae4e4f 100644 --- a/LEGO1/lego/legoomni/include/act3.h +++ b/LEGO1/lego/legoomni/include/act3.h @@ -9,31 +9,31 @@ class Act3 : public LegoWorld { public: Act3(); - virtual ~Act3() override; // vtable+00 + ~Act3() override; // vtable+00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10072510 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f013c return "Act3"; } // FUNCTION: LEGO1 0x10072520 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act3::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual void VTable0x60() override; // vtable+0x60 - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + void VTable0x60() override; // vtable+0x60 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 inline void SetUnkown420c(MxEntity* p_entity) { m_unk0x420c = p_entity; } inline void SetUnkown4270(MxU32 p_unk0x4270) { m_unk0x4270 = p_unk0x4270; } @@ -41,6 +41,11 @@ class Act3 : public LegoWorld { // SYNTHETIC: LEGO1 0x10072630 // Act3::`scalar deleting destructor' + MxBool FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); + MxBool FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); + void FUN_10073400(); + void FUN_10073430(); + protected: undefined m_unk0xf8[0x4114]; // 0xf8 MxEntity* m_unk0x420c; // 0x420c diff --git a/LEGO1/lego/legoomni/include/act3actor.h b/LEGO1/lego/legoomni/include/act3actor.h index 00d06495..3d146cb7 100644 --- a/LEGO1/lego/legoomni/include/act3actor.h +++ b/LEGO1/lego/legoomni/include/act3actor.h @@ -8,7 +8,7 @@ class Act3Actor : public MxCore { public: // FUNCTION: LEGO1 0x100431b0 - inline virtual const char* ClassName() const override + inline const char* ClassName() const override { // STRING: LEGO1 0x100f03ac return "Act3Actor"; diff --git a/LEGO1/lego/legoomni/include/act3shark.h b/LEGO1/lego/legoomni/include/act3shark.h index 5ba5a6f2..b0b26a48 100644 --- a/LEGO1/lego/legoomni/include/act3shark.h +++ b/LEGO1/lego/legoomni/include/act3shark.h @@ -7,22 +7,22 @@ class Act3Shark : public LegoAnimActor { public: // FUNCTION: LEGO1 0x100430c0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03a0 return "Act3Shark"; } // FUNCTION: LEGO1 0x1001a130 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act3Shark::ClassName()) || LegoAnimActor::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 - virtual void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 // SYNTHETIC: LEGO1 0x10043020 // Act3Shark::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/act3state.h b/LEGO1/lego/legoomni/include/act3state.h index c88c4620..0edd5345 100644 --- a/LEGO1/lego/legoomni/include/act3state.h +++ b/LEGO1/lego/legoomni/include/act3state.h @@ -4,32 +4,33 @@ #include "legostate.h" // VTABLE: LEGO1 0x100d4fc8 -// SIZE 0xc +// SIZE 0x0c class Act3State : public LegoState { public: inline Act3State() { m_unk0x08 = 0; } // FUNCTION: LEGO1 0x1000e300 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03f0 return "Act3State"; } // FUNCTION: LEGO1 0x1000e310 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act3State::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool VTable0x14() override; + MxBool VTable0x14() override; // SYNTHETIC: LEGO1 0x1000e3c0 // Act3State::`scalar deleting destructor' + inline undefined4 GetUnknown0x08() { return m_unk0x08; } + private: - // FIXME: May be part of LegoState? Uncertain... - MxU32 m_unk0x08; + undefined4 m_unk0x08; // 0x08 }; #endif // ACT3STATE_H diff --git a/LEGO1/lego/legoomni/include/ambulance.h b/LEGO1/lego/legoomni/include/ambulance.h index 88fd57d8..17175b03 100644 --- a/LEGO1/lego/legoomni/include/ambulance.h +++ b/LEGO1/lego/legoomni/include/ambulance.h @@ -9,29 +9,29 @@ class Ambulance : public IslePathActor { public: Ambulance(); - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 - virtual MxResult Tickle() override; // vtable+0x08 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10035fa0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03c4 return "Ambulance"; } // FUNCTION: LEGO1 0x10035fb0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Ambulance::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual MxU32 VTable0xdc(MxType19NotificationParam&) override; // vtable+0xdc - virtual void VTable0xe4() override; // vtable+0xe4 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xdc(MxType19NotificationParam&) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x10036130 // Ambulance::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/ambulancemissionstate.h b/LEGO1/lego/legoomni/include/ambulancemissionstate.h index ea5cfb3e..aca6120b 100644 --- a/LEGO1/lego/legoomni/include/ambulancemissionstate.h +++ b/LEGO1/lego/legoomni/include/ambulancemissionstate.h @@ -10,19 +10,19 @@ class AmbulanceMissionState : public LegoState { AmbulanceMissionState(); // FUNCTION: LEGO1 0x10037600 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f00e8 return "AmbulanceMissionState"; } // FUNCTION: LEGO1 0x10037610 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, AmbulanceMissionState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c inline MxU16 GetColor(MxU8 p_id) { @@ -46,18 +46,18 @@ class AmbulanceMissionState : public LegoState { // AmbulanceMissionState::`scalar deleting destructor' protected: - undefined4 m_unk0x8; // 0x08 - undefined4 m_unk0xc; // 0x0c - MxU16 m_unk0x10; // 0x10 - MxU16 m_unk0x12; // 0x12 - MxU16 m_unk0x14; // 0x14 - MxU16 m_unk0x16; // 0x16 - MxU16 m_unk0x18; // 0x18 - MxU16 m_color1; // 0x1a - MxU16 m_color2; // 0x1c - MxU16 m_color3; // 0x1e - MxU16 m_color4; // 0x20 - MxU16 m_color5; // 0x22 + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + MxU16 m_unk0x10; // 0x10 + MxU16 m_unk0x12; // 0x12 + MxU16 m_unk0x14; // 0x14 + MxU16 m_unk0x16; // 0x16 + MxU16 m_unk0x18; // 0x18 + MxU16 m_color1; // 0x1a + MxU16 m_color2; // 0x1c + MxU16 m_color3; // 0x1e + MxU16 m_color4; // 0x20 + MxU16 m_color5; // 0x22 }; #endif // AMBULANCEMISSIONSTATE_H diff --git a/LEGO1/lego/legoomni/include/animstate.h b/LEGO1/lego/legoomni/include/animstate.h index fe39ccc7..16c92120 100644 --- a/LEGO1/lego/legoomni/include/animstate.h +++ b/LEGO1/lego/legoomni/include/animstate.h @@ -8,33 +8,33 @@ class AnimState : public LegoState { public: AnimState(); - virtual ~AnimState() override; // vtable+0x0 + ~AnimState() override; // vtable+0x00 // FUNCTION: LEGO1 0x10065070 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0460 return "AnimState"; } // FUNCTION: LEGO1 0x10065080 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, AnimState::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool SetFlag() override; // vtable+0x18 - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1C + MxBool SetFlag() override; // vtable+0x18 + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c // SYNTHETIC: LEGO1 0x10065130 // AnimState::`scalar deleting destructor' private: - undefined4 m_unk0x8; - undefined4 m_unk0xc; - void* m_unk0x10; - undefined4 m_unk0x14; - void* m_unk0x18; + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + void* m_unk0x10; // 0x10 + undefined4 m_unk0x14; // 0x14 + void* m_unk0x18; // 0x18 }; #endif // ANIMSTATE_H diff --git a/LEGO1/lego/legoomni/include/beachhouseentity.h b/LEGO1/lego/legoomni/include/beachhouseentity.h index 1c92fc17..0910f49e 100644 --- a/LEGO1/lego/legoomni/include/beachhouseentity.h +++ b/LEGO1/lego/legoomni/include/beachhouseentity.h @@ -8,14 +8,14 @@ class BeachHouseEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000ee80 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0314 return "BeachHouseEntity"; } // FUNCTION: LEGO1 0x1000ee90 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, BeachHouseEntity::ClassName()) || BuildingEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/bike.h b/LEGO1/lego/legoomni/include/bike.h index 02265604..bfc634b4 100644 --- a/LEGO1/lego/legoomni/include/bike.h +++ b/LEGO1/lego/legoomni/include/bike.h @@ -11,22 +11,22 @@ class Bike : public IslePathActor { Bike(); // FUNCTION: LEGO1 0x100766f0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03d0 return "Bike"; } // FUNCTION: LEGO1 0x10076700 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Bike::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual void VTable0xe4() override; // vtable+0xe4 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x10076880 // Bike::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/buildingentity.h b/LEGO1/lego/legoomni/include/buildingentity.h index 0e9a9d45..d07d9f5d 100644 --- a/LEGO1/lego/legoomni/include/buildingentity.h +++ b/LEGO1/lego/legoomni/include/buildingentity.h @@ -8,19 +8,19 @@ class BuildingEntity : public LegoEntity { public: BuildingEntity(); - virtual ~BuildingEntity() override; // vtable+0x0 + ~BuildingEntity() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10014f20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f07e8 return "BuildingEntity"; } // FUNCTION: LEGO1 0x10014f30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, BuildingEntity::ClassName()) || LegoEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/bumpbouy.h b/LEGO1/lego/legoomni/include/bumpbouy.h index 112801b2..c6308d57 100644 --- a/LEGO1/lego/legoomni/include/bumpbouy.h +++ b/LEGO1/lego/legoomni/include/bumpbouy.h @@ -7,25 +7,25 @@ // VTABLE: LEGO1 0x100d6790 class BumpBouy : public LegoAnimActor { public: - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100274e0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0394 return "BumpBouy"; } // FUNCTION: LEGO1 0x10027500 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, BumpBouy::ClassName()) || LegoAnimActor::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 - virtual void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 // SYNTHETIC: LEGO1 0x10027490 // BumpBouy::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/carrace.h b/LEGO1/lego/legoomni/include/carrace.h index 776662db..c5af66e8 100644 --- a/LEGO1/lego/legoomni/include/carrace.h +++ b/LEGO1/lego/legoomni/include/carrace.h @@ -11,25 +11,25 @@ class CarRace : public LegoRace { CarRace(); // FUNCTION: LEGO1 0x10016b20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0528 return "CarRace"; } // FUNCTION: LEGO1 0x10016b30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, CarRace::ClassName()) || LegoRace::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual undefined4 VTable0x6c(undefined4) override; // vtable+0x6c - virtual undefined4 VTable0x70(undefined4) override; // vtable+0x70 - virtual undefined4 VTable0x74(undefined4) override; // vtable+0x74 - virtual undefined4 VTable0x78(undefined4) override; // vtable+0x78 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x64() override; // vtable+0x64 + undefined4 VTable0x6c(undefined4) override; // vtable+0x6c + undefined4 VTable0x70(undefined4) override; // vtable+0x70 + undefined4 VTable0x74(undefined4) override; // vtable+0x74 + undefined4 VTable0x78(undefined4) override; // vtable+0x78 // SYNTHETIC: LEGO1 0x10016c70 // CarRace::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/carracestate.h b/LEGO1/lego/legoomni/include/carracestate.h index 490900dd..c7a1e376 100644 --- a/LEGO1/lego/legoomni/include/carracestate.h +++ b/LEGO1/lego/legoomni/include/carracestate.h @@ -8,14 +8,14 @@ class CarRaceState : public RaceState { public: // FUNCTION: LEGO1 0x1000dd30 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f009c return "CarRaceState"; } // FUNCTION: LEGO1 0x1000dd40 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, CarRaceState::ClassName()) || RaceState::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/caveentity.h b/LEGO1/lego/legoomni/include/caveentity.h new file mode 100644 index 00000000..24b9759f --- /dev/null +++ b/LEGO1/lego/legoomni/include/caveentity.h @@ -0,0 +1,10 @@ +#ifndef CAVEENTITY_H +#define CAVEENTITY_H + +#include "racestandsentity.h" + +// No overrides, uses vtable from RaceStandsEntity +// SIZE 0x68 +class CaveEntity : public RaceStandsEntity {}; + +#endif // CAVEENTITY_H diff --git a/LEGO1/lego/legoomni/include/doors.h b/LEGO1/lego/legoomni/include/doors.h index dc98a866..35958455 100644 --- a/LEGO1/lego/legoomni/include/doors.h +++ b/LEGO1/lego/legoomni/include/doors.h @@ -8,21 +8,21 @@ class Doors : public LegoPathActor { public: // FUNCTION: LEGO1 0x1000e430 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03e8 return "Doors"; } // FUNCTION: LEGO1 0x1000e440 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Doors::ClassName()) || LegoPathActor::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxS32 VTable0x94() override; // vtable+0x94 + void ParseAction(char*) override; // vtable+0x20 + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x94() override; // vtable+0x94 // SYNTHETIC: LEGO1 0x1000e580 // Doors::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/dunebuggy.h b/LEGO1/lego/legoomni/include/dunebuggy.h index ca671955..27c0cdb5 100644 --- a/LEGO1/lego/legoomni/include/dunebuggy.h +++ b/LEGO1/lego/legoomni/include/dunebuggy.h @@ -11,24 +11,24 @@ class DuneBuggy : public IslePathActor { DuneBuggy(); // FUNCTION: LEGO1 0x10067c30 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0410 return "DuneBuggy"; } // FUNCTION: LEGO1 0x10067c40 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, DuneBuggy::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual MxU32 VTable0xdc(MxType19NotificationParam& p_param) override; // vtable+0xdc - virtual void VTable0xe4() override; // vtable+0xe4 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xdc(MxType19NotificationParam& p_param) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x10067dc0 // DuneBuggy::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/elevatorbottom.h b/LEGO1/lego/legoomni/include/elevatorbottom.h index 1f02d28f..bb28d710 100644 --- a/LEGO1/lego/legoomni/include/elevatorbottom.h +++ b/LEGO1/lego/legoomni/include/elevatorbottom.h @@ -2,46 +2,49 @@ #define ELEVATORBOTTOM_H #include "decomp.h" +#include "legogamestate.h" #include "legoworld.h" +class LegoControlManagerEvent; + // VTABLE: LEGO1 0x100d5f20 // SIZE: 0xfc (from inlined ctor at 0x1000a8aa) class ElevatorBottom : public LegoWorld { public: ElevatorBottom(); - virtual ~ElevatorBottom() override; // vtable+0x0 + ~ElevatorBottom() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10017f20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f04ac return "ElevatorBottom"; } // FUNCTION: LEGO1 0x10017f30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, ElevatorBottom::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 // FUNCTION: LEGO1 0x10017f10 - virtual MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x10018040 // ElevatorBottom::`scalar deleting destructor' private: - undefined4 m_unk0xf8; // 0xf8 + LegoGameState::Area m_unk0xf8; // 0xf8 - MxLong HandleNotification17(MxParam& p_param); + MxLong HandleClick(LegoControlManagerEvent& p_param); }; #endif // ELEVATORBOTTOM_H diff --git a/LEGO1/lego/legoomni/include/gasstation.h b/LEGO1/lego/legoomni/include/gasstation.h index 5f6c64f1..d2b133b5 100644 --- a/LEGO1/lego/legoomni/include/gasstation.h +++ b/LEGO1/lego/legoomni/include/gasstation.h @@ -2,55 +2,61 @@ #define GASSTATION_H #include "decomp.h" +#include "gasstationstate.h" +#include "legogamestate.h" #include "legoworld.h" #include "radio.h" // VTABLE: LEGO1 0x100d4650 // SIZE 0x128 -// Radio variable at 0x46, in constructor class GasStation : public LegoWorld { public: GasStation(); - virtual ~GasStation() override; // vtable+0x0 + ~GasStation() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10004780 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0168 return "GasStation"; } // FUNCTION: LEGO1 0x10004790 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, GasStation::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + virtual MxLong HandleClick(LegoControlManagerEvent& p_param); // vtable+0x6c // SYNTHETIC: LEGO1 0x100048a0 // GasStation::`scalar deleting destructor' private: - undefined2 m_unk0xf8; // 0xf8 - undefined2 m_unk0xfa; // 0xfa - undefined4 m_unk0xfc; // 0xfc - undefined4 m_unk0x100; // 0x100 - undefined2 m_unk0x104; // 0x104 - undefined2 m_unk0x106; // 0x106 - undefined4 m_unk0x108; // 0x108 - undefined4 m_unk0x10c; // 0x10c - undefined4 m_unk0x110; // 0x110 - undefined m_unk0x114; // 0x114 - undefined m_unk0x115; // 0x115 - Radio m_radio; // 0x118 + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleKeyPress(MxS8 p_key); + MxLong HandleButtonDown(LegoControlManagerEvent& p_param); + + undefined2 m_unk0xf8; // 0xf8 + undefined2 m_unk0xfa; // 0xfa + LegoGameState::Area m_transitionDestination; // 0xfc + GasStationState* m_state; // 0x100 + undefined2 m_unk0x104; // 0x104 + undefined2 m_unk0x106; // 0x106 + undefined4 m_unk0x108; // 0x108 + undefined4 m_unk0x10c; // 0x10c + undefined4 m_unk0x110; // 0x110 + undefined m_unk0x114; // 0x114 + undefined m_unk0x115; // 0x115 + Radio m_radio; // 0x118 }; #endif // GASSTATION_H diff --git a/LEGO1/lego/legoomni/include/gasstationentity.h b/LEGO1/lego/legoomni/include/gasstationentity.h index 7ab807cd..0b271d46 100644 --- a/LEGO1/lego/legoomni/include/gasstationentity.h +++ b/LEGO1/lego/legoomni/include/gasstationentity.h @@ -8,14 +8,14 @@ class GasStationEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000eb20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0348 return "GasStationEntity"; } // FUNCTION: LEGO1 0x1000eb30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, GasStationEntity::ClassName()) || BuildingEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/gasstationstate.h b/LEGO1/lego/legoomni/include/gasstationstate.h index 4f77e307..70ce41e8 100644 --- a/LEGO1/lego/legoomni/include/gasstationstate.h +++ b/LEGO1/lego/legoomni/include/gasstationstate.h @@ -7,34 +7,45 @@ // SIZE 0x24 class GasStationState : public LegoState { public: + // SIZE 0x04 + struct Unknown0x14 { + inline void SetUnknown0x00(undefined4 p_unk0x00) { m_unk0x00 = p_unk0x00; } + inline undefined4 GetUnknown0x00() { return m_unk0x00; } + + private: + undefined4 m_unk0x00; // 0x00 + }; + GasStationState(); // FUNCTION: LEGO1 0x100061d0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0174 return "GasStationState"; } // FUNCTION: LEGO1 0x100061e0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, GasStationState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c // SYNTHETIC: LEGO1 0x10006290 // GasStationState::`scalar deleting destructor' + inline Unknown0x14& GetUnknown0x14() { return m_unk0x14; } + private: - undefined4 m_unk0x08[3]; - undefined4 m_unk0x14; - undefined2 m_unk0x18; - undefined2 m_unk0x1a; - undefined2 m_unk0x1c; - undefined2 m_unk0x1e; - undefined2 m_unk0x20; + undefined4 m_unk0x08[3]; // 0x08 + Unknown0x14 m_unk0x14; // 0x14 + undefined2 m_unk0x18; // 0x18 + undefined2 m_unk0x1a; // 0x1a + undefined2 m_unk0x1c; // 0x1c + undefined2 m_unk0x1e; // 0x1e + undefined2 m_unk0x20; // 0x20 }; #endif // GASSTATIONSTATE_H diff --git a/LEGO1/lego/legoomni/include/gifmanager.h b/LEGO1/lego/legoomni/include/gifmanager.h deleted file mode 100644 index 898ab1fb..00000000 --- a/LEGO1/lego/legoomni/include/gifmanager.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef GIFMANAGER_H -#define GIFMANAGER_H - -#include "compat.h" -#include "decomp.h" -#include "mxstl/stlcompat.h" -#include "mxtypes.h" - -#include -#include - -#pragma warning(disable : 4237) - -// SIZE 0x14 -struct GifData { -public: - char* m_name; // 0x00 - LPDIRECTDRAWSURFACE m_surface; // 0x04 - LPDIRECTDRAWPALETTE m_palette; // 0x08 - LPDIRECT3DRMTEXTURE2 m_texture; // 0x0c - MxU8* m_data; // 0x10 - - ~GifData(); -}; - -struct GifMapComparator { - bool operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } -}; - -// SIZE 0x10 -class GifMap : public map { - // SYNTHETIC: LEGO1 0x1005a400 - // GifMap::~GifMap -}; - -typedef list GifList; - -// VTABLE: LEGO1 0x100d86d4 -// SIZE 0x18 -class GifManagerBase { -public: - // FUNCTION: LEGO1 0x1005b660 - virtual ~GifManagerBase() - { - GifMap::iterator it; - for (it = m_map.begin(); it != m_map.end(); it++) { - // DECOMP: Use of const_cast here matches ~ViewLODListManager from 96 source. - const char* const& key = (*it).first; - delete[] const_cast(key); - - if (m_ownership) { - delete (*it).second; // GifData* - } - } - } - - inline GifData* Get(const char* p_name) - { - GifMap::iterator it = m_map.find(p_name); - if (it != m_map.end()) { - return (*it).second; - } - - return NULL; - } - - // SYNTHETIC: LEGO1 0x1005a310 - // GifManagerBase::`scalar deleting destructor' - -protected: - MxBool m_ownership; // 0x04 - GifMap m_map; // 0x08 -}; - -// VTABLE: LEGO1 0x100d86fc -// SIZE 0x24 -class GifManager : public GifManagerBase { -public: - GifManager() { m_ownership = TRUE; }; - virtual ~GifManager() override; - - // SYNTHETIC: LEGO1 0x1005a580 - // GifManager::`scalar deleting destructor' - - void FUN_10099cc0(GifData* p_data); - -protected: - GifList m_list; // 0x18 -}; - -// TEMPLATE: LEGO1 0x10059c50 -// allocator::_Charalloc - -// clang-format off -// TEMPLATE: LEGO1 0x10001cc0 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Lbound - -// TEMPLATE: LEGO1 0x1004f9b0 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Insert - -// TEMPLATE: LEGO1 0x10059c70 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Color - -// TEMPLATE: LEGO1 0x10059c80 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Left - -// TEMPLATE: LEGO1 0x10059c90 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Parent - -// TEMPLATE: LEGO1 0x10059ca0 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Right - -// TEMPLATE: LEGO1 0x10059cb0 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::~_Tree,map >::_Kfn,GifMapComparator,allocator > - -// TEMPLATE: LEGO1 0x10059d80 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::iterator::_Inc - -// TEMPLATE: LEGO1 0x10059dc0 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::erase - -// TEMPLATE: LEGO1 0x1005a210 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Erase - -// TEMPLATE: LEGO1 0x1005a250 -// list >::~list > - -// TEMPLATE: LEGO1 0x1005a2c0 -// map >::~map > - -// TEMPLATE: LEGO1 0x1005a450 -// Map::~Map - -// TEMPLATE: LEGO1 0x1005a5a0 -// List::~List - -// GLOBAL: LEGO1 0x100f0100 -// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Nil -// clang-format on - -#endif // GIFMANAGER_H diff --git a/LEGO1/lego/legoomni/include/helicopter.h b/LEGO1/lego/legoomni/include/helicopter.h index e730fee4..6c917aec 100644 --- a/LEGO1/lego/legoomni/include/helicopter.h +++ b/LEGO1/lego/legoomni/include/helicopter.h @@ -12,7 +12,7 @@ class HelicopterSubclass { MxResult FUN_100040a0(Vector4& p_v, float p_f); private: - Mx4DPointFloat m_unk0x0; // 0x0 + Mx4DPointFloat m_unk0x00; // 0x00 Mx4DPointFloat m_unk0x18; // 0x18 undefined4 m_unk0x30; // 0x30 }; @@ -22,28 +22,28 @@ class HelicopterSubclass { class Helicopter : public IslePathActor { public: Helicopter(); - virtual ~Helicopter() override; // vtable+0x0 + ~Helicopter() override; // vtable+0x00 // FUNCTION: LEGO1 0x10003070 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0130 return "Helicopter"; } // FUNCTION: LEGO1 0x10003080 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Helicopter::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 - virtual void VTable0xe4() override; // vtable+0xe4 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x10003210 // Helicopter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/helicopterstate.h b/LEGO1/lego/legoomni/include/helicopterstate.h index eb104c93..993b8f7c 100644 --- a/LEGO1/lego/legoomni/include/helicopterstate.h +++ b/LEGO1/lego/legoomni/include/helicopterstate.h @@ -5,33 +5,40 @@ #include "legostate.h" // VTABLE: LEGO1 0x100d5418 -// SIZE 0xc +// SIZE 0x0c class HelicopterState : public LegoState { public: // FUNCTION: LEGO1 0x1000e0d0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0144 return "HelicopterState"; } // FUNCTION: LEGO1 0x1000e0e0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, HelicopterState::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool VTable0x14() override; // vtable+0x14 - virtual MxBool SetFlag() override; // vtable+0x18 + // FUNCTION: LEGO1 0x1000e0b0 + MxBool VTable0x14() override { return FALSE; } // vtable+0x14 - inline void SetUnknown8(MxU32 p_unk0x8) { m_unk0x8 = p_unk0x8; } - inline MxU32 GetUnkown8() { return m_unk0x8; } + // FUNCTION: LEGO1 0x1000e0c0 + MxBool SetFlag() override + { + m_unk0x08 = 0; + return TRUE; + } // vtable+0x18 + + inline void SetUnknown8(MxU32 p_unk0x08) { m_unk0x08 = p_unk0x08; } + inline MxU32 GetUnkown8() { return m_unk0x08; } // SYNTHETIC: LEGO1 0x1000e190 // HelicopterState::`scalar deleting destructor' protected: - MxU32 m_unk0x8; // 0x8 + MxU32 m_unk0x08; // 0x08 }; #endif // HELICOPTERSTATE_H diff --git a/LEGO1/lego/legoomni/include/historybook.h b/LEGO1/lego/legoomni/include/historybook.h index 172dde98..4e8c9501 100644 --- a/LEGO1/lego/legoomni/include/historybook.h +++ b/LEGO1/lego/legoomni/include/historybook.h @@ -1,36 +1,45 @@ #ifndef HISTORYBOOK_H #define HISTORYBOOK_H +#include "decomp.h" +#include "legogamestate.h" #include "legoworld.h" +#include "mxstillpresenter.h" // VTABLE: LEGO1 0x100da328 // SIZE 0x3e4 class HistoryBook : public LegoWorld { public: HistoryBook(); - virtual ~HistoryBook() override; // vtable+0x0 + ~HistoryBook() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10082390 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f04bc return "HistoryBook"; } // FUNCTION: LEGO1 0x100823a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, HistoryBook::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x64() override; // vtable+0x64 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x64() override; // vtable+0x64 // SYNTHETIC: LEGO1 0x100824b0 // HistoryBook::`scalar deleting destructor' + +private: + LegoGameState::Area m_transitionDestination; // 0xf8 + MxStillPresenter* m_alphabet[26]; // 0xfc + MxStillPresenter* m_names[20][7]; // 0x164 + MxStillPresenter* m_scores[20]; // 0x394 }; #endif // HISTORYBOOK_H diff --git a/LEGO1/lego/legoomni/include/hospital.h b/LEGO1/lego/legoomni/include/hospital.h index 3e88a58a..809e64e2 100644 --- a/LEGO1/lego/legoomni/include/hospital.h +++ b/LEGO1/lego/legoomni/include/hospital.h @@ -9,29 +9,29 @@ class Hospital : public LegoWorld { public: Hospital(); - virtual ~Hospital() override; // vtable+0x0 + ~Hospital() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 - virtual MxResult Tickle() override; // vtable+0x08 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x100746b0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0490 return "Hospital"; } // FUNCTION: LEGO1 0x100746c0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Hospital::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x100747d0 // Hospital::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/hospitalentity.h b/LEGO1/lego/legoomni/include/hospitalentity.h index fea461d8..a837bd7b 100644 --- a/LEGO1/lego/legoomni/include/hospitalentity.h +++ b/LEGO1/lego/legoomni/include/hospitalentity.h @@ -8,14 +8,14 @@ class HospitalEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000ec40 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0338 return "HospitalEntity"; } // FUNCTION: LEGO1 0x1000ec50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, HospitalEntity::ClassName()) || BuildingEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/hospitalstate.h b/LEGO1/lego/legoomni/include/hospitalstate.h index af876f89..980007e3 100644 --- a/LEGO1/lego/legoomni/include/hospitalstate.h +++ b/LEGO1/lego/legoomni/include/hospitalstate.h @@ -9,33 +9,34 @@ class HospitalState : public LegoState { public: HospitalState(); + ~HospitalState() override {} // FUNCTION: LEGO1 0x10076400 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0480 return "HospitalState"; } // FUNCTION: LEGO1 0x10076410 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, HospitalState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c // SYNTHETIC: LEGO1 0x100764c0 // HospitalState::`scalar deleting destructor' private: - undefined m_unk0x8[4]; // 0x8 - undefined2 m_unk0xc; // 0xc - undefined2 m_unk0xe; // 0xe - undefined2 m_unk0x10; // 0x10 - undefined2 m_unk0x12; // 0x12 - undefined2 m_unk0x14; // 0x14 - undefined2 m_unk0x16; // 0x16 + undefined m_unk0x08[4]; // 0x08 + undefined2 m_unk0x0c; // 0x0c + undefined2 m_unk0x0e; // 0x0e + undefined2 m_unk0x10; // 0x10 + undefined2 m_unk0x12; // 0x12 + undefined2 m_unk0x14; // 0x14 + undefined2 m_unk0x16; // 0x16 }; #endif // HOSPITALSTATE_H diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index 7de6ec45..e22314b2 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -1,17 +1,23 @@ #ifndef INFOCENTER_H #define INFOCENTER_H +#include "legogamestate.h" #include "legoworld.h" +#include "mxrect32.h" #include "radio.h" class InfocenterState; +class MxStillPresenter; +class LegoControlManagerEvent; // SIZE 0x18 -struct InfocenterUnkDataEntry { +struct InfocenterMapEntry { // FUNCTION: LEGO1 0x1006ec80 - InfocenterUnkDataEntry() {} + InfocenterMapEntry() {} - undefined m_pad[0x18]; + MxStillPresenter* m_presenter; // 0x00 + undefined4 m_unk0x04; // 0x04 + MxRect32 m_area; // 0x08 }; // VTABLE: LEGO1 0x100d9338 @@ -28,9 +34,54 @@ class Infocenter : public LegoWorld { e_goodEndMovie }; + enum Character { + e_noCharacter = 0, + e_pepper, + e_mama, + e_papa, + e_nick, + e_laura + }; + enum InfomainScript { c_noInfomain = -1, + c_leftArrowCtl = 1, + c_rightArrowCtl = 2, + c_infoCtl = 3, + c_doorCtl = 4, + c_boatCtl = 10, + c_raceCtl = 11, + c_pizzaCtl = 12, + c_gasCtl = 13, + c_medCtl = 14, + c_copCtl = 15, + c_bigInfoCtl = 16, + c_bookCtl = 17, + c_radioCtl = 18, + c_mamaCtl = 21, + c_papaCtl = 22, + c_pepperCtl = 23, + c_nickCtl = 24, + c_lauraCtl = 25, + + c_mamaSelected = 30, + c_papaSelected = 31, + c_pepperSelected = 32, + c_nickSelected = 33, + c_lauraSelected = 34, + + c_mamaMovie = 40, + c_papaMovie = 41, + c_pepperMovie = 42, + c_nickMovie = 43, + c_lauraMovie = 44, + + c_goToRegBook = 70, + c_goToRegBookRed = 71, + + c_unk499 = 499, + c_welcomeDialogue = 500, c_goodJobDialogue = 501, @@ -92,11 +143,28 @@ class Infocenter : public LegoWorld { c_noCDDialogueUnused1 = 552, c_noCDDialogueUnused2 = 553, + c_gasCtlDescription = 555, + c_medCtlDescription = 556, + c_infoCtlDescription = 557, + c_boatCtlDescription = 558, + c_copCtlDescription = 559, + c_pizzaCtlDescription = 560, + c_raceCtlDescription = 561, + c_leaveInfoCenterDialogue1 = 562, c_leaveInfoCenterDialogue2 = 563, c_leaveInfoCenterDialogue3 = 564, c_leaveInfoCenterDialogue4 = 565, + c_unk566 = 566, + c_unk567 = 567, + c_unk568 = 568, + + c_unk569 = 569, + c_unk570 = 570, + c_unk571 = 571, + c_unk572 = 572, + c_registerToContinueDialogue = 573, c_bricksterDialogue = 574, @@ -108,29 +176,29 @@ class Infocenter : public LegoWorld { }; Infocenter(); - virtual ~Infocenter() override; + ~Infocenter() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1006eb40 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f04ec return "Infocenter"; } // FUNCTION: LEGO1 0x1006eb50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Infocenter::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x1006ec60 // Infocenter::`scalar deleting destructor' @@ -141,16 +209,18 @@ class Infocenter : public LegoWorld { MxLong HandleKeyPress(MxS8 p_key); MxU8 HandleMouseMove(MxS32 p_x, MxS32 p_y); MxU8 HandleButtonUp(MxS32 p_x, MxS32 p_y); - MxU8 HandleNotification17(MxParam&); - MxLong HandleEndAction(MxParam& p_param); - MxLong HandleNotification0(MxParam&); + MxU8 HandleClick(LegoControlManagerEvent& p_param); + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleNotification0(MxNotificationParam& p_param); - void FUN_10070dc0(MxBool); - void FUN_10070e90(); + void UpdateFrameHot(MxBool p_display); + void Reset(); void PlayCutscene(Cutscene p_entityId, MxBool p_scale); void StopCutscene(); + void FUN_10070d10(MxS32 p_x, MxS32 p_y); + void StartCredits(); void StopCredits(); @@ -160,20 +230,20 @@ class Infocenter : public LegoWorld { void PlayBookAnimation(); void StopBookAnimation(); - InfomainScript m_currentInfomainScript; // 0xf8 - MxS16 m_unk0xfc; // 0xfc - InfocenterState* m_infocenterState; // 0x100 - undefined4 m_unk0x104; // 0x104 - Cutscene m_currentCutscene; // 0x108 - Radio m_radio; // 0x10c - undefined4 m_unk0x11c; // 0x11c - InfocenterUnkDataEntry m_entries[7]; // 0x120 - MxS16 m_unk0x1c8; // 0x1c8 - undefined4 m_unk0x1cc; // 0x1cc - MxS16 m_infoManDialogueTimer; // 0x1d0 - MxS16 m_bookAnimationTimer; // 0x1d2 - MxU16 m_unk0x1d4; // 0x1d4 - MxS16 m_unk0x1d6; // 0x1d6 + InfomainScript m_currentInfomainScript; // 0xf8 + MxS16 m_selectedCharacter; // 0xfc + InfocenterState* m_infocenterState; // 0x100 + LegoGameState::Area m_transitionDestination; // 0x104 + Cutscene m_currentCutscene; // 0x108 + Radio m_radio; // 0x10c + MxStillPresenter* m_unk0x11c; // 0x11c + InfocenterMapEntry m_mapAreas[7]; // 0x120 + MxS16 m_unk0x1c8; // 0x1c8 + MxStillPresenter* m_frameHotBitmap; // 0x1cc + MxS16 m_infoManDialogueTimer; // 0x1d0 + MxS16 m_bookAnimationTimer; // 0x1d2 + MxU16 m_unk0x1d4; // 0x1d4 + MxS16 m_unk0x1d6; // 0x1d6 }; #endif // INFOCENTER_H diff --git a/LEGO1/lego/legoomni/include/infocenterdoor.h b/LEGO1/lego/legoomni/include/infocenterdoor.h index 1890f0b1..eb86cc37 100644 --- a/LEGO1/lego/legoomni/include/infocenterdoor.h +++ b/LEGO1/lego/legoomni/include/infocenterdoor.h @@ -1,44 +1,49 @@ #ifndef INFOCENTERDOOR_H #define INFOCENTERDOOR_H +#include "legogamestate.h" #include "legoworld.h" +class LegoControlManagerEvent; + // VTABLE: LEGO1 0x100d72d8 // SIZE 0xfc class InfocenterDoor : public LegoWorld { public: InfocenterDoor(); - virtual ~InfocenterDoor(); // vtable+0x0 + ~InfocenterDoor() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100377b0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f049c return "InfocenterDoor"; } // FUNCTION: LEGO1 0x100377c0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, InfocenterDoor::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 // FUNCTION: LEGO1 0x100377a0 - virtual MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x100378d0 // InfocenterDoor::`scalar deleting destructor' private: - MxS32 m_unk0xf8; // 0xf8 + LegoGameState::Area m_unk0xf8; // 0xf8 + + MxLong HandleClick(LegoControlManagerEvent& p_param); }; #endif // INFOCENTERDOOR_H diff --git a/LEGO1/lego/legoomni/include/infocenterentity.h b/LEGO1/lego/legoomni/include/infocenterentity.h index 91fe03ff..85bcbce5 100644 --- a/LEGO1/lego/legoomni/include/infocenterentity.h +++ b/LEGO1/lego/legoomni/include/infocenterentity.h @@ -8,14 +8,14 @@ class InfoCenterEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000ea00 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f035c return "InfoCenterEntity"; } // FUNCTION: LEGO1 0x1000ea10 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, InfoCenterEntity::ClassName()) || BuildingEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/infocenterstate.h b/LEGO1/lego/legoomni/include/infocenterstate.h index 8314529f..d47f220e 100644 --- a/LEGO1/lego/legoomni/include/infocenterstate.h +++ b/LEGO1/lego/legoomni/include/infocenterstate.h @@ -2,6 +2,7 @@ #define INFOCENTERSTATE_H #include "decomp.h" +#include "legogamestate.h" #include "legostate.h" #include "mxstillpresenter.h" @@ -10,26 +11,32 @@ class InfocenterState : public LegoState { public: InfocenterState(); - virtual ~InfocenterState(); + ~InfocenterState() override; // FUNCTION: LEGO1 0x10071840 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f04dc return "InfocenterState"; } // FUNCTION: LEGO1 0x10071850 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, InfocenterState::ClassName()) || LegoState::IsA(p_name); } // FUNCTION: LEGO1 0x10071830 - virtual MxBool VTable0x14() override { return FALSE; } // vtable+0x14 + MxBool VTable0x14() override { return FALSE; } // vtable+0x14 - inline MxS16 GetInfocenterBufferSize() { return sizeof(m_buffer) / sizeof(m_buffer[0]); } - inline MxStillPresenter* GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } + inline MxS16 GetMaxNameLength() { return _countof(m_letters); } + inline MxStillPresenter* GetNameLetter(MxS32 p_index) { return m_letters[p_index]; } + inline MxBool HasRegistered() { return m_letters[0] != NULL; } + inline Playlist& GetExitDialogueAct1() { return m_exitDialogueAct1; } + inline Playlist& GetExitDialogueAct23() { return m_exitDialogueAct23; } + inline Playlist& GetReturnDialogue(LegoGameState::Act p_act) { return m_returnDialogue[p_act]; } + inline Playlist& GetLeaveDialogue(LegoGameState::Act p_act) { return m_leaveDialogue[p_act]; } + inline Playlist& GetBricksterDialogue() { return m_bricksterDialogue; } inline MxU32 GetUnknown0x74() { return m_unk0x74; } inline void SetUnknown0x74(MxU32 p_unk0x74) { m_unk0x74 = p_unk0x74; } @@ -38,37 +45,13 @@ class InfocenterState : public LegoState { // InfocenterState::`scalar deleting destructor' private: - // Members should be renamed with their offsets before use - /* - struct UnkStruct - { - undefined4 unk1; - undefined2 unk2; - undefined2 unk3; - undefined2 unk4; - }; - - undefined2 unk1; - undefined2 unk2; - undefined4 unk3; - undefined4 padding1; - void *unk4; - undefined2 unk5; - undefined2 unk6; - undefined2 unk7; - undefined2 padding2; - void *unk8; - undefined2 unk9; - undefined2 unk10; - undefined2 unk11; - undefined2 padding3; - UnkStruct unk12[6]; - undefined4 unk13; - */ - - undefined m_pad[0x6c]; - MxU32 m_unk0x74; // 0x74 - MxStillPresenter* m_buffer[7]; // 0x78 + Playlist m_exitDialogueAct1; // 0x08 + Playlist m_exitDialogueAct23; // 0x14 + Playlist m_returnDialogue[3]; // 0x20 + Playlist m_leaveDialogue[3]; // 0x44 + Playlist m_bricksterDialogue; // 0x68 + MxU32 m_unk0x74; // 0x74 + MxStillPresenter* m_letters[7]; // 0x78 }; #endif // INFOCENTERSTATE_H diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index 681e0337..f94e6832 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -20,35 +20,34 @@ class Act1State; // VTABLE: LEGO1 0x100d6fb8 // SIZE 0x140 -// Radio at 0x12c class Isle : public LegoWorld { public: Isle(); - virtual ~Isle() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + ~Isle() override; + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10030910 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0458 return "Isle"; } // FUNCTION: LEGO1 0x10030920 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Isle::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+50 - virtual void VTable0x58(MxCore* p_object) override; // vtable+58 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+50 + void Add(MxCore* p_object) override; // vtable+58 // FUNCTION: LEGO1 0x10030900 - virtual MxBool VTable0x5c() override { return TRUE; } // vtable+5c + MxBool VTable0x5c() override { return TRUE; } // vtable+5c // FUNCTION: LEGO1 0x10033170 - virtual void VTable0x60() override {} // vtable+60 - virtual MxBool VTable0x64() override; // vtable+64 - virtual void VTable0x68(MxBool p_add) override; // vtable+68 + void VTable0x60() override {} // vtable+60 + MxBool VTable0x64() override; // vtable+64 + void Enable(MxBool p_enable) override; // vtable+68 virtual void VTable0x6c(IslePathActor* p_actor); // vtable+6c inline void SetUnknown13c(MxU32 p_unk0x13c) { m_unk0x13c = p_unk0x13c; } diff --git a/LEGO1/lego/legoomni/include/isleactor.h b/LEGO1/lego/legoomni/include/isleactor.h index f9092363..c51946d3 100644 --- a/LEGO1/lego/legoomni/include/isleactor.h +++ b/LEGO1/lego/legoomni/include/isleactor.h @@ -6,22 +6,22 @@ // VTABLE: LEGO1 0x100d5178 class IsleActor : public LegoActor { public: - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1000e660 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f07dc return "IsleActor"; } // FUNCTION: LEGO1 0x1000e670 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, IsleActor::ClassName()) || LegoActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 }; // SYNTHETIC: LEGO1 0x1000e940 diff --git a/LEGO1/lego/legoomni/include/islepathactor.h b/LEGO1/lego/legoomni/include/islepathactor.h index e2944876..a7fabbfa 100644 --- a/LEGO1/lego/legoomni/include/islepathactor.h +++ b/LEGO1/lego/legoomni/include/islepathactor.h @@ -1,9 +1,9 @@ #ifndef ISLEPATHACTOR_H #define ISLEPATHACTOR_H +#include "legocontrolmanager.h" #include "legopathactor.h" #include "legoworld.h" -#include "mxtype17notificationparam.h" #include "mxtype18notificationparam.h" #include "mxtype19notificationparam.h" #include "mxtypes.h" @@ -15,31 +15,31 @@ class IslePathActor : public LegoPathActor { IslePathActor(); // FUNCTION: LEGO1 0x10002e10 - inline virtual ~IslePathActor() override { IslePathActor::Destroy(TRUE); } // vtable+0x0 + inline ~IslePathActor() override { IslePathActor::Destroy(TRUE); } // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10002ea0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0104 return "IslePathActor"; } // FUNCTION: LEGO1 0x10002eb0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, IslePathActor::ClassName()) || LegoPathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c // FUNCTION: LEGO1 0x10002e70 virtual MxU32 VTable0xcc() { return 0; } // vtable+0xcc // FUNCTION: LEGO1 0x10002df0 virtual MxU32 VTable0xd0() { return 0; } // vtable+0xd0 // FUNCTION: LEGO1 0x10002e80 - virtual MxU32 VTable0xd4(MxType17NotificationParam&) { return 0; } // vtable+0xd4 + virtual MxU32 VTable0xd4(LegoControlManagerEvent&) { return 0; } // vtable+0xd4 // FUNCTION: LEGO1 0x10002e90 virtual MxU32 VTable0xd8(MxType18NotificationParam&) { return 0; } // vtable+0xd8 // FUNCTION: LEGO1 0x10002e00 diff --git a/LEGO1/lego/legoomni/include/jetski.h b/LEGO1/lego/legoomni/include/jetski.h index c3136d80..b71e43cf 100644 --- a/LEGO1/lego/legoomni/include/jetski.h +++ b/LEGO1/lego/legoomni/include/jetski.h @@ -3,7 +3,7 @@ #include "decomp.h" #include "islepathactor.h" -#include "mxtype17notificationparam.h" +#include "legocontrolmanager.h" // VTABLE: LEGO1 0x100d9ec8 // SIZE 0x164 @@ -12,23 +12,23 @@ class Jetski : public IslePathActor { Jetski(); // FUNCTION: LEGO1 0x1007e430 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03d8 return "Jetski"; } // FUNCTION: LEGO1 0x1007e440 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Jetski::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam&) override; // vtable+0xd4 - virtual void VTable0xe4() override; // vtable+0xe4 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent&) override; // vtable+0xd4 + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x1007e5c0 // Jetski::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/jetskirace.h b/LEGO1/lego/legoomni/include/jetskirace.h index 9b16d9a7..4d039f70 100644 --- a/LEGO1/lego/legoomni/include/jetskirace.h +++ b/LEGO1/lego/legoomni/include/jetskirace.h @@ -8,17 +8,27 @@ class JetskiRace : public LegoRace { public: // FUNCTION: LEGO1 0x1000daf0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0530 return "JetskiRace"; } // FUNCTION: LEGO1 0x1000db00 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JetskiRace::ClassName()) || LegoRace::IsA(p_name); } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x64() override; // vtable+0x64 + undefined4 VTable0x6c(undefined4) override; // vtable+0x6c + undefined4 VTable0x70(undefined4) override; // vtable+0x70 + undefined4 VTable0x74(undefined4) override; // vtable+0x74 }; +// SYNTHETIC: LEGO1 0x1000f530 +// JetskiRace::`scalar deleting destructor' + #endif // JETSKIRACE_H diff --git a/LEGO1/lego/legoomni/include/jetskiracestate.h b/LEGO1/lego/legoomni/include/jetskiracestate.h index ccb60112..812a0a0f 100644 --- a/LEGO1/lego/legoomni/include/jetskiracestate.h +++ b/LEGO1/lego/legoomni/include/jetskiracestate.h @@ -8,14 +8,14 @@ class JetskiRaceState : public RaceState { public: // FUNCTION: LEGO1 0x1000dc40 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f00ac return "JetskiRaceState"; } // FUNCTION: LEGO1 0x1000dc50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JetskiRaceState::ClassName()) || RaceState::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/jukebox.h b/LEGO1/lego/legoomni/include/jukebox.h index 7ee46589..94728ee2 100644 --- a/LEGO1/lego/legoomni/include/jukebox.h +++ b/LEGO1/lego/legoomni/include/jukebox.h @@ -10,30 +10,31 @@ class JukeBox : public LegoWorld { public: JukeBox(); - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1005d6f0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f02cc return "JukeBox"; } // FUNCTION: LEGO1 0x1005d700 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x1005d810 // JukeBox::`scalar deleting destructor' + enum JukeBoxScript { e_mamaPapaBrickolini, e_jailUnused, @@ -65,29 +66,18 @@ class JukeBox : public LegoWorld { e_legoRadioReminder2, e_legoRadioRacingAd, - e_legoRadioNews1, e_legoRadioNews2, - e_legoRadioPizzaAd1, - e_legoRadioBricksterPSA, - e_legoRadioSports1, - e_legoRadioIntermission1, e_legoRadioIntermission2, - e_legoRadioPizzaAd2, - e_legoRadioWeatherReport, - e_legoRadioSports2, - e_legoRadioPizzaAd3, - e_legoRadioIntermission3, - e_legoRadioSuperStoreAd, e_legoRadioLuckyYou, diff --git a/LEGO1/lego/legoomni/include/jukeboxentity.h b/LEGO1/lego/legoomni/include/jukeboxentity.h index a0121eed..feb02ee3 100644 --- a/LEGO1/lego/legoomni/include/jukeboxentity.h +++ b/LEGO1/lego/legoomni/include/jukeboxentity.h @@ -8,25 +8,33 @@ class JukeBoxEntity : public LegoEntity { public: JukeBoxEntity(); - virtual ~JukeBoxEntity() override; // vtable+0x0 + ~JukeBoxEntity() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10085cc0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f02f0 return "JukeBoxEntity"; } // FUNCTION: LEGO1 0x10085cd0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JukeBoxEntity::ClassName()) || LegoEntity::IsA(p_name); } + void StartAction(); + void StopAction(MxU32 p_state); + + inline MxBool IsBackgroundAudioEnabled() { return m_audioEnabled; } + // SYNTHETIC: LEGO1 0x10085db0 // JukeBoxEntity::`scalar deleting destructor' + +protected: + MxBool m_audioEnabled; // 0x68 }; #endif // JUKEBOXENTITY_H diff --git a/LEGO1/lego/legoomni/include/jukeboxstate.h b/LEGO1/lego/legoomni/include/jukeboxstate.h index 8263e97c..a12c97e5 100644 --- a/LEGO1/lego/legoomni/include/jukeboxstate.h +++ b/LEGO1/lego/legoomni/include/jukeboxstate.h @@ -8,22 +8,30 @@ class JukeBoxState : public LegoState { public: // FUNCTION: LEGO1 0x1000f310 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f02bc return "JukeBoxState"; } // FUNCTION: LEGO1 0x1000f320 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JukeBoxState::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool VTable0x14() override; // vtable+0x14 + MxBool VTable0x14() override; // vtable+0x14 + + inline MxU32 IsActive() { return m_active; } + inline void SetActive(MxU32 p_active) { m_active = p_active; } + inline MxU32 GetState() { return m_state; } // SYNTHETIC: LEGO1 0x1000f3d0 // JukeBoxState::`scalar deleting destructor' + +protected: + MxU32 m_state; // 0x08 + MxU32 m_active; // 0x0c }; #endif // JUKEBOXSTATE_H diff --git a/LEGO1/lego/legoomni/include/lego3dwavepresenter.h b/LEGO1/lego/legoomni/include/lego3dwavepresenter.h index bf771d45..79be1834 100644 --- a/LEGO1/lego/legoomni/include/lego3dwavepresenter.h +++ b/LEGO1/lego/legoomni/include/lego3dwavepresenter.h @@ -1,6 +1,8 @@ #ifndef LEGO3DWAVEPRESENTER_H #define LEGO3DWAVEPRESENTER_H +#include "decomp.h" +#include "legounknown100d5778.h" #include "mxwavepresenter.h" // VTABLE: LEGO1 0x100d52b0 @@ -8,25 +10,29 @@ class Lego3DWavePresenter : public MxWavePresenter { public: // FUNCTION: LEGO1 0x1000d890 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f058c return "Lego3DWavePresenter"; } // FUNCTION: LEGO1 0x1000d8a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Lego3DWavePresenter::ClassName()) || MxWavePresenter::IsA(p_name); } - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 // SYNTHETIC: LEGO1 0x1000f4b0 // Lego3DWavePresenter::`scalar deleting destructor' + +private: + undefined m_unk0x6c[4]; // 0x6c + LegoUnknown100d5778 m_unk0x70; // 0x70 }; #endif // LEGO3DWAVEPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoact2.h b/LEGO1/lego/legoomni/include/legoact2.h index 4918fa76..dfedc85d 100644 --- a/LEGO1/lego/legoomni/include/legoact2.h +++ b/LEGO1/lego/legoomni/include/legoact2.h @@ -9,14 +9,14 @@ // SIZE 0x1154 class LegoAct2 : public LegoWorld { - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 - virtual MxResult Tickle() override; // vtable+0x08 - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual void VTable0x60() override; // vtable+0x60 - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + void VTable0x60() override; // vtable+0x60 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x1004fe20 // LegoAct2::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoact2state.h b/LEGO1/lego/legoomni/include/legoact2state.h index b2ae4b7e..8fcb4829 100644 --- a/LEGO1/lego/legoomni/include/legoact2state.h +++ b/LEGO1/lego/legoomni/include/legoact2state.h @@ -7,23 +7,31 @@ // SIZE 0x10 class LegoAct2State : public LegoState { public: + ~LegoAct2State() override {} + // FUNCTION: LEGO1 0x1000df80 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0428 return "LegoAct2State"; } // FUNCTION: LEGO1 0x1000df90 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoAct2State::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool VTable0x14() override; // vtable+0x14 + MxBool VTable0x14() override; // vtable+0x14 // SYNTHETIC: LEGO1 0x1000e040 // LegoAct2State::`scalar deleting destructor' + + inline undefined4 GetUnknown0x08() { return m_unk0x08; } + +private: + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c }; #endif // LEGOACT2STATE_H diff --git a/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h b/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h index 0cc18935..3dcbfecb 100644 --- a/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h @@ -10,25 +10,25 @@ class LegoActionControlPresenter : public MxMediaPresenter { public: inline LegoActionControlPresenter() { m_unk0x50 = Extra::ActionType::e_none; } - virtual ~LegoActionControlPresenter() override { Destroy(TRUE); }; // vtable+0x00 + ~LegoActionControlPresenter() override { Destroy(TRUE); } // vtable+0x00 // FUNCTION: LEGO1 0x1000d0e0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f05bc return "LegoActionControlPresenter"; } // FUNCTION: LEGO1 0x1000d0f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoActionControlPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 + void ReadyTickle() override; // vtable+0x18 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 virtual void Destroy(MxBool p_fromDestructor); // vtable+0x5c private: diff --git a/LEGO1/lego/legoomni/include/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h index 76beb249..114bf4bb 100644 --- a/LEGO1/lego/legoomni/include/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -2,6 +2,7 @@ #define LEGOACTOR_H #include "decomp.h" +#include "legocachesound.h" #include "legoentity.h" // VTABLE: LEGO1 0x100d6d68 @@ -9,42 +10,47 @@ class LegoActor : public LegoEntity { public: LegoActor(); - virtual ~LegoActor() override; + ~LegoActor() override; // FUNCTION: LEGO1 0x1002d210 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0124 return "LegoActor"; } // FUNCTION: LEGO1 0x1002d220 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoActor::ClassName()) || LegoEntity::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 - virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) override; // vtable+0x24 + void ParseAction(char*) override; // vtable+0x20 + void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) override; // vtable+0x24 // FUNCTION: LEGO1 0x10002cc0 virtual MxFloat VTable0x50() { return m_unk0x68; } // vtable+0x50 + // FUNCTION: LEGO1 0x10002cd0 virtual void VTable0x54(MxFloat p_unk0x68) { m_unk0x68 = p_unk0x68; } // vtable+0x54 + // FUNCTION: LEGO1 0x10002ce0 virtual void VTable0x58(MxFloat p_unk0x70) { m_unk0x70 = p_unk0x70; } // vtable+0x58 + // FUNCTION: LEGO1 0x10002cf0 virtual MxFloat VTable0x5c() { return m_unk0x70; } // vtable+0x5c + // FUNCTION: LEGO1 0x10002d00 virtual MxU8 VTable0x60() { return m_unk0x74; } // vtable+0x60 + // FUNCTION: LEGO1 0x10002d10 virtual void VTable0x64(MxU8 p_unk0x74) { m_unk0x74 = p_unk0x74; } // vtable+0x64 private: - MxFloat m_unk0x68; // 0x68 - undefined4 m_unk0x6c; // 0x6c - MxFloat m_unk0x70; // 0x70 - MxU8 m_unk0x74; // 0x74 + MxFloat m_unk0x68; // 0x68 + LegoCacheSound* m_sound; // 0x6c + MxFloat m_unk0x70; // 0x70 + MxU8 m_unk0x74; // 0x74 }; // SYNTHETIC: LEGO1 0x1002d300 diff --git a/LEGO1/lego/legoomni/include/legoactorpresenter.h b/LEGO1/lego/legoomni/include/legoactorpresenter.h index a9b8ae7e..9c3b35bf 100644 --- a/LEGO1/lego/legoomni/include/legoactorpresenter.h +++ b/LEGO1/lego/legoomni/include/legoactorpresenter.h @@ -7,24 +7,24 @@ // SIZE 0x50 class LegoActorPresenter : public LegoEntityPresenter { public: - virtual ~LegoActorPresenter() override{}; + ~LegoActorPresenter() override{}; // FUNCTION: LEGO1 0x1000cb10 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f06a4 return "LegoActorPresenter"; } // FUNCTION: LEGO1 0x1000cb20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoActorPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void ParseExtra() override; // vtable+0x30 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void ParseExtra() override; // vtable+0x30 }; // SYNTHETIC: LEGO1 0x1000cc30 diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index b81f2c72..31ee5a37 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -9,36 +9,41 @@ class LegoAnimationManager : public MxCore { public: LegoAnimationManager(); - virtual ~LegoAnimationManager() override; // vtable+0x0 + ~LegoAnimationManager() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1005ec80 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f7508 return "LegoAnimationManager"; } // FUNCTION: LEGO1 0x1005ec90 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); } + void FUN_1005ee80(MxBool); void FUN_1005ef10(); + void FUN_1005f0b0(); void FUN_1005f6d0(MxBool); - void FUN_1005f720(undefined4); + void FUN_1005f720(MxS32 p_scriptIndex); + void FUN_10061010(undefined4); void FUN_10064670(MxBool); - __declspec(dllexport) static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig); + static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig); // SYNTHETIC: LEGO1 0x1005ed10 // LegoAnimationManager::`scalar deleting destructor' private: void Init(); + + undefined m_unk0x08[0x4f8]; // 0x08 }; #endif // LEGOANIMATIONMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h index 790ee92c..c79c8043 100644 --- a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h @@ -9,30 +9,30 @@ class LegoAnimMMPresenter : public MxCompositePresenter { public: LegoAnimMMPresenter(); - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1004a950 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f046c return "LegoAnimMMPresenter"; } // FUNCTION: LEGO1 0x1004a960 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoAnimMMPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void DoneTickle() override; // vtable+0x2c - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void DoneTickle() override; // vtable+0x2c + void ParseExtra() override; // vtable+0x30 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 // SYNTHETIC: LEGO1 0x1004aa40 // LegoAnimMMPresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index a5aa2df3..7ae607fd 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -1,11 +1,11 @@ #ifndef LEGOANIMPRESENTER_H #define LEGOANIMPRESENTER_H +#include "anim/legoanim.h" #include "mxgeometry/mxgeometry3d.h" #include "mxvideopresenter.h" class LegoWorld; -class LegoMemoryStream; class LegoAnimClass; // VTABLE: LEGO1 0x100d90c8 @@ -13,40 +13,42 @@ class LegoAnimClass; class LegoAnimPresenter : public MxVideoPresenter { public: LegoAnimPresenter(); - virtual ~LegoAnimPresenter() override; + ~LegoAnimPresenter() override; // FUNCTION: LEGO1 0x10068530 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f071c return "LegoAnimPresenter"; } // FUNCTION: LEGO1 0x10068540 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoAnimPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual void PutFrame() override; // vtable+0x6c - virtual MxResult VTable0x88(MxStreamChunk* p_chunk); // vtable+0x88 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + virtual MxResult VTable0x88(MxStreamChunk* p_chunk); // vtable+0x88 - // 6 more virtual functions here + inline LegoAnim* GetAnimation() { return m_anim; } -private: + const char* GetActionObjectName(); + +protected: void Init(); void Destroy(MxBool p_fromDestructor); - LegoAnimClass* m_unk0x64; // 0x64 + LegoAnim* m_anim; // 0x64 undefined4 m_unk0x68; // 0x68 undefined4 m_unk0x6c; // 0x6c undefined4 m_unk0x70; // 0x70 @@ -73,41 +75,4 @@ class LegoAnimPresenter : public MxVideoPresenter { // SYNTHETIC: LEGO1 0x10068650 // LegoAnimPresenter::`scalar deleting destructor' -// VTABLE: LEGO1 0x100db768 -// SIZE 0x08 -class LegoAnimClassBase { -public: - LegoAnimClassBase(); - virtual ~LegoAnimClassBase(); - - virtual void VTable0x4(); // vtable+0x04 - virtual void VTable0x8(); // vtable+0x08 - virtual void VTable0xc(); // vtable+0x0c - - undefined4 m_unk0x4; // 0x04 -}; - -// SYNTHETIC: LEGO1 0x10099de0 -// LegoAnimClassBase::`scalar deleting destructor' - -// VTABLE: LEGO1 0x100db8d8 -// SIZE 0x18 -class LegoAnimClass : public LegoAnimClassBase { -public: - LegoAnimClass(); - virtual ~LegoAnimClass() override; - - virtual void VTable0x8() override; // vtable+0x08 - virtual void VTable0xc() override; // vtable+0x0c - virtual MxResult VTable0x10(LegoMemoryStream* p_stream, MxS32); // vtable+0x10 - - MxLong m_unk0x8; // 0x08 - undefined4 m_unk0xc; // 0x0c - undefined4 m_unk0x10; // 0x10 - undefined4 m_unk0x14; // 0x14 -}; - -// SYNTHETIC: LEGO1 0x100a0ba0 -// LegoAnimClass::`scalar deleting destructor' - #endif // LEGOANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legobackgroundcolor.h b/LEGO1/lego/legoomni/include/legobackgroundcolor.h index c11508bc..672e39be 100644 --- a/LEGO1/lego/legoomni/include/legobackgroundcolor.h +++ b/LEGO1/lego/legoomni/include/legobackgroundcolor.h @@ -7,8 +7,8 @@ // SIZE 0x30 class LegoBackgroundColor : public MxVariable { public: - __declspec(dllexport) LegoBackgroundColor(const char* p_key, const char* p_value); - virtual void SetValue(const char* p_colorString) override; + LegoBackgroundColor(const char* p_key, const char* p_value); + void SetValue(const char* p_colorString) override; private: float m_h; diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 969657ca..f6b5c0e6 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -1,6 +1,7 @@ #ifndef LEGOBUILDINGMANAGER_H #define LEGOBUILDINGMANAGER_H +#include "decomp.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6f50 @@ -8,26 +9,33 @@ class LegoBuildingManager : public MxCore { public: LegoBuildingManager(); - virtual ~LegoBuildingManager() override; + ~LegoBuildingManager() override; - virtual MxResult Tickle() override; // vtable+0x08 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1002f930 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f37d0 return "LegoBuildingManager"; } - __declspec(dllexport) static void configureLegoBuildingManager(MxS32); + static void configureLegoBuildingManager(MxS32); + static void SetCustomizeAnimFile(const char* p_value); void FUN_1002fa00(); + void FUN_1002fb30(); + void FUN_10030590(); // SYNTHETIC: LEGO1 0x1002f940 // LegoBuildingManager::`scalar deleting destructor' private: + static char* g_customizeAnimFile; + void Init(); + + undefined m_unk0x08[0x28]; // 0x08 }; #endif // LEGOBUILDINGMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legocachesound.h b/LEGO1/lego/legoomni/include/legocachesound.h index 5d587835..5843f5bc 100644 --- a/LEGO1/lego/legoomni/include/legocachesound.h +++ b/LEGO1/lego/legoomni/include/legocachesound.h @@ -1,33 +1,63 @@ #ifndef LEGOCACHESOUND_H #define LEGOCACHESOUND_H +#include "decomp.h" +#include "legounknown100d5778.h" #include "mxcore.h" +#include "mxstring.h" // VTABLE: LEGO1 0x100d4718 // SIZE 0x88 class LegoCacheSound : public MxCore { public: LegoCacheSound(); - virtual ~LegoCacheSound() override; // vtable+0x0 + ~LegoCacheSound() override; // vtable+0x00 // FUNCTION: LEGO1 0x10006580 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f01c4 return "LegoCacheSound"; } // FUNCTION: LEGO1 0x10006590 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoCacheSound::ClassName()) || MxCore::IsA(p_name); } + virtual MxResult FUN_10006710(); // vtable+0x14 + virtual void Destroy(); // vtable+0x18 + virtual void FUN_10006cd0(undefined4, undefined4); // vtable+0x1c + + inline const MxString& GetString0x48() const { return m_string0x48; } + inline const undefined GetUnk0x58() const { return m_unk0x58; } + + LegoCacheSound* FUN_10006960(); + MxResult FUN_10006a30(char* p_str, MxBool); + void FUN_10006b80(); + void FUN_10006be0(); + // SYNTHETIC: LEGO1 0x10006610 // LegoCacheSound::`scalar deleting destructor' private: void Init(); + + LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x08 + undefined m_unk0xc[4]; // 0x0c + LegoUnknown100d5778 m_unk0x10; // 0x10 + undefined* m_unk0x40; // 0x40 + undefined4 m_unk0x44; // 0x44 + MxString m_string0x48; // 0x48 + undefined m_unk0x58; // 0x58 + PCMWAVEFORMAT m_unk0x59; // 0x59 + MxBool m_isLooping; // 0x69 + MxBool m_unk0x6a; // 0x6a + undefined4 m_unk0x6c; // 0x6c + undefined m_unk0x70; // 0x70 + MxString m_string0x74; // 0x74 + undefined m_unk0x84; // 0x84 }; #endif // LEGOCACHESOUND_H diff --git a/LEGO1/lego/legoomni/include/legocachesoundlist.h b/LEGO1/lego/legoomni/include/legocachesoundlist.h new file mode 100644 index 00000000..25459911 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legocachesoundlist.h @@ -0,0 +1,104 @@ +#ifndef LEGOCACHESOUNDLIST_H +#define LEGOCACHESOUNDLIST_H + +#include "mxlist.h" +#include "mxtypes.h" + +class LegoCacheSound; + +// VTABLE: LEGO1 0x100d63b0 +// class MxCollection + +// VTABLE: LEGO1 0x100d63c8 +// class MxList + +// VTABLE: LEGO1 0x100d63e0 +// class MxPtrList + +// VTABLE: LEGO1 0x100d63f8 +// SIZE 0x18 +class LegoCacheSoundList : public MxPtrList { +public: + LegoCacheSoundList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} + + // FUNCTION: LEGO1 0x1001e650 + MxS8 Compare(LegoCacheSound* p_a, LegoCacheSound* p_b) override + { + return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; + } // vtable+0x14 +}; + +// VTABLE: LEGO1 0x100d64a0 +// class MxListCursor + +// VTABLE: LEGO1 0x100d6500 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d6518 +// SIZE 0x10 +class LegoCacheSoundListCursor : public MxPtrListCursor { +public: + LegoCacheSoundListCursor(LegoCacheSoundList* p_list) : MxPtrListCursor(p_list){}; +}; + +// TEMPLATE: LEGO1 0x1001e670 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1001e680 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1001e6d0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1001e6e0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x1001e770 +// MxPtrList::Destroy + +// SYNTHETIC: LEGO1 0x1001e780 +// LegoCacheSoundList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001e7f0 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x1001e840 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e8b0 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e960 +// MxPtrList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f350 +// LegoCacheSoundListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f3c0 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f410 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f480 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f4f0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001f540 +// LegoCacheSoundListCursor::~LegoCacheSoundListCursor + +// TEMPLATE: LEGO1 0x10020840 +// MxListCursor::MxListCursor + +// TEMPLATE: LEGO1 0x100224e0 +// MxList::InsertEntry + +// TEMPLATE: LEGO1 0x10022590 +// MxListCursor::Find + +// TEMPLATE: LEGO1 0x10022680 +// MxList::DeleteEntry + +#endif // LEGOCACHESOUNDLIST_H diff --git a/LEGO1/lego/legoomni/include/legocameracontroller.h b/LEGO1/lego/legoomni/include/legocameracontroller.h index 7d038d02..0032092b 100644 --- a/LEGO1/lego/legoomni/include/legocameracontroller.h +++ b/LEGO1/lego/legoomni/include/legocameracontroller.h @@ -12,19 +12,19 @@ class LegoCameraController : public LegoPointOfViewController { public: LegoCameraController(); - virtual ~LegoCameraController() override; // vtable+0x0 + ~LegoCameraController() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+04 + MxLong Notify(MxParam& p_param) override; // vtable+04 // FUNCTION: LEGO1 0x10011ec0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0850 return "LegoCameraController"; } // FUNCTION: LEGO1 0x10011ed0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 70db5856..03d0484d 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -8,29 +8,29 @@ class LegoCarBuild : public LegoWorld { public: LegoCarBuild(); - virtual ~LegoCarBuild() override; + ~LegoCarBuild() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10022940 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0504 return "LegoCarBuild"; } // FUNCTION: LEGO1 0x10022950 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoCarBuild::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x10022a60 // LegoCarBuild::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h index fb2d254d..fd5f8148 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h @@ -8,26 +8,26 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { public: LegoCarBuildAnimPresenter(); - virtual ~LegoCarBuildAnimPresenter() override; // vtable+0x0 + ~LegoCarBuildAnimPresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x10078510 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f05ec return "LegoCarBuildAnimPresenter"; } // FUNCTION: LEGO1 0x10078520 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoCarBuildAnimPresenter::ClassName()) || LegoAnimPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void EndAction() override; // vtable+0x40 - virtual void PutFrame() override; // vtable+0x6c + void ReadyTickle() override; // vtable+0x18 + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c // SYNTHETIC: LEGO1 0x10078660 // LegoCarBuildAnimPresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legocarraceactor.h b/LEGO1/lego/legoomni/include/legocarraceactor.h index 5f2756a3..3905be16 100644 --- a/LEGO1/lego/legoomni/include/legocarraceactor.h +++ b/LEGO1/lego/legoomni/include/legocarraceactor.h @@ -7,25 +7,25 @@ class LegoCarRaceActor : public LegoRaceActor { public: // FUNCTION: LEGO1 0x10081650 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0568 return "LegoCarRaceActor"; } // FUNCTION: LEGO1 0x10081670 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name); } - virtual void VTable0x68() override; // vtable+0x68 - virtual void VTable0x6c() override; // vtable+0x6c - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxS32 VTable0x90() override; // vtable+0x90 - virtual MxS32 VTable0x94() override; // vtable+0x94 - virtual void VTable0x98() override; // vtable+0x98 - virtual void VTable0x9c() override; // vtable+0x9c + void VTable0x68() override; // vtable+0x68 + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x90() override; // vtable+0x90 + MxS32 VTable0x94() override; // vtable+0x94 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c // SYNTHETIC: LEGO1 0x10081610 // LegoCarRaceActor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legocontrolmanager.h b/LEGO1/lego/legoomni/include/legocontrolmanager.h index 385ee92b..46719167 100644 --- a/LEGO1/lego/legoomni/include/legocontrolmanager.h +++ b/LEGO1/lego/legoomni/include/legocontrolmanager.h @@ -1,26 +1,60 @@ #ifndef LEGOCONTROLMANAGER_H #define LEGOCONTROLMANAGER_H +#include "legoeventnotificationparam.h" +#include "legoinputmanager.h" #include "mxcore.h" #include "mxpresenterlist.h" +class MxControlPresenter; + +// VTABLE: LEGO1 0x100d6a98 +// SIZE 0x2c +class LegoControlManagerEvent : public LegoEventNotificationParam { +public: + inline LegoControlManagerEvent() : LegoEventNotificationParam() + { + m_clickedObjectId = -1; + m_clickedAtom = NULL; + } + + inline MxS32 GetClickedObjectId() const { return m_clickedObjectId; } + inline const char* GetClickedAtom() const { return m_clickedAtom; } + inline MxS16 GetUnknown0x28() const { return m_unk0x28; } + + inline void SetClickedObjectId(MxS32 p_clickedObjectId) { m_clickedObjectId = p_clickedObjectId; } + inline void SetClickedAtom(const char* p_clickedAtom) { m_clickedAtom = p_clickedAtom; } + inline void SetUnknown0x28(MxS16 p_unk0x28) { m_unk0x28 = p_unk0x28; } + +private: + MxS32 m_clickedObjectId; // 0x20 + const char* m_clickedAtom; // 0x24 + MxS16 m_unk0x28; // 0x28 +}; + +// SYNTHETIC: LEGO1 0x10028bf0 +// LegoControlManagerEvent::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10028c60 +// LegoControlManagerEvent::~LegoControlManagerEvent + // VTABLE: LEGO1 0x100d6a80 class LegoControlManager : public MxCore { public: LegoControlManager(); - virtual ~LegoControlManager() override; // vtable+0x0 + ~LegoControlManager() override; // vtable+0x00 - virtual MxResult Tickle() override; // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10028cb0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f31b8 return "LegoControlManager"; } // FUNCTION: LEGO1 0x10028cc0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoControlManager::ClassName()) || MxCore::IsA(p_name); } @@ -28,10 +62,27 @@ class LegoControlManager : public MxCore { void FUN_10028df0(MxPresenterList* p_presenterList); void Register(MxCore* p_listener); void Unregister(MxCore* p_listener); + MxBool FUN_10029210(LegoEventNotificationParam& p_param, MxPresenter* p_presenter); void FUN_100293c0(undefined4, const char*, undefined2); + MxControlPresenter* FUN_100294e0(MxS32 p_x, MxS32 p_y); + MxBool FUN_10029630(); + MxBool FUN_10029750(); + void FUN_100292e0(); + + inline undefined4 GetUnknown0x0c() { return m_unk0x0c; } + inline undefined GetUnknown0x10() { return m_unk0x10; } // SYNTHETIC: LEGO1 0x10028d40 // LegoControlManager::`scalar deleting destructor' + +private: + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + MxBool m_unk0x10; // 0x10 + MxPresenter* m_unk0x14; // 0x14 + LegoControlManagerEvent m_event; // 0x18 + MxPresenterList* m_presenterList; // 0x44 + LegoNotifyList m_notifyList; // 0x48 }; #endif // LEGOCONTROLMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index b775f840..d0f64079 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -9,27 +9,23 @@ #include "roi/legoroi.h" // VTABLE: LEGO1 0x100d4858 -// SIZE 0x68 (probably) +// SIZE 0x68 class LegoEntity : public MxEntity { public: enum { - c_bit1 = 0x01 + c_bit1 = 0x01, + c_bit2 = 0x02 }; - // Inlined at 0x100853f7 inline LegoEntity() { Init(); } -#ifdef ISLE_APP - __declspec(dllexport) virtual ~LegoEntity() override; -#else // FUNCTION: LEGO1 0x1000c290 - __declspec(dllexport) virtual ~LegoEntity() override { Destroy(TRUE); } -#endif + ~LegoEntity() override { Destroy(TRUE); } - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1000c2f0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0064 return "LegoEntity"; @@ -41,27 +37,32 @@ class LegoEntity : public MxEntity { return !strcmp(p_name, LegoEntity::ClassName()) || MxEntity::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction); // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c - virtual void ParseAction(char*); // vtable+0x20 - virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 - virtual void SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, - const Vector3& p_up); // vtable+0x28 - virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c + virtual MxResult Create(MxDSAction& p_dsAction); // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c + virtual void ParseAction(char*); // vtable+0x20 + virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 + virtual void SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, const Vector3& p_up); // vtable+0x28 + virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c + // FUNCTION: LEGO1 0x10001090 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 - virtual void VTable0x34(); // vtable+0x34 - virtual void VTable0x38(); // vtable+0x38 - virtual void VTable0x3c(); // vtable+0x3c - virtual void VTable0x40(); // vtable+0x40 - virtual void VTable0x44(); // vtable+0x44 - virtual void VTable0x48(); // vtable+0x48 - virtual void VTable0x4c(); // vtable+0x4c + + virtual void VTable0x34(); // vtable+0x34 + virtual void VTable0x38(); // vtable+0x38 + virtual void VTable0x3c(); // vtable+0x3c + virtual void VTable0x40(); // vtable+0x40 + virtual void VTable0x44(); // vtable+0x44 + virtual void VTable0x48(); // vtable+0x48 + virtual void VTable0x4c(); // vtable+0x4c void FUN_10010c30(); + void FUN_100114e0(MxU8 p_unk0x59); void SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool); inline LegoROI* GetROI() { return m_roi; } + inline MxU8 GetFlags() { return m_flags; } + + inline void SetFlags(MxU8 p_flags) { m_flags = p_flags; } protected: void Init(); diff --git a/LEGO1/lego/legoomni/include/legoentitylist.h b/LEGO1/lego/legoomni/include/legoentitylist.h index 1d29e65d..938c85d4 100644 --- a/LEGO1/lego/legoomni/include/legoentitylist.h +++ b/LEGO1/lego/legoomni/include/legoentitylist.h @@ -22,10 +22,10 @@ class LegoEntityList : public MxPtrList { LegoEntityList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x1001e2d0 - virtual MxS8 Compare(LegoEntity* p_a, LegoEntity* p_b) override + MxS8 Compare(LegoEntity* p_a, LegoEntity* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; - }; // vtable+0x14 + } // vtable+0x14 }; // VTABLE: LEGO1 0x100d64e8 @@ -74,7 +74,7 @@ class LegoEntityListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x1001f110 // LegoEntityListCursor::`scalar deleting destructor' -// FUNCTION: LEGO1 0x1001f180 +// TEMPLATE: LEGO1 0x1001f180 // MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x1001f1d0 @@ -83,10 +83,19 @@ class LegoEntityListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x1001f240 // MxPtrListCursor::`scalar deleting destructor' -// FUNCTION: LEGO1 0x1001f2b0 +// TEMPLATE: LEGO1 0x1001f2b0 // MxListCursor::~MxListCursor -// FUNCTION: LEGO1 0x1001edc6 +// FUNCTION: LEGO1 0x1001f300 // LegoEntityListCursor::~LegoEntityListCursor +// TEMPLATE: LEGO1 0x100207d0 +// MxListCursor::MxListCursor + +// TEMPLATE: LEGO1 0x10022430 +// MxList::InsertEntry + +// TEMPLATE: LEGO1 0x10022630 +// MxList::DeleteEntry + #endif // LEGOENTITYLIST_H diff --git a/LEGO1/lego/legoomni/include/legoentitypresenter.h b/LEGO1/lego/legoomni/include/legoentitypresenter.h index 249e8b5c..dec78dae 100644 --- a/LEGO1/lego/legoomni/include/legoentitypresenter.h +++ b/LEGO1/lego/legoomni/include/legoentitypresenter.h @@ -10,10 +10,10 @@ class LegoEntity; class LegoEntityPresenter : public MxCompositePresenter { public: LegoEntityPresenter(); - virtual ~LegoEntityPresenter() override; // vtable+0x0 + ~LegoEntityPresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x100534b0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f06b8 return "LegoEntityPresenter"; @@ -25,16 +25,18 @@ class LegoEntityPresenter : public MxCompositePresenter { return !strcmp(p_name, LegoEntityPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual void Destroy() override; // vtable+0x38 - virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c - virtual void Init(); // vtable+0x68 - virtual undefined4 SetEntity(LegoEntity* p_entity); // vtable+0x6c + void ReadyTickle() override; // vtable+0x18 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + void Destroy() override; // vtable+0x38 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + virtual void Init(); // vtable+0x68 + virtual undefined4 SetEntity(LegoEntity* p_entity); // vtable+0x6c void SetEntityLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up); + inline LegoEntity* GetEntity() { return m_entity; } + // SYNTHETIC: LEGO1 0x100535a0 // LegoEntityPresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h index f5ec9205..a9c13632 100644 --- a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h +++ b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h @@ -3,6 +3,7 @@ #include "mxnotificationparam.h" #include "mxtypes.h" +#include "roi/legoroi.h" #include @@ -10,7 +11,14 @@ // SIZE 0x20 class LegoEventNotificationParam : public MxNotificationParam { public: - virtual MxNotificationParam* Clone() override; // vtable+0x4 + // FUNCTION: LEGO1 0x10028690 + MxNotificationParam* Clone() override + { + LegoEventNotificationParam* clone = + new LegoEventNotificationParam(m_type, m_sender, m_modifier, m_x, m_y, m_key); + clone->m_roi = m_roi; + return clone; + } // vtable+0x04 inline LegoEventNotificationParam() : MxNotificationParam(c_notificationType0, NULL) {} inline LegoEventNotificationParam( @@ -21,20 +29,27 @@ class LegoEventNotificationParam : public MxNotificationParam { MxS32 p_y, MxU8 p_key ) - : MxNotificationParam(p_type, p_sender), m_modifier(p_modifier), m_x(p_x), m_y(p_y), m_key(p_key), m_unk0x1c(0) + : MxNotificationParam(p_type, p_sender), m_modifier(p_modifier), m_x(p_x), m_y(p_y), m_key(p_key), m_roi(NULL) { } + inline MxU8 GetModifier() { return m_modifier; } inline MxU8 GetKey() const { return m_key; } inline MxS32 GetX() const { return m_x; } inline MxS32 GetY() const { return m_y; } + inline void SetROI(LegoROI* p_roi) { m_roi = p_roi; } + inline void SetModifier(MxU8 p_modifier) { m_modifier = p_modifier; } + inline void SetKey(MxU8 p_key) { m_key = p_key; } + inline void SetX(MxS32 p_x) { m_x = p_x; } + inline void SetY(MxS32 p_y) { m_y = p_y; } + protected: MxU8 m_modifier; // 0x0c MxS32 m_x; // 0x10 MxS32 m_y; // 0x14 MxU8 m_key; // 0x18 - MxU32 m_unk0x1c; // 0x1c + LegoROI* m_roi; // 0x1c }; // SYNTHETIC: LEGO1 0x10028770 diff --git a/LEGO1/lego/legoomni/include/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h index c4c76cee..87a0ab21 100644 --- a/LEGO1/lego/legoomni/include/legoextraactor.h +++ b/LEGO1/lego/legoomni/include/legoextraactor.h @@ -7,7 +7,7 @@ class LegoExtraActor : public LegoAnimActor { public: // FUNCTION: LEGO1 0x1002b7a0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f3204 return "LegoExtraActor"; diff --git a/LEGO1/lego/legoomni/include/legoflctexturepresenter.h b/LEGO1/lego/legoomni/include/legoflctexturepresenter.h index 9b136074..70f8a309 100644 --- a/LEGO1/lego/legoomni/include/legoflctexturepresenter.h +++ b/LEGO1/lego/legoomni/include/legoflctexturepresenter.h @@ -11,15 +11,15 @@ class LegoFlcTexturePresenter : public MxFlcPresenter { LegoFlcTexturePresenter(); // FUNCTION: LEGO1 0x1005def0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0634 return "LegoFlcTexturePresenter"; } - virtual void StartingTickle() override; // vtable+0x1c - virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 - virtual void PutFrame() override; // vtable+0x6c + void StartingTickle() override; // vtable+0x1c + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void PutFrame() override; // vtable+0x6c // SYNTHETIC: LEGO1 0x1005df00 // LegoFlcTexturePresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legofullscreenmovie.h b/LEGO1/lego/legoomni/include/legofullscreenmovie.h index f2cdaae4..2f2f7614 100644 --- a/LEGO1/lego/legoomni/include/legofullscreenmovie.h +++ b/LEGO1/lego/legoomni/include/legofullscreenmovie.h @@ -8,7 +8,7 @@ class LegoFullScreenMovie : public MxVariable { public: LegoFullScreenMovie(const char* p_key, const char* p_value); - virtual void SetValue(const char* p_option) override; + void SetValue(const char* p_option) override; }; #endif // LEGOFULLSCREENMOVIE_H diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index ae39654c..011fbf8a 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -4,8 +4,9 @@ #include "decomp.h" #include "legobackgroundcolor.h" #include "legofullscreenmovie.h" -#include "legostream.h" +#include "misc/legostorage.h" #include "mxtypes.h" +#include "mxvariabletable.h" class LegoState; class MxVariable; @@ -19,62 +20,160 @@ struct ColorStringStruct { // SIZE 0x430 class LegoGameState { public: - __declspec(dllexport) LegoGameState(); - __declspec(dllexport) ~LegoGameState(); - __declspec(dllexport) MxResult Load(MxULong); - __declspec(dllexport) MxResult Save(MxULong); - __declspec(dllexport) void SerializePlayersInfo(MxS16); - __declspec(dllexport) void SerializeScoreHistory(MxS16 p_flags); - __declspec(dllexport) void SetSavePath(char*); + enum Act { + e_actNotFound = -1, + e_act1, + e_act2, + e_act3 + }; + + enum Area { + e_noArea = 0, + e_previousArea = 0, + e_isle, + e_infomain, + e_infodoor, + e_unk4, + e_elevbott, + e_unk6, + e_unk7, + e_unk8, + e_unk9, + e_unk10, + e_unk11, + e_regbook, + e_infoscor, + e_jetrace, + e_unk15, + e_unk16, + e_unk17, + e_carrace, + e_unk19, + e_unk20, + e_unk21, + e_unk22, + + e_unk25 = 25, + e_garage, + e_unk27, + + e_unk29 = 29, + e_hospital, + e_unk31, + e_unk32, + + e_police = 34, + e_unk35, + e_copter, + e_dunecar, + e_jetski, + e_racecar, + + e_act2main = 46, + e_act3script, + + e_jukeboxw = 53, + + e_histbook = 56, + e_unk57, + e_unk58, + e_unk59, + e_unk60, + e_unk61, + + e_unk64 = 64, + + e_unk66 = 66 + }; + + // SIZE 0x0c + struct ScoreName { + ScoreName* operator=(const ScoreName* p_other); + + MxS16 m_letters[7]; // 0x00 + }; + + // SIZE 0x2c + struct ScoreItem { + undefined2 m_unk0x00; // 0x00 + MxU8 m_state[25]; // 0x02 + ScoreName m_name; // 0x1c + undefined2 m_unk0x2a; // 0x2a + }; + + // SIZE 0x372 + struct Scores { + void WriteScoreHistory(); + void FUN_1003ccf0(LegoFile&); + + inline ScoreItem* GetScore(MxS16 p_index) { return p_index >= m_count ? NULL : &m_scores[p_index]; } + + MxS16 m_count; // 0x00 + ScoreItem m_scores[20]; // 0x02 + }; + + LegoGameState(); + ~LegoGameState(); + + MxResult Load(MxULong); + MxResult Save(MxULong); + void SerializePlayersInfo(MxS16); + void SerializeScoreHistory(MxS16 p_flags); + void SetSavePath(char*); LegoState* GetState(const char* p_stateName); LegoState* CreateState(const char* p_stateName); void GetFileSavePath(MxString* p_outPath, MxULong p_slotn); - void FUN_1003a720(MxU32); - void HandleAction(MxU32); + void StopArea(Area p_area); + void SwitchArea(Area p_area); + + inline MxU8 GetUnknownC() { return m_unk0x0c; } + inline Act GetCurrentAct() { return m_currentAct; } + inline Act GetLoadedAct() { return m_loadedAct; } + inline Area GetCurrentArea() { return m_currentArea; } + inline Area GetPreviousArea() { return m_previousArea; } + inline MxU32 GetUnknown0x41c() { return m_unk0x41c; } + inline Area GetUnknown0x42c() { return m_unk0x42c; } + inline Scores* GetScores() { return &m_unk0xa6; } - inline MxU8 GetUnknownC() { return m_unk0xc; } - inline MxU32 GetUnknown10() { return m_unk0x10; } - inline MxS32 GetCurrentAct() { return m_currentAct; } - inline undefined4 GetUnknown424() { return m_unk0x424; } inline void SetDirty(MxBool p_dirty) { m_isDirty = p_dirty; } - inline void SetUnknown424(undefined4 p_unk0x424) { m_unk0x424 = p_unk0x424; } + inline void SetCurrentArea(Area p_currentArea) { m_currentArea = p_currentArea; } + inline void SetPreviousArea(Area p_previousArea) { m_previousArea = p_previousArea; } + inline void SetUnknown0x0c(MxU8 p_unk0x0c) { m_unk0x0c = p_unk0x0c; } + inline void SetUnknown0x41c(undefined4 p_unk0x41c) { m_unk0x41c = p_unk0x41c; } + inline void SetUnknown0x42c(Area p_unk0x42c) { m_unk0x42c = p_unk0x42c; } - void SetSomeEnumState(undefined4 p_state); - void FUN_1003ceb0(); + void SetCurrentAct(Act p_currentAct); + void FindLoadedAct(); void FUN_10039780(MxU8); - - struct ScoreStruct { - void WriteScoreHistory(); - void FUN_1003ccf0(LegoFileStream&); - - MxU16 m_unk0x00; - undefined m_unk0x02[0x2c][20]; - }; + void FUN_10039940(); private: void RegisterState(LegoState* p_state); - MxResult WriteEndOfVariables(LegoStream* p_stream); + MxResult WriteVariable(LegoStorage* p_stream, MxVariableTable* p_from, const char* p_variableName); + MxResult WriteEndOfVariables(LegoStorage* p_stream); + MxS32 ReadVariable(LegoStorage* p_stream, MxVariableTable* p_to); void SetROIHandlerFunction(); - char* m_savePath; // 0x0 - MxS16 m_stateCount; // 0x4 - LegoState** m_stateArray; // 0x8 - MxU8 m_unk0xc; // 0xc - MxU32 m_unk0x10; // 0x10 - MxS32 m_currentAct; // 0x14 + char* m_savePath; // 0x00 + MxS16 m_stateCount; // 0x04 + LegoState** m_stateArray; // 0x08 + MxU8 m_unk0x0c; // 0x0c + Act m_currentAct; // 0x10 + Act m_loadedAct; // 0x14 LegoBackgroundColor* m_backgroundColor; // 0x18 LegoBackgroundColor* m_tempBackgroundColor; // 0x1c LegoFullScreenMovie* m_fullScreenMovie; // 0x20 MxU16 m_unk0x24; // 0x24 - undefined m_unk0x28[128]; // 0x28 - ScoreStruct m_unk0xa6; // 0xa6 - undefined m_unk0x41a[8]; // 0x41a - might be part of the structure at 0xa6 + undefined m_unk0x26[128]; // 0x26 + Scores m_unk0xa6; // 0xa6 + undefined4 m_unk0x418; // 0x418 + undefined4 m_unk0x41c; // 0x41c MxBool m_isDirty; // 0x420 - undefined4 m_unk0x424; // 0x424 - undefined4 m_prevArea; // 0x428 - undefined4 m_unk0x42c; // 0x42c + Area m_currentArea; // 0x424 + Area m_previousArea; // 0x428 + Area m_unk0x42c; // 0x42c }; MxBool ROIHandlerFunction(char* p_input, char* p_output, MxU32 p_copyLen); diff --git a/LEGO1/lego/legoomni/include/legohideanimpresenter.h b/LEGO1/lego/legoomni/include/legohideanimpresenter.h index 06e8af33..37b8c475 100644 --- a/LEGO1/lego/legoomni/include/legohideanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legohideanimpresenter.h @@ -9,10 +9,10 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { public: LegoHideAnimPresenter(); - virtual ~LegoHideAnimPresenter() override; + ~LegoHideAnimPresenter() override; // FUNCTION: LEGO1 0x1006d880 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f06cc return "LegoHideAnimPresenter"; @@ -24,12 +24,12 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x18 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void EndAction() override; // vtable+0x40 - virtual void PutFrame() override; // vtable+0x6c + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x18 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c private: void Init(); diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 5198f71e..69a9dc64 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -12,6 +12,9 @@ class LegoControlManager; +extern MxS32 g_unk0x100f31b0; +extern const char* g_unk0x100f31b4; + // VTABLE: LEGO1 0x100d87b8 // class MxCollection @@ -25,30 +28,66 @@ class LegoControlManager; // SIZE 0x18 class LegoEventQueue : public MxQueue {}; +// VTABLE: LEGO1 0x100d6a20 +// class MxCollection + +// VTABLE: LEGO1 0x100d6a38 +// class MxList + +// VTABLE: LEGO1 0x100d6a50 +// class MxPtrList + +// VTABLE: LEGO1 0x100d6a68 +// SIZE 0x18 +class LegoNotifyList : public MxPtrList { +protected: + // FUNCTION: LEGO1 0x10028830 + MxS8 Compare(MxCore* p_element1, MxCore* p_element2) override + { + return p_element1 == p_element2 ? 0 : p_element1 < p_element2 ? -1 : 1; + } // vtable+0x14 + +public: + LegoNotifyList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} +}; + +// VTABLE: LEGO1 0x100d6ac0 +// class MxListCursor + +// VTABLE: LEGO1 0x100d6ad8 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d6aa8 +// SIZE 0x10 +class LegoNotifyListCursor : public MxPtrListCursor { +public: + LegoNotifyListCursor(LegoNotifyList* p_list) : MxPtrListCursor(p_list) {} +}; + // VTABLE: LEGO1 0x100d8760 // SIZE 0x338 class LegoInputManager : public MxPresenter { public: LegoInputManager(); - virtual ~LegoInputManager() override; + ~LegoInputManager() override; - __declspec(dllexport) void QueueEvent(NotificationId p_id, MxU8 p_modifier, MxLong p_x, MxLong p_y, MxU8 p_key); - __declspec(dllexport) void Register(MxCore*); - __declspec(dllexport) void UnRegister(MxCore*); + void QueueEvent(NotificationId p_id, MxU8 p_modifier, MxLong p_x, MxLong p_y, MxU8 p_key); + void Register(MxCore*); + void UnRegister(MxCore*); - virtual MxResult Tickle() override; // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1005b8c0 - virtual MxResult PutData() override { return SUCCESS; }; // vtable+0x4c + MxResult PutData() override { return SUCCESS; } // vtable+0x4c MxResult Create(HWND p_hwnd); - void Destroy(); + void Destroy() override; void CreateAndAcquireKeyboard(HWND p_hwnd); void ReleaseDX(); MxResult GetJoystickId(); MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, DWORD* p_buttonsState, MxU32* p_povPosition); - void SetTimer(); - void KillTimer(); + void StartAutoDragTimer(); + void StopAutoDragTimer(); void EnableInputProcessing(); void SetCamera(LegoCameraController* p_camera); void ClearCamera(); @@ -73,40 +112,89 @@ class LegoInputManager : public MxPresenter { void ProcessEvents(); MxBool ProcessOneEvent(LegoEventNotificationParam& p_param); + MxBool FUN_1005cdf0(LegoEventNotificationParam& p_param); // SYNTHETIC: LEGO1 0x1005b8d0 // LegoInputManager::`scalar deleting destructor' private: - MxCriticalSection m_criticalSection; - MxList* m_unk0x5c; // list or hash table - LegoCameraController* m_camera; - LegoWorld* m_world; - LegoEventQueue* m_eventQueue; // +0x68 - undefined4 m_unk0x6c; - undefined4 m_unk0x70; - undefined4 m_unk0x74; - UINT m_timer; - UINT m_timeout; - undefined m_unk0x80; - undefined m_unk0x81; - LegoControlManager* m_controlManager; - MxBool m_unk0x88; - IDirectInput* m_directInput; - IDirectInputDevice* m_directInputDevice; - undefined m_unk0x94; - undefined4 m_unk0x98; - undefined m_unk0x9c[0xF8]; - undefined m_unk0x194; - MxBool m_unk0x195; - MxS32 m_joyid; - MxS32 m_joystickIndex; - JOYCAPS m_joyCaps; - MxBool m_useJoystick; - MxBool m_unk0x335; - MxBool m_unk0x336; + MxCriticalSection m_criticalSection; // 0x58 + LegoNotifyList* m_keyboardNotifyList; // 0x5c + LegoCameraController* m_camera; // 0x60 + LegoWorld* m_world; // 0x64 + LegoEventQueue* m_eventQueue; // 0x68 + undefined4 m_unk0x6c; // 0x6c + undefined4 m_unk0x70; // 0x70 + undefined4 m_unk0x74; // 0x74 + UINT m_autoDragTimerID; // 0x78 + UINT m_autoDragTime; // 0x7c + undefined m_unk0x80; // 0x80 + undefined m_unk0x81; // 0x81 + LegoControlManager* m_controlManager; // 0x84 + MxBool m_unk0x88; // 0x88 + IDirectInput* m_directInput; // 0x8c + IDirectInputDevice* m_directInputDevice; // 0x90 + undefined m_unk0x94; // 0x94 + undefined4 m_unk0x98; // 0x98 + undefined m_unk0x9c[0xf8]; // 0x9c + undefined m_unk0x194; // 0x194 + MxBool m_unk0x195; // 0x195 + MxS32 m_joyid; // 0x198 + MxS32 m_joystickIndex; // 0x19c + JOYCAPS m_joyCaps; // 0x200 + MxBool m_useJoystick; // 0x334 + MxBool m_unk0x335; // 0x335 + MxBool m_unk0x336; // 0x336 }; +// TEMPLATE: LEGO1 0x10028850 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x10028860 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x100288b0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x100288c0 +// MxList::~MxList + +// SYNTHETIC: LEGO1 0x10028950 +// LegoNotifyList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x100289c0 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x10028a10 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10028a80 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10028b30 +// MxPtrList::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x10028ba0 +// LegoNotifyList::~LegoNotifyList + +// SYNTHETIC: LEGO1 0x10028fd0 +// LegoNotifyListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x10029040 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x10029090 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10029100 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x10029170 +// MxListCursor::~MxListCursor + +// TEMPLATE: LEGO1 0x100291c0 +// LegoNotifyListCursor::~LegoNotifyListCursor + // TEMPLATE: LEGO1 0x1005bb80 // MxCollection::Compare diff --git a/LEGO1/lego/legoomni/include/legojetski.h b/LEGO1/lego/legoomni/include/legojetski.h index ac376ab1..1ec0b9bb 100644 --- a/LEGO1/lego/legoomni/include/legojetski.h +++ b/LEGO1/lego/legoomni/include/legojetski.h @@ -6,10 +6,10 @@ // VTABLE: LEGO1 0x100d5a40 class LegoJetski : public LegoJetskiRaceActor { public: - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10013e80 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f053c return "LegoJetski"; @@ -21,13 +21,13 @@ class LegoJetski : public LegoJetskiRaceActor { return !strcmp(p_name, LegoJetski::ClassName()) || LegoJetskiRaceActor::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 - virtual void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - virtual void VTable0x6c() override; // vtable+0x6c - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxS32 VTable0x94() override; // vtable+0x94 - virtual void VTable0x98() override; // vtable+0x98 - virtual void VTable0x9c() override; // vtable+0x9c + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x94() override; // vtable+0x94 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c // SYNTHETIC: LEGO1 0x10013e20 // LegoJetski::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legojetskiraceactor.h b/LEGO1/lego/legoomni/include/legojetskiraceactor.h index 8b3a38c7..fd7d88bb 100644 --- a/LEGO1/lego/legoomni/include/legojetskiraceactor.h +++ b/LEGO1/lego/legoomni/include/legojetskiraceactor.h @@ -7,7 +7,7 @@ class LegoJetskiRaceActor : public LegoCarRaceActor { public: // FUNCTION: LEGO1 0x10081d80 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0554 return "LegoJetskiRaceActor"; @@ -19,10 +19,10 @@ class LegoJetskiRaceActor : public LegoCarRaceActor { return !strcmp(p_name, LegoJetskiRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); } - virtual void VTable0x6c() override; // vtable+0x6c - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual void VTable0x98() override; // vtable+0x98 - virtual void VTable0x9c() override; // vtable+0x9c + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c // SYNTHETIC: LEGO1 0x10081d40 // LegoJetskiRaceActor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h b/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h index dbfd478e..cb6ad80a 100644 --- a/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h +++ b/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h @@ -4,35 +4,37 @@ #include "decomp.h" #include "mxwavepresenter.h" +class LegoCacheSound; + // VTABLE: LEGO1 0x100d5fa8 // SIZE 0x90 class LegoLoadCacheSoundPresenter : public MxWavePresenter { public: LegoLoadCacheSoundPresenter(); - virtual ~LegoLoadCacheSoundPresenter() override; + ~LegoLoadCacheSoundPresenter() override; // FUNCTION: LEGO1 0x10018450 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f05a0 return "LegoLoadCacheSoundPresenter"; } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual MxResult PutData() override; // vtable+0x4c + void ReadyTickle() override; // vtable+0x18 + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + MxResult PutData() override; // vtable+0x4c private: void Init(); void Destroy(MxBool p_fromDestructor); - undefined4* m_unk0x6c; // 0x6c - undefined4* m_unk0x70; // 0x70 - undefined4 m_unk0x74; // 0x74 - undefined4 m_unk0x78; // 0x78 - undefined m_unk0x7c; // 0x7c - undefined4 m_unk0x80[4]; // 0x80 + LegoCacheSound* m_cacheSound; // 0x6c + undefined* m_unk0x70; // 0x70 + undefined* m_unk0x74; // 0x74 + undefined4 m_unk0x78; // 0x78 + undefined m_unk0x7c; // 0x7c + PCMWAVEFORMAT m_pcmWaveFormat; // 0x7d }; // SYNTHETIC: LEGO1 0x10018460 diff --git a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h index d6785fa2..2a78176d 100644 --- a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h @@ -4,12 +4,14 @@ #include "legoloopinganimpresenter.h" // VTABLE: LEGO1 0x100d9170 +// SIZE 0xd8 class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { public: LegoLocomotionAnimPresenter(); + ~LegoLocomotionAnimPresenter() override; // FUNCTION: LEGO1 0x1006ce50 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f06e4 return "LegoLocomotionAnimPresenter"; @@ -21,20 +23,37 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { return !strcmp(p_name, ClassName()) || LegoLoopingAnimPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void EndAction() override; // vtable+0x40 - virtual void PutFrame() override; // vtable+0x6c - virtual MxResult VTable0x88(MxStreamChunk* p_chunk) override; // vtable+0x88 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + MxResult VTable0x88(MxStreamChunk* p_chunk) override; // vtable+0x88 // SYNTHETIC: LEGO1 0x1006cfe0 // LegoLocomotionAnimPresenter::`scalar deleting destructor' + inline void DecrementUnknown0xd4() + { + if (m_unk0xd4) { + --m_unk0xd4; + } + } + + inline undefined2 GetUnknown0xd4() { return m_unk0xd4; } + private: void Init(); + void Destroy(MxBool p_fromDestructor); + + undefined4 m_unk0xc0; // 0xc0 + undefined4* m_unk0xc4; // 0xc4 + MxCore* m_unk0xc8; // 0xc8 + MxS32 m_unk0xcc; // 0xcc + MxS32 m_unk0xd0; // 0xd0 + undefined2 m_unk0xd4; // 0xd4 }; #endif // LEGOLOCOMOTIONANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h index d4f47d7e..50815015 100644 --- a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h @@ -8,7 +8,7 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { public: // FUNCTION: LEGO1 0x1000c9a0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0700 return "LegoLoopingAnimPresenter"; @@ -20,8 +20,8 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); } - virtual void StreamingTickle() override; // vtable+0x20 - virtual void PutFrame() override; // vtable+0x6c + void StreamingTickle() override; // vtable+0x20 + void PutFrame() override; // vtable+0x6c }; // SYNTHETIC: LEGO1 0x1006d000 diff --git a/LEGO1/lego/legoomni/include/legometerpresenter.h b/LEGO1/lego/legoomni/include/legometerpresenter.h index 33c7aa37..378c0574 100644 --- a/LEGO1/lego/legoomni/include/legometerpresenter.h +++ b/LEGO1/lego/legoomni/include/legometerpresenter.h @@ -8,13 +8,13 @@ class LegoMeterPresenter : public MxStillPresenter { public: LegoMeterPresenter(); - virtual ~LegoMeterPresenter() override; + ~LegoMeterPresenter() override; // MxStillPresenter's `::ClassName` and `::IsA` are used. - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 private: void FUN_10043a50(); diff --git a/LEGO1/lego/legoomni/include/legomodelpresenter.h b/LEGO1/lego/legoomni/include/legomodelpresenter.h index 7803187a..b85c2c26 100644 --- a/LEGO1/lego/legoomni/include/legomodelpresenter.h +++ b/LEGO1/lego/legoomni/include/legomodelpresenter.h @@ -3,14 +3,19 @@ #include "mxvideopresenter.h" +class LegoROI; + // VTABLE: LEGO1 0x100d4e50 // SIZE 0x6c (discovered through inline constructor at 0x10009ae6) class LegoModelPresenter : public MxVideoPresenter { public: - __declspec(dllexport) static void configureLegoModelPresenter(MxS32 p_modelPresenterConfig); + // inline in scalar dtor + ~LegoModelPresenter() override { Destroy(TRUE); } + + static void configureLegoModelPresenter(MxS32 p_modelPresenterConfig); // FUNCTION: LEGO1 0x1000ccb0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f067c return "LegoModelPresenter"; @@ -22,9 +27,9 @@ class LegoModelPresenter : public MxVideoPresenter { return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void ParseExtra() override; // vtable+0x30 - virtual void Destroy() override; // vtable+0x38 + void ReadyTickle() override; // vtable+0x18 + void ParseExtra() override; // vtable+0x30 + void Destroy() override; // vtable+0x38 // SYNTHETIC: LEGO1 0x1000cdd0 // LegoModelPresenter::`scalar deleting destructor' @@ -33,8 +38,10 @@ class LegoModelPresenter : public MxVideoPresenter { void Destroy(MxBool p_fromDestructor); private: - undefined4 m_unk0x64; // 0x64 + LegoROI* m_roi; // 0x64 MxBool m_addedToView; // 0x68 + + MxResult CreateROI(MxStreamChunk* p_chunk); }; #endif // LEGOMODELPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h index dd2a46ad..58ace217 100644 --- a/LEGO1/lego/legoomni/include/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -9,7 +9,7 @@ // SIZE 0x70 class LegoNavController : public MxCore { public: - __declspec(dllexport) static void GetDefaults( + static void GetDefaults( int* p_mouseDeadzone, float* p_movementMaxSpeed, float* p_turnMaxSpeed, @@ -22,7 +22,7 @@ class LegoNavController : public MxCore { float* p_rotationSensitivity, MxBool* p_turnUseVelocity ); - __declspec(dllexport) static void SetDefaults( + static void SetDefaults( int p_mouseDeadzone, float p_movementMaxSpeed, float p_turnMaxSpeed, @@ -37,11 +37,11 @@ class LegoNavController : public MxCore { ); LegoNavController(); - virtual ~LegoNavController() override; // vtable+0x0 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + ~LegoNavController() override; // vtable+0x00 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10054b80 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f66d8 return "LegoNavController"; diff --git a/LEGO1/lego/legoomni/include/legoobjectfactory.h b/LEGO1/lego/legoomni/include/legoobjectfactory.h index 9357ce34..a99efec2 100644 --- a/LEGO1/lego/legoomni/include/legoobjectfactory.h +++ b/LEGO1/lego/legoomni/include/legoobjectfactory.h @@ -4,17 +4,17 @@ #include "mxobjectfactory.h" #define FOR_LEGOOBJECTFACTORY_OBJECTS(X) \ - X(LegoModelPresenter) \ - X(LegoTexturePresenter) \ - X(LegoPhonemePresenter) \ - X(LegoFlcTexturePresenter) \ X(LegoEntityPresenter) \ X(LegoActorPresenter) \ X(LegoWorldPresenter) \ X(LegoWorld) \ + X(LegoAnimPresenter) \ + X(LegoModelPresenter) \ + X(LegoTexturePresenter) \ + X(LegoPhonemePresenter) \ + X(LegoFlcTexturePresenter) \ X(LegoPalettePresenter) \ X(LegoPathPresenter) \ - X(LegoAnimPresenter) \ X(LegoLoopingAnimPresenter) \ X(LegoLocomotionAnimPresenter) \ X(LegoHideAnimPresenter) \ @@ -28,7 +28,7 @@ X(LegoPathActor) \ X(LegoRaceCar) \ X(LegoJetski) \ - /*X(JetskiRace) \*/ \ + X(JetskiRace) \ X(LegoEntity) \ X(LegoCarRaceActor) \ X(LegoJetskiRaceActor) \ @@ -48,7 +48,7 @@ X(GasStation) \ X(LegoAct2) \ X(LegoAct2State) \ - /*X(CarRace)*/ \ + X(CarRace) \ X(HospitalState) \ X(InfocenterState) \ X(PoliceState) \ @@ -93,7 +93,7 @@ X(RaceStandsEntity) \ X(JukeBoxEntity) \ X(RadioState) \ - /*X(CaveEntity)*/ \ + X(CaveEntity) \ /*X(JailEntity)*/ \ X(MxCompositeMediaPresenter) \ X(JukeBox) \ @@ -105,12 +105,15 @@ class LegoObjectFactory : public MxObjectFactory { public: LegoObjectFactory(); - virtual MxCore* Create(const char* p_name) override; // vtable 0x14 - virtual void Destroy(MxCore* p_object) override; // vtable 0x18 + MxCore* Create(const char* p_name) override; // vtable 0x14 + void Destroy(MxCore* p_object) override; // vtable 0x18 // SYNTHETIC: LEGO1 0x10009000 // LegoObjectFactory::`scalar deleting destructor' + // SYNTHETIC: LEGO1 0x10009170 + // LegoObjectFactory::~LegoObjectFactory + private: #define X(V) MxAtomId m_id##V; FOR_LEGOOBJECTFACTORY_OBJECTS(X) diff --git a/LEGO1/lego/legoomni/include/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h index d7d9a2d4..a8b27b4d 100644 --- a/LEGO1/lego/legoomni/include/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -5,7 +5,7 @@ #include "mxdsaction.h" #include "mxomni.h" -class GifManager; +class LegoTextureContainer; class Isle; class IslePathActor; class LegoAnimationManager; @@ -28,6 +28,7 @@ class MxBackgroundAudioManager; class MxDSFile; class MxTransitionManager; class ViewLODListManager; +class ViewManager; extern MxAtomId* g_copterScript; extern MxAtomId* g_dunecarScript; @@ -68,50 +69,151 @@ class LegoOmni : public MxOmni { c_clearScreen = 0x04 }; - __declspec(dllexport) void CreateBackgroundAudio(); - __declspec(dllexport) void RemoveWorld(const MxAtomId&, MxLong); - __declspec(dllexport) static int GetCurrPathInfo(LegoPathBoundary**, MxS32&); - __declspec(dllexport) static void CreateInstance(); - __declspec(dllexport) static LegoOmni* GetInstance(); + // SIZE 0x1c + struct ScriptContainer { + // FUNCTION: LEGO1 0x1005ac40 + ScriptContainer() + { + m_index = -1; + m_script = NULL; + } + + ScriptContainer(MxS32 p_index, const char* p_key, MxAtomId* p_script) + { + m_index = p_index; + + if (p_key) { + strcpy(m_key, p_key); + } + + m_script = p_script; + } + + // FUNCTION: LEGO1 0x1005ac50 + ScriptContainer& operator=(const ScriptContainer& p_container) + { + m_index = p_container.m_index; + strcpy(m_key, p_container.m_key); + m_script = p_container.m_script; + return *this; + } + + inline MxS32 GetIndex() { return m_index; } + inline const char* GetKey() { return m_key; } + + private: + MxS32 m_index; // 0x00 + char m_key[20]; // 0x04 + MxAtomId* m_script; // 0x18 + }; + + // SIZE 0x38 + struct PathContainer { + PathContainer() {} + + // FUNCTION: LEGO1 0x1001b1b0 + PathContainer( + undefined4 p_unk0x00, + MxAtomId* p_script, + undefined4 p_unk0x04, + const char* p_key, + undefined2 p_unk0x20, + float p_unk0x24, + undefined2 p_unk0x28, + float p_unk0x2c, + undefined4 p_unk0x30, + MxS32 p_unk0x34 + ) + { + m_unk0x00 = p_unk0x00; + m_script = p_script; + m_unk0x04 = p_unk0x04; + strcpy(m_key, p_key); + m_unk0x20 = p_unk0x20; + m_unk0x24 = p_unk0x24; + m_unk0x28 = p_unk0x28; + m_unk0x2c = p_unk0x2c; + m_unk0x30 = p_unk0x30; + m_unk0x34 = p_unk0x34; + } + + // FUNCTION: LEGO1 0x1001b230 + PathContainer& operator=(const PathContainer& p_container) + { + m_unk0x00 = p_container.m_unk0x00; + m_script = p_container.m_script; + m_unk0x04 = p_container.m_unk0x04; + strcpy(m_key, p_container.m_key); + m_unk0x20 = p_container.m_unk0x20; + m_unk0x24 = p_container.m_unk0x24; + m_unk0x28 = p_container.m_unk0x28; + m_unk0x2c = p_container.m_unk0x2c; + m_unk0x30 = p_container.m_unk0x30; + m_unk0x34 = p_container.m_unk0x34; + return *this; + } + + private: + undefined4 m_unk0x00; // 0x00 + MxAtomId* m_script; // 0x04 + undefined4 m_unk0x04; // 0x08 + char m_key[20]; // 0x0c + undefined2 m_unk0x20; // 0x20 + float m_unk0x24; // 0x24 + undefined2 m_unk0x28; // 0x28 + float m_unk0x2c; // 0x2c + undefined4 m_unk0x30; // 0x30 + MxS32 m_unk0x34; // 0x34 + }; LegoOmni(); - virtual ~LegoOmni(); // vtable+00 + ~LegoOmni() override; // vtable+00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+04 + MxLong Notify(MxParam& p_param) override; // vtable+04 // FUNCTION: LEGO1 0x10058aa0 - inline virtual const char* ClassName() const override // vtable+0c + inline const char* ClassName() const override // vtable+0c { // STRING: LEGO1 0x100f671c return "LegoOmni"; } // FUNCTION: LEGO1 0x10058ab0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+10 + inline MxBool IsA(const char* p_name) const override // vtable+10 { return !strcmp(p_name, LegoOmni::ClassName()) || MxOmni::IsA(p_name); } - virtual void Init() override; // vtable+14 - virtual MxResult Create(MxOmniCreateParam& p_param) override; // vtable+18 - virtual void Destroy() override; // vtable+1c - virtual MxResult Start(MxDSAction* p_dsAction) override; // vtable+20 - virtual void DeleteObject(MxDSAction& p_dsAction) override; // vtable+24 - virtual MxBool DoesEntityExist(MxDSAction& p_dsAction) override; // vtable+28 - virtual MxEntity* FindWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) override; // vtable+30 - virtual void NotifyCurrentEntity(MxNotificationParam* p_param) override; // vtable+34 - virtual void StartTimer() override; // vtable+38 - virtual void StopTimer() override; // vtable+3c + void Init() override; // vtable+14 + MxResult Create(MxOmniCreateParam& p_param) override; // vtable+18 + void Destroy() override; // vtable+1c + MxResult Start(MxDSAction* p_dsAction) override; // vtable+20 + void DeleteObject(MxDSAction& p_dsAction) override; // vtable+24 + MxBool DoesEntityExist(MxDSAction& p_dsAction) override; // vtable+28 + MxEntity* AddToWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) override; // vtable+30 + void NotifyCurrentEntity(MxNotificationParam* p_param) override; // vtable+34 + void StartTimer() override; // vtable+38 + void StopTimer() override; // vtable+3c - LegoEntity* FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid); + LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid); + LegoROI* FindROI(const char* p_name); void AddWorld(LegoWorld* p_world); + void DeleteWorld(LegoWorld* p_world); void FUN_1005b4f0(MxBool p_disable, MxU16 p_flags); + void CreateBackgroundAudio(); + void RemoveWorld(const MxAtomId&, MxLong); + MxResult RegisterScripts(); + MxS32 GetScriptIndex(const char* p_key); + + static MxS32 GetCurrPathInfo(LegoPathBoundary**, MxS32&); + static void CreateInstance(); + static LegoOmni* GetInstance(); LegoVideoManager* GetVideoManager() { return (LegoVideoManager*) m_videoManager; } LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } - LegoInputManager* GetInputManager() { return m_inputMgr; } - GifManager* GetGifManager() { return m_gifManager; } - LegoWorld* GetCurrentOmniWorld() { return m_currentWorld; } + LegoInputManager* GetInputManager() { return m_inputManager; } + LegoTextureContainer* GetTextureContainer() { return m_textureContainer; } + LegoWorld* GetCurrentWorld() { return m_currentWorld; } LegoNavController* GetNavController() { return m_navController; } IslePathActor* GetCurrentVehicle() { return m_currentVehicle; } LegoPlantManager* GetLegoPlantManager() { return m_plantManager; } @@ -122,10 +224,11 @@ class LegoOmni : public MxOmni { MxTransitionManager* GetTransitionManager() { return m_transitionManager; } MxDSAction& GetCurrentAction() { return m_action; } LegoUnkSaveDataWriter* GetUnkSaveDataWriter() { return m_saveDataWriter; } + LegoWorldList* GetWorldList() { return m_worldList; } inline void SetNavController(LegoNavController* p_navController) { m_navController = p_navController; } - inline void SetWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } - inline void SetExit(MxBool p_exit) { m_exit = p_exit; }; + inline void SetCurrentWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } + inline void SetExit(MxBool p_exit) { m_exit = p_exit; } inline void CloseMainWindow() { PostMessageA(m_windowHandle, WM_CLOSE, 0, 0); } @@ -133,10 +236,10 @@ class LegoOmni : public MxOmni { // LegoOmni::`scalar deleting destructor' private: - undefined4* m_unk0x68; // 0x68 + ScriptContainer* m_scripts; // 0x68 ViewLODListManager* m_viewLODListManager; // 0x6c - LegoInputManager* m_inputMgr; // 0x70 - GifManager* m_gifManager; // 0x74 + LegoInputManager* m_inputManager; // 0x70 + LegoTextureContainer* m_textureContainer; // 0x74 LegoWorldList* m_worldList; // 0x78 LegoWorld* m_currentWorld; // 0x7c MxBool m_exit; // 0x80 @@ -153,35 +256,37 @@ class LegoOmni : public MxOmni { MxBool m_unk0x13c; // 0x13c }; -__declspec(dllexport) MxBackgroundAudioManager* BackgroundAudioManager(); -__declspec(dllexport) LegoGameState* GameState(); -__declspec(dllexport) const char* GetNoCD_SourceName(); -__declspec(dllexport) LegoInputManager* InputManager(); -__declspec(dllexport) LegoOmni* Lego(); -__declspec(dllexport) LegoEntity* PickEntity(MxLong, MxLong); -__declspec(dllexport) LegoROI* PickROI(MxLong, MxLong); -__declspec(dllexport) LegoSoundManager* SoundManager(); -__declspec(dllexport) MxTransitionManager* TransitionManager(); -__declspec(dllexport) LegoVideoManager* VideoManager(); - +MxBackgroundAudioManager* BackgroundAudioManager(); +LegoGameState* GameState(); +const char* GetNoCD_SourceName(); +LegoInputManager* InputManager(); +LegoOmni* Lego(); +LegoEntity* PickEntity(MxLong, MxLong); +LegoROI* PickROI(MxLong, MxLong); +LegoSoundManager* SoundManager(); +MxTransitionManager* TransitionManager(); +LegoVideoManager* VideoManager(); LegoAnimationManager* AnimationManager(); +LegoNavController* NavController(); LegoBuildingManager* BuildingManager(); LegoControlManager* ControlManager(); -IslePathActor* GetCurrentVehicle(); +IslePathActor* CurrentVehicle(); +ViewManager* GetViewManager(); LegoPlantManager* PlantManager(); -LegoWorld* GetCurrentWorld(); -LegoUnkSaveDataWriter* GetUnkSaveDataWriter(); -GifManager* GetGifManager(); +LegoWorld* CurrentWorld(); +LegoUnkSaveDataWriter* UnkSaveDataWriter(); +LegoTextureContainer* TextureContainer(); void FUN_10015820(MxBool p_disable, MxU16 p_flags); -void FUN_10015860(const char*, MxU8); -LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid); +void SetROIUnknown0x0c(const char* p_name, undefined p_unk0x0c); +LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid); +LegoROI* FindROI(const char* p_name); MxDSAction& GetCurrentAction(); void PlayMusic(MxU32 p_index); void SetIsWorldActive(MxBool p_isWorldActive); void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last); -void RegisterScripts(); -void UnregisterScripts(); +void CreateScripts(); +void DestroyScripts(); void SetCurrentWorld(LegoWorld* p_world); #endif // LEGOOMNI_H diff --git a/LEGO1/lego/legoomni/include/legopalettepresenter.h b/LEGO1/lego/legoomni/include/legopalettepresenter.h index 242c7bc0..c9e7fb81 100644 --- a/LEGO1/lego/legoomni/include/legopalettepresenter.h +++ b/LEGO1/lego/legoomni/include/legopalettepresenter.h @@ -10,10 +10,10 @@ class LegoPalettePresenter : public MxVideoPresenter { public: LegoPalettePresenter(); - virtual ~LegoPalettePresenter() override; // vtable+0x0 + ~LegoPalettePresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x10079f30 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f061c return "LegoPalettePresenter"; @@ -25,8 +25,8 @@ class LegoPalettePresenter : public MxVideoPresenter { return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void Destroy() override; // vtable+0x38 + void ReadyTickle() override; // vtable+0x18 + void Destroy() override; // vtable+0x38 MxResult ParsePalette(MxStreamChunk* p_chunk); diff --git a/LEGO1/lego/legoomni/include/legopartpresenter.h b/LEGO1/lego/legoomni/include/legopartpresenter.h index 5a422684..2ff6faa1 100644 --- a/LEGO1/lego/legoomni/include/legopartpresenter.h +++ b/LEGO1/lego/legoomni/include/legopartpresenter.h @@ -7,8 +7,10 @@ // SIZE 0x54 (from inlined construction at 0x10009fac) class LegoPartPresenter : public MxMediaPresenter { public: + ~LegoPartPresenter() override { Destroy(TRUE); } + // FUNCTION: LEGO1 0x1000cf70 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f05d8 return "LegoPartPresenter"; @@ -20,14 +22,17 @@ class LegoPartPresenter : public MxMediaPresenter { return !strcmp(p_name, LegoPartPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + void ReadyTickle() override; // vtable+0x18 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 - __declspec(dllexport) static void configureLegoPartPresenter(MxS32, MxS32); + static void configureLegoPartPresenter(MxS32, MxS32); // SYNTHETIC: LEGO1 0x1000d060 // LegoPartPresenter::`scalar deleting destructor' + +private: + void Destroy(MxBool p_fromDestructor); }; #endif // LEGOPARTPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index 2f0ce280..c2a2026c 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -10,10 +10,10 @@ class LegoPathActor : public LegoActor { public: LegoPathActor(); - virtual ~LegoPathActor() override; + ~LegoPathActor() override; // FUNCTION: LEGO1 0x1000c430 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0114 return "LegoPathActor"; @@ -25,7 +25,7 @@ class LegoPathActor : public LegoActor { return !strcmp(p_name, LegoPathActor::ClassName()) || LegoActor::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 + void ParseAction(char*) override; // vtable+0x20 virtual void VTable0x68(); // vtable+0x68 virtual void VTable0x6c(); // vtable+0x6c virtual void VTable0x70(float p_float); // vtable+0x70 diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index ada96e7e..5d054356 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -1,19 +1,23 @@ #ifndef LEGOPATHCONTROLLER_H #define LEGOPATHCONTROLLER_H +#include "decomp.h" #include "mxcore.h" +class IslePathActor; +class LegoPathBoundary; + // VTABLE: LEGO1 0x100d7d60 // SIZE 0x40 class LegoPathController : public MxCore { public: LegoPathController(); - virtual ~LegoPathController() override { Destroy(); }; + ~LegoPathController() override { Destroy(); } - virtual MxResult Tickle() override; // vtable+08 + MxResult Tickle() override; // vtable+08 // FUNCTION: LEGO1 0x10045110 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f11b8 return "LegoPathController"; @@ -30,6 +34,10 @@ class LegoPathController : public MxCore { virtual void VTable0x14(); // vtable+0x14 virtual void Destroy(); // vtable+0x18 + + undefined4 FUN_10046770(IslePathActor* p_actor); + MxResult FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value); + void Enable(MxBool p_enable); }; #endif // LEGOPATHCONTROLLER_H diff --git a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h index ead40f48..af2642a2 100644 --- a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h +++ b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h @@ -5,6 +5,12 @@ #include "mxlist.h" #include "mxtypes.h" +// VTABLE: LEGO1 0x100d6380 +// class MxCollection + +// VTABLE: LEGO1 0x100d6398 +// class MxList + // VTABLE: LEGO1 0x100d6320 // class MxPtrList @@ -15,20 +21,24 @@ class LegoPathControllerList : public MxPtrList { LegoPathControllerList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x1001d210 - virtual MxS8 Compare(LegoPathController* p_a, LegoPathController* p_b) override + MxS8 Compare(LegoPathController* p_a, LegoPathController* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 - - // SYNTHETIC: LEGO1 0x1001d3d0 - // LegoPathControllerList::`scalar deleting destructor' }; -// VTABLE: LEGO1 0x100d6380 -// class MxCollection +// VTABLE: LEGO1 0x100d6578 +// class MxListCursor -// VTABLE: LEGO1 0x100d6398 -// class MxList +// VTABLE: LEGO1 0x100d6548 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d6560 +// SIZE 0x10 +class LegoPathControllerListCursor : public MxPtrListCursor { +public: + LegoPathControllerListCursor(LegoPathControllerList* p_list) : MxPtrListCursor(p_list){}; +}; // TEMPLATE: LEGO1 0x1001d230 // MxCollection::Compare @@ -48,6 +58,12 @@ class LegoPathControllerList : public MxPtrList { // TEMPLATE: LEGO1 0x1001d3c0 // MxPtrList::Destroy +// SYNTHETIC: LEGO1 0x1001d3d0 +// LegoPathControllerList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001d440 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x1001d490 // MxCollection::`scalar deleting destructor' @@ -57,4 +73,25 @@ class LegoPathControllerList : public MxPtrList { // SYNTHETIC: LEGO1 0x1001d5b0 // MxPtrList::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x1001d620 +// LegoPathControllerList::~LegoPathControllerList + +// SYNTHETIC: LEGO1 0x1001f830 +// LegoPathControllerListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f8a0 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f8f0 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f960 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f9d0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001fa20 +// LegoPathControllerListCursor::~LegoPathControllerListCursor + #endif // LEGOPATHCONTROLLERLIST_H diff --git a/LEGO1/lego/legoomni/include/legopathpresenter.h b/LEGO1/lego/legoomni/include/legopathpresenter.h index 792b99eb..e6c5da14 100644 --- a/LEGO1/lego/legoomni/include/legopathpresenter.h +++ b/LEGO1/lego/legoomni/include/legopathpresenter.h @@ -8,10 +8,10 @@ class LegoPathPresenter : public MxMediaPresenter { public: LegoPathPresenter(); - virtual ~LegoPathPresenter() override; + ~LegoPathPresenter() override; // FUNCTION: LEGO1 0x100449a0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0690 return "LegoPathPresenter"; @@ -23,12 +23,12 @@ class LegoPathPresenter : public MxMediaPresenter { return !strcmp(p_name, LegoPathPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + void ReadyTickle() override; // vtable+0x18 + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 // SYNTHETIC: LEGO1 0x10044a90 // LegoPathPresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legophonemepresenter.h b/LEGO1/lego/legoomni/include/legophonemepresenter.h index b5aa3616..59263f7f 100644 --- a/LEGO1/lego/legoomni/include/legophonemepresenter.h +++ b/LEGO1/lego/legoomni/include/legophonemepresenter.h @@ -11,30 +11,31 @@ class LegoPhonemePresenter : public MxFlcPresenter { public: LegoPhonemePresenter(); - virtual ~LegoPhonemePresenter() override; // vtable+0x0 + ~LegoPhonemePresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x1004e310 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f064c return "LegoPhonemePresenter"; } - virtual void StartingTickle() override; // vtable+0x1c - virtual void EndAction() override; // vtable+0x40 - virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 - virtual void PutFrame() override; // vtable+0x6c + void StartingTickle() override; // vtable+0x1c + void EndAction() override; // vtable+0x40 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void PutFrame() override; // vtable+0x6c // SYNTHETIC: LEGO1 0x1004e320 // LegoPhonemePresenter::`scalar deleting destructor' private: void Init(); - int m_unk0x68; - int m_unk0x6c; - undefined m_unk0x70; - MxString m_string; // 0x74 - undefined m_unk0x84; + + undefined4 m_unk0x68; // 0x68 + undefined4 m_unk0x6c; // 0x6c + undefined m_unk0x70; // 0x70 + MxString m_unk0x74; // 0x74 + undefined m_unk0x84; // 0x84 }; #endif // LEGOPHONEMEPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index e199f11b..5d64ca27 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -9,24 +9,32 @@ class LegoPlantManager : public MxCore { public: LegoPlantManager(); - virtual ~LegoPlantManager() override; // vtable+0x0 + ~LegoPlantManager() override; // vtable+0x00 - virtual MxResult Tickle() override; // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10026290 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f318c return "LegoPlantManager"; } - void FUN_10026360(undefined4 p_world); + void FUN_10026360(MxS32 p_scriptIndex); + void FUN_100263a0(undefined4 p_und); + void FUN_10027120(); + + static void SetCustomizeAnimFile(const char* p_value); // SYNTHETIC: LEGO1 0x100262a0 // LegoPlantManager::`scalar deleting destructor' private: + static char* g_customizeAnimFile; + void Init(); + + undefined m_unk0x08[0x24]; // 0x08 }; #endif // LEGOPLANTMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legopointofviewcontroller.h b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h index 99c213e2..b6db3014 100644 --- a/LEGO1/lego/legoomni/include/legopointofviewcontroller.h +++ b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h @@ -20,7 +20,7 @@ class LegoNavController; class LegoMouseController : public MxCore { public: LegoMouseController(); - virtual ~LegoMouseController() override; + ~LegoMouseController() override; virtual void LeftDown(int, int); // vtable+0x14 virtual void LeftDrag(int, int); // vtable+0x18 @@ -30,10 +30,10 @@ class LegoMouseController : public MxCore { virtual void RightUp(int, int); // vtable+0x28 private: - BOOL m_isButtonDown; // 0x08 - undefined4 m_unk0xc; // 0x0c - MxDouble m_buttonX; // 0x10 - MxDouble m_buttonY; // 0x18 + BOOL m_isButtonDown; // 0x08 + undefined4 m_unk0x0c; // 0x0c + MxDouble m_buttonX; // 0x10 + MxDouble m_buttonY; // 0x18 }; // SYNTHETIC: LEGO1 0x100655b0 @@ -44,14 +44,14 @@ class LegoMouseController : public MxCore { class LegoPointOfViewController : public LegoMouseController { public: LegoPointOfViewController(); - virtual ~LegoPointOfViewController() override; + ~LegoPointOfViewController() override; - virtual MxResult Tickle() override; // vtable+0x08 - virtual void LeftDown(int p_x, int p_y) override; // vtable+0x0c - virtual void LeftDrag(int p_x, int p_y) override; // vtable+0x10 + MxResult Tickle() override; // vtable+0x08 + void LeftDown(int p_x, int p_y) override; // vtable+0x0c + void LeftDrag(int p_x, int p_y) override; // vtable+0x10 // FUNCTION: LEGO1 0x10011e40 - virtual void LeftUp(int p_x, int p_y) override + void LeftUp(int p_x, int p_y) override { LegoMouseController::LeftUp(p_x, p_y); AffectPointOfView(); @@ -59,7 +59,7 @@ class LegoPointOfViewController : public LegoMouseController { // vtable+0x14 // FUNCTION: LEGO1 0x10011e60 - virtual void RightDown(int p_x, int p_y) override + void RightDown(int p_x, int p_y) override { LegoMouseController::RightDown(p_x, p_y); AffectPointOfView(); @@ -67,7 +67,7 @@ class LegoPointOfViewController : public LegoMouseController { // vtable+0x20 // FUNCTION: LEGO1 0x10011e80 - virtual void RightDrag(int p_x, int p_y) override + void RightDrag(int p_x, int p_y) override { LegoMouseController::RightDrag(p_x, p_y); AffectPointOfView(); @@ -75,7 +75,7 @@ class LegoPointOfViewController : public LegoMouseController { // vtable+0x24 // FUNCTION: LEGO1 0x10011ea0 - virtual void RightUp(int p_x, int p_y) override + void RightUp(int p_x, int p_y) override { LegoMouseController::RightUp(p_x, p_y); AffectPointOfView(); @@ -86,6 +86,7 @@ class LegoPointOfViewController : public LegoMouseController { void OnViewSize(int p_width, int p_height); inline LegoEntity* GetEntity() { return m_entity; } + inline LegoNavController* GetNavController() { return m_nav; } protected: void AffectPointOfView(); diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index e3f9df88..c8b02f2e 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -11,12 +11,12 @@ class LegoRace : public LegoWorld { public: LegoRace(); - virtual ~LegoRace() override; // vtable+0x0 + ~LegoRace() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10015ba0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f07c4 return "LegoRace"; @@ -28,15 +28,15 @@ class LegoRace : public LegoWorld { return !strcmp(p_name, LegoRace::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 - virtual undefined4 VTable0x6c(undefined4) = 0; // vtable+0x6c - virtual undefined4 VTable0x70(undefined4); // vtable+0x70 - virtual undefined4 VTable0x74(undefined4); // vtable+0x74 - virtual undefined4 VTable0x78(undefined4); // vtable+0x78 - virtual void VTable0x7c(undefined4, undefined4); // vtable+0x7c + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + virtual undefined4 VTable0x6c(undefined4) = 0; // vtable+0x6c + virtual undefined4 VTable0x70(undefined4); // vtable+0x70 + virtual undefined4 VTable0x74(undefined4); // vtable+0x74 + virtual undefined4 VTable0x78(undefined4); // vtable+0x78 + virtual void VTable0x7c(undefined4, undefined4); // vtable+0x7c // SYNTHETIC: LEGO1 0x10015cc0 // LegoRace::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoraceactor.h b/LEGO1/lego/legoomni/include/legoraceactor.h index fc6c6a2d..48f66b26 100644 --- a/LEGO1/lego/legoomni/include/legoraceactor.h +++ b/LEGO1/lego/legoomni/include/legoraceactor.h @@ -8,7 +8,7 @@ class LegoRaceActor : public LegoAnimActor { public: // FUNCTION: LEGO1 0x10014af0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0bf4 return "LegoRaceActor"; @@ -20,13 +20,13 @@ class LegoRaceActor : public LegoAnimActor { return !strcmp(p_name, LegoRaceActor::ClassName()) || LegoAnimActor::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 - virtual void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - virtual void VTable0x68() override; // vtable+0x68 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 - virtual MxS32 VTable0x90() override; // vtable+0x90 - virtual MxS32 VTable0x94() override; // vtable+0x94 + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x68() override; // vtable+0x68 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + MxS32 VTable0x90() override; // vtable+0x90 + MxS32 VTable0x94() override; // vtable+0x94 // SYNTHETIC: LEGO1 0x10014ab0 // LegoRaceActor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoracecar.h b/LEGO1/lego/legoomni/include/legoracecar.h index f080ba46..f90c4cad 100644 --- a/LEGO1/lego/legoomni/include/legoracecar.h +++ b/LEGO1/lego/legoomni/include/legoracecar.h @@ -8,10 +8,10 @@ // SIZE 0x200 class LegoRaceCar : public LegoCarRaceActor { public: - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10014290 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0548 return "LegoRaceCar"; @@ -23,13 +23,13 @@ class LegoRaceCar : public LegoCarRaceActor { return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); } - virtual void ParseAction(char*) override; // vtable+0x20 - virtual void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - virtual void VTable0x6c() override; // vtable+0x6c - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxS32 VTable0x94() override; // vtable+0x94 - virtual void VTable0x98() override; // vtable+0x98 - virtual void VTable0x9c() override; // vtable+0x9c + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x94() override; // vtable+0x94 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c // SYNTHETIC: LEGO1 0x10014230 // LegoRaceCar::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legosoundmanager.h b/LEGO1/lego/legoomni/include/legosoundmanager.h index 0e4bbbbd..89e51165 100644 --- a/LEGO1/lego/legoomni/include/legosoundmanager.h +++ b/LEGO1/lego/legoomni/include/legosoundmanager.h @@ -1,6 +1,7 @@ #ifndef LEGOSOUNDMANAGER_H #define LEGOSOUNDMANAGER_H +#include "legounknown100d6b4c.h" #include "mxsoundmanager.h" // VTABLE: LEGO1 0x100d6b10 @@ -8,21 +9,26 @@ class LegoSoundManager : public MxSoundManager { public: LegoSoundManager(); - virtual ~LegoSoundManager() override; + ~LegoSoundManager() override; - virtual MxResult Tickle() override; // vtable+08 - virtual void Destroy() override; // vtable+18 - virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x30 + MxResult Tickle() override; // vtable+08 + void Destroy() override; // vtable+18 + MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x30 // SYNTHETIC: LEGO1 0x10029920 // LegoSoundManager::`scalar deleting destructor' + inline LegoUnknown100d6b4c* GetUnknown0x40() { return m_unk0x40; } + private: void Init(); void Destroy(MxBool p_fromDestructor); - undefined4 m_unk0x3c; - undefined4 m_unk0x40; + LPDIRECTSOUND3DLISTENER m_listener; // 0x3c + LegoUnknown100d6b4c* m_unk0x40; // 0x40 }; +// GLOBAL: LEGO1 0x100db6d0 +// IID_IDirectSound3DListener + #endif // LEGOSOUNDMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index 215d64d4..d4f9bad4 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -2,34 +2,96 @@ #define LEGOSTATE_H #include "decomp.h" -#include "legostream.h" +#include "misc/legostorage.h" #include "mxcore.h" #include "mxstring.h" // VTABLE: LEGO1 0x100d46c0 +// SIZE 0x08 class LegoState : public MxCore { public: - virtual ~LegoState() override; // vtable+0x00 + // FUNCTION: LEGO1 0x10005f40 + ~LegoState() override {} // FUNCTION: LEGO1 0x100060d0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f01b8 return "LegoState"; } // FUNCTION: LEGO1 0x100060e0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoState::ClassName()) || MxCore::IsA(p_name); } - virtual MxBool VTable0x14(); // vtable+0x14 - virtual MxBool SetFlag(); // vtable+0x18 - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream); // vtable+0x1C + // FUNCTION: LEGO1 0x10005f90 + virtual MxBool VTable0x14() { return TRUE; } // vtable+0x14 + + // FUNCTION: LEGO1 0x10005fa0 + virtual MxBool SetFlag() { return FALSE; } // vtable+0x18 + + // FUNCTION: LEGO1 0x10005fb0 + virtual MxResult VTable0x1c(LegoFile* p_legoFile) + { + if (p_legoFile->IsWriteMode()) { + p_legoFile->FUN_10006030(this->ClassName()); + } + return SUCCESS; + } // vtable+0x1c // SYNTHETIC: LEGO1 0x10006160 // LegoState::`scalar deleting destructor' + + // SIZE 0x0c + class Playlist { + public: + enum Mode { + e_loop, + e_once, + e_random, + e_loopSkipFirst + }; + + // FUNCTION: LEGO1 0x10017c00 + Playlist() + { + m_objectIds = NULL; + m_length = 0; + m_mode = e_loop; + m_nextIndex = 0; + } + + Playlist(MxU32* p_objectIds, MxS16 p_length) + { + m_objectIds = p_objectIds; + m_length = p_length; + m_mode = e_loop; + m_nextIndex = 0; + } + + // FUNCTION: LEGO1 0x10071800 + Playlist& operator=(const Playlist& p_shuffle) + { + m_objectIds = p_shuffle.m_objectIds; + m_length = p_shuffle.m_length; + m_nextIndex = p_shuffle.m_nextIndex; + m_mode = p_shuffle.m_mode; + return *this; + } + + MxU32 Next(); + MxBool Contains(MxU32 p_objectId); + + inline void SetUnknown0x08(MxS16 p_unk0x08) { m_nextIndex = p_unk0x08; } + + private: + MxU32* m_objectIds; // 0x00 + MxS16 m_length; // 0x04 + MxS16 m_mode; // 0x06 + MxS16 m_nextIndex; // 0x08 + }; }; #endif // LEGOSTATE_H diff --git a/LEGO1/lego/legoomni/include/legostream.h b/LEGO1/lego/legoomni/include/legostream.h deleted file mode 100644 index 601e94e2..00000000 --- a/LEGO1/lego/legoomni/include/legostream.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef LEGOSTREAM_H -#define LEGOSTREAM_H - -#include "compat.h" -#include "decomp.h" -#include "mxstring.h" -#include "mxtypes.h" - -#pragma warning(disable : 4237) -#include - -#define LEGOSTREAM_MODE_READ 1 -#define LEGOSTREAM_MODE_WRITE 2 - -class MxVariableTable; - -// VTABLE: LEGO1 0x100d7d80 -class LegoStream { -public: - LegoStream() : m_mode(0) {} - // FUNCTION: LEGO1 0x10045ad0 - inline virtual ~LegoStream() {} - - virtual MxResult Read(void* p_buffer, MxU32 p_size) = 0; - virtual MxResult Write(const void* p_buffer, MxU32 p_size) = 0; - virtual MxResult Tell(MxU32* p_offset) = 0; - virtual MxResult Seek(MxU32 p_offset) = 0; - - virtual MxBool IsWriteMode(); - virtual MxBool IsReadMode(); - - enum OpenFlags { - c_readBit = 1, - c_writeBit = 2, - c_binaryBit = 4, - }; - - static MxResult __stdcall WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName); - static MxS32 __stdcall ReadVariable(LegoStream* p_stream, MxVariableTable* p_to); - -protected: - MxU8 m_mode; -}; - -// SYNTHETIC: LEGO1 0x10045b00 -// LegoStream::`scalar deleting destructor' - -// VTABLE: LEGO1 0x100db730 -class LegoFileStream : public LegoStream { -public: - LegoFileStream(); - virtual ~LegoFileStream() override; - - MxResult Read(void* p_buffer, MxU32 p_size) override; - MxResult Write(const void* p_buffer, MxU32 p_size) override; - MxResult Tell(MxU32* p_offset) override; - MxResult Seek(MxU32 p_offset) override; - - MxResult Open(const char* p_filename, OpenFlags p_mode); - - LegoFileStream* FUN_10006030(MxString p_str); - -private: - FILE* m_hFile; -}; - -// SYNTHETIC: LEGO1 0x10099230 -// LegoFileStream::`scalar deleting destructor' - -// VTABLE: LEGO1 0x100db710 -class LegoMemoryStream : public LegoStream { -public: - LegoMemoryStream(char* p_buffer); - - MxResult Read(void* p_buffer, MxU32 p_size) override; - MxResult Write(const void* p_buffer, MxU32 p_size) override; - MxResult Tell(MxU32* p_offset) override; - MxResult Seek(MxU32 p_offset) override; - -private: - char* m_buffer; - MxU32 m_offset; -}; - -// SYNTHETIC: LEGO1 0x10045a80 -// LegoMemoryStream::~LegoMemoryStream - -// SYNTHETIC: LEGO1 0x100990f0 -// LegoMemoryStream::`scalar deleting destructor' - -#endif // LEGOSTREAM_H diff --git a/LEGO1/lego/legoomni/include/legotextureinfo.h b/LEGO1/lego/legoomni/include/legotextureinfo.h new file mode 100644 index 00000000..72afb905 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legotextureinfo.h @@ -0,0 +1,23 @@ +#ifndef LEGOTEXTUREINFO_H +#define LEGOTEXTUREINFO_H + +#include +#include + +class LegoTexture; + +// SIZE 0x10 +struct LegoTextureInfo { +public: + LegoTextureInfo(); + ~LegoTextureInfo(); + + static LegoTextureInfo* Create(const char* p_name, LegoTexture* p_texture); + + char* m_name; // 0x00 + LPDIRECTDRAWSURFACE m_surface; // 0x04 + LPDIRECTDRAWPALETTE m_palette; // 0x08 + LPDIRECT3DRMTEXTURE2 m_texture; // 0x0c +}; + +#endif // LEGOTEXTUREINFO_H diff --git a/LEGO1/lego/legoomni/include/legotexturepresenter.h b/LEGO1/lego/legoomni/include/legotexturepresenter.h index ca6541df..472c5828 100644 --- a/LEGO1/lego/legoomni/include/legotexturepresenter.h +++ b/LEGO1/lego/legoomni/include/legotexturepresenter.h @@ -7,24 +7,24 @@ // SIZE 0x54 (from inlined construction at 0x10009bb5) class LegoTexturePresenter : public MxMediaPresenter { public: - virtual ~LegoTexturePresenter() override; + ~LegoTexturePresenter() override; // FUNCTION: LEGO1 0x1000ce50 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0664 return "LegoTexturePresenter"; } // FUNCTION: LEGO1 0x1000ce60 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoTexturePresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void DoneTickle() override; // vtable+0x2c - virtual MxResult AddToManager() override; // vtable+0x34 - virtual MxResult PutData() override; // vtable+0x4c + void DoneTickle() override; // vtable+0x2c + MxResult AddToManager() override; // vtable+0x34 + MxResult PutData() override; // vtable+0x4c // SYNTHETIC: LEGO1 0x1000cf40 // LegoTexturePresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legounknown100d5778.h b/LEGO1/lego/legoomni/include/legounknown100d5778.h new file mode 100644 index 00000000..d04c200c --- /dev/null +++ b/LEGO1/lego/legoomni/include/legounknown100d5778.h @@ -0,0 +1,38 @@ +#ifndef LEGOUNKNOWN100D5778_H +#define LEGOUNKNOWN100D5778_H + +#include "decomp.h" +#include "mxtypes.h" +#include "roi/legoroi.h" + +#include + +// VTABLE: LEGO1 0x100d5778 +// SIZE 0x30 +class LegoUnknown100d5778 { +public: + LegoUnknown100d5778(); + virtual ~LegoUnknown100d5778(); + + void Init(); + MxResult FUN_100116a0(LPDIRECTSOUND p_dsound, undefined4, undefined4 p_unk0x2c); + void Destroy(); + undefined4 FUN_100118e0(LPDIRECTSOUNDBUFFER p_dsBuffer); + void FUN_10011ca0(); + + // SYNTHETIC: LEGO1 0x10011650 + // LegoUnknown100d5778::`scalar deleting destructor' + +private: + undefined m_unk0x4[4]; // 0x04 + LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x08 + LegoROI* m_unk0xc; // 0x0c + undefined4 m_unk0x10; // 0x10 + MxBool m_unk0x14; // 0x14 + MxBool m_unk0x15; // 0x15 + undefined4 m_unk0x18; // 0x18 + undefined m_unk0x1c[0x10]; // 0x1c + undefined4 m_unk0x2c; // 0x2c +}; + +#endif // LEGOUNKNOWN100D5778_H diff --git a/LEGO1/lego/legoomni/include/legounknown100d6b4c.h b/LEGO1/lego/legoomni/include/legounknown100d6b4c.h new file mode 100644 index 00000000..eef443a9 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legounknown100d6b4c.h @@ -0,0 +1,118 @@ +#ifndef LEGOUNKNOWN100D6B4C_H +#define LEGOUNKNOWN100D6B4C_H + +#include "decomp.h" +#include "legocachesound.h" +#include "mxstl/stlcompat.h" +#include "mxtypes.h" + +// SIZE 0x08 +struct Element100d6b4c { + Element100d6b4c() : m_sound(NULL), m_name(NULL) {} + Element100d6b4c(LegoCacheSound* p_sound, const char* p_name) : m_sound(p_sound), m_name(p_name) {} + Element100d6b4c(LegoCacheSound* p_sound) : m_sound(p_sound), m_name(p_sound->GetString0x48().GetData()) {} + + // FUNCTION: LEGO1 0x1003d030 + ~Element100d6b4c() + { + if (m_sound == NULL && m_name != NULL) { + delete[] const_cast(m_name); + } + } + + bool operator==(Element100d6b4c) const { return 0; } + bool operator<(Element100d6b4c) const { return 0; } + + inline LegoCacheSound* GetSound() const { return m_sound; } + inline const char* GetName() const { return m_name; } + + friend struct Set100d6b4cComparator; + +private: + LegoCacheSound* m_sound; // 0x00 + const char* m_name; // 0x04 +}; + +struct Set100d6b4cComparator { + bool operator()(const Element100d6b4c& p_a, const Element100d6b4c& p_b) const + { + return strcmpi(p_a.m_name, p_b.m_name) > 0; + } +}; + +typedef set Set100d6b4c; +typedef list List100d6b4c; + +// VTABLE: LEGO1 0x100d6b4c +// SIZE 0x20 +class LegoUnknown100d6b4c { +public: + LegoUnknown100d6b4c() {} + ~LegoUnknown100d6b4c(); + + virtual MxResult Tickle(); // vtable+0x00 + + LegoCacheSound* FUN_1003d170(const char* p_key); + LegoCacheSound* FUN_1003d290(LegoCacheSound* p_sound); + void FUN_1003dae0(char* p_one, char* p_two, MxBool p_three); + LegoCacheSound* FUN_1003db10(LegoCacheSound* p_one, char* p_two, MxBool p_three); + void FUN_1003dc40(LegoCacheSound** p_und); + +private: + Set100d6b4c m_set; // 0x04 + List100d6b4c m_list; // 0x14 +}; + +// TODO: Function names subject to change. + +// clang-format off +// TEMPLATE: LEGO1 0x10029c30 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::~_Tree >::_Kfn,Set100d6b4cComparator,allocator > + +// TEMPLATE: LEGO1 0x10029d10 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x10029d50 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::erase + +// TEMPLATE: LEGO1 0x1002a1b0 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::_Erase + +// TEMPLATE: LEGO1 0x1002a210 +// list >::~list > + +// TEMPLATE: LEGO1 0x1002a2a0 +// set >::~set > + +// TEMPLATE: LEGO1 0x1002a2f0 +// Set::~Set + +// TEMPLATE: LEGO1 0x1002a340 +// List::~List + +// TEMPLATE: LEGO1 0x1003dab0 +// list >::_Buynode + +// TEMPLATE: LEGO1 0x1003d450 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::insert + +// TEMPLATE: LEGO1 0x1003d6f0 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::iterator::_Dec + +// TEMPLATE: LEGO1 0x1003d740 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::_BuyNode + +// TEMPLATE: LEGO1 0x1003d760 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::_Insert + +// TEMPLATE: LEGO1 0x1003d9f0 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::_Lrotate + +// TEMPLATE: LEGO1 0x1003da50 +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::_Rrotate + +// GLOBAL: LEGO1 0x100f31cc +// _Tree >::_Kfn,Set100d6b4cComparator,allocator >::_Nil +// clang-format on + +#endif // LEGOUNKNOWN100D6B4C_H diff --git a/LEGO1/lego/legoomni/include/legounknown100d9d00.h b/LEGO1/lego/legoomni/include/legounknown100d9d00.h index 394ffbbd..0c567b17 100644 --- a/LEGO1/lego/legoomni/include/legounknown100d9d00.h +++ b/LEGO1/lego/legoomni/include/legounknown100d9d00.h @@ -18,7 +18,7 @@ class LegoUnknown100d9d00 : public MxList { LegoUnknown100d9d00() { SetDestroy(Destroy); } // STUB: LEGO1 0x1007b210 - virtual MxS8 Compare(LegoUnknown100d7c88* p_a, LegoUnknown100d7c88* p_b) override { return -1; } // vtable+0x14 + MxS8 Compare(LegoUnknown100d7c88* p_a, LegoUnknown100d7c88* p_b) override { return -1; } // vtable+0x14 // FUNCTION: LEGO1 0x1007b2e0 static void Destroy(LegoUnknown100d7c88* p_element) { delete p_element; } diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 240bef11..7fa539ca 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -2,10 +2,28 @@ #define LEGOUNKSAVEDATAWRITER_H #include "decomp.h" +#include "legovariables.h" +#include "misc/legostorage.h" +#include "mxstl/stlcompat.h" #include "mxtypes.h" class LegoROI; -class LegoStream; + +#pragma warning(disable : 4237) + +// TODO: generic string comparator? +struct LegoUnkSaveDataMapComparator { + bool operator()(const char* const& p_a, const char* const& p_b) const { return strcmpi(p_a, p_b) > 0; } +}; + +// TODO: pair instead? +// SIZE 0x08 +struct LegoUnkSaveDataMapValue { + LegoROI* m_roi; // 0x00 + MxU32 m_counter; // 0x04 +}; + +typedef map LegoUnkSaveDataMap; struct LegoSaveDataEntry3 { char* m_name; @@ -32,10 +50,48 @@ struct LegoSaveDataEntry3 { MxU8 m_savePart10; // 0x104 }; +// SIZE 0x08 class LegoUnkSaveDataWriter { public: - MxResult WriteSaveData3(LegoStream* p_stream); + LegoUnkSaveDataWriter(); + + MxResult WriteSaveData3(LegoStorage* p_stream); + LegoROI* FUN_10083500(char*, MxBool); + + static void InitSaveData(); + static void SetCustomizeAnimFile(const char* p_value); + + void FUN_100832a0(); void FUN_10083db0(LegoROI* p_roi); + void FUN_10083f10(LegoROI* p_roi); + +private: + static char* g_customizeAnimFile; + + LegoUnkSaveDataMap* m_map; // 0x00 + CustomizeAnimFileVariable* m_customizeAnimFile; // 0x04 }; +// clang-format off + +// FUNCTION: LEGO1 0x10082b90 +// _Tree,map >::_Kfn,LegoUnkSaveDataMapComparator,allocator >::~_Tree,map >::_Kfn,LegoUnkSaveDataMapComparator,allocator > + +// FUNCTION: LEGO1 0x10082c60 +// _Tree,map >::_Kfn,LegoUnkSaveDataMapComparator,allocator >::iterator::_Inc + +// FUNCTION: LEGO1 0x10082ca0 +// _Tree,map >::_Kfn,LegoUnkSaveDataMapComparator,allocator >::erase + +// FUNCTION: LEGO1 0x100830f0 +// _Tree,map >::_Kfn,LegoUnkSaveDataMapComparator,allocator >::_Erase + +// FUNCTION: LEGO1 0x10083130 +// map >::~map > + +// GLOBAL: LEGO1 0x100fc508 +// _Tree,map >::_Kfn,LegoUnkSaveDataMapComparator,allocator >::_Nil + +// clang-format on + #endif // LEGOUNKSAVEDATAWRITER_H diff --git a/LEGO1/lego/legoomni/include/legoutil.h b/LEGO1/lego/legoomni/include/legoutil.h index 6e9bb5ee..696a1cc4 100644 --- a/LEGO1/lego/legoomni/include/legoutil.h +++ b/LEGO1/lego/legoomni/include/legoutil.h @@ -2,6 +2,9 @@ #define LEGOUTIL_H #include "extra.h" +#include "misc/legostorage.h" +#include "misc/legotexture.h" +#include "mxstring.h" #include "mxtypes.h" #include "mxutil.h" @@ -9,7 +12,26 @@ class MxAtomId; class LegoEntity; +class LegoAnimPresenter; +class LegoTexture; + +// SIZE 0x14 +class NamedTexture { +public: + ~NamedTexture() { delete m_texture; } + + // FUNCTION: LEGO1 0x1003f920 + const MxString* GetName() const { return &m_name; } + + LegoTexture* GetTexture() { return m_texture; } + +private: + MxString m_name; // 0x00 + LegoTexture* m_texture; // 0x04 +}; + +void FUN_1003e050(LegoAnimPresenter* p_presenter); Extra::ActionType MatchActionString(const char*); void InvokeAction(Extra::ActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender); void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut); @@ -17,5 +39,12 @@ MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); void FUN_1003ef00(MxBool); void SetAppCursor(WPARAM p_wparam); MxBool FUN_1003ef60(); +MxBool RemoveFromWorld(MxAtomId& p_atomId1, MxS32 p_id1, MxAtomId& p_atomId2, MxS32 p_id2); +NamedTexture* ReadNamedTexture(LegoFile* p_file); +void FUN_1003f540(LegoFile* p_file, const char* p_filename); +void WriteNamedTexture(LegoFile* p_file, NamedTexture* p_texture); + +// SYNTHETIC: LEGO1 0x10034b40 +// LegoTexture::`scalar deleting destructor' #endif // LEGOUTIL_H diff --git a/LEGO1/lego/legoomni/include/legovariables.h b/LEGO1/lego/legoomni/include/legovariables.h new file mode 100644 index 00000000..8528d44d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legovariables.h @@ -0,0 +1,56 @@ +#ifndef LEGOVARIABLES_H +#define LEGOVARIABLES_H + +#include "mxvariable.h" + +extern const char* g_varVISIBILITY; +extern const char* g_varCAMERALOCATION; +extern const char* g_varCURSOR; +extern const char* g_varWHOAMI; + +// VTABLE: LEGO1 0x100d86c8 +// SIZE 0x24 +class VisibilityVariable : public MxVariable { +public: + VisibilityVariable() { m_key = g_varVISIBILITY; } + + void SetValue(const char* p_value) override; // vtable+0x04 +}; + +// VTABLE: LEGO1 0x100d86b8 +// SIZE 0x24 +class CameraLocationVariable : public MxVariable { +public: + CameraLocationVariable() { m_key = g_varCAMERALOCATION; } + + void SetValue(const char* p_value) override; // vtable+0x04 +}; + +// VTABLE: LEGO1 0x100d86a8 +// SIZE 0x24 +class CursorVariable : public MxVariable { +public: + CursorVariable() { m_key = g_varCURSOR; } + + void SetValue(const char* p_value) override; // vtable+0x04 +}; + +// VTABLE: LEGO1 0x100d8698 +// SIZE 0x24 +class WhoAmIVariable : public MxVariable { +public: + WhoAmIVariable() { m_key = g_varWHOAMI; } + + void SetValue(const char* p_value) override; // vtable+0x04 +}; + +// VTABLE: LEGO1 0x100da878 +// SIZE 0x24 +class CustomizeAnimFileVariable : public MxVariable { +public: + CustomizeAnimFileVariable(const char* p_key); + + void SetValue(const char* p_value) override; // vtable+0x04 +}; + +#endif // LEGOVARIABLES_H diff --git a/LEGO1/lego/legoomni/include/legovehiclebuildstate.h b/LEGO1/lego/legoomni/include/legovehiclebuildstate.h index 8deed7a5..229fdcfb 100644 --- a/LEGO1/lego/legoomni/include/legovehiclebuildstate.h +++ b/LEGO1/lego/legoomni/include/legovehiclebuildstate.h @@ -6,40 +6,30 @@ #include "mxstring.h" // VTABLE: LEGO1 0x100d66e0 -// SIZE 0x50 (from 1000acd7) +// SIZE 0x50 class LegoVehicleBuildState : public LegoState { public: LegoVehicleBuildState(char* p_classType); // FUNCTION: LEGO1 0x10025ff0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { return this->m_className.GetData(); } // FUNCTION: LEGO1 0x10026000 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, this->m_className.GetData()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c // SYNTHETIC: LEGO1 0x100260a0 // LegoVehicleBuildState::`scalar deleting destructor' -public: - struct UnkStruct { - undefined4 m_unk0x00; - undefined2 m_unk0x04; - undefined2 m_unk0x06; - undefined2 m_unk0x08; - - UnkStruct(); - }; - private: - UnkStruct m_unk0x08[4]; // 0x08 + Playlist m_unk0x08[4]; // 0x08 // This can be one of the following: // * LegoRaceCarBuildState diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index 2fe7d7a4..0cde06b6 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -17,27 +17,29 @@ class LegoROI; class LegoVideoManager : public MxVideoManager { public: LegoVideoManager(); - virtual ~LegoVideoManager() override; + ~LegoVideoManager() override; - __declspec(dllexport) int EnableRMDevice(); - __declspec(dllexport) int DisableRMDevice(); + int EnableRMDevice(); + int DisableRMDevice(); void EnableFullScreenMovie(MxBool p_enable); - __declspec(dllexport) void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); - __declspec(dllexport) void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY); + void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); + void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY); + + MxResult Tickle() override; // vtable+0x08 + void Destroy() override; // vtable+0x18 + MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x2c + MxResult RealizePalette(MxPalette*) override; // vtable+0x30 + void UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) override; // vtable+0x34 + virtual MxPresenter* GetPresenterAt(MxS32 p_x, MxS32 p_y); // vtable+0x38 - virtual MxResult Tickle() override; // vtable+0x8 - virtual void Destroy() override; // vtable+0x18 - virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) - override; // vtable+0x2c - virtual MxResult RealizePalette(MxPalette*) override; // vtable+0x30 - virtual void UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) override; // vtable+0x34 - virtual void VTable0x38(undefined4, undefined4); // vtable+0x38 // FUNCTION: LEGO1 0x1007ab10 virtual LegoUnknown100d9d00* VTable0x3c() { return m_unk0x100d9d00; } // vtable+0x3c void SetSkyColor(float p_red, float p_green, float p_blue); void OverrideSkyColor(MxBool p_shouldOverride); + void FUN_1007c520(); + inline Tgl::Renderer* GetRenderer() { return this->m_renderer; } inline Lego3DManager* Get3DManager() { return this->m_3dManager; } inline MxDirect3D* GetDirect3D() { return this->m_direct3d; } inline void SetRender3D(MxBool p_render3d) { this->m_render3d = p_render3d; } diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 31b60f84..160c8ffc 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -1,104 +1,166 @@ #ifndef LEGOWORLD_H #define LEGOWORLD_H +#include "legocachesound.h" +#include "legocachesoundlist.h" #include "legocameracontroller.h" #include "legoentity.h" #include "legoentitylist.h" #include "legopathcontrollerlist.h" -#include "mxcorelist.h" #include "mxpresenter.h" #include "mxpresenterlist.h" class IslePathActor; class LegoPathBoundary; +class LegoHideAnimPresenter; + +struct CoreSetCompare { + MxS32 operator()(MxCore* const& p_a, MxCore* const& p_b) const { return (MxS32) p_a < (MxS32) p_b; } +}; + +typedef set MxCoreSet; // VTABLE: LEGO1 0x100d6280 // SIZE 0xf8 class LegoWorld : public LegoEntity { public: - __declspec(dllexport) LegoWorld(); - __declspec(dllexport) virtual ~LegoWorld(); // vtable+0x0 + enum StartupTicks { + e_start = 0, + e_one, + e_two, + e_three, + e_four + }; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + LegoWorld(); + ~LegoWorld() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1001d690 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0058 return "LegoWorld"; } // FUNCTION: LEGO1 0x1001d6a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoWorld::ClassName()) || LegoEntity::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c - virtual void VTable0x50(); // vtable+0x50 - virtual LegoCameraController* VTable0x54(); // vtable+0x54 - virtual void VTable0x58(MxCore* p_object); // vtable+0x58 - virtual MxBool VTable0x5c(); // vtable+0x5c + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + virtual void ReadyWorld(); // vtable+0x50 + virtual LegoCameraController* VTable0x54(); // vtable+0x54 + virtual void Add(MxCore* p_object); // vtable+0x58 + virtual MxBool VTable0x5c(); // vtable+0x5c // FUNCTION: LEGO1 0x100010a0 virtual void VTable0x60() {} // vtable+0x60 - virtual MxBool VTable0x64(); // vtable+0x64 - virtual void VTable0x68(MxBool p_add); // vtable+0x68 + virtual MxBool VTable0x64(); // vtable+0x64 + virtual void Enable(MxBool p_enable); // vtable+0x68 inline LegoCameraController* GetCamera() { return m_cameraController; } - inline undefined4 GetUnknown0xec() { return m_unk0xec; } + inline MxS32 GetScriptIndex() { return m_scriptIndex; } + inline MxCoreSet& GetUnknown0xd0() { return m_set0xd0; } + inline list& GetUnknownList0xe0() { return m_list0xe0; } - undefined FUN_100220e0(); - void EndAction(MxCore* p_object); + inline void SetScriptIndex(MxS32 p_scriptIndex) { m_scriptIndex = p_scriptIndex; } + + MxBool PresentersPending(); + void Remove(MxCore* p_object); void FUN_1001fc80(IslePathActor* p_actor); - MxBool FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); - MxBool FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); - void FUN_10073400(); - void FUN_10073430(); - MxS32 GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); - MxPresenter* FindPresenter(const char* p_presenter, const char* p_name); + MxResult GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); + MxCore* Find(const char* p_class, const char* p_name); + MxCore* Find(const MxAtomId& p_atom, MxS32 p_entityId); // SYNTHETIC: LEGO1 0x1001dee0 // LegoWorld::`scalar deleting destructor' protected: - LegoPathControllerList m_list0x68; // 0x68 - MxPresenterList m_list0x80; // 0x80 - LegoCameraController* m_cameraController; // 0x98 - LegoEntityList* m_entityList; // 0x9c - MxCoreList* m_coreList; // 0xa0 - undefined m_unk0xa4[0x14]; // 0xa4 - MxPresenterList m_list0xb8; // 0xb8 - undefined m_unk0xd0[0x1c]; // 0xd0 - undefined4 m_unk0xec; // 0xec - undefined4 m_unk0xf0; // 0xf0 - MxS16 m_unk0xf4; // 0xf4 - MxBool m_worldStarted; // 0xf6 - undefined m_unk0xf7; // 0xf7 + LegoPathControllerList m_list0x68; // 0x68 + MxPresenterList m_animPresenters; // 0x80 + LegoCameraController* m_cameraController; // 0x98 + LegoEntityList* m_entityList; // 0x9c + LegoCacheSoundList* m_cacheSoundList; // 0xa0 + MxBool m_destroyed; // 0xa4 + MxCoreSet m_set0xa8; // 0xa8 + MxPresenterList m_controlPresenters; // 0xb8 + MxCoreSet m_set0xd0; // 0xd0 + list m_list0xe0; // 0xe0 + MxS32 m_scriptIndex; // 0xec + LegoHideAnimPresenter* m_hideAnimPresenter; // 0xf0 + MxS16 m_startupTicks; // 0xf4 + MxBool m_worldStarted; // 0xf6 + undefined m_unk0xf7; // 0xf7 }; -// SYNTHETIC: LEGO1 0x1001eed0 -// MxPresenterListCursor::`scalar deleting destructor' +// clang-format off +// TEMPLATE: LEGO1 0x1001d780 +// _Tree >::_Kfn,CoreSetCompare,allocator >::~_Tree >::_Kfn,CoreSetCompare,allocator > -// TEMPLATE: LEGO1 0x1001ef40 -// MxPtrListCursor::~MxPtrListCursor +// TEMPLATE: LEGO1 0x1001d850 +// _Tree >::_Kfn,CoreSetCompare,allocator >::iterator::_Inc -// SYNTHETIC: LEGO1 0x1001ef90 -// MxListCursor::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x1001d890 +// _Tree >::_Kfn,CoreSetCompare,allocator >::erase -// SYNTHETIC: LEGO1 0x1001f000 -// MxPtrListCursor::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x1001dcf0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Erase -// TEMPLATE: LEGO1 0x1001f070 -// MxListCursor::~MxListCursor +// TEMPLATE: LEGO1 0x1001dd30 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Init -// FUNCTION: LEGO1 0x1001f0c0 -// MxPresenterListCursor::~MxPresenterListCursor +// TEMPLATE: LEGO1 0x1001ddf0 +// list >::~list > -// TEMPLATE: LEGO1 0x10020760 -// MxListCursor::MxListCursor +// TEMPLATE: LEGO1 0x1001df50 +// List::~List + +// TEMPLATE: LEGO1 0x1001de60 +// list >::_Buynode + +// TEMPLATE: LEGO1 0x1001de90 +// set >::~set > + +// TEMPLATE: LEGO1 0x1001df00 +// Set::~Set + +// TEMPLATE: LEGO1 0x1001f590 +// list >::erase + +// TEMPLATE: LEGO1 0x100208b0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::insert + +// TEMPLATE: LEGO1 0x10020b20 +// _Tree >::_Kfn,CoreSetCompare,allocator >::iterator::_Dec + +// XTEMPLATE LEGO1 0x10020b70 + +// TEMPLATE: LEGO1 0x10020bb0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Buynode + +// TEMPLATE: LEGO1 0x10020bd0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Insert + +// TEMPLATE: LEGO1 0x10020e50 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Lrotate + +// TEMPLATE: LEGO1 0x10020eb0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Rrotate + +// TEMPLATE: LEGO1 0x10021340 +// _Tree >::_Kfn,CoreSetCompare,allocator >::find + +// TEMPLATE: LEGO1 0x10022360 +// ?_Construct@@YAXPAPAVMxCore@@ABQAV1@@Z + +// GLOBAL: LEGO1 0x100f11a0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Nil +// clang-format on #endif // LEGOWORLD_H diff --git a/LEGO1/lego/legoomni/include/legoworldlist.h b/LEGO1/lego/legoomni/include/legoworldlist.h index 339f5393..577d310f 100644 --- a/LEGO1/lego/legoomni/include/legoworldlist.h +++ b/LEGO1/lego/legoomni/include/legoworldlist.h @@ -22,10 +22,7 @@ class LegoWorldList : public MxPtrList { LegoWorldList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x100598d0 - virtual MxS8 Compare(LegoWorld* p_a, LegoWorld* p_b) override - { - return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; - }; // vtable+0x14 + MxS8 Compare(LegoWorld* p_a, LegoWorld* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 // SYNTHETIC: LEGO1 0x10059a00 // LegoWorldList::`scalar deleting destructor' @@ -77,6 +74,9 @@ class LegoWorldListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x100599f0 // MxPtrList::Destroy +// TEMPLATE: LEGO1 0x10059a70 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x10059ac0 // MxCollection::`scalar deleting destructor' @@ -86,4 +86,7 @@ class LegoWorldListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x10059be0 // MxPtrList::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x1005b740 +// MxList::DeleteEntry + #endif // LEGOWORLDLIST_H diff --git a/LEGO1/lego/legoomni/include/legoworldpresenter.h b/LEGO1/lego/legoomni/include/legoworldpresenter.h index f3dbba30..a9a7f324 100644 --- a/LEGO1/lego/legoomni/include/legoworldpresenter.h +++ b/LEGO1/lego/legoomni/include/legoworldpresenter.h @@ -8,28 +8,28 @@ class LegoWorldPresenter : public LegoEntityPresenter { public: LegoWorldPresenter(); - virtual ~LegoWorldPresenter() override; // vtable+0x0 + ~LegoWorldPresenter() override; // vtable+0x00 - __declspec(dllexport) static void configureLegoWorldPresenter(MxS32 p_legoWorldPresenterQuality); + static void configureLegoWorldPresenter(MxS32 p_legoWorldPresenterQuality); // FUNCTION: LEGO1 0x10066630 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0608 return "LegoWorldPresenter"; } // FUNCTION: LEGO1 0x10066640 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoWorldPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c - virtual void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void ParseExtra() override; // vtable+0x30 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 // SYNTHETIC: LEGO1 0x10066750 // LegoWorldPresenter::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/motocycle.h b/LEGO1/lego/legoomni/include/motocycle.h index e7716a33..cf3f376f 100644 --- a/LEGO1/lego/legoomni/include/motocycle.h +++ b/LEGO1/lego/legoomni/include/motocycle.h @@ -11,24 +11,24 @@ class Motocycle : public IslePathActor { Motocycle(); // FUNCTION: LEGO1 0x10035840 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f38e8 return "Motorcycle"; } // FUNCTION: LEGO1 0x10035850 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Motocycle::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual MxU32 VTable0xdc(MxType19NotificationParam&) override; // vtable+0xdc - virtual void VTable0xe4() override; // vtable+0xe4 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xdc(MxType19NotificationParam&) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x100359d0 // Motocycle::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h index e0e64ae9..4b70e9e8 100644 --- a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h +++ b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h @@ -13,24 +13,26 @@ class MxBackgroundAudioManager : public MxCore { public: MxBackgroundAudioManager(); - virtual ~MxBackgroundAudioManager() override; + ~MxBackgroundAudioManager() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 - virtual MxResult Tickle() override; // vtable+0x08 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1007eb70 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f7ac4 return "MxBackgroundAudioManager"; } // FUNCTION: LEGO1 0x1007eb80 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxBackgroundAudioManager::ClassName()) || MxCore::IsA(p_name); } + inline MxBool GetEnabled() { return m_enabled; } + void StartAction(MxParam& p_param); void StopAction(MxParam& p_param); MxResult PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c); @@ -39,7 +41,7 @@ class MxBackgroundAudioManager : public MxCore { void FUN_1007ef40(); void FadeInOrFadeOut(); - __declspec(dllexport) void Enable(MxBool p_enable); + void Enable(MxBool p_enable); virtual MxResult Create(MxAtomId& p_script, MxU32 p_frequencyMS); void Stop(); @@ -54,16 +56,16 @@ class MxBackgroundAudioManager : public MxCore { MxResult OpenMusic(MxAtomId& p_script); void DestroyMusic(); - MxBool m_musicEnabled; // 0x8 - MxDSAction m_action1; // 0xc - MxAudioPresenter* m_unk0xa0; - MxDSAction m_action2; // 0xa4 - MxAudioPresenter* m_unk0x138; - MxS32 m_unk0x13c; - MxS32 m_unk0x140; - MxS32 m_targetVolume; - MxS16 m_unk0x148; - MxAtomId m_script; + MxBool m_enabled; // 0x08 + MxDSAction m_action1; // 0x0c + MxAudioPresenter* m_unk0xa0; // 0xa0 + MxDSAction m_action2; // 0xa4 + MxAudioPresenter* m_unk0x138; // 0x138 + MxS32 m_unk0x13c; // 0x13c + MxS32 m_unk0x140; // 0x140 + MxS32 m_targetVolume; // 0x144 + MxS16 m_unk0x148; // 0x148 + MxAtomId m_script; // 0x14c }; #endif // MXBACKGROUNDAUDIOMANAGER_H diff --git a/LEGO1/lego/legoomni/include/mxcompositemediapresenter.h b/LEGO1/lego/legoomni/include/mxcompositemediapresenter.h index ed6f1335..efba804f 100644 --- a/LEGO1/lego/legoomni/include/mxcompositemediapresenter.h +++ b/LEGO1/lego/legoomni/include/mxcompositemediapresenter.h @@ -8,26 +8,26 @@ class MxCompositeMediaPresenter : public MxCompositePresenter { public: MxCompositeMediaPresenter(); - virtual ~MxCompositeMediaPresenter() override; + ~MxCompositeMediaPresenter() override; - virtual MxResult Tickle() override; // vtable+0x08 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10073f10 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f02d4 return "MxCompositeMediaPresenter"; } // FUNCTION: LEGO1 0x10073f20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxCompositeMediaPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } - virtual void StartingTickle() override; // vtable+0x1c - virtual MxResult StartAction(MxStreamController*, MxDSAction* p_action) override; // vtable+0x3c - virtual MxResult PutData() override; // vtable+0x4c + void StartingTickle() override; // vtable+0x1c + MxResult StartAction(MxStreamController*, MxDSAction* p_action) override; // vtable+0x3c + MxResult PutData() override; // vtable+0x4c private: MxS16 m_unk0x4c; // 0x4c diff --git a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h index 2db0a2e4..e12c1a25 100644 --- a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h @@ -4,49 +4,52 @@ #include "decomp.h" #include "mxcompositepresenter.h" +class LegoControlManagerEvent; +class MxVideoPresenter; + // VTABLE: LEGO1 0x100d7b88 // SIZE 0x5c class MxControlPresenter : public MxCompositePresenter { public: MxControlPresenter(); - virtual ~MxControlPresenter() override; + ~MxControlPresenter() override; // FUNCTION: LEGO1 0x10044000 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0514 return "MxControlPresenter"; } // FUNCTION: LEGO1 0x10044010 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxControlPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual MxBool VTable0x64(undefined4 p_undefined) override; // vtable+0x64 - virtual void VTable0x68(MxBool p_unk0x50); // vtable+0x68 - virtual void VTable0x6c(undefined4); // vtable+0x6c + void ReadyTickle() override; // vtable+0x18 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 + void Enable(MxBool p_enable) override; // vtable+0x54 + MxBool VTable0x64(undefined4 p_undefined) override; // vtable+0x64 + virtual void VTable0x68(MxBool p_unk0x50); // vtable+0x68 + virtual void VTable0x6c(MxS16); // vtable+0x6c + + MxBool FUN_10044480(LegoControlManagerEvent* p_event, MxPresenter* p_presenter); + MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter); private: - MxBool FUN_10044270(undefined4, undefined4, undefined4*); - MxBool FUN_10044480(undefined4, undefined4*); - void FUN_10044540(undefined2); - - undefined2 m_unk0x4c; // 0x4c - MxS16 m_unk0x4e; // 0x4e - MxBool m_unk0x50; // 0x50 - undefined2 m_unk0x52; // 0x52 - undefined2 m_unk0x54; // 0x54 - undefined4* m_unk0x58; // 0x58 + undefined2 m_unk0x4c; // 0x4c + MxS16 m_unk0x4e; // 0x4e + MxBool m_unk0x50; // 0x50 + undefined2 m_unk0x52; // 0x52 + undefined2 m_unk0x54; // 0x54 + undefined2 m_unk0x56; // 0x56 + MxS16* m_unk0x58; // 0x58 }; // SYNTHETIC: LEGO1 0x100440f0 diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h index fdfbf674..89f0d73b 100644 --- a/LEGO1/lego/legoomni/include/mxtransitionmanager.h +++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h @@ -11,20 +11,20 @@ class MxTransitionManager : public MxCore { public: MxTransitionManager(); - virtual ~MxTransitionManager() override; // vtable+0x0 + ~MxTransitionManager() override; // vtable+0x00 - __declspec(dllexport) void SetWaitIndicator(MxVideoPresenter* p_waitIndicator); + void SetWaitIndicator(MxVideoPresenter* p_waitIndicator); - virtual MxResult Tickle(); // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1004b950 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { return "MxTransitionManager"; } // FUNCTION: LEGO1 0x1004b960 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxTransitionManager::ClassName()) || MxCore::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 78eb4f75..5ba1da94 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -13,12 +13,12 @@ class Pizza : public IsleActor { public: Pizza(); - virtual ~Pizza() override; + ~Pizza() override; - virtual MxResult Tickle() override; // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10037f90 - inline const char* ClassName() const // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f038c return "Pizza"; @@ -30,7 +30,7 @@ class Pizza : public IsleActor { return !strcmp(p_name, Pizza::ClassName()) || IsleActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 // SYNTHETIC: LEGO1 0x100380e0 // Pizza::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/pizzamissionstate.h b/LEGO1/lego/legoomni/include/pizzamissionstate.h index e3867728..1b111c43 100644 --- a/LEGO1/lego/legoomni/include/pizzamissionstate.h +++ b/LEGO1/lego/legoomni/include/pizzamissionstate.h @@ -3,32 +3,34 @@ #include "legostate.h" +// SIZE 0x20 struct PizzaMissionStateEntry { public: - undefined2 m_unk0x0; + undefined2 m_unk0x00; MxU8 m_id; - undefined m_unk0x3[0x15]; + undefined m_unk0x03[0x15]; MxU16 m_color; undefined m_unk0x18[6]; }; // VTABLE: LEGO1 0x100d7408 +// SIZE 0xb0 class PizzaMissionState : public LegoState { public: // FUNCTION: LEGO1 0x10039290 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f00d4 return "PizzaMissionState"; } // FUNCTION: LEGO1 0x100392a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, PizzaMissionState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c inline MxU16 GetColor(MxU8 p_id) { return GetState(p_id)->m_color; } @@ -39,9 +41,9 @@ class PizzaMissionState : public LegoState { PizzaMissionStateEntry* GetState(MxU8 p_id); protected: - undefined4 m_unk0x8; - undefined4 m_unk0xc; - PizzaMissionStateEntry m_state[5]; + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + PizzaMissionStateEntry m_state[5]; // 0x10 }; #endif // PIZZAMISSIONSTATE_H diff --git a/LEGO1/lego/legoomni/include/pizzeria.h b/LEGO1/lego/legoomni/include/pizzeria.h index f75cf0a7..49c4960a 100644 --- a/LEGO1/lego/legoomni/include/pizzeria.h +++ b/LEGO1/lego/legoomni/include/pizzeria.h @@ -8,19 +8,19 @@ class Pizzeria : public IsleActor { public: // FUNCTION: LEGO1 0x1000e780 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0380 return "Pizzeria"; } // FUNCTION: LEGO1 0x1000e790 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Pizzeria::ClassName()) || IsleActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 // SYNTHETIC: LEGO1 0x1000e8d0 // Pizzeria::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/pizzeriastate.h b/LEGO1/lego/legoomni/include/pizzeriastate.h index 402981ff..b4d6b0fe 100644 --- a/LEGO1/lego/legoomni/include/pizzeriastate.h +++ b/LEGO1/lego/legoomni/include/pizzeriastate.h @@ -10,19 +10,19 @@ class PizzeriaState : public LegoState { PizzeriaState(); // FUNCTION: LEGO1 0x10017c20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0370 return "PizzeriaState"; } // FUNCTION: LEGO1 0x10017c30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, PizzeriaState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c // SYNTHETIC: LEGO1 0x10017ce0 // PizzeriaState::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/police.h b/LEGO1/lego/legoomni/include/police.h index 999ae4aa..d0bf5fa5 100644 --- a/LEGO1/lego/legoomni/include/police.h +++ b/LEGO1/lego/legoomni/include/police.h @@ -2,47 +2,65 @@ #define POLICE_H #include "decomp.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" #include "legoworld.h" #include "mxdsaction.h" -#include "policestate.h" #include "radio.h" +class PoliceState; + // VTABLE: LEGO1 0x100d8a80 // SIZE 0x110 // Radio at 0xf8 class Police : public LegoWorld { public: - Police(); - virtual ~Police() override; // vtable+0x0 + enum PoliceScript { + c_leftArrowCtl = 1, + c_rightArrowCtl = 2, + c_infoCtl = 3, + c_doorCtl = 4, + c_donutCtl = 5, - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + c_nickAnim = 500, + c_lauraAnim = 501, + }; + + Police(); + ~Police() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1005e1e0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0450 return "Police"; } // FUNCTION: LEGO1 0x1005e1f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Police::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x1005e300 // Police::`scalar deleting destructor' private: - Radio m_radio; // 0xf8 - PoliceState* m_policeState; // 0x108 - undefined4 m_unk0x10c; // 0x10c + MxLong HandleClick(LegoControlManagerEvent& p_param); + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleKeyPress(LegoEventNotificationParam& p_param); + + Radio m_radio; // 0xf8 + PoliceState* m_policeState; // 0x108 + LegoGameState::Area m_transitionDestination; // 0x10c }; #endif // POLICE_H diff --git a/LEGO1/lego/legoomni/include/policeentity.h b/LEGO1/lego/legoomni/include/policeentity.h index cdb89af6..acf0937b 100644 --- a/LEGO1/lego/legoomni/include/policeentity.h +++ b/LEGO1/lego/legoomni/include/policeentity.h @@ -8,14 +8,14 @@ class PoliceEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000ed60 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0328 return "PoliceEntity"; } // FUNCTION: LEGO1 0x1000ed70 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, PoliceEntity::ClassName()) || BuildingEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/policestate.h b/LEGO1/lego/legoomni/include/policestate.h index 976588a3..b5f8c055 100644 --- a/LEGO1/lego/legoomni/include/policestate.h +++ b/LEGO1/lego/legoomni/include/policestate.h @@ -3,34 +3,41 @@ #include "decomp.h" #include "legostate.h" +#include "police.h" // VTABLE: LEGO1 0x100d8af0 // SIZE 0x10 class PoliceState : public LegoState { public: PoliceState(); + ~PoliceState() override {} // FUNCTION: LEGO1 0x1005e860 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0444 return "PoliceState"; } // FUNCTION: LEGO1 0x1005e870 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, PoliceState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c // SYNTHETIC: LEGO1 0x1005e920 // PoliceState::`scalar deleting destructor' + inline undefined4 GetUnknown0x0c() { return m_unk0x0c; } + inline void SetUnknown0x0c(undefined4 p_unk0x0c) { m_unk0x0c = p_unk0x0c; } + + void FUN_1005ea40(); + private: - undefined4 m_unk0x8; // 0x8 - undefined4 m_unk0xc; // 0xc + Police::PoliceScript m_policeScript; // 0x08 + undefined4 m_unk0x0c; // 0x0c }; #endif // POLICESTATE_H diff --git a/LEGO1/lego/legoomni/include/racecar.h b/LEGO1/lego/legoomni/include/racecar.h index ddd4a9ac..462c2dbe 100644 --- a/LEGO1/lego/legoomni/include/racecar.h +++ b/LEGO1/lego/legoomni/include/racecar.h @@ -9,23 +9,23 @@ class RaceCar : public IslePathActor { public: RaceCar(); - virtual ~RaceCar() override; // vtable+0x0 + ~RaceCar() override; // vtable+0x00 // FUNCTION: LEGO1 0x10028270 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03e0 return "RaceCar"; } // FUNCTION: LEGO1 0x10028280 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RaceCar::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual MxU32 VTable0xcc() override; // vtable+0xcc + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxU32 VTable0xcc() override; // vtable+0xcc // SYNTHETIC: LEGO1 0x10028400 // RaceCar::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/racestandsentity.h b/LEGO1/lego/legoomni/include/racestandsentity.h index b2ca8ef3..5b5b83e5 100644 --- a/LEGO1/lego/legoomni/include/racestandsentity.h +++ b/LEGO1/lego/legoomni/include/racestandsentity.h @@ -7,14 +7,14 @@ // SIZE 0x68 class RaceStandsEntity : public BuildingEntity { // FUNCTION: LEGO1 0x1000efa0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0300 return "RaceStandsEntity"; } // FUNCTION: LEGO1 0x1000efb0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RaceStandsEntity::ClassName()) || BuildingEntity::IsA(p_name); } diff --git a/LEGO1/lego/legoomni/include/racestate.h b/LEGO1/lego/legoomni/include/racestate.h index bfae3525..b8daa738 100644 --- a/LEGO1/lego/legoomni/include/racestate.h +++ b/LEGO1/lego/legoomni/include/racestate.h @@ -6,8 +6,8 @@ struct RaceStateEntry { public: MxU8 m_id; - undefined m_unk0x1[1]; - MxU16 m_unk0x2; + undefined m_unk0x01[1]; + MxU16 m_unk0x02; MxU16 m_color; }; @@ -18,22 +18,25 @@ class RaceState : public LegoState { RaceState(); // FUNCTION: LEGO1 0x10016010 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f07d0 return "RaceState"; } // FUNCTION: LEGO1 0x10016020 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RaceState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1c + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c inline MxU16 GetColor(MxU8 p_id) { return GetState(p_id)->m_color; } + // SYNTHETIC: LEGO1 0x1000f6f0 + // RaceState::~RaceState + // SYNTHETIC: LEGO1 0x100160d0 // RaceState::`scalar deleting destructor' @@ -41,9 +44,9 @@ class RaceState : public LegoState { RaceStateEntry* GetState(MxU8 p_id); protected: - RaceStateEntry m_state[5]; - undefined2 m_unk0x26[2]; - undefined4 m_unk0x28; + RaceStateEntry m_state[5]; // 0x08 + undefined2 m_unk0x26[2]; // 0x26 + undefined4 m_unk0x28; // 0x28 }; #endif // RACESTATE_H diff --git a/LEGO1/lego/legoomni/include/radio.h b/LEGO1/lego/legoomni/include/radio.h index 3afb44cb..7e3cff87 100644 --- a/LEGO1/lego/legoomni/include/radio.h +++ b/LEGO1/lego/legoomni/include/radio.h @@ -1,38 +1,51 @@ #ifndef RADIO_H #define RADIO_H +#include "legocontrolmanager.h" +#include "mxactionnotificationparam.h" #include "mxcore.h" #include "radiostate.h" // VTABLE: LEGO1 0x100d6d10 +// SIZE 0x10 class Radio : public MxCore { public: Radio(); - virtual ~Radio() override; + ~Radio() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1002c8e0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f328c return "Radio"; } // FUNCTION: LEGO1 0x1002c8f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Radio::ClassName()) || MxCore::IsA(p_name); } + void Initialize(MxBool p_und); + void Play(); + void Stop(); + + inline RadioState* GetState() { return m_state; } + // SYNTHETIC: LEGO1 0x1002c970 // Radio::`scalar deleting destructor' private: - RadioState* m_state; // 0x08 - MxBool m_unk0xc; // 0x0c - void CreateRadioState(); + + RadioState* m_state; // 0x08 + MxBool m_unk0x0c; // 0x0c + MxBool m_audioEnabled; // 0x0d + + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleClick(LegoControlManagerEvent& p_param); }; #endif // RADIO_H diff --git a/LEGO1/lego/legoomni/include/radiostate.h b/LEGO1/lego/legoomni/include/radiostate.h index 68dc154a..6dcdafd9 100644 --- a/LEGO1/lego/legoomni/include/radiostate.h +++ b/LEGO1/lego/legoomni/include/radiostate.h @@ -2,6 +2,7 @@ #define RADIOSTATE_H #include "legostate.h" +#include "mxdsaction.h" // VTABLE: LEGO1 0x100d6d28 // SIZE 0x30 @@ -10,22 +11,34 @@ class RadioState : public LegoState { RadioState(); // FUNCTION: LEGO1 0x1002cf60 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f04f8 return "RadioState"; } // FUNCTION: LEGO1 0x1002cf70 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RadioState::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool VTable0x14() override; // vtable+0x14 + MxBool VTable0x14() override; // vtable+0x14 // SYNTHETIC: LEGO1 0x1002d020 // RadioState::`scalar deleting destructor' + + inline MxBool IsActive() { return m_active; } + + inline void SetActive(MxBool p_active) { m_active = p_active; } + + undefined4 FUN_1002d090(); + MxBool FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId); + +private: + Playlist m_unk0x08[3]; // 0x08 + MxS16 m_unk0x2c; // 0x2c + MxBool m_active; // 0x2e }; #endif // RADIOSTATE_H diff --git a/LEGO1/lego/legoomni/include/registrationbook.h b/LEGO1/lego/legoomni/include/registrationbook.h index 25e4b2d8..a28ffe5e 100644 --- a/LEGO1/lego/legoomni/include/registrationbook.h +++ b/LEGO1/lego/legoomni/include/registrationbook.h @@ -3,36 +3,83 @@ #include "legoworld.h" +class InfocenterState; +class MxEndActionNotificationParam; +class LegoControlManagerEvent; + // VTABLE: LEGO1 0x100d9928 // SIZE 0x2d0 class RegistrationBook : public LegoWorld { public: - RegistrationBook(); - virtual ~RegistrationBook() override; // vtable+0x0 + enum RegistrationBookScript { + c_alphabetCtl = 5, + c_aBitmap = 6, + c_backgroundBitmap = 36, + c_checkHiLiteBitmap = 37, + c_check0ctl = 68, + c_check1ctl = 71, + c_check2ctl = 74, + c_check3ctl = 77, + c_check4ctl = 80, + c_check5ctl = 83, + c_check6ctl = 86, + c_check7ctl = 89, + c_check8ctl = 92, + c_check9ctl = 95, + }; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 + RegistrationBook(); + ~RegistrationBook() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10076e10 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f04c8 return "RegistrationBook"; } // FUNCTION: LEGO1 0x10076e20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RegistrationBook::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x50() override; // vtable+0x50 - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 // SYNTHETIC: LEGO1 0x10076f30 // RegistrationBook::`scalar deleting destructor' + +private: + undefined4 m_unk0xf8; // 0xf8 + undefined m_unk0xfc; // 0xfc + undefined m_unk0xfd[3]; // 0xfd + undefined m_unk0x100[0x68]; // 0x100 + undefined m_unk0x168[0x118]; // 0x168 + struct { + undefined4 m_unk0x00[3]; // 0x00 + undefined2 m_unk0x0c; // 0x0c + undefined2 m_unk0x0e; // 0x0e + } m_unk0x280; // 0x280 + undefined m_unk0x290[0x28]; // 0x290 + undefined2 m_unk0x2b8; // 0x2b8 + InfocenterState* m_infocenterState; // 0x2bc + undefined m_unk0x2c0; // 0x2c0 + undefined m_unk0x2c1; // 0x2c1 + undefined m_unk0x2c2[0x02]; // 0x2c2 + undefined4 m_unk0x2c4; // 0x2c4 + undefined4 m_unk0x2c8; // 0x2c8 + undefined4 m_unk0x2cc; // 0x2cc + + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleKeyPress(MxS8 p_key); + MxLong HandleClick(LegoControlManagerEvent& p_param); + MxLong HandleNotification19(MxParam& p_param); }; #endif // REGISTRATIONBOOK_H diff --git a/LEGO1/lego/legoomni/include/score.h b/LEGO1/lego/legoomni/include/score.h index 1e801aa3..290e6ff4 100644 --- a/LEGO1/lego/legoomni/include/score.h +++ b/LEGO1/lego/legoomni/include/score.h @@ -1,10 +1,11 @@ #ifndef SCORE_H #define SCORE_H +#include "legocontrolmanager.h" #include "legoeventnotificationparam.h" +#include "legogamestate.h" #include "legoworld.h" #include "mxactionnotificationparam.h" -#include "mxtype17notificationparam.h" #include "scorestate.h" // VTABLE: LEGO1 0x100d4018 @@ -12,18 +13,18 @@ class Score : public LegoWorld { public: Score(); - virtual ~Score() override; // vtable+0x0 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + ~Score() override; // vtable+0x00 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100010c0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0050 return "Score"; } // FUNCTION: LEGO1 0x100010d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Score::ClassName()) || LegoWorld::IsA(p_name); } @@ -31,19 +32,19 @@ class Score : public LegoWorld { // SYNTHETIC: LEGO1 0x100011e0 // Score::`scalar deleting destructor' - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+18 - virtual void VTable0x50() override; // vtable+50 - virtual MxBool VTable0x5c() override; // vtable+5c - virtual MxBool VTable0x64() override; // vtable+64 - virtual void VTable0x68(MxBool p_add) override; // vtable+68 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+18 + void ReadyWorld() override; // vtable+50 + MxBool VTable0x5c() override; // vtable+5c + MxBool VTable0x64() override; // vtable+64 + void Enable(MxBool p_enable) override; // vtable+68 void Paint(); MxLong FUN_10001510(MxEndActionNotificationParam& p_param); - MxLong FUN_100016d0(MxType17NotificationParam& p_param); + MxLong FUN_100016d0(LegoControlManagerEvent& p_param); void FillArea(MxU32 p_x, MxU32 p_y, MxS16 p_color); protected: - undefined4 m_unk0xf8; + LegoGameState::Area m_unk0xf8; ScoreState* m_state; MxU8* m_surface; diff --git a/LEGO1/lego/legoomni/include/scorestate.h b/LEGO1/lego/legoomni/include/scorestate.h index fde33e1a..78609c02 100644 --- a/LEGO1/lego/legoomni/include/scorestate.h +++ b/LEGO1/lego/legoomni/include/scorestate.h @@ -4,24 +4,24 @@ #include "legostate.h" // VTABLE: LEGO1 0x100d53f8 -// SIZE 0xc +// SIZE 0x0c class ScoreState : public LegoState { public: // FUNCTION: LEGO1 0x1000de40 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0084 return "ScoreState"; - }; + } // FUNCTION: LEGO1 0x1000de50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, ScoreState::ClassName()) || LegoState::IsA(p_name); - }; + } - virtual MxBool VTable0x14() override; // vtable+0x14 - virtual MxBool SetFlag() override; // vtable+0x18 + MxBool VTable0x14() override; // vtable+0x14 + MxBool SetFlag() override; // vtable+0x18 inline MxBool GetTutorialFlag() { return m_playCubeTutorial; } inline void SetTutorialFlag(MxBool p_playCubeTutorial) { m_playCubeTutorial = p_playCubeTutorial; } @@ -30,7 +30,7 @@ class ScoreState : public LegoState { // ScoreState::`scalar deleting destructor' private: - MxBool m_playCubeTutorial; + MxBool m_playCubeTutorial; // 0x08 }; #endif // SCORESTATE_H diff --git a/LEGO1/lego/legoomni/include/skateboard.h b/LEGO1/lego/legoomni/include/skateboard.h index f4154b8d..628e26f5 100644 --- a/LEGO1/lego/legoomni/include/skateboard.h +++ b/LEGO1/lego/legoomni/include/skateboard.h @@ -11,23 +11,23 @@ class SkateBoard : public IslePathActor { SkateBoard(); // FUNCTION: LEGO1 0x1000fdd0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f041c return "SkateBoard"; } // FUNCTION: LEGO1 0x1000fde0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, SkateBoard::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd0() override; // vtable+0xd0 - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual void VTable0xe4() override; // vtable+0xe4 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd0() override; // vtable+0xd0 + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x1000ff60 // SkateBoard::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h index 8fb6b818..85e54e6b 100644 --- a/LEGO1/lego/legoomni/include/towtrack.h +++ b/LEGO1/lego/legoomni/include/towtrack.h @@ -11,26 +11,26 @@ class TowTrack : public IslePathActor { TowTrack(); // FUNCTION: LEGO1 0x1004c7c0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f03b8 return "TowTrack"; } // FUNCTION: LEGO1 0x1004c7d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, TowTrack::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 - virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - virtual void VTable0x70(float p_float) override; // vtable+0x70 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 - virtual MxU32 VTable0xdc(MxType19NotificationParam& p_param) override; // vtable+0xdc - virtual void VTable0xe4() override; // vtable+0xe4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 + MxU32 VTable0xdc(MxType19NotificationParam& p_param) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 // SYNTHETIC: LEGO1 0x1004c950 // TowTrack::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/towtrackmissionstate.h b/LEGO1/lego/legoomni/include/towtrackmissionstate.h index be2e2689..444806c5 100644 --- a/LEGO1/lego/legoomni/include/towtrackmissionstate.h +++ b/LEGO1/lego/legoomni/include/towtrackmissionstate.h @@ -10,18 +10,19 @@ class TowTrackMissionState : public LegoState { TowTrackMissionState(); // FUNCTION: LEGO1 0x1004dfa0 - inline virtual const char* ClassName() const // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f00bc return "TowTrackMissionState"; } // FUNCTION: LEGO1 0x1004dfb0 - inline virtual MxBool IsA(const char* p_name) const // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, TowTrackMissionState::ClassName()) || LegoState::IsA(p_name); } - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1C + + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c inline MxU16 GetColor(MxU8 p_id) { diff --git a/LEGO1/lego/legoomni/src/act1/act1state.cpp b/LEGO1/lego/legoomni/src/act1/act1state.cpp index 6a36e3c3..b4696e2e 100644 --- a/LEGO1/lego/legoomni/src/act1/act1state.cpp +++ b/LEGO1/lego/legoomni/src/act1/act1state.cpp @@ -1,30 +1,268 @@ #include "act1state.h" +DECOMP_SIZE_ASSERT(Act1State, 0x26c) +DECOMP_SIZE_ASSERT(Act1State::NamedPlane, 0x4c) + +// GLOBAL: ISLE 0x100f37f0 +MxS32 g_unk0x100f37f0[] = { + Act1State::e_unk953, + Act1State::e_unk954, + Act1State::e_unk955, +}; + // STUB: LEGO1 0x100334b0 -Act1State::Act1State() +Act1State::Act1State() : m_unk0x00c(0), m_unk0x00e(0), m_unk0x008(NULL), m_unk0x010(0) { - // TODO - m_unk0x1e = 0; - m_unk0x18 = 1; - m_unk0x20 = 0; - m_unk0x1f = 0; - m_unk0x21 = TRUE; - m_unk0x22 = 0; - m_unk0x1c = 1; + m_unk0x01e = 0; + m_unk0x018 = 1; + m_unk0x010 = 0; + m_unk0x020 = 0; + m_unk0x00e = 0; + m_unk0x01f = 0; + m_unk0x008 = g_unk0x100f37f0; + m_unk0x014 = -1; + m_unk0x022 = 0; + m_unk0x154 = NULL; + m_unk0x158 = NULL; + m_unk0x15c = NULL; + m_unk0x160 = NULL; + m_unk0x1b0 = NULL; + m_unk0x021 = 1; + m_unk0x01c = 1; + m_unk0x00c = _countof(g_unk0x100f37f0); + m_unk0x1b4 = NULL; + m_unk0x1b8 = NULL; + m_unk0x208 = NULL; + m_unk0x20c = NULL; + m_unk0x25c = NULL; + m_unk0x260 = NULL; + m_unk0x264 = NULL; + m_unk0x268 = NULL; + SetFlag(); } -// STUB: LEGO1 0x10033ac0 -MxResult Act1State::VTable0x1c(LegoFileStream* p_legoFileStream) +// FUNCTION: LEGO1 0x10033ac0 +MxResult Act1State::VTable0x1c(LegoFile* p_legoFile) { + if (p_legoFile->IsWriteMode()) { + p_legoFile->FUN_10006030(ClassName()); + } + + m_unk0x024.Serialize(p_legoFile); + m_unk0x070.Serialize(p_legoFile); + m_unk0x0bc.Serialize(p_legoFile); + m_unk0x108.Serialize(p_legoFile); + m_unk0x164.Serialize(p_legoFile); + m_unk0x1bc.Serialize(p_legoFile); + m_unk0x210.Serialize(p_legoFile); + + if (p_legoFile->IsWriteMode()) { + if (m_unk0x108.GetName()->Compare("") != 0) { + if (m_unk0x154) { + WriteNamedTexture(p_legoFile, m_unk0x154); + } + else { + FUN_1003f540(p_legoFile, "chwind.gif"); + } + if (m_unk0x158) { + WriteNamedTexture(p_legoFile, m_unk0x158); + } + else { + FUN_1003f540(p_legoFile, "chjetl.gif"); + } + if (m_unk0x15c) { + WriteNamedTexture(p_legoFile, m_unk0x15c); + } + else { + FUN_1003f540(p_legoFile, "chjetr.gif"); + } + } + if (m_unk0x164.GetName()->Compare("") != 0) { + if (m_unk0x1b0) { + WriteNamedTexture(p_legoFile, m_unk0x1b0); + } + else { + FUN_1003f540(p_legoFile, "jsfrnt.gif"); + } + if (m_unk0x1b4) { + WriteNamedTexture(p_legoFile, m_unk0x1b4); + } + else { + FUN_1003f540(p_legoFile, "jswnsh.gif"); + } + } + if (m_unk0x1bc.GetName()->Compare("") != 0) { + if (m_unk0x208) { + WriteNamedTexture(p_legoFile, m_unk0x208); + } + else { + FUN_1003f540(p_legoFile, "dbfrfn.gif"); + } + } + if (m_unk0x210.GetName()->Compare("") != 0) { + if (m_unk0x25c) { + WriteNamedTexture(p_legoFile, m_unk0x25c); + } + else { + FUN_1003f540(p_legoFile, "rcfrnt.gif"); + } + if (m_unk0x260) { + WriteNamedTexture(p_legoFile, m_unk0x260); + } + else { + FUN_1003f540(p_legoFile, "rcback.gif"); + } + if (m_unk0x264) { + WriteNamedTexture(p_legoFile, m_unk0x264); + } + else { + FUN_1003f540(p_legoFile, "rctail.gif"); + } + } + + p_legoFile->Write(&m_unk0x010, sizeof(undefined2)); + p_legoFile->Write(&m_unk0x022, sizeof(undefined)); + } + else if (p_legoFile->IsReadMode()) { + if (m_unk0x108.GetName()->Compare("") != 0) { + m_unk0x154 = ReadNamedTexture(p_legoFile); + if (m_unk0x154 == NULL) { + return FAILURE; + } + + m_unk0x158 = ReadNamedTexture(p_legoFile); + if (m_unk0x158 == NULL) { + return FAILURE; + } + + m_unk0x15c = ReadNamedTexture(p_legoFile); + if (m_unk0x15c == NULL) { + return FAILURE; + } + } + if (m_unk0x164.GetName()->Compare("") != 0) { + m_unk0x1b0 = ReadNamedTexture(p_legoFile); + if (m_unk0x1b0 == NULL) { + return FAILURE; + } + + m_unk0x1b4 = ReadNamedTexture(p_legoFile); + if (m_unk0x1b4 == NULL) { + return FAILURE; + } + } + if (m_unk0x1bc.GetName()->Compare("") != 0) { + m_unk0x208 = ReadNamedTexture(p_legoFile); + if (m_unk0x208 == NULL) { + return FAILURE; + } + } + if (m_unk0x210.GetName()->Compare("") != 0) { + m_unk0x25c = ReadNamedTexture(p_legoFile); + if (m_unk0x25c == NULL) { + return FAILURE; + } + + m_unk0x260 = ReadNamedTexture(p_legoFile); + if (m_unk0x260 == NULL) { + return FAILURE; + } + + m_unk0x264 = ReadNamedTexture(p_legoFile); + if (m_unk0x264 == NULL) { + return FAILURE; + } + } + + p_legoFile->Read(&m_unk0x010, sizeof(undefined2)); + p_legoFile->Read(&m_unk0x022, sizeof(undefined)); + } + // TODO return SUCCESS; } -// STUB: LEGO1 0x100346d0 +// FUNCTION: LEGO1 0x100346d0 MxBool Act1State::SetFlag() { - // TODO - return FALSE; + m_unk0x024.SetName(""); + m_unk0x070.SetName(""); + m_unk0x0bc.SetName(""); + m_unk0x022 = 0; + m_unk0x108.SetName(""); + + if (m_unk0x154) { + delete m_unk0x154; + m_unk0x154 = NULL; + } + + if (m_unk0x158) { + delete m_unk0x158; + m_unk0x158 = NULL; + } + + if (m_unk0x15c) { + delete m_unk0x15c; + m_unk0x15c = NULL; + } + + if (m_unk0x160) { + delete m_unk0x160; + m_unk0x160 = NULL; + } + + m_unk0x164.SetName(""); + + if (m_unk0x1b0) { + delete m_unk0x1b0; + m_unk0x1b0 = NULL; + } + + if (m_unk0x1b4) { + delete m_unk0x1b4; + m_unk0x1b4 = NULL; + } + + if (m_unk0x1b8) { + delete m_unk0x1b8; + m_unk0x1b8 = NULL; + } + + m_unk0x1bc.SetName(""); + + if (m_unk0x208) { + delete m_unk0x208; + m_unk0x208 = NULL; + } + + if (m_unk0x20c) { + delete m_unk0x20c; + m_unk0x20c = NULL; + } + + m_unk0x210.SetName(""); + + if (m_unk0x25c) { + delete m_unk0x25c; + m_unk0x25c = NULL; + } + + if (m_unk0x260) { + delete m_unk0x260; + m_unk0x260 = NULL; + } + + if (m_unk0x264) { + delete m_unk0x264; + m_unk0x264 = NULL; + } + + if (m_unk0x268) { + delete m_unk0x268; + m_unk0x268 = NULL; + } + + return TRUE; } // STUB: LEGO1 0x10034d00 diff --git a/LEGO1/lego/legoomni/src/act2/legoact2.cpp b/LEGO1/lego/legoomni/src/act2/legoact2.cpp index c487e9a4..247cf975 100644 --- a/LEGO1/lego/legoomni/src/act2/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/act2/legoact2.cpp @@ -1,10 +1,9 @@ #include "legoact2.h" -// STUB: LEGO1 0x1004fe10 +// FUNCTION: LEGO1 0x1004fe10 MxBool LegoAct2::VTable0x5c() { - // TODO - return FALSE; + return TRUE; } // STUB: LEGO1 0x1004ff20 @@ -29,13 +28,13 @@ MxLong LegoAct2::Notify(MxParam& p_param) } // STUB: LEGO1 0x10050a80 -void LegoAct2::VTable0x50() +void LegoAct2::ReadyWorld() { // TODO } // STUB: LEGO1 0x10050cf0 -void LegoAct2::VTable0x68(MxBool p_add) +void LegoAct2::Enable(MxBool p_enable) { // TODO } diff --git a/LEGO1/lego/legoomni/src/act2/legoact2state.cpp b/LEGO1/lego/legoomni/src/act2/legoact2state.cpp index 46b09a93..98d0d1ed 100644 --- a/LEGO1/lego/legoomni/src/act2/legoact2state.cpp +++ b/LEGO1/lego/legoomni/src/act2/legoact2state.cpp @@ -1,8 +1,9 @@ #include "legoact2state.h" -// STUB: LEGO1 0x1000df70 +DECOMP_SIZE_ASSERT(LegoAct2State, 0x10) + +// FUNCTION: LEGO1 0x1000df70 MxBool LegoAct2State::VTable0x14() { - // TODO return FALSE; } diff --git a/LEGO1/lego/legoomni/src/act3/act3.cpp b/LEGO1/lego/legoomni/src/act3/act3.cpp index e17db3dc..8df9f4e1 100644 --- a/LEGO1/lego/legoomni/src/act3/act3.cpp +++ b/LEGO1/lego/legoomni/src/act3/act3.cpp @@ -8,11 +8,10 @@ Act3::Act3() // TODO } -// STUB: LEGO1 0x10072500 +// FUNCTION: LEGO1 0x10072500 MxBool Act3::VTable0x5c() { - // TODO - return FALSE; + return TRUE; } // STUB: LEGO1 0x100726a0 @@ -21,6 +20,18 @@ Act3::~Act3() // TODO } +// STUB: LEGO1 0x100727e0 +MxBool Act3::FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) +{ + return FALSE; +} + +// STUB: LEGO1 0x10072980 +MxBool Act3::FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) +{ + return FALSE; +} + // STUB: LEGO1 0x10072c30 MxResult Act3::Create(MxDSAction& p_dsAction) { @@ -42,7 +53,7 @@ MxLong Act3::Notify(MxParam& p_param) } // STUB: LEGO1 0x10073270 -void Act3::VTable0x50() +void Act3::ReadyWorld() { // TODO } @@ -54,8 +65,18 @@ MxResult Act3::Tickle() return SUCCESS; } +// STUB: LEGO1 0x10073400 +void Act3::FUN_10073400() +{ +} + +// STUB: LEGO1 0x10073430 +void Act3::FUN_10073430() +{ +} + // STUB: LEGO1 0x10073a90 -void Act3::VTable0x68(MxBool p_add) +void Act3::Enable(MxBool p_enable) { // TODO } diff --git a/LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp b/LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp index 580f3405..b60f3ded 100644 --- a/LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp +++ b/LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp @@ -1,26 +1,48 @@ #include "lego3dwavepresenter.h" -// STUB: LEGO1 0x1004a7c0 +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(Lego3DWavePresenter, 0xa0) + +// FUNCTION: LEGO1 0x1004a7c0 MxResult Lego3DWavePresenter::AddToManager() { - // TODO - return SUCCESS; + MxResult result = MxWavePresenter::AddToManager(); + MxWavePresenter::Init(); + + if (MxOmni::IsSound3D()) { + m_is3d = TRUE; + } + + return result; } -// STUB: LEGO1 0x1004a7f0 +// FUNCTION: LEGO1 0x1004a7f0 void Lego3DWavePresenter::Destroy() { - // TODO + MxWavePresenter::Destroy(); + MxWavePresenter::Init(); + + if (MxOmni::IsSound3D()) { + m_is3d = TRUE; + } } // STUB: LEGO1 0x1004a810 void Lego3DWavePresenter::StartingTickle() { + if (MxOmni::IsSound3D()) { + m_is3d = TRUE; + } + + MxWavePresenter::StartingTickle(); + // TODO } // STUB: LEGO1 0x1004a8b0 void Lego3DWavePresenter::StreamingTickle() { + MxWavePresenter::StreamingTickle(); // TODO } diff --git a/LEGO1/lego/legoomni/src/audio/legocachesound.cpp b/LEGO1/lego/legoomni/src/audio/legocachesound.cpp index eb58278c..029879f9 100644 --- a/LEGO1/lego/legoomni/src/audio/legocachesound.cpp +++ b/LEGO1/lego/legoomni/src/audio/legocachesound.cpp @@ -1,5 +1,11 @@ #include "legocachesound.h" +#include "legoomni.h" +#include "legosoundmanager.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(LegoCacheSound, 0x88) + // FUNCTION: LEGO1 0x100064d0 LegoCacheSound::LegoCacheSound() { @@ -10,10 +16,140 @@ LegoCacheSound::LegoCacheSound() LegoCacheSound::~LegoCacheSound() { // TODO + Destroy(); } -// STUB: LEGO1 0x100066d0 +// FUNCTION: LEGO1 0x100066d0 void LegoCacheSound::Init() { - // TODO + m_dsBuffer = NULL; + m_unk0x40 = NULL; + m_unk0x58 = 0; + memset(&m_unk0x59, 0, sizeof(m_unk0x59)); + m_unk0x6a = FALSE; + m_unk0x70 = 0; + m_isLooping = TRUE; + m_unk0x6c = 79; + m_unk0x84 = 0; +} + +// STUB: LEGO1 0x10006710 +MxResult LegoCacheSound::FUN_10006710() +{ + // TODO + DSBUFFERDESC desc; + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + + if (MxOmni::IsSound3D()) { + desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D; + } + else { + desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; + } + + if (SoundManager()->GetDirectSound()->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) { + return FAILURE; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10006920 +void LegoCacheSound::Destroy() +{ + if (m_dsBuffer) { + m_dsBuffer->Stop(); + m_dsBuffer->Release(); + m_dsBuffer = NULL; + } + + delete m_unk0x40; + Init(); +} + +// STUB: LEGO1 0x10006960 +LegoCacheSound* LegoCacheSound::FUN_10006960() +{ + // TODO + return NULL; +} + +// STUB: LEGO1 0x10006a30 +MxResult LegoCacheSound::FUN_10006a30(char* p_str, MxBool) +{ + // TODO + // gets param2 from FUN_1003db10 + if (!m_unk0x40 && !m_unk0x44) { + return FAILURE; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10006b80 +void LegoCacheSound::FUN_10006b80() +{ + DWORD dwStatus; + + m_dsBuffer->GetStatus(&dwStatus); + if (dwStatus) { + m_dsBuffer->Stop(); + } + + m_unk0x58 = 0; + m_unk0x6a = FALSE; + + m_unk0x10.FUN_10011ca0(); + if (m_string0x74.GetLength() != 0) { + m_string0x74 = ""; + } +} + +// FUNCTION: LEGO1 0x10006be0 +void LegoCacheSound::FUN_10006be0() +{ + if (!m_isLooping) { + DWORD dwStatus; + m_dsBuffer->GetStatus(&dwStatus); + + if (m_unk0x70) { + if (dwStatus == 0) { + return; + } + + m_unk0x70 = 0; + } + + if (dwStatus == 0) { + m_dsBuffer->Stop(); + m_unk0x10.FUN_10011ca0(); + if (m_string0x74.GetLength() != 0) { + m_string0x74 = ""; + } + + m_unk0x58 = 0; + return; + } + } + + if (m_string0x74.GetLength() != 0 && !m_unk0x84) { + if (!m_unk0x10.FUN_100118e0(m_dsBuffer)) { + if (m_unk0x6a) { + return; + } + + m_dsBuffer->Stop(); + m_unk0x6a = TRUE; + } + else if (m_unk0x6a) { + m_dsBuffer->Play(0, 0, m_isLooping); + m_unk0x6a = FALSE; + } + } +} + +// FUNCTION: LEGO1 0x10006cd0 +void LegoCacheSound::FUN_10006cd0(undefined4, undefined4) +{ } diff --git a/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp index 9aeac8ba..edcd6b34 100644 --- a/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp +++ b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp @@ -1,5 +1,9 @@ #include "legoloadcachesoundpresenter.h" +#include "legocachesound.h" +#include "mxstreamchunk.h" +#include "mxwavepresenter.h" + DECOMP_SIZE_ASSERT(LegoLoadCacheSoundPresenter, 0x90) // FUNCTION: LEGO1 0x10018340 @@ -25,26 +29,44 @@ void LegoLoadCacheSoundPresenter::Init() // FUNCTION: LEGO1 0x100184f0 void LegoLoadCacheSoundPresenter::Destroy(MxBool p_fromDestructor) { - delete this->m_unk0x70; + delete[] this->m_unk0x70; MxWavePresenter::Destroy(p_fromDestructor); } -// STUB: LEGO1 0x10018510 +// FUNCTION: LEGO1 0x10018510 void LegoLoadCacheSoundPresenter::ReadyTickle() { - // TODO + MxStreamChunk* chunk = NextChunk(); + + if (chunk) { + WaveFormat* header = (WaveFormat*) chunk->GetData(); + m_unk0x78 = 0; + + MxU8* data = new MxU8[header->m_dataSize]; + m_unk0x70 = data; + m_unk0x74 = data; + + m_cacheSound = new LegoCacheSound; + memcpy(&m_pcmWaveFormat, &header->m_pcmWaveFormat, sizeof(m_pcmWaveFormat)); + + m_subscriber->FreeDataChunk(chunk); + ProgressTickleState(e_streaming); + } } // STUB: LEGO1 0x100185f0 void LegoLoadCacheSoundPresenter::StreamingTickle() { // TODO + EndAction(); } -// STUB: LEGO1 0x100186f0 +// FUNCTION: LEGO1 0x100186f0 void LegoLoadCacheSoundPresenter::DoneTickle() { - // TODO + if (m_unk0x7c != 0) { + EndAction(); + } } // STUB: LEGO1 0x10018700 diff --git a/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp b/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp index d31e5d1c..f0be968d 100644 --- a/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp @@ -17,19 +17,65 @@ LegoSoundManager::~LegoSoundManager() // FUNCTION: LEGO1 0x100299a0 void LegoSoundManager::Init() { - m_unk0x40 = 0; - m_unk0x3c = 0; + m_unk0x40 = NULL; + m_listener = NULL; } -// STUB: LEGO1 0x100299b0 +// FUNCTION: LEGO1 0x100299b0 void LegoSoundManager::Destroy(MxBool p_fromDestructor) { + delete m_unk0x40; + Init(); + + if (!p_fromDestructor) { + MxSoundManager::Destroy(); + } } -// STUB: LEGO1 0x100299f0 +// FUNCTION: LEGO1 0x100299f0 MxResult LegoSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) { - return MxSoundManager::Create(p_frequencyMS, p_createThread); + MxBool locked = FALSE; + MxResult result = FAILURE; + + if (MxSoundManager::Create(10, FALSE) == SUCCESS) { + m_criticalSection.Enter(); + locked = TRUE; + + if (MxOmni::IsSound3D()) { + if (m_dsBuffer->QueryInterface(IID_IDirectSound3DListener, (LPVOID*) &m_listener) != DS_OK) { + goto done; + } + + MxOmni* omni = MxOmni::GetInstance(); + LPDIRECTSOUND sound; + + if (omni && omni->GetSoundManager() && (sound = omni->GetSoundManager()->GetDirectSound())) { + DSCAPS caps; + memset(&caps, 0, sizeof(DSCAPS)); + caps.dwSize = sizeof(DSCAPS); + + if (sound->GetCaps(&caps) == S_OK && caps.dwMaxHw3DAllBuffers == 0) { + m_listener->SetDistanceFactor(0.026315790f, 0); + m_listener->SetRolloffFactor(10, 0); + } + } + } + + m_unk0x40 = new LegoUnknown100d6b4c; + result = SUCCESS; + } + +done: + if (result != SUCCESS) { + Destroy(); + } + + if (locked) { + m_criticalSection.Leave(); + } + + return result; } // FUNCTION: LEGO1 0x1002a390 @@ -38,11 +84,11 @@ void LegoSoundManager::Destroy() Destroy(FALSE); } -// STUB: LEGO1 0x1002a3a0 +// FUNCTION: LEGO1 0x1002a3a0 MxResult LegoSoundManager::Tickle() { - MxMediaManager::Tickle(); - MxAutoLocker lock(&this->m_criticalSection); + MxSoundManager::Tickle(); - return 0; // TODO: call something in unk0x40 + MxAutoLocker lock(&m_criticalSection); + return m_unk0x40->Tickle(); } diff --git a/LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp b/LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp new file mode 100644 index 00000000..563b9383 --- /dev/null +++ b/LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp @@ -0,0 +1,82 @@ +#include "legounknown100d5778.h" + +#include "legoomni.h" +#include "legounksavedatawriter.h" + +DECOMP_SIZE_ASSERT(LegoUnknown100d5778, 0x30) + +// FUNCTION: LEGO1 0x10011630 +LegoUnknown100d5778::LegoUnknown100d5778() +{ + Init(); +} + +// FUNCTION: LEGO1 0x10011670 +LegoUnknown100d5778::~LegoUnknown100d5778() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x10011680 +void LegoUnknown100d5778::Init() +{ + m_dsBuffer = NULL; + m_unk0xc = NULL; + m_unk0x10 = 0; + m_unk0x18 = 0; + m_unk0x14 = FALSE; + m_unk0x15 = FALSE; + m_unk0x2c = 79; +} + +// STUB: LEGO1 0x100116a0 +MxResult LegoUnknown100d5778::FUN_100116a0(LPDIRECTSOUND p_dsound, undefined4, undefined4 p_unk0x2c) +{ + m_unk0x2c = p_unk0x2c; + + if (MxOmni::IsSound3D()) { + p_dsound->QueryInterface(IID_IDirectSoundBuffer, (LPVOID*) &m_dsBuffer); + if (m_dsBuffer == NULL) { + return FAILURE; + } + + // TODO + } + + // TODO + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10011880 +void LegoUnknown100d5778::Destroy() +{ + if (m_dsBuffer) { + m_dsBuffer->Release(); + m_dsBuffer = NULL; + } + + if (m_unk0x14 && m_unk0xc && UnkSaveDataWriter()) { + if (m_unk0x15) { + UnkSaveDataWriter()->FUN_10083db0(m_unk0xc); + } + else { + UnkSaveDataWriter()->FUN_10083f10(m_unk0xc); + } + } + + Init(); +} + +// STUB: LEGO1 0x100118e0 +undefined4 LegoUnknown100d5778::FUN_100118e0(LPDIRECTSOUNDBUFFER p_dsBuffer) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10011ca0 +void LegoUnknown100d5778::FUN_10011ca0() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp b/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp new file mode 100644 index 00000000..f8469eb0 --- /dev/null +++ b/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp @@ -0,0 +1,178 @@ +#include "legounknown100d6b4c.h" + +#include "legoomni.h" +#include "legoworld.h" + +DECOMP_SIZE_ASSERT(Element100d6b4c, 0x08) +DECOMP_SIZE_ASSERT(LegoUnknown100d6b4c, 0x20) + +// FUNCTION: LEGO1 0x1003cf20 +LegoUnknown100d6b4c::~LegoUnknown100d6b4c() +{ + LegoCacheSound* sound; + + while (!m_set.empty()) { + sound = (*m_set.begin()).GetSound(); + m_set.erase(m_set.begin()); + sound->FUN_10006b80(); + delete sound; + } + + while (!m_list.empty()) { + sound = (*m_list.begin()).GetSound(); + m_list.erase(m_list.begin()); + sound->FUN_10006b80(); + // DECOMP: delete should not be inlined here + delete sound; + } +} + +// FUNCTION: LEGO1 0x1003d050 +MxResult LegoUnknown100d6b4c::Tickle() +{ +#ifdef COMPAT_MODE + Set100d6b4c::iterator setIter; + for (setIter = m_set.begin(); setIter != m_set.end(); setIter++) { +#else + for (Set100d6b4c::iterator setIter = m_set.begin(); setIter != m_set.end(); setIter++) { +#endif + LegoCacheSound* sound = (*setIter).GetSound(); + if (sound->GetUnk0x58()) { + sound->FUN_10006be0(); + } + } + + List100d6b4c::iterator listIter = m_list.begin(); + while (listIter != m_list.end()) { + LegoCacheSound* sound = (*listIter).GetSound(); + + if (sound->GetUnk0x58()) { + sound->FUN_10006be0(); + listIter++; + } + else { + sound->FUN_10006b80(); + m_list.erase(listIter++); + delete sound; + } + } + + return SUCCESS; +} + +// STUB: LEGO1 0x1003d170 +LegoCacheSound* LegoUnknown100d6b4c::FUN_1003d170(const char* p_key) +{ + // TODO + char* x = new char[strlen(p_key) + 1]; + strcpy(x, p_key); + + Set100d6b4c::iterator setIter; + for (setIter = m_set.begin(); setIter != m_set.end(); setIter++) { + if (!strcmpi((*setIter).GetName(), x)) { + return (*setIter).GetSound(); + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x1003d290 +LegoCacheSound* LegoUnknown100d6b4c::FUN_1003d290(LegoCacheSound* p_sound) +{ + Set100d6b4c::iterator it = m_set.find(Element100d6b4c(p_sound)); + if (it != m_set.end()) { + LegoCacheSound* sound = (*it).GetSound(); + + if (sound->GetUnk0x58()) { + m_list.push_back(Element100d6b4c(p_sound)); + return p_sound; + } + else { + delete p_sound; + return sound; + } + } + + m_set.insert(Element100d6b4c(p_sound)); + LegoWorld* world = CurrentWorld(); + if (world) { + world->Add(p_sound); + } + + return p_sound; +} + +// FUNCTION: LEGO1 0x1003dae0 +void LegoUnknown100d6b4c::FUN_1003dae0(char* p_one, char* p_two, MxBool p_three) +{ + // DECOMP: Second parameter is 0xe4 member of LegoPathActor subclass + FUN_1003db10(FUN_1003d170(p_one), p_two, p_three); +} + +// FUNCTION: LEGO1 0x1003db10 +LegoCacheSound* LegoUnknown100d6b4c::FUN_1003db10(LegoCacheSound* p_one, char* p_two, MxBool p_three) +{ + if (!p_one) { + return NULL; + } + + if (p_one->GetUnk0x58()) { + LegoCacheSound* result = p_one->FUN_10006960(); + + if (result) { + LegoCacheSound* t = FUN_1003d290(result); + t->FUN_10006a30(p_two, p_three); + return t; + } + } + else { + p_one->FUN_10006a30(p_two, p_three); + return p_one; + } + + return NULL; +} + +// FUNCTION: LEGO1 0x1003dc40 +void LegoUnknown100d6b4c::FUN_1003dc40(LegoCacheSound** p_und) +{ + // Called during LegoWorld::Destroy like this: + // SoundManager()->GetUnknown0x40()->FUN_1003dc40(&sound); + // LegoCacheSound*& p_sound? + +#ifdef COMPAT_MODE + Set100d6b4c::iterator setIter; + for (setIter = m_set.begin(); setIter != m_set.end(); setIter++) { +#else + for (Set100d6b4c::iterator setIter = m_set.begin(); setIter != m_set.end(); setIter++) { +#endif + if ((*setIter).GetSound() == *p_und) { + (*p_und)->FUN_10006b80(); + + delete *p_und; + m_set.erase(setIter); + return; + } + } + +#ifdef COMPAT_MODE + List100d6b4c::iterator listIter; + for (listIter = m_list.begin();; listIter++) { +#else + for (List100d6b4c::iterator listIter = m_list.begin();; listIter++) { +#endif + if (listIter == m_list.end()) { + return; + } + + LegoCacheSound* sound = (*listIter).GetSound(); + if (sound == *p_und) { + (*p_und)->FUN_10006b80(); + + delete sound; + m_list.erase(listIter); + return; + } + } +} diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index 74f8c146..734c9be7 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -7,6 +7,7 @@ #include "mxpresenter.h" #include "mxstreamer.h" #include "mxticklemanager.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxBackgroundAudioManager, 0x150) @@ -20,7 +21,7 @@ MxBackgroundAudioManager::MxBackgroundAudioManager() m_unk0x140 = 0; m_targetVolume = 0; m_unk0x148 = 0; - m_musicEnabled = FALSE; + m_enabled = FALSE; } // FUNCTION: LEGO1 0x1007ec20 @@ -38,7 +39,7 @@ MxResult MxBackgroundAudioManager::Create(MxAtomId& p_script, MxU32 p_frequencyM if (result == SUCCESS) { TickleManager()->RegisterClient(this, p_frequencyMS); - m_musicEnabled = TRUE; + m_enabled = TRUE; } return result; @@ -47,8 +48,9 @@ MxResult MxBackgroundAudioManager::Create(MxAtomId& p_script, MxU32 p_frequencyM // FUNCTION: LEGO1 0x1007ed20 MxResult MxBackgroundAudioManager::OpenMusic(MxAtomId& p_script) { - if (m_script.GetInternal()) + if (m_script.GetInternal()) { DestroyMusic(); + } MxResult result = FAILURE; @@ -69,7 +71,7 @@ void MxBackgroundAudioManager::DestroyMusic() ds.SetUnknown24(-2); DeleteObject(ds); Streamer()->Close(m_script.GetInternal()); - m_musicEnabled = FALSE; + m_enabled = FALSE; } } @@ -79,16 +81,15 @@ MxResult MxBackgroundAudioManager::Tickle() switch (m_unk0x13c) { case MxPresenter::e_starting: FadeInOrFadeOut(); - return SUCCESS; + break; case MxPresenter::e_streaming: FUN_1007ee70(); - return SUCCESS; + break; case MxPresenter::e_repeating: FUN_1007ef40(); - return SUCCESS; - default: - return SUCCESS; } + + return SUCCESS; } // FUNCTION: LEGO1 0x1007ee70 @@ -111,19 +112,23 @@ void MxBackgroundAudioManager::FUN_1007ee70() // FUNCTION: LEGO1 0x1007ef40 void MxBackgroundAudioManager::FUN_1007ef40() { - MxU32 compare; - MxU32 volume; + MxS32 compare, volume; + if (m_unk0xa0 == NULL) { if (m_unk0x138) { - compare = 30; - if (m_unk0x148 == 0) { - compare = m_unk0x148; + if (m_unk0x148 != 0) { + compare = 30; } + else { + compare = m_targetVolume; + } + volume = m_unk0x138->GetVolume(); if (volume < compare) { if (m_unk0x140 + m_unk0x138->GetVolume() <= compare) { - compare = m_unk0x140 + compare; + compare = m_unk0x140 + m_unk0x138->GetVolume(); } + m_unk0x138->SetVolume(compare); } else { @@ -142,12 +147,14 @@ void MxBackgroundAudioManager::FUN_1007ef40() DeleteObject(*m_unk0xa0->GetAction()); } else { - compare = m_unk0xa0->GetVolume(); - volume = 0; - if (compare != m_unk0x140 && -1 < compare - m_unk0x140) { + if (m_unk0xa0->GetVolume() - m_unk0x140 > 0) { volume = m_unk0xa0->GetVolume() - m_unk0x140; } - m_unk0x138->SetVolume(volume); + else { + volume = 0; + } + + m_unk0xa0->SetVolume(volume); } } } @@ -155,26 +162,24 @@ void MxBackgroundAudioManager::FUN_1007ef40() // FUNCTION: LEGO1 0x1007f0e0 void MxBackgroundAudioManager::FadeInOrFadeOut() { - // This function probably is the fade in/out routine + MxS32 volume, compare; + if (m_unk0xa0 != NULL) { - undefined4 volume = m_unk0xa0->GetVolume(); - MxU32 compare = 30; - if (m_unk0x148 == 0) { + volume = m_unk0xa0->GetVolume(); + + if (m_unk0x148 != 0) { + compare = 30; + } + else { compare = m_targetVolume; } if (volume < compare) { - volume = m_unk0x140 + volume; - if (compare <= volume) { - volume = compare; - } + volume = Min(volume + m_unk0x140, compare); m_unk0xa0->SetVolume(volume); } else if (compare < volume) { - volume = volume - m_unk0x140; - if (volume <= compare) { - volume = compare; - } + volume = Max(volume - m_unk0x140, compare); m_unk0xa0->SetVolume(volume); } else { @@ -232,9 +237,10 @@ void MxBackgroundAudioManager::StopAction(MxParam& p_param) // FUNCTION: LEGO1 0x1007f2f0 MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c) { - if (!m_musicEnabled) { + if (!m_enabled) { return SUCCESS; } + if (m_action2.GetObjectId() == -1 && m_action1.GetObjectId() != p_action.GetObjectId()) { MxDSAction action; action.SetAtomId(GetCurrentAction().GetAtomId()); @@ -256,23 +262,27 @@ MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_ m_unk0x13c = p_unk0x13c; m_unk0x140 = p_unk0x140; } + return result; } + return FAILURE; } // FUNCTION: LEGO1 0x1007f470 void MxBackgroundAudioManager::Stop() { - if (m_action2.GetObjectId() != -1) + if (m_action2.GetObjectId() != -1) { DeleteObject(m_action2); + } m_unk0x138 = 0; m_action2.SetAtomId(MxAtomId()); m_action2.SetObjectId(-1); - if (m_action1.GetObjectId() != -1) + if (m_action1.GetObjectId() != -1) { DeleteObject(m_action1); + } m_unk0xa0 = 0; m_action1.SetAtomId(MxAtomId()); @@ -310,8 +320,9 @@ void MxBackgroundAudioManager::RaiseVolume() // FUNCTION: LEGO1 0x1007f5f0 void MxBackgroundAudioManager::Enable(MxBool p_enable) { - if (this->m_musicEnabled != p_enable) { - this->m_musicEnabled = p_enable; + if (this->m_enabled != p_enable) { + this->m_enabled = p_enable; + if (!p_enable) { Stop(); } diff --git a/LEGO1/lego/legoomni/src/build/dunebuggy.cpp b/LEGO1/lego/legoomni/src/build/dunebuggy.cpp index 857a316c..66fa23d2 100644 --- a/LEGO1/lego/legoomni/src/build/dunebuggy.cpp +++ b/LEGO1/lego/legoomni/src/build/dunebuggy.cpp @@ -38,7 +38,7 @@ MxU32 DuneBuggy::VTable0xcc() } // STUB: LEGO1 0x100681b0 -MxU32 DuneBuggy::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 DuneBuggy::VTable0xd4(LegoControlManagerEvent& p_param) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/build/helicopter.cpp b/LEGO1/lego/legoomni/src/build/helicopter.cpp index 9f5cc843..d4888773 100644 --- a/LEGO1/lego/legoomni/src/build/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/build/helicopter.cpp @@ -13,6 +13,9 @@ #include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(Helicopter, 0x230) +DECOMP_SIZE_ASSERT(Mx3DPointFloat, 0x14) +DECOMP_SIZE_ASSERT(Mx4DPointFloat, 0x18) +DECOMP_SIZE_ASSERT(MxMatrix, 0x48) // FUNCTION: LEGO1 0x10001e60 Helicopter::Helicopter() @@ -31,14 +34,15 @@ Helicopter::~Helicopter() MxResult Helicopter::Create(MxDSAction& p_dsAction) { MxResult result = IslePathActor::Create(p_dsAction); - LegoWorld* world = GetCurrentWorld(); + LegoWorld* world = CurrentWorld(); SetWorld(world); if (world->IsA("Act3")) { ((Act3*) GetWorld())->SetUnkown420c(this); } world = GetWorld(); - if (world) - world->VTable0x58(this); + if (world) { + world->Add(this); + } GetState(); return result; } @@ -47,25 +51,29 @@ MxResult Helicopter::Create(MxDSAction& p_dsAction) void Helicopter::GetState() { m_state = (HelicopterState*) GameState()->GetState("HelicopterState"); - if (!m_state) + if (!m_state) { m_state = (HelicopterState*) GameState()->CreateState("HelicopterState"); + } } // FUNCTION: LEGO1 0x10003360 void Helicopter::VTable0xe4() { - if (!GameState()->GetUnknown10()) { + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { VTable0xe8(0x28, TRUE, 7); } + IslePathActor::VTable0xe4(); - if (!GameState()->GetUnknown10()) { - GameState()->SetUnknown424(0x3c); - if (GetCurrentVehicle()) { - if (GetCurrentVehicle()->IsA("IslePathActor")) { - ((IslePathActor*) GetCurrentVehicle())->VTable0xe8(0x37, TRUE, 7); + + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { + GameState()->SetCurrentArea(LegoGameState::e_unk60); + if (CurrentVehicle()) { + if (CurrentVehicle()->IsA("IslePathActor")) { + ((IslePathActor*) CurrentVehicle())->VTable0xe8(0x37, TRUE, 7); } } } + m_state->SetUnknown8(0); FUN_1003ee00(m_script, 0x16); FUN_1003ee00(m_script, 0x17); @@ -84,34 +92,41 @@ void Helicopter::VTable0xe4() // FUNCTION: LEGO1 0x10003480 MxU32 Helicopter::VTable0xcc() { - if (!FUN_1003ef60()) + if (!FUN_1003ef60()) { return 1; - if (!m_world) - m_world = GetCurrentWorld(); + } + + if (!m_world) { + m_world = CurrentWorld(); + } + AnimationManager()->FUN_1005f6d0(FALSE); - if (GetCurrentVehicle()) { - if (GetCurrentVehicle()->VTable0x60() != GameState()->GetUnknownC()) { - GetCurrentVehicle()->VTable0xe4(); + + if (CurrentVehicle()) { + if (CurrentVehicle()->VTable0x60() != GameState()->GetUnknownC()) { + CurrentVehicle()->VTable0xe4(); } } - switch (GameState()->GetUnknown10()) { - case 0: + + switch (GameState()->GetCurrentAct()) { + case LegoGameState::e_act1: m_script = *g_isleScript; AnimationManager()->FUN_10064670(FALSE); VTable0xe8(0x29, TRUE, 7); - ((Isle*) GetCurrentWorld())->SetUnknown13c(0x3c); + ((Isle*) CurrentWorld())->SetUnknown13c(0x3c); FUN_10015820(TRUE, 0); TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, TRUE); SetUnknownDC(4); PlayMusic(JukeBox::e_jail); break; - case 1: + case LegoGameState::e_act2: m_script = *g_act2mainScript; break; - case 2: + case LegoGameState::e_act3: m_script = *g_act3Script; break; } + VTable0xe0(); InvokeAction(Extra::ActionType::e_start, m_script, 0x15, NULL); GetCurrentAction().SetObjectId(-1); @@ -120,37 +135,41 @@ MxU32 Helicopter::VTable0xcc() } // FUNCTION: LEGO1 0x100035e0 -MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 Helicopter::VTable0xd4(LegoControlManagerEvent& p_param) { MxU32 ret = 0; MxAtomId script; - switch (GameState()->GetUnknown10()) { - case 0: + + switch (GameState()->GetCurrentAct()) { + case LegoGameState::e_act1: script = *g_isleScript; break; - case 1: + case LegoGameState::e_act2: script = *g_act2mainScript; break; - case 2: + case LegoGameState::e_act3: script = *g_act3Script; break; } - if (p_param.GetUnknown28() == 1) { - switch (p_param.GetUnknown20()) { + + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { case 0x17: if (*g_act3Script == script) { - ((Act3*) GetCurrentWorld())->SetUnkown4270(2); + ((Act3*) CurrentWorld())->SetUnkown4270(2); TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); } - else if (m_state->GetUnkown8() != 0) + else if (m_state->GetUnkown8() != 0) { break; + } VTable0xe4(); - GameState()->SetUnknown424(0x42); + GameState()->SetCurrentArea(LegoGameState::e_unk66); ret = 1; break; case 0x18: { - if (*g_act3Script == script) + if (*g_act3Script == script) { break; + } Act1State* state = (Act1State*) GameState()->GetState("Act1State"); if (m_state->GetUnkown8() == 0) { state->SetUnknown18(4); @@ -163,8 +182,9 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) break; } case 0x19: - if (*g_act3Script == script) + if (*g_act3Script == script) { break; + } if (m_state->GetUnkown8() == 2) { m_state->SetUnknown8(3); m_world->FUN_1001fc80(this); @@ -174,13 +194,15 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) ret = 1; break; case 0x1a: - if (*g_act3Script != script) + if (*g_act3Script != script) { break; + } ret = 1; /* fall through */ case 0x1b: - if (*g_act3Script != script) + if (*g_act3Script != script) { break; + } if (m_world && m_world->GetCamera()) { Mx3DPointFloat loc, dir, lookat; loc.CopyFrom(m_world->GetCamera()->GetWorldLocation()); @@ -193,17 +215,20 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) v68.CopyFrom(m_world->GetCamera()->GetWorldUp()); va4.EqualsCross(v68, dir); v7c.EqualsCross(va4, v90); - if (ret) - if (m_world->FUN_100727e0(m_unk0x138, loc, dir, v7c)) + if (ret) { + if (((Act3*) m_world)->FUN_100727e0(m_unk0x138, loc, dir, v7c)) { break; - else if (m_world->FUN_10072980(m_unk0x138, loc, dir, v7c)) + } + else if (((Act3*) m_world)->FUN_10072980(m_unk0x138, loc, dir, v7c)) { break; + } + } } ret = 1; break; case 0x1c: - if (GameState()->GetUnknown10() == 0) { - ((Isle*) GetCurrentWorld())->SetUnknown13c(2); + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { + ((Isle*) CurrentWorld())->SetUnknown13c(2); TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); VTable0xe4(); } @@ -224,12 +249,13 @@ MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) switch (m_state->GetUnkown8()) { case 1: { - if (GameState()->GetUnknown10() == 0) { + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { ((Act1State*) GameState()->GetState("Act1State"))->SetUnknown18(4); VTable0xe8(0x2a, TRUE, 7); } - else + else { VTable0xe8(0x31, TRUE, 7); + } m_state->SetUnknown8(2); @@ -260,12 +286,13 @@ MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) at[1] = 1.25; m_world->GetCamera()->SetWorldTransform(at, dir, up); - if (GameState()->GetUnknown10() == 0) { + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { ((Act1State*) GameState()->GetState("Act1State"))->SetUnknown18(0); VTable0xe8(0x29, TRUE, 7); } - else + else { VTable0xe8(0x30, TRUE, 7); + } m_state->SetUnknown8(0); ret = 1; @@ -286,8 +313,9 @@ void Helicopter::VTable0x74(Matrix4& p_transform) else { m_roi->FUN_100a58f0(p_transform); m_roi->VTable0x14(); - if (m_cameraFlag) + if (m_cameraFlag) { FUN_10010c30(); + } } } @@ -304,10 +332,12 @@ void Helicopter::VTable0x70(float p_float) float f = m_unk0x1f0 - p_float + 3000; if (f >= 0) { float f2 = f / 3000 + 1; - if (f2 < 0) + if (f2 < 0) { f2 = 0; - if (1.0f < f2) + } + if (1.0f < f2) { f2 = 1.0f; + } Vector3 v(m_unk0x160[3]); MxMatrix mat; Vector3 v2(m_unk0x1a8[3]); @@ -325,10 +355,12 @@ void Helicopter::VTable0x70(float p_float) m_world->GetCamera()->FUN_100123e0(mat, 0); } else { - if (state == 4) - m_world->FUN_10073400(); - else - m_world->FUN_10073430(); + if (state == 4) { + ((Act3*) m_world)->FUN_10073400(); + } + else { + ((Act3*) m_world)->FUN_10073430(); + } m_unk0xdc = 4; } } @@ -339,7 +371,7 @@ MxResult HelicopterSubclass::FUN_100040a0(Vector4& p_v, float p_f) { MxU32 state = m_unk0x30; if (state == 1) { - p_v.EqualsImpl(m_unk0x0.GetData()); + p_v.EqualsImpl(m_unk0x00.GetData()); p_v[3] = acos(p_v[3]) * (1 - p_f) * 2.0; return p_v.NormalizeQuaternion(); } @@ -349,7 +381,7 @@ MxResult HelicopterSubclass::FUN_100040a0(Vector4& p_v, float p_f) return p_v.NormalizeQuaternion(); } else if (state == 3) { - double d1 = p_v.Dot(&m_unk0x0, &m_unk0x18), d2; + double d1 = p_v.Dot(&m_unk0x00, &m_unk0x18), d2; if (d1 + 1 > 0.00001) { if (1 - d1 > 0.00001) { double d = acos(d1); @@ -362,21 +394,22 @@ MxResult HelicopterSubclass::FUN_100040a0(Vector4& p_v, float p_f) d2 = p_f; } for (MxS32 i = 0; i < 4; i++) { - p_v[i] = m_unk0x18[i] * d2 + m_unk0x0[i] * d1; + p_v[i] = m_unk0x18[i] * d2 + m_unk0x00[i] * d1; } return SUCCESS; } - p_v[0] = -m_unk0x0[1]; - p_v[1] = m_unk0x0[1]; - p_v[2] = -m_unk0x0[3]; - p_v[3] = m_unk0x0[2]; + p_v[0] = -m_unk0x00[1]; + p_v[1] = m_unk0x00[1]; + p_v[2] = -m_unk0x00[3]; + p_v[3] = m_unk0x00[2]; d1 = sin((1 - p_f) * 1.570796326794895); d2 = sin(p_f * 1.570796326794895); for (MxS32 i = 0; i < 3; i++) { - p_v[i] = m_unk0x0[i] * d1 + p_v[i] * d2; + p_v[i] = m_unk0x00[i] * d1 + p_v[i] * d2; } return SUCCESS; } - else + else { return FAILURE; + } } diff --git a/LEGO1/lego/legoomni/src/build/helicopterstate.cpp b/LEGO1/lego/legoomni/src/build/helicopterstate.cpp index 368edfad..70d71a0c 100644 --- a/LEGO1/lego/legoomni/src/build/helicopterstate.cpp +++ b/LEGO1/lego/legoomni/src/build/helicopterstate.cpp @@ -1,15 +1 @@ #include "helicopterstate.h" - -// STUB: LEGO1 0x1000e0b0 -MxBool HelicopterState::VTable0x14() -{ - // TODO - return FALSE; -} - -// STUB: LEGO1 0x1000e0c0 -MxBool HelicopterState::SetFlag() -{ - // TODO - return FALSE; -} diff --git a/LEGO1/lego/legoomni/src/build/jetski.cpp b/LEGO1/lego/legoomni/src/build/jetski.cpp index 4676ea91..7a5a3dcd 100644 --- a/LEGO1/lego/legoomni/src/build/jetski.cpp +++ b/LEGO1/lego/legoomni/src/build/jetski.cpp @@ -37,7 +37,7 @@ MxU32 Jetski::VTable0xcc() } // STUB: LEGO1 0x1007e8e0 -MxU32 Jetski::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 Jetski::VTable0xd4(LegoControlManagerEvent& p_param) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index ed890166..ddb2788d 100644 --- a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -1,5 +1,10 @@ #include "legobuildingmanager.h" +DECOMP_SIZE_ASSERT(LegoBuildingManager, 0x30) + +// GLOBAL: LEGO1 0x100f37c8 +char* LegoBuildingManager::g_customizeAnimFile = NULL; + // GLOBAL: LEGO1 0x100f37cc int g_buildingManagerConfig = 1; @@ -33,9 +38,40 @@ void LegoBuildingManager::FUN_1002fa00() // TODO } +// STUB: LEGO1 0x1002fb30 +void LegoBuildingManager::FUN_1002fb30() +{ + // TODO +} + +// FUNCTION: LEGO1 0x1002ff90 +void LegoBuildingManager::SetCustomizeAnimFile(const char* p_value) +{ + if (g_customizeAnimFile != NULL) { + delete[] g_customizeAnimFile; + } + + if (p_value != NULL) { + g_customizeAnimFile = new char[strlen(p_value) + 1]; + + if (g_customizeAnimFile != NULL) { + strcpy(g_customizeAnimFile, p_value); + } + } + else { + g_customizeAnimFile = NULL; + } +} + // STUB: LEGO1 0x10030220 MxResult LegoBuildingManager::Tickle() { // TODO return SUCCESS; } + +// STUB: LEGO1 0x10030590 +void LegoBuildingManager::FUN_10030590() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 61576ece..f27a1533 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -6,11 +6,10 @@ LegoCarBuild::LegoCarBuild() // TODO } -// STUB: LEGO1 0x10022930 +// FUNCTION: LEGO1 0x10022930 MxBool LegoCarBuild::VTable0x5c() { - // TODO - return FALSE; + return TRUE; } // STUB: LEGO1 0x10022a80 @@ -43,13 +42,13 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) } // STUB: LEGO1 0x100242c0 -void LegoCarBuild::VTable0x50() +void LegoCarBuild::ReadyWorld() { // TODO } // STUB: LEGO1 0x100256c0 -void LegoCarBuild::VTable0x68(MxBool p_add) +void LegoCarBuild::Enable(MxBool p_enable) { // TODO } diff --git a/LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp b/LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp index df9a0de6..8cf60edd 100644 --- a/LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp +++ b/LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp @@ -2,17 +2,7 @@ #include "decomp.h" -DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50); // 1000acd7 -DECOMP_SIZE_ASSERT(LegoVehicleBuildState::UnkStruct, 0xc); - -// FUNCTION: LEGO1 0x10017c00 -LegoVehicleBuildState::UnkStruct::UnkStruct() -{ - m_unk0x04 = 0; - m_unk0x00 = 0; - m_unk0x06 = 0; - m_unk0x08 = 0; -} +DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) // FUNCTION: LEGO1 0x10025f30 LegoVehicleBuildState::LegoVehicleBuildState(char* p_classType) @@ -25,7 +15,7 @@ LegoVehicleBuildState::LegoVehicleBuildState(char* p_classType) } // STUB: LEGO1 0x10026120 -MxResult LegoVehicleBuildState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult LegoVehicleBuildState::VTable0x1c(LegoFile* p_legoFile) { // TODO return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/build/racecar.cpp b/LEGO1/lego/legoomni/src/build/racecar.cpp index 02f3a09d..a057b8a4 100644 --- a/LEGO1/lego/legoomni/src/build/racecar.cpp +++ b/LEGO1/lego/legoomni/src/build/racecar.cpp @@ -1,17 +1,21 @@ #include "racecar.h" +#include "legocontrolmanager.h" +#include "legoomni.h" + DECOMP_SIZE_ASSERT(RaceCar, 0x164); // FUNCTION: LEGO1 0x10028200 RaceCar::RaceCar() { - this->m_unk0x13c = 40.0; + m_unk0x13c = 40.0; } -// STUB: LEGO1 0x10028420 +// FUNCTION: LEGO1 0x10028420 RaceCar::~RaceCar() { - // TODO + ControlManager()->Unregister(this); + VTable0xe4(); } // STUB: LEGO1 0x10028490 diff --git a/LEGO1/lego/legoomni/src/common/animstate.cpp b/LEGO1/lego/legoomni/src/common/animstate.cpp index 1a08890b..c7665237 100644 --- a/LEGO1/lego/legoomni/src/common/animstate.cpp +++ b/LEGO1/lego/legoomni/src/common/animstate.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(AnimState, 0x1c); // FUNCTION: LEGO1 0x10064ff0 AnimState::AnimState() { - m_unk0xc = 0; + m_unk0x0c = 0; m_unk0x10 = NULL; m_unk0x14 = 0; m_unk0x18 = NULL; @@ -18,7 +18,7 @@ AnimState::~AnimState() } // STUB: LEGO1 0x100652d0 -MxResult AnimState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult AnimState::VTable0x1c(LegoFile* p_legoFile) { // TODO return FAILURE; diff --git a/LEGO1/lego/legoomni/src/common/gifmanager.cpp b/LEGO1/lego/legoomni/src/common/gifmanager.cpp deleted file mode 100644 index cd485b11..00000000 --- a/LEGO1/lego/legoomni/src/common/gifmanager.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "gifmanager.h" - -DECOMP_SIZE_ASSERT(GifData, 0x14); -DECOMP_SIZE_ASSERT(GifMap, 0x10); -DECOMP_SIZE_ASSERT(GifManagerBase, 0x18); -DECOMP_SIZE_ASSERT(GifManager, 0x24); - -// FUNCTION: LEGO1 0x10065c00 -GifData::~GifData() -{ - if (m_name) { - delete[] m_name; - m_name = NULL; - } - - if (m_palette) { - m_palette->Release(); - m_palette = NULL; - } - - if (m_surface) { - m_surface->Release(); - m_surface = NULL; - } - - if (m_texture) { - m_texture->Release(); - m_texture = NULL; - } -} - -// FUNCTION: LEGO1 0x10099870 -GifManager::~GifManager() -{ -} - -// FUNCTION: LEGO1 0x10099cc0 -void GifManager::FUN_10099cc0(GifData* p_data) -{ - if (p_data == NULL) - return; - -#ifdef COMPAT_MODE - GifList::iterator it; - for (it = m_list.begin(); it != m_list.end(); it++) { -#else - for (GifList::iterator it = m_list.begin(); it != m_list.end(); it++) { -#endif - if (*it == p_data) { - // TODO: This is wrong, but what is at +0xc on the iterator? - *it = NULL; - - if (p_data->m_texture->Release() == TRUE) { - delete p_data; - m_list.erase(it); - } - - return; - } - } -} diff --git a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp index 1407de1b..d4bf7cda 100644 --- a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp @@ -21,7 +21,7 @@ void LegoActionControlPresenter::ReadyTickle() ParseExtra(); ProgressTickleState(e_starting); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); if (m_compositePresenter) { if (m_action->GetDuration() == -1 || m_action->GetFlags() & 1) { m_compositePresenter->VTable0x60(this); @@ -80,8 +80,9 @@ void LegoActionControlPresenter::ParseExtra() { MxU32 len = m_action->GetExtraLength(); - if (len == 0) + if (len == 0) { return; + } len &= MAXWORD; diff --git a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp index 5d594eaa..461e84db 100644 --- a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp +++ b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp @@ -34,8 +34,9 @@ void LegoBackgroundColor::SetValue(const char* p_colorString) m_value.ToLowerCase(); LegoVideoManager* videomanager = VideoManager(); - if (!videomanager || !p_colorString) + if (!videomanager || !p_colorString) { return; + } float convertedR, convertedG, convertedB; char* colorStringCopy = strcpy(new char[strlen(p_colorString) + 1], p_colorString); @@ -43,14 +44,17 @@ void LegoBackgroundColor::SetValue(const char* p_colorString) if (!strcmp(colorStringSplit, g_set)) { colorStringSplit = strtok(0, g_delimiter); - if (colorStringSplit) + if (colorStringSplit) { m_h = (float) (atoi(colorStringSplit) * 0.01); + } colorStringSplit = strtok(0, g_delimiter); - if (colorStringSplit) + if (colorStringSplit) { m_s = (float) (atoi(colorStringSplit) * 0.01); + } colorStringSplit = strtok(0, g_delimiter); - if (colorStringSplit) + if (colorStringSplit) { m_v = (float) (atoi(colorStringSplit) * 0.01); + } ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB); videomanager->SetSkyColor(convertedR, convertedG, convertedB); diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 0bb0b066..9d81f699 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -4,9 +4,9 @@ #include "legoanimationmanager.h" #include "legoomni.h" #include "legostate.h" -#include "legostream.h" #include "legoutil.h" #include "legovideomanager.h" +#include "legoworld.h" #include "mxbackgroundaudiomanager.h" #include "mxobjectfactory.h" #include "mxstring.h" @@ -15,8 +15,9 @@ #include -// Based on the highest dword offset (0x42c) referenced in the constructor. -// There may be other members that come after. +DECOMP_SIZE_ASSERT(LegoGameState::ScoreName, 0xe) +DECOMP_SIZE_ASSERT(LegoGameState::ScoreItem, 0x2c) +DECOMP_SIZE_ASSERT(LegoGameState::Scores, 0x372) DECOMP_SIZE_ASSERT(LegoGameState, 0x430) // GLOBAL: LEGO1 0x100f3e40 @@ -31,6 +32,13 @@ const char* g_playersGSI = "Players.gsi"; // STRING: LEGO1 0x100f3e24 const char* g_historyGSI = "History.gsi"; +// This is a pointer to the end of the global variable name table, which has +// the text "END_OF_VARIABLES" in it. +// TODO: make g_endOfVariables reference the actual end of the variable array. +// GLOBAL: LEGO1 0x100f3e50 +// STRING: LEGO1 0x100f3e00 +const char* g_endOfVariables = "END_OF_VARIABLES"; + // GLOBAL: LEGO1 0x100f3e58 ColorStringStruct g_colorSaveData[43] = { {"c_dbbkfny0", "lego red"}, {"c_dbbkxly0", "lego white"}, {"c_chbasey0", "lego black"}, @@ -61,13 +69,13 @@ LegoGameState::LegoGameState() SetROIHandlerFunction(); this->m_stateCount = 0; - this->m_unk0xc = 0; + this->m_unk0x0c = 0; this->m_savePath = NULL; - this->m_unk0x424 = 0; - this->m_prevArea = 0; - this->m_unk0x42c = 0; + this->m_currentArea = e_noArea; + this->m_previousArea = e_noArea; + this->m_unk0x42c = e_noArea; this->m_isDirty = FALSE; - this->m_currentAct = -1; + this->m_loadedAct = e_actNotFound; m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68"); VariableTable()->SetVariable(m_backgroundColor); @@ -90,8 +98,9 @@ LegoGameState::~LegoGameState() if (m_stateCount) { for (MxS16 i = 0; i < m_stateCount; i++) { LegoState* state = m_stateArray[i]; - if (state) + if (state) { delete state; + } } delete[] m_stateArray; @@ -106,34 +115,42 @@ void LegoGameState::FUN_10039780(MxU8) // TODO } +// STUB: LEGO1 0x10039940 +void LegoGameState::FUN_10039940() +{ + // TODO +} + // FUNCTION: LEGO1 0x10039980 MxResult LegoGameState::Save(MxULong p_slot) { MxResult result; InfocenterState* infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); - if (!infocenterState || infocenterState->GetInfocenterBufferElement(0) == NULL) + if (!infocenterState || !infocenterState->HasRegistered()) { result = SUCCESS; + } else { result = FAILURE; MxVariableTable* variableTable = VariableTable(); MxString savePath; GetFileSavePath(&savePath, p_slot); - LegoFileStream fileStream; - if (fileStream.Open(savePath.GetData(), LegoStream::c_writeBit) != FAILURE) { + LegoFile fileStream; + if (fileStream.Open(savePath.GetData(), LegoFile::c_write) != FAILURE) { MxU32 maybeVersion = 0x1000C; fileStream.Write(&maybeVersion, 4); fileStream.Write(&m_unk0x24, 2); - fileStream.Write(&m_unk0x10, 2); - fileStream.Write(&m_unk0xc, 1); + fileStream.Write(&m_currentAct, 2); + fileStream.Write(&m_unk0x0c, 1); for (MxS32 i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) { - if (LegoStream::WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) + if (WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { return result; + } } - if (LegoStream::WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) { - if (LegoStream::WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) { + if (WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) { + if (WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) { WriteEndOfVariables(&fileStream); // TODO: Calls down to more aggregate writing functions @@ -155,26 +172,80 @@ MxResult LegoGameState::Load(MxULong) // FUNCTION: LEGO1 0x10039f00 void LegoGameState::SetSavePath(char* p_savePath) { - if (m_savePath != NULL) + if (m_savePath != NULL) { delete[] m_savePath; + } if (p_savePath) { m_savePath = new char[strlen(p_savePath) + 1]; strcpy(m_savePath, p_savePath); } - else + else { m_savePath = NULL; + } +} + +// FUNCTION: LEGO1 0x10039f70 +MxResult LegoGameState::WriteVariable(LegoStorage* p_stream, MxVariableTable* p_from, const char* p_variableName) +{ + MxResult result = FAILURE; + const char* variableValue = p_from->GetVariable(p_variableName); + + if (variableValue) { + MxU8 length = strlen(p_variableName); + if (p_stream->Write((char*) &length, 1) == SUCCESS) { + if (p_stream->Write(p_variableName, length) == SUCCESS) { + length = strlen(variableValue); + if (p_stream->Write((char*) &length, 1) == SUCCESS) { + result = p_stream->Write((char*) variableValue, length); + } + } + } + } + return result; } // FUNCTION: LEGO1 0x1003a020 -MxResult LegoGameState::WriteEndOfVariables(LegoStream* p_stream) +MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_stream) { MxU8 len = strlen(g_endOfVariables); - if (p_stream->Write(&len, 1) == SUCCESS) + if (p_stream->Write(&len, 1) == SUCCESS) { return p_stream->Write(g_endOfVariables, len); + } return FAILURE; } +// 95% match, just some instruction ordering differences on the call to +// MxVariableTable::SetVariable at the end. +// FUNCTION: LEGO1 0x1003a080 +MxS32 LegoGameState::ReadVariable(LegoStorage* p_stream, MxVariableTable* p_to) +{ + MxS32 result = 1; + MxU8 length; + + if (p_stream->Read((char*) &length, 1) == SUCCESS) { + char nameBuffer[256]; + if (p_stream->Read(nameBuffer, length) == SUCCESS) { + nameBuffer[length] = '\0'; + if (strcmp(nameBuffer, g_endOfVariables) == 0) { + // 2 -> "This was the last entry, done reading." + result = 2; + } + else { + if (p_stream->Read((char*) &length, 1) == SUCCESS) { + char valueBuffer[256]; + if (p_stream->Read(valueBuffer, length) == SUCCESS) { + result = 0; + valueBuffer[length] = '\0'; + p_to->SetVariable(nameBuffer, valueBuffer); + } + } + } + } + } + return result; +} + // FUNCTION: LEGO1 0x1003a170 void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) { @@ -182,8 +253,9 @@ void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) char path[1024] = ""; // Save path base - if (m_savePath != NULL) + if (m_savePath != NULL) { strcpy(path, m_savePath); + } // Slot: "G0", "G1", ... strcat(path, "\\G"); @@ -201,37 +273,343 @@ void LegoGameState::SerializePlayersInfo(MxS16) // TODO } -// STUB: LEGO1 0x1003a720 -void LegoGameState::FUN_1003a720(MxU32) +// FUNCTION: LEGO1 0x1003a720 +void LegoGameState::StopArea(Area p_area) { - // TODO -} - -// STUB: LEGO1 0x1003b060 -void LegoGameState::HandleAction(MxU32 p_area) -{ - m_prevArea = p_area; - BackgroundAudioManager()->Stop(); - AnimationManager()->FUN_1005ef10(); - VideoManager()->SetUnk0x554(0); - - MxAtomId* script = g_isleScript; - switch (p_area) { - case 1: - break; - case 2: - VideoManager()->SetUnk0x554(1); - script = g_infomainScript; - break; - case 3: - VideoManager()->SetUnk0x554(1); - script = g_infodoorScript; - break; - - // TODO: implement other cases + if (p_area == e_previousArea) { + p_area = m_previousArea; } - InvokeAction(Extra::ActionType::e_opendisk, *script, 0, NULL); + switch (p_area) { + case e_isle: + InvokeAction(Extra::e_stop, *g_isleScript, 0, NULL); + InvokeAction(Extra::e_close, *g_isleScript, 0, NULL); + InvokeAction(Extra::e_close, *g_sndAnimScript, 0, NULL); + break; + case e_infomain: + InvokeAction(Extra::e_stop, *g_infomainScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infomainScript, 0, NULL); + break; + case e_infodoor: + InvokeAction(Extra::e_stop, *g_infodoorScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infodoorScript, 0, NULL); + break; + case e_elevbott: + InvokeAction(Extra::e_stop, *g_elevbottScript, 0, NULL); + InvokeAction(Extra::e_close, *g_elevbottScript, 0, NULL); + break; + case e_unk6: + case e_unk7: + RemoveFromWorld(*g_isleScript, 0x41b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 1052, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x41d, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x41e, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x420, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x422, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x424, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x426, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x428, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x42a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x42b, *g_isleScript, 0); + break; + case e_unk8: + RemoveFromWorld(*g_isleScript, 0x45b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x45c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x45d, *g_isleScript, 0); + break; + case e_unk9: + RemoveFromWorld(*g_isleScript, 0x475, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x476, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x477, *g_isleScript, 0); + break; + case e_unk10: + RemoveFromWorld(*g_isleScript, 0x45f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x460, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x461, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x462, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x463, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x464, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x465, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x466, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x467, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x469, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x468, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46d, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46e, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x471, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x472, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x12, *g_isleScript, 0); + break; + case e_unk11: + RemoveFromWorld(*g_isleScript, 0x47a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47d, *g_isleScript, 0); + break; + case e_regbook: + InvokeAction(Extra::e_stop, *g_regbookScript, 0, NULL); + InvokeAction(Extra::e_close, *g_regbookScript, 0, NULL); + break; + case e_infoscor: + InvokeAction(Extra::e_stop, *g_infoscorScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infoscorScript, 0, NULL); + break; + case e_jetrace: + InvokeAction(Extra::e_stop, *g_jetraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetracerScript, 0, NULL); + break; + case e_carrace: + InvokeAction(Extra::e_stop, *g_carraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_carraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_carracerScript, 0, NULL); + break; + case e_garage: + Lego()->RemoveWorld(*g_garageScript, 0); + InvokeAction(Extra::e_stop, *g_garageScript, 0, NULL); + InvokeAction(Extra::e_close, *g_garageScript, 0, NULL); + break; + case e_unk27: + RemoveFromWorld(*g_isleScript, 0x489, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48c, *g_isleScript, 0); + break; + case e_hospital: + InvokeAction(Extra::e_stop, *g_hospitalScript, 0, NULL); + InvokeAction(Extra::e_close, *g_hospitalScript, 0, NULL); + break; + case e_police: + InvokeAction(Extra::e_stop, *g_policeScript, 0, NULL); + InvokeAction(Extra::e_close, *g_policeScript, 0, NULL); + break; + case e_unk35: + RemoveFromWorld(*g_isleScript, 0x47f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x480, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x481, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x482, *g_isleScript, 0); + break; + case e_copter: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x2f, NULL); + InvokeAction(Extra::e_stop, *g_copterScript, 0, NULL); + InvokeAction(Extra::e_close, *g_copterScript, 0, NULL); + break; + case e_dunecar: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x31, NULL); + InvokeAction(Extra::e_stop, *g_dunecarScript, 0, NULL); + InvokeAction(Extra::e_close, *g_dunecarScript, 0, NULL); + break; + case e_jetski: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x33, NULL); + InvokeAction(Extra::e_stop, *g_jetskiScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetskiScript, 0, NULL); + break; + case e_racecar: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x35, NULL); + InvokeAction(Extra::e_stop, *g_racecarScript, 0, NULL); + InvokeAction(Extra::e_close, *g_racecarScript, 0, NULL); + break; + case e_act2main: + if (m_currentArea != 2) { + InvokeAction(Extra::e_stop, *g_act2mainScript, 0, NULL); + InvokeAction(Extra::e_close, *g_act2mainScript, 0, NULL); + } + break; + case e_act3script: + if (m_currentArea != 2) { + InvokeAction(Extra::e_stop, *g_act3Script, 0, NULL); + InvokeAction(Extra::e_close, *g_act3Script, 0, NULL); + } + break; + case e_jukeboxw: + InvokeAction(Extra::e_stop, *g_jukeboxwScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jukeboxwScript, 0, NULL); + break; + case e_histbook: + InvokeAction(Extra::e_disable, *g_histbookScript, 0, NULL); + InvokeAction(Extra::e_stop, *g_histbookScript, 0, NULL); + InvokeAction(Extra::e_close, *g_histbookScript, 0, NULL); + break; + } +} + +// FUNCTION: LEGO1 0x1003b060 +void LegoGameState::SwitchArea(Area p_area) +{ + m_previousArea = m_currentArea; + m_currentArea = p_area; + + FUN_10015820(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d); + BackgroundAudioManager()->Stop(); + AnimationManager()->FUN_1005ef10(); + VideoManager()->SetUnk0x554(FALSE); + + LegoWorld* world; + + switch (p_area) { + case e_isle: + InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); + break; + case e_infomain: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_infomainScript, 0, NULL); + break; + case e_infodoor: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_infodoorScript, 0, NULL); + break; + case e_unk4: + case e_unk15: + case e_unk16: + case e_unk17: + case e_unk19: + case e_unk20: + case e_unk21: + case e_unk22: + case e_unk25: + case e_unk29: + case e_unk31: + case e_unk32: + case e_unk57: + case e_unk58: + case e_unk59: + case e_unk60: + case e_unk61: + case e_unk64: + case e_unk66: + world = FindWorld(*g_isleScript, 0); + if (world != NULL) { + if (world->GetUnknown0xd0().empty()) { + break; + } + else { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType20, NULL); + NotificationManager()->Send(world, ¶m); + } +#else + NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); +#endif + break; + } + } + InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); + break; + case e_elevbott: + InvokeAction(Extra::ActionType::e_opendisk, *g_elevbottScript, 0, NULL); + break; + case e_unk6: + case e_unk7: + world = FindWorld(*g_isleScript, 0); + + if (world == NULL) { + InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); + } + else if (!world->GetUnknown0xd0().empty()) { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType20, NULL); + NotificationManager()->Send(world, ¶m); + } +#else + NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); +#endif + } + InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1050, NULL); + break; + case e_unk8: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1114, NULL); + break; + case e_unk9: + InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1140, NULL); + break; + case e_unk10: + InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1118, NULL); + break; + case e_unk11: + InvokeAction(Extra::ActionType::e_start, *g_isleScript, 1145, NULL); + break; + case e_regbook: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_regbookScript, 0, NULL); + break; + case e_infoscor: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_infoscorScript, 0, NULL); + break; + case e_jetrace: + if (m_previousArea == e_infomain) { + m_currentArea = e_unk15; + + world = FindWorld(*g_isleScript, 0); + if (world != NULL) { + if (world->GetUnknown0xd0().empty()) { + return; + } + else { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType20, NULL); + NotificationManager()->Send(world, ¶m); + } +#else + NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); +#endif + } + return; + } + else { + InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); + break; + } + } + + InvokeAction(Extra::ActionType::e_opendisk, *g_jetraceScript, 0, NULL); + break; + case e_carrace: + if (m_previousArea == e_infomain) { + m_currentArea = e_unk19; + + world = FindWorld(*g_isleScript, 0); + if (world != NULL) { + if (world->GetUnknown0xd0().empty()) { + return; + } + else { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType20, NULL); + NotificationManager()->Send(world, ¶m); + } +#else + NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); +#endif + } + return; + } + } + + InvokeAction(Extra::ActionType::e_opendisk, *g_carraceScript, 0, NULL); + break; + case e_garage: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_garageScript, 0, NULL); + break; + + // TODO: implement other cases + case e_histbook: + VideoManager()->SetUnk0x554(TRUE); + InvokeAction(Extra::ActionType::e_opendisk, *g_histbookScript, 0, NULL); + break; + default: + break; + } } // FUNCTION: LEGO1 0x1003bac0 @@ -264,9 +642,11 @@ MxBool ROIHandlerFunction(char* p_input, char* p_output, MxU32 p_copyLen) // FUNCTION: LEGO1 0x1003bbb0 LegoState* LegoGameState::GetState(const char* p_stateName) { - for (MxS32 i = 0; i < m_stateCount; ++i) - if (m_stateArray[i]->IsA(p_stateName)) + for (MxS32 i = 0; i < m_stateCount; ++i) { + if (m_stateArray[i]->IsA(p_stateName)) { return m_stateArray[i]; + } + } return NULL; } @@ -283,9 +663,11 @@ LegoState* LegoGameState::CreateState(const char* p_stateName) void LegoGameState::RegisterState(LegoState* p_state) { MxS32 targetIndex; - for (targetIndex = 0; targetIndex < m_stateCount; ++targetIndex) - if (m_stateArray[targetIndex]->IsA(p_state->ClassName())) + for (targetIndex = 0; targetIndex < m_stateCount; ++targetIndex) { + if (m_stateArray[targetIndex]->IsA(p_state->ClassName())) { break; + } + } if (targetIndex == m_stateCount) { LegoState** newBuffer = new LegoState*[m_stateCount + 1]; @@ -300,19 +682,27 @@ void LegoGameState::RegisterState(LegoState* p_state) return; } - if (m_stateArray[targetIndex]) + if (m_stateArray[targetIndex]) { delete m_stateArray[targetIndex]; + } m_stateArray[targetIndex] = p_state; } +// FUNCTION: LEGO1 0x1003c710 +LegoGameState::ScoreName* LegoGameState::ScoreName::operator=(const ScoreName* p_other) +{ + memcpy(m_letters, p_other->m_letters, sizeof(m_letters)); + return this; +} + // STUB: LEGO1 0x1003c870 -void LegoGameState::ScoreStruct::WriteScoreHistory() +void LegoGameState::Scores::WriteScoreHistory() { // TODO } // STUB: LEGO1 0x1003ccf0 -void LegoGameState::ScoreStruct::FUN_1003ccf0(LegoFileStream&) +void LegoGameState::Scores::FUN_1003ccf0(LegoFile&) { // TODO } @@ -320,39 +710,39 @@ void LegoGameState::ScoreStruct::FUN_1003ccf0(LegoFileStream&) // FUNCTION: LEGO1 0x1003cdd0 void LegoGameState::SerializeScoreHistory(MxS16 p_flags) { - LegoFileStream stream; + LegoFile stream; MxString savePath(m_savePath); savePath += "\\"; savePath += g_historyGSI; - if (p_flags == LegoStream::c_writeBit) { + if (p_flags == LegoFile::c_write) { m_unk0xa6.WriteScoreHistory(); } - if (stream.Open(savePath.GetData(), (LegoStream::OpenFlags) p_flags) == SUCCESS) { + if (stream.Open(savePath.GetData(), p_flags) == SUCCESS) { m_unk0xa6.FUN_1003ccf0(stream); } } // FUNCTION: LEGO1 0x1003cea0 -void LegoGameState::SetSomeEnumState(undefined4 p_state) +void LegoGameState::SetCurrentAct(Act p_currentAct) { - m_unk0x10 = p_state; + m_currentAct = p_currentAct; } // FUNCTION: LEGO1 0x1003ceb0 -void LegoGameState::FUN_1003ceb0() +void LegoGameState::FindLoadedAct() { - if (FindEntityByAtomIdOrEntityId(*g_isleScript, 0)) { - m_currentAct = 0; + if (FindWorld(*g_isleScript, 0)) { + m_loadedAct = e_act1; } - else if (FindEntityByAtomIdOrEntityId(*g_act2mainScript, 0)) { - m_currentAct = 1; + else if (FindWorld(*g_act2mainScript, 0)) { + m_loadedAct = e_act2; } - else if (FindEntityByAtomIdOrEntityId(*g_act3Script, 0)) { - m_currentAct = 2; + else if (FindWorld(*g_act3Script, 0)) { + m_loadedAct = e_act3; } else { - m_currentAct = -1; + m_loadedAct = e_actNotFound; } } diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp index 8e3d7526..87454802 100644 --- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -80,6 +80,7 @@ #include "beachhouseentity.h" #include "bumpbouy.h" #include "carracestate.h" +#include "caveentity.h" #include "gasstationentity.h" #include "hospitalentity.h" #include "infocenterentity.h" @@ -90,7 +91,6 @@ #include "policeentity.h" #include "racestandsentity.h" #include "radiostate.h" -// #include "caveentity.h" // #include "jailentity.h" #include "jukebox.h" #include "jukeboxstate.h" diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 193f5c8a..2b2cc4e9 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -1,5 +1,10 @@ #include "legoplantmanager.h" +DECOMP_SIZE_ASSERT(LegoPlantManager, 0x2c) + +// GLOBAL: LEGO1 0x100f3188 +char* LegoPlantManager::g_customizeAnimFile = NULL; + // FUNCTION: LEGO1 0x10026220 LegoPlantManager::LegoPlantManager() { @@ -19,11 +24,36 @@ void LegoPlantManager::Init() } // STUB: LEGO1 0x10026360 -void LegoPlantManager::FUN_10026360(undefined4 p_world) +void LegoPlantManager::FUN_10026360(MxS32 p_scriptIndex) { // TODO } +// STUB: LEGO1 0x100263a0 +void LegoPlantManager::FUN_100263a0(undefined4 p_und) +{ + // TODO +} + +// FUNCTION: LEGO1 0x10026be0 +void LegoPlantManager::SetCustomizeAnimFile(const char* p_value) +{ + if (g_customizeAnimFile != NULL) { + delete[] g_customizeAnimFile; + } + + if (p_value != NULL) { + g_customizeAnimFile = new char[strlen(p_value) + 1]; + + if (g_customizeAnimFile != NULL) { + strcpy(g_customizeAnimFile, p_value); + } + } + else { + g_customizeAnimFile = NULL; + } +} + // STUB: LEGO1 0x10026e00 MxResult LegoPlantManager::Tickle() { @@ -31,3 +61,9 @@ MxResult LegoPlantManager::Tickle() return 0; } + +// STUB: LEGO1 0x10027120 +void LegoPlantManager::FUN_10027120() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/common/legostate.cpp b/LEGO1/lego/legoomni/src/common/legostate.cpp index c99fb708..a8c2cc6b 100644 --- a/LEGO1/lego/legoomni/src/common/legostate.cpp +++ b/LEGO1/lego/legoomni/src/common/legostate.cpp @@ -1,42 +1,59 @@ #include "legostate.h" -DECOMP_SIZE_ASSERT(LegoState, 0x08); +#include -// FUNCTION: LEGO1 0x10005f40 -LegoState::~LegoState() +DECOMP_SIZE_ASSERT(LegoState, 0x08) +DECOMP_SIZE_ASSERT(LegoState::Playlist, 0x0c) + +// FUNCTION: LEGO1 0x10014d00 +MxU32 LegoState::Playlist::Next() { + MxU32 objectId; + + switch (m_mode) { + case e_loop: + objectId = m_objectIds[m_nextIndex]; + if (m_nextIndex - m_length == -1) { + m_nextIndex = 0; + } + else { + m_nextIndex++; + } + break; + + case e_once: + objectId = m_objectIds[m_nextIndex]; + if (m_length > m_nextIndex + 1) { + m_nextIndex++; + } + break; + + case e_random: + m_nextIndex = rand() % m_length; + objectId = m_objectIds[m_nextIndex]; + break; + + case e_loopSkipFirst: + objectId = m_objectIds[m_nextIndex]; + if (m_nextIndex - m_length == -1) { + m_nextIndex = 1; + } + else { + m_nextIndex++; + } + } + + return objectId; } -// FUNCTION: LEGO1 0x10005f90 -MxBool LegoState::VTable0x14() +// FUNCTION: LEGO1 0x10014de0 +MxBool LegoState::Playlist::Contains(MxU32 p_objectId) { - return TRUE; -} + for (MxS16 i = 0; i < m_length; i++) { + if (m_objectIds[i] == p_objectId) { + return TRUE; + } + } -// FUNCTION: LEGO1 0x10005fa0 -MxBool LegoState::SetFlag() -{ return FALSE; } - -// FUNCTION: LEGO1 0x10005fb0 -MxResult LegoState::VTable0x1c(LegoFileStream* p_legoFileStream) -{ - if (p_legoFileStream->IsWriteMode()) { - p_legoFileStream->FUN_10006030(this->ClassName()); - } - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10006030 -LegoFileStream* LegoFileStream::FUN_10006030(MxString p_str) -{ - const char* data = p_str.GetData(); - MxU32 fullLength = strlen(data); - - MxU16 limitedLength = fullLength; - Write(&limitedLength, sizeof(limitedLength)); - Write(data, (MxS16) fullLength); - - return this; -} diff --git a/LEGO1/lego/legoomni/src/common/legostream.cpp b/LEGO1/lego/legoomni/src/common/legostream.cpp deleted file mode 100644 index f54d5982..00000000 --- a/LEGO1/lego/legoomni/src/common/legostream.cpp +++ /dev/null @@ -1,201 +0,0 @@ - -#include "legostream.h" - -#include "mxvariabletable.h" - -#include -#include - -// This is a pointer to the end of the global variable name table, which has -// the text "END_OF_VARIABLES" in it. -// TODO: make g_endOfVariables reference the actual end of the variable array. -// GLOBAL: LEGO1 0x100f3e50 -// STRING: LEGO1 0x100f3e00 -const char* g_endOfVariables = "END_OF_VARIABLES"; - -// Very likely but not certain sizes. -// The classes are only used on the stack in functions we have not 100% matched -// yet, we can confirm the size once we have. -DECOMP_SIZE_ASSERT(LegoStream, 0x8); -DECOMP_SIZE_ASSERT(LegoFileStream, 0xC); -DECOMP_SIZE_ASSERT(LegoMemoryStream, 0x10); - -// FUNCTION: LEGO1 0x10039f70 -MxResult LegoStream::WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName) -{ - MxResult result = FAILURE; - const char* variableValue = p_from->GetVariable(p_variableName); - - if (variableValue) { - MxU8 length = strlen(p_variableName); - if (p_stream->Write((char*) &length, 1) == SUCCESS) { - if (p_stream->Write(p_variableName, length) == SUCCESS) { - length = strlen(variableValue); - if (p_stream->Write((char*) &length, 1) == SUCCESS) - result = p_stream->Write((char*) variableValue, length); - } - } - } - return result; -} - -// 95% match, just some instruction ordering differences on the call to -// MxVariableTable::SetVariable at the end. -// FUNCTION: LEGO1 0x1003a080 -MxS32 LegoStream::ReadVariable(LegoStream* p_stream, MxVariableTable* p_to) -{ - MxS32 result = 1; - MxU8 length; - - if (p_stream->Read((char*) &length, 1) == SUCCESS) { - char nameBuffer[256]; - if (p_stream->Read(nameBuffer, length) == SUCCESS) { - nameBuffer[length] = '\0'; - if (strcmp(nameBuffer, g_endOfVariables) == 0) - // 2 -> "This was the last entry, done reading." - result = 2; - else { - if (p_stream->Read((char*) &length, 1) == SUCCESS) { - char valueBuffer[256]; - if (p_stream->Read(valueBuffer, length) == SUCCESS) { - result = 0; - valueBuffer[length] = '\0'; - p_to->SetVariable(nameBuffer, valueBuffer); - } - } - } - } - } - return result; -} - -// FUNCTION: LEGO1 0x10045ae0 -MxBool LegoStream::IsWriteMode() -{ - return m_mode == LEGOSTREAM_MODE_WRITE; -} - -// FUNCTION: LEGO1 0x10045af0 -MxBool LegoStream::IsReadMode() -{ - return m_mode == LEGOSTREAM_MODE_READ; -} - -// FUNCTION: LEGO1 0x10099080 -LegoMemoryStream::LegoMemoryStream(char* p_buffer) : LegoStream() -{ - m_buffer = p_buffer; - m_offset = 0; -} - -// FUNCTION: LEGO1 0x10099160 -MxResult LegoMemoryStream::Read(void* p_buffer, MxU32 p_size) -{ - memcpy(p_buffer, m_buffer + m_offset, p_size); - m_offset += p_size; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10099190 -MxResult LegoMemoryStream::Write(const void* p_buffer, MxU32 p_size) -{ - memcpy(m_buffer + m_offset, p_buffer, p_size); - m_offset += p_size; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100991c0 -LegoFileStream::LegoFileStream() : LegoStream() -{ - m_hFile = NULL; -} - -// FUNCTION: LEGO1 0x10099250 -LegoFileStream::~LegoFileStream() -{ - if (m_hFile != NULL) - fclose(m_hFile); -} - -// FUNCTION: LEGO1 0x100992c0 -MxResult LegoFileStream::Read(void* p_buffer, MxU32 p_size) -{ - if (m_hFile == NULL) - return FAILURE; - - return (fread(p_buffer, 1, p_size, m_hFile) == p_size) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x10099300 -MxResult LegoFileStream::Write(const void* p_buffer, MxU32 p_size) -{ - if (m_hFile == NULL) - return FAILURE; - - return (fwrite(p_buffer, 1, p_size, m_hFile) == p_size) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x10099340 -MxResult LegoFileStream::Tell(MxU32* p_offset) -{ - if (m_hFile == NULL) - return FAILURE; - - int got = ftell(m_hFile); - if (got == -1) - return FAILURE; - - *p_offset = got; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10099370 -MxResult LegoFileStream::Seek(MxU32 p_offset) -{ - if (m_hFile == NULL) - return FAILURE; - - return (fseek(m_hFile, p_offset, 0) == 0) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x100993a0 -MxResult LegoFileStream::Open(const char* p_filename, OpenFlags p_mode) -{ - char modeString[4]; - - if (m_hFile != NULL) - fclose(m_hFile); - - modeString[0] = '\0'; - if (p_mode & c_readBit) { - m_mode = LEGOSTREAM_MODE_READ; - strcat(modeString, "r"); - } - - if (p_mode & c_writeBit) { - if (m_mode != LEGOSTREAM_MODE_READ) - m_mode = LEGOSTREAM_MODE_WRITE; - strcat(modeString, "w"); - } - - if ((p_mode & c_binaryBit) != 0) - strcat(modeString, "b"); - else - strcat(modeString, "t"); - - return (m_hFile = fopen(p_filename, modeString)) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x100994a0 -MxResult LegoMemoryStream::Tell(MxU32* p_offset) -{ - *p_offset = m_offset; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100994b0 -MxResult LegoMemoryStream::Seek(MxU32 p_offset) -{ - m_offset = p_offset; - return SUCCESS; -} diff --git a/LEGO1/lego/legoomni/src/common/legotextureinfo.cpp b/LEGO1/lego/legoomni/src/common/legotextureinfo.cpp new file mode 100644 index 00000000..539c1f48 --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/legotextureinfo.cpp @@ -0,0 +1,153 @@ +#include "legotextureinfo.h" + +#include "legoomni.h" +#include "legovideomanager.h" +#include "misc/legoimage.h" +#include "misc/legotexture.h" +#include "tgl/d3drm/impl.h" + +DECOMP_SIZE_ASSERT(LegoTextureInfo, 0x10); + +// FUNCTION: LEGO1 0x10065bf0 +LegoTextureInfo::LegoTextureInfo() +{ + m_name = NULL; + m_surface = NULL; + m_palette = NULL; + m_texture = NULL; +} + +// FUNCTION: LEGO1 0x10065c00 +LegoTextureInfo::~LegoTextureInfo() +{ + if (m_name) { + delete[] m_name; + m_name = NULL; + } + + if (m_palette) { + m_palette->Release(); + m_palette = NULL; + } + + if (m_surface) { + m_surface->Release(); + m_surface = NULL; + } + + if (m_texture) { + m_texture->Release(); + m_texture = NULL; + } +} + +// FUNCTION: LEGO1 0x10065c60 +LegoTextureInfo* LegoTextureInfo::Create(const char* p_name, LegoTexture* p_texture) +{ + LegoTextureInfo* textureInfo = new LegoTextureInfo(); + + if (p_name == NULL || p_texture == NULL) { + return NULL; + } + + if (p_name) { + textureInfo->m_name = new char[strlen(p_name) + 1]; + strcpy(textureInfo->m_name, p_name); + } + + LPDIRECTDRAW pDirectDraw = VideoManager()->GetDirect3D()->DirectDraw(); + LegoImage* image = p_texture->GetImage(); + + DDSURFACEDESC desc; + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + desc.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + desc.dwWidth = image->GetWidth(); + desc.dwHeight = image->GetHeight(); + desc.ddsCaps.dwCaps = DDCAPS_OVERLAYCANTCLIP | DDCAPS_OVERLAY; + desc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); + desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8; + desc.ddpfPixelFormat.dwRGBBitCount = 8; + + MxS32 i; + LegoU8* bits; + MxU8* surface; + + if (pDirectDraw->CreateSurface(&desc, &textureInfo->m_surface, NULL) != DD_OK) { + goto done; + } + + bits = image->GetBits(); + + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + + if (textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK) { + goto done; + } + + surface = (MxU8*) desc.lpSurface; + if (desc.dwWidth == desc.lPitch) { + memcpy(surface, bits, desc.dwWidth * desc.dwHeight); + } + else { + for (i = 0; i < desc.dwHeight; i++) { + *(MxU32*) surface = *(MxU32*) bits; + surface += desc.lPitch; + bits += desc.dwWidth; + } + } + + textureInfo->m_surface->Unlock(desc.lpSurface); + + PALETTEENTRY entries[256]; + memset(entries, 0, sizeof(entries)); + + for (i = 0; i < _countof(entries); i++) { + if (i < image->GetCount()) { + entries[i].peFlags = 0; + entries[i].peRed = image->GetPaletteEntry(i).GetRed(); + entries[i].peGreen = image->GetPaletteEntry(i).GetGreen(); + entries[i].peBlue = image->GetPaletteEntry(i).GetBlue(); + } + else { + entries[i].peFlags = 0x80; + } + } + + if (pDirectDraw->CreatePalette(DDPCAPS_ALLOW256 | DDPCAPS_8BIT, entries, &textureInfo->m_palette, NULL) != DD_OK) { + goto done; + } + + textureInfo->m_surface->SetPalette(textureInfo->m_palette); + + if (((TglImpl::RendererImpl*) VideoManager()->GetRenderer()) + ->CreateTextureFromSurface(textureInfo->m_surface, &textureInfo->m_texture) != D3DRM_OK) { + goto done; + } + + textureInfo->m_texture->SetAppData((DWORD) textureInfo); + return textureInfo; + +done: + if (textureInfo->m_name != NULL) { + delete[] textureInfo->m_name; + textureInfo->m_name = NULL; + } + + if (textureInfo->m_palette != NULL) { + textureInfo->m_palette->Release(); + textureInfo->m_palette = NULL; + } + + if (textureInfo->m_surface != NULL) { + textureInfo->m_surface->Release(); + textureInfo->m_surface = NULL; + } + + if (textureInfo != NULL) { + delete textureInfo; + } + + return NULL; +} diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index a6e7e135..336c5838 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -1,16 +1,47 @@ - #include "legounksavedatawriter.h" #include "legogamestate.h" -#include "legostream.h" +#include "legoomni.h" +#include "roi/legoroi.h" -DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108); +DECOMP_SIZE_ASSERT(LegoUnkSaveDataWriter, 0x08) +DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108) + +// GLOBAL: LEGO1 0x100f80c0 +LegoSaveDataEntry3 g_saveDataInit[66]; // TODO: add data + +// GLOBAL: LEGO1 0x100fc4e4 +char* LegoUnkSaveDataWriter::g_customizeAnimFile = NULL; // GLOBAL: LEGO1 0x10104f20 LegoSaveDataEntry3 g_saveData3[66]; +// FUNCTION: LEGO1 0x10082a20 +LegoUnkSaveDataWriter::LegoUnkSaveDataWriter() +{ + m_map = new LegoUnkSaveDataMap(); + InitSaveData(); + + m_customizeAnimFile = new CustomizeAnimFileVariable("CUSTOMIZE_ANIM_FILE"); + VariableTable()->SetVariable(m_customizeAnimFile); +} + +// FUNCTION: LEGO1 0x10083270 +void LegoUnkSaveDataWriter::InitSaveData() +{ + for (MxS32 i = 0; i < 66; i++) { + g_saveData3[i] = g_saveDataInit[i]; + } +} + +// STUB: LEGO1 0x100832a0 +void LegoUnkSaveDataWriter::FUN_100832a0() +{ + // TODO +} + // FUNCTION: LEGO1 0x10083310 -MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream* p_stream) +MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStorage* p_stream) { MxResult result = FAILURE; @@ -20,26 +51,36 @@ MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream* p_stream) const LegoSaveDataEntry3* end = &g_saveData3[66]; while (TRUE) { - if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS) + if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS) { break; - if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS) { break; - if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS) + } + if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS) { break; + } if (++entry >= end) { result = SUCCESS; break; @@ -48,8 +89,41 @@ MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream* p_stream) return result; } +// STUB: LEGO1 0x10083500 +LegoROI* LegoUnkSaveDataWriter::FUN_10083500(char* p_key, MxBool p_option) +{ + // TODO + // involves an STL map with a _Nil node at 0x100fc508 + return NULL; +} + // STUB: LEGO1 0x10083db0 void LegoUnkSaveDataWriter::FUN_10083db0(LegoROI* p_roi) { // TODO } + +// STUB: LEGO1 0x10083f10 +void LegoUnkSaveDataWriter::FUN_10083f10(LegoROI* p_roi) +{ + // TODO +} + +// FUNCTION: LEGO1 0x100851a0 +void LegoUnkSaveDataWriter::SetCustomizeAnimFile(const char* p_value) +{ + if (g_customizeAnimFile != NULL) { + delete[] g_customizeAnimFile; + } + + if (p_value != NULL) { + g_customizeAnimFile = new char[strlen(p_value) + 1]; + + if (g_customizeAnimFile != NULL) { + strcpy(g_customizeAnimFile, p_value); + } + } + else { + g_customizeAnimFile = NULL; + } +} diff --git a/LEGO1/lego/legoomni/src/common/legoutil.cpp b/LEGO1/lego/legoomni/src/common/legoutil.cpp index fb207f50..3951f94f 100644 --- a/LEGO1/lego/legoomni/src/common/legoutil.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutil.cpp @@ -2,7 +2,9 @@ #include "legoomni.h" #include "legoworld.h" +#include "legoworldlist.h" #include "mxdsaction.h" +#include "mxnotificationmanager.h" #include "mxomni.h" #include "mxstreamer.h" #include "mxtypes.h" @@ -10,31 +12,49 @@ #include #include +DECOMP_SIZE_ASSERT(NamedTexture, 0x14) + +// STUB: LEGO1 0x1003e050 +void FUN_1003e050(LegoAnimPresenter* p_presenter) +{ + // TODO +} + // FUNCTION: LEGO1 0x1003e300 Extra::ActionType MatchActionString(const char* p_str) { Extra::ActionType result = Extra::ActionType::e_unknown; - if (!strcmpi("openram", p_str)) + if (!strcmpi("openram", p_str)) { result = Extra::ActionType::e_openram; - else if (!strcmpi("opendisk", p_str)) + } + else if (!strcmpi("opendisk", p_str)) { result = Extra::ActionType::e_opendisk; - else if (!strcmpi("close", p_str)) + } + else if (!strcmpi("close", p_str)) { result = Extra::ActionType::e_close; - else if (!strcmpi("start", p_str)) + } + else if (!strcmpi("start", p_str)) { result = Extra::ActionType::e_start; - else if (!strcmpi("stop", p_str)) + } + else if (!strcmpi("stop", p_str)) { result = Extra::ActionType::e_stop; - else if (!strcmpi("run", p_str)) + } + else if (!strcmpi("run", p_str)) { result = Extra::ActionType::e_run; - else if (!strcmpi("exit", p_str)) + } + else if (!strcmpi("exit", p_str)) { result = Extra::ActionType::e_exit; - else if (!strcmpi("enable", p_str)) + } + else if (!strcmpi("enable", p_str)) { result = Extra::ActionType::e_enable; - else if (!strcmpi("disable", p_str)) + } + else if (!strcmpi("disable", p_str)) { result = Extra::ActionType::e_disable; - else if (!strcmpi("notify", p_str)) + } + else if (!strcmpi("notify", p_str)) { result = Extra::ActionType::e_notify; + } return result; } @@ -99,9 +119,10 @@ void InvokeAction(Extra::ActionType p_actionId, MxAtomId& p_pAtom, int p_targetE // FUNCTION: LEGO1 0x1003e670 MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId) { - LegoWorld* world = (LegoWorld*) FindEntityByAtomIdOrEntityId(MxAtomId(p_filename, e_lowerCase2), p_entityId); + LegoWorld* world = FindWorld(MxAtomId(p_filename, e_lowerCase2), p_entityId); + if (world) { - world->VTable0x68(p_enable); + world->Enable(p_enable); return TRUE; } else { @@ -109,9 +130,35 @@ MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_enti } } -// STUB: LEGO1 0x1003e700 +// FUNCTION: LEGO1 0x1003e700 void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender) { + MxAtomId atom(p_filename, e_lowerCase2); + LegoEntity* entity = FindWorld(atom, p_entityId); + + if (entity == NULL) { + LegoWorldListCursor cursor(Lego()->GetWorldList()); + LegoWorld* world; + + while (cursor.Next(world)) { + entity = (LegoEntity*) world->Find(atom, p_entityId); + + if (entity != NULL) { + break; + } + } + } + + if (entity != NULL) { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType0, p_sender); + NotificationManager()->Send(entity, ¶m); + } +#else + NotificationManager()->Send(entity, &MxNotificationParam(c_notificationType0, p_sender)); +#endif + } } // FUNCTION: LEGO1 0x1003eae0 @@ -126,10 +173,12 @@ void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bO double sDbl = p_s; - if (p_s > 0.5f) + if (p_s > 0.5f) { calc = (1.0f - p_v) * p_s + p_v; - else + } + else { calc = (p_v + 1.0) * sDbl; + } if (calc <= 0.0) { *p_gOut = 0.0f; *p_bOut = 0.0f; @@ -188,6 +237,35 @@ MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id) return TRUE; } +// FUNCTION: LEGO1 0x1003ee80 +MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_worldAtom, MxS32 p_worldEntityId) +{ + LegoWorld* world = FindWorld(p_worldAtom, p_worldEntityId); + + if (world) { + MxCore* object = world->Find(p_entityAtom, p_entityId); + + if (object) { + world->Remove(object); + + if (!object->IsA("MxPresenter")) { + delete object; + } + else { + if (((MxPresenter*) object)->GetAction()) { + FUN_100b7220(((MxPresenter*) object)->GetAction(), MxDSAction::c_world, FALSE); + } + + ((MxPresenter*) object)->EndAction(); + } + + return TRUE; + } + } + + return FALSE; +} + // STUB: LEGO1 0x1003ef00 void FUN_1003ef00(MxBool) { @@ -205,3 +283,21 @@ MxBool FUN_1003ef60() { return TRUE; } + +// STUB: LEGO1 0x1003f3b0 +NamedTexture* ReadNamedTexture(LegoFile* p_file) +{ + return NULL; +} + +// STUB: LEGO1 0x1003f540 +void FUN_1003f540(LegoFile* p_file, const char* p_filename) +{ +} + +// FUNCTION: LEGO1 0x1003f8a0 +void WriteNamedTexture(LegoFile* p_file, NamedTexture* p_texture) +{ + p_file->FUN_10006030(*p_texture->GetName()); + p_texture->GetTexture()->Write(p_file); +} diff --git a/LEGO1/lego/legoomni/src/common/legovariables.cpp b/LEGO1/lego/legoomni/src/common/legovariables.cpp new file mode 100644 index 00000000..420aa91e --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/legovariables.cpp @@ -0,0 +1,69 @@ +#include "legovariables.h" + +#include "legobuildingmanager.h" +#include "legoomni.h" +#include "legoplantmanager.h" +#include "legounksavedatawriter.h" + +DECOMP_SIZE_ASSERT(VisibilityVariable, 0x24) +DECOMP_SIZE_ASSERT(CameraLocationVariable, 0x24) +DECOMP_SIZE_ASSERT(CursorVariable, 0x24) +DECOMP_SIZE_ASSERT(WhoAmIVariable, 0x24) +DECOMP_SIZE_ASSERT(CustomizeAnimFileVariable, 0x24) + +// GLOBAL: LEGO1 0x100f3a40 +// STRING: LEGO1 0x100f3808 +const char* g_varVISIBILITY = "VISIBILITY"; + +// GLOBAL: LEGO1 0x100f3a44 +// STRING: LEGO1 0x100f3a30 +const char* g_varCAMERALOCATION = "CAMERA_LOCATION"; + +// GLOBAL: LEGO1 0x100f3a48 +// STRING: LEGO1 0x100f3a28 +const char* g_varCURSOR = "CURSOR"; + +// GLOBAL: LEGO1 0x100f3a4c +// STRING: LEGO1 0x100f3a1c +const char* g_varWHOAMI = "WHO_AM_I"; + +// STUB: LEGO1 0x10037d00 +void VisibilityVariable::SetValue(const char* p_value) +{ + // TODO +} + +// STUB: LEGO1 0x10037d80 +void CameraLocationVariable::SetValue(const char* p_value) +{ + // TODO +} + +// FUNCTION: LEGO1 0x10037e30 +void CursorVariable::SetValue(const char* p_value) +{ +} + +// STUB: LEGO1 0x10037e40 +void WhoAmIVariable::SetValue(const char* p_value) +{ + // TODO +} + +// FUNCTION: LEGO1 0x10085aa0 +CustomizeAnimFileVariable::CustomizeAnimFileVariable(const char* p_key) +{ + m_key = p_key; + m_key.ToUpperCase(); +} + +// FUNCTION: LEGO1 0x10085b50 +void CustomizeAnimFileVariable::SetValue(const char* p_value) +{ + // STRING: LEGO1 0x100fc4f4 + if (strcmp(m_key.GetData(), "CUSTOMIZE_ANIM_FILE") == 0) { + UnkSaveDataWriter()->SetCustomizeAnimFile(p_value); + PlantManager()->SetCustomizeAnimFile(p_value); + BuildingManager()->SetCustomizeAnimFile(p_value); + } +} diff --git a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp index d3971150..fe1543a2 100644 --- a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp @@ -57,10 +57,12 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller if (presenter->StartAction(p_controller, action) == SUCCESS) { presenter->SetTickleState(e_idle); - if (presenter->IsA("MxVideoPresenter")) + if (presenter->IsA("MxVideoPresenter")) { VideoManager()->UnregisterPresenter(*presenter); - else if (presenter->IsA("MxAudioPresenter")) + } + else if (presenter->IsA("MxAudioPresenter")) { SoundManager()->UnregisterPresenter(*presenter); + } success = TRUE; } @@ -70,8 +72,9 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller action->SetOrigin(this); m_list.push_back(presenter); } - else if (presenter) + else if (presenter) { delete presenter; + } } if (!m_compositePresenter) { @@ -97,8 +100,9 @@ void MxCompositeMediaPresenter::StartingTickle() (*it)->Tickle(); if ((*it)->GetCurrentTickleState() == e_streaming || - ((*it)->GetAction() && (*it)->GetAction()->GetStartTime())) + ((*it)->GetAction() && (*it)->GetAction()->GetStartTime())) { m_unk0x4c++; + } } } @@ -107,8 +111,9 @@ void MxCompositeMediaPresenter::StartingTickle() m_unk0x4c = 0; for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { - if (!(*it)->GetAction()->GetStartTime()) + if (!(*it)->GetAction()->GetStartTime()) { m_unk0x4c++; + } } } } @@ -145,8 +150,9 @@ MxResult MxCompositeMediaPresenter::Tickle() case e_repeating: case e_unk5: case e_done: { - for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { (*it)->Tickle(); + } break; } default: @@ -162,8 +168,9 @@ MxResult MxCompositeMediaPresenter::PutData() MxAutoLocker lock(&m_criticalSection); if (m_currentTickleState >= e_streaming && m_currentTickleState <= e_done) { - for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { (*it)->PutData(); + } } return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index 481bd9c5..01d5bb3a 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -1,33 +1,121 @@ #include "legocontrolmanager.h" -// STUB: LEGO1 0x10028520 +#include "legoeventnotificationparam.h" +#include "legoomni.h" +#include "legovideomanager.h" +#include "mxcontrolpresenter.h" +#include "mxpresenter.h" +#include "mxticklemanager.h" + +DECOMP_SIZE_ASSERT(LegoControlManager, 0x60) +DECOMP_SIZE_ASSERT(LegoControlManagerEvent, 0x2c) + +// FUNCTION: LEGO1 0x10028520 LegoControlManager::LegoControlManager() { - // TODO + m_presenterList = NULL; + m_unk0x08 = 0; + m_unk0x0c = 0; + m_unk0x10 = FALSE; + m_unk0x14 = NULL; + TickleManager()->RegisterClient(this, 10); } -// STUB: LEGO1 0x10028d60 +// FUNCTION: LEGO1 0x10028d60 LegoControlManager::~LegoControlManager() { - // TODO + TickleManager()->UnregisterClient(this); } -// STUB: LEGO1 0x10028df0 +// FUNCTION: LEGO1 0x10028df0 void LegoControlManager::FUN_10028df0(MxPresenterList* p_presenterList) { - // TODO + m_presenterList = p_presenterList; + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; } -// STUB: LEGO1 0x10028e10 +// FUNCTION: LEGO1 0x10028e10 void LegoControlManager::Register(MxCore* p_listener) { - // TODO + m_notifyList.Append(p_listener); } -// STUB: LEGO1 0x10028ea0 +// FUNCTION: LEGO1 0x10028ea0 void LegoControlManager::Unregister(MxCore* p_listener) { - // TODO + LegoNotifyListCursor cursor(&m_notifyList); + if (cursor.Find(p_listener)) { + cursor.Detach(); + } +} + +// FUNCTION: LEGO1 0x10029210 +MxBool LegoControlManager::FUN_10029210(LegoEventNotificationParam& p_param, MxPresenter* p_presenter) +{ + if (m_presenterList != NULL && m_presenterList->GetCount() != 0) { + m_unk0x14 = p_presenter; + + if (p_param.GetType() == c_notificationButtonUp || p_param.GetType() == c_notificationButtonDown) { + m_event.SetType(p_param.GetType()); + m_event.SetSender(p_param.GetSender()); + m_event.SetModifier(p_param.GetModifier()); + m_event.SetX(p_param.GetX()); + m_event.SetY(p_param.GetY()); + m_event.SetKey(p_param.GetKey()); + + if (p_param.GetType() == c_notificationButtonUp) { + if (m_unk0x10 == TRUE) { + m_unk0x10 = FALSE; + return TRUE; + } + + if (g_unk0x100f31b0 != -1 && g_unk0x100f31b4 != NULL) { + if (m_unk0x08 == 2) { + return FUN_10029750(); + } + else { + m_unk0x0c = 1; + return TRUE; + } + } + } + else if (p_param.GetType() == c_notificationButtonDown) { + if (m_unk0x0c == 1) { + m_unk0x10 = TRUE; + return TRUE; + } + else { + return FUN_10029630(); + } + } + } + + return FALSE; + } + else { + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; + + return FALSE; + } +} + +// FUNCTION: LEGO1 0x100292e0 +void LegoControlManager::FUN_100292e0() +{ + LegoNotifyListCursor cursor(&m_notifyList); + MxCore* target; + + // The usual cursor.Next() loop doesn't match here, even though + // the logic is the same. It does match when "deconstructed" into + // the following Head(), Current() and NextFragment() calls, + // but this seems unlikely to be the original code. + cursor.Head(); + while (cursor.Current(target)) { + cursor.NextFragment(); + target->Notify(m_event); + } } // STUB: LEGO1 0x100293c0 @@ -35,10 +123,83 @@ void LegoControlManager::FUN_100293c0(undefined4, const char*, undefined2) { } -// STUB: LEGO1 0x10029600 +// FUNCTION: LEGO1 0x100294e0 +MxControlPresenter* LegoControlManager::FUN_100294e0(MxS32 p_x, MxS32 p_y) +{ + if (m_presenterList) { + MxPresenterListCursor cursor(m_presenterList); + MxPresenter* control; + MxVideoPresenter* presenter = (MxVideoPresenter*) VideoManager()->GetPresenterAt(p_x, p_y); + + if (presenter) { + while (cursor.Next(control)) { + if (((MxControlPresenter*) control)->FUN_10044270(p_x, p_y, presenter)) { + return (MxControlPresenter*) control; + } + } + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10029600 MxResult LegoControlManager::Tickle() { - // TODO - + if (m_unk0x08 == 2 && m_unk0x0c == 1) { + m_event.SetType(c_notificationButtonUp); + FUN_10029750(); + return 0; + } + else if (m_unk0x08 == 1) { + m_unk0x08 = 2; + } return 0; } + +// FUNCTION: LEGO1 0x10029630 +MxBool LegoControlManager::FUN_10029630() +{ + MxPresenterListCursor cursor(m_presenterList); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + if (((MxControlPresenter*) presenter)->FUN_10044480(&m_event, m_unk0x14)) { + g_unk0x100f31b0 = m_event.GetClickedObjectId(); + g_unk0x100f31b4 = m_event.GetClickedAtom(); + FUN_100292e0(); + m_unk0x08 = 1; + return TRUE; + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x10029750 +MxBool LegoControlManager::FUN_10029750() +{ + MxPresenterListCursor cursor(m_presenterList); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + if (presenter->GetAction() && presenter->GetAction()->GetObjectId() == g_unk0x100f31b0 && + presenter->GetAction()->GetAtomId().GetInternal() == g_unk0x100f31b4) { + if (((MxControlPresenter*) presenter)->FUN_10044480(&m_event, m_unk0x14)) { + FUN_100292e0(); + } + + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; + + m_unk0x08 = 0; + m_unk0x0c = 0; + + return TRUE; + } + } + + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp index 7a204a78..ae131445 100644 --- a/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp @@ -1,10 +1,31 @@ #include "mxcontrolpresenter.h" +#include "define.h" +#include "legocontrolmanager.h" +#include "mxdsmultiaction.h" #include "mxticklemanager.h" +#include "mxtimer.h" #include "mxutil.h" +#include "mxvideopresenter.h" DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) +// GLOBAL: LEGO1 0x10102064 +// STRING: LEGO1 0x10101fec +const char* g_style = "STYLE"; + +// GLOBAL: LEGO1 0x10102068 +// STRING: LEGO1 0x10101fe4 +const char* g_grid = "GRID"; + +// GLOBAL: LEGO1 0x1010206c +// STRING: LEGO1 0x10101fe0 +const char* g_map = "MAP"; + +// GLOBAL: LEGO1 0x10102074 +// STRING: LEGO1 0x10101fd0 +const char* g_toggle = "TOGGLE"; + // FUNCTION: LEGO1 0x10043f50 MxControlPresenter::MxControlPresenter() { @@ -37,8 +58,9 @@ void MxControlPresenter::VTable0x68(MxBool p_unk0x50) // FUNCTION: LEGO1 0x10044110 MxControlPresenter::~MxControlPresenter() { - if (m_unk0x58) + if (m_unk0x58) { delete m_unk0x58; + } } // FUNCTION: LEGO1 0x10044180 @@ -81,24 +103,145 @@ void MxControlPresenter::EndAction() } } -// STUB: LEGO1 0x10044270 -MxBool MxControlPresenter::FUN_10044270(undefined4, undefined4, undefined4*) +// FUNCTION: LEGO1 0x10044270 +MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter) { - // TODO - return TRUE; + if (m_unk0x4c == 3) { + MxVideoPresenter* frontPresenter = (MxVideoPresenter*) m_list.front(); + + if (p_presenter == frontPresenter || frontPresenter->GetDisplayZ() < p_presenter->GetDisplayZ()) { + if (p_presenter->VTable0x7c()) { + MxS32 height = frontPresenter->GetHeight(); + MxS32 width = frontPresenter->GetWidth(); + + if (frontPresenter->GetLocation().GetX() <= p_x && + p_x < width - 1 + frontPresenter->GetLocation().GetX() && + frontPresenter->GetLocation().GetY() <= p_y && + p_y < height - 1 + frontPresenter->GetLocation().GetY()) { + MxU8* start; + + if (frontPresenter->GetAlphaMask() == NULL) { + start = frontPresenter->GetBitmap()->GetStart( + p_x - frontPresenter->GetLocation().GetX(), + p_y - frontPresenter->GetLocation().GetY() + ); + } + else { + start = NULL; + } + + m_unk0x56 = 0; + if (m_unk0x58 == NULL) { + if (*start != 0) { + m_unk0x56 = 1; + } + } + else { + for (MxS16 i = 1; i <= *m_unk0x58; i++) { + if (m_unk0x58[i] == *start) { + m_unk0x56 = i; + break; + } + } + } + + if (m_unk0x56) { + return TRUE; + } + } + } + } + } + else { + if (ContainsPresenter(m_list, p_presenter)) { + if (m_unk0x4c == 2) { + MxS32 width = p_presenter->GetWidth(); + MxS32 height = p_presenter->GetHeight(); + + if (m_unk0x52 == 2 && m_unk0x54 == 2) { + MxS16 val; + if (p_x < p_presenter->GetLocation().GetX() + width / 2) { + val = 3; + if (p_y < p_presenter->GetLocation().GetY() + height / 2) { + val = 1; + } + m_unk0x56 = val; + return TRUE; + } + + val = 4; + if (p_y < p_presenter->GetLocation().GetY() + height / 2) { + val = 2; + } + + m_unk0x56 = val; + return TRUE; + } + } + else { + m_unk0x56 = -1; + } + + return TRUE; + } + } + + return FALSE; } -// STUB: LEGO1 0x10044480 -MxBool MxControlPresenter::FUN_10044480(undefined4, undefined4*) +// FUNCTION: LEGO1 0x10044480 +MxBool MxControlPresenter::FUN_10044480(LegoControlManagerEvent* p_event, MxPresenter* p_presenter) { - // TODO - return TRUE; + if (IsEnabled()) { + switch (p_event->GetType()) { + case c_notificationButtonUp: + if (m_unk0x4c == 0 || m_unk0x4c == 2 || m_unk0x4c == 3) { + p_event->SetClickedObjectId(m_action->GetObjectId()); + p_event->SetClickedAtom(m_action->GetAtomId().GetInternal()); + VTable0x6c(0); + p_event->SetType(c_notificationClick); + p_event->SetUnknown0x28(m_unk0x4e); + return TRUE; + } + break; + case c_notificationButtonDown: + if (FUN_10044270(p_event->GetX(), p_event->GetY(), (MxVideoPresenter*) p_presenter)) { + p_event->SetClickedObjectId(m_action->GetObjectId()); + p_event->SetClickedAtom(m_action->GetAtomId().GetInternal()); + VTable0x6c(m_unk0x56); + p_event->SetType(c_notificationClick); + p_event->SetUnknown0x28(m_unk0x4e); + return TRUE; + } + break; + } + } + + return FALSE; } -// STUB: LEGO1 0x10044540 -void MxControlPresenter::VTable0x6c(undefined4) +// FUNCTION: LEGO1 0x10044540 +void MxControlPresenter::VTable0x6c(MxS16 p_val) { - // TODO + if (p_val == -1) { + if ((MxS16) ((MxDSMultiAction*) m_action)->GetActionList()->GetCount() - m_unk0x4e == 1) { + m_unk0x4e = 0; + } + else { + m_unk0x4e++; + } + } + else { + m_unk0x4e = p_val; + } + + m_action->SetUnknown90(Timer()->GetTime()); + + MxS16 i = 0; + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + (*it)->Enable(((m_unk0x4c == 3 && m_unk0x4e == 0) || !IsEnabled()) ? FALSE : m_unk0x4e == i); + i++; + } } // FUNCTION: LEGO1 0x10044610 @@ -109,10 +252,49 @@ void MxControlPresenter::ReadyTickle() ProgressTickleState(e_repeating); } -// STUB: LEGO1 0x10044640 +// FUNCTION: LEGO1 0x10044640 void MxControlPresenter::ParseExtra() { - // TODO + char result[256]; + MxU16 len = m_action->GetExtraLength(); + if (len) { + char buffer[256]; + memcpy(buffer, m_action->GetExtraData(), m_action->GetExtraLength()); + buffer[len] = 0; + + if (KeyValueStringParse(result, g_style, buffer)) { + char* str = strtok(result, g_parseExtraTokens); + if (!strcmpi(str, g_toggle)) { + m_unk0x4c = 1; + } + else if (!strcmpi(str, g_grid)) { + m_unk0x4c = 2; + m_unk0x52 = atoi(strtok(NULL, g_parseExtraTokens)); + m_unk0x54 = atoi(strtok(NULL, g_parseExtraTokens)); + } + else if (!strcmpi(str, g_map)) { + m_unk0x4c = 3; + str = strtok(NULL, g_parseExtraTokens); + if (str) { + MxS16 count = atoi(str); + m_unk0x58 = new MxS16[count + 1]; + *m_unk0x58 = count; + for (MxS16 i = 1; i <= count; i++) { + m_unk0x58[i] = atoi(strtok(NULL, g_parseExtraTokens)); + } + } + } + else { + m_unk0x4c = 0; + } + } + + if (KeyValueStringParse(result, g_strVISIBILITY, buffer)) { + if (!strcmpi(result, "FALSE")) { + Enable(FALSE); + } + } + } } // FUNCTION: LEGO1 0x10044820 @@ -141,8 +323,9 @@ void MxControlPresenter::Enable(MxBool p_enable) MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState) { MxCompositePresenterList::iterator it = m_list.begin(); - for (MxS16 i = m_unk0x4e; i > 0; i--, it++) + for (MxS16 i = m_unk0x4e; i > 0; i--, it++) { ; + } return (*it)->HasTickleStatePassed(p_tickleState); } diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index 5c18b9d3..4fc0daa2 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -2,20 +2,25 @@ DECOMP_SIZE_ASSERT(LegoActor, 0x78) +// GLOBAL: LEGO1 0x100f32d0 +const char* g_unk0x100f32d0[] = {"none", "pepper", "mama", "papa", "nick", "laura", "The_Brickster!"}; + // FUNCTION: LEGO1 0x1002d110 LegoActor::LegoActor() { m_unk0x68 = 0.0f; - m_unk0x6c = 0; + m_sound = NULL; m_unk0x70 = 0.0f; m_unk0x10 = 0; m_unk0x74 = 0; } -// STUB: LEGO1 0x1002d320 +// FUNCTION: LEGO1 0x1002d320 LegoActor::~LegoActor() { - // TODO + if (m_sound) { + m_sound->FUN_10006b80(); + } } // STUB: LEGO1 0x1002d390 @@ -24,8 +29,20 @@ void LegoActor::ParseAction(char*) // TODO } -// STUB: LEGO1 0x1002d670 +// FUNCTION: LEGO1 0x1002d670 void LegoActor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) { - // TODO + if (p_roi) { + const char* name = p_roi->GetName(); + + for (MxU32 i = 1; i <= _countof(g_unk0x100f32d0) - 1; i++) { + if (!strcmpi(name, g_unk0x100f32d0[i])) { + m_unk0x59 = 0; + m_unk0x74 = i; + break; + } + } + } + + LegoEntity::SetROI(p_roi, p_bool1, p_bool2); } diff --git a/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp index 927677fe..076333a6 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp @@ -6,7 +6,7 @@ // FUNCTION: LEGO1 0x10076c30 void LegoActorPresenter::ReadyTickle() { - if (GetCurrentWorld()) { + if (CurrentWorld()) { m_entity = (LegoEntity*) CreateEntity("LegoActor"); if (m_entity) { SetEntityLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index d48d22ff..b68d0a01 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -64,10 +64,12 @@ void LegoCameraController::OnRButtonUp(MxPoint32 p_point) // FUNCTION: LEGO1 0x10012230 void LegoCameraController::OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) { - if (p_modifier & c_lButtonState) + if (p_modifier & c_lButtonState) { LeftDrag(p_point.GetX(), p_point.GetY()); - else if (p_modifier & c_rButtonState) + } + else if (p_modifier & c_rButtonState) { RightDrag(p_point.GetX(), p_point.GetY()); + } } // FUNCTION: LEGO1 0x10012260 @@ -90,8 +92,9 @@ Mx3DPointFloat LegoCameraController::GetWorldUp() vec = m_lego3DView->GetPointOfView()->GetWorldUp(); return Mx3DPointFloat(vec[0], vec[1], vec[2]); } - else + else { return Mx3DPointFloat(0, 0, 0); + } } // FUNCTION: LEGO1 0x100127f0 @@ -102,8 +105,9 @@ Mx3DPointFloat LegoCameraController::GetWorldLocation() vec = m_lego3DView->GetPointOfView()->GetWorldPosition(); return Mx3DPointFloat(vec[0], vec[1] - m_entityOffsetUp, vec[2]); } - else + else { return Mx3DPointFloat(0, 0, 0); + } } // FUNCTION: LEGO1 0x100128a0 @@ -114,6 +118,7 @@ Mx3DPointFloat LegoCameraController::GetWorldDirection() vec = m_lego3DView->GetPointOfView()->GetWorldDirection(); return Mx3DPointFloat(vec[0], vec[1], vec[2]); } - else + else { return Mx3DPointFloat(0, 0, 0); + } } diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index 2c482715..9ac45046 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -51,10 +51,11 @@ void LegoEntity::Destroy(MxBool p_fromDestructor) { if (m_roi) { if (m_flags & c_bit1) { - if (m_roi->GetUnknown0x104() == this) + if (m_roi->GetUnknown0x104() == this) { m_roi->SetUnknown0x104(NULL); + } - GetUnkSaveDataWriter()->FUN_10083db0(m_roi); + UnkSaveDataWriter()->FUN_10083db0(m_roi); } else { VideoManager()->Get3DManager()->GetLego3DView()->Remove(*m_roi); @@ -69,9 +70,9 @@ void LegoEntity::Destroy(MxBool p_fromDestructor) // FUNCTION: LEGO1 0x10010880 void LegoEntity::SetWorld() { - LegoWorld* world = GetCurrentWorld(); + LegoWorld* world = CurrentWorld(); if (world != NULL && world != (LegoWorld*) this) { - world->VTable0x58(this); + world->Add(this); } } @@ -90,10 +91,11 @@ void LegoEntity::SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direc // FUNCTION: LEGO1 0x10010c30 void LegoEntity::FUN_10010c30() { - LegoWorld* world = GetCurrentWorld(); + LegoWorld* world = CurrentWorld(); - if (m_cameraFlag && world && world->GetCamera() && m_roi) + if (m_cameraFlag && world && world->GetCamera() && m_roi) { world->GetCamera()->FUN_100123e0(m_roi->GetLocal2World(), 1); + } } // FUNCTION: LEGO1 0x10010e10 @@ -161,6 +163,12 @@ void LegoEntity::VTable0x4c() // TODO } +// FUNCTION: LEGO1 0x100114e0 +void LegoEntity::FUN_100114e0(MxU8 p_unk0x59) +{ + m_unk0x59 = p_unk0x59; +} + // STUB: LEGO1 0x100114f0 MxLong LegoEntity::Notify(MxParam& p_param) { diff --git a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp index 0da082cd..f43f1aa9 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp @@ -62,7 +62,7 @@ MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDS // FUNCTION: LEGO1 0x100536c0 void LegoEntityPresenter::ReadyTickle() { - if (GetCurrentWorld()) { + if (CurrentWorld()) { m_entity = (LegoEntity*) MxPresenter::CreateEntity("LegoEntity"); if (m_entity) { m_entity->Create(*m_action); diff --git a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index 6a6a035c..8a9ec812 100644 --- a/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -148,8 +148,9 @@ void LegoNavController::SetDefaults( // FUNCTION: LEGO1 0x10054e40 void LegoNavController::SetTargets(int p_hPos, int p_vPos, MxBool p_accel) { - if (this->m_trackDefault != FALSE) + if (this->m_trackDefault != FALSE) { ResetToDefault(); + } if (p_accel != FALSE) { this->m_targetTurnSpeed = CalculateNewTargetSpeed(p_hPos, this->m_hMax / 2, this->m_turnMaxSpeed); @@ -178,12 +179,15 @@ float LegoNavController::CalculateNewTargetSpeed(int p_pos, int p_center, float float result; int diff = p_pos - p_center; - if (diff > this->m_mouseDeadzone) + if (diff > this->m_mouseDeadzone) { result = (diff - m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone); - else if (diff < -m_mouseDeadzone) + } + else if (diff < -m_mouseDeadzone) { result = (diff + m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone); - else + } + else { result = 0.0f; + } return result; } @@ -196,8 +200,9 @@ float LegoNavController::CalculateNewAccel(int p_pos, int p_center, float p_maxA result = Abs(diff) * p_maxAccel / p_center; - if (result < p_minAccel) + if (result < p_minAccel) { result = (float) p_minAccel; + } return result; } @@ -214,10 +219,12 @@ float LegoNavController::CalculateNewVel(float p_targetVel, float p_currentVel, float deltaVel = p_accel * p_time; newVel = p_currentVel + (deltaVel * vSign); - if (vSign > 0) + if (vSign > 0) { newVel = Min(newVel, p_targetVel); - else + } + else { newVel = Max(newVel, p_targetVel); + } } return newVel; diff --git a/LEGO1/lego/legoomni/src/entity/legorace.cpp b/LEGO1/lego/legoomni/src/entity/legorace.cpp index 79565966..7c65c4da 100644 --- a/LEGO1/lego/legoomni/src/entity/legorace.cpp +++ b/LEGO1/lego/legoomni/src/entity/legorace.cpp @@ -82,7 +82,7 @@ MxLong LegoRace::Notify(MxParam& p_param) } // STUB: LEGO1 0x10015ed0 -void LegoRace::VTable0x68(MxBool p_add) +void LegoRace::Enable(MxBool p_enable) { // TODO } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index 8e5c7465..c1fe9e39 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -1,11 +1,20 @@ #include "legoworld.h" +#include "legoanimationmanager.h" +#include "legoanimpresenter.h" +#include "legobuildingmanager.h" #include "legocontrolmanager.h" +#include "legogamestate.h" #include "legoinputmanager.h" +#include "legolocomotionanimpresenter.h" +#include "legonavcontroller.h" #include "legoomni.h" +#include "legoplantmanager.h" +#include "legosoundmanager.h" #include "legoutil.h" #include "legovideomanager.h" #include "mxactionnotificationparam.h" +#include "mxcontrolpresenter.h" #include "mxnotificationmanager.h" #include "mxnotificationparam.h" #include "mxomni.h" @@ -14,15 +23,20 @@ DECOMP_SIZE_ASSERT(LegoWorld, 0xf8) DECOMP_SIZE_ASSERT(LegoEntityList, 0x18) DECOMP_SIZE_ASSERT(LegoEntityListCursor, 0x10) -DECOMP_SIZE_ASSERT(MxCoreList, 0x18) -DECOMP_SIZE_ASSERT(MxCoreListCursor, 0x10) +DECOMP_SIZE_ASSERT(LegoCacheSoundList, 0x18) +DECOMP_SIZE_ASSERT(LegoCacheSoundListCursor, 0x10) -// STUB: LEGO1 0x1001ca40 +// FUNCTION: LEGO1 0x1001ca40 LegoWorld::LegoWorld() : m_list0x68(TRUE) { - // TODO + m_startupTicks = e_four; + m_cameraController = NULL; + m_entityList = NULL; + m_cacheSoundList = NULL; + m_destroyed = FALSE; + m_hideAnimPresenter = NULL; m_worldStarted = FALSE; - m_unk0xf4 = 4; + NotificationManager()->Register(this); } @@ -38,10 +52,13 @@ MxBool LegoWorld::VTable0x64() return FALSE; } -// STUB: LEGO1 0x1001dfa0 +// FUNCTION: LEGO1 0x1001dfa0 LegoWorld::~LegoWorld() { - // TODO + Destroy(TRUE); + + TickleManager()->UnregisterClient(this); + NotificationManager()->Unregister(this); } // FUNCTION: LEGO1 0x1001e0b0 @@ -51,36 +68,150 @@ MxResult LegoWorld::Create(MxDSAction& p_dsAction) m_entityList = new LegoEntityList(TRUE); - if (!m_entityList) + if (!m_entityList) { return FAILURE; + } - m_coreList = new MxCoreList(TRUE); + m_cacheSoundList = new LegoCacheSoundList(TRUE); - if (!m_coreList) + if (!m_cacheSoundList) { return FAILURE; + } - if (!VTable0x54()) + if (!VTable0x54()) { return FAILURE; + } if (p_dsAction.GetFlags() & MxDSAction::c_enabled) { - if (GetCurrentWorld()) { - GetCurrentWorld()->VTable0x68(0); + if (CurrentWorld()) { + CurrentWorld()->Enable(FALSE); } SetCurrentWorld(this); - ControlManager()->FUN_10028df0(&m_list0xb8); + ControlManager()->FUN_10028df0(&m_controlPresenters); } SetIsWorldActive(TRUE); - m_unk0xec = -1; + m_scriptIndex = -1; return SUCCESS; } -// STUB: LEGO1 0x1001e9d0 +// FUNCTION: LEGO1 0x1001e9d0 void LegoWorld::Destroy(MxBool p_fromDestructor) { - // TODO + m_destroyed = TRUE; + + if (CurrentWorld() == this) { + ControlManager()->FUN_10028df0(NULL); + SetCurrentWorld(NULL); + } + + m_list0x68.DeleteAll(); + + if (m_cameraController) { + delete m_cameraController; + m_cameraController = NULL; + } + + MxPresenterListCursor animPresenterCursor(&m_animPresenters); + MxPresenter* presenter; + + while (animPresenterCursor.First(presenter)) { + animPresenterCursor.Detach(); + + MxDSAction* action = presenter->GetAction(); + if (action) { + if (presenter->IsA("LegoLocomotionAnimPresenter")) { + LegoLocomotionAnimPresenter* animPresenter = (LegoLocomotionAnimPresenter*) presenter; + + animPresenter->DecrementUnknown0xd4(); + if (animPresenter->GetUnknown0xd4() == 0) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + else { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + } + + while (!m_set0xa8.empty()) { + MxCoreSet::iterator it = m_set0xa8.begin(); + MxCore* object = *it; + m_set0xa8.erase(it); + + if (object->IsA("MxPresenter")) { + MxPresenter* presenter = (MxPresenter*) object; + MxDSAction* action = presenter->GetAction(); + + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + else { + delete object; + } + } + + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + + while (controlPresenterCursor.First(presenter)) { + controlPresenterCursor.Detach(); + + MxDSAction* action = presenter->GetAction(); + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + + if (m_scriptIndex != -1 && m_set0xd0.empty()) { + PlantManager()->FUN_100263a0(m_scriptIndex); + BuildingManager()->FUN_1002fb30(); + } + + if (m_entityList) { + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.First(entity)) { + cursor.Detach(); + + if (!(entity->GetFlags() & LegoEntity::c_bit2)) { + delete entity; + } + } + + delete m_entityList; + m_entityList = NULL; + } + + if (m_cacheSoundList) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); + LegoCacheSound* sound; + + while (cursor.First(sound)) { + cursor.Detach(); + SoundManager()->GetUnknown0x40()->FUN_1003dc40(&sound); + } + + delete m_cacheSoundList; + m_cacheSoundList = NULL; + } + + while (!m_list0xe0.empty()) { + LegoROI* roi = m_list0xe0.front(); + m_list0xe0.pop_front(); + delete roi; + } + + if (!p_fromDestructor) { + LegoEntity::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x1001f5e0 @@ -90,7 +221,7 @@ MxLong LegoWorld::Notify(MxParam& p_param) switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationEndAction: { MxPresenter* presenter = (MxPresenter*) ((MxEndActionNotificationParam&) p_param).GetSender(); - EndAction(presenter); + Remove(presenter); ret = 1; break; } @@ -134,91 +265,454 @@ LegoCameraController* LegoWorld::VTable0x54() return m_cameraController; } -// STUB: LEGO1 0x1001fc80 +// FUNCTION: LEGO1 0x1001fc80 void LegoWorld::FUN_1001fc80(IslePathActor* p_actor) { + LegoPathControllerListCursor cursor(&m_list0x68); + LegoPathController* controller; + + while (cursor.Next(controller)) { + if (!controller->FUN_10046770(p_actor)) { + break; + } + } } -// STUB: LEGO1 0x10020120 -MxS32 LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) +// FUNCTION: LEGO1 0x10020120 +MxResult LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) { - // TODO - return 0; + LegoPathControllerListCursor cursor(&m_list0x68); + LegoPathController* controller; + + cursor.Next(controller); + + if (!controller) { + return FAILURE; + } + + return controller->FUN_10046b30(p_path, p_value); } -// STUB: LEGO1 0x10020220 -void LegoWorld::VTable0x58(MxCore* p_object) +// FUNCTION: LEGO1 0x10020220 +void LegoWorld::Add(MxCore* p_object) { - // TODO + if (p_object && !p_object->IsA("LegoWorld") && !p_object->IsA("LegoWorldPresenter")) { + if (p_object->IsA("LegoAnimPresenter")) { + LegoAnimPresenter* animPresenter = (LegoAnimPresenter*) p_object; + + if (!strcmpi(animPresenter->GetAction()->GetObjectName(), "ConfigAnimation")) { + FUN_1003e050(animPresenter); + animPresenter->GetAction()->SetDuration(animPresenter->GetAnimation()->GetDuration()); + } + } + + if (p_object->IsA("MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + + if (cursor.Find((MxPresenter*) p_object)) { + return; + } + + m_controlPresenters.Append((MxPresenter*) p_object); + } + else if (p_object->IsA("MxEntity")) { + LegoEntityListCursor cursor(m_entityList); + + if (cursor.Find((LegoEntity*) p_object)) { + return; + } + + m_entityList->Append((LegoEntity*) p_object); + } + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); + + if (cursor.Find((MxPresenter*) p_object)) { + return; + } + + ((MxPresenter*) p_object)->SendToCompositePresenter(Lego()); + m_animPresenters.Append(((MxPresenter*) p_object)); + + if (p_object->IsA("LegoHideAnimPresenter")) { + m_hideAnimPresenter = (LegoHideAnimPresenter*) p_object; + } + } + else if (p_object->IsA("LegoCacheSound")) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); + + if (cursor.Find((LegoCacheSound*) p_object)) { + return; + } + + m_cacheSoundList->Append((LegoCacheSound*) p_object); + } + else { + if (m_set0xa8.find(p_object) == m_set0xa8.end()) { + m_set0xa8.insert(p_object); + } + } + + if (!m_set0xd0.empty() && p_object->IsA("MxPresenter")) { + if (((MxPresenter*) p_object)->IsEnabled()) { + ((MxPresenter*) p_object)->Enable(FALSE); + m_set0xd0.insert(p_object); + } + } + } } -// STUB: LEGO1 0x10020f10 -void LegoWorld::EndAction(MxCore* p_object) +// FUNCTION: LEGO1 0x10020f10 +void LegoWorld::Remove(MxCore* p_object) { + if (p_object) { + MxCoreSet::iterator it; + + if (p_object->IsA("MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + + if (cursor.Find((MxControlPresenter*) p_object)) { + cursor.Detach(); + ((MxControlPresenter*) p_object)->GetAction()->SetOrigin(Lego()); + ((MxControlPresenter*) p_object)->VTable0x68(TRUE); + } + } + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); + + if (cursor.Find((MxPresenter*) p_object)) { + cursor.Detach(); + } + + if (p_object->IsA("LegoHideAnimPresenter")) { + m_hideAnimPresenter = NULL; + } + } + else if (p_object->IsA("MxEntity")) { + if (p_object->IsA("LegoPathActor")) { + FUN_1001fc80((IslePathActor*) p_object); + } + + if (m_entityList) { + LegoEntityListCursor cursor(m_entityList); + + if (cursor.Find((LegoEntity*) p_object)) { + cursor.Detach(); + } + } + } + else if (p_object->IsA("LegoCacheSound")) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); + + if (cursor.Find((LegoCacheSound*) p_object)) { + cursor.Detach(); + } + } + else { + it = m_set0xa8.find(p_object); + if (it != m_set0xa8.end()) { + m_set0xa8.erase(it); + } + } + + it = m_set0xd0.find(p_object); + if (it != m_set0xd0.end()) { + m_set0xd0.erase(it); + } + } } -// STUB: LEGO1 0x100213a0 -MxPresenter* LegoWorld::FindPresenter(const char* p_presenter, const char* p_name) +// FUNCTION: LEGO1 0x100213a0 +MxCore* LegoWorld::Find(const char* p_class, const char* p_name) { + if (!strcmp(p_class, "MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + MxDSAction* action = presenter->GetAction(); + if (!strcmp(action->GetObjectName(), p_name)) { + return presenter; + } + } + + return NULL; + } + else if (!strcmp(p_class, "MxEntity")) { + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.Next(entity)) { + if (!p_name) { + return entity; + } + + LegoROI* roi = entity->GetROI(); + if (roi && !strcmpi(roi->GetName(), p_name)) { + return entity; + } + } + + return NULL; + } + else if (!strcmp(p_class, "LegoAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + if (!strcmpi(((LegoAnimPresenter*) presenter)->GetActionObjectName(), p_name)) { + return presenter; + } + } + + return NULL; + } + else { + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + if ((*it)->IsA(p_class) && (*it)->IsA("MxPresenter")) { + MxPresenter* presenter = (MxPresenter*) *it; + MxDSAction* action = presenter->GetAction(); + + if (!strcmp(action->GetObjectName(), p_name)) { + return *it; + } + } + } + + return NULL; + } +} + +// FUNCTION: LEGO1 0x10021790 +MxCore* LegoWorld::Find(const MxAtomId& p_atom, MxS32 p_entityId) +{ + LegoEntityListCursor entityCursor(m_entityList); + LegoEntity* entity; + + while (entityCursor.Next(entity)) { + if (entity->GetAtom() == p_atom && entity->GetEntityId() == p_entityId) { + return entity; + } + } + + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + MxPresenter* presenter; + + while (controlPresenterCursor.Next(presenter)) { + MxDSAction* action = presenter->GetAction(); + + if (action->GetAtomId() == p_atom && action->GetObjectId() == p_entityId) { + return presenter; + } + } + + MxPresenterListCursor animPresenterCursor(&m_animPresenters); + + while (animPresenterCursor.Next(presenter)) { + MxDSAction* action = presenter->GetAction(); + + if (action && action->GetAtomId() == p_atom && action->GetObjectId() == p_entityId) { + return presenter; + } + } + + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + MxCore* core = *it; + + if (core->IsA("MxPresenter")) { + MxPresenter* presenter = (MxPresenter*) *it; + MxDSAction* action = presenter->GetAction(); + + if (action->GetAtomId() == p_atom && action->GetObjectId() == p_entityId) { + return *it; + } + } + } + return NULL; } -// STUB: LEGO1 0x10021a70 -void LegoWorld::VTable0x68(MxBool p_add) +// FUNCTION: LEGO1 0x10021a70 +void LegoWorld::Enable(MxBool p_enable) { - // TODO + if (p_enable && !m_set0xd0.empty()) { + if (CurrentWorld() != this) { + if (CurrentWorld()) { + AnimationManager()->FUN_10061010(0); + CurrentWorld()->Enable(FALSE); + + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.Next(entity)) { + if (entity->GetROI()) { + entity->GetROI()->SetUnknown0x104(entity); + GetViewManager()->AddToUnknown0x08(entity->GetROI()); + } + } + } + + while (!m_set0xd0.empty()) { + MxCoreSet::iterator it = m_set0xd0.begin(); + + if ((*it)->IsA("MxPresenter")) { + ((MxPresenter*) *it)->Enable(TRUE); + } + else if ((*it)->IsA("LegoPathController")) { + ((LegoPathController*) *it)->Enable(TRUE); + } + + m_set0xd0.erase(it); + } + + SetCurrentWorld(this); + ControlManager()->FUN_10028df0(&m_controlPresenters); + InputManager()->SetCamera(m_cameraController); + + if (m_cameraController) { + InputManager()->Register(m_cameraController->GetNavController()); + Lego()->SetNavController(m_cameraController->GetNavController()); + } + + if (m_scriptIndex != -1) { + PlantManager()->FUN_10026360(m_scriptIndex); + AnimationManager()->FUN_1005f720(m_scriptIndex); + BuildingManager()->FUN_1002fa00(); + AnimationManager()->FUN_1005f0b0(); + } + + GameState()->FUN_10039940(); + SetIsWorldActive(TRUE); + } + } + else if (!p_enable && m_set0xd0.empty()) { + MxPresenter* presenter; + LegoPathController* controller; + IslePathActor* vehicle = CurrentVehicle(); + + if (vehicle) { + FUN_1001fc80(vehicle); + } + + AnimationManager()->FUN_1005ee80(FALSE); + m_set0xd0.insert(this); + + if (m_scriptIndex != -1) { + PlantManager()->FUN_100263a0(m_scriptIndex); + BuildingManager()->FUN_1002fb30(); + } + + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + + while (controlPresenterCursor.Next(presenter)) { + if (presenter->IsEnabled()) { + m_set0xd0.insert(presenter); + presenter->Enable(FALSE); + } + } + + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + if ((*it)->IsA("LegoActionControlPresenter") || + ((*it)->IsA("MxPresenter") && ((MxPresenter*) *it)->IsEnabled())) { + m_set0xd0.insert(*it); + ((MxPresenter*) *it)->Enable(FALSE); + } + } + + if (CurrentWorld() && CurrentWorld() == this) { + ControlManager()->FUN_10028df0(NULL); + Lego()->SetCurrentWorld(NULL); + } + + if (InputManager()->GetCamera() == m_cameraController) { + InputManager()->ClearCamera(); + } + + if (m_cameraController) { + InputManager()->UnRegister(m_cameraController->GetNavController()); + + if (NavController() == m_cameraController->GetNavController()) { + Lego()->SetNavController(NULL); + } + } + + LegoPathControllerListCursor pathControllerCursor(&m_list0x68); + + while (pathControllerCursor.Next(controller)) { + controller->Enable(FALSE); + m_set0xd0.insert(controller); + } + + GetViewManager()->RemoveAll(NULL); + } } // FUNCTION: LEGO1 0x10022080 MxResult LegoWorld::Tickle() { if (!m_worldStarted) { - switch (m_unk0xf4) { - case 0: + switch (m_startupTicks) { + case e_start: m_worldStarted = TRUE; SetAppCursor(0); - VTable0x50(); + ReadyWorld(); return TRUE; - case 2: - if (FUN_100220e0() == 1) + case e_two: + if (PresentersPending()) { break; + } default: - m_unk0xf4--; + m_startupTicks--; } } + return TRUE; } -// STUB: LEGO1 0x100220e0 -undefined LegoWorld::FUN_100220e0() +// FUNCTION: LEGO1 0x100220e0 +MxBool LegoWorld::PresentersPending() { - return 0; + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + MxPresenter* presenter; + + while (controlPresenterCursor.Next(presenter)) { + if (presenter->IsEnabled() && !presenter->HasTickleStatePassed(MxPresenter::e_starting)) { + return TRUE; + } + } + + MxPresenterListCursor animPresenterCursor(&m_animPresenters); + + while (animPresenterCursor.Next(presenter)) { + if (presenter->IsEnabled()) { + if (presenter->IsA("LegoLocomotionAnimPresenter")) { + if (!presenter->HasTickleStatePassed(MxPresenter::e_ready)) { + return TRUE; + } + } + else { + if (!presenter->HasTickleStatePassed(MxPresenter::e_starting)) { + return TRUE; + } + } + } + } + + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + if ((*it)->IsA("MxPresenter")) { + presenter = (MxPresenter*) *it; + + if (presenter->IsEnabled() && !presenter->HasTickleStatePassed(MxPresenter::e_starting)) { + return TRUE; + } + } + } + + return FALSE; } // FUNCTION: LEGO1 0x10022340 -void LegoWorld::VTable0x50() +void LegoWorld::ReadyWorld() { TickleManager()->UnregisterClient(this); } - -// STUB: LEGO1 0x100727e0 -MxBool LegoWorld::FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) -{ - return FALSE; -} - -// STUB: LEGO1 0x10072980 -MxBool LegoWorld::FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) -{ - return FALSE; -} - -// STUB: LEGO1 0x10073400 -void LegoWorld::FUN_10073400() -{ -} - -// STUB: LEGO1 0x10073430 -void LegoWorld::FUN_10073430() -{ -} diff --git a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp index 55f908bd..21721f17 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp @@ -1,5 +1,6 @@ #include "legoworldpresenter.h" +#include "define.h" #include "legoanimationmanager.h" #include "legobuildingmanager.h" #include "legoentity.h" @@ -16,6 +17,7 @@ #include "mxobjectfactory.h" #include "mxpresenter.h" #include "mxstl/stlcompat.h" +#include "mxutil.h" // GLOBAL: LEGO1 0x100f75d4 undefined4 g_legoWorldPresenterQuality = 1; @@ -37,9 +39,9 @@ LegoWorldPresenter::~LegoWorldPresenter() { MxBool result = FALSE; if (m_entity) { - undefined4 world = ((LegoWorld*) m_entity)->GetUnknown0xec(); - PlantManager()->FUN_10026360(world); - AnimationManager()->FUN_1005f720(world); + MxS32 scriptIndex = ((LegoWorld*) m_entity)->GetScriptIndex(); + PlantManager()->FUN_10026360(scriptIndex); + AnimationManager()->FUN_1005f720(scriptIndex); BuildingManager()->FUN_1002fa00(); result = ((LegoWorld*) m_entity)->VTable0x5c(); } @@ -100,8 +102,9 @@ MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSA action->SetOrigin(this); m_list.push_back(presenter); } - else if (presenter) + else if (presenter) { delete presenter; + } } VideoManager()->RegisterPresenter(*this); @@ -146,6 +149,11 @@ void LegoWorldPresenter::StartingTickle() ProgressTickleState(e_streaming); } +// STUB: LEGO1 0x10066b40 +void LoadWorld(char* p_worldName, LegoWorld* p_world) +{ +} + // FUNCTION: LEGO1 0x10067a70 void LegoWorldPresenter::VTable0x60(MxPresenter* p_presenter) { @@ -165,11 +173,25 @@ void LegoWorldPresenter::VTable0x60(MxPresenter* p_presenter) if (!p_presenter->IsA("LegoAnimPresenter") && !p_presenter->IsA("MxControlPresenter") && !p_presenter->IsA("MxCompositePresenter")) { p_presenter->SendToCompositePresenter(Lego()); - ((LegoWorld*) m_entity)->VTable0x58(p_presenter); + ((LegoWorld*) m_entity)->Add(p_presenter); } } -// STUB: LEGO1 0x10067b00 +// FUNCTION: LEGO1 0x10067b00 void LegoWorldPresenter::ParseExtra() { + char data[1024]; + char output[1024]; + MxU16 len = m_action->GetExtraLength(); + *((MxU16*) &data[0]) = m_action->GetExtraLength(); + if (len != 0) { + memcpy(data, m_action->GetExtraData(), len); + data[len] = 0; + + if (KeyValueStringParse(output, g_strWORLD, data)) { + char* worldKey = strtok(output, g_parseExtraTokens); + LoadWorld(worldKey, (LegoWorld*) m_entity); + ((LegoWorld*) m_entity)->SetScriptIndex(Lego()->GetScriptIndex(worldKey)); + } + } } diff --git a/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp index 8bedf0cf..1b938bcf 100644 --- a/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp @@ -1,62 +1,163 @@ #include "gasstation.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" #include "mxnotificationmanager.h" +#include "mxticklemanager.h" + +// GLOBAL: LEGO1 0x100f0160 +undefined4 g_unk0x100f0160; // FUNCTION: LEGO1 0x100046a0 GasStation::GasStation() { - this->m_unk0xf8 = 0; - this->m_unk0x100 = 0; - this->m_unk0xfc = 0; - this->m_unk0x108 = 0; - this->m_unk0x104 = 0; - this->m_unk0x114 = 0; - this->m_unk0x106 = 0; - this->m_unk0x10c = 0; - this->m_unk0x115 = 0; - this->m_unk0x110 = 0; + m_unk0xf8 = 0; + m_state = NULL; + m_transitionDestination = LegoGameState::e_noArea; + m_unk0x108 = 0; + m_unk0x104 = 0; + m_unk0x114 = 0; + m_unk0x106 = 0; + m_unk0x10c = 0; + m_unk0x115 = 0; + m_unk0x110 = 0; NotificationManager()->Register(this); } -// STUB: LEGO1 0x10004770 +// FUNCTION: LEGO1 0x10004770 MxBool GasStation::VTable0x5c() { - // TODO - return FALSE; + return TRUE; } -// STUB: LEGO1 0x100048c0 +// FUNCTION: LEGO1 0x100048c0 GasStation::~GasStation() { - // TODO + InputManager()->UnRegister(this); + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + ControlManager()->Unregister(this); + TickleManager()->UnregisterClient(this); + NotificationManager()->Unregister(this); + g_unk0x100f0160 = 3; } -// STUB: LEGO1 0x10004990 +// FUNCTION: LEGO1 0x10004990 MxResult GasStation::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + InputManager()->SetCamera(NULL); + + m_state = (GasStationState*) GameState()->GetState("GasStationState"); + if (!m_state) { + m_state = (GasStationState*) GameState()->CreateState("GasStationState"); + m_state->GetUnknown0x14().SetUnknown0x00(1); + } + else { + GasStationState::Unknown0x14& unk0x14 = m_state->GetUnknown0x14(); + if (unk0x14.GetUnknown0x00() == 4) { + unk0x14.SetUnknown0x00(4); + } + else { + unk0x14.SetUnknown0x00(3); + } + } + + GameState()->SetCurrentArea(LegoGameState::e_garage); + GameState()->StopArea(LegoGameState::e_previousArea); + + InputManager()->Register(this); + SetIsWorldActive(FALSE); + return result; } -// STUB: LEGO1 0x10004a60 +// FUNCTION: LEGO1 0x10004a60 MxLong GasStation::Notify(MxParam& p_param) { - // TODO + MxResult result = 0; + LegoWorld::Notify(p_param); - return 0; + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) p_param); + break; + case c_notificationKeyPress: + result = HandleKeyPress((((LegoEventNotificationParam&) p_param)).GetKey()); + break; + case c_notificationButtonDown: + result = HandleButtonDown(((LegoControlManagerEvent&) p_param)); + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_transitionDestination); + break; + } + } + + return result; } // STUB: LEGO1 0x10004b30 -void GasStation::VTable0x50() +void GasStation::ReadyWorld() { // TODO } -// STUB: LEGO1 0x10005c40 -void GasStation::VTable0x68(MxBool p_add) +// STUB: LEGO1 0x10005660 +MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param) { // TODO + return 0; +} + +// STUB: LEGO1 0x10005920 +MxLong GasStation::HandleKeyPress(MxS8 p_key) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10005960 +MxLong GasStation::HandleButtonDown(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10005b20 +MxLong GasStation::HandleClick(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} + +// FUNCTION: LEGO1 0x10005c40 +void GasStation::Enable(MxBool p_enable) +{ + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + InputManager()->SetCamera(NULL); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } } // STUB: LEGO1 0x10005c90 @@ -64,7 +165,7 @@ MxResult GasStation::Tickle() { // TODO - return 0; + return SUCCESS; } // STUB: LEGO1 0x10005e70 diff --git a/LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp b/LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp index 5bbcdde6..b4b242ac 100644 --- a/LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp +++ b/LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp @@ -18,7 +18,7 @@ GasStationState::GasStationState() } // STUB: LEGO1 0x10006300 -MxResult GasStationState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult GasStationState::VTable0x1c(LegoFile* p_legoFile) { // TODO return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/hospital/ambulance.cpp b/LEGO1/lego/legoomni/src/hospital/ambulance.cpp index a7bd2689..aad42ca4 100644 --- a/LEGO1/lego/legoomni/src/hospital/ambulance.cpp +++ b/LEGO1/lego/legoomni/src/hospital/ambulance.cpp @@ -67,7 +67,7 @@ void Ambulance::VTable0xe4() } // STUB: LEGO1 0x10036f90 -MxU32 Ambulance::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 Ambulance::VTable0xd4(LegoControlManagerEvent& p_param) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp b/LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp index 601f1ccd..e99c3229 100644 --- a/LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp +++ b/LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp @@ -8,9 +8,9 @@ AmbulanceMissionState::AmbulanceMissionState() m_unk0x10 = 0; m_unk0x12 = 0; m_unk0x14 = 0; - m_unk0x8 = 0; + m_unk0x08 = 0; m_unk0x16 = 0; - m_unk0xc = 0; + m_unk0x0c = 0; m_unk0x18 = 0; m_color1 = 0; m_color2 = 0; @@ -20,7 +20,7 @@ AmbulanceMissionState::AmbulanceMissionState() } // STUB: LEGO1 0x10037440 -MxResult AmbulanceMissionState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult AmbulanceMissionState::VTable0x1c(LegoFile* p_legoFile) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/hospital/hospital.cpp b/LEGO1/lego/legoomni/src/hospital/hospital.cpp index 8ede37e2..e298ef34 100644 --- a/LEGO1/lego/legoomni/src/hospital/hospital.cpp +++ b/LEGO1/lego/legoomni/src/hospital/hospital.cpp @@ -23,11 +23,10 @@ Hospital::Hospital() NotificationManager()->Register(this); } -// STUB: LEGO1 0x100746a0 +// FUNCTION: LEGO1 0x100746a0 MxBool Hospital::VTable0x5c() { - // TODO - return FALSE; + return TRUE; } // STUB: LEGO1 0x100747f0 @@ -52,13 +51,13 @@ MxLong Hospital::Notify(MxParam& p_param) } // STUB: LEGO1 0x10074a60 -void Hospital::VTable0x50() +void Hospital::ReadyWorld() { // TODO } // STUB: LEGO1 0x10076220 -void Hospital::VTable0x68(MxBool p_add) +void Hospital::Enable(MxBool p_enable) { // TODO } diff --git a/LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp b/LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp index 5921cd0c..326415d1 100644 --- a/LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp +++ b/LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp @@ -5,8 +5,8 @@ DECOMP_SIZE_ASSERT(HospitalState, 0x18) // FUNCTION: LEGO1 0x10076370 HospitalState::HospitalState() { - this->m_unk0xc = 0; - this->m_unk0xe = 0; + this->m_unk0x0c = 0; + this->m_unk0x0e = 0; this->m_unk0x10 = 0; this->m_unk0x12 = 0; this->m_unk0x14 = 0; @@ -14,7 +14,7 @@ HospitalState::HospitalState() } // STUB: LEGO1 0x10076530 -MxResult HospitalState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult HospitalState::VTable0x1c(LegoFile* p_legoFile) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp index ab4d3cff..5ef0d580 100644 --- a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -1,12 +1,15 @@ #include "elevatorbottom.h" +#include "act1state.h" #include "jukebox.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "legoomni.h" +#include "legovariables.h" #include "mxnotificationmanager.h" #include "mxomni.h" +#include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) @@ -14,7 +17,7 @@ DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) ElevatorBottom::ElevatorBottom() { NotificationManager()->Register(this); - this->m_unk0xf8 = 0; + this->m_unk0xf8 = LegoGameState::e_noArea; } // FUNCTION: LEGO1 0x10018060 @@ -38,8 +41,8 @@ MxResult ElevatorBottom::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetUnknown424(5); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(LegoGameState::e_elevbott); + GameState()->StopArea(LegoGameState::e_previousArea); return result; } @@ -52,11 +55,11 @@ MxLong ElevatorBottom::Notify(MxParam& p_param) if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetType()) { - case c_notificationType17: - ret = HandleNotification17(p_param); + case c_notificationClick: + ret = HandleClick((LegoControlManagerEvent&) p_param); break; case c_notificationTransitioned: - GameState()->HandleAction(m_unk0xf8); + GameState()->SwitchArea(m_unk0xf8); break; } } @@ -65,25 +68,56 @@ MxLong ElevatorBottom::Notify(MxParam& p_param) } // FUNCTION: LEGO1 0x100181b0 -void ElevatorBottom::VTable0x50() +void ElevatorBottom::ReadyWorld() { - LegoWorld::VTable0x50(); + LegoWorld::ReadyWorld(); PlayMusic(JukeBox::e_informationCenter); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } -// STUB: LEGO1 0x100181d0 -MxLong ElevatorBottom::HandleNotification17(MxParam& p_param) +// FUNCTION: LEGO1 0x100181d0 +MxLong ElevatorBottom::HandleClick(LegoControlManagerEvent& p_param) { - return 0; + MxLong result = 0; + + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { + case 1: + m_unk0xf8 = LegoGameState::e_infodoor; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 2: + m_unk0xf8 = LegoGameState::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 3: + LegoGameState* gs = GameState(); + Act1State* state = (Act1State*) gs->GetState("Act1State"); + + if (state == NULL) { + state = (Act1State*) gs->CreateState("Act1State"); + } + + state->SetUnknown1c(1); + m_unk0xf8 = LegoGameState::e_unk6; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + VariableTable()->SetVariable(g_varCAMERALOCATION, "LCAMZI1,90"); + result = 1; + break; + } + } + + return result; } // FUNCTION: LEGO1 0x100182c0 -void ElevatorBottom::VTable0x68(MxBool p_add) +void ElevatorBottom::Enable(MxBool p_enable) { - LegoWorld::VTable0x68(p_add); + LegoWorld::Enable(p_enable); - if (p_add) { + if (p_enable) { InputManager()->SetWorld(this); SetIsWorldActive(FALSE); } @@ -98,6 +132,6 @@ void ElevatorBottom::VTable0x68(MxBool p_add) MxBool ElevatorBottom::VTable0x64() { DeleteObjects(&m_atom, 500, 999); - m_unk0xf8 = 2; + m_unk0xf8 = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index 170147d0..64bd9e58 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -1,22 +1,30 @@ #include "infocenter.h" +#include "act3state.h" +#include "helicopterstate.h" #include "infocenterstate.h" #include "jukebox.h" +#include "legoact2state.h" +#include "legoanimationmanager.h" +#include "legobuildingmanager.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "legoomni.h" +#include "legoplantmanager.h" +#include "legounksavedatawriter.h" #include "legoutil.h" #include "legovideomanager.h" #include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" +#include "mxcontrolpresenter.h" #include "mxnotificationmanager.h" #include "mxstillpresenter.h" #include "mxticklemanager.h" #include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(Infocenter, 0x1d8) -DECOMP_SIZE_ASSERT(InfocenterUnkDataEntry, 0x18) +DECOMP_SIZE_ASSERT(InfocenterMapEntry, 0x18) // GLOBAL: LEGO1 0x100f76a0 const char* g_object2x4red = "2x4red"; @@ -27,16 +35,15 @@ const char* g_object2x4grn = "2x4grn"; // FUNCTION: LEGO1 0x1006ea20 Infocenter::Infocenter() { - m_unk0xfc = 0; - m_unk0x11c = 0; + m_selectedCharacter = e_noCharacter; + m_unk0x11c = NULL; m_infocenterState = NULL; - m_unk0x1cc = 0; - m_unk0x11c = 0; - m_unk0x104 = 0; + m_frameHotBitmap = NULL; + m_transitionDestination = LegoGameState::e_noArea; m_currentInfomainScript = c_noInfomain; m_currentCutscene = e_noIntro; - memset(&m_entries, 0, sizeof(m_entries)); + memset(&m_mapAreas, 0, sizeof(m_mapAreas)); m_unk0x1c8 = -1; SetAppCursor(1); @@ -55,11 +62,11 @@ Infocenter::~Infocenter() MxS16 i = 0; do { - if (m_infocenterState->GetInfocenterBufferElement(i) != NULL) { - m_infocenterState->GetInfocenterBufferElement(i)->Enable(FALSE); + if (m_infocenterState->GetNameLetter(i) != NULL) { + m_infocenterState->GetNameLetter(i)->Enable(FALSE); } i++; - } while (i < m_infocenterState->GetInfocenterBufferSize()); + } while (i < m_infocenterState->GetMaxNameLength()); ControlManager()->Unregister(this); @@ -73,28 +80,54 @@ Infocenter::~Infocenter() TickleManager()->UnregisterClient(this); } -// STUB: LEGO1 0x1006ed90 +// FUNCTION: LEGO1 0x1006ed90 MxResult Infocenter::Create(MxDSAction& p_dsAction) { - if (LegoWorld::Create(p_dsAction) == SUCCESS) { + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { InputManager()->SetWorld(this); ControlManager()->Register(this); } - LegoGameState* gs = GameState(); - m_infocenterState = (InfocenterState*) gs->GetState("InfocenterState"); + m_infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); if (!m_infocenterState) { - m_infocenterState = (InfocenterState*) gs->CreateState("InfocenterState"); + m_infocenterState = (InfocenterState*) GameState()->CreateState("InfocenterState"); m_infocenterState->SetUnknown0x74(3); } else { - // TODO + if (m_infocenterState->GetUnknown0x74() != 8 && m_infocenterState->GetUnknown0x74() != 4 && + m_infocenterState->GetUnknown0x74() != 15) { + m_infocenterState->SetUnknown0x74(2); + } + + MxS16 count, i; + for (count = 0; count < m_infocenterState->GetMaxNameLength(); count++) { + if (m_infocenterState->GetNameLetter(count) == NULL) { + break; + } + } + + for (i = 0; i < count; i++) { + if (m_infocenterState->GetNameLetter(i)) { + m_infocenterState->GetNameLetter(i)->Enable(TRUE); + m_infocenterState->GetNameLetter(i)->SetTickleState(MxPresenter::e_repeating); + m_infocenterState->GetNameLetter(i)->SetPosition(((7 - count) / 2 + i) * 29 + 223, 45); + } + } + } + + GameState()->SetCurrentArea(LegoGameState::e_infomain); + GameState()->StopArea(LegoGameState::e_previousArea); + + if (m_infocenterState->GetUnknown0x74() == 4) { + LegoGameState* state = GameState(); + state->SetPreviousArea(GameState()->GetUnknown0x42c()); } - // TODO InputManager()->Register(this); SetIsWorldActive(FALSE); - return SUCCESS; + + return result; } // FUNCTION: LEGO1 0x1006ef10 @@ -106,10 +139,10 @@ MxLong Infocenter::Notify(MxParam& p_param) if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationType0: - result = HandleNotification0(p_param); + result = HandleNotification0((MxNotificationParam&) p_param); break; case c_notificationEndAction: - result = HandleEndAction(p_param); + result = HandleEndAction((MxEndActionNotificationParam&) p_param); break; case c_notificationKeyPress: result = HandleKeyPress(((LegoEventNotificationParam&) p_param).GetKey()); @@ -126,21 +159,21 @@ MxLong Infocenter::Notify(MxParam& p_param) ((LegoEventNotificationParam&) p_param).GetY() ); break; - case c_notificationType17: - result = HandleNotification17(p_param); + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); break; case c_notificationTransitioned: StopBookAnimation(); m_bookAnimationTimer = 0; - if (m_infocenterState->GetUnknown0x74() == 0xc) { + if (m_infocenterState->GetUnknown0x74() == 0x0c) { StartCredits(); m_infocenterState->SetUnknown0x74(0xd); } - else if (m_unk0x104 != 0) { + else if (m_transitionDestination != 0) { BackgroundAudioManager()->RaiseVolume(); - GameState()->HandleAction(m_unk0x104); - m_unk0x104 = 0; + GameState()->SwitchArea(m_transitionDestination); + m_transitionDestination = LegoGameState::e_noArea; } break; } @@ -150,53 +183,55 @@ MxLong Infocenter::Notify(MxParam& p_param) } // FUNCTION: LEGO1 0x1006f080 -MxLong Infocenter::HandleEndAction(MxParam& p_param) +MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) { - MxDSAction* action = ((MxEndActionNotificationParam&) p_param).GetAction(); - if (action->GetAtomId() == *g_creditsScript && action->GetObjectId() == 499) { + MxDSAction* action = p_param.GetAction(); + if (action->GetAtomId() == *g_creditsScript && action->GetObjectId() == c_unk499) { Lego()->CloseMainWindow(); return 1; } if (action->GetAtomId() == m_atom && - (action->GetObjectId() == 40 || action->GetObjectId() == 41 || action->GetObjectId() == 42 || - action->GetObjectId() == 43 || action->GetObjectId() == 44)) { + (action->GetObjectId() == c_mamaMovie || action->GetObjectId() == c_papaMovie || + action->GetObjectId() == c_pepperMovie || action->GetObjectId() == c_nickMovie || + action->GetObjectId() == c_lauraMovie)) { if (m_unk0x1d4) { m_unk0x1d4--; } if (!m_unk0x1d4) { PlayMusic(JukeBox::e_informationCenter); - GameState()->FUN_10039780(m_unk0xfc); + GameState()->FUN_10039780(m_selectedCharacter); - switch (m_unk0xfc) { - case 1: + switch (m_selectedCharacter) { + case e_pepper: PlayAction(c_pepperCharacterSelect); break; - case 2: + case e_mama: PlayAction(c_mamaCharacterSelect); break; - case 3: + case e_papa: PlayAction(c_papaCharacterSelect); break; - case 4: + case e_nick: PlayAction(c_nickCharacterSelect); break; - case 5: + case e_laura: PlayAction(c_lauraCharacterSelect); break; default: break; } - FUN_10070dc0(TRUE); + UpdateFrameHot(TRUE); } } MxLong result = m_radio.Notify(p_param); - if (result || (action->GetAtomId() != m_atom && action->GetAtomId() != *g_introScript)) + if (result || (action->GetAtomId() != m_atom && action->GetAtomId() != *g_introScript)) { return result; + } if (action->GetObjectId() == c_returnBackGuidanceDialogue2) { ControlManager()->FUN_100293c0(0x10, action->GetAtomId().GetInternal(), 0); @@ -232,7 +267,7 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) PlayAction(c_welcomeDialogue); m_currentCutscene = e_noIntro; - if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + if (!m_infocenterState->HasRegistered()) { m_bookAnimationTimer = 1; return 1; } @@ -254,12 +289,12 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) m_currentCutscene = e_noIntro; return 1; case 2: - FUN_10015860(g_object2x4red, 0); - FUN_10015860(g_object2x4grn, 0); + SetROIUnknown0x0c(g_object2x4red, 0); + SetROIUnknown0x0c(g_object2x4grn, 0); BackgroundAudioManager()->RaiseVolume(); return 1; case 4: - if (action->GetObjectId() == 70 || action->GetObjectId() == 71) { + if (action->GetObjectId() == c_goToRegBook || action->GetObjectId() == c_goToRegBookRed) { TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); m_infocenterState->SetUnknown0x74(14); return 1; @@ -267,8 +302,8 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) break; case 5: if (action->GetObjectId() == m_currentInfomainScript) { - if (GameState()->GetUnknown10() != 2 && m_unk0xfc != 0) { - GameState()->FUN_10039780(m_unk0xfc); + if (GameState()->GetCurrentAct() != LegoGameState::e_act3 && m_selectedCharacter != e_noCharacter) { + GameState()->FUN_10039780(m_selectedCharacter); } TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); m_infocenterState->SetUnknown0x74(14); @@ -276,15 +311,15 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) } break; case 11: - if (m_infocenterState->GetInfocenterBufferElement(0) == 0 && m_currentInfomainScript != 40 && - m_currentInfomainScript != 41 && m_currentInfomainScript != 42 && m_currentInfomainScript != 43 && - m_currentInfomainScript != 44) { + if (!m_infocenterState->HasRegistered() && m_currentInfomainScript != c_mamaMovie && + m_currentInfomainScript != c_papaMovie && m_currentInfomainScript != c_pepperMovie && + m_currentInfomainScript != c_nickMovie && m_currentInfomainScript != c_lauraMovie) { m_infoManDialogueTimer = 1; PlayMusic(JukeBox::e_informationCenter); } m_infocenterState->SetUnknown0x74(2); - FUN_10015860("infoman", 1); + SetROIUnknown0x0c("infoman", 1); return 1; case 12: if (action->GetObjectId() == m_currentInfomainScript) { @@ -297,79 +332,283 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) return result; } -// STUB: LEGO1 0x1006f4e0 -void Infocenter::VTable0x50() +// FUNCTION: LEGO1 0x1006f4e0 +void Infocenter::ReadyWorld() { m_infoManDialogueTimer = 0; m_bookAnimationTimer = 0; m_unk0x1d4 = 0; m_unk0x1d6 = 0; - MxStillPresenter* bg = (MxStillPresenter*) FindPresenter("MxStillPresenter", "Background_Bitmap"); - MxStillPresenter* bgRed = (MxStillPresenter*) FindPresenter("MxStillPresenter", "BackgroundRed_Bitmap"); + MxStillPresenter* bg = (MxStillPresenter*) Find("MxStillPresenter", "Background_Bitmap"); + MxStillPresenter* bgRed = (MxStillPresenter*) Find("MxStillPresenter", "BackgroundRed_Bitmap"); - switch (GameState()->GetUnknown10()) { - case 0: - // bg->Enable(1); // TODO: Uncomment once LegoWorld::FindPresenter and LegoWorld::VTable0x58 are implemented. + switch (GameState()->GetCurrentAct()) { + case LegoGameState::e_act1: + bg->Enable(TRUE); InitializeBitmaps(); + switch (m_infocenterState->GetUnknown0x74()) { case 3: PlayCutscene(e_legoMovie, TRUE); m_infocenterState->SetUnknown0x74(0); - return; + break; case 4: m_infocenterState->SetUnknown0x74(2); - if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + if (!m_infocenterState->HasRegistered()) { m_bookAnimationTimer = 1; } PlayAction(c_letsGetStartedDialogue); PlayMusic(JukeBox::e_informationCenter); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); - return; - default: - PlayMusic(JukeBox::e_informationCenter); - // TODO break; + case 5: + default: { + PlayMusic(JukeBox::e_informationCenter); + + InfomainScript script = + (InfomainScript) m_infocenterState->GetReturnDialogue(GameState()->GetCurrentAct()).Next(); + PlayAction(script); + + if (script == c_returnBackGuidanceDialogue2) { + m_unk0x1d6 = 1; + } + + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + + if (!m_infocenterState->HasRegistered()) { + m_bookAnimationTimer = 1; + } + + m_infocenterState->SetUnknown0x74(11); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + break; + } case 8: PlayMusic(JukeBox::e_informationCenter); PlayAction(c_exitConfirmationDialogue); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); - return; + break; case 0xf: - if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_infocenterState->SetUnknown0x74(2); + if (!m_infocenterState->HasRegistered()) { m_bookAnimationTimer = 1; } PlayAction(c_clickOnInfomanDialogue); PlayMusic(JukeBox::e_informationCenter); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + break; + } + return; + case LegoGameState::e_act2: { + if (m_infocenterState->GetUnknown0x74() == 8) { + PlayMusic(JukeBox::e_informationCenter); + bgRed->Enable(TRUE); + PlayAction(c_exitConfirmationDialogue); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); return; } + + LegoAct2State* state = (LegoAct2State*) GameState()->GetState("LegoAct2State"); + GameState()->FindLoadedAct(); + + if (state && state->GetUnknown0x08() == 0x68) { + bg->Enable(TRUE); + PlayCutscene(e_badEndMovie, TRUE); + m_infocenterState->SetUnknown0x74(0); + return; + } + + if (m_infocenterState->GetUnknown0x74() == 4) { + bgRed->Enable(TRUE); + + if (GameState()->GetCurrentAct() == GameState()->GetLoadedAct()) { + GameState()->SetCurrentArea(LegoGameState::e_act2main); + GameState()->StopArea(LegoGameState::e_act2main); + GameState()->SetCurrentArea(LegoGameState::e_infomain); + } + + m_infocenterState->SetUnknown0x74(5); + m_transitionDestination = LegoGameState::e_act2main; + + InfomainScript script = + (InfomainScript) m_infocenterState->GetReturnDialogue(GameState()->GetCurrentAct()).Next(); + PlayAction(script); + + InputManager()->DisableInputProcessing(); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + return; + } + + PlayMusic(JukeBox::e_informationCenter); + InfomainScript script = + (InfomainScript) m_infocenterState->GetReturnDialogue(GameState()->GetCurrentAct()).Next(); + PlayAction(script); + bgRed->Enable(TRUE); break; - case 1: - // TODO - break; - case 2: - // TODO - break; - default: - m_infocenterState->SetUnknown0x74(11); - FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); - return; } + case LegoGameState::e_act3: { + if (m_infocenterState->GetUnknown0x74() == 8) { + PlayMusic(JukeBox::e_informationCenter); + bgRed->Enable(TRUE); + PlayAction(c_exitConfirmationDialogue); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + return; + } + + Act3State* state = (Act3State*) GameState()->GetState("Act3State"); + GameState()->FindLoadedAct(); + + if (state) { + if (state->GetUnknown0x08() == 3) { + bg->Enable(TRUE); + PlayCutscene(e_badEndMovie, TRUE); + m_infocenterState->SetUnknown0x74(0); + return; + } + + if (state && state->GetUnknown0x08() == 2) { + bg->Enable(TRUE); + PlayCutscene(e_goodEndMovie, TRUE); + m_infocenterState->SetUnknown0x74(0); + return; + } + } + + if (m_infocenterState->GetUnknown0x74() == 4) { + bgRed->Enable(TRUE); + + if (GameState()->GetCurrentAct() == GameState()->GetLoadedAct()) { + GameState()->SetCurrentArea(LegoGameState::e_act3script); + GameState()->StopArea(LegoGameState::e_act3script); + GameState()->SetCurrentArea(LegoGameState::e_infomain); + } + + m_infocenterState->SetUnknown0x74(5); + m_transitionDestination = LegoGameState::e_act3script; + + InfomainScript script = + (InfomainScript) m_infocenterState->GetReturnDialogue(GameState()->GetCurrentAct()).Next(); + PlayAction(script); + + InputManager()->DisableInputProcessing(); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + return; + } + + PlayMusic(JukeBox::e_informationCenter); + InfomainScript script = + (InfomainScript) m_infocenterState->GetReturnDialogue(GameState()->GetCurrentAct()).Next(); + PlayAction(script); + bgRed->Enable(TRUE); + break; + } + } + + m_infocenterState->SetUnknown0x74(11); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } -// STUB: LEGO1 0x1006f9a0 +// FUNCTION: LEGO1 0x1006f9a0 void Infocenter::InitializeBitmaps() { - // TODO: Infocenter class size is wrong + m_radio.Initialize(TRUE); + + ((MxPresenter*) Find(m_atom, c_leftArrowCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_rightArrowCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_infoCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_boatCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_raceCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_pizzaCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_gasCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_medCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_copCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_mamaCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_papaCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_pepperCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_nickCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_lauraCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_radioCtl))->Enable(TRUE); + + m_mapAreas[0].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Info_A_Bitmap"); + m_mapAreas[0].m_area.SetLeft(391); + m_mapAreas[0].m_area.SetTop(182); + m_mapAreas[0].m_area.SetRight(427); + m_mapAreas[0].m_area.SetBottom(230); + m_mapAreas[0].m_unk0x04 = 3; + + m_mapAreas[1].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Boat_A_Bitmap"); + m_mapAreas[1].m_area.SetLeft(304); + m_mapAreas[1].m_area.SetTop(225); + m_mapAreas[1].m_area.SetRight(350); + m_mapAreas[1].m_area.SetBottom(268); + m_mapAreas[1].m_unk0x04 = 10; + + m_mapAreas[2].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Race_A_Bitmap"); + m_mapAreas[2].m_area.SetLeft(301); + m_mapAreas[2].m_area.SetTop(133); + m_mapAreas[2].m_area.SetRight(347); + m_mapAreas[2].m_area.SetBottom(181); + m_mapAreas[2].m_unk0x04 = 11; + + m_mapAreas[3].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Pizza_A_Bitmap"); + m_mapAreas[3].m_area.SetLeft(289); + m_mapAreas[3].m_area.SetTop(182); + m_mapAreas[3].m_area.SetRight(335); + m_mapAreas[3].m_area.SetBottom(225); + m_mapAreas[3].m_unk0x04 = 12; + + m_mapAreas[4].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Gas_A_Bitmap"); + m_mapAreas[4].m_area.SetLeft(350); + m_mapAreas[4].m_area.SetTop(161); + m_mapAreas[4].m_area.SetRight(391); + m_mapAreas[4].m_area.SetBottom(209); + m_mapAreas[4].m_unk0x04 = 13; + + m_mapAreas[5].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Med_A_Bitmap"); + m_mapAreas[5].m_area.SetLeft(392); + m_mapAreas[5].m_area.SetTop(130); + m_mapAreas[5].m_area.SetRight(438); + m_mapAreas[5].m_area.SetBottom(176); + m_mapAreas[5].m_unk0x04 = 14; + + m_mapAreas[6].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Cop_A_Bitmap"); + m_mapAreas[6].m_area.SetLeft(396); + m_mapAreas[6].m_area.SetTop(229); + m_mapAreas[6].m_area.SetRight(442); + m_mapAreas[6].m_area.SetBottom(272); + m_mapAreas[6].m_unk0x04 = 15; + + m_frameHotBitmap = (MxStillPresenter*) Find("MxStillPresenter", "FrameHot_Bitmap"); + + UpdateFrameHot(TRUE); } -// STUB: LEGO1 0x1006fd00 +// FUNCTION: LEGO1 0x1006fd00 MxU8 Infocenter::HandleMouseMove(MxS32 p_x, MxS32 p_y) { - return 1; + if (m_unk0x11c) { + if (!m_unk0x11c->IsEnabled()) { + MxS32 oldDisplayZ = m_unk0x11c->GetDisplayZ(); + + m_unk0x11c->SetDisplayZ(1000); + VideoManager()->SortPresenterList(); + m_unk0x11c->Enable(TRUE); + m_unk0x11c->SetPosition(p_x, p_y); + + m_unk0x11c->SetDisplayZ(oldDisplayZ); + } + else { + m_unk0x11c->SetPosition(p_x, p_y); + } + + FUN_10070d10(p_x, p_y); + return 1; + } + + return 0; } // FUNCTION: LEGO1 0x1006fda0 @@ -383,7 +622,7 @@ MxLong Infocenter::HandleKeyPress(MxS8 p_key) StopCutscene(); m_infocenterState->SetUnknown0x74(1); - if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + if (!m_infocenterState->HasRegistered()) { m_bookAnimationTimer = 1; return 1; } @@ -419,30 +658,451 @@ MxLong Infocenter::HandleKeyPress(MxS8 p_key) return result; } -// STUB: LEGO1 0x1006feb0 +// FUNCTION: LEGO1 0x1006feb0 MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) { + if (m_unk0x11c) { + MxControlPresenter* control = InputManager()->GetControlManager()->FUN_100294e0(p_x - 1, p_y - 1); + + switch (m_unk0x11c->GetAction()->GetObjectId()) { + case c_pepperSelected: + m_selectedCharacter = e_pepper; + break; + case c_mamaSelected: + m_selectedCharacter = e_mama; + break; + case c_papaSelected: + m_selectedCharacter = e_papa; + break; + case c_nickSelected: + m_selectedCharacter = e_nick; + break; + case c_lauraSelected: + m_selectedCharacter = e_laura; + break; + } + + if (control != NULL) { + m_infoManDialogueTimer = 0; + + switch (control->GetAction()->GetObjectId()) { + case c_pepperCtl: + if (m_selectedCharacter == e_pepper) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_pepperMovie); + m_unk0x1d4++; + } + break; + case c_mamaCtl: + if (m_selectedCharacter == e_mama) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_mamaMovie); + m_unk0x1d4++; + } + break; + case c_papaCtl: + if (m_selectedCharacter == e_papa) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_papaMovie); + m_unk0x1d4++; + } + break; + case c_nickCtl: + if (m_selectedCharacter == e_nick) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_nickMovie); + m_unk0x1d4++; + } + break; + case c_lauraCtl: + if (m_selectedCharacter == e_laura) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_lauraMovie); + m_unk0x1d4++; + } + break; + } + } + else { + if (m_unk0x1c8 != -1) { + m_infoManDialogueTimer = 0; + + switch (m_mapAreas[m_unk0x1c8].m_unk0x04) { + case 3: + GameState()->FUN_10039780(m_selectedCharacter); + + switch (m_selectedCharacter) { + case e_pepper: + PlayAction(c_pepperCharacterSelect); + break; + case e_mama: + PlayAction(c_mamaCharacterSelect); + break; + case e_papa: + PlayAction(c_papaCharacterSelect); + break; + case e_nick: + PlayAction(c_nickCharacterSelect); + break; + case e_laura: + PlayAction(c_lauraCharacterSelect); + break; + } + break; + case 10: + if (m_selectedCharacter) { + m_transitionDestination = LegoGameState::e_unk16; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 11: + if (m_selectedCharacter) { + m_transitionDestination = LegoGameState::e_unk19; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 12: + if (m_selectedCharacter) { + m_transitionDestination = LegoGameState::e_unk22; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 13: + if (m_selectedCharacter) { + m_transitionDestination = LegoGameState::e_unk25; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 14: + if (m_selectedCharacter) { + m_transitionDestination = LegoGameState::e_unk29; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 15: + if (m_selectedCharacter) { + m_transitionDestination = LegoGameState::e_unk32; + m_infocenterState->SetUnknown0x74(5); + } + break; + } + } + } + + m_unk0x11c->Enable(FALSE); + m_unk0x11c = NULL; + + if (m_infocenterState->GetUnknown0x74() == 5) { + InfomainScript dialogueToPlay; + + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { + if (!m_infocenterState->HasRegistered()) { + m_infocenterState->SetUnknown0x74(2); + m_transitionDestination = LegoGameState::e_noArea; + dialogueToPlay = c_registerToContinueDialogue; + } + else { + switch (m_selectedCharacter) { + case e_pepper: + dialogueToPlay = c_pepperCharacterSelect; + GameState()->SetUnknown0x0c(m_selectedCharacter); + break; + case e_mama: + dialogueToPlay = c_mamaCharacterSelect; + GameState()->SetUnknown0x0c(m_selectedCharacter); + break; + case e_papa: + dialogueToPlay = c_papaCharacterSelect; + GameState()->SetUnknown0x0c(m_selectedCharacter); + break; + case e_nick: + dialogueToPlay = c_nickCharacterSelect; + GameState()->SetUnknown0x0c(m_selectedCharacter); + break; + case e_laura: + dialogueToPlay = c_lauraCharacterSelect; + GameState()->SetUnknown0x0c(m_selectedCharacter); + break; + default: + dialogueToPlay = + (InfomainScript) m_infocenterState->GetLeaveDialogue(GameState()->GetCurrentAct()).Next(); + break; + } + + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + } + } + else { + dialogueToPlay = + (InfomainScript) m_infocenterState->GetLeaveDialogue(GameState()->GetCurrentAct()).Next(); + } + + PlayAction(dialogueToPlay); + } + + UpdateFrameHot(TRUE); + FUN_10070d10(0, 0); + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x10070370 +MxU8 Infocenter::HandleClick(LegoControlManagerEvent& p_param) +{ + if (p_param.GetUnknown0x28() == 1) { + m_infoManDialogueTimer = 0; + + InfomainScript actionToPlay = c_noInfomain; + StopCurrentAction(); + InfomainScript characterBitmap = c_noInfomain; + + LegoGameState* state = GameState(); + + switch (p_param.GetClickedObjectId()) { + case c_leftArrowCtl: + m_infocenterState->SetUnknown0x74(14); + StopCurrentAction(); + + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { + m_radio.Stop(); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_transitionDestination = LegoGameState::e_elevbott; + } + else { + MxU32 objectId = m_infocenterState->GetBricksterDialogue().Next(); + PlayAction((InfomainScript) objectId); + } + + break; + case c_rightArrowCtl: + m_infocenterState->SetUnknown0x74(14); + StopCurrentAction(); + + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { + m_radio.Stop(); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_transitionDestination = LegoGameState::e_infoscor; + } + else { + MxU32 objectId = m_infocenterState->GetBricksterDialogue().Next(); + PlayAction((InfomainScript) objectId); + } + + break; + case c_infoCtl: + actionToPlay = c_infoCtlDescription; + m_radio.Stop(); + break; + case c_doorCtl: + if (m_infocenterState->GetUnknown0x74() != 8) { + actionToPlay = c_exitConfirmationDialogue; + m_radio.Stop(); + m_infocenterState->SetUnknown0x74(8); + } + + break; + case c_boatCtl: + actionToPlay = c_boatCtlDescription; + m_radio.Stop(); + break; + case c_raceCtl: + actionToPlay = c_raceCtlDescription; + m_radio.Stop(); + break; + case c_pizzaCtl: + actionToPlay = c_pizzaCtlDescription; + m_radio.Stop(); + break; + case c_gasCtl: + actionToPlay = c_gasCtlDescription; + m_radio.Stop(); + break; + case c_medCtl: + actionToPlay = c_medCtlDescription; + m_radio.Stop(); + break; + case c_copCtl: + actionToPlay = c_copCtlDescription; + m_radio.Stop(); + break; + case c_bigInfoCtl: + switch (state->GetCurrentAct()) { + case LegoGameState::e_act1: + switch (state->GetPreviousArea()) { + case LegoGameState::e_infodoor: + case LegoGameState::e_regbook: + case LegoGameState::e_infoscor: + m_infocenterState->SetUnknown0x74(5); + m_transitionDestination = state->GetPreviousArea(); + actionToPlay = + (InfomainScript) m_infocenterState->GetLeaveDialogue(GameState()->GetCurrentAct()).Next(); + m_radio.Stop(); + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + break; + case LegoGameState::e_unk4: + if (state->GetUnknownC()) { + if (m_infocenterState->HasRegistered()) { + m_infocenterState->SetUnknown0x74(5); + m_transitionDestination = state->GetPreviousArea(); + actionToPlay = + (InfomainScript) m_infocenterState->GetLeaveDialogue(GameState()->GetCurrentAct()) + .Next(); + m_radio.Stop(); + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + } + else { + PlayAction(c_registerToContinueDialogue); + m_infocenterState->SetUnknown0x74(2); + } + } + break; + } + break; + case LegoGameState::e_act2: + m_infocenterState->SetUnknown0x74(5); + m_transitionDestination = LegoGameState::e_act2main; + actionToPlay = + (InfomainScript) m_infocenterState->GetLeaveDialogue(GameState()->GetCurrentAct()).Next(); + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + break; + case LegoGameState::e_act3: + m_infocenterState->SetUnknown0x74(5); + m_transitionDestination = LegoGameState::e_act3script; + actionToPlay = + (InfomainScript) m_infocenterState->GetLeaveDialogue(GameState()->GetCurrentAct()).Next(); + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + break; + } + break; + case c_bookCtl: + m_transitionDestination = LegoGameState::e_regbook; + m_infocenterState->SetUnknown0x74(4); + actionToPlay = GameState()->GetCurrentAct() != LegoGameState::e_act1 ? c_goToRegBookRed : c_goToRegBook; + m_radio.Stop(); + GameState()->SetUnknown0x42c(GameState()->GetPreviousArea()); + InputManager()->DisableInputProcessing(); + break; + case c_mamaCtl: + characterBitmap = c_mamaSelected; + UpdateFrameHot(FALSE); + break; + case c_papaCtl: + characterBitmap = c_papaSelected; + UpdateFrameHot(FALSE); + break; + case c_pepperCtl: + characterBitmap = c_pepperSelected; + UpdateFrameHot(FALSE); + break; + case c_nickCtl: + characterBitmap = c_nickSelected; + UpdateFrameHot(FALSE); + break; + case c_lauraCtl: + characterBitmap = c_lauraSelected; + UpdateFrameHot(FALSE); + break; + } + + if (actionToPlay != c_noInfomain) { + PlayAction(actionToPlay); + } + + if (characterBitmap != c_noInfomain) { + m_unk0x11c = (MxStillPresenter*) Find(m_atom, characterBitmap); + } + } + return 1; } -// STUB: LEGO1 0x10070370 -MxU8 Infocenter::HandleNotification17(MxParam&) +// FUNCTION: LEGO1 0x10070870 +MxLong Infocenter::HandleNotification0(MxNotificationParam& p_param) { - return 1; -} + // MxLong result + MxCore* sender = p_param.GetSender(); + + if (sender == NULL) { + if (m_infocenterState->GetUnknown0x74() == 8) { + m_infoManDialogueTimer = 0; + StopCutscene(); + PlayAction(c_exitConfirmationDialogue); + } + } + else if (sender->IsA("MxEntity") && m_infocenterState->GetUnknown0x74() != 5 && m_infocenterState->GetUnknown0x74() != 12) { + switch (((MxEntity*) sender)->GetEntityId()) { + case 5: { + m_infoManDialogueTimer = 0; + + InfomainScript objectId; + if (GameState()->GetCurrentAct() != LegoGameState::e_act1) { + objectId = (InfomainScript) m_infocenterState->GetExitDialogueAct23().Next(); + } + else { + objectId = (InfomainScript) m_infocenterState->GetExitDialogueAct1().Next(); + } + + PlayAction(objectId); + SetROIUnknown0x0c(g_object2x4red, 0); + SetROIUnknown0x0c(g_object2x4grn, 0); + return 1; + } + case 6: + if (m_infocenterState->GetUnknown0x74() == 8) { + StopCurrentAction(); + SetROIUnknown0x0c(g_object2x4red, 0); + SetROIUnknown0x0c(g_object2x4grn, 0); + m_infocenterState->SetUnknown0x74(2); + PlayAction(c_infomanSneeze); + return 1; + } + case 7: + if (m_infocenterState->GetUnknown0x74() == 8) { + if (m_infocenterState->HasRegistered()) { + GameState()->Save(0); + } + + m_infocenterState->SetUnknown0x74(12); + PlayAction(c_exitGameDialogue); + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + return 1; + } + } + } + else { + if (sender->IsA("Radio") && m_radio.GetState()->IsActive()) { + if (m_currentInfomainScript == c_mamaMovie || m_currentInfomainScript == c_papaMovie || + m_currentInfomainScript == c_pepperMovie || m_currentInfomainScript == c_nickMovie || + m_currentInfomainScript == c_lauraMovie || m_currentInfomainScript == c_infoCtlDescription || + m_currentInfomainScript == c_boatCtlDescription || m_currentInfomainScript == c_raceCtlDescription || + m_currentInfomainScript == c_pizzaCtlDescription || m_currentInfomainScript == c_gasCtlDescription || + m_currentInfomainScript == c_medCtlDescription || m_currentInfomainScript == c_copCtlDescription) { + StopCurrentAction(); + } + } + } -// STUB: LEGO1 0x10070870 -MxLong Infocenter::HandleNotification0(MxParam&) -{ return 1; } // FUNCTION: LEGO1 0x10070aa0 -void Infocenter::VTable0x68(MxBool p_add) +void Infocenter::Enable(MxBool p_enable) { - LegoWorld::VTable0x68(p_add); + LegoWorld::Enable(p_enable); - if (p_add) { + if (p_enable) { InputManager()->SetWorld(this); SetIsWorldActive(FALSE); } @@ -504,9 +1164,9 @@ void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale) VideoManager()->GetDisplaySurface()->ClearScreen(); if (m_currentCutscene != e_noIntro) { - // check if the cutscene is not an ending + // check if the cutscene is an ending if (m_currentCutscene >= e_badEndMovie && m_currentCutscene <= e_goodEndMovie) { - FUN_10070e90(); + Reset(); } InvokeAction(Extra::ActionType::e_opendisk, *g_introScript, m_currentCutscene, NULL); } @@ -531,26 +1191,197 @@ MxBool Infocenter::VTable0x5c() return TRUE; } -// STUB: LEGO1 0x10070dc0 -void Infocenter::FUN_10070dc0(MxBool) +// FUNCTION: LEGO1 0x10070d10 +void Infocenter::FUN_10070d10(MxS32 p_x, MxS32 p_y) { + MxS16 i; + for (i = 0; i < (MxS32) (sizeof(m_mapAreas) / sizeof(m_mapAreas[0])); i++) { + MxS32 right = m_mapAreas[i].m_area.GetRight(); + MxS32 bottom = m_mapAreas[i].m_area.GetBottom(); + MxS32 left = m_mapAreas[i].m_area.GetLeft(); + MxS32 top = m_mapAreas[i].m_area.GetTop(); + + if (left <= p_x && p_x <= right && top <= p_y && p_y <= bottom) { + break; + } + } + + if (i == 7) { + i = -1; + } + + if (i != m_unk0x1c8) { + if (m_unk0x1c8 != -1) { + m_mapAreas[m_unk0x1c8].m_presenter->Enable(FALSE); + } + + m_unk0x1c8 = i; + if (i != -1) { + m_mapAreas[i].m_presenter->Enable(TRUE); + } + } } -// STUB: LEGO1 0x10070e90 -void Infocenter::FUN_10070e90() +// FUNCTION: LEGO1 0x10070dc0 +void Infocenter::UpdateFrameHot(MxBool p_display) { + if (p_display) { + MxS32 x, y; + + switch (GameState()->GetUnknownC()) { + case 1: + x = 302; + y = 81; + break; + case 2: + x = 204; + y = 81; + break; + case 3: + x = 253; + y = 81; + break; + case 4: + x = 353; + y = 81; + break; + case 5: + x = 399; + y = 81; + break; + default: + return; + } + + MxS32 originalDisplayZ = m_frameHotBitmap->GetDisplayZ(); + + m_frameHotBitmap->SetDisplayZ(1000); + VideoManager()->SortPresenterList(); + + m_frameHotBitmap->Enable(TRUE); + m_frameHotBitmap->SetPosition(x, y); + m_frameHotBitmap->SetDisplayZ(originalDisplayZ); + } + else { + if (m_frameHotBitmap) { + m_frameHotBitmap->Enable(FALSE); + } + } } -// STUB: LEGO1 0x10070f60 +// FUNCTION: LEGO1 0x10070e90 +void Infocenter::Reset() +{ + switch (GameState()->GetCurrentAct()) { + case LegoGameState::e_act2: + Lego()->RemoveWorld(*g_act2mainScript, 0); + break; + case LegoGameState::e_act3: + Lego()->RemoveWorld(*g_act3Script, 0); + break; + } + + PlantManager()->FUN_10027120(); + BuildingManager()->FUN_10030590(); + AnimationManager()->FUN_1005ee80(FALSE); + UnkSaveDataWriter()->FUN_100832a0(); + GameState()->SetCurrentAct(LegoGameState::e_act1); + GameState()->SetPreviousArea(LegoGameState::e_noArea); + GameState()->SetUnknown0x42c(LegoGameState::e_noArea); + + InitializeBitmaps(); + m_selectedCharacter = e_pepper; + + GameState()->FUN_10039780(e_pepper); + + HelicopterState* state = (HelicopterState*) GameState()->GetState("HelicopterState"); + + if (state) { + state->SetFlag(); + } +} + +// FUNCTION: LEGO1 0x10070f60 MxBool Infocenter::VTable0x64() { + if (m_infocenterState != NULL) { + MxU32 val = m_infocenterState->GetUnknown0x74(); + + if (val == 0) { + StopCutscene(); + m_infocenterState->SetUnknown0x74(1); + } + else if (val == 13) { + StopCredits(); + } + else if (val != 8) { + m_infocenterState->SetUnknown0x74(8); + +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType0, NULL); + Notify(param); + } +#else + Notify(MxNotificationParam(c_notificationType0, NULL)); +#endif + } + } + return FALSE; } -// STUB: LEGO1 0x10071030 +// FUNCTION: LEGO1 0x10071030 void Infocenter::StartCredits() { - // TODO + MxPresenter* presenter; + + while (!m_set0xa8.empty()) { + MxCoreSet::iterator it = m_set0xa8.begin(); + MxCore* object = *it; + m_set0xa8.erase(it); + + if (object->IsA("MxPresenter")) { + presenter = (MxPresenter*) object; + MxDSAction* action = presenter->GetAction(); + + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + else { + delete object; + } + } + + MxPresenterListCursor cursor(&m_controlPresenters); + + while (cursor.First(presenter)) { + cursor.Detach(); + + MxDSAction* action = presenter->GetAction(); + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + + BackgroundAudioManager()->Stop(); + + MxS16 i = 0; + do { + if (m_infocenterState->GetNameLetter(i) != NULL) { + m_infocenterState->GetNameLetter(i)->Enable(FALSE); + } + i++; + } while (i < m_infocenterState->GetMaxNameLength()); + + VideoManager()->FUN_1007c520(); + GetViewManager()->RemoveAll(NULL); + + InvokeAction(Extra::e_opendisk, *g_creditsScript, c_unk499, NULL); + SetAppCursor(0); } // FUNCTION: LEGO1 0x10071250 diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp index 79e88a99..74d1cfdc 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp @@ -1,18 +1,22 @@ #include "infocenterdoor.h" +#include "infocenterstate.h" #include "jukebox.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "legoomni.h" +#include "mxactionnotificationparam.h" +#include "mxbackgroundaudiomanager.h" #include "mxnotificationmanager.h" +#include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(InfocenterDoor, 0xfc) // FUNCTION: LEGO1 0x10037730 InfocenterDoor::InfocenterDoor() { - m_unk0xf8 = 0; + m_unk0xf8 = LegoGameState::e_noArea; NotificationManager()->Register(this); } @@ -39,33 +43,112 @@ MxResult InfocenterDoor::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetUnknown424(3); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(LegoGameState::e_infodoor); + GameState()->StopArea(LegoGameState::e_previousArea); return result; } -// STUB: LEGO1 0x100379e0 +// FUNCTION: LEGO1 0x100379e0 MxLong InfocenterDoor::Notify(MxParam& p_param) { - // TODO - return LegoWorld::Notify(p_param); + MxLong result = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationEndAction: + if (((MxEndActionNotificationParam&) p_param).GetAction()->GetAtomId() == m_atom) { + BackgroundAudioManager()->RaiseVolume(); + result = 1; + } + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_unk0xf8); + result = 1; + break; + } + } + + return result; } // FUNCTION: LEGO1 0x10037a70 -void InfocenterDoor::VTable0x50() +void InfocenterDoor::ReadyWorld() { - LegoWorld::VTable0x50(); + LegoWorld::ReadyWorld(); PlayMusic(JukeBox::e_informationCenter); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } -// FUNCTION: LEGO1 0x10037c80 -void InfocenterDoor::VTable0x68(MxBool p_add) +// FUNCTION: LEGO1 0x10037a90 +MxLong InfocenterDoor::HandleClick(LegoControlManagerEvent& p_param) { - LegoWorld::VTable0x68(p_add); + MxLong result = 0; - if (p_add) { + if (p_param.GetUnknown0x28() == 1) { + DeleteObjects(&m_atom, 500, 510); + + switch (p_param.GetClickedObjectId()) { + case 1: + m_unk0xf8 = LegoGameState::e_infoscor; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 2: + m_unk0xf8 = LegoGameState::e_elevbott; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 3: + m_unk0xf8 = LegoGameState::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 4: + if (GameState()->GetUnknownC()) { + InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState"); + if (state->HasRegistered()) { + m_unk0xf8 = LegoGameState::e_unk4; + } + else { + MxDSAction action; + action.SetObjectId(503); + action.SetAtomId(*g_infodoorScript); + BackgroundAudioManager()->LowerVolume(); + Start(&action); + goto done; + } + } + else { + MxDSAction action; + action.SetObjectId(500); + action.SetAtomId(*g_infodoorScript); + BackgroundAudioManager()->LowerVolume(); + Start(&action); + goto done; + } + + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + + done: + result = 1; + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x10037c80 +void InfocenterDoor::Enable(MxBool p_enable) +{ + LegoWorld::Enable(p_enable); + + if (p_enable) { InputManager()->SetWorld(this); SetIsWorldActive(FALSE); } @@ -80,6 +163,6 @@ void InfocenterDoor::VTable0x68(MxBool p_add) MxBool InfocenterDoor::VTable0x64() { DeleteObjects(&m_atom, 500, 510); - m_unk0xf8 = 2; + m_unk0xf8 = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp index 76ffd3ea..0394d710 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp @@ -1,12 +1,113 @@ #include "infocenterstate.h" +#include "infocenter.h" + DECOMP_SIZE_ASSERT(InfocenterState, 0x94); +// GLOBAL: LEGO1 0x100f76a8 +Infocenter::InfomainScript g_exitDialogueAct1[14] = { + Infocenter::c_clickOnObjectsGuidanceDialogue, + Infocenter::c_arrowNavigationGuidanceDialogue, + Infocenter::c_elevatorGuidanceDialogue, + Infocenter::c_radioGuidanceDialogue, + Infocenter::c_exitGuidanceDialogue1, + Infocenter::c_goOutsideGuidanceDialogue, + Infocenter::c_experimentGuidanceDialogue, + Infocenter::c_returnBackGuidanceDialogue1, + Infocenter::c_bricksterWarningDialogue, + Infocenter::c_infomanHiccup, + Infocenter::c_infomanSneeze, + Infocenter::c_infomanLaughs, + Infocenter::c_newGameGuidanceDialogue, + Infocenter::c_returnBackGuidanceDialogue3 +}; + +// GLOBAL: LEGO1 0x100f76e0 +Infocenter::InfomainScript g_exitDialogueAct23[6] = { + Infocenter::c_bricksterWarningDialogue, + Infocenter::c_newGameGuidanceDialogue, + Infocenter::c_bricksterEscapedDialogue1, + Infocenter::c_bricksterEscapedDialogue5, + Infocenter::c_exitGuidanceDialogue2 + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f76f8 +Infocenter::InfomainScript g_returnDialogueAct1[6] = { + Infocenter::c_returnBackGuidanceDialogue2, + Infocenter::c_reenterInfoCenterDialogue1, + Infocenter::c_reenterInfoCenterDialogue2, + Infocenter::c_reenterInfoCenterDialogue3, + Infocenter::c_reenterInfoCenterDialogue4 + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f7710 +Infocenter::InfomainScript g_returnDialogueAct2[4] = { + Infocenter::c_bricksterEscapedDialogue1, + Infocenter::c_bricksterEscapedDialogue2, + Infocenter::c_bricksterEscapedDialogue3, + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f7720 +Infocenter::InfomainScript g_returnDialogueAct3[4] = { + Infocenter::c_bricksterEscapedDialogue4, + Infocenter::c_bricksterEscapedDialogue5, + Infocenter::c_bricksterEscapedDialogue6, + Infocenter::c_bricksterEscapedDialogue7 +}; + +// GLOBAL: LEGO1 0x100f7730 +Infocenter::InfomainScript g_leaveDialogueAct1[4] = { + Infocenter::c_leaveInfoCenterDialogue1, + Infocenter::c_leaveInfoCenterDialogue2, + Infocenter::c_leaveInfoCenterDialogue3, + Infocenter::c_leaveInfoCenterDialogue4 +}; + +// GLOBAL: LEGO1 0x100f7740 +Infocenter::InfomainScript g_leaveDialogueAct2[4] = + {Infocenter::c_unk569, Infocenter::c_unk570, Infocenter::c_unk571, Infocenter::c_unk572}; + +// GLOBAL: LEGO1 0x100f7750 +Infocenter::InfomainScript g_leaveDialogueAct3[4] = { + Infocenter::c_unk566, + Infocenter::c_unk567, + Infocenter::c_unk568, + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f7760 +Infocenter::InfomainScript g_bricksterDialogue[2] = {Infocenter::c_bricksterDialogue, Infocenter::c_bricksterLaughs}; + // FUNCTION: LEGO1 0x10071600 InfocenterState::InfocenterState() { - // TODO - memset(m_buffer, 0, sizeof(m_buffer)); + m_exitDialogueAct1 = LegoState::Playlist((MxU32*) g_exitDialogueAct1, _countof(g_exitDialogueAct1)); + m_exitDialogueAct23 = LegoState::Playlist((MxU32*) g_exitDialogueAct23, _countof(g_exitDialogueAct23) - 1); + + m_returnDialogue[LegoGameState::e_act1] = + LegoState::Playlist((MxU32*) g_returnDialogueAct1, _countof(g_returnDialogueAct1) - 1); + + m_returnDialogue[LegoGameState::e_act2] = + LegoState::Playlist((MxU32*) g_returnDialogueAct2, _countof(g_returnDialogueAct2) - 1); + + m_returnDialogue[LegoGameState::e_act3] = + LegoState::Playlist((MxU32*) g_returnDialogueAct3, _countof(g_returnDialogueAct3)); + + m_leaveDialogue[LegoGameState::e_act1] = + LegoState::Playlist((MxU32*) g_leaveDialogueAct1, _countof(g_leaveDialogueAct1)); + + m_leaveDialogue[LegoGameState::e_act2] = + LegoState::Playlist((MxU32*) g_leaveDialogueAct2, _countof(g_leaveDialogueAct2)); + + m_leaveDialogue[LegoGameState::e_act3] = + LegoState::Playlist((MxU32*) g_leaveDialogueAct3, _countof(g_leaveDialogueAct3) - 1); + + m_bricksterDialogue = LegoState::Playlist((MxU32*) g_bricksterDialogue, _countof(g_bricksterDialogue)); + + memset(m_letters, 0, sizeof(m_letters)); } // FUNCTION: LEGO1 0x10071920 @@ -14,10 +115,10 @@ InfocenterState::~InfocenterState() { MxS16 i = 0; do { - if (GetInfocenterBufferElement(i) != NULL) { - delete GetInfocenterBufferElement(i)->GetAction(); - delete GetInfocenterBufferElement(i); + if (GetNameLetter(i) != NULL) { + delete GetNameLetter(i)->GetAction(); + delete GetNameLetter(i); } i++; - } while (i < GetInfocenterBufferSize()); + } while (i < GetMaxNameLength()); } diff --git a/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp b/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp index f68bc29e..d8ae7003 100644 --- a/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp @@ -1,11 +1,37 @@ #include "registrationbook.h" +#include "infocenterstate.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" #include "legoomni.h" +#include "mxactionnotificationparam.h" +#include "mxnotificationmanager.h" +#include "mxtimer.h" -// STUB: LEGO1 0x10076d20 -RegistrationBook::RegistrationBook() +DECOMP_SIZE_ASSERT(RegistrationBook, 0x2d0) + +// FUNCTION: LEGO1 0x10076d20 +RegistrationBook::RegistrationBook() : m_unk0xf8(0x80000000), m_unk0xfc(1) { - // TODO + memset(m_unk0x100, 0, sizeof(m_unk0x100)); + memset(m_unk0x168, 0, sizeof(m_unk0x168)); + + // Maybe not be part of the struct, but then it would need packing + m_unk0x280.m_unk0x0e = 0; + + memset(m_unk0x290, 0, sizeof(m_unk0x290)); + memset(&m_unk0x280, -1, sizeof(m_unk0x280) - 2); + + m_unk0x2b8 = 0; + m_infocenterState = NULL; + + NotificationManager()->Register(this); + + m_unk0x2c1 = 0; + m_unk0x2c4 = 0; + m_unk0x2c8 = 0; + m_unk0x2cc = 0; } // STUB: LEGO1 0x10076f50 @@ -14,22 +40,77 @@ RegistrationBook::~RegistrationBook() // TODO } -// STUB: LEGO1 0x10077060 +// FUNCTION: LEGO1 0x10077060 MxResult RegistrationBook::Create(MxDSAction& p_dsAction) { - return SUCCESS; + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + SetIsWorldActive(FALSE); + InputManager()->Register(this); + + GameState()->SetCurrentArea(LegoGameState::e_regbook); + GameState()->StopArea(LegoGameState::e_previousArea); + + m_infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); + } + return result; } -// STUB: LEGO1 0x100770e0 +// FUNCTION: LEGO1 0x100770e0 MxLong RegistrationBook::Notify(MxParam& p_param) { - // TODO + MxLong result = 0; + LegoWorld::Notify(p_param); + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) p_param); + break; + case c_notificationKeyPress: + m_unk0xf8 = Timer()->GetTime(); + result = HandleKeyPress(((LegoEventNotificationParam&) p_param).GetKey()); + break; + case c_notificationButtonDown: + m_unk0xf8 = Timer()->GetTime(); + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationType19: + result = HandleNotification19(p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(LegoGameState::e_infomain); + break; + } + } + + return result; +} + +// STUB: LEGO1 0x10077210 +MxLong RegistrationBook::HandleEndAction(MxEndActionNotificationParam& p_param) +{ + return 0; +} + +// STUB: LEGO1 0x100772d0 +MxLong RegistrationBook::HandleKeyPress(MxS8 p_key) +{ + return 0; +} + +// STUB: LEGO1 0x100774a0 +MxLong RegistrationBook::HandleClick(LegoControlManagerEvent& p_param) +{ return 0; } // STUB: LEGO1 0x10077cc0 -void RegistrationBook::VTable0x50() +void RegistrationBook::ReadyWorld() { // TODO } @@ -37,14 +118,36 @@ void RegistrationBook::VTable0x50() // STUB: LEGO1 0x10077fd0 MxResult RegistrationBook::Tickle() { - // TODO + if (!m_worldStarted) { + LegoWorld::Tickle(); + } + else { + // TODO + } + return SUCCESS; } -// STUB: LEGO1 0x10078180 -void RegistrationBook::VTable0x68(MxBool p_add) +// FUNCTION: LEGO1 0x10078180 +void RegistrationBook::Enable(MxBool p_enable) { - // TODO + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } +} + +// STUB: LEGO1 0x100781d0 +MxLong RegistrationBook::HandleNotification19(MxParam& p_param) +{ + return 0; } // FUNCTION: LEGO1 0x100783e0 diff --git a/LEGO1/lego/legoomni/src/infocenter/score.cpp b/LEGO1/lego/legoomni/src/infocenter/score.cpp index 2d7d8c05..0f924725 100644 --- a/LEGO1/lego/legoomni/src/infocenter/score.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/score.cpp @@ -1,12 +1,12 @@ #include "score.h" #include "ambulancemissionstate.h" -#include "gifmanager.h" #include "jukebox.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "legoomni.h" +#include "misc/legocontainer.h" #include "mxnotificationmanager.h" #include "mxnotificationparam.h" #include "mxtransitionmanager.h" @@ -19,7 +19,7 @@ DECOMP_SIZE_ASSERT(Score, 0x104) // FUNCTION: LEGO1 0x10001000 Score::Score() { - m_unk0xf8 = 0; + m_unk0xf8 = LegoGameState::e_noArea; NotificationManager()->Register(this); } @@ -32,8 +32,9 @@ MxBool Score::VTable0x5c() // FUNCTION: LEGO1 0x10001200 Score::~Score() { - if (InputManager()->GetWorld() == this) + if (InputManager()->GetWorld() == this) { InputManager()->ClearWorld(); + } InputManager()->UnRegister(this); ControlManager()->Unregister(this); NotificationManager()->Unregister(this); @@ -52,8 +53,8 @@ MxResult Score::Create(MxDSAction& p_dsAction) LegoGameState* gs = GameState(); ScoreState* state = (ScoreState*) gs->GetState("ScoreState"); m_state = state ? state : (ScoreState*) gs->CreateState("ScoreState"); - GameState()->SetUnknown424(0xd); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(LegoGameState::e_infoscor); + GameState()->StopArea(LegoGameState::e_previousArea); } return result; @@ -87,17 +88,19 @@ MxLong Score::Notify(MxParam& p_param) ret = FUN_10001510((MxEndActionNotificationParam&) p_param); break; case c_notificationKeyPress: - if (((LegoEventNotificationParam&) p_param).GetKey() == 0x20) + if (((LegoEventNotificationParam&) p_param).GetKey() == 0x20) { DeleteScript(); // Shutting down + } ret = 1; break; - case c_notificationType17: - ret = FUN_100016d0((MxType17NotificationParam&) p_param); + case c_notificationClick: + ret = FUN_100016d0((LegoControlManagerEvent&) p_param); break; case c_notificationTransitioned: DeleteObjects(g_infoscorScript, 7, 9); - if (m_unk0xf8) - GameState()->HandleAction(m_unk0xf8); + if (m_unk0xf8) { + GameState()->SwitchArea(m_unk0xf8); + } ret = 1; break; default: @@ -116,7 +119,7 @@ MxLong Score::FUN_10001510(MxEndActionNotificationParam& p_param) MxU32 id = action->GetObjectId(); switch (action->GetObjectId()) { case 10: - m_unk0xf8 = 0x38; + m_unk0xf8 = LegoGameState::e_histbook; TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; case 0x1f5: @@ -129,9 +132,9 @@ MxLong Score::FUN_10001510(MxEndActionNotificationParam& p_param) } // FUNCTION: LEGO1 0x10001580 -void Score::VTable0x50() +void Score::ReadyWorld() { - LegoWorld::VTable0x50(); + LegoWorld::ReadyWorld(); MxDSAction action; action.SetObjectId(0x1f4); @@ -145,26 +148,27 @@ void Score::VTable0x50() action.SetAtomId(*g_infoscorScript); Start(&action); } - else + else { PlayMusic(JukeBox::e_informationCenter); + } FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x100016d0 -MxLong Score::FUN_100016d0(MxType17NotificationParam& p_param) +MxLong Score::FUN_100016d0(LegoControlManagerEvent& p_param) { - MxS16 l = p_param.GetUnknown28(); + MxS16 l = p_param.GetUnknown0x28(); - if (l == 1 || p_param.GetUnknown20() == 4) { - switch (p_param.GetUnknown20()) { + if (l == 1 || p_param.GetClickedObjectId() == 4) { + switch (p_param.GetClickedObjectId()) { case 1: - m_unk0xf8 = 2; + m_unk0xf8 = LegoGameState::e_infomain; DeleteScript(); TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; case 2: - m_unk0xf8 = 3; + m_unk0xf8 = LegoGameState::e_infodoor; DeleteScript(); TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; @@ -213,22 +217,23 @@ MxLong Score::FUN_100016d0(MxType17NotificationParam& p_param) } // FUNCTION: LEGO1 0x10001980 -void Score::VTable0x68(MxBool p_add) +void Score::Enable(MxBool p_enable) { - LegoWorld::VTable0x68(p_add); + LegoWorld::Enable(p_enable); - if (p_add) { + if (p_enable) { InputManager()->SetWorld(this); SetIsWorldActive(FALSE); } - else if (InputManager()->GetWorld() == this) + else if (InputManager()->GetWorld() == this) { InputManager()->ClearWorld(); + } } // FUNCTION: LEGO1 0x100019d0 void Score::Paint() { - GifData* gd = GetGifManager()->Get("bigcube.gif"); + LegoTextureInfo* gd = TextureContainer()->Get("bigcube.gif"); if (gd) { RaceState* l78 = (RaceState*) GameState()->GetState("JetskiRaceState"); @@ -249,25 +254,30 @@ void Score::Paint() for (MxU8 id = 1; id <= 5; id++) { m_surface = (MxU8*) desc.lpSurface; MxU16 color = 0; - if (l70) + if (l70) { color = l70->GetColor(id); + } MxU32 row = id - 1; FillArea(0, row, color); color = 0; - if (l78) + if (l78) { color = l78->GetColor(id); + } FillArea(1, row, color); color = 0; - if (l74) + if (l74) { color = l74->GetColor(id); + } FillArea(2, row, color); color = 0; - if (lesi) + if (lesi) { color = lesi->GetColor(id); + } FillArea(3, row, color); color = 0; - if (lebp) + if (lebp) { color = lebp->GetColor(id); + } FillArea(4, row, color); } @@ -303,12 +313,12 @@ void Score::FillArea(MxU32 p_x, MxU32 p_y, MxS16 p_color) data[0] = 0x11; data[17] = 0x28; data[18] = 0x28; - data[1] = 0xf; + data[1] = 0x0f; MxU32 size = data[p_x + 14]; MxU8* ptr = data[p_x + 4] + data[p_y + 9] + m_surface; MxS32 count = data[p_y + 19]; - data[2] = 0x8; - data[3] = 0x5; + data[2] = 0x08; + data[3] = 0x05; MxU32 value = data[p_color]; for (; count > 0; count--) { memset(ptr++, value, size); @@ -320,6 +330,6 @@ void Score::FillArea(MxU32 p_x, MxU32 p_y, MxS16 p_color) MxBool Score::VTable0x64() { DeleteScript(); - m_unk0xf8 = 2; + m_unk0xf8 = LegoGameState::e_infomain; return TRUE; } diff --git a/LEGO1/lego/legoomni/src/infocenter/scorestate.cpp b/LEGO1/lego/legoomni/src/infocenter/scorestate.cpp index 669b41e9..bab97719 100644 --- a/LEGO1/lego/legoomni/src/infocenter/scorestate.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/scorestate.cpp @@ -1,6 +1,6 @@ #include "scorestate.h" -DECOMP_SIZE_ASSERT(ScoreState, 0x0C); +DECOMP_SIZE_ASSERT(ScoreState, 0x0c); // FUNCTION: LEGO1 0x1000de20 MxBool ScoreState::VTable0x14() diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 87c72a63..1b70583c 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -2,26 +2,30 @@ #include "legocontrolmanager.h" #include "legoomni.h" +#include "legovideomanager.h" #include "mxautolocker.h" +#include "roi/legoroi.h" -DECOMP_SIZE_ASSERT(LegoInputManager, 0x338); -DECOMP_SIZE_ASSERT(LegoEventQueue, 0x18); +DECOMP_SIZE_ASSERT(LegoInputManager, 0x338) +DECOMP_SIZE_ASSERT(LegoNotifyList, 0x18) +DECOMP_SIZE_ASSERT(LegoNotifyListCursor, 0x10) +DECOMP_SIZE_ASSERT(LegoEventQueue, 0x18) // GLOBAL: LEGO1 0x100f31b0 MxS32 g_unk0x100f31b0 = -1; // GLOBAL: LEGO1 0x100f31b4 -MxS32 g_unk0x100f31b4 = 0; +const char* g_unk0x100f31b4 = NULL; // FUNCTION: LEGO1 0x1005b790 LegoInputManager::LegoInputManager() { - m_unk0x5c = NULL; + m_keyboardNotifyList = NULL; m_world = NULL; m_camera = NULL; m_eventQueue = NULL; m_unk0x80 = 0; - m_timer = 0; + m_autoDragTimerID = 0; m_unk0x6c = 0; m_unk0x70 = 0; m_controlManager = NULL; @@ -37,10 +41,10 @@ LegoInputManager::LegoInputManager() m_unk0x335 = FALSE; m_unk0x336 = FALSE; m_unk0x74 = 0x19; - m_timeout = 1000; + m_autoDragTime = 1000; } -// STUB: LEGO1 0x1005b8b0 +// FUNCTION: LEGO1 0x1005b8b0 MxResult LegoInputManager::Tickle() { ProcessEvents(); @@ -56,10 +60,27 @@ LegoInputManager::~LegoInputManager() // FUNCTION: LEGO1 0x1005b960 MxResult LegoInputManager::Create(HWND p_hwnd) { - // TODO - if (m_eventQueue == NULL) - m_eventQueue = new LegoEventQueue(); - return SUCCESS; + MxResult result = SUCCESS; + + m_controlManager = new LegoControlManager; + + if (!m_keyboardNotifyList) { + m_keyboardNotifyList = new LegoNotifyList; + } + + if (!m_eventQueue) { + m_eventQueue = new LegoEventQueue; + } + + CreateAndAcquireKeyboard(p_hwnd); + GetJoystickId(); + + if (!m_keyboardNotifyList || !m_eventQueue || !m_directInputDevice) { + Destroy(); + result = FAILURE; + } + + return result; } // FUNCTION: LEGO1 0x1005bfe0 @@ -67,16 +88,19 @@ void LegoInputManager::Destroy() { ReleaseDX(); - if (m_unk0x5c) - delete m_unk0x5c; - m_unk0x5c = NULL; + if (m_keyboardNotifyList) { + delete m_keyboardNotifyList; + } + m_keyboardNotifyList = NULL; - if (m_eventQueue) + if (m_eventQueue) { delete m_eventQueue; + } m_eventQueue = NULL; - if (m_controlManager) + if (m_controlManager) { delete m_controlManager; + } } // FUNCTION: LEGO1 0x1005c030 @@ -164,8 +188,9 @@ MxResult LegoInputManager::GetJoystickState( if ((capabilities & JOYCAPS_HASPOV) != 0) { joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS; - if ((capabilities & JOYCAPS_POVCTS) != 0) + if ((capabilities & JOYCAPS_POVCTS) != 0) { joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS | JOY_RETURNPOVCTS; + } } MMRESULT mmresult = joyGetPosEx(m_joyid, &joyinfoex); @@ -195,16 +220,26 @@ MxResult LegoInputManager::GetJoystickState( return FAILURE; } -// STUB: LEGO1 0x1005c470 -void LegoInputManager::Register(MxCore*) +// FUNCTION: LEGO1 0x1005c470 +void LegoInputManager::Register(MxCore* p_notify) { - // TODO + MxAutoLocker lock(&m_criticalSection); + + LegoNotifyListCursor cursor(m_keyboardNotifyList); + if (!cursor.Find(p_notify)) { + m_keyboardNotifyList->Append(p_notify); + } } -// STUB: LEGO1 0x1005c5c0 -void LegoInputManager::UnRegister(MxCore*) +// FUNCTION: LEGO1 0x1005c5c0 +void LegoInputManager::UnRegister(MxCore* p_notify) { - // TODO + MxAutoLocker lock(&m_criticalSection); + + LegoNotifyListCursor cursor(m_keyboardNotifyList); + if (cursor.Find(p_notify)) { + cursor.Detach(); + } } // FUNCTION: LEGO1 0x1005c700 @@ -249,32 +284,149 @@ void LegoInputManager::ProcessEvents() LegoEventNotificationParam event; while (m_eventQueue->Dequeue(event)) { - if (ProcessOneEvent(event)) + if (ProcessOneEvent(event)) { break; + } } } -// STUB: LEGO1 0x1005c9c0 +// FUNCTION: LEGO1 0x1005c9c0 MxBool LegoInputManager::ProcessOneEvent(LegoEventNotificationParam& p_param) +{ + MxBool processRoi; + + if (p_param.GetType() == c_notificationKeyPress) { + if (!Lego()->IsTimerRunning() || p_param.GetKey() == 0x13) { + if (p_param.GetKey() == 0x10) { + if (m_unk0x195) { + m_unk0x80 = 0; + p_param.SetType(c_notificationDrag); + + if (m_camera) { + m_camera->Notify(p_param); + } + } + + m_unk0x195 = !m_unk0x195; + return TRUE; + } + + LegoNotifyListCursor cursor(m_keyboardNotifyList); + MxCore* target; + + while (cursor.Next(target)) { + if (target->Notify(p_param) != 0) { + return TRUE; + } + } + } + } + else { + if (!Lego()->IsTimerRunning()) { + processRoi = TRUE; + + if (m_unk0x335 != 0) { + if (p_param.GetType() == c_notificationButtonDown) { + LegoEventNotificationParam notification(c_notificationKeyPress, NULL, 0, 0, 0, ' '); + LegoNotifyListCursor cursor(m_keyboardNotifyList); + MxCore* target; + + while (cursor.Next(target)) { + if (target->Notify(notification) != 0) { + return TRUE; + } + } + } + + return TRUE; + } + + if (m_unk0x195 && p_param.GetType() == c_notificationButtonDown) { + m_unk0x195 = 0; + return TRUE; + } + + if (m_world != NULL && m_world->Notify(p_param) != 0) { + return TRUE; + } + + if (p_param.GetType() == c_notificationButtonDown) { + MxPresenter* presenter = VideoManager()->GetPresenterAt(p_param.GetX(), p_param.GetY()); + + if (presenter) { + if (presenter->GetDisplayZ() < 0) { + processRoi = FALSE; + + if (m_controlManager->FUN_10029210(p_param, presenter)) { + return TRUE; + } + } + else { + LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY()); + + if (roi == NULL && m_controlManager->FUN_10029210(p_param, presenter)) { + return TRUE; + } + } + } + } + else if (p_param.GetType() == c_notificationButtonUp) { + if (g_unk0x100f31b0 != -1 || m_controlManager->GetUnknown0x10() || + m_controlManager->GetUnknown0x0c() == 1) { + MxBool result = m_controlManager->FUN_10029210(p_param, NULL); + StopAutoDragTimer(); + + m_unk0x80 = 0; + m_unk0x81 = 0; + return result; + } + } + + if (FUN_1005cdf0(p_param)) { + if (processRoi && p_param.GetType() == c_notificationType11) { + LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY()); + p_param.SetROI(roi); + + if (roi && roi->GetUnknown0x0c() == 1) { + for (OrientableROI* oroi = roi->GetUnknown0xd4(); oroi; oroi = oroi->GetUnknown0xd4()) { + roi = (LegoROI*) oroi; + } + + LegoEntity* entity = roi->GetUnknown0x104(); + if (entity && entity->Notify(p_param) != 0) { + return TRUE; + } + } + } + + if (m_camera && m_camera->Notify(p_param) != 0) { + return TRUE; + } + } + } + } + + return FALSE; +} + +// STUB: LEGO1 0x1005cdf0 +MxBool LegoInputManager::FUN_1005cdf0(LegoEventNotificationParam& p_param) { // TODO return FALSE; } // FUNCTION: LEGO1 0x1005cfb0 -void LegoInputManager::SetTimer() +void LegoInputManager::StartAutoDragTimer() { - LegoOmni* omni = LegoOmni::GetInstance(); - UINT timer = ::SetTimer(omni->GetWindowHandle(), 1, m_timeout, NULL); - m_timer = timer; + m_autoDragTimerID = ::SetTimer(LegoOmni::GetInstance()->GetWindowHandle(), 1, m_autoDragTime, NULL); } // FUNCTION: LEGO1 0x1005cfd0 -void LegoInputManager::KillTimer() +void LegoInputManager::StopAutoDragTimer() { - if (m_timer != 0) { - LegoOmni* omni = LegoOmni::GetInstance(); - ::KillTimer(omni->GetWindowHandle(), m_timer); + if (m_autoDragTimerID) { + ::KillTimer(LegoOmni::GetInstance()->GetWindowHandle(), m_autoDragTimerID); } } @@ -283,5 +435,5 @@ void LegoInputManager::EnableInputProcessing() { m_unk0x88 = FALSE; g_unk0x100f31b0 = -1; - g_unk0x100f31b4 = 0; + g_unk0x100f31b4 = NULL; } diff --git a/LEGO1/lego/legoomni/src/isle/bike.cpp b/LEGO1/lego/legoomni/src/isle/bike.cpp index 1c71b299..484cef9b 100644 --- a/LEGO1/lego/legoomni/src/isle/bike.cpp +++ b/LEGO1/lego/legoomni/src/isle/bike.cpp @@ -1,5 +1,11 @@ #include "bike.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoomni.h" +#include "legoutil.h" +#include "legoworld.h" + DECOMP_SIZE_ASSERT(Bike, 0x164); // FUNCTION: LEGO1 0x10076670 @@ -10,17 +16,30 @@ Bike::Bike() this->m_unk0x148 = 1; } -// STUB: LEGO1 0x100768f0 +// FUNCTION: LEGO1 0x100768f0 MxResult Bike::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = IslePathActor::Create(p_dsAction); + m_world = CurrentWorld(); + + if (m_world) { + m_world->Add(this); + } + + return result; } -// STUB: LEGO1 0x10076920 +// FUNCTION: LEGO1 0x10076920 void Bike::VTable0xe4() { - // TODO + IslePathActor::VTable0xe4(); + GameState()->SetCurrentArea(LegoGameState::Area::e_unk57); + FUN_1003ee00(*g_isleScript, 11); + FUN_1003ee00(*g_isleScript, 12); + FUN_1003ee00(*g_isleScript, 15); + FUN_1003ee00(*g_isleScript, 14); + FUN_1003ee00(*g_isleScript, 13); + ControlManager()->Unregister(this); } // STUB: LEGO1 0x100769a0 @@ -31,7 +50,7 @@ MxU32 Bike::VTable0xcc() } // STUB: LEGO1 0x10076aa0 -MxU32 Bike::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 Bike::VTable0xd4(LegoControlManagerEvent& p_param) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/isle/historybook.cpp b/LEGO1/lego/legoomni/src/isle/historybook.cpp index f5a970b3..981d3018 100644 --- a/LEGO1/lego/legoomni/src/isle/historybook.cpp +++ b/LEGO1/lego/legoomni/src/isle/historybook.cpp @@ -1,9 +1,22 @@ #include "historybook.h" -// STUB: LEGO1 0x100822f0 +#include "jukebox.h" +#include "legocontrolmanager.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "mxnotificationmanager.h" +#include "mxomni.h" +#include "mxtransitionmanager.h" + +DECOMP_SIZE_ASSERT(HistoryBook, 0x3e4) + +// FUNCTION: LEGO1 0x100822f0 HistoryBook::HistoryBook() { - // TODO + memset(m_alphabet, NULL, sizeof(m_alphabet)); + memset(m_names, NULL, sizeof(m_names)); + memset(m_scores, NULL, sizeof(m_scores)); + NotificationManager()->Register(this); } // STUB: LEGO1 0x100824d0 @@ -12,30 +25,130 @@ HistoryBook::~HistoryBook() // TODO } -// STUB: LEGO1 0x10082610 +// FUNCTION: LEGO1 0x10082610 MxResult HistoryBook::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + InputManager()->SetCamera(NULL); + InputManager()->Register(this); + + GameState()->SetCurrentArea(LegoGameState::Area::e_histbook); + GameState()->StopArea(LegoGameState::Area::e_previousArea); + return result; } -// STUB: LEGO1 0x10082680 +// FUNCTION: LEGO1 0x10082680 MxLong HistoryBook::Notify(MxParam& p_param) { - // TODO + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationButtonUp: + m_transitionDestination = LegoGameState::Area::e_infoscor; + TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_pixelation, 50, FALSE, FALSE); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_transitionDestination); + break; + } + } return 0; } -// STUB: LEGO1 0x100826f0 -void HistoryBook::VTable0x50() +inline void SetColor(MxStillPresenter* p_presenter, MxU8 p_color, MxU8* p_colors, MxS32 p_x, MxS32 p_y) { - // TODO + if (p_color) { + for (MxS32 lax = 0; lax < 4; lax++) { + if (p_presenter->GetAlphaMask() != NULL) { + memset(NULL, p_colors[p_color - 1], 4); + } + else { + memset(p_presenter->GetBitmap()->GetStart(p_x, p_y + lax), p_colors[p_color - 1], 4); + } + } + } } -// STUB: LEGO1 0x10082a10 +// FUNCTION: LEGO1 0x100826f0 +void HistoryBook::ReadyWorld() +{ + LegoWorld::ReadyWorld(); + GameState()->GetScores()->WriteScoreHistory(); + + char bitmap[] = "A_Bitmap"; + for (MxS16 i = 0; i < 26; i++) { + m_alphabet[i] = (MxStillPresenter*) Find("MxStillPresenter", bitmap); + bitmap[0]++; + } + + MxStillPresenter* scoreboxMaster = (MxStillPresenter*) Find("MxStillPresenter", "ScoreBox"); + MxU8 scoreColors[3] = + {0x76, 0x4c, 0x38}; // yellow - #FFB900, blue - #00548C, red - #CB1220, background - #CECECE, border - #74818B + MxS32 scoreY = 0x79; + + for (MxS16 scoreIndex = 0; scoreIndex < GameState()->GetScores()->m_count; scoreIndex++) { + LegoGameState::ScoreItem* score = GameState()->GetScores()->GetScore(scoreIndex); + + MxStillPresenter** scorebox = &m_scores[scoreIndex]; + *scorebox = scoreboxMaster->Clone(); + + MxS32 scoreX = 0x90; + if (scoreIndex >= 10) { + if (scoreIndex == 10) { + scoreY = 0x79; + } + + scoreX = 0x158; + } + + MxS32 scoreboxX = 1; + MxS32 scoreboxRow = 5; + MxU8* scoreState = score->m_state; + + for (; scoreboxRow > 0; scoreboxRow--) { + for (MxS32 scoreBoxColumn = 0, scoreboxY = 1; scoreBoxColumn < 5; scoreBoxColumn++, scoreboxY += 5) { + SetColor(*scorebox, scoreState[scoreBoxColumn], scoreColors, scoreboxX, scoreboxY); + } + + scoreState += 5; + scoreboxX += 5; + } + + (*scorebox)->Enable(TRUE); + (*scorebox)->SetTickleState(MxPresenter::e_repeating); + (*scorebox)->SetPosition(scoreX + 0xa1, scoreY); + + for (MxS16 letterIndex = 0; letterIndex < (MxS16) _countof(m_names[0]);) { + MxS16 letter = score->m_name.m_letters[letterIndex]; + + if (letter == -1) { + break; + } + + MxS16 nameIndex = letterIndex++; + m_names[scoreIndex][nameIndex] = m_alphabet[letter]->Clone(); + m_names[scoreIndex][nameIndex]->Enable(TRUE); + m_names[scoreIndex][nameIndex]->SetTickleState(MxPresenter::e_repeating); + m_names[scoreIndex][nameIndex]->SetPosition(scoreX, scoreY); + scoreX += 0x17; + } + + scoreY += 0x1b; + } + + PlayMusic(JukeBox::e_informationCenter); +} + +// FUNCTION: LEGO1 0x10082a10 MxBool HistoryBook::VTable0x64() { - // TODO - return FALSE; + m_transitionDestination = LegoGameState::Area::e_infomain; + return TRUE; } diff --git a/LEGO1/lego/legoomni/src/isle/isle.cpp b/LEGO1/lego/legoomni/src/isle/isle.cpp index 7172a7a6..1f2085c2 100644 --- a/LEGO1/lego/legoomni/src/isle/isle.cpp +++ b/LEGO1/lego/legoomni/src/isle/isle.cpp @@ -46,8 +46,8 @@ Isle::~Isle() InputManager()->ClearWorld(); } - if (GetCurrentVehicle() != NULL) { - VTable0x6c(GetCurrentVehicle()); + if (CurrentVehicle() != NULL) { + VTable0x6c(CurrentVehicle()); } NotificationManager()->Unregister(this); @@ -56,27 +56,27 @@ Isle::~Isle() // FUNCTION: LEGO1 0x10030b20 MxResult Isle::Create(MxDSAction& p_dsAction) { - GameState()->FUN_1003ceb0(); + GameState()->FindLoadedAct(); MxResult result = LegoWorld::Create(p_dsAction); if (result == SUCCESS) { ControlManager()->Register(this); InputManager()->SetWorld(this); - GameState()->FUN_1003a720(0); + GameState()->StopArea(LegoGameState::e_previousArea); - switch (GameState()->GetCurrentAct()) { - case 1: - GameState()->FUN_1003a720(0x2e); + switch (GameState()->GetLoadedAct()) { + case LegoGameState::e_act2: + GameState()->StopArea(LegoGameState::e_act2main); break; - case 2: - GameState()->FUN_1003a720(0x2e); + case LegoGameState::e_act3: + GameState()->StopArea(LegoGameState::e_act2main); // Looks like a bug break; - case -1: + case LegoGameState::e_actNotFound: m_unk0x13c = 2; } - if (GameState()->GetUnknown424() == 1) { - GameState()->SetUnknown424(0); + if (GameState()->GetCurrentArea() == LegoGameState::e_isle) { + GameState()->SetCurrentArea(LegoGameState::e_noArea); } LegoGameState* gameState = GameState(); @@ -115,13 +115,13 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case c_notificationType17: + case c_notificationClick: result = HandleType17Notification(p_param); break; case c_notificationType18: switch (m_act1state->GetUnknown18()) { case 4: - result = GetCurrentVehicle()->Notify(p_param); + result = CurrentVehicle()->Notify(p_param); break; case 8: result = m_towtrack->Notify(p_param); @@ -135,7 +135,7 @@ MxLong Isle::Notify(MxParam& p_param) result = HandleType19Notification(p_param); break; case c_notificationType20: - VTable0x68(TRUE); + Enable(TRUE); break; case c_notificationTransitioned: result = HandleTransitionEnd(); @@ -153,16 +153,16 @@ MxLong Isle::StopAction(MxParam& p_param) } // FUNCTION: LEGO1 0x10030fc0 -void Isle::VTable0x50() +void Isle::ReadyWorld() { - LegoWorld::VTable0x50(); + LegoWorld::ReadyWorld(); if (m_act1state->GetUnknown21()) { - GameState()->HandleAction(2); + GameState()->SwitchArea(LegoGameState::e_infomain); m_act1state->SetUnknown18(0); m_act1state->SetUnknown21(0); } - else if (GameState()->GetCurrentAct()) { + else if (GameState()->GetLoadedAct()) { FUN_1003ef00(TRUE); FUN_10032620(); m_act1state->FUN_10034d00(); @@ -183,9 +183,23 @@ MxLong Isle::HandleType19Notification(MxParam& p_param) } // STUB: LEGO1 0x10031820 -void Isle::VTable0x68(MxBool p_add) +void Isle::Enable(MxBool p_enable) { - // TODO + if (m_set0xd0.empty() == p_enable) { + return; + } + + LegoWorld::Enable(p_enable); + m_radio.Initialize(p_enable); + + if (p_enable) { + // TODO + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } } // STUB: LEGO1 0x10032620 @@ -201,9 +215,9 @@ MxLong Isle::HandleTransitionEnd() } // FUNCTION: LEGO1 0x10032f10 -void Isle::VTable0x58(MxCore* p_object) +void Isle::Add(MxCore* p_object) { - LegoWorld::VTable0x58(p_object); + LegoWorld::Add(p_object); if (p_object->IsA("Pizza")) { m_pizza = (Pizza*) p_object; @@ -246,7 +260,7 @@ void Isle::VTable0x58(MxCore* p_object) // FUNCTION: LEGO1 0x10033050 void Isle::VTable0x6c(IslePathActor* p_actor) { - LegoWorld::EndAction(p_actor); + LegoWorld::Remove(p_actor); if (p_actor->IsA("Helicopter")) { m_helicopter = NULL; diff --git a/LEGO1/lego/legoomni/src/isle/islepathactor.cpp b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp index b93535f6..55ef5b71 100644 --- a/LEGO1/lego/legoomni/src/isle/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp @@ -20,8 +20,9 @@ MxResult IslePathActor::Create(MxDSAction& p_dsAction) // FUNCTION: LEGO1 0x1001a2a0 void IslePathActor::Destroy(MxBool p_fromDestructor) { - if (!p_fromDestructor) + if (!p_fromDestructor) { LegoPathActor::Destroy(FALSE); + } } // STUB: LEGO1 0x1001a2c0 diff --git a/LEGO1/lego/legoomni/src/isle/jukebox.cpp b/LEGO1/lego/legoomni/src/isle/jukebox.cpp index 687c0a79..73b03ab0 100644 --- a/LEGO1/lego/legoomni/src/isle/jukebox.cpp +++ b/LEGO1/lego/legoomni/src/isle/jukebox.cpp @@ -13,11 +13,10 @@ JukeBox::JukeBox() NotificationManager()->Register(this); } -// STUB: LEGO1 0x1005d6e0 +// FUNCTION: LEGO1 0x1005d6e0 MxBool JukeBox::VTable0x5c() { - // TODO - return FALSE; + return TRUE; } // STUB: LEGO1 0x1005d8d0 @@ -35,13 +34,13 @@ MxLong JukeBox::Notify(MxParam& p_param) } // STUB: LEGO1 0x1005d9f0 -void JukeBox::VTable0x50() +void JukeBox::ReadyWorld() { // TODO } // STUB: LEGO1 0x1005dde0 -void JukeBox::VTable0x68(MxBool p_add) +void JukeBox::Enable(MxBool p_enable) { // TODO } diff --git a/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp b/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp index 026772c0..47d81510 100644 --- a/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp +++ b/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp @@ -1,20 +1,125 @@ #include "jukeboxentity.h" -// STUB: LEGO1 0x10085bc0 +#include "isle.h" +#include "islepathactor.h" +#include "jukeboxstate.h" +#include "legogamestate.h" +#include "legoutil.h" +#include "mxbackgroundaudiomanager.h" +#include "mxnotificationmanager.h" +#include "mxtransitionmanager.h" + +// FUNCTION: LEGO1 0x10085bc0 JukeBoxEntity::JukeBoxEntity() { - // TODO + NotificationManager()->Register(this); } -// STUB: LEGO1 0x10085dd0 +// FUNCTION: LEGO1 0x10085dd0 JukeBoxEntity::~JukeBoxEntity() { - // TODO + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x10085e40 +// FUNCTION: LEGO1 0x10085e40 MxLong JukeBoxEntity::Notify(MxParam& p_param) { - // TODO + if (((MxNotificationParam&) p_param).GetType() == c_notificationType11) { + if (!FUN_1003ef60()) { + return 1; + } + + if (CurrentVehicle()->VTable0x60() != GameState()->GetUnknownC()) { + CurrentVehicle()->VTable0xe4(); + } + + ((Isle*) FindWorld(*g_isleScript, 0))->SetUnknown13c(0x35); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + return 1; + } + return 0; } + +// FUNCTION: LEGO1 0x10085ed0 +void JukeBoxEntity::StartAction() +{ + MxDSAction action; + BackgroundAudioManager()->Stop(); + JukeBoxState* state = (JukeBoxState*) GameState()->GetState("JukeBoxState"); + state->SetActive(TRUE); + + switch (state->GetState()) { + case 0: + InvokeAction(Extra::e_start, *g_isleScript, 0x319, NULL); + GameState()->SetUnknown0x41c(0x37); + break; + case 1: + InvokeAction(Extra::e_start, *g_isleScript, 0x31e, NULL); + GameState()->SetUnknown0x41c(0x38); + break; + case 2: + InvokeAction(Extra::e_start, *g_isleScript, 0x31b, NULL); + GameState()->SetUnknown0x41c(0x39); + break; + case 3: + InvokeAction(Extra::e_start, *g_isleScript, 0x31a, NULL); + GameState()->SetUnknown0x41c(0x3a); + break; + case 4: + InvokeAction(Extra::e_start, *g_isleScript, 0x31f, NULL); + GameState()->SetUnknown0x41c(0x3b); + break; + case 5: + InvokeAction(Extra::e_start, *g_isleScript, 0x31c, NULL); + GameState()->SetUnknown0x41c(0x3c); + break; + } + + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(GameState()->GetUnknown0x41c()); + + m_audioEnabled = BackgroundAudioManager()->GetEnabled(); + if (!m_audioEnabled) { + BackgroundAudioManager()->Enable(TRUE); + } + + BackgroundAudioManager()->PlayMusic(action, 5, 4); +} + +// FUNCTION: LEGO1 0x100860f0 +void JukeBoxEntity::StopAction(MxU32 p_state) +{ + JukeBoxState* state = (JukeBoxState*) GameState()->GetState("JukeBoxState"); + + if (state && state->IsActive()) { + switch (p_state) { + case 0x37: + state->SetActive(FALSE); + InvokeAction(Extra::e_stop, *g_isleScript, 0x319, NULL); + break; + case 0x38: + state->SetActive(FALSE); + InvokeAction(Extra::e_stop, *g_isleScript, 0x31e, NULL); + break; + case 0x39: + state->SetActive(FALSE); + InvokeAction(Extra::e_stop, *g_isleScript, 0x31b, NULL); + break; + case 0x3a: + state->SetActive(FALSE); + InvokeAction(Extra::e_stop, *g_isleScript, 0x31a, NULL); + break; + case 0x3b: + state->SetActive(FALSE); + InvokeAction(Extra::e_stop, *g_isleScript, 0x31f, NULL); + break; + case 0x3c: + state->SetActive(FALSE); + InvokeAction(Extra::e_stop, *g_isleScript, 0x31c, NULL); + break; + } + + BackgroundAudioManager()->Enable(IsBackgroundAudioEnabled()); + } +} diff --git a/LEGO1/lego/legoomni/src/isle/motocycle.cpp b/LEGO1/lego/legoomni/src/isle/motocycle.cpp index c54bd841..0f4424f9 100644 --- a/LEGO1/lego/legoomni/src/isle/motocycle.cpp +++ b/LEGO1/lego/legoomni/src/isle/motocycle.cpp @@ -38,7 +38,7 @@ MxU32 Motocycle::VTable0xcc() } // STUB: LEGO1 0x10035d70 -MxU32 Motocycle::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 Motocycle::VTable0xd4(LegoControlManagerEvent& p_param) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/isle/radio.cpp b/LEGO1/lego/legoomni/src/isle/radio.cpp index c87ac04e..c0a4e44d 100644 --- a/LEGO1/lego/legoomni/src/isle/radio.cpp +++ b/LEGO1/lego/legoomni/src/isle/radio.cpp @@ -3,6 +3,8 @@ #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoomni.h" +#include "mxbackgroundaudiomanager.h" +#include "mxcontrolpresenter.h" #include "mxnotificationmanager.h" DECOMP_SIZE_ASSERT(Radio, 0x10); @@ -13,23 +15,136 @@ Radio::Radio() NotificationManager()->Register(this); ControlManager()->Register(this); - m_unk0xc = TRUE; + m_unk0x0c = TRUE; CreateRadioState(); } -// STUB: LEGO1 0x1002c990 +// FUNCTION: LEGO1 0x1002c990 Radio::~Radio() { - // TODO + if (m_state->IsActive()) { + BackgroundAudioManager()->Stop(); + m_state->SetActive(FALSE); + } + + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x1002ca30 +// FUNCTION: LEGO1 0x1002ca30 MxLong Radio::Notify(MxParam& p_param) { - // TODO + MxLong result = 0; + + if (m_unk0x0c) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) p_param); + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x1002ca70 +void Radio::Play() +{ + if (!m_state->IsActive()) { + CurrentWorld(); + + MxDSAction action; + action.SetObjectId(m_state->FUN_1002d090()); + action.SetAtomId(*g_jukeboxScript); + action.SetLoopCount(1); + + m_audioEnabled = BackgroundAudioManager()->GetEnabled(); + if (!m_audioEnabled) { + BackgroundAudioManager()->Enable(TRUE); + } + + BackgroundAudioManager()->PlayMusic(action, 3, 4); + m_state->SetActive(TRUE); + } +} + +// FUNCTION: LEGO1 0x1002cb70 +void Radio::Stop() +{ + if (m_state->IsActive()) { + LegoWorld* world = CurrentWorld(); + + MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtom(), 18); + + if (presenter) { + presenter->VTable0x6c(0); + } + + BackgroundAudioManager()->Stop(); + BackgroundAudioManager()->Enable(m_audioEnabled); + m_state->SetActive(FALSE); + } +} + +// FUNCTION: LEGO1 0x1002cbc0 +MxLong Radio::HandleClick(LegoControlManagerEvent& p_param) +{ + MxDSAction action; // Unused + MxS32 objectId = p_param.GetClickedObjectId(); + + if (objectId == 18) { + if (m_state->IsActive()) { + Stop(); + } + else { + Play(); + } + + if (CurrentWorld()) { +#ifdef COMPAT_MODE + MxNotificationParam param(c_notificationEndAction, this); + CurrentWorld()->Notify(param); +#else + CurrentWorld()->Notify(MxNotificationParam(c_notificationType0, this)); +#endif + } + + return 1; + } + return 0; } +// FUNCTION: LEGO1 0x1002ccc0 +MxLong Radio::HandleEndAction(MxEndActionNotificationParam& p_param) +{ + if (m_state->IsActive() && + m_state->FUN_1002d0c0(p_param.GetAction()->GetAtomId(), p_param.GetAction()->GetObjectId())) { + + MxDSAction action; + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(m_state->FUN_1002d090()); + action.SetLoopCount(1); + + BackgroundAudioManager()->PlayMusic(action, 3, 4); + return 1; + } + + return 0; +} + +// FUNCTION: LEGO1 0x1002cdc0 +void Radio::Initialize(MxBool p_und) +{ + if (m_unk0x0c != p_und) { + m_unk0x0c = p_und; + CreateRadioState(); + } +} + // FUNCTION: LEGO1 0x1002cde0 void Radio::CreateRadioState() { diff --git a/LEGO1/lego/legoomni/src/isle/radiostate.cpp b/LEGO1/lego/legoomni/src/isle/radiostate.cpp index 08aa91fa..077864a7 100644 --- a/LEGO1/lego/legoomni/src/isle/radiostate.cpp +++ b/LEGO1/lego/legoomni/src/isle/radiostate.cpp @@ -1,14 +1,99 @@ #include "radiostate.h" -// STUB: LEGO1 0x1002ce10 +#include "jukebox.h" +#include "legoomni.h" +#include "mxtimer.h" + +// GLOBAL: LEGO1 0x100f3218 +JukeBox::JukeBoxScript g_unk0x100f3218[6] = { + JukeBox::e_legoRadioReminder1, + JukeBox::e_legoRadioJingle1, + JukeBox::e_legoRadioJingle2, + JukeBox::e_legoRadioJingle3, + JukeBox::e_legoRadioJingle4, + JukeBox::e_legoRadioReminder2 +}; + +// GLOBAL: LEGO1 0x100f3230 +JukeBox::JukeBoxScript g_unk0x100f3230[14] = { + JukeBox::e_legoRadioRacingAd, + JukeBox::e_legoRadioNews1, + JukeBox::e_legoRadioNews2, + JukeBox::e_legoRadioPizzaAd1, + JukeBox::e_legoRadioBricksterPSA, + JukeBox::e_legoRadioSports1, + JukeBox::e_legoRadioIntermission1, + JukeBox::e_legoRadioIntermission2, + JukeBox::e_legoRadioPizzaAd2, + JukeBox::e_legoRadioWeatherReport, + JukeBox::e_legoRadioSports2, + JukeBox::e_legoRadioPizzaAd3, + JukeBox::e_legoRadioIntermission3, + JukeBox::e_legoRadioSuperStoreAd, +}; + +// GLOBAL: LEGO1 0x100f3268 +JukeBox::JukeBoxScript g_unk0x100f3268[9] = { + JukeBox::e_centralRoads, + JukeBox::e_beachBlvd, + JukeBox::e_residentialArea, + JukeBox::e_legoRadioLuckyYou, + JukeBox::e_legoRadioJazzInterlude, + JukeBox::e_legoRadioPianoInterlude1, + JukeBox::e_legoRadioPoliceStation, + JukeBox::e_legoRadioPianoInterlude2, + JukeBox::e_legoRadioCredits, +}; + +// FUNCTION: LEGO1 0x1002ce10 RadioState::RadioState() { - // TODO + srand(Timer()->GetTime()); + + MxS32 random = rand(); + m_unk0x2c = random % 3; + + m_unk0x08[0] = LegoState::Playlist((MxU32*) g_unk0x100f3218, sizeof(g_unk0x100f3218) / sizeof(g_unk0x100f3218[0])); + m_unk0x08[0].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3218) / sizeof(g_unk0x100f3218[0]))); + + m_unk0x08[1] = LegoState::Playlist((MxU32*) g_unk0x100f3230, sizeof(g_unk0x100f3230) / sizeof(g_unk0x100f3230[0])); + m_unk0x08[1].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3230) / sizeof(g_unk0x100f3230[0]))); + + m_unk0x08[2] = LegoState::Playlist((MxU32*) g_unk0x100f3268, sizeof(g_unk0x100f3268) / sizeof(g_unk0x100f3268[0])); + m_unk0x08[2].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3268) / sizeof(g_unk0x100f3268[0]))); + + m_active = FALSE; } -// STUB: LEGO1 0x1002cf50 +// FUNCTION: LEGO1 0x1002cf50 MxBool RadioState::VTable0x14() { - // TODO + return FALSE; +} + +// FUNCTION: LEGO1 0x1002d090 +MxU32 RadioState::FUN_1002d090() +{ + if (m_unk0x2c == 2) { + m_unk0x2c = 0; + } + else { + m_unk0x2c++; + } + + return m_unk0x08[m_unk0x2c].Next(); +} + +// FUNCTION: LEGO1 0x1002d0c0 +MxBool RadioState::FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId) +{ + if (*g_jukeboxScript == p_atom) { + for (MxS16 i = 0; i < 3; i++) { + if (m_unk0x08[i].Contains(p_objectId)) { + return TRUE; + } + } + } + return FALSE; } diff --git a/LEGO1/lego/legoomni/src/isle/skateboard.cpp b/LEGO1/lego/legoomni/src/isle/skateboard.cpp index 2863ec40..22998f85 100644 --- a/LEGO1/lego/legoomni/src/isle/skateboard.cpp +++ b/LEGO1/lego/legoomni/src/isle/skateboard.cpp @@ -1,4 +1,4 @@ -#include "SkateBoard.h" +#include "skateboard.h" #include "decomp.h" #include "mxnotificationmanager.h" @@ -38,7 +38,7 @@ MxU32 SkateBoard::VTable0xcc() } // STUB: LEGO1 0x10010230 -MxU32 SkateBoard::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 SkateBoard::VTable0xd4(LegoControlManagerEvent& p_param) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/main/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp index a8d06b89..0ea4607d 100644 --- a/LEGO1/lego/legoomni/src/main/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -1,6 +1,5 @@ #include "legoomni.h" -#include "gifmanager.h" #include "legoanimationmanager.h" #include "legobuildingmanager.h" #include "legogamestate.h" @@ -10,20 +9,26 @@ #include "legosoundmanager.h" #include "legounksavedatawriter.h" #include "legoutil.h" +#include "legovariables.h" #include "legovideomanager.h" #include "legoworld.h" #include "legoworldlist.h" +#include "misc/legocontainer.h" #include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxbackgroundaudiomanager.h" #include "mxdsfile.h" #include "mxomnicreateflags.h" #include "mxomnicreateparam.h" +#include "mxstreamer.h" #include "mxticklemanager.h" #include "mxtransitionmanager.h" +#include "viewmanager/viewmanager.h" -DECOMP_SIZE_ASSERT(LegoWorldList, 0x18); -DECOMP_SIZE_ASSERT(LegoWorldListCursor, 0x10); +DECOMP_SIZE_ASSERT(LegoOmni::ScriptContainer, 0x1c) +DECOMP_SIZE_ASSERT(LegoOmni::PathContainer, 0x38) +DECOMP_SIZE_ASSERT(LegoWorldList, 0x18) +DECOMP_SIZE_ASSERT(LegoWorldListCursor, 0x10) // GLOBAL: LEGO1 0x100f451c MxAtomId* g_copterScript = NULL; @@ -116,6 +121,9 @@ const char* g_current = "current"; // GLOBAL: LEGO1 0x100f4c58 MxBool g_isWorldActive = TRUE; +// GLOBAL: LEGO1 0x10102b28 +LegoOmni::PathContainer g_extraPaths[29]; + // FUNCTION: LEGO1 0x10015700 LegoOmni* Lego() { @@ -171,23 +179,29 @@ LegoNavController* NavController() } // FUNCTION: LEGO1 0x10015790 -IslePathActor* GetCurrentVehicle() +IslePathActor* CurrentVehicle() { return LegoOmni::GetInstance()->GetCurrentVehicle(); } // FUNCTION: LEGO1 0x100157a0 -LegoWorld* GetCurrentWorld() +LegoWorld* CurrentWorld() { - return LegoOmni::GetInstance()->GetCurrentOmniWorld(); + return LegoOmni::GetInstance()->GetCurrentWorld(); } // FUNCTION: LEGO1 0x100157b0 -LegoUnkSaveDataWriter* GetUnkSaveDataWriter() +LegoUnkSaveDataWriter* UnkSaveDataWriter() { return LegoOmni::GetInstance()->GetUnkSaveDataWriter(); } +// FUNCTION: LEGO1 0x100157c0 +ViewManager* GetViewManager() +{ + return VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager(); +} + // FUNCTION: LEGO1 0x100157e0 LegoPlantManager* PlantManager() { @@ -201,9 +215,9 @@ LegoBuildingManager* BuildingManager() } // FUNCTION: LEGO1 0x10015800 -GifManager* GetGifManager() +LegoTextureContainer* TextureContainer() { - return LegoOmni::GetInstance()->GetGifManager(); + return LegoOmni::GetInstance()->GetTextureContainer(); } // FUNCTION: LEGO1 0x10015820 @@ -212,16 +226,26 @@ void FUN_10015820(MxBool p_disable, MxU16 p_flags) LegoOmni::GetInstance()->FUN_1005b4f0(p_disable, p_flags); } -// STUB: LEGO1 0x10015860 -void FUN_10015860(const char*, MxU8) +// FUNCTION: LEGO1 0x10015840 +LegoROI* FindROI(const char* p_name) { - // TODO + return LegoOmni::GetInstance()->FindROI(p_name); +} + +// FUNCTION: LEGO1 0x10015860 +void SetROIUnknown0x0c(const char* p_name, undefined p_unk0x0c) +{ + LegoROI* roi = FindROI(p_name); + + if (roi) { + roi->SetUnknown0x0c(p_unk0x0c); + } } // FUNCTION: LEGO1 0x100158c0 -LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid) +LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) { - return LegoOmni::GetInstance()->FindByEntityIdOrAtomId(p_atom, p_entityid); + return LegoOmni::GetInstance()->FindWorld(p_atom, p_entityid); } // FUNCTION: LEGO1 0x100158e0 @@ -233,7 +257,7 @@ MxDSAction& GetCurrentAction() // FUNCTION: LEGO1 0x100158f0 void SetCurrentWorld(LegoWorld* p_world) { - LegoOmni::GetInstance()->SetWorld(p_world); + LegoOmni::GetInstance()->SetCurrentWorld(p_world); } // FUNCTION: LEGO1 0x10015900 @@ -256,8 +280,9 @@ void PlayMusic(MxU32 p_index) // FUNCTION: LEGO1 0x100159c0 void SetIsWorldActive(MxBool p_isWorldActive) { - if (!p_isWorldActive) + if (!p_isWorldActive) { LegoOmni::GetInstance()->GetInputManager()->SetCamera(NULL); + } g_isWorldActive = p_isWorldActive; } @@ -275,12 +300,38 @@ void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last) } } -// STUB: LEGO1 0x1001a700 -void FUN_1001a700() +// FUNCTION: LEGO1 0x1001a700 +void RegisterExtraPaths() { - // TODO - - // This function seems to populate an unknown structure, and then calls 0x1001b230 + g_extraPaths[0] = LegoOmni::PathContainer(0x16, g_isleScript, 0, "int35", 2, 0.6, 4, 0.4, 0x2a, 0x12); + g_extraPaths[1] = LegoOmni::PathContainer(0x17, g_isleScript, 0, "edg00_49", 1, 0.43, 2, 0.6, 0x27, 0x12); + g_extraPaths[2] = LegoOmni::PathContainer(0x18, g_isleScript, 0, "edg00_191", 2, 0.5, 0, 0.55, 0x26, 0x12); + g_extraPaths[3] = LegoOmni::PathContainer(0x04, g_isleScript, 0, "int46", 0, 0.5, 2, 0.5, 0x10, 0x0b); + g_extraPaths[4] = LegoOmni::PathContainer(0x10, g_isleScript, 0, "EDG00_46", 0, 0.95, 2, 0.19, 0x17, 0x11); + g_extraPaths[5] = LegoOmni::PathContainer(0x11, g_isleScript, 0, "EDG00_46", 3, 0.625, 2, 0.03, 0x18, 0x11); + g_extraPaths[6] = LegoOmni::PathContainer(0x0f, g_isleScript, 0, "EDG10_63", 0, 0.26, 1, 0.01, 0, -1); + g_extraPaths[7] = LegoOmni::PathContainer(0x13, g_isleScript, 0, "INT15", 5, 0.65, 1, 0.68, 0x33, 0x0e); + g_extraPaths[8] = LegoOmni::PathContainer(0x14, g_isleScript, 0, "INT16", 4, 0.1, 2, 0, 0x34, 0x0e); + g_extraPaths[9] = LegoOmni::PathContainer(0x15, g_isleScript, 0, "INT62", 2, 0.1, 3, 0.7, 0x36, 0x0e); + g_extraPaths[10] = LegoOmni::PathContainer(0x19, g_isleScript, 0, "INT24", 0, 0.55, 2, 0.71, 0x08, 0x0f); + g_extraPaths[11] = LegoOmni::PathContainer(0x1c, g_isleScript, 0, "INT24", 2, 0.73, 4, 0.71, 0x0a, 0x0f); + g_extraPaths[12] = LegoOmni::PathContainer(0x1d, g_isleScript, 0, "INT19", 0, 0.85, 1, 0.28, 0, 0x0a); + g_extraPaths[13] = LegoOmni::PathContainer(0x1f, g_isleScript, 0, "EDG02_28", 3, 0.37, 1, 0.52, 0x0c, 0x0a); + g_extraPaths[14] = LegoOmni::PathContainer(0x20, g_isleScript, 0, "INT33", 0, 0.88, 2, 0.74, 0x22, 0x0c); + g_extraPaths[15] = LegoOmni::PathContainer(0x21, g_isleScript, 0, "EDG02_64", 2, 0.24, 0, 0.84, 0x23, 0x0c); + g_extraPaths[16] = LegoOmni::PathContainer(0x28, g_isleScript, 0, "edg02_51", 2, 0.63, 3, 0.01, 0, -1); + g_extraPaths[17] = LegoOmni::PathContainer(0x29, g_isleScript, 0, "edg02_51", 2, 0.63, 0, 0.4, 0, -1); + g_extraPaths[18] = LegoOmni::PathContainer(0x2b, g_isleScript, 0, "edg02_35", 2, 0.8, 0, 0.2, 0, -1); + g_extraPaths[19] = LegoOmni::PathContainer(0x2c, g_isleScript, 0, "EDG03_01", 2, 0.25, 0, 0.75, 0, -1); + g_extraPaths[20] = LegoOmni::PathContainer(0x2d, g_isleScript, 0, "edg10_70", 3, 0.25, 0, 0.7, 0x44, -1); + g_extraPaths[21] = LegoOmni::PathContainer(0x2a, g_isleScript, 0, "inv_05", 2, 0.75, 0, 0.19, 0, -1); + g_extraPaths[22] = LegoOmni::PathContainer(0x30, g_act3Script, 0, "edg02_51", 2, 0.63, 0, 0.4, 0, -1); + g_extraPaths[23] = LegoOmni::PathContainer(0x31, g_act3Script, 0, "inv_05", 2, 0.75, 0, 0.19, 0, -1); + g_extraPaths[24] = LegoOmni::PathContainer(0x32, g_act2mainScript, 0, "EDG02_51", 0, 0.64, 1, 0.37, 0, -1); + g_extraPaths[25] = LegoOmni::PathContainer(0x33, g_isleScript, 0, "edg02_32", 0, 0.5, 2, 0.5, 0, -1); + g_extraPaths[26] = LegoOmni::PathContainer(0x34, g_isleScript, 0, "edg02_19", 2, 0.5, 0, 0.5, 0, -1); + g_extraPaths[27] = LegoOmni::PathContainer(0x36, g_isleScript, 0, "int36", 0, 0.2, 4, 0.4, 0, -1); + g_extraPaths[28] = LegoOmni::PathContainer(0x37, g_isleScript, 0, "edg02_50", 2, 0.8, 1, 0.3, 0, -1); } // FUNCTION: LEGO1 0x1003dd70 @@ -297,7 +348,7 @@ LegoEntity* PickEntity(MxLong, MxLong) } // FUNCTION: LEGO1 0x100528e0 -void RegisterScripts() +void CreateScripts() { g_copterScript = new MxAtomId("\\lego\\scripts\\build\\copter", e_lowerCase2); g_dunecarScript = new MxAtomId("\\lego\\scripts\\build\\dunecar", e_lowerCase2); @@ -330,7 +381,7 @@ void RegisterScripts() } // FUNCTION: LEGO1 0x100530c0 -void UnregisterScripts() +void DestroyScripts() { delete g_copterScript; delete g_dunecarScript; @@ -414,10 +465,10 @@ LegoOmni::~LegoOmni() void LegoOmni::Init() { MxOmni::Init(); - m_unk0x68 = 0; - m_inputMgr = NULL; + m_scripts = NULL; + m_inputManager = NULL; m_viewLODListManager = NULL; - m_gifManager = NULL; + m_textureContainer = NULL; m_worldList = NULL; m_currentWorld = NULL; m_exit = FALSE; @@ -469,9 +520,9 @@ void LegoOmni::Destroy() m_buildingManager = NULL; } - if (m_gifManager) { - delete m_gifManager; - m_gifManager = NULL; + if (m_textureContainer) { + delete m_textureContainer; + m_textureContainer = NULL; } if (m_viewLODListManager) { @@ -479,14 +530,14 @@ void LegoOmni::Destroy() m_viewLODListManager = NULL; } - if (m_inputMgr) { - delete m_inputMgr; - m_inputMgr = NULL; + if (m_inputManager) { + delete m_inputManager; + m_inputManager = NULL; } - if (m_inputMgr) { - delete m_inputMgr; - m_inputMgr = NULL; + if (m_inputManager) { + delete m_inputManager; + m_inputManager = NULL; } // todo FUN_10046de0 @@ -504,9 +555,9 @@ void LegoOmni::Destroy() } m_action.ClearAtom(); - UnregisterScripts(); + DestroyScripts(); - delete[] m_unk0x68; + delete[] m_scripts; MxOmni::Destroy(); } @@ -522,68 +573,136 @@ MxResult LegoOmni::Create(MxOmniCreateParam& p_param) p_param.CreateFlags().CreateSoundManager(FALSE); p_param.CreateFlags().CreateTickleManager(FALSE); - if (!(m_tickleManager = new MxTickleManager())) - return FAILURE; - - if (MxOmni::Create(p_param) != SUCCESS) - return FAILURE; - - m_objectFactory = new LegoObjectFactory(); - if (m_objectFactory == NULL) - return FAILURE; - - if (m_soundManager = new LegoSoundManager()) { - if (m_soundManager->Create(10, 0) != SUCCESS) { - delete m_soundManager; - m_soundManager = NULL; - return FAILURE; - } + if (!(m_tickleManager = new MxTickleManager())) { + goto done; } - if (m_videoManager = new LegoVideoManager()) { - if (m_videoManager->Create(p_param.GetVideoParam(), 100, 0) != SUCCESS) { - delete m_videoManager; - m_videoManager = NULL; - } + if (MxOmni::Create(p_param) != SUCCESS) { + goto done; } - if (m_inputMgr = new LegoInputManager()) { - if (m_inputMgr->Create(p_param.GetWindowHandle()) != SUCCESS) { - delete m_inputMgr; - m_inputMgr = NULL; - } + if (!(m_objectFactory = new LegoObjectFactory())) { + goto done; + } + + if (!(m_soundManager = new LegoSoundManager()) || m_soundManager->Create(10, 0) != SUCCESS) { + delete m_soundManager; + m_soundManager = NULL; + goto done; + } + + if (!(m_videoManager = new LegoVideoManager()) || + m_videoManager->Create(p_param.GetVideoParam(), 100, 0) != SUCCESS) { + delete m_videoManager; + m_videoManager = NULL; + goto done; + } + + if (!(m_inputManager = new LegoInputManager()) || m_inputManager->Create(p_param.GetWindowHandle()) != SUCCESS) { + delete m_inputManager; + m_inputManager = NULL; + goto done; } m_viewLODListManager = new ViewLODListManager(); - m_gifManager = new GifManager(); - // TODO: there is another class here + m_textureContainer = new LegoTextureContainer(); + m_textureContainer->SetOwnership(FALSE); + // FUN_10046c10 + + m_saveDataWriter = new LegoUnkSaveDataWriter(); m_plantManager = new LegoPlantManager(); m_animationManager = new LegoAnimationManager(); m_buildingManager = new LegoBuildingManager(); m_gameState = new LegoGameState(); m_worldList = new LegoWorldList(TRUE); - if (m_viewLODListManager && m_gifManager && m_worldList && m_plantManager && m_animationManager && - m_buildingManager) { - // TODO: initialize a bunch of MxVariables - RegisterScripts(); - FUN_1001a700(); - // todo: another function call. in legoomni maybe? - m_bkgAudioManager = new MxBackgroundAudioManager(); - if (m_bkgAudioManager != NULL) { - m_transitionManager = new MxTransitionManager(); - if (m_transitionManager != NULL) { - if (m_transitionManager->GetDDrawSurfaceFromVideoManager() == SUCCESS) { - m_notificationManager->Register(this); - SetAppCursor(1); - m_gameState->SetSomeEnumState(0); - return SUCCESS; - } - } - } + if (!m_viewLODListManager || !m_textureContainer || !m_worldList || !m_saveDataWriter || !m_plantManager || + !m_animationManager || !m_buildingManager) { + goto done; } - return FAILURE; + MxVariable* variable; + + if (!(variable = new VisibilityVariable())) { + goto done; + } + m_variableTable->SetVariable(variable); + + if (!(variable = new CameraLocationVariable())) { + goto done; + } + m_variableTable->SetVariable(variable); + + if (!(variable = new CursorVariable())) { + goto done; + } + m_variableTable->SetVariable(variable); + + if (!(variable = new WhoAmIVariable())) { + goto done; + } + m_variableTable->SetVariable(variable); + + CreateScripts(); + RegisterExtraPaths(); + result = RegisterScripts(); + + if (result != SUCCESS) { + goto done; + } + + if (!(m_bkgAudioManager = new MxBackgroundAudioManager())) { + goto done; + } + + if (!(m_transitionManager = new MxTransitionManager())) { + goto done; + } + + if (m_transitionManager->GetDDrawSurfaceFromVideoManager() != SUCCESS) { + goto done; + } + + m_notificationManager->Register(this); + SetAppCursor(1); + m_gameState->SetCurrentAct(LegoGameState::e_act1); + + result = SUCCESS; + +done: + return result; +} + +// FUNCTION: LEGO1 0x1005a5f0 +MxResult LegoOmni::RegisterScripts() +{ + m_scripts = new ScriptContainer[19]; + + if (!m_scripts) { + return FAILURE; + } + + m_scripts[0] = ScriptContainer(); + m_scripts[1] = ScriptContainer(0, "ACT1", g_isleScript); + m_scripts[2] = ScriptContainer(1, "IMAIN", g_infomainScript); + m_scripts[3] = ScriptContainer(2, "ICUBE", g_infoscorScript); + m_scripts[4] = ScriptContainer(3, "IREG", g_regbookScript); + m_scripts[5] = ScriptContainer(4, "IELEV", g_elevbottScript); + m_scripts[6] = ScriptContainer(5, "IISLE", g_infodoorScript); + m_scripts[7] = ScriptContainer(6, "HOSP", g_hospitalScript); + m_scripts[8] = ScriptContainer(7, "POLICE", g_policeScript); + m_scripts[9] = ScriptContainer(8, "GMAIN", g_garageScript); + m_scripts[10] = ScriptContainer(9, "BLDH", g_copterScript); + m_scripts[11] = ScriptContainer(10, "BLDD", g_dunecarScript); + m_scripts[12] = ScriptContainer(11, "BLDJ", g_jetskiScript); + m_scripts[13] = ScriptContainer(12, "BLDR", g_racecarScript); + m_scripts[14] = ScriptContainer(13, "RACC", g_carraceScript); + m_scripts[15] = ScriptContainer(14, "RACJ", g_jetraceScript); + m_scripts[16] = ScriptContainer(15, "ACT2", g_act2mainScript); + m_scripts[17] = ScriptContainer(16, "ACT3", g_act3Script); + m_scripts[18] = ScriptContainer(17, "TEST", g_testScript); + + return SUCCESS; } // FUNCTION: LEGO1 0x1005ac90 @@ -605,65 +724,149 @@ void LegoOmni::AddWorld(LegoWorld* p_world) m_worldList->Append(p_world); } -// STUB: LEGO1 0x1005af10 -void LegoOmni::RemoveWorld(const MxAtomId&, MxLong) +// FUNCTION: LEGO1 0x1005adb0 +void LegoOmni::DeleteWorld(LegoWorld* p_world) { - // TODO + if (m_worldList) { + LegoWorldListCursor cursor(m_worldList); + + if (cursor.Find(p_world)) { + cursor.Detach(); + + if (m_currentWorld == p_world) { + m_currentWorld = NULL; + } + + delete p_world; + } + } +} + +// FUNCTION: LEGO1 0x1005af10 +void LegoOmni::RemoveWorld(const MxAtomId& p_atom, MxLong p_objectId) +{ + if (m_worldList) { + LegoWorldListCursor a(m_worldList); + LegoWorldListCursor b(m_worldList); + LegoWorld* world; + + a.Head(); + while (a.Current(world)) { + b = a; + b.Next(); + + if ((p_objectId == -1 || world->GetEntityId() == p_objectId) && + (!p_atom.GetInternal() || world->GetAtom() == p_atom)) { + a.Detach(); + delete world; + } + + a = b; + } + } } // FUNCTION: LEGO1 0x1005b0c0 -LegoEntity* LegoOmni::FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid) +LegoWorld* LegoOmni::FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) { if (m_worldList) { - LegoWorld* world; LegoWorldListCursor cursor(m_worldList); + LegoWorld* world; while (cursor.Next(world)) { if ((p_entityid == -1 || world->GetEntityId() == p_entityid) && - (!p_atom.GetInternal() || world->GetAtom() == p_atom)) + (!p_atom.GetInternal() || world->GetAtom() == p_atom)) { return world; + } } } return NULL; } -// STUB: LEGO1 0x1005b1d0 +// FUNCTION: LEGO1 0x1005b1d0 void LegoOmni::DeleteObject(MxDSAction& p_dsAction) { - // TODO + if (p_dsAction.GetAtomId().GetInternal() != NULL) { + LegoWorld* world = FindWorld(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()); + if (world) { + DeleteWorld(world); + return; + } + + if (m_currentWorld != NULL) { + MxCore* entity = m_currentWorld->Find(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()); + if (entity) { + m_currentWorld->Remove(entity); + + if (entity->IsA("MxPresenter")) { + Streamer()->FUN_100b98f0(((MxPresenter*) entity)->GetAction()); + ((MxPresenter*) entity)->EndAction(); + } + else { + delete entity; + } + return; + } + } + } + MxOmni::DeleteObject(p_dsAction); +} + +// FUNCTION: LEGO1 0x1005b270 +LegoROI* LegoOmni::FindROI(const char* p_name) +{ + ViewManager* viewManager = GetVideoManager()->Get3DManager()->GetLego3DView()->GetViewManager(); + CompoundObject& unk0x08 = viewManager->GetUnknown0x08(); + + if (p_name != NULL && *p_name != '\0' && unk0x08.size() > 0) { + for (CompoundObject::iterator it = unk0x08.begin(); it != unk0x08.end(); it++) { + LegoROI* roi = (LegoROI*) *it; + const char* name = roi->GetName(); + + if (name != NULL) { + if (!strcmpi(name, p_name)) { + return roi; + } + } + } + } + + return NULL; } // FUNCTION: LEGO1 0x1005b2f0 -MxEntity* LegoOmni::FindWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) +MxEntity* LegoOmni::AddToWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) { - LegoWorld* foundEntity = NULL; + LegoWorld* world = NULL; + if (strcmpi(p_id, g_current)) { - foundEntity = (LegoWorld*) FindByEntityIdOrAtomId(MxAtomId(p_id, e_lowerCase2), p_entityId); + world = FindWorld(MxAtomId(p_id, e_lowerCase2), p_entityId); } else { - foundEntity = this->m_currentWorld; + world = this->m_currentWorld; } - if (foundEntity != NULL) { - foundEntity->VTable0x58(p_presenter); + if (world != NULL) { + world->Add(p_presenter); } - return foundEntity; + return world; } // FUNCTION: LEGO1 0x1005b3a0 void LegoOmni::NotifyCurrentEntity(MxNotificationParam* p_param) { - if (m_currentWorld) + if (m_currentWorld) { NotificationManager()->Send(m_currentWorld, p_param); + } } // FUNCTION: LEGO1 0x1005b3c0 MxBool LegoOmni::DoesEntityExist(MxDSAction& p_dsAction) { if (MxOmni::DoesEntityExist(p_dsAction)) { - if (FindByEntityIdOrAtomId(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()) == NULL) { + if (FindWorld(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()) == NULL) { return TRUE; } } @@ -673,11 +876,23 @@ MxBool LegoOmni::DoesEntityExist(MxDSAction& p_dsAction) // FUNCTION: LEGO1 0x1005b400 MxS32 LegoOmni::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) { - if (GetCurrentWorld() == NULL) { - return -1; + if (::CurrentWorld() == NULL) { + return FAILURE; } - return GetCurrentWorld()->GetCurrPathInfo(p_path, p_value); + return ::CurrentWorld()->GetCurrPathInfo(p_path, p_value); +} + +// FUNCTION: LEGO1 0x1005b490 +MxS32 LegoOmni::GetScriptIndex(const char* p_key) +{ + for (MxS32 i = 0; i < 19; i++) { + if ((MxS32) &m_scripts[i] != -4 && !strcmpi(m_scripts[i].GetKey(), p_key)) { + return m_scripts[i].GetIndex(); + } + } + + return -1; } // FUNCTION: LEGO1 0x1005b4f0 @@ -685,7 +900,7 @@ void LegoOmni::FUN_1005b4f0(MxBool p_disable, MxU16 p_flags) { if (p_disable) { if (p_flags & c_disableInput) { - m_inputMgr->DisableInputProcessing(); + m_inputManager->DisableInputProcessing(); } if (p_flags & c_disable3d) { @@ -697,7 +912,7 @@ void LegoOmni::FUN_1005b4f0(MxBool p_disable, MxU16 p_flags) } } else { - m_inputMgr->EnableInputProcessing(); + m_inputManager->EnableInputProcessing(); ((LegoVideoManager*) m_videoManager)->SetRender3D(TRUE); ((LegoVideoManager*) m_videoManager)->UpdateView(0, 0, 0, 0); } @@ -706,8 +921,9 @@ void LegoOmni::FUN_1005b4f0(MxBool p_disable, MxU16 p_flags) // FUNCTION: LEGO1 0x1005b560 void LegoOmni::CreateBackgroundAudio() { - if (m_bkgAudioManager) + if (m_bkgAudioManager) { m_bkgAudioManager->Create(*g_jukeboxScript, 100); + } } // FUNCTION: LEGO1 0x1005b580 diff --git a/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp b/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp index 299bbe33..b6abd2c4 100644 --- a/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp +++ b/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp @@ -3,10 +3,3 @@ #include "decomp.h" DECOMP_SIZE_ASSERT(LegoEventNotificationParam, 0x20); - -// STUB: LEGO1 0x10028690 -MxNotificationParam* LegoEventNotificationParam::Clone() -{ - // TODO - return NULL; -} diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index c187344c..404835eb 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -24,3 +24,21 @@ MxResult LegoPathController::Tickle() // TODO return SUCCESS; } + +// STUB: LEGO1 0x10046770 +undefined4 LegoPathController::FUN_10046770(IslePathActor* p_actor) +{ + return 0; +} + +// STUB: LEGO1 0x10046b30 +MxResult LegoPathController::FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value) +{ + return SUCCESS; +} + +// STUB: LEGO1 0x10046be0 +void LegoPathController::Enable(MxBool p_enable) +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp index 48d592a3..0b94b4eb 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp @@ -39,16 +39,18 @@ MxResult LegoPathPresenter::AddToManager() // FUNCTION: LEGO1 0x10044b70 void LegoPathPresenter::Destroy(MxBool p_fromDestructor) { - if (VideoManager()) + if (VideoManager()) { VideoManager()->UnregisterPresenter(*this); + } { MxAutoLocker lock(&this->m_criticalSection); Init(); } - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x10044c10 @@ -67,22 +69,23 @@ void LegoPathPresenter::ReadyTickle() // FUNCTION: LEGO1 0x10044d00 void LegoPathPresenter::StreamingTickle() { - MxStreamChunk* chunk = m_subscriber->NextChunk(); + MxStreamChunk* chunk = m_subscriber->PopData(); if (chunk) { if (chunk->GetFlags() & MxStreamChunk::c_end) { ProgressTickleState(e_repeating); } - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); } } // FUNCTION: LEGO1 0x10044d40 void LegoPathPresenter::RepeatingTickle() { - if (this->m_action->GetDuration() == -1) + if (this->m_action->GetDuration() == -1) { return; + } EndAction(); } diff --git a/LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp b/LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp index 6fb460a1..c1804a4f 100644 --- a/LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp +++ b/LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp @@ -4,7 +4,7 @@ DECOMP_SIZE_ASSERT(PizzaMissionStateEntry, 0x20) DECOMP_SIZE_ASSERT(PizzaMissionState, 0xb0) // STUB: LEGO1 0x100393c0 -MxResult PizzaMissionState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult PizzaMissionState::VTable0x1c(LegoFile* p_legoFile) { // TODO return SUCCESS; @@ -13,8 +13,10 @@ MxResult PizzaMissionState::VTable0x1c(LegoFileStream* p_legoFileStream) // FUNCTION: LEGO1 0x10039510 PizzaMissionStateEntry* PizzaMissionState::GetState(MxU8 p_id) { - for (MxS16 i = 0; i < 5; i++) - if (m_state[i].m_id == p_id) + for (MxS16 i = 0; i < 5; i++) { + if (m_state[i].m_id == p_id) { return m_state + i; + } + } return NULL; } diff --git a/LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp b/LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp index 3422c68d..6694e4d8 100644 --- a/LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp +++ b/LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp @@ -7,7 +7,7 @@ PizzeriaState::PizzeriaState() } // STUB: LEGO1 0x10017da0 -MxResult PizzeriaState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult PizzeriaState::VTable0x1c(LegoFile* p_legoFile) { // TODO return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/police/police.cpp b/LEGO1/lego/legoomni/src/police/police.cpp index 42456814..6c404a33 100644 --- a/LEGO1/lego/legoomni/src/police/police.cpp +++ b/LEGO1/lego/legoomni/src/police/police.cpp @@ -5,7 +5,10 @@ #include "legogamestate.h" #include "legoinputmanager.h" #include "legoomni.h" +#include "mxbackgroundaudiomanager.h" #include "mxnotificationmanager.h" +#include "mxtransitionmanager.h" +#include "policestate.h" DECOMP_SIZE_ASSERT(Police, 0x110) @@ -13,15 +16,14 @@ DECOMP_SIZE_ASSERT(Police, 0x110) Police::Police() { m_policeState = NULL; - m_unk0x10c = 0; + m_transitionDestination = LegoGameState::e_noArea; NotificationManager()->Register(this); } -// STUB: LEGO1 0x1005e1d0 +// FUNCTION: LEGO1 0x1005e1d0 MxBool Police::VTable0x5c() { - // TODO - return FALSE; + return TRUE; } // FUNCTION: LEGO1 0x1005e320 @@ -55,36 +57,137 @@ MxResult Police::Create(MxDSAction& p_dsAction) } m_policeState = policeState; - GameState()->SetUnknown424(0x22); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(LegoGameState::e_police); + GameState()->StopArea(LegoGameState::e_previousArea); return ret; } -// STUB: LEGO1 0x1005e480 +// FUNCTION: LEGO1 0x1005e480 MxLong Police::Notify(MxParam& p_param) { - // TODO + MxLong result = 0; + LegoWorld::Notify(p_param); - return 0; + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) p_param); + break; + case c_notificationKeyPress: + result = HandleKeyPress(((LegoEventNotificationParam&) p_param)); + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_transitionDestination); + break; + } + } + + return result; } // FUNCTION: LEGO1 0x1005e530 -void Police::VTable0x50() +void Police::ReadyWorld() { - LegoWorld::VTable0x50(); + LegoWorld::ReadyWorld(); PlayMusic(JukeBox::e_policeStation); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } -// STUB: LEGO1 0x1005e740 -void Police::VTable0x68(MxBool p_add) +// FUNCTION: LEGO1 0x1005e550 +MxLong Police::HandleClick(LegoControlManagerEvent& p_param) { - // TODO + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { + case c_leftArrowCtl: + case c_rightArrowCtl: + if (m_policeState->GetUnknown0x0c() == 1) { + DeleteObjects(&m_atom, c_nickAnim, c_lauraAnim); + } + + BackgroundAudioManager()->Stop(); + m_transitionDestination = LegoGameState::Area::e_unk35; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + break; + case c_infoCtl: + if (m_policeState->GetUnknown0x0c() == 1) { + DeleteObjects(&m_atom, c_nickAnim, c_lauraAnim); + } + + BackgroundAudioManager()->Stop(); + m_transitionDestination = LegoGameState::Area::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + break; + case c_doorCtl: + if (m_policeState->GetUnknown0x0c() == 1) { + DeleteObjects(&m_atom, c_nickAnim, c_lauraAnim); + } + + BackgroundAudioManager()->Stop(); + m_transitionDestination = LegoGameState::Area::e_copter; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + break; + case c_donutCtl: + m_policeState->FUN_1005ea40(); + } + } + + return 1; } -// STUB: LEGO1 0x1005e790 +// FUNCTION: LEGO1 0x1005e6a0 +MxLong Police::HandleEndAction(MxEndActionNotificationParam& p_param) +{ + MxDSAction* action = p_param.GetAction(); + + if (m_radio.Notify(p_param) == 0 && m_atom == action->GetAtomId()) { + if (m_policeState->GetUnknown0x0c() == 1) { + m_policeState->SetUnknown0x0c(0); + return 1; + } + + return 0; + } + + return 0; +} + +// FUNCTION: LEGO1 0x1005e6f0 +MxLong Police::HandleKeyPress(LegoEventNotificationParam& p_param) +{ + MxLong result = 0; + + if (p_param.GetKey() == ' ' && m_policeState->GetUnknown0x0c() == 1) { + DeleteObjects(&m_atom, c_nickAnim, c_lauraAnim); + m_policeState->SetUnknown0x0c(0); + return 1; + } + + return 0; +} + +// FUNCTION: LEGO1 0x1005e740 +void Police::Enable(MxBool p_enable) +{ + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } +} + +// FUNCTION: LEGO1 0x1005e790 MxBool Police::VTable0x64() { - // TODO - return FALSE; + DeleteObjects(&m_atom, c_nickAnim, 510); + m_transitionDestination = LegoGameState::e_infomain; + return TRUE; } diff --git a/LEGO1/lego/legoomni/src/police/policestate.cpp b/LEGO1/lego/legoomni/src/police/policestate.cpp index b0011ccb..07ef3a55 100644 --- a/LEGO1/lego/legoomni/src/police/policestate.cpp +++ b/LEGO1/lego/legoomni/src/police/policestate.cpp @@ -1,5 +1,11 @@ #include "policestate.h" +#include "islepathactor.h" +#include "legoomni.h" +#include "mxdsaction.h" +#include "mxomni.h" +#include "police.h" + #include DECOMP_SIZE_ASSERT(PoliceState, 0x10) @@ -7,24 +13,58 @@ DECOMP_SIZE_ASSERT(PoliceState, 0x10) // FUNCTION: LEGO1 0x1005e7c0 PoliceState::PoliceState() { - m_unk0xc = 0; - m_unk0x8 = (rand() % 2 == 0) ? 501 : 500; + m_unk0x0c = 0; + m_policeScript = (rand() % 2 == 0) ? Police::PoliceScript::c_lauraAnim : Police::PoliceScript::c_nickAnim; } // FUNCTION: LEGO1 0x1005e990 -MxResult PoliceState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult PoliceState::VTable0x1c(LegoFile* p_legoFile) { - if (p_legoFileStream->IsWriteMode()) { - p_legoFileStream->FUN_10006030(ClassName()); + if (p_legoFile->IsWriteMode()) { + p_legoFile->FUN_10006030(ClassName()); } - if (p_legoFileStream->IsReadMode()) { - p_legoFileStream->Read(&m_unk0x8, sizeof(m_unk0x8)); + if (p_legoFile->IsReadMode()) { + p_legoFile->Read(&m_policeScript, sizeof(m_policeScript)); } else { - undefined4 unk0x8 = m_unk0x8; - p_legoFileStream->Write(&unk0x8, sizeof(m_unk0x8)); + Police::PoliceScript policeScript = m_policeScript; + p_legoFile->Write(&policeScript, sizeof(m_policeScript)); } return SUCCESS; } + +// FUNCTION: LEGO1 0x1005ea40 +void PoliceState::FUN_1005ea40() +{ + Police::PoliceScript policeScript; + + if (m_unk0x0c == 1) { + return; + } + + switch (CurrentVehicle()->VTable0x60()) { + case 4: + policeScript = Police::PoliceScript::c_lauraAnim; + m_policeScript = policeScript; + break; + case 5: + policeScript = Police::PoliceScript::c_nickAnim; + m_policeScript = policeScript; + break; + default: + policeScript = m_policeScript; + m_policeScript = policeScript == Police::PoliceScript::c_lauraAnim ? Police::PoliceScript::c_nickAnim + : Police::PoliceScript::c_lauraAnim; + } + + { + MxDSAction action; + action.SetObjectId(policeScript); + action.SetAtomId(*g_policeScript); + Start(&action); + } + + m_unk0x0c = 1; +} diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp index 2e5c3b11..6230ed78 100644 --- a/LEGO1/lego/legoomni/src/race/carrace.cpp +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -17,7 +17,7 @@ MxResult CarRace::Create(MxDSAction& p_dsAction) } // STUB: LEGO1 0x10016dd0 -void CarRace::VTable0x50() +void CarRace::ReadyWorld() { // TODO } diff --git a/LEGO1/lego/legoomni/src/race/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp index cc119878..8f477204 100644 --- a/LEGO1/lego/legoomni/src/race/jetskirace.cpp +++ b/LEGO1/lego/legoomni/src/race/jetskirace.cpp @@ -1 +1,36 @@ #include "jetskirace.h" + +// STUB: LEGO1 0x100162c0 +MxResult JetskiRace::Create(MxDSAction& p_dsAction) +{ + return SUCCESS; +} + +// STUB: LEGO1 0x100163b0 +void JetskiRace::ReadyWorld() +{ +} + +// STUB: LEGO1 0x10016520 +undefined4 JetskiRace::VTable0x74(undefined4) +{ + return 0; +} + +// STUB: LEGO1 0x100165a0 +undefined4 JetskiRace::VTable0x6c(undefined4) +{ + return 0; +} + +// STUB: LEGO1 0x100166a0 +undefined4 JetskiRace::VTable0x70(undefined4) +{ + return 0; +} + +// STUB: LEGO1 0x10016a10 +MxBool JetskiRace::VTable0x64() +{ + return TRUE; +} diff --git a/LEGO1/lego/legoomni/src/race/racestate.cpp b/LEGO1/lego/legoomni/src/race/racestate.cpp index bdc003f0..39e6c51c 100644 --- a/LEGO1/lego/legoomni/src/race/racestate.cpp +++ b/LEGO1/lego/legoomni/src/race/racestate.cpp @@ -12,7 +12,7 @@ RaceState::RaceState() } // STUB: LEGO1 0x10016140 -MxResult RaceState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult RaceState::VTable0x1c(LegoFile* p_legoFile) { // TODO return SUCCESS; @@ -22,9 +22,11 @@ MxResult RaceState::VTable0x1c(LegoFileStream* p_legoFileStream) RaceStateEntry* RaceState::GetState(MxU8 p_id) { for (MxS16 i = 0;; i++) { - if (i >= 5) + if (i >= 5) { return NULL; - if (m_state[i].m_id == p_id) + } + if (m_state[i].m_id == p_id) { return m_state + i; + } } } diff --git a/LEGO1/lego/legoomni/src/towtrack/towtrack.cpp b/LEGO1/lego/legoomni/src/towtrack/towtrack.cpp index eb05e57b..ebfd3ee7 100644 --- a/LEGO1/lego/legoomni/src/towtrack/towtrack.cpp +++ b/LEGO1/lego/legoomni/src/towtrack/towtrack.cpp @@ -64,7 +64,7 @@ void TowTrack::VTable0xe4() } // STUB: LEGO1 0x1004d9e0 -MxU32 TowTrack::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 TowTrack::VTable0xd4(LegoControlManagerEvent& p_param) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp b/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp index a5719da5..9a85e0b6 100644 --- a/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp +++ b/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp @@ -21,54 +21,54 @@ TowTrackMissionState::TowTrackMissionState() } // FUNCTION: LEGO1 0x1004dde0 -MxResult TowTrackMissionState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult TowTrackMissionState::VTable0x1c(LegoFile* p_legoFile) { - if (p_legoFileStream->IsWriteMode()) { - p_legoFileStream->FUN_10006030(this->ClassName()); + if (p_legoFile->IsWriteMode()) { + p_legoFile->FUN_10006030(this->ClassName()); } - if (p_legoFileStream->IsReadMode()) { - p_legoFileStream->Read(&m_unk0x12, sizeof(MxU16)); - p_legoFileStream->Read(&m_unk0x14, sizeof(MxU16)); - p_legoFileStream->Read(&m_unk0x16, sizeof(MxU16)); - p_legoFileStream->Read(&m_unk0x18, sizeof(MxU16)); - p_legoFileStream->Read(&m_unk0x1a, sizeof(MxU16)); - p_legoFileStream->Read(&m_unk0x1c, sizeof(MxU16)); - p_legoFileStream->Read(&m_color1, sizeof(MxU16)); - p_legoFileStream->Read(&m_color2, sizeof(MxU16)); - p_legoFileStream->Read(&m_color3, sizeof(MxU16)); - p_legoFileStream->Read(&m_color4, sizeof(MxU16)); + if (p_legoFile->IsReadMode()) { + p_legoFile->Read(&m_unk0x12, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x14, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x16, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x18, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x1a, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x1c, sizeof(MxU16)); + p_legoFile->Read(&m_color1, sizeof(MxU16)); + p_legoFile->Read(&m_color2, sizeof(MxU16)); + p_legoFile->Read(&m_color3, sizeof(MxU16)); + p_legoFile->Read(&m_color4, sizeof(MxU16)); } - else if (p_legoFileStream->IsWriteMode()) { + else if (p_legoFile->IsWriteMode()) { MxU16 write = m_unk0x12; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_unk0x14; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_unk0x16; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_unk0x18; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_unk0x1a; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_unk0x1c; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_color1; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_color2; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_color3; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); write = m_color4; - p_legoFileStream->Write(&write, sizeof(MxU16)); + p_legoFile->Write(&write, sizeof(MxU16)); } return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp index 476c6291..bdf3eb98 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp @@ -1,5 +1,7 @@ #include "legoanimationmanager.h" +DECOMP_SIZE_ASSERT(LegoAnimationManager, 0x500) + // GLOBAL: LEGO1 0x100f74f8 int g_legoAnimationManagerConfig = 1; @@ -21,9 +23,22 @@ LegoAnimationManager::~LegoAnimationManager() // TODO } +// STUB: LEGO1 0x1005ee80 +void LegoAnimationManager::FUN_1005ee80(MxBool) +{ + // TODO +} + // STUB: LEGO1 0x1005ef10 void LegoAnimationManager::FUN_1005ef10() { + // TODO +} + +// STUB: LEGO1 0x1005f0b0 +void LegoAnimationManager::FUN_1005f0b0() +{ + // TODO } // STUB: LEGO1 0x1005f130 @@ -39,7 +54,13 @@ void LegoAnimationManager::FUN_1005f6d0(MxBool) } // STUB: LEGO1 0x1005f720 -void LegoAnimationManager::FUN_1005f720(undefined4) +void LegoAnimationManager::FUN_1005f720(MxS32 p_scriptIndex) +{ + // TODO +} + +// STUB: LEGO1 0x10061010 +void LegoAnimationManager::FUN_10061010(undefined4) { // TODO } diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index d5f50654..ba22865c 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1,15 +1,13 @@ #include "legoanimpresenter.h" #include "legoomni.h" -#include "legostream.h" #include "legoworld.h" #include "mxcompositepresenter.h" #include "mxdsanim.h" #include "mxstreamchunk.h" +#include "mxvideomanager.h" DECOMP_SIZE_ASSERT(LegoAnimPresenter, 0xc0) -DECOMP_SIZE_ASSERT(LegoAnimClassBase, 0x08) -DECOMP_SIZE_ASSERT(LegoAnimClass, 0x18) // FUNCTION: LEGO1 0x10068420 LegoAnimPresenter::LegoAnimPresenter() @@ -26,7 +24,7 @@ LegoAnimPresenter::~LegoAnimPresenter() // FUNCTION: LEGO1 0x100686f0 void LegoAnimPresenter::Init() { - m_unk0x64 = NULL; + m_anim = NULL; m_unk0x68 = 0; m_unk0x6c = 0; m_unk0x74 = 0; @@ -59,35 +57,47 @@ void LegoAnimPresenter::Destroy(MxBool p_fromDestructor) MxResult LegoAnimPresenter::VTable0x88(MxStreamChunk* p_chunk) { MxResult result = FAILURE; - LegoMemoryStream stream((char*) p_chunk->GetData()); - + LegoMemory storage(p_chunk->GetData()); MxS32 magicSig; - MxS32 val2 = 0; + LegoS32 parseScene = 0; MxS32 val3; - if (stream.Read(&magicSig, sizeof(MxS32)) == SUCCESS && magicSig == 0x11) { - if (stream.Read(&m_unk0xa4, sizeof(MxU32)) == SUCCESS) { - if (stream.Read(&m_unk0xa8[0], sizeof(float)) == SUCCESS) { - if (stream.Read(&m_unk0xa8[1], sizeof(float)) == SUCCESS) { - if (stream.Read(&m_unk0xa8[2], sizeof(float)) == SUCCESS) { - if (stream.Read(&val2, sizeof(MxS32)) == SUCCESS) { - if (stream.Read(&val3, sizeof(MxS32)) == SUCCESS) { - m_unk0x64 = new LegoAnimClass(); - if (m_unk0x64) { - if (m_unk0x64->VTable0x10(&stream, val2) == SUCCESS) { - result = SUCCESS; - } - } - } - } - } - } - } - } + if (storage.Read(&magicSig, sizeof(magicSig)) != SUCCESS || magicSig != 0x11) { + goto done; + } + if (storage.Read(&m_unk0xa4, sizeof(m_unk0xa4)) != SUCCESS) { + goto done; + } + if (storage.Read(&m_unk0xa8[0], sizeof(m_unk0xa8[0])) != SUCCESS) { + goto done; + } + if (storage.Read(&m_unk0xa8[1], sizeof(m_unk0xa8[1])) != SUCCESS) { + goto done; + } + if (storage.Read(&m_unk0xa8[2], sizeof(m_unk0xa8[2])) != SUCCESS) { + goto done; + } + if (storage.Read(&parseScene, sizeof(parseScene)) != SUCCESS) { + goto done; + } + if (storage.Read(&val3, sizeof(val3)) != SUCCESS) { + goto done; } + m_anim = new LegoAnim(); + if (!m_anim) { + goto done; + } + + if (m_anim->Read(&storage, parseScene) != SUCCESS) { + goto done; + } + + result = SUCCESS; + +done: if (result != SUCCESS) { - delete m_unk0x64; + delete m_anim; Init(); } @@ -103,15 +113,15 @@ void LegoAnimPresenter::PutFrame() // FUNCTION: LEGO1 0x1006b550 void LegoAnimPresenter::ReadyTickle() { - m_currentWorld = GetCurrentWorld(); + m_currentWorld = CurrentWorld(); if (m_currentWorld) { - MxStreamChunk* chunk = m_subscriber->CurrentChunk(); + MxStreamChunk* chunk = m_subscriber->PeekData(); if (chunk && chunk->GetTime() + m_action->GetStartTime() <= m_action->GetElapsedTime()) { - chunk = m_subscriber->NextChunk(); + chunk = m_subscriber->PopData(); MxResult result = VTable0x88(chunk); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); if (result == SUCCESS) { ProgressTickleState(e_starting); @@ -135,17 +145,12 @@ void LegoAnimPresenter::StartingTickle() // FUNCTION: LEGO1 0x1006b840 void LegoAnimPresenter::StreamingTickle() { - if (m_subscriber->CurrentChunk()) { - MxStreamChunk* chunk = m_subscriber->NextChunk(); - m_subscriber->DestroyChunk(chunk); + if (m_subscriber->PeekData()) { + MxStreamChunk* chunk = m_subscriber->PopData(); + m_subscriber->FreeDataChunk(chunk); } - if (m_unk0x95 == 0) { - if (m_unk0x64->m_unk0x8 + m_action->GetStartTime() < m_action->GetElapsedTime()) { - m_unk0x95 = 1; - } - } - else { + if (m_unk0x95) { ProgressTickleState(e_done); if (m_compositePresenter) { if (m_compositePresenter->IsA("LegoAnimMMPresenter")) { @@ -153,6 +158,11 @@ void LegoAnimPresenter::StreamingTickle() } } } + else { + if (m_action->GetElapsedTime() > m_anim->GetDuration() + m_action->GetStartTime()) { + m_unk0x95 = 1; + } + } } // STUB: LEGO1 0x1006b8c0 @@ -161,11 +171,10 @@ void LegoAnimPresenter::DoneTickle() // TODO } -// STUB: LEGO1 0x1006b8d0 +// FUNCTION: LEGO1 0x1006b8d0 MxResult LegoAnimPresenter::AddToManager() { - // TODO - return SUCCESS; + return MxVideoPresenter::AddToManager(); } // FUNCTION: LEGO1 0x1006b8e0 @@ -174,6 +183,12 @@ void LegoAnimPresenter::Destroy() Destroy(FALSE); } +// FUNCTION: LEGO1 0x1006b8f0 +const char* LegoAnimPresenter::GetActionObjectName() +{ + return m_action->GetObjectName(); +} + // STUB: LEGO1 0x1006bac0 void LegoAnimPresenter::ParseExtra() { @@ -194,63 +209,3 @@ void LegoAnimPresenter::EndAction() // TODO MxVideoPresenter::EndAction(); } - -// FUNCTION: LEGO1 0x10099dd0 -LegoAnimClassBase::LegoAnimClassBase() -{ - m_unk0x4 = 0; -} - -// STUB: LEGO1 0x10099e00 -LegoAnimClassBase::~LegoAnimClassBase() -{ - // TODO -} - -// STUB: LEGO1 0x10099e20 -void LegoAnimClassBase::VTable0x4() -{ -} - -// STUB: LEGO1 0x10099e40 -void LegoAnimClassBase::VTable0x8() -{ -} - -// STUB: LEGO1 0x10099f70 -void LegoAnimClassBase::VTable0xc() -{ -} - -// FUNCTION: LEGO1 0x100a0b30 -LegoAnimClass::LegoAnimClass() -{ - m_unk0x8 = 0; - m_unk0xc = 0; - m_unk0x10 = 0; - m_unk0x14 = 0; -} - -// STUB: LEGO1 0x100a0bc0 -LegoAnimClass::~LegoAnimClass() -{ - // TODO -} - -// STUB: LEGO1 0x100a0c70 -MxResult LegoAnimClass::VTable0x10(LegoMemoryStream* p_stream, MxS32) -{ - return SUCCESS; -} - -// STUB: LEGO1 0x100a0e30 -void LegoAnimClass::VTable0x8() -{ - // TODO -} - -// STUB: LEGO1 0x100a1040 -void LegoAnimClass::VTable0xc() -{ - // TODO -} diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp index 07035332..5bb59615 100644 --- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp @@ -25,22 +25,23 @@ void LegoHideAnimPresenter::Destroy(MxBool p_fromDestructor) { m_criticalSection.Enter(); - if (m_unk0xc0) + if (m_unk0xc0) { delete m_unk0xc0; + } Init(); m_criticalSection.Leave(); // This appears to be a bug, since it results in an endless loop - if (!p_fromDestructor) + if (!p_fromDestructor) { LegoHideAnimPresenter::Destroy(); + } } -// STUB: LEGO1 0x1006dab0 +// FUNCTION: LEGO1 0x1006dab0 MxResult LegoHideAnimPresenter::AddToManager() { - // TODO - return SUCCESS; + return LegoAnimPresenter::AddToManager(); } // FUNCTION: LEGO1 0x1006dac0 diff --git a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp index debe6659..45098aac 100644 --- a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp @@ -1,63 +1,115 @@ #include "legolocomotionanimpresenter.h" +#include "legoomni.h" +#include "legoworld.h" + +DECOMP_SIZE_ASSERT(LegoLocomotionAnimPresenter, 0xd8) + // FUNCTION: LEGO1 0x1006cdd0 LegoLocomotionAnimPresenter::LegoLocomotionAnimPresenter() { Init(); } -// STUB: LEGO1 0x1006d0b0 -void LegoLocomotionAnimPresenter::Init() +// FUNCTION: LEGO1 0x1006d050 +LegoLocomotionAnimPresenter::~LegoLocomotionAnimPresenter() { - // TODO + Destroy(TRUE); } -// STUB: LEGO1 0x1006d140 +// FUNCTION: LEGO1 0x1006d0b0 +void LegoLocomotionAnimPresenter::Init() +{ + m_unk0xc0 = 0; + m_unk0xc4 = 0; + m_unk0xcc = -1; + m_unk0xd0 = -1; + m_unk0xc8 = 0; + m_unk0xd4 = 0; +} + +// FUNCTION: LEGO1 0x1006d0e0 +void LegoLocomotionAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + m_criticalSection.Enter(); + + if (m_unk0xc4) { + delete[] m_unk0xc4; + } + + if (m_unk0xc8) { + delete m_unk0xc8; + } + + m_unk0x68 = 0; + Init(); + + m_criticalSection.Leave(); + + if (!p_fromDestructor) { + LegoAnimPresenter::Destroy(); + } +} + +// FUNCTION: LEGO1 0x1006d140 MxResult LegoLocomotionAnimPresenter::VTable0x88(MxStreamChunk* p_chunk) { - // TODO - return SUCCESS; + MxResult result = LegoAnimPresenter::VTable0x88(p_chunk); + return result == SUCCESS ? SUCCESS : result; } // STUB: LEGO1 0x1006d160 MxResult LegoLocomotionAnimPresenter::AddToManager() { - // TODO - return SUCCESS; + return MxVideoPresenter::AddToManager(); } -// STUB: LEGO1 0x1006d5b0 +// FUNCTION: LEGO1 0x1006d5b0 void LegoLocomotionAnimPresenter::Destroy() { - // TODO + Destroy(FALSE); } -// STUB: LEGO1 0x1006d5c0 +// FUNCTION: LEGO1 0x1006d5c0 void LegoLocomotionAnimPresenter::PutFrame() { - // TODO + // Empty } -// STUB: LEGO1 0x1006d5d0 +// FUNCTION: LEGO1 0x1006d5d0 void LegoLocomotionAnimPresenter::ReadyTickle() { - // TODO + LegoAnimPresenter::ReadyTickle(); + + if (m_currentWorld != NULL && m_currentTickleState == e_starting) { + m_currentWorld->Add(this); + if (m_compositePresenter != NULL) { + SendToCompositePresenter(Lego()); + } + + m_unk0xd4++; + } } // STUB: LEGO1 0x1006d610 void LegoLocomotionAnimPresenter::StartingTickle() { // TODO + EndAction(); } -// STUB: LEGO1 0x1006d660 +// FUNCTION: LEGO1 0x1006d660 void LegoLocomotionAnimPresenter::StreamingTickle() { - // TODO + if (m_unk0xd4 == 0) { + EndAction(); + } } -// STUB: LEGO1 0x1006d670 +// FUNCTION: LEGO1 0x1006d670 void LegoLocomotionAnimPresenter::EndAction() { - // TODO + if (m_action) { + MxVideoPresenter::EndAction(); + } } diff --git a/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp index f347545d..4ea26beb 100644 --- a/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp @@ -41,7 +41,7 @@ LegoMeterPresenter::LegoMeterPresenter() m_unk0x6c = 0; m_unk0x84 = 0; m_type = 1; - m_flags &= ~c_bit2; + SetBit1(FALSE); } // FUNCTION: LEGO1 0x10043780 diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index 4f835212..abc43b4e 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -1,8 +1,27 @@ #include "legomodelpresenter.h" +#include "define.h" +#include "legoentity.h" +#include "legoentitypresenter.h" +#include "legoomni.h" +#include "legounksavedatawriter.h" +#include "legovideomanager.h" +#include "legoworld.h" +#include "mxcompositepresenter.h" +#include "mxutil.h" +#include "roi/legoroi.h" + // GLOBAL: LEGO1 0x100f7ae0 int g_modelPresenterConfig = 1; +// GLOBAL: LEGO1 0x10102054 +// STRING: LEGO1 0x10102018 +char* g_autoCreate = "AUTO_CREATE"; + +// GLOBAL: LEGO1 0x10102078 +// STRING: LEGO1 0x10101fc4 +char* g_dbCreate = "DB_CREATE"; + // FUNCTION: LEGO1 0x1000cca0 void LegoModelPresenter::Destroy() { @@ -19,23 +38,113 @@ void LegoModelPresenter::configureLegoModelPresenter(MxS32 p_modelPresenterConfi void LegoModelPresenter::Destroy(MxBool p_fromDestructor) { m_criticalSection.Enter(); - m_unk0x64 = 0; + m_roi = NULL; m_addedToView = FALSE; m_criticalSection.Leave(); + if (!p_fromDestructor) { MxVideoPresenter::Destroy(FALSE); } } -// STUB: LEGO1 0x10080050 -void LegoModelPresenter::ReadyTickle() +// STUB: LEGO1 0x1007f6b0 +MxResult LegoModelPresenter::CreateROI(MxStreamChunk* p_chunk) { // TODO - SetTickleState(e_starting); + return FAILURE; } -// STUB: LEGO1 0x100801b0 +// FUNCTION: LEGO1 0x10080050 +void LegoModelPresenter::ReadyTickle() +{ + if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoEntityPresenter") && + m_compositePresenter->GetCurrentTickleState() <= e_ready) { + return; + } + + ParseExtra(); + + if (m_roi != NULL) { + if (m_compositePresenter && m_compositePresenter->IsA("LegoEntityPresenter")) { + ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->SetROI((LegoROI*) m_roi, m_addedToView, TRUE); + ((LegoEntityPresenter*) m_compositePresenter) + ->GetEntity() + ->SetFlags( + ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->GetFlags() & ~LegoEntity::c_bit2 + ); + ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->FUN_100114e0(0); + } + + ParseExtra(); + ProgressTickleState(e_starting); + EndAction(); + } + else { + MxStreamChunk* chunk = m_subscriber->PeekData(); + + if (chunk != NULL && chunk->GetTime() <= m_action->GetElapsedTime()) { + chunk = m_subscriber->PopData(); + MxResult result = CreateROI(chunk); + m_subscriber->FreeDataChunk(chunk); + + if (result == SUCCESS) { + VideoManager()->Get3DManager()->GetLego3DView()->Add(*m_roi); + VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); + + if (m_compositePresenter != NULL && m_compositePresenter->IsA("LegoEntityPresenter")) { + ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->SetROI((LegoROI*) m_roi, TRUE, TRUE); + ((LegoEntityPresenter*) m_compositePresenter) + ->GetEntity() + ->SetFlags( + ((LegoEntityPresenter*) m_compositePresenter)->GetEntity()->GetFlags() & ~LegoEntity::c_bit2 + ); + } + + ParseExtra(); + ProgressTickleState(e_starting); + } + + EndAction(); + } + } +} + +// FUNCTION: LEGO1 0x100801b0 void LegoModelPresenter::ParseExtra() { - // TODO + char output[1024]; + + MxU16 len = m_action->GetExtraLength(); + char* extraData = m_action->GetExtraData(); + + if (len != 0) { + char buffer[1024]; + output[0] = 0; + memcpy(buffer, extraData, len); + buffer[len] = 0; + + if (KeyValueStringParse(output, g_autoCreate, buffer) != 0) { + char* token = strtok(output, g_parseExtraTokens); + if (m_roi == NULL) { + m_roi = UnkSaveDataWriter()->FUN_10083500(token, FALSE); + m_addedToView = FALSE; + } + } + else if (KeyValueStringParse(output, g_dbCreate, buffer) != 0 && m_roi == NULL) { + LegoWorld* currentWorld = CurrentWorld(); + list& roiList = currentWorld->GetUnknownList0xe0(); + + for (list::iterator it = roiList.begin(); it != roiList.end(); it++) { + if (!strcmpi((*it)->GetName(), output)) { + m_roi = *it; + roiList.erase(it); + + m_addedToView = TRUE; + VideoManager()->Get3DManager()->GetLego3DView()->Add(*m_roi); + VideoManager()->Get3DManager()->GetLego3DView()->Moved(*m_roi); + break; + } + } + } + } } diff --git a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp index ce352f7e..c071a37e 100644 --- a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp @@ -1,8 +1,8 @@ #include "legopalettepresenter.h" #include "legoomni.h" -#include "legostream.h" #include "legovideomanager.h" +#include "misc/legostorage.h" #include "mxstreamchunk.h" DECOMP_SIZE_ASSERT(LegoPalettePresenter, 0x68) @@ -52,7 +52,7 @@ MxResult LegoPalettePresenter::ParsePalette(MxStreamChunk* p_chunk) RGBQUAD palette[256]; MxResult result = FAILURE; - LegoMemoryStream stream((char*) p_chunk->GetData()); + LegoMemory stream((char*) p_chunk->GetData()); if (stream.Read(buffer, sizeof(buffer)) == SUCCESS) { if (stream.Read(palette, sizeof(palette)) == SUCCESS) { m_palette = new MxPalette(palette); @@ -73,15 +73,15 @@ MxResult LegoPalettePresenter::ParsePalette(MxStreamChunk* p_chunk) // FUNCTION: LEGO1 0x1007a230 void LegoPalettePresenter::ReadyTickle() { - MxStreamChunk* chunk = m_subscriber->CurrentChunk(); + MxStreamChunk* chunk = m_subscriber->PeekData(); if (chunk) { if (chunk->GetTime() <= m_action->GetElapsedTime()) { ParseExtra(); ProgressTickleState(e_starting); - chunk = m_subscriber->NextChunk(); + chunk = m_subscriber->PopData(); MxResult result = ParsePalette(chunk); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); if (result == SUCCESS) { VideoManager()->RealizePalette(m_palette); diff --git a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp index 545d2f65..08cfe878 100644 --- a/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp @@ -1,15 +1,18 @@ #include "legopartpresenter.h" +#include "legoomni.h" +#include "legovideomanager.h" + // GLOBAL: LEGO1 0x100f7aa0 int g_partPresenterConfig1 = 1; // GLOBAL: LEGO1 0x100f7aa4 int g_partPresenterConfig2 = 100; -// STUB: LEGO1 0x1000cf60 +// FUNCTION: LEGO1 0x1000cf60 void LegoPartPresenter::Destroy() { - // TODO + Destroy(FALSE); } // FUNCTION: LEGO1 0x1007c990 @@ -19,13 +22,19 @@ void LegoPartPresenter::configureLegoPartPresenter(MxS32 p_partPresenterConfig1, g_partPresenterConfig2 = p_partPresenterConfig2; } -// STUB: LEGO1 0x1007c9b0 +// FUNCTION: LEGO1 0x1007c9b0 MxResult LegoPartPresenter::AddToManager() { - // TODO + VideoManager()->RegisterPresenter(*this); return SUCCESS; } +// STUB: LEGO1 0x1007c9d0 +void LegoPartPresenter::Destroy(MxBool p_fromDestructor) +{ + // TODO +} + // STUB: LEGO1 0x1007deb0 void LegoPartPresenter::ReadyTickle() { diff --git a/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp b/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp index 4d128531..8b226368 100644 --- a/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp @@ -26,6 +26,8 @@ void LegoPhonemePresenter::Init() void LegoPhonemePresenter::StartingTickle() { // TODO + + EndAction(); } // STUB: LEGO1 0x1004e800 @@ -44,4 +46,8 @@ void LegoPhonemePresenter::PutFrame() void LegoPhonemePresenter::EndAction() { // TODO + + if (m_action != NULL) { + MxFlcPresenter::EndAction(); + } } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index f31879b3..32ec0b99 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -50,8 +50,9 @@ LegoVideoManager::~LegoVideoManager() // FUNCTION: LEGO1 0x1007abb0 MxResult LegoVideoManager::CreateDirect3D() { - if (!m_direct3d) + if (!m_direct3d) { m_direct3d = new MxDirect3D; + } return m_direct3d ? SUCCESS : FAILURE; } @@ -61,7 +62,7 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM { MxBool paletteCreated = FALSE; MxDriver* driver = NULL; - MxDevice* device = NULL; + Direct3DDeviceInfo* device = NULL; MxResult result = FAILURE; MxDeviceEnumerate100d9cc8 deviceEnumerate; @@ -77,25 +78,29 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM MxPalette* palette = new MxPalette; p_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } paletteCreated = TRUE; } PALETTEENTRY paletteEntries[256]; p_videoParam.GetPalette()->GetEntries(paletteEntries); - if (CreateDirect3D() != SUCCESS) + if (CreateDirect3D() != SUCCESS) { goto done; + } - if (deviceEnumerate.DoEnumerate() != SUCCESS) + if (deviceEnumerate.DoEnumerate() != SUCCESS) { goto done; + } if (p_videoParam.GetDeviceName()) { deviceNum = deviceEnumerate.ParseDeviceName(p_videoParam.GetDeviceName()); if (deviceNum >= 0) { - if ((deviceNum = deviceEnumerate.GetDevice(deviceNum, driver, device)) != SUCCESS) + if ((deviceNum = deviceEnumerate.GetDevice(deviceNum, driver, device)) != SUCCESS) { deviceNum = -1; + } } } @@ -107,10 +112,12 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM m_direct3d->SetDevice(deviceEnumerate, driver, device); - if (!driver->m_ddCaps.dwCaps2 && driver->m_ddCaps.dwSVBRops[7] != 2) + if (!driver->m_ddCaps.dwCaps2 && driver->m_ddCaps.dwSVBRops[7] != 2) { p_videoParam.Flags().SetF2bit0(TRUE); - else + } + else { p_videoParam.Flags().SetF2bit0(FALSE); + } ViewROI::SetUnk101013d8(p_videoParam.Flags().GetF2bit0() == FALSE); @@ -124,30 +131,34 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM bits, paletteEntries, sizeof(paletteEntries) / sizeof(paletteEntries[0]) - )) + )) { goto done; + } if (MxVideoManager::VTable0x28( p_videoParam, - m_direct3d->GetDirectDraw(), - m_direct3d->GetDirect3D(), - m_direct3d->GetFrontBuffer(), - m_direct3d->GetBackBuffer(), - m_direct3d->GetClipper(), + m_direct3d->DirectDraw(), + m_direct3d->Direct3D(), + m_direct3d->FrontBuffer(), + m_direct3d->BackBuffer(), + m_direct3d->Clipper(), p_frequencyMS, p_createThread - ) != SUCCESS) + ) != SUCCESS) { goto done; + } m_renderer = Tgl::CreateRenderer(); - if (!m_renderer) + if (!m_renderer) { goto done; + } m_3dManager = new Lego3DManager; - if (!m_3dManager) + if (!m_3dManager) { goto done; + } Lego3DManager::CreateStruct createStruct; memset(&createStruct, 0, sizeof(createStruct)); @@ -158,19 +169,21 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM createStruct.m_pPalette = m_videoParam.GetPalette()->CreateNativePalette(); createStruct.m_isFullScreen = FALSE; createStruct.m_isWideViewAngle = m_videoParam.Flags().GetWideViewAngle(); - createStruct.m_direct3d = m_direct3d->GetDirect3D(); - createStruct.m_d3dDevice = m_direct3d->GetDirect3DDevice(); + createStruct.m_direct3d = m_direct3d->Direct3D(); + createStruct.m_d3dDevice = m_direct3d->Direct3DDevice(); - if (!m_3dManager->Create(createStruct)) + if (!m_3dManager->Create(createStruct)) { goto done; + } ViewLODList* pLODList; - if (ConfigureD3DRM() != SUCCESS) + if (ConfigureD3DRM() != SUCCESS) { goto done; + } pLODList = m_3dManager->GetViewLODListManager()->Create("CameraROI", 1); - m_viewROI = new LegoROI(m_renderer, pLODList, Timer()->GetTime()); + m_viewROI = new TimeROI(m_renderer, pLODList, Timer()->GetTime()); pLODList->Release(); CalcLocalTransform(posVec, dirVec, upVec, outMatrix); @@ -219,19 +232,22 @@ void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) m_cursorY = p_cursorY; m_drawCursor = TRUE; - if (623 < p_cursorX) + if (623 < p_cursorX) { m_cursorX = 623; + } - if (463 < p_cursorY) + if (463 < p_cursorY) { m_cursorY = 463; + } } // FUNCTION: LEGO1 0x1007b770 MxResult LegoVideoManager::Tickle() { if (m_unk0x554 && !m_videoParam.Flags().GetFlipSurfaces() && - TransitionManager()->GetTransitionType() == MxTransitionManager::e_notTransitioning) + TransitionManager()->GetTransitionType() == MxTransitionManager::e_notTransitioning) { Sleep(30); + } m_stopWatch->Stop(); m_elapsedSeconds = m_stopWatch->ElapsedSeconds(); @@ -245,11 +261,13 @@ MxResult LegoVideoManager::Tickle() MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->Tickle(); + } - if (m_render3d && !m_paused) + if (m_render3d && !m_paused) { m_3dManager->GetLego3DView()->GetView()->Clear(); + } MxRect32 rect(0, 0, m_videoParam.GetRect().GetWidth() - 1, m_videoParam.GetRect().GetHeight() - 1); InvalidateRect(rect); @@ -257,8 +275,9 @@ MxResult LegoVideoManager::Tickle() if (!m_paused && (m_render3d || m_unk0xe5)) { cursor.Reset(); - while (cursor.Next(presenter) && presenter->GetDisplayZ() >= 0) + while (cursor.Next(presenter) && presenter->GetDisplayZ() >= 0) { presenter->PutData(); + } if (!m_unk0xe5) { m_3dManager->Render(0.0); @@ -267,21 +286,25 @@ MxResult LegoVideoManager::Tickle() cursor.Prev(); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->PutData(); + } - if (m_drawCursor) + if (m_drawCursor) { DrawCursor(); + } - if (m_drawFPS) + if (m_drawFPS) { DrawFPS(); + } } else if (m_fullScreenMovie) { MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - if (cursor.Last(presenter)) + if (cursor.Last(presenter)) { presenter->PutData(); + } } if (!m_paused) { @@ -316,8 +339,9 @@ inline void LegoVideoManager::DrawCursor() m_cursorRect.right = 16; m_cursorSurface = MxDisplaySurface::CreateCursorSurface(); - if (!m_cursorSurface) + if (!m_cursorSurface) { m_drawCursor = FALSE; + } } ddSurface2 @@ -330,10 +354,19 @@ void LegoVideoManager::DrawFPS() // TODO } -// STUB: LEGO1 0x1007c080 -void LegoVideoManager::VTable0x38(undefined4, undefined4) +// FUNCTION: LEGO1 0x1007c080 +MxPresenter* LegoVideoManager::GetPresenterAt(MxS32 p_x, MxS32 p_y) { - // TODO + MxPresenterListCursor cursor(m_presenters); + MxPresenter* presenter; + + while (cursor.Prev(presenter)) { + if (presenter->IsHit(p_x, p_y)) { + return presenter; + } + } + + return NULL; } // FUNCTION: LEGO1 0x1007c290 @@ -438,6 +471,12 @@ void LegoVideoManager::UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_h } } +// STUB: LEGO1 0x1007c520 +void LegoVideoManager::FUN_1007c520() +{ + // TODO +} + // STUB: LEGO1 0x1007c560 int LegoVideoManager::EnableRMDevice() { @@ -458,19 +497,22 @@ MxResult LegoVideoManager::ConfigureD3DRM() IDirect3DRMDevice2* d3drm = ((TglImpl::DeviceImpl*) m_3dManager->GetLego3DView()->GetDevice())->ImplementationData(); - if (!d3drm) + if (!d3drm) { return FAILURE; + } - MxAssignedDevice* assignedDevice = m_direct3d->GetAssignedDevice(); + MxAssignedDevice* assignedDevice = m_direct3d->AssignedDevice(); if (assignedDevice && assignedDevice->GetFlags() & MxAssignedDevice::c_hardwareMode) { - if (assignedDevice->GetDesc().dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) + if (assignedDevice->GetDesc().dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) { d3drm->SetTextureQuality(D3DRMTEXTURE_LINEAR); + } d3drm->SetDither(TRUE); - if (assignedDevice->GetDesc().dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_ALPHAFLATBLEND) + if (assignedDevice->GetDesc().dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_ALPHAFLATBLEND) { d3drm->SetRenderMode(D3DRMRENDERMODE_BLENDEDTRANSPARENCY); + } } return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp index 677837bf..8672cdaa 100644 --- a/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp @@ -137,7 +137,7 @@ void MxTransitionManager::EndTransition(MxBool p_notifyWorld) TickleManager()->UnregisterClient(this); if (p_notifyWorld) { - LegoWorld* world = GetCurrentWorld(); + LegoWorld* world = CurrentWorld(); if (world) { #ifdef COMPAT_MODE @@ -209,11 +209,13 @@ void MxTransitionManager::TransitionDissolve() for (MxS32 col = 0; col < 640; col++) { // Select 16 columns on each tick - if (m_animationTimer * 16 > m_columnOrder[col]) + if (m_animationTimer * 16 > m_columnOrder[col]) { continue; + } - if (m_animationTimer * 16 + 15 < m_columnOrder[col]) + if (m_animationTimer * 16 + 15 < m_columnOrder[col]) { continue; + } for (MxS32 row = 0; row < 480; row++) { // Shift the chosen column a different amount at each scanline. @@ -223,10 +225,12 @@ void MxTransitionManager::TransitionDissolve() // Set the chosen pixel to black if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) { - ((MxU8*) ddsd.lpSurface)[row * ddsd.lPitch + xShift] = 0; + MxU8* surf = (MxU8*) ddsd.lpSurface + ddsd.lPitch * row + xShift; + *surf = 0; } else { - ((MxU16*) ddsd.lpSurface)[row * ddsd.lPitch + xShift] = 0; + MxU8* surf = (MxU8*) ddsd.lpSurface + ddsd.lPitch * row + xShift * 2; + *(MxU16*) surf = 0; } } } @@ -289,60 +293,47 @@ void MxTransitionManager::TransitionPixelation() for (MxS32 col = 0; col < 64; col++) { // Select 4 columns on each tick - if (m_animationTimer * 4 > m_columnOrder[col]) + if (m_animationTimer * 4 > m_columnOrder[col]) { continue; + } - if (m_animationTimer * 4 + 3 < m_columnOrder[col]) + if (m_animationTimer * 4 + 3 < m_columnOrder[col]) { continue; + } for (MxS32 row = 0; row < 48; row++) { - MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64); - // To do the pixelation, we subdivide the 640x480 surface into // 10x10 pixel blocks. At the chosen block, we sample the top-leftmost // color and set the other 99 pixels to that value. - // Find the pixel to sample - MxS32 sampleOfs = 10 * row * ddsd.lPitch + xShift; + // First, get the offset of the 10x10 block that we will sample for this row. + MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64); + + // Combine xShift with this value to target the correct location in the buffer. MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8; - // Save this cast from void* to save time. - // Seems to help accuracy doing it this way. - MxU8* surface = (MxU8*) ddsd.lpSurface; - MxU8* source = surface + sampleOfs * bytesPerPixel; + // Seek to the sample position. + MxU8* source = (MxU8*) ddsd.lpSurface + 10 * row * ddsd.lPitch + bytesPerPixel * xShift; + // Sample byte or word depending on display mode. MxU32 sample = bytesPerPixel == 1 ? *source : *(MxU16*) source; + // For each of the 10 rows in the 10x10 square: for (MxS32 k = 10 * row; k < 10 * row + 10; k++) { if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) { - // TODO: This block and the next don't match, but they are - // hopefully correct in principle. - MxU16 colorWord = MAKEWORD(LOBYTE(sample), LOBYTE(sample)); - MxU32 newColor = MAKELONG(colorWord, colorWord); + MxU8* pos = (MxU8*) ddsd.lpSurface + k * ddsd.lPitch + xShift; - MxU8* pos = surface + k * ddsd.lPitch + xShift; - MxU32* dest = (MxU32*) pos; - - // Sets 10 pixels (10 bytes) - dest[0] = newColor; - dest[1] = newColor; - MxU16* half = (MxU16*) (dest + 2); - *half = newColor; + for (MxS32 tt = 0; tt < 10; tt++) { + pos[tt] = sample; + } } else { - MxU32 newColor = MAKELONG(sample, sample); + // Need to double xShift because it measures pixels not bytes + MxU16* pos = (MxU16*) ((MxU8*) ddsd.lpSurface + k * ddsd.lPitch + 2 * xShift); - // You might expect a cast to MxU16* instead, but lPitch is - // bytes/scanline, not pixels/scanline. Therefore, we just - // need to double the xShift to get to the right spot. - MxU8* pos = surface + k * ddsd.lPitch + 2 * xShift; - MxU32* dest = (MxU32*) pos; - // Sets 10 pixels (20 bytes) - dest[0] = newColor; - dest[1] = newColor; - dest[2] = newColor; - dest[3] = newColor; - dest[4] = newColor; + for (MxS32 tt = 0; tt < 10; tt++) { + pos[tt] = sample; + } } } } @@ -562,8 +553,9 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) (const MxU8*) p_ddsc->lpSurface + m_copyRect.top * p_ddsc->lPitch + bytesPerPixel * m_copyRect.left; m_copyBuffer = new MxU8[bytesPerPixel * width * height]; - if (!m_copyBuffer) + if (!m_copyBuffer) { return; + } // Copy into the copy buffer MxU8* dst = m_copyBuffer; diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.cpp b/LEGO1/lego/sources/3dmanager/lego3dview.cpp index cfa274f6..34f699d8 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.cpp +++ b/LEGO1/lego/sources/3dmanager/lego3dview.cpp @@ -29,8 +29,9 @@ Lego3DView::~Lego3DView() BOOL Lego3DView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) { double viewAngle = 45; - if (rCreateStruct.m_isWideViewAngle) + if (rCreateStruct.m_isWideViewAngle) { viewAngle = 90; + } float frontClippingDistance = 0.1; float backClippingDistance = 500; diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.h b/LEGO1/lego/sources/3dmanager/lego3dview.h index 7e68bdcb..cbbde4a8 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.h +++ b/LEGO1/lego/sources/3dmanager/lego3dview.h @@ -13,10 +13,10 @@ class Lego3DView : public LegoView1 { public: Lego3DView(); - virtual ~Lego3DView() override; + ~Lego3DView() override; BOOL Create(const CreateStruct&, Tgl::Renderer*); - virtual void Destroy() override; // vtable+0x08 + void Destroy() override; // vtable+0x08 BOOL Add(ViewROI&); BOOL Remove(ViewROI&); diff --git a/LEGO1/lego/sources/3dmanager/legoview1.cpp b/LEGO1/lego/sources/3dmanager/legoview1.cpp index 97114469..28ffb911 100644 --- a/LEGO1/lego/sources/3dmanager/legoview1.cpp +++ b/LEGO1/lego/sources/3dmanager/legoview1.cpp @@ -42,8 +42,9 @@ LegoView::~LegoView() BOOL LegoView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) { float viewAngle = 45; - if (rCreateStruct.m_isWideViewAngle) + if (rCreateStruct.m_isWideViewAngle) { viewAngle = 90; + } float frontClippingDistance = 0.1; float backClippingDistance = 500; diff --git a/LEGO1/lego/sources/3dmanager/legoview1.h b/LEGO1/lego/sources/3dmanager/legoview1.h index 4060e54f..34b8f026 100644 --- a/LEGO1/lego/sources/3dmanager/legoview1.h +++ b/LEGO1/lego/sources/3dmanager/legoview1.h @@ -18,16 +18,16 @@ class Camera; class LegoView : public TglSurface { public: LegoView(); - virtual ~LegoView() override; + ~LegoView() override; BOOL Create(const CreateStruct&, Tgl::Renderer*); - virtual void Destroy() override; // vtable+0x08 + void Destroy() override; // vtable+0x08 Tgl::Group* GetScene() const; Tgl::Camera* GetCamera() const; protected: - virtual Tgl::View* CreateView(Tgl::Renderer*, Tgl::Device*); // vtable+0x10 + Tgl::View* CreateView(Tgl::Renderer*, Tgl::Device*) override; // vtable+0x10 private: Tgl::Group* m_pScene; // 0x70 @@ -58,11 +58,11 @@ inline Tgl::Camera* LegoView::GetCamera() const class LegoView1 : public LegoView { public: LegoView1(); - virtual ~LegoView1() override; + ~LegoView1() override; BOOL AddLightsToViewport(); BOOL Create(const TglSurface::CreateStruct&, Tgl::Renderer*); - virtual void Destroy() override; // vtable+0x08 + void Destroy() override; // vtable+0x08 private: Tgl::Light* m_pSunLight; // 0x78 diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.cpp b/LEGO1/lego/sources/3dmanager/tglsurface.cpp index 394e03e5..9664b2b2 100644 --- a/LEGO1/lego/sources/3dmanager/tglsurface.cpp +++ b/LEGO1/lego/sources/3dmanager/tglsurface.cpp @@ -181,8 +181,7 @@ double TglSurface::Render() m_renderingRateMeter.StartOperation(); renderTimer.Start(); - // TODO: Wrong interface - result = m_pView->Render((Tgl::Light*) m_pScene); + result = m_pView->Render(m_pScene); renderTimer.Stop(); assert(Succeeded(result)); diff --git a/LEGO1/lego/sources/anim/legoanim.cpp b/LEGO1/lego/sources/anim/legoanim.cpp new file mode 100644 index 00000000..d172ceb8 --- /dev/null +++ b/LEGO1/lego/sources/anim/legoanim.cpp @@ -0,0 +1,524 @@ +#include "legoanim.h" + +DECOMP_SIZE_ASSERT(LegoAnimKey, 0x08) +DECOMP_SIZE_ASSERT(LegoTranslationKey, 0x14) +DECOMP_SIZE_ASSERT(LegoRotationKey, 0x18) +DECOMP_SIZE_ASSERT(LegoScaleKey, 0x14) +DECOMP_SIZE_ASSERT(LegoMorphKey, 0x0c) +DECOMP_SIZE_ASSERT(LegoUnknownKey, 0x0c) +DECOMP_SIZE_ASSERT(LegoAnimNodeData, 0x34) +DECOMP_SIZE_ASSERT(LegoAnimActorEntry, 0x08) +DECOMP_SIZE_ASSERT(LegoAnimScene, 0x24) +DECOMP_SIZE_ASSERT(LegoAnim, 0x18) + +// FUNCTION: LEGO1 0x1009f000 +LegoUnknownKey::LegoUnknownKey() +{ + m_unk0x08 = 0; +} + +// FUNCTION: LEGO1 0x1009f020 +LegoResult LegoUnknownKey::Read(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Read(p_storage)) != SUCCESS) { + return result; + } + + result = p_storage->Read(&m_unk0x08, sizeof(m_unk0x08)); + return result == SUCCESS ? SUCCESS : result; +} + +// FUNCTION: LEGO1 0x1009f0a0 +LegoAnimScene::LegoAnimScene() +{ + m_unk0x00 = 0; + m_unk0x04 = NULL; + m_unk0x08 = 0; + m_unk0x0c = NULL; + m_unk0x10 = 0; + m_unk0x14 = NULL; + m_unk0x18 = 0; + m_unk0x1c = 0; + m_unk0x20 = 0; +} + +// FUNCTION: LEGO1 0x1009f0d0 +LegoAnimScene::~LegoAnimScene() +{ + if (m_unk0x04 != NULL) { + delete[] m_unk0x04; + m_unk0x04 = NULL; + } + + if (m_unk0x0c != NULL) { + delete[] m_unk0x0c; + m_unk0x0c = NULL; + } + + if (m_unk0x14 != NULL) { + delete[] m_unk0x14; + m_unk0x14 = NULL; + } +} + +// FUNCTION: LEGO1 0x1009f200 +LegoResult LegoAnimScene::Read(LegoStorage* p_storage) +{ + LegoResult result; + LegoS32 i; + + if ((result = p_storage->Read(&m_unk0x00, sizeof(m_unk0x00))) != SUCCESS) { + return result; + } + + if (m_unk0x00) { + m_unk0x04 = new LegoTranslationKey[m_unk0x00]; + for (i = 0; i < m_unk0x00; i++) { + if ((result = m_unk0x04[i].Read(p_storage)) != SUCCESS) { + goto done; + } + } + } + + if ((result = p_storage->Read(&m_unk0x08, sizeof(m_unk0x08))) != SUCCESS) { + return result; + } + + if (m_unk0x08) { + m_unk0x0c = new LegoTranslationKey[m_unk0x08]; + for (i = 0; i < m_unk0x08; i++) { + if ((result = m_unk0x0c[i].Read(p_storage)) != SUCCESS) { + goto done; + } + } + } + + if ((result = p_storage->Read(&m_unk0x10, sizeof(m_unk0x10))) != SUCCESS) { + return result; + } + + if (m_unk0x10) { + m_unk0x14 = new LegoUnknownKey[m_unk0x10]; + for (i = 0; i < m_unk0x10; i++) { + if ((result = m_unk0x14[i].Read(p_storage)) != SUCCESS) { + goto done; + } + } + } + + return SUCCESS; + +done: + if (m_unk0x04 != NULL) { + delete[] m_unk0x04; + m_unk0x00 = 0; + m_unk0x04 = NULL; + } + + if (m_unk0x0c != NULL) { + delete[] m_unk0x0c; + m_unk0x08 = 0; + m_unk0x0c = NULL; + } + + if (m_unk0x14 != NULL) { + delete[] m_unk0x14; + m_unk0x10 = 0; + m_unk0x14 = NULL; + } + + return result; +} + +// FUNCTION: LEGO1 0x1009f900 +LegoAnimKey::LegoAnimKey() +{ + m_unk0x00 = 0; + m_unk0x04 = 0; +} + +// FUNCTION: LEGO1 0x1009f910 +LegoResult LegoAnimKey::Read(LegoStorage* p_storage) +{ + LegoResult result; + LegoS32 und; + + if ((result = p_storage->Read(&und, sizeof(und))) != SUCCESS) { + return result; + } + + m_unk0x00 = (LegoU32) und >> 24; + m_unk0x04 = und & 0xffffff; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009f990 +LegoTranslationKey::LegoTranslationKey() +{ + m_x = 0.0F; + m_y = 0.0F; + m_z = 0.0F; +} + +// FUNCTION: LEGO1 0x1009f9b0 +LegoResult LegoTranslationKey::Read(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Read(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_x, sizeof(m_x))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_y, sizeof(m_y))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + if (m_x > 1e-05F || m_x < -1e-05F || m_y > 1e-05F || m_y < -1e-05F || m_z > 1e-05F || m_z < -1e-05F) { + m_unk0x00 |= c_bit1; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009faa0 +LegoRotationKey::LegoRotationKey() +{ + m_angle = 1.0F; + m_x = 0.0F; + m_y = 0.0F; + m_z = 0.0F; +} + +// FUNCTION: LEGO1 0x1009fac0 +LegoResult LegoRotationKey::Read(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Read(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_angle, sizeof(m_angle))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_x, sizeof(m_x))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_y, sizeof(m_y))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + if (m_angle != 1.0F) { + m_unk0x00 |= c_bit1; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009fba0 +LegoScaleKey::LegoScaleKey() +{ + m_x = 1.0F; + m_y = 1.0F; + m_z = 1.0F; +} + +// FUNCTION: LEGO1 0x1009fbc0 +LegoResult LegoScaleKey::Read(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Read(p_storage)) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_x, sizeof(m_x))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_y, sizeof(m_y))) != SUCCESS) { + return result; + } + + if ((result = p_storage->Read(&m_z, sizeof(m_z))) != SUCCESS) { + return result; + } + + if (m_x > 1.00001 || m_x < 0.99999 || m_y > 1.00001 || m_y < 0.99999 || m_z > 1.00001 || m_z < 0.99999) { + m_unk0x00 |= c_bit1; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009fcf0 +LegoAnimNodeData::LegoAnimNodeData() +{ + m_numTranslationKeys = 0; + m_numRotationKeys = 0; + m_numScaleKeys = 0; + m_numMorphKeys = 0; + + m_name = NULL; + m_translationKeys = NULL; + m_unk0x20 = 0; + m_rotationKeys = NULL; + m_unk0x22 = 0; + m_scaleKeys = NULL; + m_morphKeys = NULL; + m_unk0x24 = 0; + m_unk0x28 = 0; + m_unk0x2c = 0; + m_unk0x30 = 0; +} + +// FUNCTION: LEGO1 0x1009fda0 +LegoAnimNodeData::~LegoAnimNodeData() +{ + if (m_name) { + delete[] m_name; + } + if (m_translationKeys) { + delete[] m_translationKeys; + } + if (m_rotationKeys) { + delete[] m_rotationKeys; + } + if (m_scaleKeys) { + delete[] m_scaleKeys; + } + if (m_morphKeys) { + delete[] m_morphKeys; + } +} + +// FUNCTION: LEGO1 0x1009fe60 +LegoResult LegoAnimNodeData::Read(LegoStorage* p_storage) +{ + LegoResult result; + + LegoU32 length; + if ((result = p_storage->Read(&length, sizeof(length))) != SUCCESS) { + return result; + } + + if (m_name) { + delete[] m_name; + m_name = NULL; + } + if (length) { + m_name = new LegoChar[length + 1]; + if ((result = p_storage->Read(m_name, length)) != SUCCESS) { + return result; + } + m_name[length] = '\0'; + } + + LegoU32 i; + + if ((result = p_storage->Read(&m_numTranslationKeys, sizeof(m_numTranslationKeys))) != SUCCESS) { + return result; + } + if (m_translationKeys) { + delete[] m_translationKeys; + m_translationKeys = NULL; + } + if (m_numTranslationKeys) { + m_translationKeys = new LegoTranslationKey[m_numTranslationKeys]; + for (i = 0; i < m_numTranslationKeys; i++) { + if ((result = m_translationKeys[i].Read(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Read(&m_numRotationKeys, sizeof(m_numRotationKeys))) != SUCCESS) { + return result; + } + if (m_rotationKeys) { + delete[] m_rotationKeys; + m_rotationKeys = NULL; + } + if (m_numRotationKeys) { + m_rotationKeys = new LegoRotationKey[m_numRotationKeys]; + for (i = 0; i < m_numRotationKeys; i++) { + if ((result = m_rotationKeys[i].Read(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Read(&m_numScaleKeys, sizeof(m_numScaleKeys))) != SUCCESS) { + return result; + } + if (m_scaleKeys) { + delete[] m_scaleKeys; + m_scaleKeys = NULL; + } + if (m_numScaleKeys) { + m_scaleKeys = new LegoScaleKey[m_numScaleKeys]; + for (i = 0; i < m_numScaleKeys; i++) { + if ((result = m_scaleKeys[i].Read(p_storage)) != SUCCESS) { + return result; + } + } + } + + if ((result = p_storage->Read(&m_numMorphKeys, sizeof(m_numMorphKeys))) != SUCCESS) { + return result; + } + if (m_morphKeys) { + delete[] m_morphKeys; + m_morphKeys = NULL; + } + if (m_numMorphKeys) { + m_morphKeys = new LegoMorphKey[m_numMorphKeys]; + for (i = 0; i < m_numMorphKeys; i++) { + if ((result = m_morphKeys[i].Read(p_storage)) != SUCCESS) { + return result; + } + } + } + + return SUCCESS; +} + +// STUB: LEGO1 0x100a01e0 +LegoResult LegoAnimNodeData::Write(LegoStorage* p_storage) +{ + // TODO + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100a0b30 +LegoAnim::LegoAnim() +{ + m_duration = 0; + m_actors = NULL; + m_numActors = 0; + m_scene = NULL; +} + +// FUNCTION: LEGO1 0x100a0bc0 +LegoAnim::~LegoAnim() +{ + if (m_actors != NULL) { + for (LegoU32 i = 0; i < m_numActors; i++) { + delete[] m_actors[i].m_name; + } + + delete[] m_actors; + } + + if (m_scene != NULL) { + delete m_scene; + } +} + +// FUNCTION: LEGO1 0x100a0c70 +LegoResult LegoAnim::Read(LegoStorage* p_storage, LegoS32 p_parseScene) +{ + LegoResult result = FAILURE; + LegoU32 length, i; + + if (p_storage->Read(&length, sizeof(length)) != SUCCESS) { + goto done; + } + + m_actors = new LegoAnimActorEntry[length]; + m_numActors = 0; + + for (i = 0; i < length; i++) { + LegoU32 length; + if (p_storage->Read(&length, sizeof(length)) != SUCCESS) { + goto done; + } + + if (length) { + m_actors[i].m_name = new LegoChar[length + 1]; + + if (p_storage->Read(m_actors[i].m_name, length) != SUCCESS) { + goto done; + } + + m_actors[i].m_name[length] = '\0'; + + if (p_storage->Read(&m_actors[i].m_unk0x04, sizeof(m_actors[i].m_unk0x04)) != SUCCESS) { + goto done; + } + } + + m_numActors++; + } + + if ((result = p_storage->Read(&m_duration, sizeof(m_duration))) != SUCCESS) { + goto done; + } + + if (p_parseScene) { + m_scene = new LegoAnimScene(); + + result = m_scene->Read(p_storage); + + if (result != SUCCESS) { + goto done; + } + } + + result = LegoTree::Read(p_storage); + +done: + if (result != SUCCESS && m_actors != NULL) { + for (i = 0; i < m_numActors; i++) { + delete[] m_actors[i].m_name; + } + + m_numActors = 0; + delete[] m_actors; + m_actors = NULL; + } + + return result; +} + +// STUB: LEGO1 0x100a0e30 +LegoResult LegoAnim::Write(LegoStorage* p_storage) +{ + // TODO + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100a0f60 +LegoMorphKey::LegoMorphKey() +{ + m_unk0x08 = 0; +} + +// FUNCTION: LEGO1 0x100a0f70 +LegoResult LegoMorphKey::Read(LegoStorage* p_storage) +{ + LegoResult result; + + if ((result = LegoAnimKey::Read(p_storage)) != SUCCESS) { + return result; + } + + result = p_storage->Read(&m_unk0x08, sizeof(m_unk0x08)); + return result == SUCCESS ? SUCCESS : result; +} diff --git a/LEGO1/lego/sources/anim/legoanim.h b/LEGO1/lego/sources/anim/legoanim.h new file mode 100644 index 00000000..a16b2415 --- /dev/null +++ b/LEGO1/lego/sources/anim/legoanim.h @@ -0,0 +1,158 @@ +#ifndef __LEGOANIM_H +#define __LEGOANIM_H + +#include "decomp.h" +#include "misc/legostorage.h" +#include "misc/legotree.h" + +// SIZE 0x08 +class LegoAnimKey { +public: + enum Flags { + c_bit1 = 0x01 + }; + + LegoAnimKey(); + LegoResult Read(LegoStorage* p_storage); + +protected: + undefined m_unk0x00; // 0x00 + float m_unk0x04; // 0x04 +}; + +// SIZE 0x14 +class LegoTranslationKey : public LegoAnimKey { +public: + LegoTranslationKey(); + LegoResult Read(LegoStorage* p_storage); + +protected: + LegoFloat m_x; // 0x08 + LegoFloat m_y; // 0x0c + LegoFloat m_z; // 0x10 +}; + +// SIZE 0x18 +class LegoRotationKey : public LegoAnimKey { +public: + LegoRotationKey(); + LegoResult Read(LegoStorage* p_storage); + +protected: + LegoFloat m_angle; // 0x08 + LegoFloat m_x; // 0x0c + LegoFloat m_y; // 0x10 + LegoFloat m_z; // 0x14 +}; + +// SIZE 0x14 +class LegoScaleKey : public LegoAnimKey { +public: + LegoScaleKey(); + LegoResult Read(LegoStorage* p_storage); + +protected: + LegoFloat m_x; // 0x08 + LegoFloat m_y; // 0x0c + LegoFloat m_z; // 0x10 +}; + +// SIZE 0x0c +class LegoMorphKey : public LegoAnimKey { +public: + LegoMorphKey(); + LegoResult Read(LegoStorage* p_storage); + +protected: + undefined m_unk0x08; // 0x08 +}; + +// SIZE 0x0c +class LegoUnknownKey : public LegoAnimKey { +public: + LegoUnknownKey(); + LegoResult Read(LegoStorage* p_storage); + +protected: + undefined4 m_unk0x08; // 0x08 +}; + +// VTABLE: LEGO1 0x100db8c8 +// SIZE 0x34 +class LegoAnimNodeData : public LegoTreeNodeData { +public: + LegoAnimNodeData(); + ~LegoAnimNodeData() override; + LegoResult Read(LegoStorage* p_storage) override; // vtable+0x04 + LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 + + // SYNTHETIC: LEGO1 0x1009fd80 + // LegoAnimNodeData::`scalar deleting destructor' + +protected: + LegoChar* m_name; // 0x04 + LegoU16 m_numTranslationKeys; // 0x08 + LegoU16 m_numRotationKeys; // 0x0a + LegoU16 m_numScaleKeys; // 0x0c + LegoU16 m_numMorphKeys; // 0x0e + LegoTranslationKey* m_translationKeys; // 0x10 + LegoRotationKey* m_rotationKeys; // 0x14 + LegoScaleKey* m_scaleKeys; // 0x18 + LegoMorphKey* m_morphKeys; // 0x1c + undefined2 m_unk0x20; // 0x20 + undefined2 m_unk0x22; // 0x22 + undefined4 m_unk0x24; // 0x24 + undefined4 m_unk0x28; // 0x28 + undefined4 m_unk0x2c; // 0x2c + undefined4 m_unk0x30; // 0x30 +}; + +// SIZE 0x08 +struct LegoAnimActorEntry { + LegoChar* m_name; // 0x00 + undefined4 m_unk0x04; // 0x04 +}; + +// SIZE 0x24 +class LegoAnimScene { +public: + LegoAnimScene(); + ~LegoAnimScene(); + LegoResult Read(LegoStorage* p_storage); + +private: + LegoU16 m_unk0x00; // 0x00 + LegoTranslationKey* m_unk0x04; // 0x04 + LegoU16 m_unk0x08; // 0x08 + LegoTranslationKey* m_unk0x0c; // 0x0c + LegoU16 m_unk0x10; // 0x10 + LegoUnknownKey* m_unk0x14; // 0x14 + undefined4 m_unk0x18; // 0x18 + undefined4 m_unk0x1c; // 0x1c + undefined4 m_unk0x20; // 0x20 +}; + +// VTABLE: LEGO1 0x100db8d8 +// SIZE 0x18 +class LegoAnim : public LegoTree { +public: + LegoAnim(); + ~LegoAnim() override; + LegoTime GetDuration() { return m_duration; } + LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 + virtual LegoResult Read(LegoStorage* p_storage, LegoS32 p_parseScene); // vtable+0x10 + + // SYNTHETIC: LEGO1 0x100a0ba0 + // LegoAnim::`scalar deleting destructor' + +protected: + LegoTime m_duration; // 0x08 + LegoAnimActorEntry* m_actors; // 0x0c + LegoU32 m_numActors; // 0x10 + LegoAnimScene* m_scene; // 0x14 + + // FUNCTION: LEGO1 0x100a1040 + LegoTreeNodeData* CreateData() override { return new LegoAnimNodeData(); } // vtable+0x0c +}; + +#endif // __LEGOANIM_H diff --git a/LEGO1/lego/sources/misc/legocontainer.cpp b/LEGO1/lego/sources/misc/legocontainer.cpp new file mode 100644 index 00000000..aebfc96d --- /dev/null +++ b/LEGO1/lego/sources/misc/legocontainer.cpp @@ -0,0 +1,136 @@ +#include "legocontainer.h" + +#include "lego/legoomni/include/legoomni.h" +#include "lego/legoomni/include/legovideomanager.h" +#include "tgl/d3drm/impl.h" + +DECOMP_SIZE_ASSERT(LegoContainerInfo, 0x10); +// DECOMP_SIZE_ASSERT(LegoContainer, 0x18); +DECOMP_SIZE_ASSERT(LegoTextureContainer, 0x24); + +// FUNCTION: LEGO1 0x10099870 +LegoTextureContainer::~LegoTextureContainer() +{ +} + +// FUNCTION: LEGO1 0x100998e0 +LegoTextureInfo* LegoTextureContainer::Insert(LegoTextureInfo* p_textureInfo) +{ + DDSURFACEDESC desc, newDesc; + DWORD width, height; + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + + if (p_textureInfo->m_surface->Lock(NULL, &desc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) { + width = desc.dwWidth; + height = desc.dwHeight; + p_textureInfo->m_surface->Unlock(desc.lpSurface); + } + + for (LegoTextureList::iterator it = m_list.begin(); it != m_list.end(); it++) { + if ((*it).second == FALSE && (*it).first->m_texture->AddRef() != 0 && (*it).first->m_texture->Release() == 1) { + if (!strcmp((*it).first->m_name, p_textureInfo->m_name)) { + memset(&newDesc, 0, sizeof(newDesc)); + newDesc.dwSize = sizeof(newDesc); + + if ((*it).first->m_surface->Lock(NULL, &newDesc, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK) { + BOOL und = FALSE; + if (newDesc.dwWidth == width && newDesc.dwHeight == height) { + und = TRUE; + } + + (*it).first->m_surface->Unlock(newDesc.lpSurface); + + if (und) { + (*it).second = TRUE; + (*it).first->m_texture->AddRef(); + return (*it).first; + } + } + } + } + } + + LegoTextureInfo* textureInfo = new LegoTextureInfo(); + + textureInfo->m_palette = p_textureInfo->m_palette; + p_textureInfo->m_palette->Release(); + + memset(&newDesc, 0, sizeof(newDesc)); + newDesc.dwWidth = desc.dwWidth; + newDesc.dwHeight = desc.dwHeight; + newDesc.dwSize = sizeof(newDesc); + newDesc.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + newDesc.ddsCaps.dwCaps = DDCAPS_OVERLAYCANTCLIP | DDCAPS_OVERLAY; + newDesc.ddpfPixelFormat.dwSize = sizeof(desc.ddpfPixelFormat); + newDesc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8; + newDesc.ddpfPixelFormat.dwRGBBitCount = 8; + + if (VideoManager()->GetDirect3D()->DirectDraw()->CreateSurface(&newDesc, &textureInfo->m_surface, NULL) == DD_OK) { + RECT rect; + rect.left = 0; + rect.top = newDesc.dwWidth - 1; + rect.right = 0; + rect.bottom = newDesc.dwHeight - 1; + + textureInfo->m_surface->SetPalette(textureInfo->m_palette); + + if (textureInfo->m_surface->BltFast(0, 0, p_textureInfo->m_surface, &rect, DDBLTFAST_WAIT) != DD_OK) { + textureInfo->m_surface->Release(); + textureInfo->m_palette->Release(); + delete textureInfo; + return NULL; + } + else { + if (((TglImpl::RendererImpl*) VideoManager()->GetRenderer()) + ->CreateTextureFromSurface(textureInfo->m_surface, &textureInfo->m_texture) != D3DRM_OK) { + textureInfo->m_surface->Release(); + textureInfo->m_palette->Release(); + delete textureInfo; + return NULL; + } + else { + textureInfo->m_texture->SetAppData((DWORD) textureInfo); + m_list.push_back(LegoTextureListElement(textureInfo, TRUE)); + + textureInfo->m_texture->AddRef(); + + if (textureInfo->m_name != NULL) { + delete[] textureInfo->m_name; + } + + textureInfo->m_name = new char[strlen(p_textureInfo->m_name) + 1]; + strcpy(textureInfo->m_name, p_textureInfo->m_name); + return textureInfo; + } + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10099cc0 +void LegoTextureContainer::Erase(LegoTextureInfo* p_textureInfo) +{ + if (p_textureInfo == NULL) { + return; + } + +#ifdef COMPAT_MODE + LegoTextureList::iterator it; + for (it = m_list.begin(); it != m_list.end(); it++) { +#else + for (LegoTextureList::iterator it = m_list.begin(); it != m_list.end(); it++) { +#endif + if ((*it).first == p_textureInfo) { + (*it).second = FALSE; + + if (p_textureInfo->m_texture->Release() == TRUE) { + delete p_textureInfo; + m_list.erase(it); + } + + return; + } + } +} diff --git a/LEGO1/lego/sources/misc/legocontainer.h b/LEGO1/lego/sources/misc/legocontainer.h new file mode 100644 index 00000000..a1b869f1 --- /dev/null +++ b/LEGO1/lego/sources/misc/legocontainer.h @@ -0,0 +1,148 @@ +#ifndef LEGOCONTAINER_H +#define LEGOCONTAINER_H + +#include "compat.h" +#include "decomp.h" +#include "legotexture.h" +#include "legotypes.h" +#include "mxstl/stlcompat.h" + +// Note: dependency on LegoOmni +#include "lego/legoomni/include/legotextureinfo.h" + +#pragma warning(disable : 4237) + +struct LegoContainerInfoComparator { + bool operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } +}; + +// SIZE 0x10 +template +class LegoContainerInfo : public map {}; + +// SIZE 0x18 +template +class LegoContainer { +public: + virtual ~LegoContainer() + { +#ifdef COMPAT_MODE + typename LegoContainerInfo::iterator it; +#else + LegoContainerInfo::iterator it; +#endif + for (it = m_map.begin(); it != m_map.end(); it++) { + // DECOMP: Use of const_cast here matches ~ViewLODListManager from 96 source. + const char* const& key = (*it).first; + delete[] const_cast(key); + + if (m_ownership) { + delete (*it).second; + } + } + } + + inline T* Get(const char* p_name) + { +#ifdef COMPAT_MODE + typename LegoContainerInfo::iterator it = m_map.find(p_name); +#else + LegoContainerInfo::iterator it = m_map.find(p_name); +#endif + if (it != m_map.end()) { + return (*it).second; + } + + return NULL; + } + + inline void SetOwnership(LegoBool p_ownership) { m_ownership = p_ownership; } + +protected: + LegoBool m_ownership; // 0x04 + LegoContainerInfo m_map; // 0x08 +}; + +// VTABLE: LEGO1 0x100d86d4 +// class LegoContainer + +typedef pair LegoTextureListElement; +typedef list LegoTextureList; + +// VTABLE: LEGO1 0x100d86fc +// SIZE 0x24 +class LegoTextureContainer : public LegoContainer { +public: + LegoTextureContainer() { m_ownership = TRUE; } + ~LegoTextureContainer() override; + + LegoTextureInfo* Insert(LegoTextureInfo* p_textureInfo); + void Erase(LegoTextureInfo* p_textureInfo); + +protected: + LegoTextureList m_list; // 0x18 +}; + +// TEMPLATE: LEGO1 0x10059c50 +// allocator::_Charalloc + +// clang-format off +// TEMPLATE: LEGO1 0x10001cc0 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Lbound + +// TEMPLATE: LEGO1 0x1004f9b0 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Insert + +// TEMPLATE: LEGO1 0x10059c70 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Color + +// TEMPLATE: LEGO1 0x10059c80 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Left + +// TEMPLATE: LEGO1 0x10059c90 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Parent + +// TEMPLATE: LEGO1 0x10059ca0 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Right + +// TEMPLATE: LEGO1 0x10059cb0 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::~_Tree,map >::_Kfn,LegoContainerInfoComparator,allocator > + +// TEMPLATE: LEGO1 0x10059d80 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x10059dc0 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::erase + +// TEMPLATE: LEGO1 0x1005a210 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Erase + +// TEMPLATE: LEGO1 0x1005a250 +// list,allocator > >::~list,allocator > > + +// TEMPLATE: LEGO1 0x1005a2c0 +// map >::~map > + +// TEMPLATE: LEGO1 0x1005a310 +// LegoContainer::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1005a400 +// LegoContainerInfo::~LegoContainerInfo + +// TEMPLATE: LEGO1 0x1005a450 +// Map::~Map + +// SYNTHETIC: LEGO1 0x1005a580 +// LegoTextureContainer::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1005a5a0 +// List >::~List > + +// TEMPLATE: LEGO1 0x1005b660 +// LegoContainer::~LegoContainer + +// GLOBAL: LEGO1 0x100f0100 +// _Tree,map >::_Kfn,LegoContainerInfoComparator,allocator >::_Nil +// clang-format on + +#endif // LEGOCONTAINER_H diff --git a/LEGO1/lego/sources/misc/legoimage.cpp b/LEGO1/lego/sources/misc/legoimage.cpp new file mode 100644 index 00000000..da3f04a0 --- /dev/null +++ b/LEGO1/lego/sources/misc/legoimage.cpp @@ -0,0 +1,176 @@ +#include "legoimage.h" + +#include "decomp.h" +#include "legostorage.h" +#include "memory.h" + +DECOMP_SIZE_ASSERT(LegoPaletteEntry, 0x03); +DECOMP_SIZE_ASSERT(LegoImage, 0x310); + +// FUNCTION: LEGO1 0x100994c0 +LegoPaletteEntry::LegoPaletteEntry() +{ + m_red = 0; + m_green = 0; + m_blue = 0; +} + +// FUNCTION: LEGO1 0x100994d0 +LegoResult LegoPaletteEntry::Read(LegoStorage* p_storage) +{ + LegoResult result; + if ((result = p_storage->Read(&m_red, sizeof(m_red))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_green, sizeof(m_green))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_blue, sizeof(m_blue))) != SUCCESS) { + return result; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099520 +LegoResult LegoPaletteEntry::Write(LegoStorage* p_storage) +{ + LegoResult result; + if ((result = p_storage->Write(&m_red, sizeof(m_red))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_green, sizeof(m_green))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_blue, sizeof(m_blue))) != SUCCESS) { + return result; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099570 +LegoImage::LegoImage() +{ + m_width = 0; + m_height = 0; + m_count = 0; + m_bits = NULL; +} + +// FUNCTION: LEGO1 0x100995a0 +LegoImage::LegoImage(LegoU32 p_width, LegoU32 p_height) +{ + m_width = p_width; + m_height = p_height; + m_count = 0; + m_bits = new LegoU8[m_width * m_height]; +} + +// FUNCTION: LEGO1 0x100995f0 +LegoImage::~LegoImage() +{ + if (m_bits) { + delete[] m_bits; + } +} + +// FUNCTION: LEGO1 0x10099610 +LegoResult LegoImage::Read(LegoStorage* p_storage, LegoU32 p_square) +{ + LegoResult result; + if ((result = p_storage->Read(&m_width, sizeof(m_width))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_height, sizeof(m_height))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_count, sizeof(m_height))) != SUCCESS) { + return result; + } + for (LegoU32 i = 0; i < m_count; i++) { + if ((result = m_palette[i].Read(p_storage)) != SUCCESS) { + return result; + } + } + if (m_bits) { + delete[] m_bits; + } + m_bits = new LegoU8[m_width * m_height]; + if ((result = p_storage->Read(m_bits, m_width * m_height)) != SUCCESS) { + return result; + } + + if (p_square && m_width != m_height) { + LegoU8* newBits; + + if (m_height < m_width) { + LegoU32 aspect = m_width / m_height; + newBits = new LegoU8[m_width * m_width]; + LegoU8* src = m_bits; + LegoU8* dst = newBits; + + for (LegoU32 row = 0; row < m_height; row++) { + if (aspect) { + for (LegoU32 dup = aspect; dup; dup--) { + memcpy(dst, src, m_width); + dst += m_width; + } + } + src += m_width; + } + + m_height = m_width; + } + else { + LegoU32 aspect = m_height / m_width; + newBits = new LegoU8[m_height * m_height]; + LegoU8* src = m_bits; + LegoU8* dst = newBits; + + for (LegoU32 row = 0; row < m_height; row++) { + for (LegoU32 col = 0; col < m_width; col++) { + if (aspect) { + for (LegoU32 dup = aspect; dup; dup--) { + *dst = *src; + dst++; + } + } + + src++; + } + } + + m_width = m_height; + } + + delete[] m_bits; + m_bits = newBits; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100997e0 +LegoResult LegoImage::Write(LegoStorage* p_storage) +{ + LegoResult result; + if ((result = p_storage->Write(&m_width, sizeof(m_width))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_height, sizeof(m_height))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_count, sizeof(m_height))) != SUCCESS) { + return result; + } + for (LegoU32 i = 0; i < m_count; i++) { + if ((result = m_palette[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + if (m_bits) { + if ((result = p_storage->Write(m_bits, m_width * m_height)) != SUCCESS) { + return result; + } + } + return SUCCESS; +} diff --git a/LEGO1/lego/sources/misc/legoimage.h b/LEGO1/lego/sources/misc/legoimage.h new file mode 100644 index 00000000..7e0fbb17 --- /dev/null +++ b/LEGO1/lego/sources/misc/legoimage.h @@ -0,0 +1,55 @@ +#ifndef __LEGOIMAGE_H +#define __LEGOIMAGE_H + +#include "legotypes.h" + +class LegoStorage; + +// SIZE 0x03 +class LegoPaletteEntry { +public: + LegoPaletteEntry(); + // LegoPaletteEntry(LegoU8 p_red, LegoU8 p_green, LegoU8 p_blue); + LegoU8 GetRed() { return m_red; } + void SetRed(LegoU8 p_red) { m_red = p_red; } + LegoU8 GetGreen() { return m_green; } + void SetGreen(LegoU8 p_green) { m_green = p_green; } + LegoU8 GetBlue() { return m_blue; } + void SetBlue(LegoU8 p_blue) { m_blue = p_blue; } + LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); + +protected: + LegoU8 m_red; // 0x00 + LegoU8 m_green; // 0x01 + LegoU8 m_blue; // 0x02 +}; + +// 0x310 +class LegoImage { +public: + LegoImage(); + LegoImage(LegoU32 p_width, LegoU32 p_height); + ~LegoImage(); + LegoU32 GetWidth() { return m_width; } + void SetWidth(LegoU32 p_width) { m_width = p_width; } + LegoU32 GetHeight() { return m_height; } + void SetHeight(LegoU32 p_height) { m_height = p_height; } + LegoU32 GetCount() { return m_count; } + LegoPaletteEntry* GetPalette() { return m_palette; } + LegoPaletteEntry& GetPaletteEntry(LegoU32 p_i) { return m_palette[p_i]; } + void SetPaletteEntry(LegoU32 p_i, LegoPaletteEntry& p_paletteEntry) { m_palette[p_i] = p_paletteEntry; } + LegoU8* GetBits() { return m_bits; } + void SetBits(LegoU8* p_bits) { m_bits = p_bits; } + LegoResult Read(LegoStorage* p_storage, LegoU32 p_square); + LegoResult Write(LegoStorage* p_storage); + +protected: + LegoU32 m_width; // 0x00 + LegoU32 m_height; // 0x04 + LegoU32 m_count; // 0x08 + LegoPaletteEntry m_palette[256]; // 0x0c + LegoU8* m_bits; // 0x30c +}; + +#endif // __LEGOIMAGE_H diff --git a/LEGO1/lego/sources/misc/legostorage.cpp b/LEGO1/lego/sources/misc/legostorage.cpp new file mode 100644 index 00000000..8fa71553 --- /dev/null +++ b/LEGO1/lego/sources/misc/legostorage.cpp @@ -0,0 +1,142 @@ +#include "legostorage.h" + +#include "decomp.h" + +#include +#include + +DECOMP_SIZE_ASSERT(LegoStorage, 0x08); +DECOMP_SIZE_ASSERT(LegoMemory, 0x10); +DECOMP_SIZE_ASSERT(LegoFile, 0x0c); + +// FUNCTION: LEGO1 0x10099080 +LegoMemory::LegoMemory(void* p_buffer) : LegoStorage() +{ + m_buffer = (LegoU8*) p_buffer; + m_position = 0; +} + +// FUNCTION: LEGO1 0x10099160 +LegoResult LegoMemory::Read(void* p_buffer, LegoU32 p_size) +{ + memcpy(p_buffer, m_buffer + m_position, p_size); + m_position += p_size; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099190 +LegoResult LegoMemory::Write(const void* p_buffer, LegoU32 p_size) +{ + memcpy(m_buffer + m_position, p_buffer, p_size); + m_position += p_size; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100991c0 +LegoFile::LegoFile() +{ + m_file = NULL; +} + +// FUNCTION: LEGO1 0x10099250 +LegoFile::~LegoFile() +{ + if (m_file) { + fclose(m_file); + } +} + +// FUNCTION: LEGO1 0x100992c0 +LegoResult LegoFile::Read(void* p_buffer, LegoU32 p_size) +{ + if (!m_file) { + return FAILURE; + } + if (fread(p_buffer, 1, p_size, m_file) != p_size) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099300 +LegoResult LegoFile::Write(const void* p_buffer, LegoU32 p_size) +{ + if (!m_file) { + return FAILURE; + } + if (fwrite(p_buffer, 1, p_size, m_file) != p_size) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099340 +LegoResult LegoFile::GetPosition(LegoU32& p_position) +{ + if (!m_file) { + return FAILURE; + } + LegoU32 position = ftell(m_file); + if (position == -1) { + return FAILURE; + } + p_position = position; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099370 +LegoResult LegoFile::SetPosition(LegoU32 p_position) +{ + if (!m_file) { + return FAILURE; + } + if (fseek(m_file, p_position, SEEK_SET) != 0) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100993a0 +LegoResult LegoFile::Open(const char* p_name, LegoU32 p_mode) +{ + if (m_file) { + fclose(m_file); + } + char mode[4]; + mode[0] = '\0'; + if (p_mode & c_read) { + m_mode = c_read; + strcat(mode, "r"); + } + if (p_mode & c_write) { + if (m_mode != c_read) { + m_mode = c_write; + } + strcat(mode, "w"); + } + if ((p_mode & c_text) != 0) { + strcat(mode, "t"); + } + else { + strcat(mode, "b"); + } + + if (!(m_file = fopen(p_name, mode))) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100994a0 +LegoResult LegoMemory::GetPosition(LegoU32& p_position) +{ + p_position = m_position; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100994b0 +LegoResult LegoMemory::SetPosition(LegoU32 p_position) +{ + m_position = p_position; + return SUCCESS; +} diff --git a/LEGO1/lego/sources/misc/legostorage.h b/LEGO1/lego/sources/misc/legostorage.h new file mode 100644 index 00000000..e975c347 --- /dev/null +++ b/LEGO1/lego/sources/misc/legostorage.h @@ -0,0 +1,135 @@ +#ifndef __LEGOSTORAGE_H +#define __LEGOSTORAGE_H + +#include "legotypes.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxstring.h" + +#include + +// VTABLE: LEGO1 0x100d7d80 +// SIZE 0x08 +class LegoStorage { +public: + enum OpenFlags { + c_read = 1, + c_write = 2, + c_text = 4 + }; + + LegoStorage() : m_mode(0) {} + + // FUNCTION: LEGO1 0x10045ad0 + virtual ~LegoStorage(){}; + + virtual LegoResult Read(void* p_buffer, LegoU32 p_size) = 0; + virtual LegoResult Write(const void* p_buffer, LegoU32 p_size) = 0; + virtual LegoResult GetPosition(LegoU32& p_position) = 0; + virtual LegoResult SetPosition(LegoU32 p_position) = 0; + + // FUNCTION: LEGO1 0x10045ae0 + virtual LegoBool IsWriteMode() { return m_mode == c_write; } + + // FUNCTION: LEGO1 0x10045af0 + virtual LegoBool IsReadMode() { return m_mode == c_read; } + + // SYNTHETIC: LEGO1 0x10045b00 + // LegoStorage::`scalar deleting destructor' + +protected: + LegoU8 m_mode; // 0x04 +}; + +// VTABLE: LEGO1 0x100db710 +// SIZE 0x10 +class LegoMemory : public LegoStorage { +public: + LegoMemory(void* p_buffer); + LegoResult Read(void* p_buffer, LegoU32 p_size) override; + LegoResult Write(const void* p_buffer, LegoU32 p_size) override; + LegoResult GetPosition(LegoU32& p_position) override; + LegoResult SetPosition(LegoU32 p_position) override; + + // SYNTHETIC: LEGO1 0x10045a80 + // LegoMemory::~LegoMemory + + // SYNTHETIC: LEGO1 0x100990f0 + // LegoMemory::`scalar deleting destructor' + +protected: + LegoU8* m_buffer; // 0x04 + LegoU32 m_position; // 0x08 +}; + +// VTABLE: LEGO1 0x100db730 +// SIZE 0x0c +class LegoFile : public LegoStorage { +public: + LegoFile(); + ~LegoFile() override; + LegoResult Read(void* p_buffer, LegoU32 p_size) override; + LegoResult Write(const void* p_buffer, LegoU32 p_size) override; + LegoResult GetPosition(LegoU32& p_position) override; + LegoResult SetPosition(LegoU32 p_position) override; + LegoResult Open(const char* p_name, LegoU32 p_mode); + + // FUNCTION: LEGO1 0x100343d0 + LegoStorage* WriteVector3(Mx3DPointFloat p_vec3) + { + float data = p_vec3[0]; + Write(&data, sizeof(float)); + + data = p_vec3[1]; + Write(&data, sizeof(float)); + + data = p_vec3[2]; + Write(&data, sizeof(float)); + return this; + } + + // FUNCTION: LEGO1 0x10034430 + LegoStorage* ReadVector3(Mx3DPointFloat& p_vec3) + { + Read(&p_vec3[0], sizeof(float)); + Read(&p_vec3[1], sizeof(float)); + Read(&p_vec3[2], sizeof(float)); + return this; + } + + // FUNCTION: LEGO1 0x10034470 + LegoStorage* ReadString(MxString& p_str) + { + MxS16 len; + Read(&len, sizeof(MxS16)); + + char* text = new char[len + 1]; + Read(text, len); + + text[len] = '\0'; + p_str = text; + delete[] text; + + return this; + } + + // FUNCTION: LEGO1 0x10006030 + LegoStorage* FUN_10006030(MxString p_str) + { + const char* data = p_str.GetData(); + LegoU32 fullLength = strlen(data); + + LegoU16 limitedLength = fullLength; + Write(&limitedLength, sizeof(limitedLength)); + Write((char*) data, (LegoS16) fullLength); + + return this; + } + + // SYNTHETIC: LEGO1 0x10099230 + // LegoFile::`scalar deleting destructor' + +protected: + FILE* m_file; // 0x08 +}; + +#endif // __LEGOSTORAGE_H diff --git a/LEGO1/lego/sources/misc/legotexture.cpp b/LEGO1/lego/sources/misc/legotexture.cpp new file mode 100644 index 00000000..1f8844ff --- /dev/null +++ b/LEGO1/lego/sources/misc/legotexture.cpp @@ -0,0 +1,31 @@ +#include "legotexture.h" + +#include "decomp.h" +#include "legoimage.h" +#include "legostorage.h" + +DECOMP_SIZE_ASSERT(LegoTexture, 0x04); + +// FUNCTION: LEGO1 0x10098fb0 +LegoTexture::LegoTexture() +{ + m_image = new LegoImage(); +} + +// FUNCTION: LEGO1 0x10099030 +LegoTexture::~LegoTexture() +{ + delete m_image; +} + +// FUNCTION: LEGO1 0x10099050 +LegoResult LegoTexture::Read(LegoStorage* p_storage, LegoU32 p_square) +{ + return m_image->Read(p_storage, p_square); +} + +// FUNCTION: LEGO1 0x10099070 +LegoResult LegoTexture::Write(LegoStorage* p_storage) +{ + return m_image->Write(p_storage); +} diff --git a/LEGO1/lego/sources/misc/legotexture.h b/LEGO1/lego/sources/misc/legotexture.h new file mode 100644 index 00000000..1e279660 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotexture.h @@ -0,0 +1,23 @@ +#ifndef __LEGOTEXTURE_H +#define __LEGOTEXTURE_H + +#include "legotypes.h" + +class LegoImage; +class LegoStorage; + +// SIZE 0x04 +class LegoTexture { +public: + LegoTexture(); + ~LegoTexture(); + LegoImage* GetImage() { return m_image; } + void SetImage(LegoImage* p_image) { m_image = p_image; } + LegoResult Read(LegoStorage* p_storage, LegoU32 p_square); + LegoResult Write(LegoStorage* p_storage); + +protected: + LegoImage* m_image; // 0x00 +}; + +#endif // __LEGOTEXTURE_H diff --git a/LEGO1/lego/sources/misc/legotree.cpp b/LEGO1/lego/sources/misc/legotree.cpp new file mode 100644 index 00000000..e7f24513 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotree.cpp @@ -0,0 +1,110 @@ +#include "legotree.h" + +#include "decomp.h" +#include "legostorage.h" + +DECOMP_SIZE_ASSERT(LegoTreeNodeData, 0x04) +DECOMP_SIZE_ASSERT(LegoTreeNode, 0x010) +DECOMP_SIZE_ASSERT(LegoTree, 0x08) + +// FUNCTION: LEGO1 0x10099d60 +LegoTreeNode::LegoTreeNode() +{ + m_data = NULL; + m_numChildren = 0; + m_children = NULL; +} + +// FUNCTION: LEGO1 0x10099da0 +LegoTreeNode::~LegoTreeNode() +{ + if (m_data) { + delete m_data; + } + if (m_children) { + delete[] m_children; + } +} + +// FUNCTION: LEGO1 0x10099dd0 +LegoTree::LegoTree() +{ + m_root = NULL; +} + +// FUNCTION: LEGO1 0x10099e00 +LegoTree::~LegoTree() +{ + if (m_root) { + Delete(m_root); + } +} + +// FUNCTION: LEGO1 0x10099e20 +LegoResult LegoTree::Read(LegoStorage* p_storage) +{ + return Read(p_storage, m_root); +} + +// FUNCTION: LEGO1 0x10099e40 +LegoResult LegoTree::Write(LegoStorage* p_storage) +{ + return Write(p_storage, m_root); +} + +// FUNCTION: LEGO1 0x10099e60 +LegoResult LegoTree::Read(LegoStorage* p_storage, LegoTreeNode*& p_node) +{ + LegoResult result; + p_node = new LegoTreeNode(); + p_node->SetData(CreateData()); + if ((result = p_node->GetData()->Read(p_storage)) != SUCCESS) { + return result; + } + LegoU32 numChildren; + if ((result = p_storage->Read(&numChildren, sizeof(numChildren))) != SUCCESS) { + return result; + } + if (numChildren) { + p_node->SetChildren(new LegoTreeNode*[numChildren]); + for (LegoU32 i = 0; i < numChildren; i++) { + LegoTreeNode* node; + if ((result = Read(p_storage, node)) != SUCCESS) { + return result; + } + p_node->SetNumChildren(p_node->GetNumChildren() + 1); + p_node->SetChild(i, node); + } + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009a020 +LegoResult LegoTree::Write(LegoStorage* p_storage, LegoTreeNode* p_node) +{ + LegoResult result; + if (p_node->GetData()) { + if ((result = p_node->GetData()->Write(p_storage)) != SUCCESS) { + return result; + } + } + LegoU32 numChildren = p_node->GetNumChildren(); + if ((result = p_storage->Write(&numChildren, sizeof(numChildren))) != SUCCESS) { + return result; + } + for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { + if ((result = Write(p_storage, p_node->GetChild(i))) != SUCCESS) { + return result; + } + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009a0a0 +void LegoTree::Delete(LegoTreeNode* p_node) +{ + for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { + Delete(p_node->GetChild(i)); + } + delete p_node; +} diff --git a/LEGO1/lego/sources/misc/legotree.h b/LEGO1/lego/sources/misc/legotree.h new file mode 100644 index 00000000..9d4aec69 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotree.h @@ -0,0 +1,78 @@ +#ifndef __LEGOTREE_H +#define __LEGOTREE_H + +#ifdef _DEBUG +#include +#endif +#include "legotypes.h" + +class LegoStorage; + +// VTABLE: LEGO1 0x100db778 +// SIZE 0x04 +class LegoTreeNodeData { +public: + LegoTreeNodeData() {} + // FUNCTION: LEGO1 0x1009a0e0 + virtual ~LegoTreeNodeData() {} + + // FUNCTION: LEGO1 0x10099fe0 + virtual LegoResult Read(LegoStorage* p_storage) { return SUCCESS; } // vtable+0x04 + + // FUNCTION: LEGO1 0x10099ff0 + virtual LegoResult Write(LegoStorage* p_storage) { return SUCCESS; } // vtable+0x08 + + // SYNTHETIC: LEGO1 0x1009a000 + // LegoTreeNodeData::`scalar deleting destructor' +}; + +// VTABLE: LEGO1 0x100db764 +// SIZE 0x10 +class LegoTreeNode { +public: + LegoTreeNode(); + virtual ~LegoTreeNode(); + LegoTreeNodeData* GetData() { return m_data; } + void SetData(LegoTreeNodeData* p_data) { m_data = p_data; } + LegoU32 GetNumChildren() { return m_numChildren; } + void SetNumChildren(LegoU32 p_numChildren) { m_numChildren = p_numChildren; } + LegoTreeNode* GetChild(LegoU32 p_i) { return m_children[p_i]; } + void SetChild(LegoU32 p_i, LegoTreeNode* p_child) { m_children[p_i] = p_child; } + LegoTreeNode** GetChildren() { return m_children; } + void SetChildren(LegoTreeNode** p_children) { m_children = p_children; } + + // SYNTHETIC: LEGO1 0x10099d80 + // LegoTreeNode::`scalar deleting destructor' + +protected: + LegoTreeNodeData* m_data; // 0x04 + LegoU32 m_numChildren; // 0x08 + LegoTreeNode** m_children; // 0x0c +}; + +// VTABLE: LEGO1 0x100db768 +// SIZE 0x08 +class LegoTree { +public: + LegoTree(); + virtual ~LegoTree(); + LegoTreeNode* GetRoot() { return m_root; } + void SetRoot(LegoTreeNode* p_root) { m_root = p_root; } + virtual LegoResult Read(LegoStorage* p_storage); // vtable+0x04 + virtual LegoResult Write(LegoStorage* p_storage); // vtable+0x08 + + // SYNTHETIC: LEGO1 0x10099de0 + // LegoTree::`scalar deleting destructor' + +protected: + LegoResult Read(LegoStorage* p_storage, LegoTreeNode*& p_node); + LegoResult Write(LegoStorage* p_storage, LegoTreeNode* p_node); + void Delete(LegoTreeNode* p_node); + + // FUNCTION: LEGO1 0x10099f70 + virtual LegoTreeNodeData* CreateData() { return new LegoTreeNodeData(); } // vtable+0x0c + + LegoTreeNode* m_root; // 0x04 +}; + +#endif // __LEGOTREE_H diff --git a/LEGO1/lego/sources/misc/legotypes.h b/LEGO1/lego/sources/misc/legotypes.h new file mode 100644 index 00000000..7ba6ada1 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotypes.h @@ -0,0 +1,44 @@ +/* + This unpublished source code contains trade secrets and + copyrighted materials which are the property of Mindscape, Inc. + Unauthorized use, copying or distribution is a violation of U.S. + and international laws and is strictly prohibited. +*/ + +#ifndef __LEGOTYPES_H +#define __LEGOTYPES_H + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef SUCCESS +#define SUCCESS 0 +#endif + +#ifndef FAILURE +#define FAILURE -1 +#endif + +typedef char LegoS8; +typedef unsigned char LegoU8; +typedef short LegoS16; +typedef unsigned short LegoU16; +typedef long LegoS32; +typedef unsigned long LegoU32; +typedef float LegoFloat; +typedef char LegoChar; + +typedef LegoU8 LegoBool; +typedef LegoS32 LegoTime; +typedef LegoS32 LegoResult; + +#endif // __LEGOTYPES_H diff --git a/LEGO1/lego/sources/misc/legoutil.h b/LEGO1/lego/sources/misc/legoutil.h new file mode 100644 index 00000000..92bb84c2 --- /dev/null +++ b/LEGO1/lego/sources/misc/legoutil.h @@ -0,0 +1,54 @@ +#ifndef __LEGOUTIL_H +#define __LEGOUTIL_H + +template +inline T Min(T p_t1, T p_t2) +{ + return p_t1 < p_t2 ? p_t1 : p_t2; +} + +template +inline T Min(T p_t1, T p_t2, T p_t3) +{ + return Min(p_t1, Min(p_t2, p_t3)); +} + +template +inline T Max(T p_t1, T p_t2) +{ + return p_t1 > p_t2 ? p_t1 : p_t2; +} + +template +inline T Max(T p_t1, T p_t2, T p_t3) +{ + return Max(p_t1, Max(p_t2, p_t3)); +} + +template +inline T Abs(T p_t) +{ + return p_t < 0 ? -p_t : p_t; +} + +template +inline void Swap(T& p_t1, T& p_t2) +{ + T t = p_t1; + p_t1 = p_t2; + p_t2 = t; +} + +template +inline T DToR(T p_d) +{ + return p_d * 3.1416F / 180.0F; +} + +template +inline T RToD(T p_r) +{ + return p_r * 180.0F / 3.1416F; +} + +#endif // __LEGOUTIL_H diff --git a/LEGO1/lego/sources/misc/version.h b/LEGO1/lego/sources/misc/version.h new file mode 100644 index 00000000..1eaa84af --- /dev/null +++ b/LEGO1/lego/sources/misc/version.h @@ -0,0 +1,6 @@ +#ifndef __VERSION_H +#define __VERSION_H + +#define MODEL_VERSION 3 + +#endif // __VERSION_H diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index 0f262a51..bc0131f7 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -2,15 +2,16 @@ #include -DECOMP_SIZE_ASSERT(LegoROI, 0x10c); +DECOMP_SIZE_ASSERT(LegoROI, 0x108) +DECOMP_SIZE_ASSERT(TimeROI, 0x10c) // SIZE 0x14 typedef struct { const char* m_name; - MxS32 m_red; - MxS32 m_green; - MxS32 m_blue; - MxS32 m_unk0x10; + int m_red; + int m_green; + int m_blue; + int m_unk0x10; } ROIColorAlias; // GLOBAL: LEGO1 0x100dbe28 @@ -32,7 +33,7 @@ ROIColorAlias g_roiColorAliases[22] = { }; // GLOBAL: LEGO1 0x10101368 -MxS32 g_roiConfig = 100; +int g_roiConfig = 100; // GLOBAL: LEGO1 0x101013ac ROIHandler g_someHandlerFunction = NULL; @@ -54,45 +55,83 @@ void LegoROI::FUN_100a58f0(Matrix4& p_transform) } // FUNCTION: LEGO1 0x100a81c0 -void LegoROI::configureLegoROI(MxS32 p_roiConfig) +void LegoROI::configureLegoROI(int p_roiConfig) { g_roiConfig = p_roiConfig; } -// STUB: LEGO1 0x100a9a50 -LegoROI::LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, MxTime p_time) : ViewROI(p_renderer, p_lodList) +// FUNCTION: LEGO1 0x100a81d0 +LegoROI::LegoROI(Tgl::Renderer* p_renderer) : ViewROI(p_renderer, NULL), m_unk0xe0(-1) +{ + m_unk0xd4 = NULL; + m_name = NULL; + m_unk0x104 = NULL; +} + +// FUNCTION: LEGO1 0x100a82d0 +LegoROI::LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList) : ViewROI(p_renderer, p_lodList), m_unk0xe0(-1) +{ + m_unk0xd4 = NULL; + m_name = NULL; + m_unk0x104 = NULL; +} + +// FUNCTION: LEGO1 0x100a83c0 +LegoROI::~LegoROI() +{ + if (comp) { + CompoundObject::iterator iterator; + + for (iterator = comp->begin(); !(iterator == comp->end()); ++iterator) { + ROI* child = *iterator; + + delete child; + } + + delete comp; + comp = 0; + } + if (m_name) { + delete[] m_name; + } +} + +// FUNCTION: LEGO1 0x100a9a50 +TimeROI::TimeROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, int p_time) : LegoROI(p_renderer, p_lodList) { m_time = p_time; } // FUNCTION: LEGO1 0x100a9bf0 -MxBool LegoROI::CallTheHandlerFunction( +unsigned char LegoROI::CallTheHandlerFunction( char* p_param, - MxFloat& p_red, - MxFloat& p_green, - MxFloat& p_blue, - MxFloat& p_other + float& p_red, + float& p_green, + float& p_blue, + float& p_other ) { // TODO - if (p_param == NULL) + if (p_param == NULL) { return FALSE; + } if (g_someHandlerFunction) { char buf[32]; - if (g_someHandlerFunction(p_param, buf, 32)) + if (g_someHandlerFunction(p_param, buf, 32)) { p_param = buf; + } } return ColorAliasLookup(p_param, p_red, p_green, p_blue, p_other); } // FUNCTION: LEGO1 0x100a9c50 -MxBool LegoROI::ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green, MxFloat& p_blue, MxFloat& p_other) +unsigned char LegoROI::ColorAliasLookup(char* p_param, float& p_red, float& p_green, float& p_blue, float& p_other) { // TODO: this seems awfully hacky for these devs. is there a dynamic way // to represent `the end of this array` that would improve this? - MxU32 i = 0; + unsigned int i = 0; do { if (strcmpi(g_roiColorAliases[i].m_name, p_param) == 0) { p_red = g_roiColorAliases[i].m_red * g_normalizeByteToFloat; @@ -102,7 +141,7 @@ MxBool LegoROI::ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green return TRUE; } i++; - } while ((MxS32*) &g_roiColorAliases[i] < &g_roiConfig); + } while ((int*) &g_roiColorAliases[i] < &g_roiConfig); return FALSE; } @@ -114,7 +153,7 @@ void LegoROI::SetSomeHandlerFunction(ROIHandler p_func) } // FUNCTION: LEGO1 0x100a9e10 -void LegoROI::SetDisplayBB(MxS32 p_displayBB) +void LegoROI::SetDisplayBB(int p_displayBB) { // Intentionally empty function } @@ -125,7 +164,6 @@ float LegoROI::IntrinsicImportance() const return .5; } -// Note: Actually part of parent class (doesn't exist yet) // STUB: LEGO1 0x100aa350 void LegoROI::UpdateWorldBoundingVolumes() { diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index 5dfac62f..8b6c78ce 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -1,53 +1,68 @@ #ifndef LEGOROI_H #define LEGOROI_H -#include "mxtypes.h" +#include "misc/legotypes.h" #include "viewmanager/viewroi.h" -typedef MxBool (*ROIHandler)(char*, char*, MxU32); +typedef unsigned char (*ROIHandler)(char*, char*, unsigned int); class LegoEntity; -// Note: There is an extra class between LegoROI and ViewROI, -// maybe called "AutoROI". VTABLE 0x100dbe38 - -// VTABLE: LEGO1 0x100dbea8 -// SIZE 0x10c +// VTABLE: LEGO1 0x100dbe38 +// SIZE 0x108 class LegoROI : public ViewROI { public: - LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, MxTime p_time); + LegoROI(Tgl::Renderer* p_renderer); + LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList); + ~LegoROI() override; - virtual float IntrinsicImportance() const override; // vtable+0x4 - // Note: Actually part of parent class (doesn't exist yet) - virtual void UpdateWorldBoundingVolumes() override; // vtable+0x18 + float IntrinsicImportance() const override; // vtable+0x04 + void UpdateWorldBoundingVolumes() override; // vtable+0x18 - __declspec(dllexport) void SetDisplayBB(MxS32 p_displayBB); - __declspec(dllexport) static void configureLegoROI(MxS32 p_roi); + void SetDisplayBB(int p_displayBB); + static void configureLegoROI(int p_roi); static void SetSomeHandlerFunction(ROIHandler p_func); - static MxBool CallTheHandlerFunction( + static unsigned char CallTheHandlerFunction( char* p_param, - MxFloat& p_red, - MxFloat& p_green, - MxFloat& p_blue, - MxFloat& p_other + float& p_red, + float& p_green, + float& p_blue, + float& p_other ); - static MxBool ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green, MxFloat& p_blue, MxFloat& p_other); + static unsigned char ColorAliasLookup(char* p_param, float& p_red, float& p_green, float& p_blue, float& p_other); void WrappedSetLocalTransform(Matrix4& p_transform); void FUN_100a46b0(Matrix4& p_transform); void FUN_100a58f0(Matrix4& p_transform); + inline const char* GetName() const { return m_name; } inline LegoEntity* GetUnknown0x104() { return m_unk0x104; } + inline void SetUnknown0x104(LegoEntity* p_unk0x104) { m_unk0x104 = p_unk0x104; } - // SYNTHETIC: LEGO1 0x100a9ad0 + // SYNTHETIC: LEGO1 0x100a82b0 // LegoROI::`scalar deleting destructor' private: - undefined m_pad[0x24]; // 0xe0 - LegoEntity* m_unk0x104; // 0x104 - MxTime m_time; // 0x108 + int m_unk0xe0; // 0xe0 + LegoChar* m_name; // 0xe4 + BoundingSphere m_sphere; // 0xe8 + undefined4 m_unk0x100; // 0x100 + LegoEntity* m_unk0x104; // 0x104 +}; + +// VTABLE: LEGO1 0x100dbea8 +// SIZE 0x10c +class TimeROI : public LegoROI { +public: + TimeROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, int p_time); + + // SYNTHETIC: LEGO1 0x100a9ad0 + // TimeROI::`scalar deleting destructor' + +private: + int m_time; // 0x108 }; #endif // LEGOROI_H diff --git a/LEGO1/main.cpp b/LEGO1/main.cpp index f760aeae..260afb24 100644 --- a/LEGO1/main.cpp +++ b/LEGO1/main.cpp @@ -1,7 +1,7 @@ #include // FUNCTION: LEGO1 0x10091ee0 -__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { return TRUE; } diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index b2166ca1..ccfd6405 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -2,19 +2,28 @@ #include // for vsprintf +#if !defined(MXDIRECTX_FOR_CONFIG) DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4); DECOMP_SIZE_ASSERT(MxDirect3D, 0x894); -DECOMP_SIZE_ASSERT(MxDevice, 0x1a4); +#endif +DECOMP_SIZE_ASSERT(Direct3DDeviceInfo, 0x1a4); DECOMP_SIZE_ASSERT(MxDisplayMode, 0x0c); DECOMP_SIZE_ASSERT(MxDriver, 0x190); DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x14); +#if !defined(MXDIRECTX_FOR_CONFIG) +#define RELEASE(x) \ + if (x != NULL) { \ + x->Release(); \ + x = NULL; \ + } + // FUNCTION: LEGO1 0x1009b0a0 MxDirect3D::MxDirect3D() { this->m_pDirect3d = NULL; this->m_pDirect3dDevice = NULL; - this->m_unk0x88c = 0; + this->m_bTexturesDisabled = FALSE; this->m_assignedDevice = NULL; } @@ -50,11 +59,13 @@ BOOL MxDirect3D::Create( paletteEntryCount ); - if (ret && CreateIDirect3D() && D3DSetMode()) + if (ret && D3DCreate() && D3DSetMode()) { success = TRUE; + } - if (!success) + if (!success) { FUN_1009d920(); + } return success; } @@ -62,23 +73,17 @@ BOOL MxDirect3D::Create( // FUNCTION: LEGO1 0x1009b210 void MxDirect3D::Destroy() { - if (this->m_pDirect3dDevice) { - this->m_pDirect3dDevice->Release(); - this->m_pDirect3dDevice = NULL; - } - - if (this->m_pDirect3d) { - this->m_pDirect3d->Release(); - this->m_pDirect3d = NULL; - } + RELEASE(m_pDirect3dDevice); + RELEASE(m_pDirect3d); if (this->m_assignedDevice) { delete m_assignedDevice; this->m_assignedDevice = NULL; } - if (m_pCurrentDeviceModesList) + if (m_pCurrentDeviceModesList) { m_pCurrentDeviceModesList = NULL; + } MxDirectDraw::Destroy(); } @@ -86,27 +91,21 @@ void MxDirect3D::Destroy() // FUNCTION: LEGO1 0x1009b290 void MxDirect3D::DestroyButNotDirectDraw() { - if (this->m_pDirect3dDevice) { - this->m_pDirect3dDevice->Release(); - this->m_pDirect3dDevice = NULL; - } - if (this->m_pDirect3d) { - this->m_pDirect3d->Release(); - this->m_pDirect3d = NULL; - } + RELEASE(m_pDirect3dDevice); + RELEASE(m_pDirect3d); MxDirectDraw::DestroyButNotDirectDraw(); } // FUNCTION: LEGO1 0x1009b2d0 -BOOL MxDirect3D::CreateIDirect3D() +BOOL MxDirect3D::D3DCreate() { - HRESULT ret = IDirect3D_QueryInterface(m_pDirectDraw, IID_IDirect3D2, (LPVOID*) &m_pDirect3d); + HRESULT result; - if (ret) { - Error("Creation of IDirect3D failed", ret); + result = DirectDraw()->QueryInterface(IID_IDirect3D2, (LPVOID*) &m_pDirect3d); + if (result != DD_OK) { + Error("Creation of IDirect3D failed", result); return FALSE; } - return TRUE; } @@ -119,24 +118,28 @@ BOOL MxDirect3D::D3DSetMode() return FALSE; } - if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) - m_unk0x88c = FALSE; - else - m_unk0x88c = TRUE; + if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + m_bTexturesDisabled = FALSE; + } + else { + m_bTexturesDisabled = TRUE; + } - DWORD bitDepth = GetZBufferBitDepth(m_assignedDevice); - if (!CreateZBuffer(DDSCAPS_VIDEOMEMORY, bitDepth)) + if (!CreateZBuffer(DDSCAPS_VIDEOMEMORY, ZBufferDepth(m_assignedDevice))) { return FALSE; + } } else { - if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) - m_unk0x88c = FALSE; - else - m_unk0x88c = TRUE; + if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + m_bTexturesDisabled = FALSE; + } + else { + m_bTexturesDisabled = TRUE; + } - DWORD bitDepth = GetZBufferBitDepth(m_assignedDevice); - if (!CreateZBuffer(DDSCAPS_SYSTEMMEMORY, bitDepth)) + if (!CreateZBuffer(DDSCAPS_SYSTEMMEMORY, ZBufferDepth(m_assignedDevice))) { return FALSE; + } } HRESULT result = m_pDirect3d->CreateDevice(m_assignedDevice->m_guid, m_pBackBuffer, &m_pDirect3dDevice); @@ -148,9 +151,11 @@ BOOL MxDirect3D::D3DSetMode() MxDirectDraw::Mode mode = m_currentMode; - if (m_bFullScreen && !IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel)) { - Error("This device cannot support the current display mode", DDERR_GENERIC); - return FALSE; + if (IsFullScreen()) { + if (!IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel)) { + Error("This device cannot support the current display mode", DDERR_GENERIC); + return FALSE; + } } LPDIRECTDRAWSURFACE frontBuffer = m_pFrontBuffer; @@ -197,29 +202,39 @@ BOOL MxDirect3D::D3DSetMode() } // FUNCTION: LEGO1 0x1009b5a0 -DWORD MxDirect3D::GetZBufferBitDepth(MxAssignedDevice* p_assignedDevice) +int MxDirect3D::ZBufferDepth(MxAssignedDevice* p_assignedDevice) { - DWORD bitDepth; + int depth; + DWORD deviceDepth; - if (p_assignedDevice->m_desc.dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH) - bitDepth = p_assignedDevice->m_desc.dwDeviceZBufferBitDepth; - else - bitDepth = 0; + if (p_assignedDevice->m_desc.dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH) { + deviceDepth = p_assignedDevice->m_desc.dwDeviceZBufferBitDepth; + } + else { + deviceDepth = 0; + } - if (bitDepth & DDBD_32) - return 32; - if (bitDepth & DDBD_24) - return 24; - if (bitDepth & DDBD_16) - return 16; - if (bitDepth & DDBD_8) - return 8; + if (deviceDepth & DDBD_32) { + depth = 32; + } + else if (deviceDepth & DDBD_24) { + depth = 24; + } + else if (deviceDepth & DDBD_16) { + depth = 16; + } + else if (deviceDepth & DDBD_8) { + depth = 8; + } + else { + depth = -1; + } - return -1; + return depth; } // FUNCTION: LEGO1 0x1009b5f0 -BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, MxDevice* p_device) +BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device) { if (m_assignedDevice) { delete m_assignedDevice; @@ -264,13 +279,16 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri sizeof(assignedDevice->m_deviceInfo->m_ddcaps) ); - if (i == 0) + if (i == 0) { assignedDevice->m_flags |= MxAssignedDevice::c_primaryDevice; + } - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { - MxDevice& device = *it2; - if (&device != p_device) + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); + it2++) { + Direct3DDeviceInfo& device = *it2; + if (&device != p_device) { continue; + } memcpy(&assignedDevice->m_guid, device.m_guid, sizeof(assignedDevice->m_guid)); @@ -279,8 +297,9 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri assignedDevice->m_flags |= MxAssignedDevice::c_hardwareMode; desc = &device.m_HWDesc; } - else + else { desc = &device.m_HELDesc; + } memcpy(&assignedDevice->m_desc, desc, sizeof(assignedDevice->m_desc)); m_assignedDevice = assignedDevice; @@ -314,7 +333,9 @@ MxAssignedDevice::~MxAssignedDevice() m_deviceInfo = NULL; } } +#endif +// FUNCTION: CONFIG 0x00401180 // FUNCTION: LEGO1 0x1009ba80 MxDriver::MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { @@ -326,17 +347,22 @@ MxDriver::MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) Init(p_guid, p_driverDesc, p_driverName); } +// FUNCTION: CONFIG 0x401280 // FUNCTION: LEGO1 0x1009bb80 MxDriver::~MxDriver() { - if (m_guid) + if (m_guid) { delete m_guid; - if (m_driverDesc) + } + if (m_driverDesc) { delete[] m_driverDesc; - if (m_driverName) + } + if (m_driverName) { delete[] m_driverName; + } } +// FUNCTION: CONFIG 0x00401330 // FUNCTION: LEGO1 0x1009bc30 void MxDriver::Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { @@ -367,7 +393,7 @@ void MxDriver::Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) } // FUNCTION: LEGO1 0x1009bd20 -MxDevice::MxDevice( +Direct3DDeviceInfo::Direct3DDeviceInfo( LPGUID p_guid, LPSTR p_deviceDesc, LPSTR p_deviceName, @@ -377,22 +403,26 @@ MxDevice::MxDevice( { memset(this, 0, sizeof(*this)); - Init(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); + Initialize(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); } +// FUNCTION: CONFIG 0x401460 // FUNCTION: LEGO1 0x1009bd60 -MxDevice::~MxDevice() +Direct3DDeviceInfo::~Direct3DDeviceInfo() { - if (m_guid) + if (m_guid) { delete m_guid; - if (m_deviceDesc) + } + if (m_deviceDesc) { delete[] m_deviceDesc; - if (m_deviceName) + } + if (m_deviceName) { delete[] m_deviceName; + } } // FUNCTION: LEGO1 0x1009bda0 -void MxDevice::Init( +void Direct3DDeviceInfo::Initialize( LPGUID p_guid, LPSTR p_deviceDesc, LPSTR p_deviceName, @@ -425,19 +455,29 @@ void MxDevice::Init( strcpy(m_deviceName, p_deviceName); } - if (p_HWDesc) + if (p_HWDesc) { memcpy(&m_HWDesc, p_HWDesc, sizeof(m_HWDesc)); + } - if (p_HELDesc) + if (p_HELDesc) { memcpy(&m_HELDesc, p_HELDesc, sizeof(m_HELDesc)); + } } +// FUNCTION: CONFIG 0x004015c0 // FUNCTION: LEGO1 0x1009bec0 MxDeviceEnumerate::MxDeviceEnumerate() { m_initialized = FALSE; } +// FUNCTION: CONFIG 0x401710 +// FUNCTION: LEGO1 0x1009c010 +MxDeviceEnumerate::~MxDeviceEnumerate() +{ +} + +// FUNCTION: CONFIG 0x00401770 // FUNCTION: LEGO1 0x1009c070 BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) { @@ -456,25 +496,29 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc MxDriver& newDevice = m_list.back(); HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); - if (result != DD_OK) + if (result != DD_OK) { BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); + } else { lpDD->EnumDisplayModes(0, NULL, this, DisplayModesEnumerateCallback); newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); - if (result != DD_OK) + if (result != DD_OK) { BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); + } else { result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); - if (result != DD_OK) + if (result != DD_OK) { BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); + } else { result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); - if (result != DD_OK) + if (result != DD_OK) { BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + } else { if (newDevice.m_devices.empty()) { m_list.pop_back(); @@ -484,15 +528,18 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc } } - if (lpDirect3d2) + if (lpDirect3d2) { lpDirect3d2->Release(); + } - if (lpDD) + if (lpDD) { lpDD->Release(); + } return DDENUMRET_OK; } +// FUNCTION: CONFIG 0x00401bc0 // FUNCTION: LEGO1 0x1009c4c0 void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) { @@ -506,6 +553,7 @@ void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) OutputDebugString(buf); } +// FUNCTION: CONFIG 0x00401bf0 // FUNCTION: LEGO1 0x1009c4f0 HRESULT CALLBACK MxDeviceEnumerate::DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context) { @@ -513,6 +561,7 @@ HRESULT CALLBACK MxDeviceEnumerate::DisplayModesEnumerateCallback(LPDDSURFACEDES return deviceEnumerate->EnumDisplayModesCallback(p_ddsd); } +// FUNCTION: CONFIG 0x00401c10 // FUNCTION: LEGO1 0x1009c510 HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( LPGUID p_guid, @@ -527,6 +576,7 @@ HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( return deviceEnumerate->EnumDevicesCallback(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); } +// FUNCTION: CONFIG 0x00401c40 // FUNCTION: LEGO1 0x1009c540 HRESULT MxDeviceEnumerate::EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd) { @@ -539,6 +589,7 @@ HRESULT MxDeviceEnumerate::EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd) return DDENUMRET_OK; } +// FUNCTION: CONFIG 0x00401cd0 // FUNCTION: LEGO1 0x1009c5d0 HRESULT MxDeviceEnumerate::EnumDevicesCallback( LPGUID p_guid, @@ -548,17 +599,19 @@ HRESULT MxDeviceEnumerate::EnumDevicesCallback( LPD3DDEVICEDESC p_HELDesc ) { - MxDevice device(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); + Direct3DDeviceInfo device(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); m_list.back().m_devices.push_back(device); memset(&device, 0, sizeof(device)); return DDENUMRET_OK; } +// FUNCTION: CONFIG 0x00401dc0 // FUNCTION: LEGO1 0x1009c6c0 int MxDeviceEnumerate::DoEnumerate() { - if (m_initialized) + if (m_initialized) { return -1; + } HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); if (ret != DD_OK) { @@ -570,6 +623,7 @@ int MxDeviceEnumerate::DoEnumerate() return 0; } +// FUNCTION: CONFIG 0x00401e10 // FUNCTION: LEGO1 0x1009c710 BOOL CALLBACK MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context) @@ -578,45 +632,248 @@ MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc return deviceEnumerate->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); } -// STUB: LEGO1 0x1009c730 +// FUNCTION: CONFIG 0x00401e30 +// FUNCTION: LEGO1 0x1009c730 const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) { - // TODO: This is a list of error messages, similar to the function in - // MxDirectDraw, except that this one now contains the Direct3D errors. - // Probably just copied from a sample file in the dx5 sdk. - return ""; + switch (p_error) { + case DD_OK: + return "No error."; + case DDERR_GENERIC: + return "Generic failure."; + case DDERR_UNSUPPORTED: + return "Action not supported."; + case DDERR_INVALIDPARAMS: + return "One or more of the parameters passed to the function are incorrect."; + case DDERR_OUTOFMEMORY: + return "DirectDraw does not have enough memory to perform the operation."; + case DDERR_CANNOTATTACHSURFACE: + return "This surface can not be attached to the requested surface."; + case DDERR_ALREADYINITIALIZED: + return "This object is already initialized."; + case DDERR_CURRENTLYNOTAVAIL: + return "Support is currently not available."; + case DDERR_CANNOTDETACHSURFACE: + return "This surface can not be detached from the requested surface."; + case DDERR_HEIGHTALIGN: + return "Height of rectangle provided is not a multiple of reqd alignment."; + case DDERR_EXCEPTION: + return "An exception was encountered while performing the requested operation."; + case DDERR_INVALIDCAPS: + return "One or more of the caps bits passed to the callback are incorrect."; + case DDERR_INCOMPATIBLEPRIMARY: + return "Unable to match primary surface creation request with existing primary surface."; + case DDERR_INVALIDMODE: + return "DirectDraw does not support the requested mode."; + case DDERR_INVALIDCLIPLIST: + return "DirectDraw does not support the provided cliplist."; + case DDERR_INVALIDPIXELFORMAT: + return "The pixel format was invalid as specified."; + case DDERR_INVALIDOBJECT: + return "DirectDraw received a pointer that was an invalid DIRECTDRAW object."; + case DDERR_LOCKEDSURFACES: + return "Operation could not be carried out because one or more surfaces are locked."; + case DDERR_INVALIDRECT: + return "Rectangle provided was invalid."; + case DDERR_NOALPHAHW: + return "Operation could not be carried out because there is no alpha accleration hardware present or " + "available."; + case DDERR_NO3D: + return "There is no 3D present."; + case DDERR_NOCOLORCONVHW: + return "Operation could not be carried out because there is no color conversion hardware present or available."; + case DDERR_NOCLIPLIST: + return "No cliplist available."; + case DDERR_NOCOLORKEY: + return "Surface doesn't currently have a color key"; + case DDERR_NOCOOPERATIVELEVELSET: + return "Create function called without DirectDraw object method SetCooperativeLevel being called."; + case DDERR_NOEXCLUSIVEMODE: + return "Operation requires the application to have exclusive mode but the application does not have exclusive " + "mode."; + case DDERR_NOCOLORKEYHW: + return "Operation could not be carried out because there is no hardware support of the destination color key."; + case DDERR_NOGDI: + return "There is no GDI present."; + case DDERR_NOFLIPHW: + return "Flipping visible surfaces is not supported."; + case DDERR_NOTFOUND: + return "Requested item was not found."; + case DDERR_NOMIRRORHW: + return "Operation could not be carried out because there is no hardware present or available."; + case DDERR_NORASTEROPHW: + return "Operation could not be carried out because there is no appropriate raster op hardware present or " + "available."; + case DDERR_NOOVERLAYHW: + return "Operation could not be carried out because there is no overlay hardware present or available."; + case DDERR_NOSTRETCHHW: + return "Operation could not be carried out because there is no hardware support for stretching."; + case DDERR_NOROTATIONHW: + return "Operation could not be carried out because there is no rotation hardware present or available."; + case DDERR_NOTEXTUREHW: + return "Operation could not be carried out because there is no texture mapping hardware present or available."; + case DDERR_NOT4BITCOLOR: + return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color " + "palette."; + case DDERR_NOT4BITCOLORINDEX: + return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color " + "index palette."; + case DDERR_NOT8BITCOLOR: + return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color."; + case DDERR_NOZBUFFERHW: + return "Operation could not be carried out because there is no hardware support for zbuffer blitting."; + case DDERR_NOVSYNCHW: + return "Operation could not be carried out because there is no hardware support for vertical blank " + "synchronized operations."; + case DDERR_OUTOFCAPS: + return "The hardware needed for the requested operation has already been allocated."; + case DDERR_NOZOVERLAYHW: + return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support " + "z layering of overlays."; + case DDERR_COLORKEYNOTSET: + return "No src color key specified for this operation."; + case DDERR_OUTOFVIDEOMEMORY: + return "DirectDraw does not have enough memory to perform the operation."; + case DDERR_OVERLAYCANTCLIP: + return "The hardware does not support clipped overlays."; + case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: + return "Can only have ony color key active at one time for overlays."; + case DDERR_PALETTEBUSY: + return "Access to this palette is being refused because the palette is already locked by another thread."; + case DDERR_SURFACEALREADYDEPENDENT: + return "This surface is already a dependency of the surface it is being made a dependency of."; + case DDERR_SURFACEALREADYATTACHED: + return "This surface is already attached to the surface it is being attached to."; + case DDERR_SURFACEISOBSCURED: + return "Access to surface refused because the surface is obscured."; + case DDERR_SURFACEBUSY: + return "Access to this surface is being refused because the surface is already locked by another thread."; + case DDERR_SURFACENOTATTACHED: + return "The requested surface is not attached."; + case DDERR_SURFACELOST: + return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface " + "object representing this surface should have Restore called on it."; + case DDERR_TOOBIGSIZE: + return "Size requested by DirectDraw is too large, but the individual height and width are OK."; + case DDERR_TOOBIGHEIGHT: + return "Height requested by DirectDraw is too large."; + case DDERR_UNSUPPORTEDFORMAT: + return "FOURCC format requested is unsupported by DirectDraw."; + case DDERR_TOOBIGWIDTH: + return "Width requested by DirectDraw is too large."; + case DDERR_VERTICALBLANKINPROGRESS: + return "Vertical blank is in progress."; + case DDERR_UNSUPPORTEDMASK: + return "Bitmask in the pixel format requested is unsupported by DirectDraw."; + case DDERR_XALIGN: + return "Rectangle provided was not horizontally aligned on required boundary."; + case DDERR_WASSTILLDRAWING: + return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is " + "incomplete."; + case DDERR_INVALIDDIRECTDRAWGUID: + return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."; + case DDERR_DIRECTDRAWALREADYCREATED: + return "A DirectDraw object representing this driver has already been created for this process."; + case DDERR_NODIRECTDRAWHW: + return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware."; + case DDERR_PRIMARYSURFACEALREADYEXISTS: + return "This process already has created a primary surface."; + case DDERR_NOEMULATION: + return "Software emulation not available."; + case DDERR_REGIONTOOSMALL: + return "Region passed to Clipper::GetClipList is too small."; + case DDERR_CLIPPERISUSINGHWND: + return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."; + case DDERR_NOCLIPPERATTACHED: + return "No clipper object attached to surface object."; + case DDERR_NOHWND: + return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND."; + case DDERR_HWNDSUBCLASSED: + return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring " + "state."; + case DDERR_HWNDALREADYSET: + return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or " + "palettes created."; + case DDERR_NOPALETTEATTACHED: + return "No palette object attached to this surface."; + case DDERR_NOPALETTEHW: + return "No hardware support for 16 or 256 color palettes."; + case DDERR_BLTFASTCANTCLIP: + return "Return if a clipper object is attached to the source surface passed into a BltFast call."; + case DDERR_NOBLTHW: + return "No blitter hardware present."; + case DDERR_NODDROPSHW: + return "No DirectDraw ROP hardware."; + case DDERR_OVERLAYNOTVISIBLE: + return "Returned when GetOverlayPosition is called on a hidden overlay."; + case DDERR_NOOVERLAYDEST: + return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on " + "to establish a destination."; + case DDERR_INVALIDPOSITION: + return "Returned when the position of the overlay on the destination is no longer legal for that destination."; + case DDERR_NOTAOVERLAYSURFACE: + return "Returned when an overlay member is called for a non-overlay surface."; + case DDERR_EXCLUSIVEMODEALREADYSET: + return "An attempt was made to set the cooperative level when it was already set to exclusive."; + case DDERR_NOTFLIPPABLE: + return "An attempt has been made to flip a surface that is not flippable."; + case DDERR_CANTDUPLICATE: + return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."; + case DDERR_NOTLOCKED: + return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this " + "process, has been attempted."; + case DDERR_CANTCREATEDC: + return "Windows can not create any more DCs."; + case DDERR_NODC: + return "No DC was ever created for this surface."; + case DDERR_WRONGMODE: + return "This surface can not be restored because it was created in a different mode."; + case DDERR_IMPLICITLYCREATED: + return "This surface can not be restored because it is an implicitly created surface."; + case DDERR_NOTPALETTIZED: + return "The surface being used is not a palette-based surface."; + default: + return "Unrecognized error value."; + } } +// FUNCTION: CONFIG 0x00402560 // FUNCTION: LEGO1 0x1009ce60 int MxDeviceEnumerate::ParseDeviceName(const char* p_deviceId) { - if (!m_initialized) + if (!m_initialized) { return -1; + } int num = -1; int hex[4]; - if (sscanf(p_deviceId, "%d 0x%x 0x%x 0x%x 0x%x", &num, &hex[0], &hex[1], &hex[2], &hex[3]) != 5) + if (sscanf(p_deviceId, "%d 0x%x 0x%x 0x%x 0x%x", &num, &hex[0], &hex[1], &hex[2], &hex[3]) != 5) { return -1; + } - if (num < 0) + if (num < 0) { return -1; + } GUID guid; memcpy(&guid, hex, sizeof(guid)); int result = ProcessDeviceBytes(num, guid); - if (result < 0) + if (result < 0) { return ProcessDeviceBytes(-1, guid); + } return result; } +// FUNCTION: CONFIG 0x00402620 // FUNCTION: LEGO1 0x1009cf20 int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) { - if (!m_initialized) + if (!m_initialized) { return -1; + } int i = 0; int j = 0; @@ -634,18 +891,20 @@ int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) memcpy(&deviceGuid, &p_guid, sizeof(GUID4)); for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { - if (p_deviceNum >= 0 && p_deviceNum < i) + if (p_deviceNum >= 0 && p_deviceNum < i) { return -1; + } GUID4 compareGuid; MxDriver& driver = *it; - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { memcpy(&compareGuid, (*it2).m_guid, sizeof(GUID4)); if (compareGuid.m_data1 == deviceGuid.m_data1 && compareGuid.m_data2 == deviceGuid.m_data2 && compareGuid.m_data3 == deviceGuid.m_data3 && compareGuid.m_data4 == deviceGuid.m_data4 && - i == p_deviceNum) + i == p_deviceNum) { return j; + } j++; } @@ -656,8 +915,9 @@ int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) return -1; } +// FUNCTION: CONFIG 0x00402730 // FUNCTION: LEGO1 0x1009d030 -int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice*& p_device) +int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device) { if (p_deviceNum >= 0 && m_initialized) { int i = 0; @@ -665,7 +925,8 @@ int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice* for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { p_driver = &*it; - for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); it2++) { + for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); + it2++) { if (i == p_deviceNum) { p_device = &*it2; return 0; @@ -680,110 +941,217 @@ int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice* return -1; } +#if defined(MXDIRECTX_FOR_CONFIG) +// FUNCTION: CONFIG 0x004027d0 +int MxDeviceEnumerate::FormatDeviceName(char* p_buffer, const MxDriver* p_driver, const Direct3DDeviceInfo* p_device) + const +{ + int number = 0; + for (list::const_iterator it = m_list.begin(); it != m_list.end(); it++) { + if (&(*it) == p_driver) { + sprintf( + p_buffer, + "%d 0x%x 0x%x 0x%x 0x%x", + number, + ((DWORD*) (p_device->m_guid))[0], + ((DWORD*) (p_device->m_guid))[1], + ((DWORD*) (p_device->m_guid))[2], + ((DWORD*) (p_device->m_guid))[3] + ); + return 0; + } + number++; + } + return -1; +} +#endif + +// FUNCTION: CONFIG 0x00402860 // FUNCTION: LEGO1 0x1009d0d0 int MxDeviceEnumerate::FUN_1009d0d0() { - if (!m_initialized) + if (!m_initialized) { return -1; + } - if (m_list.empty()) + if (m_list.empty()) { return -1; + } int i = 0; int j = 0; int k = -1; - unsigned int und = FUN_1009d1a0(); + int cpu_mmx = SupportsMMX(); for (list::iterator it = m_list.begin();; it++) { - if (it == m_list.end()) + if (it == m_list.end()) { return k; + } - for (list::iterator it2 = (*it).m_devices.begin(); it2 != (*it).m_devices.end(); it2++) { - if ((*it2).m_HWDesc.dcmColorModel) + for (list::iterator it2 = (*it).m_devices.begin(); it2 != (*it).m_devices.end(); it2++) { + if ((*it2).m_HWDesc.dcmColorModel) { return j; + } - if ((und && (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_RGB && i == 0) || - (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_MONO && i == 0 && k < 0) + if ((cpu_mmx && (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_RGB && i == 0) || + ((*it2).m_HELDesc.dcmColorModel == D3DCOLOR_MONO && i == 0 && k < 0)) { k = j; + } j++; } i++; } - - return -1; } -// STUB: LEGO1 0x1009d1a0 -undefined4 MxDeviceEnumerate::FUN_1009d1a0() +// FUNCTION: CONFIG 0x00402930 +// FUNCTION: LEGO1 0x1009d1a0 +int MxDeviceEnumerate::SupportsMMX() { - return 1; + if (!SupportsCPUID()) { + return 0; + } + int supports_mmx; +#ifdef _MSC_VER + __asm { + mov eax, 0x0 ; EAX=0: Highest Function Parameter and Manufacturer ID +#if _MSC_VER > 1100 + cpuid ; Run CPUID +#else + __emit 0x0f + __emit 0xa2 +#endif + mov eax, 0x1 ; EAX=1: Processor Info and Feature Bits (unused) +#if _MSC_VER > 1100 + cpuid ; Run CPUID +#else + __emit 0x0f + __emit 0xa2 +#endif + xor eax, eax ; Zero EAX register + bt edx, 0x17 ; Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) + adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF + mov supports_mmx, eax ; Save eax into C variable + } +#else + __asm__("movl $0x0, %%eax\n\t" // EAX=0: Highest Function Parameter and Manufacturer ID + "cpuid\n\t" // Run CPUID\n" + "mov $0x1, %%eax\n\t" // EAX=1: Processor Info and Feature Bits (unused) + "cpuid\n\t" // Run CPUID + "xorl %%eax, %%eax\n\t" // Zero EAX register + "btl $0x15, %%edx\n\t" // Test bit 0x17 (23): MMX instructions (64-bit SIMD) (Store in CF) + "adc %%eax, %%eax" // Add with carry: EAX = EAX + EAX + CF = CF + : "=a"(supports_mmx) // supports_mmx == EAX + ); +#endif + return supports_mmx; } -// STUB: LEGO1 0x1009d1e0 -undefined4 MxDeviceEnumerate::FUN_1009d1e0() +// FUNCTION: CONFIG 0x00402970 +// FUNCTION: LEGO1 0x1009d1e0 +int MxDeviceEnumerate::SupportsCPUID() { - return 1; + int has_cpuid; +#ifdef _MSC_VER + __asm { + xor eax, eax ; Zero EAX register + pushfd ; Push EFLAGS register value on the stack + or dword ptr[esp], 0x200000 ; Set bit 0x200000: Able to use CPUID instruction (Pentium+) + popfd ; Write the updated value into the EFLAGS register + pushfd ; Push EFLAGS register value on the stack (again) + btr dword ptr[esp], 0x15 ; Test bit 0x15 (21) and reset (set CF) + adc eax, eax ; Add with carry: EAX = EAX + EAX + CF = CF + popfd ; Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) + mov has_cpuid, eax ; Save eax into C variable + } +#else + __asm__("xorl %%eax, %%eax\n\t" // Zero EAX register + "pushfl\n\t" // Push EFLAGS register value on the stack + "orl $0x200000, (%%esp)\n\t" // Set bit 0x200000: Able to use CPUID instruction (Pentium+) + "popfl\n\t" // Write the updated value into the EFLAGS register + "pushfl\n\t" // Push EFLAGS register value on the stack (again) + "btrl $0x15, (%%esp)\n\t" // Test bit 0x15 (21) and reset (set CF) + "adc %%eax, %%eax\n\t" // Add with carry: EAX = EAX + EAX + CF = CF + "popfl" // Push EFLAGS register value on the stack (again, and makes sure the stack remains the same) + : "=a"(has_cpuid) // has_cpuid == EAX + ); +#endif + return has_cpuid; } +// FUNCTION: CONFIG 0x004029a0 // FUNCTION: LEGO1 0x1009d210 int MxDeviceEnumerate::FUN_1009d210() { - if (!m_initialized) + if (!m_initialized) { return -1; + } for (list::iterator it = m_list.begin(); it != m_list.end();) { MxDriver& driver = *it; - if (!FUN_1009d370(driver)) + if (!DriverSupportsRequiredDisplayMode(driver)) { m_list.erase(it++); + } else { - for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { - MxDevice& device = *it2; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { + Direct3DDeviceInfo& device = *it2; - if (!FUN_1009d3d0(device)) + if (!FUN_1009d3d0(device)) { driver.m_devices.erase(it2++); - else + } + else { it2++; + } } - if (driver.m_devices.empty()) + if (driver.m_devices.empty()) { m_list.erase(it++); - else + } + else { it++; + } } } return m_list.empty() ? -1 : 0; } +// FUNCTION: CONFIG 0x00402b00 // FUNCTION: LEGO1 0x1009d370 -unsigned char MxDeviceEnumerate::FUN_1009d370(MxDriver& p_driver) +unsigned char MxDeviceEnumerate::DriverSupportsRequiredDisplayMode(MxDriver& p_driver) { for (list::iterator it = p_driver.m_displayModes.begin(); it != p_driver.m_displayModes.end(); it++) { if ((*it).m_width == 640 && (*it).m_height == 480) { - if ((*it).m_bitsPerPixel == 8 || (*it).m_bitsPerPixel == 16) + if ((*it).m_bitsPerPixel == 8 || (*it).m_bitsPerPixel == 16) { return TRUE; + } } } return FALSE; } +// FUNCTION: CONFIG 0x00402b60 // FUNCTION: LEGO1 0x1009d3d0 -unsigned char MxDeviceEnumerate::FUN_1009d3d0(MxDevice& p_device) +unsigned char MxDeviceEnumerate::FUN_1009d3d0(Direct3DDeviceInfo& p_device) { - if (m_list.size() <= 0) + if (m_list.size() <= 0) { return FALSE; + } - if (p_device.m_HWDesc.dcmColorModel) - return p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & 1; + if (p_device.m_HWDesc.dcmColorModel) { + return p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && + p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE; + } - for (list::iterator it = m_list.front().m_devices.begin(); it != m_list.front().m_devices.end(); it++) { - if ((&*it) == &p_device) + for (list::iterator it = m_list.front().m_devices.begin(); it != m_list.front().m_devices.end(); + it++) { + if ((&*it) == &p_device) { return TRUE; + } } return FALSE; diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index 2d89ad39..341f9c69 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -7,6 +7,7 @@ #include +#if !defined(MXDIRECTX_FOR_CONFIG) class MxDirect3D; // SIZE 0xe4 @@ -34,16 +35,16 @@ class MxAssignedDevice { class MxDeviceEnumerate; struct MxDriver; -struct MxDevice; +struct Direct3DDeviceInfo; // VTABLE: LEGO1 0x100db800 // SIZE 0x894 class MxDirect3D : public MxDirectDraw { public: MxDirect3D(); - virtual ~MxDirect3D(); + ~MxDirect3D() override; - virtual BOOL Create( + BOOL Create( HWND hWnd, BOOL fullscreen_1, BOOL surface_fullscreen, @@ -53,18 +54,21 @@ class MxDirect3D : public MxDirectDraw { int bpp, const PALETTEENTRY* pPaletteEntries, int paletteEntryCount - ) override; // vtable+0x04 - virtual void Destroy() override; // vtable+0x08 - virtual void DestroyButNotDirectDraw() override; // vtable+0x0c + ) override; // vtable+0x04 + void Destroy() override; // vtable+0x08 + void DestroyButNotDirectDraw() override; // vtable+0x0c - BOOL CreateIDirect3D(); + inline MxAssignedDevice* AssignedDevice() { return this->m_assignedDevice; } + inline IDirect3D2* Direct3D() { return this->m_pDirect3d; } + inline IDirect3DDevice2* Direct3DDevice() { return this->m_pDirect3dDevice; } + + BOOL SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, Direct3DDeviceInfo* p_device); + +protected: + BOOL D3DCreate(); BOOL D3DSetMode(); - DWORD GetZBufferBitDepth(MxAssignedDevice* p_assignedDevice); - BOOL SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, MxDevice* p_device); - inline MxAssignedDevice* GetAssignedDevice() { return this->m_assignedDevice; }; - inline IDirect3D2* GetDirect3D() { return this->m_pDirect3d; } - inline IDirect3DDevice2* GetDirect3DDevice() { return this->m_pDirect3dDevice; } + int ZBufferDepth(MxAssignedDevice* p_assignedDevice); // SYNTHETIC: LEGO1 0x1009b120 // MxDirect3D::`scalar deleting destructor' @@ -73,15 +77,16 @@ class MxDirect3D : public MxDirectDraw { MxAssignedDevice* m_assignedDevice; // 0x880 IDirect3D2* m_pDirect3d; // 0x884 IDirect3DDevice2* m_pDirect3dDevice; // 0x888 - BOOL m_unk0x88c; // 0x88c + BOOL m_bTexturesDisabled; // 0x88c undefined4 m_unk0x890; // 0x890 }; +#endif // SIZE 0x1a4 -struct MxDevice { - MxDevice() {} - ~MxDevice(); - MxDevice( +struct Direct3DDeviceInfo { + Direct3DDeviceInfo() {} + ~Direct3DDeviceInfo(); + Direct3DDeviceInfo( LPGUID p_guid, LPSTR p_deviceDesc, LPSTR p_deviceName, @@ -89,7 +94,7 @@ struct MxDevice { LPD3DDEVICEDESC p_HELDesc ); - void Init( + void Initialize( LPGUID p_guid, LPSTR p_deviceDesc, LPSTR p_deviceName, @@ -103,8 +108,8 @@ struct MxDevice { D3DDEVICEDESC m_HWDesc; // 0x0c D3DDEVICEDESC m_HELDesc; // 0xd8 - int operator==(MxDevice) const { return 0; } - int operator<(MxDevice) const { return 0; } + int operator==(Direct3DDeviceInfo) const { return 0; } + int operator<(Direct3DDeviceInfo) const { return 0; } }; // SIZE 0x0c @@ -129,7 +134,7 @@ struct MxDriver { char* m_driverDesc; // 0x04 char* m_driverName; // 0x08 DDCAPS m_ddCaps; // 0x0c - list m_devices; // 0x178 + list m_devices; // 0x178 list m_displayModes; // 0x184 int operator==(MxDriver) const { return 0; } @@ -137,36 +142,45 @@ struct MxDriver { }; // clang-format off +// TEMPLATE: CONFIG 0x401000 // TEMPLATE: LEGO1 0x1009b900 -// list >::~list > +// list >::~list > // clang-format on // clang-format off +// TEMPLATE: CONFIG 0x401070 // TEMPLATE: LEGO1 0x1009b970 // list >::~list > // clang-format on +// TEMPLATE: CONFIG 0x4010e0 // TEMPLATE: LEGO1 0x1009b9e0 -// List::~List +// List::~List +// TEMPLATE: CONFIG 0x401130 // TEMPLATE: LEGO1 0x1009ba30 // List::~List // clang-format off +// TEMPLATE: CONFIG 0x401650 // TEMPLATE: LEGO1 0x1009bf50 // list >::~list > // clang-format on +// TEMPLATE: CONFIG 0x4016c0 // TEMPLATE: LEGO1 0x1009bfc0 // List::~List // Compiler-generated copy ctor +// SYNTHETIC: CONFIG 0x401990 // SYNTHETIC: LEGO1 0x1009c290 // MxDriver::MxDriver +// SYNTHETIC: CONFIG 0x401b00 // SYNTHETIC: LEGO1 0x1009c400 -// list >::insert +// list >::insert +// SYNTHETIC: CONFIG 0x401b60 // SYNTHETIC: LEGO1 0x1009c460 // list >::insert @@ -174,15 +188,15 @@ struct MxDriver { // MxDriver::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x1009d470 -// MxDevice::`scalar deleting destructor' +// Direct3DDeviceInfo::`scalar deleting destructor' +// VTABLE: CONFIG 0x00406000 // VTABLE: LEGO1 0x100db814 // SIZE 0x14 class MxDeviceEnumerate { public: MxDeviceEnumerate(); - // FUNCTION: LEGO1 0x1009c010 - ~MxDeviceEnumerate() {} + ~MxDeviceEnumerate(); virtual int DoEnumerate(); // vtable+0x00 @@ -198,11 +212,16 @@ class MxDeviceEnumerate { const char* EnumerateErrorToString(HRESULT p_error); int ParseDeviceName(const char* p_deviceId); int ProcessDeviceBytes(int p_deviceNum, GUID& p_guid); - int GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice*& p_device); + int GetDevice(int p_deviceNum, MxDriver*& p_driver, Direct3DDeviceInfo*& p_device); + +#if defined(MXDIRECTX_FOR_CONFIG) + int FormatDeviceName(char* p_buffer, const MxDriver* p_driver, const Direct3DDeviceInfo* p_device) const; +#endif + int FUN_1009d0d0(); int FUN_1009d210(); - unsigned char FUN_1009d370(MxDriver& p_driver); - unsigned char FUN_1009d3d0(MxDevice& p_device); + unsigned char DriverSupportsRequiredDisplayMode(MxDriver& p_driver); + unsigned char FUN_1009d3d0(Direct3DDeviceInfo& p_device); static void BuildErrorString(const char*, ...); static BOOL CALLBACK @@ -216,11 +235,13 @@ class MxDeviceEnumerate { LPD3DDEVICEDESC p_HELDesc, LPVOID p_context ); - static undefined4 FUN_1009d1a0(); - static undefined4 FUN_1009d1e0(); + static int SupportsMMX(); + static int SupportsCPUID(); friend class MxDirect3D; + const list& GetDriverList() const { return m_list; } + private: list m_list; // 0x04 unsigned char m_initialized; // 0x10 diff --git a/LEGO1/mxdirectx/mxdirectdraw.cpp b/LEGO1/mxdirectx/mxdirectdraw.cpp index 7e78cf69..0b3d05ff 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.cpp +++ b/LEGO1/mxdirectx/mxdirectdraw.cpp @@ -5,6 +5,12 @@ DECOMP_SIZE_ASSERT(MxDirectDraw, 0x880); DECOMP_SIZE_ASSERT(MxDirectDraw::DeviceModesInfo, 0x17c); +#define RELEASE(x) \ + if (x != NULL) { \ + x->Release(); \ + x = NULL; \ + } + #ifndef DDSCAPS_3DDEVICE #define DDSCAPS_3DDEVICE 0x00002000l #endif @@ -75,7 +81,7 @@ int MxDirectDraw::GetPrimaryBitDepth() // FUNCTION: LEGO1 0x1009d5e0 BOOL MxDirectDraw::Create( HWND hWnd, - BOOL fullscreen_1, + BOOL fullscreen, BOOL surface_fullscreen, BOOL onlySystemMemory, int width, @@ -96,10 +102,9 @@ BOOL MxDirectDraw::Create( m_bFlipSurfaces = surface_fullscreen; m_bOnlySystemMemory = onlySystemMemory; m_bIsOnPrimaryDevice = !m_pCurrentDeviceModesList->m_guid; - BOOL fullscreen = 1; - if (m_bIsOnPrimaryDevice) { - fullscreen = fullscreen_1; + if (!m_bIsOnPrimaryDevice) { + fullscreen = TRUE; } if (!SetPaletteEntries(pPaletteEntries, paletteEntryCount, fullscreen)) { @@ -120,23 +125,19 @@ BOOL MxDirectDraw::Create( // FUNCTION: LEGO1 0x1009d690 BOOL MxDirectDraw::RecreateDirectDraw(GUID** ppGUID) { - if (m_pDirectDraw) { - m_pDirectDraw->Release(); - m_pDirectDraw = NULL; - } - + RELEASE(m_pDirectDraw); return (DirectDrawCreate(*ppGUID, &m_pDirectDraw, 0) == DD_OK); } // FUNCTION: LEGO1 0x1009d6c0 BOOL MxDirectDraw::CacheOriginalPaletteEntries() { - HDC dc; + HDC hdc; if (g_isPaletteIndexed8) { - dc = GetDC(0); - GetSystemPaletteEntries(dc, 0, _countof(m_originalPaletteEntries), m_originalPaletteEntries); - ReleaseDC(0, dc); + hdc = GetDC(NULL); + GetSystemPaletteEntries(hdc, 0, (1 << 8), &m_originalPaletteEntries[0]); + ReleaseDC(NULL, hdc); } return TRUE; } @@ -152,7 +153,7 @@ BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int pa if (g_isPaletteIndexed8) { hdc = GetDC(NULL); - GetSystemPaletteEntries(hdc, 0, arraySize, m_paletteEntries); + GetSystemPaletteEntries(hdc, 0, (1 << 8), m_paletteEntries); ReleaseDC(NULL, hdc); } @@ -168,20 +169,21 @@ BOOL MxDirectDraw::SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int pa m_paletteEntries[i].peFlags = 0x84; } - for (i = arraySize - reservedHighEntryCount; i < arraySize; i++) { + for (i = 256 - reservedHighEntryCount; i < 256; i++) { m_paletteEntries[i].peFlags = 0x80; } if (paletteEntryCount != 0) { - for (i = reservedLowEntryCount; (i < paletteEntryCount) && (i < arraySize - reservedHighEntryCount); i++) { + for (i = reservedLowEntryCount; (i < paletteEntryCount) && (i < 256 - reservedHighEntryCount); i++) { m_paletteEntries[i].peRed = pPaletteEntries[i].peRed; m_paletteEntries[i].peGreen = pPaletteEntries[i].peGreen; m_paletteEntries[i].peBlue = pPaletteEntries[i].peBlue; } } - if (m_pPalette != NULL) { + if (m_pPalette) { HRESULT result; + result = m_pPalette->SetEntries(0, 0, _countof(m_paletteEntries), m_paletteEntries); if (result != DD_OK) { Error("SetEntries failed", result); @@ -199,10 +201,7 @@ void MxDirectDraw::Destroy() FUN_1009d920(); - if (m_pDirectDraw != NULL) { - m_pDirectDraw->Release(); - m_pDirectDraw = NULL; - } + RELEASE(m_pDirectDraw); m_bIsOnPrimaryDevice = TRUE; @@ -217,47 +216,20 @@ void MxDirectDraw::DestroyButNotDirectDraw() { RestoreOriginalPaletteEntries(); if (m_bFullScreen) { - if (m_pDirectDraw != NULL) { + if (m_pDirectDraw) { m_bIgnoreWMSIZE = TRUE; m_pDirectDraw->RestoreDisplayMode(); m_bIgnoreWMSIZE = FALSE; } } - if (m_pPalette) { - m_pPalette->Release(); - m_pPalette = NULL; - } - - if (m_pClipper) { - m_pClipper->Release(); - m_pClipper = NULL; - } - - if (m_pText1Surface) { - m_pText1Surface->Release(); - m_pText1Surface = NULL; - } - - if (m_pText2Surface) { - m_pText2Surface->Release(); - m_pText2Surface = NULL; - } - - if (m_pZBuffer) { - m_pZBuffer->Release(); - m_pZBuffer = NULL; - } - - if (m_pBackBuffer) { - m_pBackBuffer->Release(); - m_pBackBuffer = NULL; - } - - if (m_pFrontBuffer) { - m_pFrontBuffer->Release(); - m_pFrontBuffer = NULL; - } + RELEASE(m_pPalette); + RELEASE(m_pClipper); + RELEASE(m_pText1Surface); + RELEASE(m_pText2Surface); + RELEASE(m_pZBuffer); + RELEASE(m_pBackBuffer); + RELEASE(m_pFrontBuffer); } // FUNCTION: LEGO1 0x1009d920 @@ -366,16 +338,18 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) DWORD dwStyle; if (!m_bIsOnPrimaryDevice) { - Error("Attempt made enter a windowed mode on a DirectDraw device that is not the primary display", E_FAIL); + Error( + "Attempt made enter a windowed mode on a DirectDraw device that is not the primary display", + DDERR_GENERIC + ); return FALSE; } m_bIgnoreWMSIZE = TRUE; dwStyle = GetWindowLong(m_hWndMain, GWL_STYLE); dwStyle &= ~WS_POPUP; - dwStyle |= WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPED; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME; SetWindowLong(m_hWndMain, GWL_STYLE, dwStyle); - SetRect(&rc, 0, 0, width - 1, height - 1); AdjustWindowRectEx( &rc, @@ -443,9 +417,13 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) } // FUNCTION: LEGO1 0x1009dd80 -HRESULT MxDirectDraw::CreateDDSurface(LPDDSURFACEDESC a2, LPDIRECTDRAWSURFACE* a3, IUnknown* a4) +HRESULT MxDirectDraw::CreateDDSurface( + LPDDSURFACEDESC p_lpDDSurfDesc, + LPDIRECTDRAWSURFACE FAR* p_lpDDSurface, + IUnknown FAR* p_pUnkOuter +) { - return m_pDirectDraw->CreateSurface(a2, a3, a4); + return m_pDirectDraw->CreateSurface(p_lpDDSurfDesc, p_lpDDSurface, p_pUnkOuter); } // FUNCTION: LEGO1 0x1009dda0 @@ -453,8 +431,8 @@ BOOL MxDirectDraw::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSU { HRESULT result; - memset(lpDDSurfDesc, 0, sizeof(*lpDDSurfDesc)); - lpDDSurfDesc->dwSize = sizeof(*lpDDSurfDesc); + memset(lpDDSurfDesc, 0, sizeof(DDSURFACEDESC)); + lpDDSurfDesc->dwSize = sizeof(DDSURFACEDESC); result = lpDDSurf->GetSurfaceDesc(lpDDSurfDesc); if (result != DD_OK) { Error("Error getting a surface description", result); @@ -467,25 +445,23 @@ BOOL MxDirectDraw::GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSU BOOL MxDirectDraw::DDCreateSurfaces() { HRESULT result; - DDSCAPS ddscaps; DDSURFACEDESC ddsd; + DDSCAPS ddscaps; if (m_bFlipSurfaces) { - memset(&ddsd, 0, sizeof(ddsd)); + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX; if (m_bOnlySystemMemory) { - ddsd.ddsCaps.dwCaps = - DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_SYSTEMMEMORY; + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; } ddsd.dwBackBufferCount = 1; - result = CreateDDSurface(&ddsd, &m_pFrontBuffer, 0); + result = CreateDDSurface(&ddsd, &m_pFrontBuffer, NULL); if (result != DD_OK) { Error("CreateSurface for front/back fullScreen buffer failed", result); return FALSE; } - ddscaps.dwCaps = DDSCAPS_BACKBUFFER; result = m_pFrontBuffer->GetAttachedSurface(&ddscaps, &m_pBackBuffer); if (result != DD_OK) { @@ -497,8 +473,8 @@ BOOL MxDirectDraw::DDCreateSurfaces() } } else { - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; result = CreateDDSurface(&ddsd, &m_pFrontBuffer, NULL); @@ -506,18 +482,18 @@ BOOL MxDirectDraw::DDCreateSurfaces() Error("CreateSurface for window front buffer failed", result); return FALSE; } + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.dwHeight = m_currentMode.height; ddsd.dwWidth = m_currentMode.width; - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; - if (m_bOnlySystemMemory) - ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY; + if (m_bOnlySystemMemory) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } result = CreateDDSurface(&ddsd, &m_pBackBuffer, NULL); if (result != DD_OK) { Error("CreateSurface for window back buffer failed", result); return FALSE; } - if (!GetDDSurfaceDesc(&ddsd, m_pBackBuffer)) { return FALSE; } @@ -589,7 +565,7 @@ BOOL MxDirectDraw::TextToTextSurface(const char* text, IDirectDrawSurface* pSurf RECT rc; size_t textLength; - if (pSurface == NULL) { + if (!pSurface) { return FALSE; } @@ -631,15 +607,14 @@ BOOL MxDirectDraw::CreateTextSurfaces() HRESULT result; DDCOLORKEY ddck; DDSURFACEDESC ddsd; - HDC dc; + HDC hdc; char dummyinfo[] = "000x000x00 (RAMP) 0000"; char dummyfps[] = "000.00 fps (000.00 fps (000.00 fps) 00000 tps)"; if (m_hFont != NULL) { DeleteObject(m_hFont); } - - m_hFont = CreateFontA( + m_hFont = CreateFont( m_currentMode.width <= 600 ? 12 : 24, 0, 0, @@ -656,27 +631,26 @@ BOOL MxDirectDraw::CreateTextSurfaces() "Arial" ); - dc = GetDC(NULL); - SelectObject(dc, m_hFont); - GetTextExtentPointA(dc, dummyfps, strlen(dummyfps), &m_text1SizeOnSurface); - GetTextExtentPointA(dc, dummyinfo, strlen(dummyinfo), &m_text2SizeOnSurface); - ReleaseDC(NULL, dc); + hdc = GetDC(NULL); + SelectObject(hdc, m_hFont); + GetTextExtentPoint(hdc, dummyfps, strlen(dummyfps), &m_text1SizeOnSurface); + GetTextExtentPoint(hdc, dummyinfo, strlen(dummyinfo), &m_text2SizeOnSurface); + ReleaseDC(NULL, hdc); memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - if (m_bOnlySystemMemory) - ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + if (m_bOnlySystemMemory) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } ddsd.dwHeight = m_text1SizeOnSurface.cy; ddsd.dwWidth = m_text1SizeOnSurface.cx; - - result = CreateDDSurface(&ddsd, &m_pText1Surface, 0); + result = CreateDDSurface(&ddsd, &m_pText1Surface, NULL); if (result != DD_OK) { Error("CreateSurface for text surface 1 failed", result); return FALSE; } - memset(&ddck, 0, sizeof(ddck)); m_pText1Surface->SetColorKey(DDCKEY_SRCBLT, &ddck); if (!TextToTextSurface1(dummyfps)) { @@ -687,17 +661,16 @@ BOOL MxDirectDraw::CreateTextSurfaces() ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - if (m_bOnlySystemMemory) - ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + if (m_bOnlySystemMemory) { + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } ddsd.dwHeight = m_text2SizeOnSurface.cy; ddsd.dwWidth = m_text2SizeOnSurface.cx; - - result = CreateDDSurface(&ddsd, &m_pText2Surface, 0); + result = CreateDDSurface(&ddsd, &m_pText2Surface, NULL); if (result != DD_OK) { Error("CreateSurface for text surface 2 failed", result); return FALSE; } - memset(&ddck, 0, sizeof(ddck)); m_pText2Surface->SetColorKey(DDCKEY_SRCBLT, &ddck); if (!TextToTextSurface2(dummyinfo)) { @@ -774,13 +747,13 @@ BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth) memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH; ddsd.dwHeight = m_currentMode.height; ddsd.dwWidth = m_currentMode.width; ddsd.dwZBufferBitDepth = depth; - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH; ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | memorytype; - result = CreateDDSurface(&ddsd, &lpZBuffer, 0); + if (result != DD_OK) { Error("CreateSurface for fullScreen Z-buffer failed", result); return FALSE; @@ -797,10 +770,10 @@ BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth) } // FUNCTION: LEGO1 0x1009e6a0 -int MxDirectDraw::Pause(int p_increment) +int MxDirectDraw::Pause(BOOL p_pause) { - if (p_increment) { - m_pauseCount++; + if (p_pause) { + ++m_pauseCount; if (m_pauseCount > 1) { return TRUE; @@ -820,11 +793,13 @@ int MxDirectDraw::Pause(int p_increment) } } else { - m_pauseCount--; + --m_pauseCount; + if (m_pauseCount > 0) { return TRUE; } - else if (m_pauseCount < 0) { + + if (m_pauseCount < 0) { m_pauseCount = 0; } @@ -839,11 +814,13 @@ int MxDirectDraw::Pause(int p_increment) // FUNCTION: LEGO1 0x1009e750 BOOL MxDirectDraw::RestorePaletteEntries() { - HRESULT result; if (m_bFullScreen && m_bPrimaryPalettized) { if (m_pPalette) { - result = m_pPalette->SetEntries(0, 0, _countof(m_paletteEntries), m_paletteEntries); + HRESULT result; + + result = + m_pPalette->SetEntries(0, 0, sizeof(m_paletteEntries) / sizeof(m_paletteEntries[0]), m_paletteEntries); if (result != DD_OK) { Error("SetEntries failed", result); return FALSE; @@ -857,11 +834,16 @@ BOOL MxDirectDraw::RestorePaletteEntries() // FUNCTION: LEGO1 0x1009e7a0 BOOL MxDirectDraw::RestoreOriginalPaletteEntries() { - HRESULT result; - if (m_bPrimaryPalettized) { if (m_pPalette) { - result = m_pPalette->SetEntries(0, 0, 256, m_originalPaletteEntries); + HRESULT result; + + result = m_pPalette->SetEntries( + 0, + 0, + sizeof(m_originalPaletteEntries) / sizeof(m_originalPaletteEntries[0]), + m_originalPaletteEntries + ); if (result != DD_OK) { Error("SetEntries failed", result); return FALSE; @@ -875,17 +857,18 @@ BOOL MxDirectDraw::RestoreOriginalPaletteEntries() // FUNCTION: LEGO1 0x1009e7f0 int MxDirectDraw::FlipToGDISurface() { - HRESULT ret; if (m_pDirectDraw) { - ret = m_pDirectDraw->FlipToGDISurface(); - if (ret != DD_OK) { - Error("FlipToGDISurface failed", ret); + HRESULT result; + + result = m_pDirectDraw->FlipToGDISurface(); + if (result != DD_OK) { + Error("FlipToGDISurface failed", result); } - return !ret; + return (result == DD_OK); } - return 1; + return TRUE; } // FUNCTION: LEGO1 0x1009e830 @@ -908,208 +891,208 @@ const char* MxDirectDraw::ErrorToString(HRESULT p_error) { switch (p_error) { case DD_OK: - return "No error.\0"; + return "No error."; case DDERR_ALREADYINITIALIZED: - return "This object is already initialized.\0"; + return "This object is already initialized."; case DDERR_BLTFASTCANTCLIP: - return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0"; + return "Return if a clipper object is attached to the source surface passed into a BltFast call."; case DDERR_CANNOTATTACHSURFACE: - return "This surface can not be attached to the requested surface.\0"; + return "This surface can not be attached to the requested surface."; case DDERR_CANNOTDETACHSURFACE: - return "This surface can not be detached from the requested surface.\0"; + return "This surface can not be detached from the requested surface."; case DDERR_CANTCREATEDC: - return "Windows can not create any more DCs.\0"; + return "Windows can not create any more DCs."; case DDERR_CANTDUPLICATE: - return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0"; + return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created."; case DDERR_CLIPPERISUSINGHWND: - return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0"; + return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd."; case DDERR_COLORKEYNOTSET: - return "No src color key specified for this operation.\0"; + return "No src color key specified for this operation."; case DDERR_CURRENTLYNOTAVAIL: - return "Support is currently not available.\0"; + return "Support is currently not available."; case DDERR_DIRECTDRAWALREADYCREATED: - return "A DirectDraw object representing this driver has already been created for this process.\0"; + return "A DirectDraw object representing this driver has already been created for this process."; case DDERR_EXCEPTION: - return "An exception was encountered while performing the requested operation.\0"; + return "An exception was encountered while performing the requested operation."; case DDERR_EXCLUSIVEMODEALREADYSET: - return "An attempt was made to set the cooperative level when it was already set to exclusive.\0"; + return "An attempt was made to set the cooperative level when it was already set to exclusive."; case DDERR_GENERIC: - return "Generic failure.\0"; + return "Generic failure."; case DDERR_HEIGHTALIGN: - return "Height of rectangle provided is not a multiple of reqd alignment.\0"; + return "Height of rectangle provided is not a multiple of reqd alignment."; case DDERR_HWNDALREADYSET: return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or " - "palettes created.\0"; + "palettes created."; case DDERR_HWNDSUBCLASSED: return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring " - "state.\0"; + "state."; case DDERR_IMPLICITLYCREATED: - return "This surface can not be restored because it is an implicitly created surface.\0"; + return "This surface can not be restored because it is an implicitly created surface."; case DDERR_INCOMPATIBLEPRIMARY: - return "Unable to match primary surface creation request with existing primary surface.\0"; + return "Unable to match primary surface creation request with existing primary surface."; case DDERR_INVALIDCAPS: - return "One or more of the caps bits passed to the callback are incorrect.\0"; + return "One or more of the caps bits passed to the callback are incorrect."; case DDERR_INVALIDCLIPLIST: - return "DirectDraw does not support the provided cliplist.\0"; + return "DirectDraw does not support the provided cliplist."; case DDERR_INVALIDDIRECTDRAWGUID: - return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0"; + return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier."; case DDERR_INVALIDMODE: - return "DirectDraw does not support the requested mode.\0"; + return "DirectDraw does not support the requested mode."; case DDERR_INVALIDOBJECT: - return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0"; + return "DirectDraw received a pointer that was an invalid DIRECTDRAW object."; case DDERR_INVALIDPARAMS: - return "One or more of the parameters passed to the function are incorrect.\0"; + return "One or more of the parameters passed to the function are incorrect."; case DDERR_INVALIDPIXELFORMAT: - return "The pixel format was invalid as specified.\0"; + return "The pixel format was invalid as specified."; case DDERR_INVALIDPOSITION: return "Returned when the position of the overlay on the destination is no longer legal for that " - "destination.\0"; + "destination."; case DDERR_INVALIDRECT: - return "Rectangle provided was invalid.\0"; + return "Rectangle provided was invalid."; case DDERR_LOCKEDSURFACES: - return "Operation could not be carried out because one or more surfaces are locked.\0"; + return "Operation could not be carried out because one or more surfaces are locked."; case DDERR_NO3D: - return "There is no 3D present.\0"; + return "There is no 3D present."; case DDERR_NOALPHAHW: return "Operation could not be carried out because there is no alpha accleration hardware present or " - "available.\0"; + "available."; case DDERR_NOBLTHW: - return "No blitter hardware present.\0"; + return "No blitter hardware present."; case DDERR_NOCLIPLIST: - return "No cliplist available.\0"; + return "No cliplist available."; case DDERR_NOCLIPPERATTACHED: - return "No clipper object attached to surface object.\0"; + return "No clipper object attached to surface object."; case DDERR_NOCOLORCONVHW: return "Operation could not be carried out because there is no color conversion hardware present or " - "available.\0"; + "available."; case DDERR_NOCOLORKEY: - return "Surface doesn't currently have a color key\0"; + return "Surface doesn't currently have a color key"; case DDERR_NOCOLORKEYHW: return "Operation could not be carried out because there is no hardware support of the destination color " - "key.\0"; + "key."; case DDERR_NOCOOPERATIVELEVELSET: - return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0"; + return "Create function called without DirectDraw object method SetCooperativeLevel being called."; case DDERR_NODC: - return "No DC was ever created for this surface.\0"; + return "No DC was ever created for this surface."; case DDERR_NODDROPSHW: - return "No DirectDraw ROP hardware.\0"; + return "No DirectDraw ROP hardware."; case DDERR_NODIRECTDRAWHW: return "A hardware-only DirectDraw object creation was attempted but the driver did not support any " - "hardware.\0"; + "hardware."; case DDERR_NOEMULATION: - return "Software emulation not available.\0"; + return "Software emulation not available."; case DDERR_NOEXCLUSIVEMODE: return "Operation requires the application to have exclusive mode but the application does not have exclusive " - "mode.\0"; + "mode."; case DDERR_NOFLIPHW: - return "Flipping visible surfaces is not supported.\0"; + return "Flipping visible surfaces is not supported."; case DDERR_NOGDI: - return "There is no GDI present.\0"; + return "There is no GDI present."; case DDERR_NOHWND: return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel " - "HWND.\0"; + "HWND."; case DDERR_NOMIRRORHW: - return "Operation could not be carried out because there is no hardware present or available.\0"; + return "Operation could not be carried out because there is no hardware present or available."; case DDERR_NOOVERLAYDEST: return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on " - "to establish a destination.\0"; + "to establish a destination."; case DDERR_NOOVERLAYHW: - return "Operation could not be carried out because there is no overlay hardware present or available.\0"; + return "Operation could not be carried out because there is no overlay hardware present or available."; case DDERR_NOPALETTEATTACHED: - return "No palette object attached to this surface.\0"; + return "No palette object attached to this surface."; case DDERR_NOPALETTEHW: - return "No hardware support for 16 or 256 color palettes.\0"; + return "No hardware support for 16 or 256 color palettes."; case DDERR_NORASTEROPHW: return "Operation could not be carried out because there is no appropriate raster op hardware present or " - "available.\0"; + "available."; case DDERR_NOROTATIONHW: - return "Operation could not be carried out because there is no rotation hardware present or available.\0"; + return "Operation could not be carried out because there is no rotation hardware present or available."; case DDERR_NOSTRETCHHW: - return "Operation could not be carried out because there is no hardware support for stretching.\0"; + return "Operation could not be carried out because there is no hardware support for stretching."; case DDERR_NOT4BITCOLOR: return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color " - "palette.\0"; + "palette."; case DDERR_NOT4BITCOLORINDEX: return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color " - "index palette.\0"; + "index palette."; case DDERR_NOT8BITCOLOR: - return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0"; + return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color."; case DDERR_NOTAOVERLAYSURFACE: - return "Returned when an overlay member is called for a non-overlay surface.\0"; + return "Returned when an overlay member is called for a non-overlay surface."; case DDERR_NOTEXTUREHW: return "Operation could not be carried out because there is no texture mapping hardware present or " - "available.\0"; + "available."; case DDERR_NOTFLIPPABLE: - return "An attempt has been made to flip a surface that is not flippable.\0"; + return "An attempt has been made to flip a surface that is not flippable."; case DDERR_NOTFOUND: - return "Requested item was not found.\0"; + return "Requested item was not found."; case DDERR_NOTLOCKED: return "Surface was not locked. An attempt to unlock a surface that was not locked at all, or by this " - "process, has been attempted.\0"; + "process, has been attempted."; case DDERR_NOTPALETTIZED: - return "The surface being used is not a palette-based surface.\0"; + return "The surface being used is not a palette-based surface."; case DDERR_NOVSYNCHW: return "Operation could not be carried out because there is no hardware support for vertical blank " - "synchronized operations.\0"; + "synchronized operations."; case DDERR_NOZBUFFERHW: - return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0"; + return "Operation could not be carried out because there is no hardware support for zbuffer blitting."; case DDERR_NOZOVERLAYHW: return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support " - "z layering of overlays.\0"; + "z layering of overlays."; case DDERR_OUTOFCAPS: - return "The hardware needed for the requested operation has already been allocated.\0"; + return "The hardware needed for the requested operation has already been allocated."; case DDERR_OUTOFMEMORY: - return "DirectDraw does not have enough memory to perform the operation.\0"; + return "DirectDraw does not have enough memory to perform the operation."; case DDERR_OUTOFVIDEOMEMORY: - return "DirectDraw does not have enough memory to perform the operation.\0"; + return "DirectDraw does not have enough memory to perform the operation."; case DDERR_OVERLAYCANTCLIP: - return "The hardware does not support clipped overlays.\0"; + return "The hardware does not support clipped overlays."; case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: - return "Can only have ony color key active at one time for overlays.\0"; + return "Can only have ony color key active at one time for overlays."; case DDERR_OVERLAYNOTVISIBLE: - return "Returned when GetOverlayPosition is called on a hidden overlay.\0"; + return "Returned when GetOverlayPosition is called on a hidden overlay."; case DDERR_PALETTEBUSY: - return "Access to this palette is being refused because the palette is already locked by another thread.\0"; + return "Access to this palette is being refused because the palette is already locked by another thread."; case DDERR_PRIMARYSURFACEALREADYEXISTS: - return "This process already has created a primary surface.\0"; + return "This process already has created a primary surface."; case DDERR_REGIONTOOSMALL: - return "Region passed to Clipper::GetClipList is too small.\0"; + return "Region passed to Clipper::GetClipList is too small."; case DDERR_SURFACEALREADYATTACHED: - return "This surface is already attached to the surface it is being attached to.\0"; + return "This surface is already attached to the surface it is being attached to."; case DDERR_SURFACEALREADYDEPENDENT: - return "This surface is already a dependency of the surface it is being made a dependency of.\0"; + return "This surface is already a dependency of the surface it is being made a dependency of."; case DDERR_SURFACEBUSY: - return "Access to this surface is being refused because the surface is already locked by another thread.\0"; + return "Access to this surface is being refused because the surface is already locked by another thread."; case DDERR_SURFACEISOBSCURED: - return "Access to surface refused because the surface is obscured.\0"; + return "Access to surface refused because the surface is obscured."; case DDERR_SURFACELOST: return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface " - "object representing this surface should have Restore called on it.\0"; + "object representing this surface should have Restore called on it."; case DDERR_SURFACENOTATTACHED: - return "The requested surface is not attached.\0"; + return "The requested surface is not attached."; case DDERR_TOOBIGHEIGHT: - return "Height requested by DirectDraw is too large.\0"; + return "Height requested by DirectDraw is too large."; case DDERR_TOOBIGSIZE: - return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0"; + return "Size requested by DirectDraw is too large, but the individual height and width are OK."; case DDERR_TOOBIGWIDTH: - return "Width requested by DirectDraw is too large.\0"; + return "Width requested by DirectDraw is too large."; case DDERR_UNSUPPORTED: - return "Action not supported.\0"; + return "Action not supported."; case DDERR_UNSUPPORTEDFORMAT: - return "FOURCC format requested is unsupported by DirectDraw.\0"; + return "FOURCC format requested is unsupported by DirectDraw."; case DDERR_UNSUPPORTEDMASK: - return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0"; + return "Bitmask in the pixel format requested is unsupported by DirectDraw."; case DDERR_VERTICALBLANKINPROGRESS: - return "Vertical blank is in progress.\0"; + return "Vertical blank is in progress."; case DDERR_WASSTILLDRAWING: return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is " - "incomplete.\0"; + "incomplete."; case DDERR_WRONGMODE: - return "This surface can not be restored because it was created in a different mode.\0"; + return "This surface can not be restored because it was created in a different mode."; case DDERR_XALIGN: - return "Rectangle provided was not horizontally aligned on required boundary.\0"; + return "Rectangle provided was not horizontally aligned on required boundary."; default: - return "Unrecognized error value.\0"; + return "Unrecognized error value."; } } diff --git a/LEGO1/mxdirectx/mxdirectdraw.h b/LEGO1/mxdirectx/mxdirectdraw.h index b8f5f551..61c92ae0 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.h +++ b/LEGO1/mxdirectx/mxdirectdraw.h @@ -34,9 +34,7 @@ class MxDirectDraw { void* m_unk0x178; // 0x178 }; - __declspec(dllexport) int FlipToGDISurface(); - __declspec(dllexport) static int GetPrimaryBitDepth(); - __declspec(dllexport) int Pause(int); + static int GetPrimaryBitDepth(); MxDirectDraw(); virtual ~MxDirectDraw(); @@ -51,38 +49,50 @@ class MxDirectDraw { int bpp, const PALETTEENTRY* pPaletteEntries, int paletteEntryCount - ); // vtable+0x04 - virtual void Destroy(); // vtable+0x08 - virtual void DestroyButNotDirectDraw(); // vtable+0x0c - virtual const char* ErrorToString(HRESULT p_error); // vtable+0x10 + ); // vtable+0x04 + virtual void Destroy(); // vtable+0x08 + virtual void DestroyButNotDirectDraw(); // vtable+0x0c - BOOL CacheOriginalPaletteEntries(); - HRESULT CreateDDSurface(LPDDSURFACEDESC a2, LPDIRECTDRAWSURFACE* a3, IUnknown* a4); - BOOL CreateTextSurfaces(); - BOOL CreateZBuffer(DWORD memorytype, DWORD depth); - BOOL DDCreateSurfaces(); - BOOL DDInit(BOOL fullscreen); - BOOL DDSetMode(int width, int height, int bpp); - void Error(const char* p_message, int p_error); + inline IDirectDraw* DirectDraw() { return m_pDirectDraw; } + inline IDirectDrawSurface* FrontBuffer() { return m_pFrontBuffer; } + inline IDirectDrawSurface* BackBuffer() { return m_pBackBuffer; } + inline IDirectDrawClipper* Clipper() { return m_pClipper; } + + BOOL IsFullScreen() { return m_bFullScreen; } - BOOL GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf); BOOL IsSupportedMode(int width, int height, int bpp); - BOOL RecreateDirectDraw(GUID** a2); - BOOL RestoreOriginalPaletteEntries(); - BOOL RestorePaletteEntries(); + + int Pause(BOOL); BOOL RestoreSurfaces(); - BOOL SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int paletteEntryCount, BOOL fullscreen); - BOOL TextToTextSurface(const char* text, IDirectDrawSurface* pSurface, SIZE& textSizeOnSurface); + BOOL TextToTextSurface1(const char* text); BOOL TextToTextSurface2(const char* lpString); + + virtual const char* ErrorToString(HRESULT p_error); // vtable+0x10 + int FlipToGDISurface(); + +protected: + BOOL SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int paletteEntryCount, BOOL fullscreen); + BOOL CacheOriginalPaletteEntries(); + BOOL RestoreOriginalPaletteEntries(); + BOOL RestorePaletteEntries(); + + BOOL DDInit(BOOL fullscreen); + BOOL DDSetMode(int width, int height, int bpp); + BOOL DDCreateSurfaces(); + HRESULT CreateDDSurface(LPDDSURFACEDESC a2, LPDIRECTDRAWSURFACE* a3, IUnknown* a4); + BOOL GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf); + BOOL CreateZBuffer(DWORD memorytype, DWORD depth); + + BOOL CreateTextSurfaces(); + BOOL TextToTextSurface(const char* text, IDirectDrawSurface* pSurface, SIZE& textSizeOnSurface); + + void Error(const char* p_message, int p_error); + + BOOL RecreateDirectDraw(GUID** a2); void FUN_1009e020(); void FUN_1009d920(); - inline IDirectDraw* GetDirectDraw() { return m_pDirectDraw; } - inline IDirectDrawSurface* GetFrontBuffer() { return m_pFrontBuffer; } - inline IDirectDrawSurface* GetBackBuffer() { return m_pBackBuffer; } - inline IDirectDrawClipper* GetClipper() { return m_pClipper; } - // SYNTHETIC: LEGO1 0x1009d510 // MxDirectDraw::`scalar deleting destructor' diff --git a/LEGO1/mxdirectx/mxstopwatch.h b/LEGO1/mxdirectx/mxstopwatch.h index 0630d2f6..5a86b283 100644 --- a/LEGO1/mxdirectx/mxstopwatch.h +++ b/LEGO1/mxdirectx/mxstopwatch.h @@ -3,6 +3,7 @@ #include "assert.h" +#include // ULONG_MAX #include #include diff --git a/LEGO1/mxgeometry/mxgeometry3d.cpp b/LEGO1/mxgeometry/mxgeometry3d.cpp deleted file mode 100644 index 03ce60eb..00000000 --- a/LEGO1/mxgeometry/mxgeometry3d.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "mxgeometry3d.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(Mx3DPointFloat, 0x14); -DECOMP_SIZE_ASSERT(Mx4DPointFloat, 0x18); diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 13781722..bdb3f191 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -15,6 +15,12 @@ class Mx3DPointFloat : public Vector3 { m_elements[2] = p_z; } + // FUNCTION: LEGO1 0x100343a0 + inline Mx3DPointFloat(const Mx3DPointFloat& p_other) : Vector3(m_elements) { EqualsImpl(p_other.m_data); } + + // SYNTHETIC: LEGO1 0x1001d170 + // Mx3DPointFloat::Mx3DPointFloat + // FUNCTION: LEGO1 0x10003c10 virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88 @@ -25,8 +31,9 @@ class Mx3DPointFloat : public Vector3 { float* dest = m_elements; const float* src = p_other.m_elements; - for (size_t i = sizeof(m_elements) / sizeof(float); i > 0; --i) + for (size_t i = sizeof(m_elements) / sizeof(float); i > 0; --i) { *dest++ = *src++; + } } inline void EqualsCross(Mx3DPointFloat& p_a, Mx3DPointFloat& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } diff --git a/LEGO1/mxgeometry/mxmatrix.cpp b/LEGO1/mxgeometry/mxmatrix.cpp deleted file mode 100644 index fc768f38..00000000 --- a/LEGO1/mxgeometry/mxmatrix.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "mxmatrix.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(MxMatrix, 0x48); diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h index 3ae03404..81cdaa2c 100644 --- a/LEGO1/mxgeometry/mxmatrix.h +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -11,7 +11,7 @@ class MxMatrix : public Matrix4 { inline MxMatrix(const MxMatrix& p_matrix) : Matrix4(m_elements) { Equals(p_matrix); } // FUNCTION: LEGO1 0x10002850 - virtual void operator=(const Matrix4& p_matrix) { Equals(p_matrix); } // vtable+0x28 + void operator=(const Matrix4& p_matrix) override { Equals(p_matrix); } // vtable+0x28 // No idea why there's another equals. Maybe to some other type like the // DirectX Retained Mode Matrix type which is also a float* alias? diff --git a/LEGO1/mxstl/stlcompat.h b/LEGO1/mxstl/stlcompat.h index 29c31549..c6f525bd 100644 --- a/LEGO1/mxstl/stlcompat.h +++ b/LEGO1/mxstl/stlcompat.h @@ -12,9 +12,11 @@ #include #include #include +#include #include using std::list; using std::map; +using std::pair; using std::set; using std::vector; #endif diff --git a/LEGO1/omni/include/mxactionnotificationparam.h b/LEGO1/omni/include/mxactionnotificationparam.h index 5628cf7b..96c44a93 100644 --- a/LEGO1/omni/include/mxactionnotificationparam.h +++ b/LEGO1/omni/include/mxactionnotificationparam.h @@ -21,8 +21,9 @@ class MxActionNotificationParam : public MxNotificationParam { MxDSAction* oldAction = p_action; this->m_realloc = p_reallocAction; - if (p_reallocAction) + if (p_reallocAction) { this->m_action = new MxDSAction(); + } else { this->m_action = oldAction; return; @@ -34,25 +35,27 @@ class MxActionNotificationParam : public MxNotificationParam { } // FUNCTION: LEGO1 0x10051050 - inline virtual ~MxActionNotificationParam() override + inline ~MxActionNotificationParam() override { - if (!this->m_realloc) + if (!this->m_realloc) { return; + } - if (this->m_action) + if (this->m_action) { delete this->m_action; + } } // FUNCTION: LEGO1 0x100510c0 - virtual MxNotificationParam* Clone() override + MxNotificationParam* Clone() override { return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc); - }; // vtable+0x4 + } // vtable+0x04 inline MxDSAction* GetAction() { return m_action; } protected: - MxDSAction* m_action; // 0xc + MxDSAction* m_action; // 0x0c MxBool m_realloc; // 0x10 }; @@ -70,7 +73,7 @@ class MxStartActionNotificationParam : public MxActionNotificationParam { { } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + MxNotificationParam* Clone() override; // vtable+0x04 }; // VTABLE: LEGO1 0x100d8358 @@ -88,7 +91,7 @@ class MxEndActionNotificationParam : public MxActionNotificationParam { } // FUNCTION: LEGO1 0x10051270 - virtual MxNotificationParam* Clone() override + MxNotificationParam* Clone() override { return new MxEndActionNotificationParam( c_notificationEndAction, @@ -96,7 +99,7 @@ class MxEndActionNotificationParam : public MxActionNotificationParam { this->m_action, this->m_realloc ); - }; // vtable+0x4 + } // vtable+0x04 }; // VTABLE: LEGO1 0x100dc208 @@ -109,7 +112,7 @@ class MxType4NotificationParam : public MxActionNotificationParam { m_unk0x14 = p_unk0x14; } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + MxNotificationParam* Clone() override; // vtable+0x04 private: MxPresenter* m_unk0x14; // 0x14 diff --git a/LEGO1/omni/include/mxatomid.h b/LEGO1/omni/include/mxatomid.h index 388ffce3..337f0b76 100644 --- a/LEGO1/omni/include/mxatomid.h +++ b/LEGO1/omni/include/mxatomid.h @@ -14,9 +14,9 @@ enum LookupMode { // SIZE 0x04 class MxAtomId { public: - __declspec(dllexport) MxAtomId(const char*, LookupMode); - __declspec(dllexport) MxAtomId& operator=(const MxAtomId& p_atomId); - __declspec(dllexport) ~MxAtomId(); + MxAtomId(const char*, LookupMode); + MxAtomId& operator=(const MxAtomId& p_atomId); + ~MxAtomId(); MxAtomId() { this->m_internal = 0; } diff --git a/LEGO1/omni/include/mxatomidcounter.h b/LEGO1/omni/include/mxatomidcounter.h index 79a98f34..4d8bfe38 100644 --- a/LEGO1/omni/include/mxatomidcounter.h +++ b/LEGO1/omni/include/mxatomidcounter.h @@ -25,8 +25,8 @@ class MxAtomIdCounter { void Inc(); void Dec(); - inline MxString* GetKey() { return &m_key; }; - inline MxU16 GetValue() { return m_value; }; + inline MxString* GetKey() { return &m_key; } + inline MxU16 GetValue() { return m_value; } private: MxString m_key; diff --git a/LEGO1/omni/include/mxaudiomanager.h b/LEGO1/omni/include/mxaudiomanager.h index 94b5c4c9..020bda54 100644 --- a/LEGO1/omni/include/mxaudiomanager.h +++ b/LEGO1/omni/include/mxaudiomanager.h @@ -9,13 +9,13 @@ class MxAudioManager : public MxMediaManager { public: MxAudioManager(); - virtual ~MxAudioManager() override; + ~MxAudioManager() override; - virtual MxResult InitPresenters() override; // vtable+14 - virtual void Destroy() override; // vtable+18 + MxResult InitPresenters() override; // vtable+14 + void Destroy() override; // vtable+18 // FUNCTION: LEGO1 0x10029910 - virtual MxS32 GetVolume() { return this->m_volume; }; // vtable+28 + virtual MxS32 GetVolume() { return this->m_volume; } // vtable+28 virtual void SetVolume(MxS32 p_volume); // vtable+2c diff --git a/LEGO1/omni/include/mxaudiopresenter.h b/LEGO1/omni/include/mxaudiopresenter.h index 82e4b48a..873871ec 100644 --- a/LEGO1/omni/include/mxaudiopresenter.h +++ b/LEGO1/omni/include/mxaudiopresenter.h @@ -11,23 +11,23 @@ class MxAudioPresenter : public MxMediaPresenter { MxAudioPresenter() { m_volume = 100; } // FUNCTION: LEGO1 0x1000d280 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f078c return "MxAudioPresenter"; } // FUNCTION: LEGO1 0x1000d290 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxAudioPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } // FUNCTION: LEGO1 0x1000d260 - virtual MxS32 GetVolume() { return m_volume; }; // vtable+0x5c + virtual MxS32 GetVolume() { return m_volume; } // vtable+0x5c // FUNCTION: LEGO1 0x1000d270 - virtual void SetVolume(MxS32 p_volume) { m_volume = p_volume; }; // vtable+0x60 + virtual void SetVolume(MxS32 p_volume) { m_volume = p_volume; } // vtable+0x60 protected: MxS32 m_volume; diff --git a/LEGO1/omni/include/mxbitmap.h b/LEGO1/omni/include/mxbitmap.h index f17ddb4b..465b2026 100644 --- a/LEGO1/omni/include/mxbitmap.h +++ b/LEGO1/omni/include/mxbitmap.h @@ -34,17 +34,17 @@ struct MxBITMAPINFO { // VTABLE: LEGO1 0x100dc7b0 class MxBitmap : public MxCore { public: - __declspec(dllexport) MxBitmap(); - __declspec(dllexport) virtual ~MxBitmap(); // vtable+00 + MxBitmap(); + ~MxBitmap() override; // vtable+00 virtual MxResult ImportBitmap(MxBitmap* p_bitmap); // vtable+14 virtual MxResult ImportBitmapInfo(MxBITMAPINFO* p_info); // vtable+18 virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool); // vtable+1c virtual MxResult LoadFile(HANDLE p_handle); // vtable+20 - __declspec(dllexport) virtual MxLong Read(const char* p_filename); // vtable+24 + virtual MxLong Read(const char* p_filename); // vtable+24 // FUNCTION: LEGO1 0x1004e0d0 - virtual int VTable0x28(int) { return -1; }; // vtable+28 + virtual int VTable0x28(int) { return -1; } // vtable+28 virtual void BitBlt( MxBitmap* p_src, @@ -63,10 +63,10 @@ class MxBitmap : public MxCore { MxS32 p_bottom, MxS32 p_width, MxS32 p_height - ); // vtable+30 - __declspec(dllexport) virtual MxPalette* CreatePalette(); // vtable+34 - virtual void ImportPalette(MxPalette* p_palette); // vtable+38 - virtual MxResult SetBitDepth(MxBool); // vtable+3c + ); // vtable+30 + virtual MxPalette* CreatePalette(); // vtable+34 + virtual void ImportPalette(MxPalette* p_palette); // vtable+38 + virtual MxResult SetBitDepth(MxBool); // vtable+3c virtual MxResult StretchBits( HDC p_hdc, MxS32 p_xSrc, @@ -102,30 +102,37 @@ class MxBitmap : public MxCore { } inline MxLong GetAdjustedStride() { - if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) + if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) { return GetBmiStride(); - else + } + else { return -GetBmiStride(); + } } inline MxLong GetLine(MxS32 p_top) { MxS32 height; - if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) + if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) { height = p_top; - else + } + else { height = GetBmiHeightAbs() - p_top - 1; + } return GetBmiStride() * height; } inline MxU8* GetStart(MxS32 p_left, MxS32 p_top) { - if (m_bmiHeader->biCompression == BI_RGB) + if (m_bmiHeader->biCompression == BI_RGB) { return GetLine(p_top) + m_data + p_left; - else if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) + } + else if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) { return m_data; - else + } + else { return GetLine(0) + m_data; + } } // SYNTHETIC: LEGO1 0x100bc9f0 @@ -134,8 +141,8 @@ class MxBitmap : public MxCore { private: MxResult ImportColorsToPalette(RGBQUAD*, MxPalette*); - MxBITMAPINFO* m_info; // 0x8 - BITMAPINFOHEADER* m_bmiHeader; // 0xc + MxBITMAPINFO* m_info; // 0x08 + BITMAPINFOHEADER* m_bmiHeader; // 0x0c RGBQUAD* m_paletteData; // 0x10 MxU8* m_data; // 0x14 MxBool m_isHighColor; // 0x18 diff --git a/LEGO1/omni/include/mxcollection.h b/LEGO1/omni/include/mxcollection.h index b0b4da88..84acdeef 100644 --- a/LEGO1/omni/include/mxcollection.h +++ b/LEGO1/omni/include/mxcollection.h @@ -16,12 +16,12 @@ class MxCollection : public MxCore { void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; } - virtual ~MxCollection() {} + ~MxCollection() override {} virtual MxS8 Compare(T, T) { return 0; } protected: - MxU32 m_count; // 0x8 - void (*m_customDestructor)(T); // 0xc + MxU32 m_count; // 0x08 + void (*m_customDestructor)(T); // 0x0c }; #endif // MXCOLLECTION_H diff --git a/LEGO1/omni/include/mxcompositepresenter.h b/LEGO1/omni/include/mxcompositepresenter.h index 33d00dc8..a39507c0 100644 --- a/LEGO1/omni/include/mxcompositepresenter.h +++ b/LEGO1/omni/include/mxcompositepresenter.h @@ -12,39 +12,42 @@ class MxCompositePresenterList : public list {}; class MxCompositePresenter : public MxPresenter { public: MxCompositePresenter(); - virtual ~MxCompositePresenter() override; // vtable+0x0 + ~MxCompositePresenter() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100b6210 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0774 return "MxCompositePresenter"; } // FUNCTION: LEGO1 0x100b6220 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxCompositePresenter::ClassName()) || MxPresenter::IsA(p_name); } - virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual void SetTickleState(TickleState p_tickleState) override; // vtable+0x44 - virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void VTable0x58(MxEndActionNotificationParam& p_param); // vtable+0x58 - virtual void VTable0x5c(MxNotificationParam& p_param); // vtable+0x5c - virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void SetTickleState(TickleState p_tickleState) override; // vtable+0x44 + MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 + void Enable(MxBool p_enable) override; // vtable+0x54 + virtual void VTable0x58(MxEndActionNotificationParam& p_param); // vtable+0x58 + virtual void VTable0x5c(MxNotificationParam& p_param); // vtable+0x5c + virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 // FUNCTION: LEGO1 0x1000caf0 virtual MxBool VTable0x64(undefined4 p_undefined) { - if (m_compositePresenter) + if (m_compositePresenter) { return m_compositePresenter->VTable0x64(p_undefined); + } return TRUE; - }; // vtable+0x64 + } // vtable+0x64 + + inline MxCompositePresenterList& GetList() { return m_list; } protected: MxCompositePresenterList m_list; // 0x40 diff --git a/LEGO1/omni/include/mxcore.h b/LEGO1/omni/include/mxcore.h index cae7020e..dc167f2b 100644 --- a/LEGO1/omni/include/mxcore.h +++ b/LEGO1/omni/include/mxcore.h @@ -9,15 +9,15 @@ class MxParam; // VTABLE: LEGO1 0x100dc0f8 -// SIZE 0x8 +// SIZE 0x08 class MxCore { public: - __declspec(dllexport) MxCore(); - __declspec(dllexport) virtual ~MxCore(); // vtable+00 - __declspec(dllexport) virtual MxLong Notify(MxParam& p_param); // vtable+04 + MxCore(); + virtual ~MxCore(); // vtable+00 + virtual MxLong Notify(MxParam& p_param); // vtable+04 // FUNCTION: LEGO1 0x10001f70 - virtual MxResult Tickle() { return SUCCESS; }; // vtable+08 + virtual MxResult Tickle() { return SUCCESS; } // vtable+08 // FUNCTION: LEGO1 0x100144c0 inline virtual const char* ClassName() const // vtable+0c diff --git a/LEGO1/omni/include/mxcorelist.h b/LEGO1/omni/include/mxcorelist.h deleted file mode 100644 index 15ae7c9b..00000000 --- a/LEGO1/omni/include/mxcorelist.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef MXCORELIST_H -#define MXCORELIST_H - -#include "mxlist.h" -#include "mxtypes.h" - -class MxCore; - -// VTABLE: LEGO1 0x100d63b0 -// class MxCollection - -// VTABLE: LEGO1 0x100d63c8 -// class MxList - -// VTABLE: LEGO1 0x100d63e0 -// class MxPtrList - -// VTABLE: LEGO1 0x100d63f8 -// SIZE 0x18 -class MxCoreList : public MxPtrList { -public: - MxCoreList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} - - // FUNCTION: LEGO1 0x1001e650 - virtual MxS8 Compare(MxCore* p_a, MxCore* p_b) override - { - return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; - }; // vtable+0x14 -}; - -// VTABLE: LEGO1 0x100d64a0 -// class MxListCursor - -// VTABLE: LEGO1 0x100d6500 -// class MxPtrListCursor - -// VTABLE: LEGO1 0x100d6518 -// SIZE 0x10 -class MxCoreListCursor : public MxPtrListCursor { -public: - MxCoreListCursor(MxCoreList* p_list) : MxPtrListCursor(p_list){}; -}; - -// TEMPLATE: LEGO1 0x1001e670 -// MxCollection::Compare - -// TEMPLATE: LEGO1 0x1001e680 -// MxCollection::~MxCollection - -// TEMPLATE: LEGO1 0x1001e6d0 -// MxCollection::Destroy - -// TEMPLATE: LEGO1 0x1001e6e0 -// MxList::~MxList - -// TEMPLATE: LEGO1 0x1001e770 -// MxPtrList::Destroy - -// SYNTHETIC: LEGO1 0x1001e780 -// MxCoreList::`scalar deleting destructor' - -// TEMPLATE: LEGO1 0x1001e7f0 -// MxPtrList::~MxPtrList - -// SYNTHETIC: LEGO1 0x1001e840 -// MxCollection::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1001e8b0 -// MxList::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1001e960 -// MxPtrList::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1001f350 -// MxCoreListCursor::`scalar deleting destructor' - -// FUNCTION: LEGO1 0x1001f3c0 -// MxPtrListCursor::~MxPtrListCursor - -// SYNTHETIC: LEGO1 0x1001f410 -// MxListCursor::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1001f480 -// MxPtrListCursor::`scalar deleting destructor' - -// FUNCTION: LEGO1 0x1001f4f0 -// MxListCursor::~MxListCursor - -// FUNCTION: LEGO1 0x1001f540 -// MxCoreListCursor::~MxCoreListCursor - -// TEMPLATE: LEGO1 0x10020840 -// MxListCursor::MxListCursor - -#endif // MXCORELIST_H diff --git a/LEGO1/omni/include/mxcriticalsection.h b/LEGO1/omni/include/mxcriticalsection.h index 8c5f77d6..011ac680 100644 --- a/LEGO1/omni/include/mxcriticalsection.h +++ b/LEGO1/omni/include/mxcriticalsection.h @@ -6,9 +6,9 @@ // SIZE 0x1c class MxCriticalSection { public: - __declspec(dllexport) MxCriticalSection(); - __declspec(dllexport) ~MxCriticalSection(); - __declspec(dllexport) static void SetDoMutex(); + MxCriticalSection(); + ~MxCriticalSection(); + static void SetDoMutex(); void Enter(); void Leave(); diff --git a/LEGO1/omni/include/mxdiskstreamcontroller.h b/LEGO1/omni/include/mxdiskstreamcontroller.h index 52c0d8b4..ab13c73d 100644 --- a/LEGO1/omni/include/mxdiskstreamcontroller.h +++ b/LEGO1/omni/include/mxdiskstreamcontroller.h @@ -15,30 +15,30 @@ class MxDiskStreamController : public MxStreamController { public: MxDiskStreamController(); - virtual ~MxDiskStreamController() override; + ~MxDiskStreamController() override; - virtual MxResult Tickle() override; // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x100c7360 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102144 return "MxDiskStreamController"; } // FUNCTION: LEGO1 0x100c7370 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDiskStreamController::ClassName()) || MxStreamController::IsA(p_name); } - virtual MxResult Open(const char* p_filename) override; // vtable+0x14 - virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 - virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 - virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 - virtual MxDSStreamingAction* VTable0x28() override; // vtable+0x28 - virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 - virtual MxResult VTable0x34(undefined4); // vtable+0x34 + MxResult Open(const char* p_filename) override; // vtable+0x14 + MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 + MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 + MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 + MxDSStreamingAction* VTable0x28() override; // vtable+0x28 + MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 + virtual MxResult VTable0x34(undefined4); // vtable+0x34 inline MxBool GetUnk0xc4() const { return m_unk0xc4; } diff --git a/LEGO1/omni/include/mxdiskstreamprovider.h b/LEGO1/omni/include/mxdiskstreamprovider.h index 517fa463..7bac3a0b 100644 --- a/LEGO1/omni/include/mxdiskstreamprovider.h +++ b/LEGO1/omni/include/mxdiskstreamprovider.h @@ -27,17 +27,17 @@ class MxDiskStreamProviderThread : public MxThread { class MxDiskStreamProvider : public MxStreamProvider { public: MxDiskStreamProvider(); - virtual ~MxDiskStreamProvider() override; + ~MxDiskStreamProvider() override; // FUNCTION: LEGO1 0x100d1160 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x1010287c return "MxDiskStreamProvider"; } // FUNCTION: LEGO1 0x100d1170 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDiskStreamProvider::ClassName()) || MxStreamProvider::IsA(p_name); } @@ -48,12 +48,12 @@ class MxDiskStreamProvider : public MxStreamProvider { static MxBool FUN_100d1af0(MxDSStreamingAction* p_action); MxResult FUN_100d1b20(MxDSStreamingAction* p_action); - virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 - virtual MxU32 GetFileSize() override; // vtable+0x18 - virtual MxS32 GetStreamBuffersNum() override; // vtable+0x1c - virtual void VTable0x20(MxDSAction* p_action) override; // vtable+0x20 - virtual MxU32 GetLengthInDWords() override; // vtable+0x24 - virtual MxU32* GetBufferForDWords() override; // vtable+0x28 + MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 + MxU32 GetFileSize() override; // vtable+0x18 + MxS32 GetStreamBuffersNum() override; // vtable+0x1c + void VTable0x20(MxDSAction* p_action) override; // vtable+0x20 + MxU32 GetLengthInDWords() override; // vtable+0x24 + MxU32* GetBufferForDWords() override; // vtable+0x28 private: MxDiskStreamProviderThread m_thread; // 0x10 diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h index 1d26264c..4e107f60 100644 --- a/LEGO1/omni/include/mxdisplaysurface.h +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -14,7 +14,7 @@ class MxDisplaySurface : public MxCore { public: MxDisplaySurface(); - virtual ~MxDisplaySurface() override; + ~MxDisplaySurface() override; virtual MxResult Init( MxVideoParam& p_videoParam, @@ -92,6 +92,7 @@ class MxDisplaySurface : public MxCore { void ClearScreen(); static LPDIRECTDRAWSURFACE CreateCursorSurface(); + static LPDIRECTDRAWSURFACE FUN_100bbfb0(LPDIRECTDRAWSURFACE p_und); inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } inline LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return this->m_ddSurface2; } diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h index 67449868..0146ba04 100644 --- a/LEGO1/omni/include/mxdsaction.h +++ b/LEGO1/omni/include/mxdsaction.h @@ -24,36 +24,36 @@ class MxDSAction : public MxDSObject { c_bit11 = 0x400, }; - __declspec(dllexport) MxDSAction(); - __declspec(dllexport) virtual ~MxDSAction(); + MxDSAction(); + ~MxDSAction() override; void CopyFrom(MxDSAction& p_dsAction); MxDSAction& operator=(MxDSAction& p_dsAction); // FUNCTION: LEGO1 0x100ad980 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101013f4 return "MxDSAction"; } // FUNCTION: LEGO1 0x100ad990 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSAction::ClassName()) || MxDSObject::IsA(p_name); } - virtual undefined4 VTable0x14() override; // vtable+14; - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual MxLong GetDuration(); // vtable+24; - virtual void SetDuration(MxLong p_duration); // vtable+28; - virtual MxDSAction* Clone(); // vtable+2c; - virtual void MergeFrom(MxDSAction& p_dsAction); // vtable+30; - virtual MxBool HasId(MxU32 p_objectId); // vtable+34; - virtual void SetUnknown90(MxLong p_unk0x90); // vtable+38; - virtual MxLong GetUnknown90(); // vtable+3c; - virtual MxLong GetElapsedTime(); // vtable+40; + undefined4 VTable0x14() override; // vtable+14; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + virtual MxLong GetDuration(); // vtable+24; + virtual void SetDuration(MxLong p_duration); // vtable+28; + virtual MxDSAction* Clone(); // vtable+2c; + virtual void MergeFrom(MxDSAction& p_dsAction); // vtable+30; + virtual MxBool HasId(MxU32 p_objectId); // vtable+34; + virtual void SetUnknown90(MxLong p_unk0x90); // vtable+38; + virtual MxLong GetUnknown90(); // vtable+3c; + virtual MxLong GetElapsedTime(); // vtable+40; void AppendData(MxU16 p_extraLength, const char* p_extraData); @@ -77,10 +77,12 @@ class MxDSAction : public MxDSObject { inline void CopyFlags(MxU32 p_flags) { - if (p_flags & MxDSAction::c_looping) + if (p_flags & MxDSAction::c_looping) { SetFlags(GetFlags() | MxDSAction::c_looping); - else if (p_flags & MxDSAction::c_bit3) + } + else if (p_flags & MxDSAction::c_bit3) { SetFlags(GetFlags() | MxDSAction::c_bit3); + } } // SYNTHETIC: LEGO1 0x100ada60 diff --git a/LEGO1/omni/include/mxdsactionlist.h b/LEGO1/omni/include/mxdsactionlist.h index 75d96842..b413cd2b 100644 --- a/LEGO1/omni/include/mxdsactionlist.h +++ b/LEGO1/omni/include/mxdsactionlist.h @@ -19,7 +19,7 @@ class MxDSActionList : public MxList { MxDSActionList() { this->m_unk0x18 = 0; } // FUNCTION: LEGO1 0x100c9c90 - virtual MxS8 Compare(MxDSAction* p_a, MxDSAction* p_b) override + MxS8 Compare(MxDSAction* p_a, MxDSAction* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 diff --git a/LEGO1/omni/include/mxdsanim.h b/LEGO1/omni/include/mxdsanim.h index 0e5b9a0c..09f9c72c 100644 --- a/LEGO1/omni/include/mxdsanim.h +++ b/LEGO1/omni/include/mxdsanim.h @@ -8,25 +8,25 @@ class MxDSAnim : public MxDSMediaAction { public: MxDSAnim(); - virtual ~MxDSAnim() override; + ~MxDSAnim() override; void CopyFrom(MxDSAnim& p_dsAnim); MxDSAnim& operator=(MxDSAnim& p_dsAnim); // FUNCTION: LEGO1 0x100c9060 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101025d8 return "MxDSAnim"; } // FUNCTION: LEGO1 0x100c9070 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSAnim::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; // SYNTHETIC: LEGO1 0x100c9180 // MxDSAnim::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxdsbuffer.h b/LEGO1/omni/include/mxdsbuffer.h index 01696471..79dee7d7 100644 --- a/LEGO1/omni/include/mxdsbuffer.h +++ b/LEGO1/omni/include/mxdsbuffer.h @@ -22,10 +22,10 @@ class MxDSBuffer : public MxCore { }; MxDSBuffer(); - virtual ~MxDSBuffer() override; + ~MxDSBuffer() override; // FUNCTION: LEGO1 0x100c6500 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101025b8 return "MxDSBuffer"; diff --git a/LEGO1/omni/include/mxdschunk.h b/LEGO1/omni/include/mxdschunk.h index 52806580..c21816e6 100644 --- a/LEGO1/omni/include/mxdschunk.h +++ b/LEGO1/omni/include/mxdschunk.h @@ -18,17 +18,17 @@ class MxDSChunk : public MxCore { }; MxDSChunk(); - virtual ~MxDSChunk() override; + ~MxDSChunk() override; // FUNCTION: LEGO1 0x100be0c0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101e6c return "MxDSChunk"; } // FUNCTION: LEGO1 0x100be0d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSChunk::ClassName()) || MxCore::IsA(p_name); } @@ -53,16 +53,17 @@ class MxDSChunk : public MxCore { inline void Release() { - if (m_data) + if (m_data) { delete[] m_data; + } } // SYNTHETIC: LEGO1 0x100be150 // MxDSChunk::`scalar deleting destructor' protected: - MxU16 m_flags; // 0x8 - MxU32 m_objectId; // 0xc + MxU16 m_flags; // 0x08 + MxU32 m_objectId; // 0x0c MxLong m_time; // 0x10 MxU32 m_length; // 0x14 MxU8* m_data; // 0x18 diff --git a/LEGO1/omni/include/mxdsevent.h b/LEGO1/omni/include/mxdsevent.h index 1a197496..492cfd10 100644 --- a/LEGO1/omni/include/mxdsevent.h +++ b/LEGO1/omni/include/mxdsevent.h @@ -7,25 +7,25 @@ class MxDSEvent : public MxDSMediaAction { public: MxDSEvent(); - virtual ~MxDSEvent() override; + ~MxDSEvent() override; void CopyFrom(MxDSEvent& p_dsEvent); MxDSEvent& operator=(MxDSEvent& p_dsEvent); // FUNCTION: LEGO1 0x100c9660 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101025f0 return "MxDSEvent"; } // FUNCTION: LEGO1 0x100c9670 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSEvent::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; // SYNTHETIC: LEGO1 0x100c9780 // MxDSEvent::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxdsfile.h b/LEGO1/omni/include/mxdsfile.h index 473b9741..b635c896 100644 --- a/LEGO1/omni/include/mxdsfile.h +++ b/LEGO1/omni/include/mxdsfile.h @@ -9,30 +9,39 @@ #include // VTABLE: LEGO1 0x100dc890 +// SIZE 0x7c class MxDSFile : public MxDSSource { public: - __declspec(dllexport) MxDSFile(const char* p_filename, MxULong p_skipReadingChunks); - __declspec(dllexport) virtual ~MxDSFile(); // vtable+0x0 + MxDSFile(const char* p_filename, MxULong p_skipReadingChunks); + +#ifdef ISLE_APP + ~MxDSFile() override { Close(); } +#else + // We have to explicitly use dllexport, otherwise this function cannot be exported, + // since it is inlined everywhere in LEGO1.DLL + // FUNCTION: LEGO1 0x100bfed0 + __declspec(dllexport) ~MxDSFile() override { Close(); } +#endif // FUNCTION: LEGO1 0x100c0120 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102594 return "MxDSFile"; } // FUNCTION: LEGO1 0x100c0130 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSFile::ClassName()) || MxDSSource::IsA(p_name); } - __declspec(dllexport) virtual MxLong Open(MxULong); // vtable+0x14 - __declspec(dllexport) virtual MxLong Close(); // vtable+0x18 - __declspec(dllexport) virtual MxResult Read(unsigned char*, MxULong); // vtable+0x20 - __declspec(dllexport) virtual MxLong Seek(MxLong, int); // vtable+0x24 - __declspec(dllexport) virtual MxULong GetBufferSize(); // vtable+0x28 - __declspec(dllexport) virtual MxULong GetStreamBuffersNum(); // vtable+0x2c + MxLong Open(MxULong) override; // vtable+0x14 + MxLong Close() override; // vtable+0x18 + MxResult Read(unsigned char*, MxULong) override; // vtable+0x20 + MxLong Seek(MxLong, int) override; // vtable+0x24 + MxULong GetBufferSize() override; // vtable+0x28 + MxULong GetStreamBuffersNum() override; // vtable+0x2c inline void SetFileName(const char* p_filename) { m_filename = p_filename; } @@ -41,25 +50,27 @@ class MxDSFile : public MxDSSource { // SYNTHETIC: LEGO1 0x100c01e0 // MxDSFile::`scalar deleting destructor' -private: - MxLong ReadChunks(); + // SIZE 0x0c struct ChunkHeader { ChunkHeader() : m_majorVersion(0), m_minorVersion(0), m_bufferSize(0), m_streamBuffersNum(0) {} - MxU16 m_majorVersion; - MxU16 m_minorVersion; - MxULong m_bufferSize; - MxS16 m_streamBuffersNum; - MxS16 m_reserved; + MxU16 m_majorVersion; // 0x00 + MxU16 m_minorVersion; // 0x02 + MxULong m_bufferSize; // 0x04 + MxS16 m_streamBuffersNum; // 0x08 + MxS16 m_reserved; // 0x0a }; - MxString m_filename; - MXIOINFO m_io; - ChunkHeader m_header; +private: + MxLong ReadChunks(); + + MxString m_filename; // 0x14 + MXIOINFO m_io; // 0x24 + ChunkHeader m_header; // 0x6c // If false, read chunks immediately on open, otherwise // skip reading chunks until ReadChunks is explicitly called. - MxULong m_skipReadingChunks; + MxULong m_skipReadingChunks; // 0x78 }; #endif // MXDSFILE_H diff --git a/LEGO1/omni/include/mxdsmediaaction.h b/LEGO1/omni/include/mxdsmediaaction.h index 7422ec2d..32664156 100644 --- a/LEGO1/omni/include/mxdsmediaaction.h +++ b/LEGO1/omni/include/mxdsmediaaction.h @@ -10,20 +10,20 @@ class MxDSMediaAction : public MxDSAction { public: MxDSMediaAction(); - virtual ~MxDSMediaAction() override; + ~MxDSMediaAction() override; void CopyFrom(MxDSMediaAction& p_dsMediaAction); MxDSMediaAction& operator=(MxDSMediaAction& p_dsMediaAction); // FUNCTION: LEGO1 0x100c8be0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f7624 return "MxDSMediaAction"; } // FUNCTION: LEGO1 0x100c8bf0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSMediaAction::ClassName()) || MxDSAction::IsA(p_name); } @@ -31,10 +31,10 @@ class MxDSMediaAction : public MxDSAction { // SYNTHETIC: LEGO1 0x100c8cd0 // MxDSMediaAction::`scalar deleting destructor' - virtual undefined4 VTable0x14(); // vtable+14; - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual MxDSAction* Clone() override; // vtable+2c; + undefined4 VTable0x14() override; // vtable+14; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + MxDSAction* Clone() override; // vtable+2c; void CopyMediaSrcPath(const char* p_mediaSrcPath); diff --git a/LEGO1/omni/include/mxdsmultiaction.h b/LEGO1/omni/include/mxdsmultiaction.h index efc1a11d..d97e6116 100644 --- a/LEGO1/omni/include/mxdsmultiaction.h +++ b/LEGO1/omni/include/mxdsmultiaction.h @@ -9,34 +9,34 @@ class MxDSMultiAction : public MxDSAction { public: MxDSMultiAction(); - virtual ~MxDSMultiAction() override; + ~MxDSMultiAction() override; void CopyFrom(MxDSMultiAction& p_dsMultiAction); MxDSMultiAction& operator=(MxDSMultiAction& p_dsMultiAction); // FUNCTION: LEGO1 0x100c9f50 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101dbc return "MxDSMultiAction"; } // FUNCTION: LEGO1 0x100c9f60 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSMultiAction::ClassName()) || MxDSAction::IsA(p_name); } - virtual undefined4 VTable0x14() override; // vtable+14; - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual void SetAtomId(MxAtomId p_atomId) override; // vtable+20; - virtual MxDSAction* Clone() override; // vtable+2c; - virtual void MergeFrom(MxDSAction& p_dsAction) override; // vtable+30; - virtual MxBool HasId(MxU32 p_objectId) override; // vtable+34; - virtual void SetUnknown90(MxLong p_unk0x90) override; // vtable+38; + undefined4 VTable0x14() override; // vtable+14; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + void SetAtomId(MxAtomId p_atomId) override; // vtable+20; + MxDSAction* Clone() override; // vtable+2c; + void MergeFrom(MxDSAction& p_dsAction) override; // vtable+30; + MxBool HasId(MxU32 p_objectId) override; // vtable+34; + void SetUnknown90(MxLong p_unk0x90) override; // vtable+38; - inline MxDSActionList* GetActionList() const { return m_actions; }; + inline MxDSActionList* GetActionList() const { return m_actions; } // SYNTHETIC: LEGO1 0x100ca040 // MxDSMultiAction::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxdsobject.h b/LEGO1/omni/include/mxdsobject.h index ad1cae40..c7156004 100644 --- a/LEGO1/omni/include/mxdsobject.h +++ b/LEGO1/omni/include/mxdsobject.h @@ -27,22 +27,22 @@ class MxDSObject : public MxCore { }; MxDSObject(); - virtual ~MxDSObject() override; + ~MxDSObject() override; void CopyFrom(MxDSObject& p_dsObject); MxDSObject& operator=(MxDSObject& p_dsObject); - __declspec(dllexport) void SetObjectName(const char* p_objectName); + void SetObjectName(const char* p_objectName); void SetSourceName(const char* p_sourceName); // FUNCTION: LEGO1 0x100bf730 - inline virtual const char* ClassName() const override { return "MxDSObject"; }; // vtable+0c + inline const char* ClassName() const override { return "MxDSObject"; } // vtable+0c // FUNCTION: LEGO1 0x100bf740 - inline virtual MxBool IsA(const char* p_name) const override + inline MxBool IsA(const char* p_name) const override { return !strcmp(p_name, MxDSObject::ClassName()) || MxCore::IsA(p_name); - }; // vtable+10; + } // vtable+10; virtual undefined4 VTable0x14(); // vtable+14; virtual MxU32 GetSizeOnDisk(); // vtable+18; @@ -51,6 +51,7 @@ class MxDSObject : public MxCore { inline Type GetType() const { return (Type) this->m_type; } inline const char* GetSourceName() const { return this->m_sourceName; } + inline const char* GetObjectName() const { return this->m_objectName; } inline MxU32 GetObjectId() { return this->m_objectId; } inline const MxAtomId& GetAtomId() { return this->m_atomId; } inline MxS16 GetUnknown24() { return this->m_unk0x24; } @@ -67,8 +68,8 @@ class MxDSObject : public MxCore { // MxDSObject::`scalar deleting destructor' private: - MxU32 m_sizeOnDisk; // 0x8 - MxU16 m_type; // 0xc + MxU32 m_sizeOnDisk; // 0x08 + MxU16 m_type; // 0x0c char* m_sourceName; // 0x10 undefined4 m_unk0x14; // 0x14 char* m_objectName; // 0x18 diff --git a/LEGO1/omni/include/mxdsobjectaction.h b/LEGO1/omni/include/mxdsobjectaction.h index 77480452..205c6d81 100644 --- a/LEGO1/omni/include/mxdsobjectaction.h +++ b/LEGO1/omni/include/mxdsobjectaction.h @@ -8,24 +8,24 @@ class MxDSObjectAction : public MxDSMediaAction { public: MxDSObjectAction(); - virtual ~MxDSObjectAction() override; + ~MxDSObjectAction() override; MxDSObjectAction& operator=(MxDSObjectAction& p_dsObjectAction); // FUNCTION: LEGO1 0x100c88e0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101025c4 return "MxDSObjectAction"; } // FUNCTION: LEGO1 0x100c88f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSObjectAction::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; virtual void CopyFrom(MxDSObjectAction& p_dsObjectAction); // vtable+44; // SYNTHETIC: LEGO1 0x100c8a00 diff --git a/LEGO1/omni/include/mxdsparallelaction.h b/LEGO1/omni/include/mxdsparallelaction.h index 0386de7f..212fb8f0 100644 --- a/LEGO1/omni/include/mxdsparallelaction.h +++ b/LEGO1/omni/include/mxdsparallelaction.h @@ -8,20 +8,20 @@ class MxDSParallelAction : public MxDSMultiAction { public: MxDSParallelAction(); - virtual ~MxDSParallelAction() override; + ~MxDSParallelAction() override; void CopyFrom(MxDSParallelAction& p_dsParallelAction); MxDSParallelAction& operator=(MxDSParallelAction& p_dsParallelAction); // FUNCTION: LEGO1 0x100caf00 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102608 return "MxDSParallelAction"; } // FUNCTION: LEGO1 0x100caf10 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSParallelAction::ClassName()) || MxDSMultiAction::IsA(p_name); } @@ -29,12 +29,12 @@ class MxDSParallelAction : public MxDSMultiAction { // SYNTHETIC: LEGO1 0x100cb020 // MxDSParallelAction::`scalar deleting destructor' - virtual MxLong GetDuration() override; // vtable+24; + MxLong GetDuration() override; // vtable+24; // FUNCTION: LEGO1 0x100caef0 - virtual void SetDuration(MxLong p_duration) override { m_duration = p_duration; } // vtable+0x28 + void SetDuration(MxLong p_duration) override { m_duration = p_duration; } // vtable+0x28 - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; }; #endif // MXDSPARALLELACTION_H diff --git a/LEGO1/omni/include/mxdsselectaction.h b/LEGO1/omni/include/mxdsselectaction.h index f7c6a148..ab2e6609 100644 --- a/LEGO1/omni/include/mxdsselectaction.h +++ b/LEGO1/omni/include/mxdsselectaction.h @@ -10,27 +10,27 @@ class MxDSSelectAction : public MxDSParallelAction { public: MxDSSelectAction(); - virtual ~MxDSSelectAction() override; + ~MxDSSelectAction() override; void CopyFrom(MxDSSelectAction& p_dsSelectAction); MxDSSelectAction& operator=(MxDSSelectAction& p_dsSelectAction); // FUNCTION: LEGO1 0x100cb6f0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x1010261c return "MxDSSelectAction"; } // FUNCTION: LEGO1 0x100cb700 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSelectAction::ClassName()) || MxDSParallelAction::IsA(p_name); } - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual MxDSAction* Clone() override; // vtable+2c; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + MxDSAction* Clone() override; // vtable+2c; // SYNTHETIC: LEGO1 0x100cb840 // MxDSSelectAction::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxdsserialaction.h b/LEGO1/omni/include/mxdsserialaction.h index 694c9afa..b1c2a695 100644 --- a/LEGO1/omni/include/mxdsserialaction.h +++ b/LEGO1/omni/include/mxdsserialaction.h @@ -9,27 +9,27 @@ class MxDSSerialAction : public MxDSMultiAction { public: MxDSSerialAction(); - virtual ~MxDSSerialAction() override; + ~MxDSSerialAction() override; void CopyFrom(MxDSSerialAction& p_dsSerialAction); MxDSSerialAction& operator=(MxDSSerialAction& p_dsSerialAction); // FUNCTION: LEGO1 0x100caad0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f75dc return "MxDSSerialAction"; } // FUNCTION: LEGO1 0x100caae0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSerialAction::ClassName()) || MxDSMultiAction::IsA(p_name); } - virtual MxLong GetDuration() override; // vtable+24; - virtual void SetDuration(MxLong p_duration) override; // vtable+28; - virtual MxDSAction* Clone() override; // vtable+2c; + MxLong GetDuration() override; // vtable+24; + void SetDuration(MxLong p_duration) override; // vtable+28; + MxDSAction* Clone() override; // vtable+2c; // SYNTHETIC: LEGO1 0x100cabf0 // MxDSSerialAction::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxdssound.h b/LEGO1/omni/include/mxdssound.h index 3d1fa31d..193fde3a 100644 --- a/LEGO1/omni/include/mxdssound.h +++ b/LEGO1/omni/include/mxdssound.h @@ -8,27 +8,27 @@ class MxDSSound : public MxDSMediaAction { public: MxDSSound(); - virtual ~MxDSSound() override; + ~MxDSSound() override; void CopyFrom(MxDSSound& p_dsSound); MxDSSound& operator=(MxDSSound& p_dsSound); // FUNCTION: LEGO1 0x100c9330 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101025e4 return "MxDSSound"; } // FUNCTION: LEGO1 0x100c9340 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSound::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual MxDSAction* Clone() override; // vtable+2c; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + MxDSAction* Clone() override; // vtable+2c; inline MxS32 GetVolume() const { return m_volume; } diff --git a/LEGO1/omni/include/mxdssource.h b/LEGO1/omni/include/mxdssource.h index 143b9c78..d3b9474b 100644 --- a/LEGO1/omni/include/mxdssource.h +++ b/LEGO1/omni/include/mxdssource.h @@ -12,17 +12,17 @@ class MxDSSource : public MxCore { MxDSSource() : m_lengthInDWords(0), m_pBuffer(NULL), m_position(-1) {} // FUNCTION: LEGO1 0x100bff60 - virtual ~MxDSSource() override { delete[] m_pBuffer; } + ~MxDSSource() override { delete[] m_pBuffer; } // FUNCTION: LEGO1 0x100c0010 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102588 return "MxDSSource"; } // FUNCTION: LEGO1 0x100c0020 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSource::ClassName()) || MxCore::IsA(p_name); } diff --git a/LEGO1/omni/include/mxdsstill.h b/LEGO1/omni/include/mxdsstill.h index 4de69475..f46fff32 100644 --- a/LEGO1/omni/include/mxdsstill.h +++ b/LEGO1/omni/include/mxdsstill.h @@ -8,25 +8,25 @@ class MxDSStill : public MxDSMediaAction { public: MxDSStill(); - virtual ~MxDSStill() override; + ~MxDSStill() override; void CopyFrom(MxDSStill& p_dsStill); MxDSStill& operator=(MxDSStill& p_dsStill); // FUNCTION: LEGO1 0x100c9930 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101025fc return "MxDSStill"; } // FUNCTION: LEGO1 0x100c9940 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSStill::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; // SYNTHETIC: LEGO1 0x100c9a50 // MxDSStill::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxdsstreamingaction.h b/LEGO1/omni/include/mxdsstreamingaction.h index 074bd5ed..94e652ae 100644 --- a/LEGO1/omni/include/mxdsstreamingaction.h +++ b/LEGO1/omni/include/mxdsstreamingaction.h @@ -11,7 +11,7 @@ class MxDSStreamingAction : public MxDSAction { public: MxDSStreamingAction(MxDSAction& p_dsAction, MxU32 p_offset); MxDSStreamingAction(MxDSStreamingAction& p_dsStreamingAction); - virtual ~MxDSStreamingAction(); + ~MxDSStreamingAction() override; MxDSStreamingAction* CopyFrom(MxDSStreamingAction& p_dsStreamingAction); MxDSStreamingAction& operator=(MxDSAction& p_dsAction) @@ -25,7 +25,7 @@ class MxDSStreamingAction : public MxDSAction { return *this; } - virtual MxBool HasId(MxU32 p_objectId) override; // vtable+34; + MxBool HasId(MxU32 p_objectId) override; // vtable+34; MxResult Init(); void SetInternalAction(MxDSAction* p_dsAction); diff --git a/LEGO1/omni/include/mxdssubscriber.h b/LEGO1/omni/include/mxdssubscriber.h index 1156be36..54cd203d 100644 --- a/LEGO1/omni/include/mxdssubscriber.h +++ b/LEGO1/omni/include/mxdssubscriber.h @@ -14,27 +14,27 @@ class MxStreamController; class MxDSSubscriber : public MxCore { public: MxDSSubscriber(); - virtual ~MxDSSubscriber() override; + ~MxDSSubscriber() override; // FUNCTION: LEGO1 0x100b7d50 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101020f8 return "MxDSSubscriber"; } // FUNCTION: LEGO1 0x100b7d60 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSubscriber::ClassName()) || MxCore::IsA(p_name); } MxResult Create(MxStreamController* p_controller, MxU32 p_objectId, MxS16 p_unk0x48); - void DeleteChunks(); - MxResult AddChunk(MxStreamChunk* p_chunk, MxBool p_append); - MxStreamChunk* NextChunk(); - MxStreamChunk* CurrentChunk(); - void DestroyChunk(MxStreamChunk* p_chunk); + void DestroyData(); + MxResult AddData(MxStreamChunk* p_chunk, MxBool p_append); + MxStreamChunk* PopData(); + MxStreamChunk* PeekData(); + void FreeDataChunk(MxStreamChunk* p_chunk); inline MxU32 GetObjectId() { return m_objectId; } inline MxS16 GetUnknown48() { return m_unk0x48; } diff --git a/LEGO1/omni/include/mxentity.h b/LEGO1/omni/include/mxentity.h index e78d3b2b..ed75d148 100644 --- a/LEGO1/omni/include/mxentity.h +++ b/LEGO1/omni/include/mxentity.h @@ -15,17 +15,17 @@ class MxEntity : public MxCore { MxEntity() { this->m_mxEntityId = -1; } // FUNCTION: LEGO1 0x1000c110 - virtual ~MxEntity() override{}; + ~MxEntity() override{}; // FUNCTION: LEGO1 0x1000c180 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0070 return "MxEntity"; } // FUNCTION: LEGO1 0x1000c190 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxEntity::ClassName()) || MxCore::IsA(p_name); } @@ -36,7 +36,7 @@ class MxEntity : public MxCore { this->m_mxEntityId = p_id; this->m_atom = p_atom; return SUCCESS; - }; // vtable+0x14 + } // vtable+0x14 inline MxResult Create(MxDSAction& p_dsAction) { @@ -52,8 +52,8 @@ class MxEntity : public MxCore { // MxEntity::`scalar deleting destructor' protected: - MxS32 m_mxEntityId; // 0x8 - MxAtomId m_atom; // 0xc + MxS32 m_mxEntityId; // 0x08 + MxAtomId m_atom; // 0x0c }; #endif // MXENTITY_H diff --git a/LEGO1/omni/include/mxeventmanager.h b/LEGO1/omni/include/mxeventmanager.h index c21e92bc..b23a2ad0 100644 --- a/LEGO1/omni/include/mxeventmanager.h +++ b/LEGO1/omni/include/mxeventmanager.h @@ -9,9 +9,9 @@ class MxEventManager : public MxMediaManager { public: MxEventManager(); - virtual ~MxEventManager() override; + ~MxEventManager() override; - virtual void Destroy() override; // vtable+18 + void Destroy() override; // vtable+18 virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+28 // SYNTHETIC: LEGO1 0x100c03d0 diff --git a/LEGO1/omni/include/mxeventpresenter.h b/LEGO1/omni/include/mxeventpresenter.h index 52d503df..1812280f 100644 --- a/LEGO1/omni/include/mxeventpresenter.h +++ b/LEGO1/omni/include/mxeventpresenter.h @@ -9,26 +9,26 @@ class MxEventPresenter : public MxMediaPresenter { public: MxEventPresenter(); - virtual ~MxEventPresenter() override; + ~MxEventPresenter() override; // FUNCTION: LEGO1 0x100c2c30 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101dcc return "MxEventPresenter"; } // FUNCTION: LEGO1 0x100c2c40 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxEventPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual MxResult PutData() override; // vtable+0x4c + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + MxResult PutData() override; // vtable+0x4c virtual void CopyData(MxStreamChunk* p_chunk); // vtable+0x5c // SYNTHETIC: LEGO1 0x100c2d20 diff --git a/LEGO1/omni/include/mxflcpresenter.h b/LEGO1/omni/include/mxflcpresenter.h index c8f9854d..569fa06c 100644 --- a/LEGO1/omni/include/mxflcpresenter.h +++ b/LEGO1/omni/include/mxflcpresenter.h @@ -11,25 +11,25 @@ class MxFlcPresenter : public MxVideoPresenter { public: MxFlcPresenter(); - virtual ~MxFlcPresenter() override; + ~MxFlcPresenter() override; // FUNCTION: LEGO1 0x1004e200 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxFlcPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); } // FUNCTION: LEGO1 0x100b33f0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f43c8 return "MxFlcPresenter"; } - virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c - virtual void CreateBitmap() override; // vtable+0x60 - virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 - virtual void RealizePalette() override; // vtable+0x70 + void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c + void CreateBitmap() override; // vtable+0x60 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void RealizePalette() override; // vtable+0x70 // SYNTHETIC: LEGO1 0x100b3400 // MxFlcPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxhashtable.h b/LEGO1/omni/include/mxhashtable.h index 056ff402..f2506758 100644 --- a/LEGO1/omni/include/mxhashtable.h +++ b/LEGO1/omni/include/mxhashtable.h @@ -46,7 +46,7 @@ class MxHashTable : protected MxCollection { m_resizeOption = e_noExpand; } - virtual ~MxHashTable() override; + ~MxHashTable() override; void Resize(); void Add(T); @@ -99,8 +99,9 @@ MxBool MxHashTableCursor::Find(T p_obj) MxHashTableNode* t = m_table->m_slots[bucket]; while (t) { - if (t->m_hash == hash && !m_table->Compare(t->m_obj, p_obj)) + if (t->m_hash == hash && !m_table->Compare(t->m_obj, p_obj)) { m_match = t; + } t = t->m_next; } @@ -122,8 +123,9 @@ void MxHashTableCursor::DeleteMatch() { // Cut the matching node out of the linked list // by updating pointer references. - if (m_match == NULL) + if (m_match == NULL) { return; + } if (m_match->m_prev) { m_match->m_prev->m_next = m_match->m_next; @@ -134,8 +136,9 @@ void MxHashTableCursor::DeleteMatch() m_table->m_slots[bucket] = m_match->m_next; } - if (m_match->m_next) + if (m_match->m_next) { m_match->m_next->m_prev = m_match->m_prev; + } m_table->m_customDestructor(m_match->m_obj); delete m_match; @@ -210,8 +213,9 @@ inline void MxHashTable::NodeInsert(MxHashTableNode* p_node) p_node->m_next = m_slots[bucket]; - if (m_slots[bucket]) + if (m_slots[bucket]) { m_slots[bucket]->m_prev = p_node; + } m_slots[bucket] = p_node; this->m_count++; @@ -220,8 +224,9 @@ inline void MxHashTable::NodeInsert(MxHashTableNode* p_node) template inline void MxHashTable::Add(T p_newobj) { - if (m_resizeOption && ((this->m_count + 1) / m_numSlots) > m_autoResizeRatio) + if (m_resizeOption && ((this->m_count + 1) / m_numSlots) > m_autoResizeRatio) { MxHashTable::Resize(); + } MxU32 hash = Hash(p_newobj); MxHashTableNode* node = new MxHashTableNode(p_newobj, hash); diff --git a/LEGO1/omni/include/mxioinfo.h b/LEGO1/omni/include/mxioinfo.h index 2a978b63..7fc3c343 100644 --- a/LEGO1/omni/include/mxioinfo.h +++ b/LEGO1/omni/include/mxioinfo.h @@ -9,10 +9,11 @@ #include // clang-format on +// SIZE 0x48 class MXIOINFO { public: MXIOINFO(); - __declspec(dllexport) ~MXIOINFO(); + ~MXIOINFO(); MxU16 Open(const char*, MxULong); MxU16 Close(MxLong); diff --git a/LEGO1/omni/include/mxlist.h b/LEGO1/omni/include/mxlist.h index 99330975..5ad02492 100644 --- a/LEGO1/omni/include/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -51,10 +51,10 @@ class MxList : protected MxCollection { m_first = NULL; } - virtual ~MxList() override; + ~MxList() override; - void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); }; - void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); }; + void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); } + void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); } void DeleteAll(MxBool p_destroy = TRUE); MxU32 GetCount() { return this->m_count; } @@ -75,7 +75,7 @@ class MxPtrList : public MxList { public: MxPtrList(MxBool p_ownership) { SetOwnership(p_ownership); } - static void Destroy(T* p_obj) { delete p_obj; }; + static void Destroy(T* p_obj) { delete p_obj; } void SetOwnership(MxBool p_ownership) { @@ -121,8 +121,9 @@ class MxListCursor : public MxCore { // TODO: Probably shouldn't exist void NextFragment() { - if (m_match) + if (m_match) { m_match = m_match->GetNext(); + } } private: @@ -147,13 +148,15 @@ template inline void MxList::DeleteAll(MxBool p_destroy) { for (MxListEntry* t = m_first;;) { - if (!t) + if (!t) { break; + } MxListEntry* next = t->GetNext(); - if (p_destroy) + if (p_destroy) { this->m_customDestructor(t->GetValue()); + } delete t; t = next; @@ -169,15 +172,19 @@ inline MxListEntry* MxList::InsertEntry(T p_newobj, MxListEntry* p_prev { MxListEntry* newEntry = new MxListEntry(p_newobj, p_prev, p_next); - if (p_prev) + if (p_prev) { p_prev->SetNext(newEntry); - else + } + else { this->m_first = newEntry; + } - if (p_next) + if (p_next) { p_next->SetPrev(newEntry); - else + } + else { this->m_last = newEntry; + } this->m_count++; return newEntry; @@ -186,15 +193,19 @@ inline MxListEntry* MxList::InsertEntry(T p_newobj, MxListEntry* p_prev template inline void MxList::DeleteEntry(MxListEntry* p_match) { - if (p_match->GetPrev()) + if (p_match->GetPrev()) { p_match->GetPrev()->SetNext(p_match->GetNext()); - else + } + else { m_first = p_match->GetNext(); + } - if (p_match->GetNext()) + if (p_match->GetNext()) { p_match->GetNext()->SetPrev(p_match->GetPrev()); - else + } + else { m_last = p_match->GetPrev(); + } delete p_match; this->m_count--; @@ -204,8 +215,9 @@ template inline MxBool MxListCursor::Find(T p_obj) { for (m_match = m_list->m_first; m_match && m_list->Compare(m_match->GetValue(), p_obj); - m_match = m_match->GetNext()) + m_match = m_match->GetNext()) { ; + } return m_match != NULL; } @@ -232,10 +244,12 @@ inline void MxListCursor::Destroy() template inline MxBool MxListCursor::Next() { - if (!m_match) + if (!m_match) { m_match = m_list->m_first; - else + } + else { m_match = m_match->GetNext(); + } return m_match != NULL; } @@ -243,13 +257,16 @@ inline MxBool MxListCursor::Next() template inline MxBool MxListCursor::Next(T& p_obj) { - if (!m_match) + if (!m_match) { m_match = m_list->m_first; - else + } + else { m_match = m_match->GetNext(); + } - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -257,10 +274,12 @@ inline MxBool MxListCursor::Next(T& p_obj) template inline MxBool MxListCursor::Prev() { - if (!m_match) + if (!m_match) { m_match = m_list->m_last; - else + } + else { m_match = m_match->GetPrev(); + } return m_match != NULL; } @@ -268,13 +287,16 @@ inline MxBool MxListCursor::Prev() template inline MxBool MxListCursor::Prev(T& p_obj) { - if (!m_match) + if (!m_match) { m_match = m_list->m_last; - else + } + else { m_match = m_match->GetPrev(); + } - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -282,8 +304,9 @@ inline MxBool MxListCursor::Prev(T& p_obj) template inline MxBool MxListCursor::Current(T& p_obj) { - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -292,8 +315,9 @@ template inline MxBool MxListCursor::First(T& p_obj) { m_match = m_list->m_first; - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -302,8 +326,9 @@ template inline MxBool MxListCursor::Last(T& p_obj) { m_match = m_list->m_last; - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -311,15 +336,17 @@ inline MxBool MxListCursor::Last(T& p_obj) template inline void MxListCursor::SetValue(T p_obj) { - if (m_match) + if (m_match) { m_match->SetValue(p_obj); + } } template inline void MxListCursor::Prepend(T p_newobj) { - if (m_match) + if (m_match) { m_list->InsertEntry(p_newobj, m_match->GetPrev(), m_match); + } } #endif // MXLIST_H diff --git a/LEGO1/omni/include/mxloopingflcpresenter.h b/LEGO1/omni/include/mxloopingflcpresenter.h index 7075332d..1bc76e18 100644 --- a/LEGO1/omni/include/mxloopingflcpresenter.h +++ b/LEGO1/omni/include/mxloopingflcpresenter.h @@ -9,20 +9,20 @@ class MxLoopingFlcPresenter : public MxFlcPresenter { public: MxLoopingFlcPresenter(); - virtual ~MxLoopingFlcPresenter() override; + ~MxLoopingFlcPresenter() override; // FUNCTION: LEGO1 0x100b4380 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101e20 return "MxLoopingFlcPresenter"; } - virtual void RepeatingTickle() override; // vtable+0x24 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void NextFrame() override; // vtable+0x64 - virtual void VTable0x88(); // vtable+0x88 + void RepeatingTickle() override; // vtable+0x24 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void NextFrame() override; // vtable+0x64 + virtual void VTable0x88(); // vtable+0x88 // SYNTHETIC: LEGO1 0x100b4390 // MxLoopingFlcPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxloopingmidipresenter.h b/LEGO1/omni/include/mxloopingmidipresenter.h index e47ef30d..1a9eff73 100644 --- a/LEGO1/omni/include/mxloopingmidipresenter.h +++ b/LEGO1/omni/include/mxloopingmidipresenter.h @@ -8,21 +8,21 @@ class MxLoopingMIDIPresenter : public MxMIDIPresenter { public: // FUNCTION: LEGO1 0x100b1830 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101de0 return "MxLoopingMIDIPresenter"; } // FUNCTION: LEGO1 0x100b1840 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxLoopingMIDIPresenter::ClassName()) || MxMIDIPresenter::IsA(p_name); } - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual MxResult PutData() override; // vtable+0x4c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + MxResult PutData() override; // vtable+0x4c }; // SYNTHETIC: LEGO1 0x100b19c0 diff --git a/LEGO1/omni/include/mxloopingsmkpresenter.h b/LEGO1/omni/include/mxloopingsmkpresenter.h index 9506de84..de0f506f 100644 --- a/LEGO1/omni/include/mxloopingsmkpresenter.h +++ b/LEGO1/omni/include/mxloopingsmkpresenter.h @@ -9,21 +9,21 @@ class MxLoopingSmkPresenter : public MxSmkPresenter { public: MxLoopingSmkPresenter(); - virtual ~MxLoopingSmkPresenter() override; // vtable+0x0 + ~MxLoopingSmkPresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x100b4920 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101e08 return "MxLoopingSmkPresenter"; } - virtual void RepeatingTickle() override; // vtable+0x24 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void NextFrame() override; // vtable+0x64 - virtual void VTable0x88() override; // vtable+0x88 - virtual void VTable0x8c(); // vtable+0x8c + void RepeatingTickle() override; // vtable+0x24 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void NextFrame() override; // vtable+0x64 + void VTable0x88() override; // vtable+0x88 + virtual void VTable0x8c(); // vtable+0x8c private: void Init(); diff --git a/LEGO1/omni/include/mxmediamanager.h b/LEGO1/omni/include/mxmediamanager.h index 25853adf..77720bf3 100644 --- a/LEGO1/omni/include/mxmediamanager.h +++ b/LEGO1/omni/include/mxmediamanager.h @@ -12,9 +12,9 @@ class MxMediaManager : public MxCore { public: MxMediaManager(); - virtual ~MxMediaManager() override; + ~MxMediaManager() override; - virtual MxResult Tickle() override; // vtable+08 + MxResult Tickle() override; // vtable+08 virtual MxResult InitPresenters(); // vtable+14 virtual void Destroy(); // vtable+18 virtual void RegisterPresenter(MxPresenter& p_presenter); // vtable+1c @@ -27,8 +27,8 @@ class MxMediaManager : public MxCore { // MxMediaManager::`scalar deleting destructor' protected: - MxPresenterList* m_presenters; // 0x8 - MxThread* m_thread; // 0xc + MxPresenterList* m_presenters; // 0x08 + MxThread* m_thread; // 0x0c MxCriticalSection m_criticalSection; // 0x10 }; diff --git a/LEGO1/omni/include/mxmediapresenter.h b/LEGO1/omni/include/mxmediapresenter.h index 954a2dcc..fba44880 100644 --- a/LEGO1/omni/include/mxmediapresenter.h +++ b/LEGO1/omni/include/mxmediapresenter.h @@ -13,34 +13,34 @@ class MxMediaPresenter : public MxPresenter { inline MxMediaPresenter() { Init(); } // FUNCTION: LEGO1 0x1000c550 - virtual ~MxMediaPresenter() override { Destroy(TRUE); }; + ~MxMediaPresenter() override { Destroy(TRUE); } - virtual MxResult Tickle() override; // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1000c5c0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f074c return "MxMediaPresenter"; } // FUNCTION: LEGO1 0x1000c5d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxMediaPresenter::ClassName()) || MxPresenter::IsA(p_name); } - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void DoneTickle() override; // vtable+0x2c + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void DoneTickle() override; // vtable+0x2c // FUNCTION: LEGO1 0x1000c5b0 - virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 - virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void LoopChunk(MxStreamChunk* p_chunk); // vtable+0x58 + MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void Enable(MxBool p_enable) override; // vtable+0x54 + virtual void LoopChunk(MxStreamChunk* p_chunk); // vtable+0x58 // SYNTHETIC: LEGO1 0x1000c680 // MxMediaPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxmidipresenter.h b/LEGO1/omni/include/mxmidipresenter.h index 0bde447c..3dabbc0e 100644 --- a/LEGO1/omni/include/mxmidipresenter.h +++ b/LEGO1/omni/include/mxmidipresenter.h @@ -9,29 +9,29 @@ class MxMIDIPresenter : public MxMusicPresenter { public: MxMIDIPresenter(); - virtual ~MxMIDIPresenter() override; + ~MxMIDIPresenter() override; // FUNCTION: LEGO1 0x100c2650 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101df8 return "MxMIDIPresenter"; } // FUNCTION: LEGO1 0x100c2660 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxMIDIPresenter::ClassName()) || MxMusicPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual void Destroy() override; // vtable+0x38 - virtual void EndAction() override; // vtable+0x40 - virtual MxResult PutData() override; // vtable+0x4c - virtual void SetVolume(MxS32 p_volume) override; // vtable+0x60 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + MxResult PutData() override; // vtable+0x4c + void SetVolume(MxS32 p_volume) override; // vtable+0x60 // SYNTHETIC: LEGO1 0x100c27a0 // MxMIDIPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxmusicmanager.h b/LEGO1/omni/include/mxmusicmanager.h index 2a8b30e5..1107e7e3 100644 --- a/LEGO1/omni/include/mxmusicmanager.h +++ b/LEGO1/omni/include/mxmusicmanager.h @@ -11,10 +11,10 @@ class MxMusicManager : public MxAudioManager { public: MxMusicManager(); - virtual ~MxMusicManager() override; + ~MxMusicManager() override; - virtual void Destroy() override; // vtable+18 - virtual void SetVolume(MxS32 p_volume) override; // vtable+2c + void Destroy() override; // vtable+18 + void SetVolume(MxS32 p_volume) override; // vtable+2c virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+30 inline MxBool GetMIDIInitialized() { return m_midiInitialized; } diff --git a/LEGO1/omni/include/mxmusicpresenter.h b/LEGO1/omni/include/mxmusicpresenter.h index 88be5c7f..a66afa78 100644 --- a/LEGO1/omni/include/mxmusicpresenter.h +++ b/LEGO1/omni/include/mxmusicpresenter.h @@ -8,23 +8,23 @@ class MxMusicPresenter : public MxAudioPresenter { public: MxMusicPresenter(); - virtual ~MxMusicPresenter() override; + ~MxMusicPresenter() override; // FUNCTION: LEGO1 0x100c23a0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101e48 return "MxMusicPresenter"; } // FUNCTION: LEGO1 0x100c23b0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxMusicPresenter::ClassName()) || MxAudioPresenter::IsA(p_name); } - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 // SYNTHETIC: LEGO1 0x100c24c0 // MxMusicPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxnextactiondatastart.h b/LEGO1/omni/include/mxnextactiondatastart.h index 3b58a338..0f08ec75 100644 --- a/LEGO1/omni/include/mxnextactiondatastart.h +++ b/LEGO1/omni/include/mxnextactiondatastart.h @@ -16,14 +16,14 @@ class MxNextActionDataStart : public MxCore { } // FUNCTION: LEGO1 0x100c1900 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x101025a0 return "MxNextActionDataStart"; } // FUNCTION: LEGO1 0x100c1910 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxNextActionDataStart::ClassName()) || MxCore::IsA(p_name); } diff --git a/LEGO1/omni/include/mxnotificationmanager.h b/LEGO1/omni/include/mxnotificationmanager.h index 4ed58f62..287ae40b 100644 --- a/LEGO1/omni/include/mxnotificationmanager.h +++ b/LEGO1/omni/include/mxnotificationmanager.h @@ -16,8 +16,8 @@ class MxNotification { inline MxNotificationParam* GetParam() { return m_param; } private: - MxCore* m_target; // 0x0 - MxNotificationParam* m_param; // 0x4 + MxCore* m_target; // 0x00 + MxNotificationParam* m_param; // 0x04 }; class MxIdList : public list {}; @@ -27,8 +27,8 @@ class MxNotificationPtrList : public list {}; // VTABLE: LEGO1 0x100dc078 class MxNotificationManager : public MxCore { private: - MxNotificationPtrList* m_queue; // 0x8 - MxNotificationPtrList* m_sendList; // 0xc + MxNotificationPtrList* m_queue; // 0x08 + MxNotificationPtrList* m_sendList; // 0x0c MxCriticalSection m_lock; // 0x10 MxS32 m_unk0x2c; // 0x2c MxIdList m_listenerIds; // 0x30 @@ -36,9 +36,9 @@ class MxNotificationManager : public MxCore { public: MxNotificationManager(); - virtual ~MxNotificationManager(); // vtable+0x0 (scalar deleting destructor) + ~MxNotificationManager() override; // vtable+0x00 (scalar deleting destructor) - virtual MxResult Tickle(); // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // TODO: Where does this method come from? virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x14 void Register(MxCore* p_listener); diff --git a/LEGO1/omni/include/mxnotificationparam.h b/LEGO1/omni/include/mxnotificationparam.h index e990abe6..d0ad675f 100644 --- a/LEGO1/omni/include/mxnotificationparam.h +++ b/LEGO1/omni/include/mxnotificationparam.h @@ -23,7 +23,7 @@ enum NotificationId { c_notificationDragStart = 13, c_notificationDrag = 14, c_notificationTimer = 15, // 100d6aa0 - c_notificationType17 = 17, + c_notificationClick = 17, c_notificationType18 = 18, // 100d7e80 c_notificationType19 = 19, // 100d6230 c_notificationType20 = 20, @@ -42,12 +42,15 @@ class MxNotificationParam : public MxParam { } // FUNCTION: LEGO1 0x10010390 - virtual MxNotificationParam* Clone() { return new MxNotificationParam(m_type, m_sender); }; // vtable+0x4 + virtual MxNotificationParam* Clone() { return new MxNotificationParam(m_type, m_sender); } // vtable+0x04 inline NotificationId GetNotification() const { return m_type; } inline MxCore* GetSender() const { return m_sender; } inline NotificationId GetType() const { return m_type; } + inline void SetType(NotificationId p_type) { m_type = p_type; } + inline void SetSender(MxCore* p_sender) { m_sender = p_sender; } + protected: NotificationId m_type; // 0x04 MxCore* m_sender; // 0x08 diff --git a/LEGO1/omni/include/mxobjectfactory.h b/LEGO1/omni/include/mxobjectfactory.h index 4ae3e348..aed354c4 100644 --- a/LEGO1/omni/include/mxobjectfactory.h +++ b/LEGO1/omni/include/mxobjectfactory.h @@ -24,14 +24,14 @@ class MxObjectFactory : public MxCore { MxObjectFactory(); // FUNCTION: LEGO1 0x10008f70 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0730 return "MxObjectFactory"; } // FUNCTION: LEGO1 0x10008f80 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxObjectFactory::ClassName()) || MxCore::IsA(p_name); } diff --git a/LEGO1/omni/include/mxomni.h b/LEGO1/omni/include/mxomni.h index 9ade97b3..e82bf84f 100644 --- a/LEGO1/omni/include/mxomni.h +++ b/LEGO1/omni/include/mxomni.h @@ -28,19 +28,19 @@ class MxStreamController; // SIZE 0x68 class MxOmni : public MxCore { public: - __declspec(dllexport) static void DestroyInstance(); - __declspec(dllexport) static const char* GetCD(); - __declspec(dllexport) static const char* GetHD(); - __declspec(dllexport) static MxOmni* GetInstance(); - __declspec(dllexport) static MxBool IsSound3D(); - __declspec(dllexport) static void SetCD(const char* p_cd); - __declspec(dllexport) static void SetHD(const char* p_hd); - __declspec(dllexport) static void SetSound3D(MxBool p_use3dSound); + static void DestroyInstance(); + static const char* GetCD(); + static const char* GetHD(); + static MxOmni* GetInstance(); + static MxBool IsSound3D(); + static void SetCD(const char* p_cd); + static void SetHD(const char* p_hd); + static void SetSound3D(MxBool p_use3dSound); MxOmni(); - virtual ~MxOmni() override; + ~MxOmni() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+04 + MxLong Notify(MxParam& p_param) override; // vtable+04 virtual void Init(); // vtable+14 virtual MxResult Create(MxOmniCreateParam& p_param); // vtable+18 virtual void Destroy(); // vtable+1c @@ -48,13 +48,13 @@ class MxOmni : public MxCore { virtual void DeleteObject(MxDSAction& p_dsAction); // vtable+24 virtual MxBool DoesEntityExist(MxDSAction& p_dsAction); // vtable+28 virtual MxResult CreatePresenter(MxStreamController* p_controller, MxDSAction& p_action); // vtable+2c - virtual MxEntity* FindWorld(const char*, MxS32, MxPresenter*); // vtable+30 + virtual MxEntity* AddToWorld(const char*, MxS32, MxPresenter*); // vtable+30 virtual void NotifyCurrentEntity(MxNotificationParam* p_param); // vtable+34 virtual void StartTimer(); // vtable+38 virtual void StopTimer(); // vtable+3c // FUNCTION: LEGO1 0x10058a90 - virtual MxBool IsTimerRunning() { return m_timerRunning; }; // vtable+40 + virtual MxBool IsTimerRunning() { return m_timerRunning; } // vtable+40 static void SetInstance(MxOmni* p_instance); static MxBool ActionSourceEquals(MxDSAction* p_action, const char* p_name); @@ -79,32 +79,32 @@ class MxOmni : public MxCore { protected: static MxOmni* g_instance; - MxString m_mediaPath; // 0x8 + MxString m_mediaPath; // 0x08 HWND m_windowHandle; // 0x18 - MxObjectFactory* m_objectFactory; // 0x1C + MxObjectFactory* m_objectFactory; // 0x1c MxVariableTable* m_variableTable; // 0x20 MxTickleManager* m_tickleManager; // 0x24 MxNotificationManager* m_notificationManager; // 0x28 - MxVideoManager* m_videoManager; // 0x2C + MxVideoManager* m_videoManager; // 0x2c MxSoundManager* m_soundManager; // 0x30 MxMusicManager* m_musicManager; // 0x34 MxEventManager* m_eventManager; // 0x38 - MxTimer* m_timer; // 0x3C + MxTimer* m_timer; // 0x3c MxStreamer* m_streamer; // 0x40 MxAtomIdCounterSet* m_atomIdCounterSet; // 0x44 MxCriticalSection m_criticalsection; // 0x48 MxBool m_timerRunning; // 0x64 }; -__declspec(dllexport) MxTickleManager* TickleManager(); -__declspec(dllexport) MxTimer* Timer(); -__declspec(dllexport) MxStreamer* Streamer(); -__declspec(dllexport) MxSoundManager* MSoundManager(); -__declspec(dllexport) MxVariableTable* VariableTable(); -__declspec(dllexport) MxMusicManager* MusicManager(); -__declspec(dllexport) MxEventManager* EventManager(); -__declspec(dllexport) MxResult Start(MxDSAction*); -__declspec(dllexport) MxNotificationManager* NotificationManager(); +MxTickleManager* TickleManager(); +MxTimer* Timer(); +MxStreamer* Streamer(); +MxSoundManager* MSoundManager(); +MxVariableTable* VariableTable(); +MxMusicManager* MusicManager(); +MxEventManager* EventManager(); +MxResult Start(MxDSAction*); +MxNotificationManager* NotificationManager(); MxVideoManager* MVideoManager(); MxAtomIdCounterSet* AtomIdCounterSet(); diff --git a/LEGO1/omni/include/mxomnicreateflags.h b/LEGO1/omni/include/mxomnicreateflags.h index 24b1e942..1e9f334d 100644 --- a/LEGO1/omni/include/mxomnicreateflags.h +++ b/LEGO1/omni/include/mxomnicreateflags.h @@ -21,7 +21,7 @@ class MxOmniCreateFlags { c_createStreamer = 0x04 }; - __declspec(dllexport) MxOmniCreateFlags(); + MxOmniCreateFlags(); inline const MxBool CreateObjectFactory() const { return this->m_flags1 & c_createObjectFactory; } inline const MxBool CreateVariableTable() const { return this->m_flags1 & c_createVariableTable; } diff --git a/LEGO1/omni/include/mxomnicreateparam.h b/LEGO1/omni/include/mxomnicreateparam.h index 53539bc6..8d04ed18 100644 --- a/LEGO1/omni/include/mxomnicreateparam.h +++ b/LEGO1/omni/include/mxomnicreateparam.h @@ -11,7 +11,7 @@ // VTABLE: LEGO1 0x100dc218 class MxOmniCreateParam : public MxParam { public: - __declspec(dllexport) MxOmniCreateParam( + MxOmniCreateParam( const char* p_mediaPath, struct HWND__* p_windowHandle, MxVideoParam& p_vparam, diff --git a/LEGO1/omni/include/mxpalette.h b/LEGO1/omni/include/mxpalette.h index 5ed5e80f..4f38c91b 100644 --- a/LEGO1/omni/include/mxpalette.h +++ b/LEGO1/omni/include/mxpalette.h @@ -10,12 +10,12 @@ // SIZE 0x414 class MxPalette : public MxCore { public: - __declspec(dllexport) MxBool operator==(MxPalette& p_other); - __declspec(dllexport) void Detach(); + MxBool operator==(MxPalette& p_other); + void Detach(); MxPalette(); MxPalette(const RGBQUAD*); - virtual ~MxPalette(); + ~MxPalette() override; void ApplySystemEntriesToPalette(LPPALETTEENTRY p_entries); MxPalette* Clone(); @@ -33,7 +33,7 @@ class MxPalette : public MxCore { private: LPDIRECTDRAWPALETTE m_palette; - PALETTEENTRY m_entries[256]; // 0xc + PALETTEENTRY m_entries[256]; // 0x0c MxBool m_overrideSkyColor; // 0x40c PALETTEENTRY m_skyColor; // 0x40d }; diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h index a6b3eca8..cd403949 100644 --- a/LEGO1/omni/include/mxpresenter.h +++ b/LEGO1/omni/include/mxpresenter.h @@ -28,24 +28,20 @@ class MxPresenter : public MxCore { MxPresenter() { Init(); } -#ifdef ISLE_APP - __declspec(dllexport) virtual ~MxPresenter() override; // vtable+0x00 -#else // FUNCTION: LEGO1 0x1000bf00 - __declspec(dllexport) virtual ~MxPresenter() override{}; // vtable+0x00 -#endif + ~MxPresenter() override{}; // vtable+0x00 - __declspec(dllexport) virtual MxResult Tickle() override; // vtable+0x08 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1000bfe0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0740 return "MxPresenter"; } // FUNCTION: LEGO1 0x1000bff0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxPresenter::ClassName()) || MxCore::IsA(p_name); } @@ -64,23 +60,19 @@ class MxPresenter : public MxCore { virtual void StartingTickle() { ProgressTickleState(e_streaming); } // vtable+0x1c // FUNCTION: LEGO1 0x1000be80 - virtual void StreamingTickle() { ProgressTickleState(e_repeating); }; // vtable+0x20 + virtual void StreamingTickle() { ProgressTickleState(e_repeating); } // vtable+0x20 // FUNCTION: LEGO1 0x1000bea0 - virtual void RepeatingTickle() { ProgressTickleState(e_unk5); }; // vtable+0x24 + virtual void RepeatingTickle() { ProgressTickleState(e_unk5); } // vtable+0x24 // FUNCTION: LEGO1 0x1000bec0 - virtual void Unk5Tickle() { ProgressTickleState(e_done); }; // vtable+0x28 + virtual void Unk5Tickle() { ProgressTickleState(e_done); } // vtable+0x28 protected: -#ifdef ISLE_APP - __declspec(dllexport) virtual void DoneTickle(); // vtable+0x2c -#else // FUNCTION: LEGO1 0x1000bee0 - __declspec(dllexport) virtual void DoneTickle() { ProgressTickleState(e_idle); }; // vtable+0x2c -#endif + virtual void DoneTickle() { ProgressTickleState(e_idle); } // vtable+0x2c - __declspec(dllexport) virtual void ParseExtra(); // vtable+0x30 + virtual void ParseExtra(); // vtable+0x30 inline void ProgressTickleState(TickleState p_tickleState) { @@ -90,13 +82,13 @@ class MxPresenter : public MxCore { public: // FUNCTION: LEGO1 0x1000bf70 - virtual MxResult AddToManager() { return SUCCESS; }; // vtable+0x34 + virtual MxResult AddToManager() { return SUCCESS; } // vtable+0x34 // FUNCTION: LEGO1 0x1000bf80 - virtual void Destroy() { Init(); }; // vtable+0x38 + virtual void Destroy() { Init(); } // vtable+0x38 - __declspec(dllexport) virtual MxResult StartAction(MxStreamController*, MxDSAction*); // vtable+0x3c - __declspec(dllexport) virtual void EndAction(); // vtable+0x40 + virtual MxResult StartAction(MxStreamController*, MxDSAction*); // vtable+0x3c + virtual void EndAction(); // vtable+0x40 // FUNCTION: LEGO1 0x1000bf90 virtual void SetTickleState(TickleState p_tickleState) { ProgressTickleState(p_tickleState); } // vtable+0x44 @@ -105,15 +97,15 @@ class MxPresenter : public MxCore { virtual MxBool HasTickleStatePassed(TickleState p_tickleState) { return m_previousTickleStates & (1 << (MxU8) p_tickleState); - }; // vtable+0x48 + } // vtable+0x48 // FUNCTION: LEGO1 0x1000bfc0 - virtual MxResult PutData() { return SUCCESS; }; // vtable+0x4c + virtual MxResult PutData() { return SUCCESS; } // vtable+0x4c // FUNCTION: LEGO1 0x1000bfd0 - virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) { return FALSE; }; // vtable+0x50 + virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) { return FALSE; } // vtable+0x50 - __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 + virtual void Enable(MxBool p_enable); // vtable+0x54 MxEntity* CreateEntity(const char* p_name); void SendToCompositePresenter(MxOmni*); @@ -129,13 +121,15 @@ class MxPresenter : public MxCore { m_compositePresenter = p_compositePresenter; } + inline void SetDisplayZ(MxS32 p_displayZ) { m_displayZ = p_displayZ; } + // SYNTHETIC: LEGO1 0x1000c070 // MxPresenter::`scalar deleting destructor' protected: - __declspec(dllexport) void Init(); + void Init(); - TickleState m_currentTickleState; // 0x8 + TickleState m_currentTickleState; // 0x08 MxU32 m_previousTickleStates; // 0x0c MxPoint32 m_location; // 0x10 MxS32 m_displayZ; // 0x18 diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index 257d0996..1c52f360 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -14,10 +14,10 @@ class MxPresenterList : public MxPtrList { MxPresenterList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x1001cd00 - virtual MxS8 Compare(MxPresenter* p_a, MxPresenter* p_b) override + MxS8 Compare(MxPresenter* p_a, MxPresenter* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; - }; // vtable+0x14 + } // vtable+0x14 // SYNTHETIC: LEGO1 0x1001ceb0 // MxPresenterList::`scalar deleting destructor' @@ -68,4 +68,34 @@ class MxPresenterListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x1001d090 // MxPtrList::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x1001d100 +// MxPresenterList::~MxPresenterList + +// SYNTHETIC: LEGO1 0x1001eed0 +// MxPresenterListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001ef40 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001ef90 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f000 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f070 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001f0c0 +// MxPresenterListCursor::~MxPresenterListCursor + +// TEMPLATE: LEGO1 0x10020760 +// MxListCursor::MxListCursor + +// TEMPLATE: LEGO1 0x10022380 +// MxList::InsertEntry + +// TEMPLATE: LEGO1 0x100225e0 +// MxList::DeleteEntry + #endif // MXPRESENTERLIST_H diff --git a/LEGO1/omni/include/mxramstreamcontroller.h b/LEGO1/omni/include/mxramstreamcontroller.h index 6b56ee49..820fc3f7 100644 --- a/LEGO1/omni/include/mxramstreamcontroller.h +++ b/LEGO1/omni/include/mxramstreamcontroller.h @@ -12,22 +12,22 @@ class MxRAMStreamController : public MxStreamController { inline MxRAMStreamController() {} // FUNCTION: LEGO1 0x100b9430 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102118 return "MxRAMStreamController"; } // FUNCTION: LEGO1 0x100b9440 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxRAMStreamController::ClassName()) || !strcmp(p_name, MxStreamController::ClassName()) || MxCore::IsA(p_name); } - virtual MxResult Open(const char* p_filename) override; - virtual MxResult VTable0x20(MxDSAction* p_action) override; - virtual MxResult VTable0x24(MxDSAction* p_action) override; + MxResult Open(const char* p_filename) override; + MxResult VTable0x20(MxDSAction* p_action) override; + MxResult VTable0x24(MxDSAction* p_action) override; private: MxDSBuffer m_buffer; // 0x64 diff --git a/LEGO1/omni/include/mxramstreamprovider.h b/LEGO1/omni/include/mxramstreamprovider.h index f5ac0897..08c1ea95 100644 --- a/LEGO1/omni/include/mxramstreamprovider.h +++ b/LEGO1/omni/include/mxramstreamprovider.h @@ -8,26 +8,26 @@ class MxRAMStreamProvider : public MxStreamProvider { public: MxRAMStreamProvider(); - virtual ~MxRAMStreamProvider() override; + ~MxRAMStreamProvider() override; // FUNCTION: LEGO1 0x100d0970 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102864 return "MxRAMStreamProvider"; } // FUNCTION: LEGO1 0x100d0980 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxRAMStreamProvider::ClassName()) || MxStreamProvider::IsA(p_name); } - virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 - virtual MxU32 GetFileSize() override; // vtable+0x18 - virtual MxS32 GetStreamBuffersNum() override; // vtable+0x1c - virtual MxU32 GetLengthInDWords() override; // vtable+0x24 - virtual MxU32* GetBufferForDWords() override; // vtable+0x28 + MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 + MxU32 GetFileSize() override; // vtable+0x18 + MxS32 GetStreamBuffersNum() override; // vtable+0x1c + MxU32 GetLengthInDWords() override; // vtable+0x24 + MxU32* GetBufferForDWords() override; // vtable+0x28 inline MxU8* GetBufferOfFileSize() { return m_pBufferOfFileSize; } diff --git a/LEGO1/omni/include/mxrect32.h b/LEGO1/omni/include/mxrect32.h index b52a0c31..207d93fa 100644 --- a/LEGO1/omni/include/mxrect32.h +++ b/LEGO1/omni/include/mxrect32.h @@ -65,6 +65,7 @@ class MxRect32 { } inline MxBool IsValid() const { return m_left < m_right && m_top < m_bottom; } + inline MxBool IntersectsWith(const MxRect32& p_rect) const { return m_left < p_rect.m_right && p_rect.m_left < m_right && m_top < p_rect.m_bottom && p_rect.m_top < m_bottom; @@ -114,8 +115,8 @@ class MxRect32 { return this; } - inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; }; - inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; }; + inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; } + inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; } MxS32 m_left; // 0x00 MxS32 m_top; // 0x04 diff --git a/LEGO1/omni/include/mxregion.h b/LEGO1/omni/include/mxregion.h index 5659ba81..3bf639e1 100644 --- a/LEGO1/omni/include/mxregion.h +++ b/LEGO1/omni/include/mxregion.h @@ -11,7 +11,7 @@ class MxRegion : public MxCore { public: MxRegion(); - virtual ~MxRegion() override; + ~MxRegion() override; virtual void Reset(); // vtable+0x14 virtual void VTable0x18(MxRect32& p_rect); // vtable+0x18 diff --git a/LEGO1/omni/include/mxregioncursor.h b/LEGO1/omni/include/mxregioncursor.h index 5f4a24b8..e114c7ed 100644 --- a/LEGO1/omni/include/mxregioncursor.h +++ b/LEGO1/omni/include/mxregioncursor.h @@ -8,7 +8,7 @@ class MxRegionCursor : public MxCore { public: MxRegionCursor(MxRegion* p_region); - virtual ~MxRegionCursor() override; + ~MxRegionCursor() override; virtual MxRect32* VTable0x14(MxRect32& p_rect); // vtable+0x14 virtual MxRect32* VTable0x18(); // vtable+0x18 diff --git a/LEGO1/omni/include/mxscheduler.h b/LEGO1/omni/include/mxscheduler.h index 17b7ecb8..1f60029d 100644 --- a/LEGO1/omni/include/mxscheduler.h +++ b/LEGO1/omni/include/mxscheduler.h @@ -5,8 +5,8 @@ class MxScheduler { public: - __declspec(dllexport) static MxScheduler* GetInstance(); - __declspec(dllexport) void StartMultiTasking(MxULong); + static MxScheduler* GetInstance(); + void StartMultiTasking(MxULong); }; #endif // MXSCHEDULER_H diff --git a/LEGO1/omni/include/mxsmkpresenter.h b/LEGO1/omni/include/mxsmkpresenter.h index eeb12945..d17ce59d 100644 --- a/LEGO1/omni/include/mxsmkpresenter.h +++ b/LEGO1/omni/include/mxsmkpresenter.h @@ -10,28 +10,28 @@ class MxSmkPresenter : public MxVideoPresenter { public: MxSmkPresenter(); - virtual ~MxSmkPresenter() override; + ~MxSmkPresenter() override; // FUNCTION: LEGO1 0x100b3730 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101e38 return "MxSmkPresenter"; } // FUNCTION: LEGO1 0x100b3740 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxSmkPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c - virtual void CreateBitmap() override; // vtable+0x60 - virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 - virtual void RealizePalette() override; // vtable+0x70 - virtual void VTable0x88(); // vtable+0x88 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c + void CreateBitmap() override; // vtable+0x60 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void RealizePalette() override; // vtable+0x70 + virtual void VTable0x88(); // vtable+0x88 // SYNTHETIC: LEGO1 0x100b3850 // MxSmkPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxsoundmanager.h b/LEGO1/omni/include/mxsoundmanager.h index 5131e1e2..6dde7d5c 100644 --- a/LEGO1/omni/include/mxsoundmanager.h +++ b/LEGO1/omni/include/mxsoundmanager.h @@ -12,10 +12,10 @@ class MxSoundManager : public MxAudioManager { public: MxSoundManager(); - virtual ~MxSoundManager() override; // vtable+0x0 + ~MxSoundManager() override; // vtable+0x00 - virtual void Destroy() override; // vtable+0x18 - virtual void SetVolume(MxS32 p_volume) override; // vtable+0x2c + void Destroy() override; // vtable+0x18 + void SetVolume(MxS32 p_volume) override; // vtable+0x2c virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x30 virtual void Pause(); // vtable+0x34 virtual void Resume(); // vtable+0x38 @@ -24,7 +24,7 @@ class MxSoundManager : public MxAudioManager { MxS32 FUN_100aecf0(MxU32 p_undefined); -private: +protected: void Init(); void Destroy(MxBool p_fromDestructor); MxPresenter* FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_objectId); diff --git a/LEGO1/omni/include/mxsoundpresenter.h b/LEGO1/omni/include/mxsoundpresenter.h index 1949617f..1281b2be 100644 --- a/LEGO1/omni/include/mxsoundpresenter.h +++ b/LEGO1/omni/include/mxsoundpresenter.h @@ -9,25 +9,25 @@ class MxSoundPresenter : public MxAudioPresenter { public: // FUNCTION: LEGO1 0x1000d430 - virtual ~MxSoundPresenter() override { Destroy(TRUE); }; + ~MxSoundPresenter() override { Destroy(TRUE); } // FUNCTION: LEGO1 0x1000d4a0 - inline virtual const char* ClassName() const // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f07a0 return "MxSoundPresenter"; - }; + } // FUNCTION: LEGO1 0x1000d4b0 - inline virtual MxBool IsA(const char* p_name) const // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxSoundPresenter::ClassName()) || MxAudioPresenter::IsA(p_name); - }; + } - virtual MxResult AddToManager() override; // vtable+0x34 + MxResult AddToManager() override; // vtable+0x34 // FUNCTION: LEGO1 0x1000d490 - virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 // SYNTHETIC: LEGO1 0x1000d5c0 // MxSoundPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxstillpresenter.h b/LEGO1/omni/include/mxstillpresenter.h index 0fa48bf3..0fb92862 100644 --- a/LEGO1/omni/include/mxstillpresenter.h +++ b/LEGO1/omni/include/mxstillpresenter.h @@ -9,38 +9,39 @@ class MxStillPresenter : public MxVideoPresenter { public: MxStillPresenter() { m_bitmapInfo = NULL; } + // FUNCTION: LEGO1 0x10043550 - virtual ~MxStillPresenter() override { Destroy(TRUE); }; // vtable+0x00 + ~MxStillPresenter() override { Destroy(TRUE); } // vtable+0x00 // FUNCTION: LEGO1 0x100435c0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0184 return "MxStillPresenter"; } // FUNCTION: LEGO1 0x100435d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStillPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 // FUNCTION: LEGO1 0x100435b0 - virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c - virtual void CreateBitmap() override; // vtable+0x60 - virtual void NextFrame() override; // vtable+0x64 - virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 - virtual void RealizePalette() override; // vtable+0x70 - virtual void VTable0x88(MxS32 p_x, MxS32 p_y); // vtable+0x88 - virtual MxStillPresenter* Clone(); // vtable+0x8c + void Enable(MxBool p_enable) override; // vtable+0x54 + void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c + void CreateBitmap() override; // vtable+0x60 + void NextFrame() override; // vtable+0x64 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void RealizePalette() override; // vtable+0x70 + virtual void SetPosition(MxS32 p_x, MxS32 p_y); // vtable+0x88 + virtual MxStillPresenter* Clone(); // vtable+0x8c private: void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxstreamchunk.h b/LEGO1/omni/include/mxstreamchunk.h index 5b9ecb64..00e242d0 100644 --- a/LEGO1/omni/include/mxstreamchunk.h +++ b/LEGO1/omni/include/mxstreamchunk.h @@ -12,17 +12,17 @@ class MxStreamListMxDSSubscriber; class MxStreamChunk : public MxDSChunk { public: inline MxStreamChunk() : m_buffer(NULL) {} - virtual ~MxStreamChunk() override; + ~MxStreamChunk() override; // FUNCTION: LEGO1 0x100b1fe0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10101e5c return "MxStreamChunk"; } // FUNCTION: LEGO1 0x100b1ff0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamChunk::ClassName()) || MxDSChunk::IsA(p_name); } diff --git a/LEGO1/omni/include/mxstreamchunklist.h b/LEGO1/omni/include/mxstreamchunklist.h index 9d8aec0e..defdd4a0 100644 --- a/LEGO1/omni/include/mxstreamchunklist.h +++ b/LEGO1/omni/include/mxstreamchunklist.h @@ -19,7 +19,7 @@ class MxStreamChunkList : public MxList { MxStreamChunkList() { m_customDestructor = Destroy; } // FUNCTION: LEGO1 0x100b5900 - virtual MxS8 Compare(MxStreamChunk* p_a, MxStreamChunk* p_b) override + MxS8 Compare(MxStreamChunk* p_a, MxStreamChunk* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 diff --git a/LEGO1/omni/include/mxstreamcontroller.h b/LEGO1/omni/include/mxstreamcontroller.h index 57caae8e..f4bd328f 100644 --- a/LEGO1/omni/include/mxstreamcontroller.h +++ b/LEGO1/omni/include/mxstreamcontroller.h @@ -19,17 +19,17 @@ class MxDSStreamingAction; class MxStreamController : public MxCore { public: MxStreamController(); - virtual ~MxStreamController() override; // vtable+0x0 + ~MxStreamController() override; // vtable+0x00 // FUNCTION: LEGO1 0x100c0f10 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x10102130 return "MxStreamController"; } // FUNCTION: LEGO1 0x100c0f20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamController::ClassName()) || MxCore::IsA(p_name); } @@ -53,14 +53,14 @@ class MxStreamController : public MxCore { MxResult InsertActionToList54(MxDSAction* p_action); MxNextActionDataStart* FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action); - inline MxAtomId& GetAtom() { return m_atom; }; - inline MxStreamProvider* GetProvider() { return m_provider; }; - inline MxStreamListMxDSAction& GetUnk0x3c() { return m_unk0x3c; }; - inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; }; - inline MxStreamListMxDSSubscriber& GetSubscriberList() { return m_subscriberList; }; + inline MxAtomId& GetAtom() { return m_atom; } + inline MxStreamProvider* GetProvider() { return m_provider; } + inline MxStreamListMxDSAction& GetUnk0x3c() { return m_unk0x3c; } + inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; } + inline MxStreamListMxDSSubscriber& GetSubscriberList() { return m_subscriberList; } protected: - MxCriticalSection m_criticalSection; // 0x8 + MxCriticalSection m_criticalSection; // 0x08 MxAtomId m_atom; // 0x24 MxStreamProvider* m_provider; // 0x28 undefined4* m_unk0x2c; // 0x2c diff --git a/LEGO1/omni/include/mxstreamer.h b/LEGO1/omni/include/mxstreamer.h index f22e343f..2308981d 100644 --- a/LEGO1/omni/include/mxstreamer.h +++ b/LEGO1/omni/include/mxstreamer.h @@ -58,7 +58,7 @@ class MxStreamerNotification : public MxNotificationParam { m_controller = p_ctrlr; } - virtual MxNotificationParam* Clone() override; + MxNotificationParam* Clone() override; MxStreamController* GetController() { return m_controller; } @@ -76,22 +76,22 @@ class MxStreamer : public MxCore { }; MxStreamer(); - virtual ~MxStreamer() override; // vtable+0x0 + ~MxStreamer() override; // vtable+0x00 - __declspec(dllexport) MxStreamController* Open(const char* p_name, MxU16 p_openMode); - __declspec(dllexport) MxLong Close(const char* p_name); + MxStreamController* Open(const char* p_name, MxU16 p_openMode); + MxLong Close(const char* p_name); - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100b9000 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x1010210c return "MxStreamer"; } // FUNCTION: LEGO1 0x100b9010 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamer::ClassName()) || MxCore::IsA(p_name); } @@ -109,7 +109,7 @@ class MxStreamer : public MxCore { inline const MxStreamerSubClass3& GetSubclass2() { return m_subclass2; } private: - list m_openStreams; // 0x8 + list m_openStreams; // 0x08 MxStreamerSubClass2 m_subclass1; // 0x14 MxStreamerSubClass3 m_subclass2; // 0x20 }; diff --git a/LEGO1/omni/include/mxstreamlist.h b/LEGO1/omni/include/mxstreamlist.h index cbe53eae..0e0f1e9f 100644 --- a/LEGO1/omni/include/mxstreamlist.h +++ b/LEGO1/omni/include/mxstreamlist.h @@ -11,8 +11,9 @@ class MxStreamList : public list { public: MxBool PopFront(T& p_obj) { - if (this->empty()) + if (this->empty()) { return FALSE; + } p_obj = this->front(); this->pop_front(); @@ -20,7 +21,7 @@ class MxStreamList : public list { } }; -// SIZE 0xc +// SIZE 0x0c class MxStreamListMxDSAction : public MxStreamList { public: MxDSAction* Find(MxDSAction* p_action, MxBool p_delete); @@ -29,8 +30,9 @@ class MxStreamListMxDSAction : public MxStreamList { // instead of MxDSAction. Until then, we use this helper. MxBool PopFrontStreamingAction(MxDSStreamingAction*& p_obj) { - if (empty()) + if (empty()) { return FALSE; + } p_obj = (MxDSStreamingAction*) front(); pop_front(); @@ -38,14 +40,14 @@ class MxStreamListMxDSAction : public MxStreamList { } }; -// SIZE 0xc +// SIZE 0x0c class MxStreamListMxNextActionDataStart : public MxStreamList { public: MxNextActionDataStart* Find(MxU32 p_id, MxS16 p_value); MxNextActionDataStart* FindAndErase(MxU32 p_id, MxS16 p_value); }; -// SIZE 0xc +// SIZE 0x0c class MxStreamListMxDSSubscriber : public MxStreamList { public: MxDSSubscriber* Find(MxDSObject* p_object); diff --git a/LEGO1/omni/include/mxstreamprovider.h b/LEGO1/omni/include/mxstreamprovider.h index 803038e3..1082fffe 100644 --- a/LEGO1/omni/include/mxstreamprovider.h +++ b/LEGO1/omni/include/mxstreamprovider.h @@ -15,13 +15,13 @@ class MxStreamProvider : public MxCore { inline MxStreamProvider() : m_pLookup(NULL), m_pFile(NULL) {} // FUNCTION: LEGO1 0x100d07e0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { return "MxStreamProvider"; } // FUNCTION: LEGO1 0x100d07f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamProvider::ClassName()) || MxCore::IsA(p_name); } diff --git a/LEGO1/omni/include/mxstring.h b/LEGO1/omni/include/mxstring.h index 65c15d3e..f2a5c95a 100644 --- a/LEGO1/omni/include/mxstring.h +++ b/LEGO1/omni/include/mxstring.h @@ -7,9 +7,9 @@ // SIZE 0x10 class MxString : public MxCore { public: - __declspec(dllexport) MxString(const MxString& p_str); - __declspec(dllexport) virtual ~MxString(); - __declspec(dllexport) const MxString& operator=(const char* p_data); + MxString(const MxString& p_str); + ~MxString() override; + const MxString& operator=(const char* p_data); MxString(); MxString(const char*); @@ -21,6 +21,7 @@ class MxString : public MxCore { inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); } inline const char* GetData() const { return m_data; } + inline const MxU16 GetLength() const { return m_length; } // SYNTHETIC: LEGO1 0x100ae280 // MxString::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxthread.h b/LEGO1/omni/include/mxthread.h index 5ab80041..6016aa8f 100644 --- a/LEGO1/omni/include/mxthread.h +++ b/LEGO1/omni/include/mxthread.h @@ -47,7 +47,6 @@ class MxThread { class MxTickleThread : public MxThread { public: MxTickleThread(MxCore* p_target, MxS32 p_frequencyMS); - virtual ~MxTickleThread() {} MxResult Run() override; diff --git a/LEGO1/omni/include/mxticklemanager.h b/LEGO1/omni/include/mxticklemanager.h index 6ebd655b..f07d0dc3 100644 --- a/LEGO1/omni/include/mxticklemanager.h +++ b/LEGO1/omni/include/mxticklemanager.h @@ -24,10 +24,10 @@ class MxTickleClient { inline void SetFlags(MxU16 p_flags) { m_flags = p_flags; } private: - MxCore* m_client; // 0x0 - MxTime m_interval; // 0x4 - MxTime m_lastUpdateTime; // 0x8 - MxU16 m_flags; // 0xc + MxCore* m_client; // 0x00 + MxTime m_interval; // 0x04 + MxTime m_lastUpdateTime; // 0x08 + MxU16 m_flags; // 0x0c }; typedef list MxTickleClientPtrList; @@ -36,9 +36,9 @@ typedef list MxTickleClientPtrList; class MxTickleManager : public MxCore { public: inline MxTickleManager() {} - virtual ~MxTickleManager(); // vtable+0x0 (scalar deleting destructor) + ~MxTickleManager() override; // vtable+0x00 (scalar deleting destructor) - virtual MxResult Tickle(); // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 virtual void RegisterClient(MxCore* p_client, MxTime p_interval); // vtable+0x14 virtual void UnregisterClient(MxCore* p_client); // vtable+0x18 virtual void SetClientTickleInterval(MxCore* p_client, MxTime p_interval); // vtable+0x1c @@ -48,7 +48,7 @@ class MxTickleManager : public MxCore { // MxTickleManager::`scalar deleting destructor' private: - MxTickleClientPtrList m_clients; // 0x8 + MxTickleClientPtrList m_clients; // 0x08 }; #define TICKLE_MANAGER_NOT_FOUND 0x80000000 diff --git a/LEGO1/omni/include/mxtimer.h b/LEGO1/omni/include/mxtimer.h index 63b597ac..468cd602 100644 --- a/LEGO1/omni/include/mxtimer.h +++ b/LEGO1/omni/include/mxtimer.h @@ -12,14 +12,16 @@ class MxTimer : public MxCore { void Start(); void Stop(); - __declspec(dllexport) MxLong GetRealTime(); + MxLong GetRealTime(); inline MxLong GetTime() { - if (this->m_isRunning) + if (this->m_isRunning) { return g_lastTimeTimerStarted; - else + } + else { return g_lastTimeCalculated - this->m_startTime; + } } // SYNTHETIC: LEGO1 0x100ae0d0 diff --git a/LEGO1/omni/include/mxtype17notificationparam.h b/LEGO1/omni/include/mxtype17notificationparam.h deleted file mode 100644 index cf4e78fa..00000000 --- a/LEGO1/omni/include/mxtype17notificationparam.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MXTYPE17NOTIFICATIONPARAM_H -#define MXTYPE17NOTIFICATIONPARAM_H - -#include "decomp.h" -#include "mxnotificationparam.h" - -// ??? This type is handled, but seemingly never created and no VTABLE fits -class MxType17NotificationParam : public MxNotificationParam { -public: - inline MxU32 GetUnknown20() { return m_unk0x20; } - inline MxU16 GetUnknown28() { return m_unk0x28; } - -protected: - undefined m_unk0xc[0x14]; - MxU32 m_unk0x20; - undefined4 m_unk0x24; - MxU16 m_unk0x28; -}; - -#endif // MXTYPE17NOTIFICATIONPARAM_H diff --git a/LEGO1/omni/include/mxtype18notificationparam.h b/LEGO1/omni/include/mxtype18notificationparam.h index bce896e3..589fd2bb 100644 --- a/LEGO1/omni/include/mxtype18notificationparam.h +++ b/LEGO1/omni/include/mxtype18notificationparam.h @@ -8,7 +8,7 @@ // SIZE 0x10 class MxType18NotificationParam : public MxNotificationParam { protected: - undefined4 m_unk0xc; // 0xc + undefined4 m_unk0x0c; // 0x0c }; #endif // MXTYPE18NOTIFICATIONPARAM_H diff --git a/LEGO1/omni/include/mxtype19notificationparam.h b/LEGO1/omni/include/mxtype19notificationparam.h index ddd47998..51a6a713 100644 --- a/LEGO1/omni/include/mxtype19notificationparam.h +++ b/LEGO1/omni/include/mxtype19notificationparam.h @@ -8,8 +8,8 @@ // SIZE 0x10 class MxType19NotificationParam : public MxNotificationParam { protected: - MxU16 m_unk0xc; // 0xc - MxU8 m_unk0xe; // 0xe + MxU16 m_unk0x0c; // 0x0c + MxU8 m_unk0x0e; // 0x0e }; #endif // MXTYPE19NOTIFICATIONPARAM_H diff --git a/LEGO1/omni/include/mxutil.h b/LEGO1/omni/include/mxutil.h index 5eb0a984..c85259bb 100644 --- a/LEGO1/omni/include/mxutil.h +++ b/LEGO1/omni/include/mxutil.h @@ -8,6 +8,8 @@ class MxDSFile; class MxDSObject; class MxDSAction; +class MxCompositePresenterList; +class MxPresenter; template inline T Abs(T p_t) @@ -69,10 +71,11 @@ MxBool GetRectIntersection( MxS32* p_height ); -__declspec(dllexport) void MakeSourceName(char*, const char*); -__declspec(dllexport) void SetOmniUserMessage(void (*)(const char*, int)); +void MakeSourceName(char*, const char*); +void SetOmniUserMessage(void (*)(const char*, int)); +MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter); void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags); -__declspec(dllexport) MxDSObject* CreateStreamObject(MxDSFile*, MxS16); +MxDSObject* CreateStreamObject(MxDSFile*, MxS16); MxBool KeyValueStringParse(char*, const char*, const char*); diff --git a/LEGO1/omni/include/mxvariable.h b/LEGO1/omni/include/mxvariable.h index e09d449c..d201cd39 100644 --- a/LEGO1/omni/include/mxvariable.h +++ b/LEGO1/omni/include/mxvariable.h @@ -22,13 +22,13 @@ class MxVariable { } // FUNCTION: LEGO1 0x1003bea0 - virtual MxString* GetValue() { return &m_value; }; + virtual MxString* GetValue() { return &m_value; } // vtable+0x00 // FUNCTION: LEGO1 0x1003beb0 - virtual void SetValue(const char* p_value) { m_value = p_value; }; + virtual void SetValue(const char* p_value) { m_value = p_value; } // vtable+0x04 // FUNCTION: LEGO1 0x1003bec0 - virtual void Destroy() { delete this; }; + virtual void Destroy() { delete this; } // vtable+0x08 inline const MxString* GetKey() const { return &m_key; } diff --git a/LEGO1/omni/include/mxvariabletable.h b/LEGO1/omni/include/mxvariabletable.h index fd5cdea2..81059f9d 100644 --- a/LEGO1/omni/include/mxvariabletable.h +++ b/LEGO1/omni/include/mxvariabletable.h @@ -10,14 +10,14 @@ class MxVariableTable : public MxHashTable { public: MxVariableTable() { m_customDestructor = Destroy; } - __declspec(dllexport) void SetVariable(const char* p_key, const char* p_value); - __declspec(dllexport) void SetVariable(MxVariable* p_var); - __declspec(dllexport) const char* GetVariable(const char* p_key); + void SetVariable(const char* p_key, const char* p_value); + void SetVariable(MxVariable* p_var); + const char* GetVariable(const char* p_key); static void Destroy(MxVariable* p_obj) { p_obj->Destroy(); } - virtual MxS8 Compare(MxVariable*, MxVariable*) override; // vtable+0x14 - virtual MxU32 Hash(MxVariable*) override; // vtable+0x18 + MxS8 Compare(MxVariable*, MxVariable*) override; // vtable+0x14 + MxU32 Hash(MxVariable*) override; // vtable+0x18 // SYNTHETIC: LEGO1 0x100afdd0 // MxVariableTable::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxvideomanager.h b/LEGO1/omni/include/mxvideomanager.h index 57919da3..a915f5f5 100644 --- a/LEGO1/omni/include/mxvideomanager.h +++ b/LEGO1/omni/include/mxvideomanager.h @@ -14,10 +14,10 @@ class MxVideoManager : public MxMediaManager { public: MxVideoManager(); - virtual ~MxVideoManager() override; + ~MxVideoManager() override; - virtual MxResult Tickle() override; // vtable+0x8 - virtual void Destroy() override; // vtable+0x18 + MxResult Tickle() override; // vtable+0x08 + void Destroy() override; // vtable+0x18 virtual MxResult VTable0x28( MxVideoParam& p_videoParam, LPDIRECTDRAW p_pDirectDraw, @@ -30,8 +30,8 @@ class MxVideoManager : public MxMediaManager { ); // vtable+0x28 virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x2c - __declspec(dllexport) void InvalidateRect(MxRect32&); - __declspec(dllexport) virtual MxResult RealizePalette(MxPalette*); // vtable+0x30 + void InvalidateRect(MxRect32&); + virtual MxResult RealizePalette(MxPalette*); // vtable+0x30 virtual void UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height); // vtable+0x34 MxResult Init(); diff --git a/LEGO1/omni/include/mxvideoparam.h b/LEGO1/omni/include/mxvideoparam.h index 33aecb32..b9ae10ba 100644 --- a/LEGO1/omni/include/mxvideoparam.h +++ b/LEGO1/omni/include/mxvideoparam.h @@ -13,17 +13,13 @@ // SIZE 0x24 class MxVideoParam { public: - __declspec(dllexport) MxVideoParam(); - __declspec(dllexport) MxVideoParam(MxVideoParam& p_videoParam); - __declspec(dllexport) MxVideoParam( - COMPAT_CONST MxRect32& p_rect, - MxPalette* p_palette, - MxULong p_backBuffers, - COMPAT_CONST MxVideoParamFlags& p_flags - ); - __declspec(dllexport) MxVideoParam& operator=(const MxVideoParam& p_videoParam); - __declspec(dllexport) ~MxVideoParam(); - __declspec(dllexport) void SetDeviceName(char* p_deviceId); + MxVideoParam(); + MxVideoParam(MxVideoParam& p_videoParam); + __declspec(dllexport) + MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_backBuffers, MxVideoParamFlags& p_flags); + MxVideoParam& operator=(const MxVideoParam& p_videoParam); + ~MxVideoParam(); + void SetDeviceName(char* p_deviceId); inline MxVideoParamFlags& Flags() { return m_flags; } diff --git a/LEGO1/omni/include/mxvideoparamflags.h b/LEGO1/omni/include/mxvideoparamflags.h index 551a6c0a..8b937d38 100644 --- a/LEGO1/omni/include/mxvideoparamflags.h +++ b/LEGO1/omni/include/mxvideoparamflags.h @@ -7,7 +7,7 @@ class MxVideoParamFlags { public: - __declspec(dllexport) MxVideoParamFlags(); + MxVideoParamFlags(); inline void SetFullScreen(BOOL p_e) { m_flags1.m_bit0 = p_e; } inline void SetFlipSurfaces(BOOL p_e) { m_flags1.m_bit1 = p_e; } diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index f338b972..06436163 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -10,45 +10,37 @@ // SIZE 0x64 class MxVideoPresenter : public MxMediaPresenter { public: - enum { - c_bit1 = 0x01, - c_bit2 = 0x02, - c_bit3 = 0x04, - c_bit4 = 0x08, - c_bit5 = 0x10, - }; - MxVideoPresenter() { Init(); } // FUNCTION: LEGO1 0x1000c740 - virtual ~MxVideoPresenter() override { Destroy(TRUE); }; // vtable+0x0 + ~MxVideoPresenter() override { Destroy(TRUE); } // vtable+0x00 // FUNCTION: LEGO1 0x1000c820 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0760 return "MxVideoPresenter"; } // FUNCTION: LEGO1 0x1000c830 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxVideoPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void Unk5Tickle() override; // vtable+0x28 - virtual MxResult AddToManager() override; // vtable+0x34 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void Unk5Tickle() override; // vtable+0x28 + MxResult AddToManager() override; // vtable+0x34 // FUNCTION: LEGO1 0x1000c7a0 - virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 - virtual void EndAction() override; // vtable+0x40 - virtual MxResult PutData() override; // vtable+0x4c - virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 + void EndAction() override; // vtable+0x40 + MxResult PutData() override; // vtable+0x4c + MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 // FUNCTION: LEGO1 0x1000c700 virtual void LoadHeader(MxStreamChunk* p_chunk){}; // vtable+0x5c @@ -69,19 +61,19 @@ class MxVideoPresenter : public MxMediaPresenter { virtual undefined VTable0x74(); // vtable+0x74 // FUNCTION: LEGO1 0x1000c7b0 - virtual LPDIRECTDRAWSURFACE VTable0x78() { return m_unk0x58; }; // vtable+0x78 + virtual LPDIRECTDRAWSURFACE VTable0x78() { return m_unk0x58; } // vtable+0x78 // FUNCTION: LEGO1 0x1000c7c0 - virtual MxBool VTable0x7c() { return (m_bitmap != NULL) || (m_alpha != NULL); }; // vtable+0x7c + virtual MxBool VTable0x7c() { return m_bitmap != NULL || m_alpha != NULL; } // vtable+0x7c // FUNCTION: LEGO1 0x1000c7e0 - virtual MxS32 GetWidth() { return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiWidth(); }; // vtable+0x80 + virtual MxS32 GetWidth() { return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiWidth(); } // vtable+0x80 // FUNCTION: LEGO1 0x1000c800 - virtual MxS32 GetHeight() { return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs(); }; // vtable+0x84 + virtual MxS32 GetHeight() { return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs(); } // vtable+0x84 // VTABLE: LEGO1 0x100dc2bc - // SIZE 0xc + // SIZE 0x0c struct AlphaMask { MxU8* m_bitmask; MxU16 m_width; @@ -99,6 +91,19 @@ class MxVideoPresenter : public MxMediaPresenter { inline MxS32 PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc); inline MxBitmap* GetBitmap() { return m_bitmap; } + inline AlphaMask* GetAlphaMask() { return m_alpha; } + + inline void SetBit0(BOOL p_e) { m_flags.m_bit0 = p_e; } + inline void SetBit1(BOOL p_e) { m_flags.m_bit1 = p_e; } + inline void SetBit2(BOOL p_e) { m_flags.m_bit2 = p_e; } + inline void SetBit3(BOOL p_e) { m_flags.m_bit3 = p_e; } + inline void SetBit4(BOOL p_e) { m_flags.m_bit4 = p_e; } + + inline BYTE GetBit0() { return m_flags.m_bit0; } + inline BYTE GetBit1() { return m_flags.m_bit1; } + inline BYTE GetBit2() { return m_flags.m_bit2; } + inline BYTE GetBit3() { return m_flags.m_bit3; } + inline BYTE GetBit4() { return m_flags.m_bit4; } // SYNTHETIC: LEGO1 0x1000c910 // MxVideoPresenter::`scalar deleting destructor' @@ -113,7 +118,7 @@ class MxVideoPresenter : public MxMediaPresenter { AlphaMask* m_alpha; // 0x54 LPDIRECTDRAWSURFACE m_unk0x58; // 0x58 MxS16 m_unk0x5c; // 0x5c - MxU8 m_flags; // 0x5e + FlagBitfield m_flags; // 0x5e MxLong m_unk0x60; // 0x60 }; diff --git a/LEGO1/omni/include/mxwavepresenter.h b/LEGO1/omni/include/mxwavepresenter.h index bffefe15..27bd1824 100644 --- a/LEGO1/omni/include/mxwavepresenter.h +++ b/LEGO1/omni/include/mxwavepresenter.h @@ -13,58 +13,56 @@ class MxWavePresenter : public MxSoundPresenter { MxWavePresenter() { Init(); } // FUNCTION: LEGO1 0x1000d640 - virtual ~MxWavePresenter() override { Destroy(TRUE); }; // vtable+0x00 + ~MxWavePresenter() override { Destroy(TRUE); } // vtable+0x00 // FUNCTION: LEGO1 0x1000d6c0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f07b4 return "MxWavePresenter"; } // FUNCTION: LEGO1 0x1000d6d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxWavePresenter::ClassName()) || MxSoundPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 // FUNCTION: LEGO1 0x1000d6a0 - virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 - virtual void EndAction() override; // vtable+0x40 - virtual MxResult PutData() override; // vtable+0x4c - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void LoopChunk(MxStreamChunk* p_chunk) override; // vtable+0x58 - virtual void SetVolume(MxS32 p_volume) override; // vtable+0x60 - virtual void Pause(); // vtable+0x64 - virtual void Resume(); // vtable+0x68 + void EndAction() override; // vtable+0x40 + MxResult PutData() override; // vtable+0x4c + void Enable(MxBool p_enable) override; // vtable+0x54 + void LoopChunk(MxStreamChunk* p_chunk) override; // vtable+0x58 + void SetVolume(MxS32 p_volume) override; // vtable+0x60 + virtual void Pause(); // vtable+0x64 + virtual void Resume(); // vtable+0x68 // FUNCTION: LEGO1 0x1000d6b0 - virtual MxBool IsPaused() { return m_paused; }; // vtable+0x6c + virtual MxBool IsPaused() { return m_paused; } // vtable+0x6c - // Reference: https://github.com/itsmattkc/SIEdit/blob/master/lib/othertypes.h - // SIZE 0x1c + // SIZE 0x18 struct WaveFormat { - WAVEFORMATEX m_waveFormatEx; - MxU32 m_dataSize; - MxU32 m_flags; + PCMWAVEFORMAT m_pcmWaveFormat; // 0x00 + MxU32 m_dataSize; // 0x10 + MxU32 m_flags; // 0x14 }; // SYNTHETIC: LEGO1 0x1000d810 // MxWavePresenter::`scalar deleting destructor' protected: + void Init(); void Destroy(MxBool p_fromDestructor); -private: - void Init(); MxS8 GetPlayedChunks(); MxBool FUN_100b1ba0(); void WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length); @@ -75,7 +73,7 @@ class MxWavePresenter : public MxSoundPresenter { MxU32 m_lockSize; // 0x60 MxU8 m_writtenChunks; // 0x64 MxBool m_started; // 0x65 - MxBool m_unk0x66; // 0x66 + MxBool m_is3d; // 0x66 MxS8 m_silenceData; // 0x67 MxBool m_paused; // 0x68 }; diff --git a/LEGO1/omni/src/action/mxdsaction.cpp b/LEGO1/omni/src/action/mxdsaction.cpp index cea02696..49f40561 100644 --- a/LEGO1/omni/src/action/mxdsaction.cpp +++ b/LEGO1/omni/src/action/mxdsaction.cpp @@ -108,8 +108,9 @@ MxU32 MxDSAction::GetSizeOnDisk() // FUNCTION: LEGO1 0x100adc10 MxDSAction& MxDSAction::operator=(MxDSAction& p_dsAction) { - if (this == &p_dsAction) + if (this == &p_dsAction) { return *this; + } MxDSObject::operator=(p_dsAction); this->CopyFrom(p_dsAction); @@ -121,8 +122,9 @@ MxDSAction* MxDSAction::Clone() { MxDSAction* clone = new MxDSAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -136,35 +138,47 @@ MxLong MxDSAction::GetElapsedTime() // FUNCTION: LEGO1 0x100add00 void MxDSAction::MergeFrom(MxDSAction& p_dsAction) { - if (p_dsAction.m_startTime != INT_MIN) + if (p_dsAction.m_startTime != INT_MIN) { this->m_startTime = p_dsAction.m_startTime; + } - if (p_dsAction.GetDuration() != INT_MIN) + if (p_dsAction.GetDuration() != INT_MIN) { this->m_duration = p_dsAction.GetDuration(); + } - if (p_dsAction.m_loopCount != -1) + if (p_dsAction.m_loopCount != -1) { this->m_loopCount = p_dsAction.m_loopCount; + } - if (p_dsAction.m_location[0] != FLT_MAX) + if (p_dsAction.m_location[0] != FLT_MAX) { this->m_location[0] = p_dsAction.m_location[0]; - if (p_dsAction.m_location[1] != FLT_MAX) + } + if (p_dsAction.m_location[1] != FLT_MAX) { this->m_location[1] = p_dsAction.m_location[1]; - if (p_dsAction.m_location[2] != FLT_MAX) + } + if (p_dsAction.m_location[2] != FLT_MAX) { this->m_location[2] = p_dsAction.m_location[2]; + } - if (p_dsAction.m_direction[0] != FLT_MAX) + if (p_dsAction.m_direction[0] != FLT_MAX) { this->m_direction[0] = p_dsAction.m_direction[0]; - if (p_dsAction.m_direction[1] != FLT_MAX) + } + if (p_dsAction.m_direction[1] != FLT_MAX) { this->m_direction[1] = p_dsAction.m_direction[1]; - if (p_dsAction.m_direction[2] != FLT_MAX) + } + if (p_dsAction.m_direction[2] != FLT_MAX) { this->m_direction[2] = p_dsAction.m_up[2]; // This is correct + } - if (p_dsAction.m_up[0] != FLT_MAX) + if (p_dsAction.m_up[0] != FLT_MAX) { this->m_up[0] = p_dsAction.m_up[0]; - if (p_dsAction.m_up[1] != FLT_MAX) + } + if (p_dsAction.m_up[1] != FLT_MAX) { this->m_up[1] = p_dsAction.m_up[1]; - if (p_dsAction.m_up[2] != FLT_MAX) + } + if (p_dsAction.m_up[2] != FLT_MAX) { this->m_up[2] = p_dsAction.m_up[2]; + } MxU16 extraLength = p_dsAction.m_extraLength; char* extraData = p_dsAction.m_extraData; @@ -185,8 +199,9 @@ void MxDSAction::MergeFrom(MxDSAction& p_dsAction) // FUNCTION: LEGO1 0x100ade60 void MxDSAction::AppendData(MxU16 p_extraLength, const char* p_extraData) { - if (this->m_extraData == p_extraData || !p_extraData) + if (this->m_extraData == p_extraData || !p_extraData) { return; + } if (this->m_extraLength) { char* concat = new char[p_extraLength + this->m_extraLength + sizeof(g_sep)]; diff --git a/LEGO1/omni/src/action/mxdsanim.cpp b/LEGO1/omni/src/action/mxdsanim.cpp index cef2321c..c90933b1 100644 --- a/LEGO1/omni/src/action/mxdsanim.cpp +++ b/LEGO1/omni/src/action/mxdsanim.cpp @@ -21,8 +21,9 @@ void MxDSAnim::CopyFrom(MxDSAnim& p_dsAnim) // FUNCTION: LEGO1 0x100c9200 MxDSAnim& MxDSAnim::operator=(MxDSAnim& p_dsAnim) { - if (this == &p_dsAnim) + if (this == &p_dsAnim) { return *this; + } MxDSMediaAction::operator=(p_dsAnim); this->CopyFrom(p_dsAnim); @@ -34,8 +35,9 @@ MxDSAction* MxDSAnim::Clone() { MxDSAnim* clone = new MxDSAnim(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/omni/src/action/mxdsevent.cpp b/LEGO1/omni/src/action/mxdsevent.cpp index bc925369..64702e65 100644 --- a/LEGO1/omni/src/action/mxdsevent.cpp +++ b/LEGO1/omni/src/action/mxdsevent.cpp @@ -21,8 +21,9 @@ void MxDSEvent::CopyFrom(MxDSEvent& p_dsEvent) // FUNCTION: LEGO1 0x100c9800 MxDSEvent& MxDSEvent::operator=(MxDSEvent& p_dsEvent) { - if (this == &p_dsEvent) + if (this == &p_dsEvent) { return *this; + } MxDSMediaAction::operator=(p_dsEvent); this->CopyFrom(p_dsEvent); @@ -34,8 +35,9 @@ MxDSAction* MxDSEvent::Clone() { MxDSEvent* clone = new MxDSEvent(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/omni/src/action/mxdsmediaaction.cpp b/LEGO1/omni/src/action/mxdsmediaaction.cpp index fda2721a..c563b380 100644 --- a/LEGO1/omni/src/action/mxdsmediaaction.cpp +++ b/LEGO1/omni/src/action/mxdsmediaaction.cpp @@ -39,8 +39,9 @@ void MxDSMediaAction::CopyFrom(MxDSMediaAction& p_dsMediaAction) // FUNCTION: LEGO1 0x100c8dc0 MxDSMediaAction& MxDSMediaAction::operator=(MxDSMediaAction& p_dsMediaAction) { - if (this == &p_dsMediaAction) + if (this == &p_dsMediaAction) { return *this; + } MxDSAction::operator=(p_dsMediaAction); this->CopyFrom(p_dsMediaAction); @@ -52,8 +53,9 @@ MxDSAction* MxDSMediaAction::Clone() { MxDSMediaAction* clone = new MxDSMediaAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -61,18 +63,21 @@ MxDSAction* MxDSMediaAction::Clone() // FUNCTION: LEGO1 0x100c8e80 void MxDSMediaAction::CopyMediaSrcPath(const char* p_mediaSrcPath) { - if (this->m_mediaSrcPath == p_mediaSrcPath) + if (this->m_mediaSrcPath == p_mediaSrcPath) { return; + } delete[] this->m_mediaSrcPath; if (p_mediaSrcPath) { this->m_mediaSrcPath = new char[strlen(p_mediaSrcPath) + 1]; - if (this->m_mediaSrcPath) + if (this->m_mediaSrcPath) { strcpy(this->m_mediaSrcPath, p_mediaSrcPath); + } } - else + else { this->m_mediaSrcPath = NULL; + } } // FUNCTION: LEGO1 0x100c8f00 @@ -86,10 +91,12 @@ MxU32 MxDSMediaAction::GetSizeOnDisk() { MxU32 totalSizeOnDisk = MxDSAction::GetSizeOnDisk(); - if (this->m_mediaSrcPath) + if (this->m_mediaSrcPath) { totalSizeOnDisk += strlen(this->m_mediaSrcPath) + 1; - else + } + else { totalSizeOnDisk++; + } totalSizeOnDisk += 24; this->m_sizeOnDisk = totalSizeOnDisk - MxDSAction::GetSizeOnDisk(); diff --git a/LEGO1/omni/src/action/mxdsmultiaction.cpp b/LEGO1/omni/src/action/mxdsmultiaction.cpp index 64e20a55..40216ae7 100644 --- a/LEGO1/omni/src/action/mxdsmultiaction.cpp +++ b/LEGO1/omni/src/action/mxdsmultiaction.cpp @@ -15,8 +15,9 @@ MxDSMultiAction::MxDSMultiAction() // FUNCTION: LEGO1 0x100ca060 MxDSMultiAction::~MxDSMultiAction() { - if (this->m_actions) + if (this->m_actions) { delete this->m_actions; + } } // FUNCTION: LEGO1 0x100ca0d0 @@ -26,15 +27,17 @@ void MxDSMultiAction::CopyFrom(MxDSMultiAction& p_dsMultiAction) MxDSActionListCursor cursor(p_dsMultiAction.m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { this->m_actions->Append(action->Clone()); + } } // FUNCTION: LEGO1 0x100ca260 MxDSMultiAction& MxDSMultiAction::operator=(MxDSMultiAction& p_dsMultiAction) { - if (this == &p_dsMultiAction) + if (this == &p_dsMultiAction) { return *this; + } MxDSAction::operator=(p_dsMultiAction); this->CopyFrom(p_dsMultiAction); @@ -48,8 +51,9 @@ void MxDSMultiAction::SetUnknown90(MxLong p_unk0x90) MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { action->SetUnknown90(p_unk0x90); + } } // FUNCTION: LEGO1 0x100ca370 @@ -59,21 +63,24 @@ void MxDSMultiAction::MergeFrom(MxDSAction& p_dsMultiAction) MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { action->MergeFrom(p_dsMultiAction); + } } // FUNCTION: LEGO1 0x100ca450 MxBool MxDSMultiAction::HasId(MxU32 p_objectId) { - if (this->GetObjectId() == p_objectId) + if (this->GetObjectId() == p_objectId) { return TRUE; + } MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; while (cursor.Next(action)) { - if (action->HasId(p_objectId)) + if (action->HasId(p_objectId)) { return TRUE; + } } return FALSE; @@ -84,8 +91,9 @@ MxDSAction* MxDSMultiAction::Clone() { MxDSMultiAction* clone = new MxDSMultiAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -97,8 +105,9 @@ undefined4 MxDSMultiAction::VTable0x14() MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { result += action->VTable0x14(); + } return result; } @@ -110,8 +119,9 @@ MxU32 MxDSMultiAction::GetSizeOnDisk() MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { totalSizeOnDisk += action->GetSizeOnDisk(); + } this->m_sizeOnDisk = totalSizeOnDisk - MxDSAction::GetSizeOnDisk(); @@ -151,6 +161,7 @@ void MxDSMultiAction::SetAtomId(MxAtomId p_atomId) MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { action->SetAtomId(p_atomId); + } } diff --git a/LEGO1/omni/src/action/mxdsobject.cpp b/LEGO1/omni/src/action/mxdsobject.cpp index 6d11476d..9bbdf195 100644 --- a/LEGO1/omni/src/action/mxdsobject.cpp +++ b/LEGO1/omni/src/action/mxdsobject.cpp @@ -52,8 +52,9 @@ void MxDSObject::CopyFrom(MxDSObject& p_dsObject) // FUNCTION: LEGO1 0x100bf8c0 MxDSObject& MxDSObject::operator=(MxDSObject& p_dsObject) { - if (this == &p_dsObject) + if (this == &p_dsObject) { return *this; + } this->CopyFrom(p_dsObject); return *this; @@ -108,17 +109,21 @@ MxU32 MxDSObject::GetSizeOnDisk() { MxU32 sizeOnDisk; - if (this->m_sourceName) + if (this->m_sourceName) { sizeOnDisk = strlen(this->m_sourceName) + 3; - else + } + else { sizeOnDisk = 3; + } sizeOnDisk += 4; - if (this->m_objectName) + if (this->m_objectName) { sizeOnDisk += strlen(this->m_objectName) + 1; - else + } + else { sizeOnDisk++; + } sizeOnDisk += 4; this->m_sizeOnDisk = sizeOnDisk; diff --git a/LEGO1/omni/src/action/mxdsobjectaction.cpp b/LEGO1/omni/src/action/mxdsobjectaction.cpp index db8b149f..40eadec3 100644 --- a/LEGO1/omni/src/action/mxdsobjectaction.cpp +++ b/LEGO1/omni/src/action/mxdsobjectaction.cpp @@ -21,8 +21,9 @@ void MxDSObjectAction::CopyFrom(MxDSObjectAction& p_dsObjectAction) // FUNCTION: LEGO1 0x100c8a80 MxDSObjectAction& MxDSObjectAction::operator=(MxDSObjectAction& p_dsObjectAction) { - if (this == &p_dsObjectAction) + if (this == &p_dsObjectAction) { return *this; + } MxDSMediaAction::operator=(p_dsObjectAction); this->CopyFrom(p_dsObjectAction); @@ -34,8 +35,9 @@ MxDSAction* MxDSObjectAction::Clone() { MxDSObjectAction* clone = new MxDSObjectAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/omni/src/action/mxdsparallelaction.cpp b/LEGO1/omni/src/action/mxdsparallelaction.cpp index a14a326f..f4e61245 100644 --- a/LEGO1/omni/src/action/mxdsparallelaction.cpp +++ b/LEGO1/omni/src/action/mxdsparallelaction.cpp @@ -23,8 +23,9 @@ void MxDSParallelAction::CopyFrom(MxDSParallelAction& p_dsParallelAction) // FUNCTION: LEGO1 0x100cb0a0 MxDSParallelAction& MxDSParallelAction::operator=(MxDSParallelAction& p_dsParallelAction) { - if (this == &p_dsParallelAction) + if (this == &p_dsParallelAction) { return *this; + } MxDSMultiAction::operator=(p_dsParallelAction); this->CopyFrom(p_dsParallelAction); @@ -36,8 +37,9 @@ MxDSAction* MxDSParallelAction::Clone() { MxDSParallelAction* clone = new MxDSParallelAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -45,15 +47,17 @@ MxDSAction* MxDSParallelAction::Clone() // FUNCTION: LEGO1 0x100cb160 MxLong MxDSParallelAction::GetDuration() { - if (this->m_duration) + if (this->m_duration) { return this->m_duration; + } MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; while (cursor.Next(action)) { - if (!action) + if (!action) { continue; + } MxLong duration = action->GetDuration(); if (duration == -1) { @@ -65,10 +69,12 @@ MxLong MxDSParallelAction::GetDuration() if (action->IsA("MxDSMediaAction")) { MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime(); - if (sustainTime == -1) + if (sustainTime == -1) { duration = -1; - else if (sustainTime) + } + else if (sustainTime) { duration += sustainTime; + } } if (duration == -1) { @@ -76,12 +82,14 @@ MxLong MxDSParallelAction::GetDuration() break; } - if (this->m_duration < duration) + if (this->m_duration < duration) { this->m_duration = duration; + } } - if (this->IsBit3()) + if (this->IsBit3()) { this->m_duration *= this->m_loopCount; + } return this->m_duration; } diff --git a/LEGO1/omni/src/action/mxdsselectaction.cpp b/LEGO1/omni/src/action/mxdsselectaction.cpp index ddadde84..97e9ff73 100644 --- a/LEGO1/omni/src/action/mxdsselectaction.cpp +++ b/LEGO1/omni/src/action/mxdsselectaction.cpp @@ -19,8 +19,9 @@ MxDSSelectAction::MxDSSelectAction() // FUNCTION: LEGO1 0x100cb8d0 MxDSSelectAction::~MxDSSelectAction() { - if (this->m_unk0xac) + if (this->m_unk0xac) { delete this->m_unk0xac; + } } // FUNCTION: LEGO1 0x100cb950 @@ -32,8 +33,9 @@ void MxDSSelectAction::CopyFrom(MxDSSelectAction& p_dsSelectAction) MxStringListCursor cursor(p_dsSelectAction.m_unk0xac); MxString string; - while (cursor.Next(string)) + while (cursor.Next(string)) { this->m_unk0xac->Append(string); + } } // FUNCTION: LEGO1 0x100cbd50 @@ -51,8 +53,9 @@ MxDSAction* MxDSSelectAction::Clone() { MxDSSelectAction* clone = new MxDSSelectAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -66,8 +69,9 @@ MxU32 MxDSSelectAction::GetSizeOnDisk() MxStringListCursor cursor(this->m_unk0xac); MxString string; - while (cursor.Next(string)) + while (cursor.Next(string)) { totalSizeOnDisk += strlen(string.GetData()) + 1; + } // Note: unlike the other classes, MxDSSelectAction does not have its own // sizeOnDisk member. Instead, it overrides the one from MxDSMultiAction. @@ -95,8 +99,9 @@ void MxDSSelectAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) MxS32 random = rand() % value; string = itoa((MxS16) random, buffer, 10); } - else + else { string = VariableTable()->GetVariable((char*) *p_source); + } *p_source += strlen((char*) *p_source) + 1; @@ -109,8 +114,9 @@ void MxDSSelectAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) MxU32 i; for (i = 0; i < count; i++) { - if (!strcmp(string.GetData(), (char*) *p_source)) + if (!strcmp(string.GetData(), (char*) *p_source)) { index = i; + } this->m_unk0xac->Append((char*) *p_source); *p_source += strlen((char*) *p_source) + 1; @@ -122,10 +128,12 @@ void MxDSSelectAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) MxDSAction* action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_unk0x24); - if (index == i) + if (index == i) { this->m_actions->Append(action); - else + } + else { delete action; + } *p_source += extraFlag; } diff --git a/LEGO1/omni/src/action/mxdsserialaction.cpp b/LEGO1/omni/src/action/mxdsserialaction.cpp index 24513f48..b03efdf0 100644 --- a/LEGO1/omni/src/action/mxdsserialaction.cpp +++ b/LEGO1/omni/src/action/mxdsserialaction.cpp @@ -21,8 +21,9 @@ void MxDSSerialAction::SetDuration(MxLong p_duration) // FUNCTION: LEGO1 0x100cac10 MxDSSerialAction::~MxDSSerialAction() { - if (this->m_cursor) + if (this->m_cursor) { delete this->m_cursor; + } this->m_cursor = NULL; } @@ -35,8 +36,9 @@ void MxDSSerialAction::CopyFrom(MxDSSerialAction& p_dsSerialAction) // FUNCTION: LEGO1 0x100caca0 MxDSSerialAction& MxDSSerialAction::operator=(MxDSSerialAction& p_dsSerialAction) { - if (this == &p_dsSerialAction) + if (this == &p_dsSerialAction) { return *this; + } MxDSMultiAction::operator=(p_dsSerialAction); this->CopyFrom(p_dsSerialAction); @@ -48,8 +50,9 @@ MxDSAction* MxDSSerialAction::Clone() { MxDSSerialAction* clone = new MxDSSerialAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -57,23 +60,26 @@ MxDSAction* MxDSSerialAction::Clone() // FUNCTION: LEGO1 0x100cad60 MxLong MxDSSerialAction::GetDuration() { - if (this->m_duration) + if (this->m_duration) { return this->m_duration; + } MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; while (cursor.Next(action)) { - if (!action) + if (!action) { continue; + } this->m_duration += action->GetDuration() + action->GetStartTime(); if (action->IsA("MxDSMediaAction")) { MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime(); - if (sustainTime && sustainTime != -1) + if (sustainTime && sustainTime != -1) { this->m_duration += sustainTime; + } } } diff --git a/LEGO1/omni/src/action/mxdssound.cpp b/LEGO1/omni/src/action/mxdssound.cpp index 61022cab..e75ad0c9 100644 --- a/LEGO1/omni/src/action/mxdssound.cpp +++ b/LEGO1/omni/src/action/mxdssound.cpp @@ -26,8 +26,9 @@ void MxDSSound::CopyFrom(MxDSSound& p_dsSound) // FUNCTION: LEGO1 0x100c94e0 MxDSSound& MxDSSound::operator=(MxDSSound& p_dsSound) { - if (this == &p_dsSound) + if (this == &p_dsSound) { return *this; + } MxDSMediaAction::operator=(p_dsSound); this->CopyFrom(p_dsSound); @@ -39,8 +40,9 @@ MxDSAction* MxDSSound::Clone() { MxDSSound* clone = new MxDSSound(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/omni/src/action/mxdsstill.cpp b/LEGO1/omni/src/action/mxdsstill.cpp index 59a78ffc..c044a2e6 100644 --- a/LEGO1/omni/src/action/mxdsstill.cpp +++ b/LEGO1/omni/src/action/mxdsstill.cpp @@ -21,8 +21,9 @@ void MxDSStill::CopyFrom(MxDSStill& p_dsStill) // FUNCTION: LEGO1 0x100c9ad0 MxDSStill& MxDSStill::operator=(MxDSStill& p_dsStill) { - if (this == &p_dsStill) + if (this == &p_dsStill) { return *this; + } MxDSMediaAction::operator=(p_dsStill); this->CopyFrom(p_dsStill); @@ -34,8 +35,9 @@ MxDSAction* MxDSStill::Clone() { MxDSStill* clone = new MxDSStill(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/omni/src/action/mxdsstreamingaction.cpp b/LEGO1/omni/src/action/mxdsstreamingaction.cpp index e8eb4dc1..85759897 100644 --- a/LEGO1/omni/src/action/mxdsstreamingaction.cpp +++ b/LEGO1/omni/src/action/mxdsstreamingaction.cpp @@ -17,8 +17,9 @@ MxDSStreamingAction::MxDSStreamingAction(MxDSAction& p_dsAction, MxU32 p_offset) // FUNCTION: LEGO1 0x100cd090 MxBool MxDSStreamingAction::HasId(MxU32 p_objectId) { - if (this->m_internalAction) + if (this->m_internalAction) { return this->m_internalAction->HasId(p_objectId); + } return FALSE; } @@ -32,12 +33,15 @@ MxDSStreamingAction::MxDSStreamingAction(MxDSStreamingAction& p_dsStreamingActio // FUNCTION: LEGO1 0x100cd150 MxDSStreamingAction::~MxDSStreamingAction() { - if (this->m_unk0xa0) + if (this->m_unk0xa0) { delete this->m_unk0xa0; - if (this->m_unk0xa4) + } + if (this->m_unk0xa4) { delete this->m_unk0xa4; - if (this->m_internalAction) + } + if (this->m_internalAction) { delete this->m_internalAction; + } } // FUNCTION: LEGO1 0x100cd1e0 @@ -73,16 +77,18 @@ MxDSStreamingAction* MxDSStreamingAction::CopyFrom(MxDSStreamingAction& p_dsStre // FUNCTION: LEGO1 0x100cd2a0 void MxDSStreamingAction::SetInternalAction(MxDSAction* p_dsAction) { - if (this->m_internalAction) + if (this->m_internalAction) { delete this->m_internalAction; + } this->m_internalAction = p_dsAction; } // FUNCTION: LEGO1 0x100cd2d0 void MxDSStreamingAction::FUN_100cd2d0() { - if (this->m_duration == -1) + if (this->m_duration == -1) { return; + } MxLong duration = this->m_duration / this->m_loopCount; this->m_loopCount--; diff --git a/LEGO1/omni/src/audio/mxaudiomanager.cpp b/LEGO1/omni/src/audio/mxaudiomanager.cpp index a2d6072a..0be79a24 100644 --- a/LEGO1/omni/src/audio/mxaudiomanager.cpp +++ b/LEGO1/omni/src/audio/mxaudiomanager.cpp @@ -31,8 +31,9 @@ void MxAudioManager::Destroy(MxBool p_fromDestructor) Init(); this->m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaManager::Destroy(); + } } // FUNCTION: LEGO1 0x100b8e40 @@ -48,11 +49,13 @@ MxResult MxAudioManager::InitPresenters() g_count++; } - if (result) + if (result) { Destroy(); + } - if (success) + if (success) { this->m_criticalSection.Leave(); + } return result; } diff --git a/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp index 77b32506..c7f4ea1c 100644 --- a/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp @@ -20,17 +20,20 @@ void MxLoopingMIDIPresenter::StreamingTickle() return; } - if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) + if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) { ProgressTickleState(e_done); + } } // FUNCTION: LEGO1 0x100c2ae0 void MxLoopingMIDIPresenter::DoneTickle() { - if (m_action->GetLoopCount()) + if (m_action->GetLoopCount()) { MxMIDIPresenter::DoneTickle(); - else + } + else { EndAction(); + } } // FUNCTION: LEGO1 0x100c2b00 diff --git a/LEGO1/omni/src/audio/mxmidipresenter.cpp b/LEGO1/omni/src/audio/mxmidipresenter.cpp index 5796fb67..91e5ba60 100644 --- a/LEGO1/omni/src/audio/mxmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxmidipresenter.cpp @@ -34,14 +34,16 @@ void MxMIDIPresenter::Destroy(MxBool p_fromDestructor) m_criticalSection.Enter(); - if (m_subscriber && m_chunk) - m_subscriber->DestroyChunk(m_chunk); + if (m_subscriber && m_chunk) { + m_subscriber->FreeDataChunk(m_chunk); + } Init(); m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMusicPresenter::Destroy(); + } } // FUNCTION: LEGO1 0x100c2890 @@ -50,7 +52,7 @@ void MxMIDIPresenter::ReadyTickle() MxStreamChunk* chunk = NextChunk(); if (chunk) { - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); ParseExtra(); ProgressTickleState(e_starting); } @@ -61,24 +63,28 @@ void MxMIDIPresenter::StartingTickle() { MxStreamChunk* chunk = CurrentChunk(); - if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { ProgressTickleState(e_streaming); + } } // FUNCTION: LEGO1 0x100c2910 void MxMIDIPresenter::StreamingTickle() { - if (m_chunk) + if (m_chunk) { ProgressTickleState(e_done); - else + } + else { m_chunk = NextChunk(); + } } // FUNCTION: LEGO1 0x100c2940 void MxMIDIPresenter::DoneTickle() { - if (!MusicManager()->GetMIDIInitialized()) + if (!MusicManager()->GetMIDIInitialized()) { EndAction(); + } } // FUNCTION: LEGO1 0x100c2960 @@ -95,8 +101,9 @@ MxResult MxMIDIPresenter::PutData() if (m_currentTickleState == e_streaming && m_chunk && !MusicManager()->GetMIDIInitialized()) { SetVolume(((MxDSSound*) m_action)->GetVolume()); - if (MusicManager()->InitializeMIDI(m_chunk->GetData(), 1) != SUCCESS) + if (MusicManager()->InitializeMIDI(m_chunk->GetData(), 1) != SUCCESS) { EndAction(); + } } m_criticalSection.Leave(); diff --git a/LEGO1/omni/src/audio/mxmusicmanager.cpp b/LEGO1/omni/src/audio/mxmusicmanager.cpp index 7a0684f8..23562678 100644 --- a/LEGO1/omni/src/audio/mxmusicmanager.cpp +++ b/LEGO1/omni/src/audio/mxmusicmanager.cpp @@ -82,8 +82,9 @@ MxResult MxMusicManager::ResetStream() } if (m_midiHdrP->dwFlags & MHDR_DONE || m_midiHdrP->dwFlags & MHDR_PREPARED) { - if (midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR)) != MMSYSERR_NOERROR) + if (midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR)) != MMSYSERR_NOERROR) { goto done; + } memset(m_midiHdrP, 0, sizeof(MIDIHDR)); } @@ -131,8 +132,9 @@ void MxMusicManager::SetMIDIVolume() // FUNCTION: LEGO1 0x100c0820 void CALLBACK MxMusicManager::MidiCallbackProc(HDRVR p_hdrvr, UINT p_uMsg, DWORD p_dwUser, DWORD p_dw1, DWORD p_dw2) { - if (p_uMsg == MOM_DONE) + if (p_uMsg == MOM_DONE) { ((MxMusicManager*) p_dwUser)->ResetStream(); + } } // FUNCTION: LEGO1 0x100c0840 @@ -147,21 +149,25 @@ MxResult MxMusicManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) locked = TRUE; m_thread = new MxTickleThread(this, p_frequencyMS); - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; } done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return status; } @@ -211,22 +217,26 @@ MxResult MxMusicManager::InitializeMIDI(MxU8* p_data, MxS32 p_loopCount) for (; device < total; device++) { MIDIOUTCAPSA caps; midiOutGetDevCapsA(device, &caps, sizeof(MIDIOUTCAPSA)); - if (caps.wTechnology == MOD_FMSYNTH) + if (caps.wTechnology == MOD_FMSYNTH) { break; + } } - if (device >= total) + if (device >= total) { device = -1; + } if (midiStreamOpen(&m_midiStreamH, &device, 1, (DWORD) MidiCallbackProc, (DWORD) this, CALLBACK_FUNCTION) != - MMSYSERR_NOERROR) + MMSYSERR_NOERROR) { goto done; + } GetMIDIVolume(m_midiVolume); m_midiHdrP = new MIDIHDR(); - if (!m_midiHdrP) + if (!m_midiHdrP) { goto done; + } memset(m_midiHdrP, 0, sizeof(MIDIHDR)); @@ -236,8 +246,9 @@ MxResult MxMusicManager::InitializeMIDI(MxU8* p_data, MxS32 p_loopCount) m_bufferOffset += 0x14; timediv.dwTimeDiv = *((DWORD*) m_bufferOffset); - if (midiStreamProperty(m_midiStreamH, (LPBYTE) &timediv, MIDIPROP_SET | MIDIPROP_TIMEDIV) != MMSYSERR_NOERROR) + if (midiStreamProperty(m_midiStreamH, (LPBYTE) &timediv, MIDIPROP_SET | MIDIPROP_TIMEDIV) != MMSYSERR_NOERROR) { goto done; + } m_bufferOffset += 0x14; m_bufferSize = *((MxU32*) m_bufferOffset); @@ -246,12 +257,14 @@ MxResult MxMusicManager::InitializeMIDI(MxU8* p_data, MxS32 p_loopCount) m_midiInitialized = TRUE; ResetBuffer(); - if (ResetStream() != SUCCESS) + if (ResetStream() != SUCCESS) { goto done; + } SetMIDIVolume(); - if (midiStreamRestart(m_midiStreamH) != MMSYSERR_NOERROR) + if (midiStreamRestart(m_midiStreamH) != MMSYSERR_NOERROR) { goto done; + } result = SUCCESS; } diff --git a/LEGO1/omni/src/audio/mxsoundmanager.cpp b/LEGO1/omni/src/audio/mxsoundmanager.cpp index b06c5e37..55055107 100644 --- a/LEGO1/omni/src/audio/mxsoundmanager.cpp +++ b/LEGO1/omni/src/audio/mxsoundmanager.cpp @@ -59,46 +59,55 @@ MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) MxResult status = FAILURE; MxBool locked = FALSE; - if (MxAudioManager::InitPresenters() != SUCCESS) + if (MxAudioManager::InitPresenters() != SUCCESS) { goto done; + } m_criticalSection.Enter(); locked = TRUE; - if (DirectSoundCreate(NULL, &m_directSound, NULL) != DS_OK) + if (DirectSoundCreate(NULL, &m_directSound, NULL) != DS_OK) { goto done; + } - if (m_directSound->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DSSCL_PRIORITY) != DS_OK) + if (m_directSound->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DSSCL_PRIORITY) != DS_OK) { goto done; + } DSBUFFERDESC desc; memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); - if (MxOmni::IsSound3D()) + if (MxOmni::IsSound3D()) { desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D; - else + } + else { desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; + } if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) { - if (!MxOmni::IsSound3D()) + if (!MxOmni::IsSound3D()) { goto done; + } MxOmni::SetSound3D(FALSE); desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; - if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) + if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) { goto done; + } } WAVEFORMATEX format; format.wFormatTag = WAVE_FORMAT_PCM; - if (MxOmni::IsSound3D()) + if (MxOmni::IsSound3D()) { format.nChannels = 2; - else + } + else { format.nChannels = 1; + } format.nSamplesPerSec = 11025; // KHz format.wBitsPerSample = 16; @@ -111,20 +120,24 @@ MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) if (p_createThread) { m_thread = new MxTickleThread(this, p_frequencyMS); - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return status; } @@ -144,8 +157,9 @@ void MxSoundManager::SetVolume(MxS32 p_volume) MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { ((MxAudioPresenter*) presenter)->SetVolume(((MxAudioPresenter*) presenter)->GetVolume()); + } m_criticalSection.Leave(); } @@ -160,8 +174,9 @@ MxPresenter* MxSoundManager::FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_obje while (cursor.Next(presenter)) { if (presenter->GetAction()->GetAtomId().GetInternal() == p_atomId.GetInternal() && - presenter->GetAction()->GetObjectId() == p_objectId) + presenter->GetAction()->GetObjectId() == p_objectId) { return presenter; + } } return NULL; @@ -170,8 +185,9 @@ MxPresenter* MxSoundManager::FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_obje // FUNCTION: LEGO1 0x100aecf0 MxS32 MxSoundManager::FUN_100aecf0(MxU32 p_undefined) { - if (!p_undefined) + if (!p_undefined) { return -10000; + } return g_mxcoreCount[p_undefined]; } @@ -183,9 +199,11 @@ void MxSoundManager::Pause() MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - while (cursor.Next(presenter)) - if (presenter->IsA("MxWavePresenter")) + while (cursor.Next(presenter)) { + if (presenter->IsA("MxWavePresenter")) { ((MxWavePresenter*) presenter)->Pause(); + } + } } // FUNCTION: LEGO1 0x100aee10 @@ -196,7 +214,9 @@ void MxSoundManager::Resume() MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - while (cursor.Next(presenter)) - if (presenter->IsA("MxWavePresenter")) + while (cursor.Next(presenter)) { + if (presenter->IsA("MxWavePresenter")) { ((MxWavePresenter*) presenter)->Resume(); + } + } } diff --git a/LEGO1/omni/src/audio/mxsoundpresenter.cpp b/LEGO1/omni/src/audio/mxsoundpresenter.cpp index b0376331..60459d2c 100644 --- a/LEGO1/omni/src/audio/mxsoundpresenter.cpp +++ b/LEGO1/omni/src/audio/mxsoundpresenter.cpp @@ -8,15 +8,17 @@ DECOMP_SIZE_ASSERT(MxSoundPresenter, 0x54) // FUNCTION: LEGO1 0x100b1a50 void MxSoundPresenter::Destroy(MxBool p_fromDestructor) { - if (MSoundManager()) + if (MSoundManager()) { MSoundManager()->UnregisterPresenter(*this); + } this->m_criticalSection.Enter(); MxMediaPresenter::Init(); this->m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b1aa0 diff --git a/LEGO1/omni/src/audio/mxwavepresenter.cpp b/LEGO1/omni/src/audio/mxwavepresenter.cpp index 831e0043..1ecf6021 100644 --- a/LEGO1/omni/src/audio/mxwavepresenter.cpp +++ b/LEGO1/omni/src/audio/mxwavepresenter.cpp @@ -9,7 +9,7 @@ #include "mxutil.h" DECOMP_SIZE_ASSERT(MxWavePresenter, 0x6c); -DECOMP_SIZE_ASSERT(MxWavePresenter::WaveFormat, 0x1c); +DECOMP_SIZE_ASSERT(MxWavePresenter::WaveFormat, 0x18); // FUNCTION: LEGO1 0x100b1ad0 void MxWavePresenter::Init() @@ -20,7 +20,7 @@ void MxWavePresenter::Init() m_lockSize = 0; m_writtenChunks = 0; m_started = FALSE; - m_unk0x66 = FALSE; + m_is3d = FALSE; m_paused = FALSE; } @@ -40,13 +40,15 @@ void MxWavePresenter::Destroy(MxBool p_fromDestructor) m_dsBuffer->Release(); } - if (m_waveFormat) + if (m_waveFormat) { delete[] ((MxU8*) m_waveFormat); + } Init(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxSoundPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b1b60 @@ -55,8 +57,9 @@ MxS8 MxWavePresenter::GetPlayedChunks() DWORD dwCurrentPlayCursor, dwCurrentWriteCursor; MxS8 playedChunks = -1; - if (m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor) == DS_OK) + if (m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor) == DS_OK) { playedChunks = dwCurrentPlayCursor / m_chunkLength; + } return playedChunks; } @@ -116,7 +119,7 @@ void MxWavePresenter::ReadyTickle() if (chunk) { m_waveFormat = (WaveFormat*) new MxU8[chunk->GetLength()]; memcpy(m_waveFormat, chunk->GetData(), chunk->GetLength()); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); ParseExtra(); ProgressTickleState(e_starting); } @@ -134,33 +137,39 @@ void MxWavePresenter::StartingTickle() m_chunkLength = length; memset(&waveFormatEx, 0, sizeof(waveFormatEx)); - waveFormatEx.wFormatTag = m_waveFormat->m_waveFormatEx.wFormatTag; - waveFormatEx.nChannels = m_waveFormat->m_waveFormatEx.nChannels; - waveFormatEx.nSamplesPerSec = m_waveFormat->m_waveFormatEx.nSamplesPerSec; - waveFormatEx.nAvgBytesPerSec = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec; - waveFormatEx.nBlockAlign = m_waveFormat->m_waveFormatEx.nBlockAlign; - waveFormatEx.wBitsPerSample = m_waveFormat->m_waveFormatEx.wBitsPerSample; + waveFormatEx.wFormatTag = m_waveFormat->m_pcmWaveFormat.wf.wFormatTag; + waveFormatEx.nChannels = m_waveFormat->m_pcmWaveFormat.wf.nChannels; + waveFormatEx.nSamplesPerSec = m_waveFormat->m_pcmWaveFormat.wf.nSamplesPerSec; + waveFormatEx.nAvgBytesPerSec = m_waveFormat->m_pcmWaveFormat.wf.nAvgBytesPerSec; + waveFormatEx.nBlockAlign = m_waveFormat->m_pcmWaveFormat.wf.nBlockAlign; + waveFormatEx.wBitsPerSample = m_waveFormat->m_pcmWaveFormat.wBitsPerSample; - if (waveFormatEx.wBitsPerSample == 8) + if (waveFormatEx.wBitsPerSample == 8) { m_silenceData = 0x7F; + } - if (waveFormatEx.wBitsPerSample == 16) + if (waveFormatEx.wBitsPerSample == 16) { m_silenceData = 0; + } DSBUFFERDESC desc; memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); - if (m_unk0x66) + if (m_is3d) { desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME; - else + } + else { desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME; + } - if (m_action->GetFlags() & MxDSAction::c_looping) - desc.dwBufferBytes = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec * + if (m_action->GetFlags() & MxDSAction::c_looping) { + desc.dwBufferBytes = m_waveFormat->m_pcmWaveFormat.wf.nAvgBytesPerSec * (m_action->GetDuration() / m_action->GetLoopCount()) / 1000; - else + } + else { desc.dwBufferBytes = 2 * length; + } desc.lpwfxFormat = &waveFormatEx; @@ -209,19 +218,22 @@ void MxWavePresenter::DoneTickle() MxS8 playedChunks = dwCurrentPlayCursor / m_chunkLength; if (m_action->GetFlags() & MxDSAction::c_bit7 || m_action->GetFlags() & MxDSAction::c_looping || - m_writtenChunks != playedChunks || m_lockSize + (m_chunkLength * playedChunks) <= dwCurrentPlayCursor) + m_writtenChunks != playedChunks || m_lockSize + (m_chunkLength * playedChunks) <= dwCurrentPlayCursor) { MxMediaPresenter::DoneTickle(); + } } - else + else { MxMediaPresenter::DoneTickle(); + } } // FUNCTION: LEGO1 0x100b2130 void MxWavePresenter::LoopChunk(MxStreamChunk* p_chunk) { WriteToSoundBuffer(p_chunk->GetData(), p_chunk->GetLength()); - if (IsEnabled()) - m_subscriber->DestroyChunk(p_chunk); + if (IsEnabled()) { + m_subscriber->FreeDataChunk(p_chunk); + } } // FUNCTION: LEGO1 0x100b2160 @@ -234,25 +246,28 @@ MxResult MxWavePresenter::PutData() case e_streaming: if (m_currentChunk && FUN_100b1ba0()) { WriteToSoundBuffer(m_currentChunk->GetData(), m_currentChunk->GetLength()); - m_subscriber->DestroyChunk(m_currentChunk); + m_subscriber->FreeDataChunk(m_currentChunk); m_currentChunk = NULL; } if (!m_started) { m_dsBuffer->SetCurrentPosition(0); - if (m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK) + if (m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK) { m_started = TRUE; + } } break; case e_repeating: - if (m_started) + if (m_started) { break; + } m_dsBuffer->SetCurrentPosition(0); - if (m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1) == DS_OK) + if (m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1) == DS_OK) { m_started = TRUE; + } } } @@ -266,8 +281,9 @@ void MxWavePresenter::EndAction() MxAutoLocker lock(&m_criticalSection); MxMediaPresenter::EndAction(); - if (m_dsBuffer) + if (m_dsBuffer) { m_dsBuffer->Stop(); + } } } @@ -296,8 +312,9 @@ void MxWavePresenter::Enable(MxBool p_enable) m_writtenChunks = 0; m_started = FALSE; } - else if (m_dsBuffer) + else if (m_dsBuffer) { m_dsBuffer->Stop(); + } } } @@ -317,8 +334,9 @@ void MxWavePresenter::ParseExtra() char soundValue[512]; if (KeyValueStringParse(soundValue, g_strSOUND, extraCopy)) { - if (!strcmpi(soundValue, "FALSE")) + if (!strcmpi(soundValue, "FALSE")) { Enable(FALSE); + } } } } @@ -327,8 +345,9 @@ void MxWavePresenter::ParseExtra() void MxWavePresenter::Pause() { if (!m_paused && m_started) { - if (m_dsBuffer) + if (m_dsBuffer) { m_dsBuffer->Stop(); + } m_paused = TRUE; } } diff --git a/LEGO1/omni/src/common/mxatomid.cpp b/LEGO1/omni/src/common/mxatomid.cpp index 6c400eed..94decf7e 100644 --- a/LEGO1/omni/src/common/mxatomid.cpp +++ b/LEGO1/omni/src/common/mxatomid.cpp @@ -5,11 +5,13 @@ // FUNCTION: LEGO1 0x100acf90 MxAtomId::MxAtomId(const char* p_str, LookupMode p_mode) { - if (!MxOmni::GetInstance()) + if (!MxOmni::GetInstance()) { return; + } - if (!AtomIdCounterSet()) + if (!AtomIdCounterSet()) { return; + } MxAtomIdCounter* counter = GetCounter(p_str, p_mode); m_internal = counter->GetKey()->GetData(); @@ -25,20 +27,23 @@ MxAtomId::~MxAtomId() // FUNCTION: LEGO1 0x100acfe0 void MxAtomId::Destroy() { - if (!m_internal) + if (!m_internal) { return; + } - if (!MxOmni::GetInstance()) + if (!MxOmni::GetInstance()) { return; + } - if (!AtomIdCounterSet()) + if (!AtomIdCounterSet()) { return; + } #ifdef COMPAT_MODE MxAtomIdCounterSet::iterator it; { - MxAtomIdCounter id_counter(m_internal); - it = AtomIdCounterSet()->find(&id_counter); + MxAtomIdCounter idCounter(m_internal); + it = AtomIdCounterSet()->find(&idCounter); } #else MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find(&MxAtomIdCounter(m_internal)); @@ -51,8 +56,9 @@ void MxAtomId::Destroy() // FUNCTION: LEGO1 0x100ad1c0 MxAtomId& MxAtomId::operator=(const MxAtomId& p_atomId) { - if (m_internal) + if (m_internal) { Destroy(); + } if (p_atomId.m_internal && MxOmni::GetInstance() && AtomIdCounterSet()) { MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, e_exact); diff --git a/LEGO1/omni/src/common/mxatomidcounter.cpp b/LEGO1/omni/src/common/mxatomidcounter.cpp index f3be8764..cfec47b1 100644 --- a/LEGO1/omni/src/common/mxatomidcounter.cpp +++ b/LEGO1/omni/src/common/mxatomidcounter.cpp @@ -14,6 +14,7 @@ void MxAtomIdCounter::Inc() // FUNCTION: LEGO1 0x100ad800 void MxAtomIdCounter::Dec() { - if (m_value) + if (m_value) { m_value--; + } } diff --git a/LEGO1/omni/src/common/mxcompositepresenter.cpp b/LEGO1/omni/src/common/mxcompositepresenter.cpp index 5c5b612e..5996f634 100644 --- a/LEGO1/omni/src/common/mxcompositepresenter.cpp +++ b/LEGO1/omni/src/common/mxcompositepresenter.cpp @@ -50,16 +50,18 @@ MxResult MxCompositePresenter::StartAction(MxStreamController* p_controller, MxD if (presenter && presenter->AddToManager() == SUCCESS) { presenter->SetCompositePresenter(this); - if (presenter->StartAction(p_controller, action) == SUCCESS) + if (presenter->StartAction(p_controller, action) == SUCCESS) { success = TRUE; + } } if (success) { action->SetOrigin(this); m_list.push_back(presenter); } - else if (presenter) + else if (presenter) { delete presenter; + } } result = SUCCESS; @@ -73,8 +75,9 @@ void MxCompositePresenter::EndAction() { MxAutoLocker lock(&m_criticalSection); - if (!m_action) + if (!m_action) { return; + } ((MxDSMultiAction*) m_action)->GetActionList()->DeleteAll(FALSE); @@ -139,15 +142,18 @@ void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param) MxDSActionList* actions = ((MxDSMultiAction*) m_action)->GetActionList(); MxDSActionListCursor cursor(actions); - if (cursor.Find(action)) + if (cursor.Find(action)) { cursor.Detach(); + } } - if (presenter) + if (presenter) { delete presenter; + } - if (action) + if (action) { delete action; + } if (m_list.empty()) { EndAction(); @@ -155,8 +161,9 @@ void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param) else { if (m_action->IsA("MxDSSerialAction") && it != m_list.end()) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == e_idle) + if (presenter->GetCurrentTickleState() == e_idle) { presenter->SetTickleState(e_ready); + } } } } @@ -171,14 +178,16 @@ void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param) if (*it == presenter) { m_list.erase(it++); - if (presenter->GetCurrentTickleState() == e_idle) + if (presenter->GetCurrentTickleState() == e_idle) { presenter->SetTickleState(e_ready); + } MxDSActionList* actions = ((MxDSMultiAction*) m_action)->GetActionList(); MxDSActionListCursor cursor(actions); - if (cursor.Find(presenter->GetAction())) + if (cursor.Find(presenter->GetAction())) { cursor.Detach(); + } if (m_list.empty()) { EndAction(); @@ -186,8 +195,9 @@ void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param) else { if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == e_idle) + if (presenter->GetCurrentTickleState() == e_idle) { presenter->SetTickleState(e_ready); + } } } @@ -205,13 +215,15 @@ void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter) for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { if (*it == p_presenter) { if (++it == m_list.end()) { - if (m_compositePresenter) + if (m_compositePresenter) { m_compositePresenter->VTable0x60(this); + } } else if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == e_idle) + if (presenter->GetCurrentTickleState() == e_idle) { presenter->SetTickleState(e_ready); + } } return; } @@ -227,8 +239,9 @@ void MxCompositePresenter::SetTickleState(TickleState p_tickleState) MxPresenter* presenter = *it; presenter->SetTickleState(p_tickleState); - if (m_action->IsA("MxDSSerialAction") && p_tickleState == e_ready) + if (m_action->IsA("MxDSSerialAction") && p_tickleState == e_ready) { return; + } } } @@ -248,8 +261,9 @@ MxBool MxCompositePresenter::HasTickleStatePassed(TickleState p_tickleState) { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { MxPresenter* presenter = *it; - if (!presenter->HasTickleStatePassed(p_tickleState)) + if (!presenter->HasTickleStatePassed(p_tickleState)) { return FALSE; + } } return TRUE; diff --git a/LEGO1/omni/src/common/mxmediamanager.cpp b/LEGO1/omni/src/common/mxmediamanager.cpp index 778d7f86..6a9d99c5 100644 --- a/LEGO1/omni/src/common/mxmediamanager.cpp +++ b/LEGO1/omni/src/common/mxmediamanager.cpp @@ -50,8 +50,9 @@ void MxMediaManager::Destroy() { MxAutoLocker lock(&this->m_criticalSection); - if (this->m_presenters) + if (this->m_presenters) { delete this->m_presenters; + } Init(); } @@ -63,13 +64,15 @@ MxResult MxMediaManager::Tickle() MxPresenter* presenter; MxPresenterListCursor cursor(this->m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->Tickle(); + } cursor.Reset(); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->PutData(); + } return SUCCESS; } @@ -88,8 +91,9 @@ void MxMediaManager::UnregisterPresenter(MxPresenter& p_presenter) MxAutoLocker lock(&this->m_criticalSection); MxPresenterListCursor cursor(this->m_presenters); - if (cursor.Find(&p_presenter)) + if (cursor.Find(&p_presenter)) { cursor.Detach(); + } } // FUNCTION: LEGO1 0x100b8ac0 @@ -99,6 +103,7 @@ void MxMediaManager::StopPresenters() MxPresenter* presenter; MxPresenterListCursor cursor(this->m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->EndAction(); + } } diff --git a/LEGO1/omni/src/common/mxmediapresenter.cpp b/LEGO1/omni/src/common/mxmediapresenter.cpp index 2abc5007..b0a11c1b 100644 --- a/LEGO1/omni/src/common/mxmediapresenter.cpp +++ b/LEGO1/omni/src/common/mxmediapresenter.cpp @@ -26,21 +26,25 @@ void MxMediaPresenter::Destroy(MxBool p_fromDestructor) { MxAutoLocker lock(&m_criticalSection); - if (m_currentChunk && m_subscriber) - m_subscriber->DestroyChunk(m_currentChunk); + if (m_currentChunk && m_subscriber) { + m_subscriber->FreeDataChunk(m_currentChunk); + } - if (m_subscriber) + if (m_subscriber) { delete m_subscriber; + } - if (m_loopingChunkCursor) + if (m_loopingChunkCursor) { delete m_loopingChunkCursor; + } if (m_loopingChunks) { MxStreamChunkListCursor cursor(m_loopingChunks); MxStreamChunk* chunk; - while (cursor.Next(chunk)) + while (cursor.Next(chunk)) { chunk->Release(); + } delete m_loopingChunks; } @@ -48,8 +52,9 @@ void MxMediaPresenter::Destroy(MxBool p_fromDestructor) Init(); } - if (!p_fromDestructor) + if (!p_fromDestructor) { MxPresenter::Destroy(); + } } // FUNCTION: LEGO1 0x100b5650 @@ -58,12 +63,12 @@ MxStreamChunk* MxMediaPresenter::CurrentChunk() MxStreamChunk* chunk = NULL; if (m_subscriber) { - chunk = m_subscriber->CurrentChunk(); + chunk = m_subscriber->PeekData(); if (chunk && chunk->GetFlags() & MxDSChunk::c_bit3) { m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_bit7); - m_subscriber->NextChunk(); - m_subscriber->DestroyChunk(chunk); + m_subscriber->PopData(); + m_subscriber->FreeDataChunk(chunk); chunk = NULL; ProgressTickleState(e_done); } @@ -78,11 +83,11 @@ MxStreamChunk* MxMediaPresenter::NextChunk() MxStreamChunk* chunk = NULL; if (m_subscriber) { - chunk = m_subscriber->NextChunk(); + chunk = m_subscriber->PopData(); if (chunk && chunk->GetFlags() & MxDSChunk::c_bit3) { m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_bit7); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); chunk = NULL; ProgressTickleState(e_done); } @@ -102,16 +107,18 @@ MxResult MxMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAct m_loopingChunks = new MxStreamChunkList; m_loopingChunkCursor = new MxStreamChunkListCursor(m_loopingChunks); - if (!m_loopingChunks && !m_loopingChunkCursor) + if (!m_loopingChunks && !m_loopingChunkCursor) { goto done; + } } if (p_controller) { m_subscriber = new MxDSSubscriber; if (!m_subscriber || - m_subscriber->Create(p_controller, p_action->GetObjectId(), p_action->GetUnknown24()) != SUCCESS) + m_subscriber->Create(p_controller, p_action->GetObjectId(), p_action->GetUnknown24()) != SUCCESS) { goto done; + } } result = SUCCESS; @@ -126,8 +133,9 @@ void MxMediaPresenter::EndAction() { MxAutoLocker lock(&m_criticalSection); - if (!m_action) + if (!m_action) { return; + } m_currentChunk = NULL; @@ -178,7 +186,7 @@ void MxMediaPresenter::StreamingTickle() if (m_currentChunk) { if (m_currentChunk->GetFlags() & MxDSChunk::c_end) { - m_subscriber->DestroyChunk(m_currentChunk); + m_subscriber->FreeDataChunk(m_currentChunk); m_currentChunk = NULL; ProgressTickleState(e_repeating); } @@ -186,7 +194,7 @@ void MxMediaPresenter::StreamingTickle() LoopChunk(m_currentChunk); if (!IsEnabled()) { - m_subscriber->DestroyChunk(m_currentChunk); + m_subscriber->FreeDataChunk(m_currentChunk); m_currentChunk = NULL; } } @@ -198,18 +206,22 @@ void MxMediaPresenter::StreamingTickle() void MxMediaPresenter::RepeatingTickle() { if (IsEnabled() && !m_currentChunk) { - if (m_loopingChunkCursor) - if (!m_loopingChunkCursor->Next(m_currentChunk)) + if (m_loopingChunkCursor) { + if (!m_loopingChunkCursor->Next(m_currentChunk)) { m_loopingChunkCursor->Next(m_currentChunk); + } + } if (m_currentChunk) { MxLong time = m_currentChunk->GetTime(); - if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) + if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) { ProgressTickleState(e_unk5); + } } else { - if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) + if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) { ProgressTickleState(e_unk5); + } } } } @@ -217,8 +229,7 @@ void MxMediaPresenter::RepeatingTickle() // FUNCTION: LEGO1 0x100b5ef0 void MxMediaPresenter::DoneTickle() { - m_previousTickleStates |= 1 << m_currentTickleState; - m_currentTickleState = e_idle; + ProgressTickleState(e_idle); EndAction(); } @@ -248,8 +259,9 @@ void MxMediaPresenter::Enable(MxBool p_enable) SetTickleState(e_repeating); } else { - if (m_loopingChunkCursor) + if (m_loopingChunkCursor) { m_loopingChunkCursor->Reset(); + } m_currentChunk = NULL; SetTickleState(e_done); } diff --git a/LEGO1/omni/src/common/mxpresenter.cpp b/LEGO1/omni/src/common/mxpresenter.cpp index 9d074278..794d1227 100644 --- a/LEGO1/omni/src/common/mxpresenter.cpp +++ b/LEGO1/omni/src/common/mxpresenter.cpp @@ -49,8 +49,9 @@ MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action) // FUNCTION: LEGO1 0x100b4e40 void MxPresenter::EndAction() { - if (this->m_action == NULL) + if (this->m_action == NULL) { return; + } MxAutoLocker lock(&this->m_criticalSection); @@ -94,12 +95,13 @@ void MxPresenter::ParseExtra() token = strtok(NULL, g_parseExtraTokens); MxS32 val = token ? atoi(token) : 0; - MxEntity* result = MxOmni::GetInstance()->FindWorld(buf, val, this); + MxEntity* result = MxOmni::GetInstance()->AddToWorld(buf, val, this); m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_world); - if (result) + if (result) { SendToCompositePresenter(MxOmni::GetInstance()); + } } } } @@ -133,28 +135,33 @@ MxResult MxPresenter::Tickle() case e_ready: this->ReadyTickle(); - if (m_currentTickleState != e_starting) + if (m_currentTickleState != e_starting) { break; + } case e_starting: this->StartingTickle(); - if (m_currentTickleState != e_streaming) + if (m_currentTickleState != e_streaming) { break; + } case e_streaming: this->StreamingTickle(); - if (m_currentTickleState != e_repeating) + if (m_currentTickleState != e_repeating) { break; + } case e_repeating: this->RepeatingTickle(); - if (m_currentTickleState != e_unk5) + if (m_currentTickleState != e_unk5) { break; + } case e_unk5: this->Unk5Tickle(); - if (m_currentTickleState != e_done) + if (m_currentTickleState != e_done) { break; + } case e_done: this->DoneTickle(); default: @@ -170,10 +177,12 @@ void MxPresenter::Enable(MxBool p_enable) if (this->m_action && this->IsEnabled() != p_enable) { MxU32 flags = this->m_action->GetFlags(); - if (p_enable) + if (p_enable) { this->m_action->SetFlags(flags | MxDSAction::c_enabled); - else + } + else { this->m_action->SetFlags(flags & ~MxDSAction::c_enabled); + } } } diff --git a/LEGO1/omni/src/common/mxticklemanager.cpp b/LEGO1/omni/src/common/mxticklemanager.cpp index 29f8428c..e8b0d410 100644 --- a/LEGO1/omni/src/common/mxticklemanager.cpp +++ b/LEGO1/omni/src/common/mxticklemanager.cpp @@ -5,7 +5,7 @@ #include "mxtimer.h" #include "mxtypes.h" -#define TICKLE_MANAGER_FLAG_DESTROY 0x1 +#define TICKLE_MANAGER_FLAG_DESTROY 0x01 DECOMP_SIZE_ASSERT(MxTickleClient, 0x10); DECOMP_SIZE_ASSERT(MxTickleManager, 0x14); @@ -45,8 +45,9 @@ MxResult MxTickleManager::Tickle() else { it++; - if (client->GetLastUpdateTime() > time) + if (client->GetLastUpdateTime() > time) { client->SetLastUpdateTime(-client->GetTickleInterval()); + } if ((client->GetTickleInterval() + client->GetLastUpdateTime()) < time) { client->GetClient()->Tickle(); @@ -64,8 +65,9 @@ void MxTickleManager::RegisterClient(MxCore* p_client, MxTime p_interval) MxTime interval = GetClientTickleInterval(p_client); if (interval == TICKLE_MANAGER_NOT_FOUND) { MxTickleClient* client = new MxTickleClient(p_client, p_interval); - if (client != NULL) + if (client != NULL) { m_clients.push_back(client); + } } } @@ -102,8 +104,9 @@ MxTime MxTickleManager::GetClientTickleInterval(MxCore* p_client) MxTickleClientPtrList::iterator it = m_clients.begin(); while (it != m_clients.end()) { MxTickleClient* client = *it; - if ((client->GetClient() == p_client) && ((client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) == 0)) + if ((client->GetClient() == p_client) && ((client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) == 0)) { return client->GetTickleInterval(); + } it++; } diff --git a/LEGO1/omni/src/common/mxutil.cpp b/LEGO1/omni/src/common/mxutil.cpp index 29b71863..5ffab77c 100644 --- a/LEGO1/omni/src/common/mxutil.cpp +++ b/LEGO1/omni/src/common/mxutil.cpp @@ -1,10 +1,12 @@ #include "mxutil.h" +#include "mxcompositepresenter.h" #include "mxdsaction.h" #include "mxdsactionlist.h" #include "mxdsfile.h" #include "mxdsmultiaction.h" #include "mxdsobject.h" +#include "mxpresenterlist.h" #include "mxrect32.h" // GLOBAL: LEGO1 0x101020e8 @@ -33,15 +35,17 @@ MxBool GetRectIntersection( MxRect32 rect(0, 0, *p_width, *p_height); rect.AddPoint(rect1Origin); - if (!rect.IntersectsWith(rect1)) + if (!rect.IntersectsWith(rect1)) { return FALSE; + } rect.Intersect(rect1); rect.SubtractPoint(rect1Origin); rect.AddPoint(rect2Origin); - if (!rect.IntersectsWith(rect2)) + if (!rect.IntersectsWith(rect2)) { return FALSE; + } rect.Intersect(rect2); rect.SubtractPoint(rect2Origin); @@ -91,8 +95,9 @@ MxBool KeyValueStringParse(char* p_outputValue, const char* p_key, const char* p char* cur = &token[strlen(p_key)]; cur++; while (*cur != ',') { - if (*cur == ' ' || *cur == '\0' || *cur == '\t' || *cur == '\n' || *cur == '\r') + if (*cur == ' ' || *cur == '\0' || *cur == '\t' || *cur == '\n' || *cur == '\r') { break; + } *p_outputValue++ = *cur++; } *p_outputValue = '\0'; @@ -109,6 +114,19 @@ MxBool KeyValueStringParse(char* p_outputValue, const char* p_key, const char* p return didMatch; } +// FUNCTION: LEGO1 0x100b7170 +MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter) +{ + for (MxCompositePresenterList::iterator it = p_presenterList.begin(); it != p_presenterList.end(); it++) { + if (p_presenter == *it || ((*it)->IsA("MxCompositePresenter") && + ContainsPresenter(((MxCompositePresenter*) *it)->GetList(), p_presenter))) { + return TRUE; + } + } + + return FALSE; +} + // FUNCTION: LEGO1 0x100b7210 void SetOmniUserMessage(void (*p_userMsg)(const char*, int)) { diff --git a/LEGO1/omni/src/common/mxvariabletable.cpp b/LEGO1/omni/src/common/mxvariabletable.cpp index 9503ee5e..94bdbacb 100644 --- a/LEGO1/omni/src/common/mxvariabletable.cpp +++ b/LEGO1/omni/src/common/mxvariabletable.cpp @@ -41,8 +41,9 @@ void MxVariableTable::SetVariable(MxVariable* p_var) MxHashTableCursor cursor(this); MxBool found = cursor.Find(p_var); - if (found) + if (found) { cursor.DeleteMatch(); + } MxHashTable::Add(p_var); } diff --git a/LEGO1/omni/src/event/mxeventmanager.cpp b/LEGO1/omni/src/event/mxeventmanager.cpp index 7819c38f..c0ee3229 100644 --- a/LEGO1/omni/src/event/mxeventmanager.cpp +++ b/LEGO1/omni/src/event/mxeventmanager.cpp @@ -30,11 +30,13 @@ void MxEventManager::Destroy(MxBool p_fromDestructor) m_thread->Terminate(); delete m_thread; } - else + else { TickleManager()->UnregisterClient(this); + } - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaManager::Destroy(); + } } // FUNCTION: LEGO1 0x100c04a0 @@ -50,21 +52,25 @@ MxResult MxEventManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) locked = TRUE; this->m_thread = new MxTickleThread(this, p_frequencyMS); - if (!this->m_thread || this->m_thread->Start(0, 0) != SUCCESS) + if (!this->m_thread || this->m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; } done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { this->m_criticalSection.Leave(); + } return status; } diff --git a/LEGO1/omni/src/event/mxeventpresenter.cpp b/LEGO1/omni/src/event/mxeventpresenter.cpp index 03b0de14..9652ca9a 100644 --- a/LEGO1/omni/src/event/mxeventpresenter.cpp +++ b/LEGO1/omni/src/event/mxeventpresenter.cpp @@ -42,13 +42,15 @@ MxResult MxEventPresenter::AddToManager() // FUNCTION: LEGO1 0x100c2de0 void MxEventPresenter::Destroy() { - if (EventManager()) + if (EventManager()) { EventManager()->UnregisterPresenter(*this); + } m_criticalSection.Enter(); - if (m_data) + if (m_data) { delete[] m_data; + } Init(); @@ -69,7 +71,7 @@ void MxEventPresenter::ReadyTickle() if (chunk) { CopyData(chunk); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); ParseExtra(); ProgressTickleState(e_starting); } @@ -80,8 +82,9 @@ void MxEventPresenter::StartingTickle() { MxStreamChunk* chunk = CurrentChunk(); - if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { ProgressTickleState(e_streaming); + } } // FUNCTION: LEGO1 0x100c2ef0 @@ -103,8 +106,9 @@ MxResult MxEventPresenter::PutData() variableTable->SetVariable(key, value); } - if (m_currentTickleState == e_streaming) - m_subscriber->DestroyChunk(m_currentChunk); + if (m_currentTickleState == e_streaming) { + m_subscriber->FreeDataChunk(m_currentChunk); + } m_currentChunk = NULL; } } diff --git a/LEGO1/omni/src/main/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp index f9fa5733..c04425b1 100644 --- a/LEGO1/omni/src/main/mxomni.cpp +++ b/LEGO1/omni/src/main/mxomni.cpp @@ -113,7 +113,7 @@ MxOmni::MxOmni() } // FUNCTION: LEGO1 0x100aefb0 -MxEntity* MxOmni::FindWorld(const char*, MxS32, MxPresenter*) +MxEntity* MxOmni::AddToWorld(const char*, MxS32, MxPresenter*) { return NULL; } @@ -158,48 +158,56 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) { MxResult result = FAILURE; - if (!(m_atomIdCounterSet = new MxAtomIdCounterSet())) + if (!(m_atomIdCounterSet = new MxAtomIdCounterSet())) { goto done; + } m_mediaPath = p_param.GetMediaPath(); m_windowHandle = p_param.GetWindowHandle(); if (p_param.CreateFlags().CreateObjectFactory()) { - if (!(m_objectFactory = new MxObjectFactory())) + if (!(m_objectFactory = new MxObjectFactory())) { goto done; + } } if (p_param.CreateFlags().CreateVariableTable()) { - if (!(m_variableTable = new MxVariableTable())) + if (!(m_variableTable = new MxVariableTable())) { goto done; + } } if (p_param.CreateFlags().CreateTimer()) { - if (!(m_timer = new MxTimer())) + if (!(m_timer = new MxTimer())) { goto done; + } } if (p_param.CreateFlags().CreateTickleManager()) { - if (!(m_tickleManager = new MxTickleManager())) + if (!(m_tickleManager = new MxTickleManager())) { goto done; + } } if (p_param.CreateFlags().CreateNotificationManager()) { - if (m_notificationManager = new MxNotificationManager()) { - if (m_notificationManager->Create(100, 0) != SUCCESS) + if ((m_notificationManager = new MxNotificationManager())) { + if (m_notificationManager->Create(100, 0) != SUCCESS) { goto done; + } } - else + else { goto done; + } } if (p_param.CreateFlags().CreateStreamer()) { - if (!(m_streamer = new MxStreamer()) || m_streamer->Create() != SUCCESS) + if (!(m_streamer = new MxStreamer()) || m_streamer->Create() != SUCCESS) { goto done; + } } if (p_param.CreateFlags().CreateVideoManager()) { - if (m_videoManager = new MxVideoManager()) { + if ((m_videoManager = new MxVideoManager())) { if (m_videoManager->Create(p_param.GetVideoParam(), 100, 0) != SUCCESS) { delete m_videoManager; m_videoManager = NULL; @@ -208,7 +216,7 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } if (p_param.CreateFlags().CreateSoundManager()) { - if (m_soundManager = new MxSoundManager()) { + if ((m_soundManager = new MxSoundManager())) { if (m_soundManager->Create(10, 0) != SUCCESS) { delete m_soundManager; m_soundManager = NULL; @@ -217,7 +225,7 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } if (p_param.CreateFlags().CreateMusicManager()) { - if (m_musicManager = new MxMusicManager()) { + if ((m_musicManager = new MxMusicManager())) { if (m_musicManager->Create(50, 0) != SUCCESS) { delete m_musicManager; m_musicManager = NULL; @@ -226,7 +234,7 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } if (p_param.CreateFlags().CreateEventManager()) { - if (m_eventManager = new MxEventManager()) { + if ((m_eventManager = new MxEventManager())) { if (m_eventManager->Create(50, 0) != SUCCESS) { delete m_eventManager; m_eventManager = NULL; @@ -235,9 +243,11 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } result = SUCCESS; + done: - if (result != SUCCESS) + if (result != SUCCESS) { Destroy(); + } return result; } @@ -255,8 +265,9 @@ void MxOmni::Destroy() // TODO: private members if (m_notificationManager) { while (m_notificationManager->GetQueue()) { - if (m_notificationManager->GetQueue()->size() == 0) + if (m_notificationManager->GetQueue()->size() == 0) { break; + } m_notificationManager->Tickle(); } @@ -317,16 +328,18 @@ MxResult MxOmni::CreatePresenter(MxStreamController* p_controller, MxDSAction& p if (object) { if (object->AddToManager() == SUCCESS) { MxPresenter* sender = p_action.GetUnknown28(); - if (!sender) + if (!sender) { sender = p_controller->FUN_100c1e70(p_action); + } if (sender) { p_action.SetOrigin(sender); object->SetCompositePresenter((MxCompositePresenter*) sender); } else { - if (!p_action.GetOrigin()) + if (!p_action.GetOrigin()) { p_action.SetOrigin(this); + } object->SetCompositePresenter(NULL); } @@ -381,16 +394,18 @@ void MxOmni::DestroyInstance() // FUNCTION: LEGO1 0x100b06b0 MxBool MxOmni::ActionSourceEquals(MxDSAction* p_action, const char* p_name) { - if (!strcmp(p_action->GetSourceName(), p_name)) + if (!strcmp(p_action->GetSourceName(), p_name)) { return TRUE; + } if (p_action->IsA("MxDSMultiAction")) { MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList()); MxDSAction* action; while (cursor.Next(action)) { - if (ActionSourceEquals(action, p_name)) + if (ActionSourceEquals(action, p_name)) { return TRUE; + } } } @@ -402,8 +417,9 @@ MxLong MxOmni::Notify(MxParam& p_param) { MxAutoLocker lock(&this->m_criticalsection); - if (((MxNotificationParam&) p_param).GetNotification() != c_notificationEndAction) + if (((MxNotificationParam&) p_param).GetNotification() != c_notificationEndAction) { return 0; + } return HandleActionEnd(p_param); } @@ -476,8 +492,9 @@ MxBool MxOmni::DoesEntityExist(MxDSAction& p_dsAction) if (m_streamer->FUN_100b9b30(p_dsAction)) { MxNotificationPtrList* queue = m_notificationManager->GetQueue(); - if (!queue || queue->size() == 0) + if (!queue || queue->size() == 0) { return TRUE; + } } return FALSE; } diff --git a/LEGO1/omni/src/notify/mxnotificationmanager.cpp b/LEGO1/omni/src/notify/mxnotificationmanager.cpp index 37eab387..fe10a82c 100644 --- a/LEGO1/omni/src/notify/mxnotificationmanager.cpp +++ b/LEGO1/omni/src/notify/mxnotificationmanager.cpp @@ -8,7 +8,7 @@ #include "mxticklemanager.h" #include "mxtypes.h" -DECOMP_SIZE_ASSERT(MxNotification, 0x8); +DECOMP_SIZE_ASSERT(MxNotification, 0x08); DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40); // FUNCTION: LEGO1 0x100ac220 @@ -128,9 +128,9 @@ void MxNotificationManager::FlushPending(MxCore* p_listener) MxNotificationPtrList::iterator it = m_sendList->begin(); while (it != m_sendList->end()) { notif = *it; - if ((notif->GetTarget()->GetId() == p_listener->GetId()) || - (notif->GetParam()->GetSender()) && - (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { + if (notif->GetTarget()->GetId() == p_listener->GetId() || + (notif->GetParam()->GetSender() && notif->GetParam()->GetSender()->GetId() == p_listener->GetId() + )) { m_sendList->erase(it++); pending.push_back(notif); } @@ -143,8 +143,8 @@ void MxNotificationManager::FlushPending(MxCore* p_listener) MxNotificationPtrList::iterator it = m_queue->begin(); while (it != m_queue->end()) { notif = *it; - if ((notif->GetTarget()->GetId() == p_listener->GetId()) || - (notif->GetParam()->GetSender()) && (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { + if (notif->GetTarget()->GetId() == p_listener->GetId() || + (notif->GetParam()->GetSender() && notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { m_queue->erase(it++); pending.push_back(notif); } @@ -169,8 +169,9 @@ void MxNotificationManager::Register(MxCore* p_listener) MxAutoLocker lock(&m_lock); MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); - if (it != m_listenerIds.end()) + if (it != m_listenerIds.end()) { return; + } m_listenerIds.push_back(p_listener->GetId()); } diff --git a/LEGO1/omni/src/notify/mxnotificationparam.cpp b/LEGO1/omni/src/notify/mxnotificationparam.cpp index cb15a2df..cf5bf8b9 100644 --- a/LEGO1/omni/src/notify/mxnotificationparam.cpp +++ b/LEGO1/omni/src/notify/mxnotificationparam.cpp @@ -2,4 +2,4 @@ #include "decomp.h" -DECOMP_SIZE_ASSERT(MxNotificationParam, 0xc); +DECOMP_SIZE_ASSERT(MxNotificationParam, 0x0c); diff --git a/LEGO1/omni/src/notify/mxtype17notificationparam.cpp b/LEGO1/omni/src/notify/mxtype17notificationparam.cpp deleted file mode 100644 index dbb047f6..00000000 --- a/LEGO1/omni/src/notify/mxtype17notificationparam.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "mxtype17notificationparam.h" - -DECOMP_SIZE_ASSERT(MxType17NotificationParam, 0x2c) diff --git a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp index 5833d18f..a2b2edf9 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp @@ -35,8 +35,9 @@ MxDiskStreamController::~MxDiskStreamController() } MxDSAction* action; - while (m_unk0x3c.PopFront(action)) + while (m_unk0x3c.PopFront(action)) { delete action; + } if (m_provider) { delete m_provider; @@ -45,11 +46,13 @@ MxDiskStreamController::~MxDiskStreamController() FUN_100c8720(); - while (m_list0x80.PopFront(action)) + while (m_list0x80.PopFront(action)) { FUN_100c7cb0((MxDSStreamingAction*) action); + } - while (m_list0x64.PopFront(action)) + while (m_list0x64.PopFront(action)) { FUN_100c7cb0((MxDSStreamingAction*) action); + } while (!m_list0x74.empty()) { MxDSBuffer* buffer = m_list0x74.front(); @@ -130,15 +133,17 @@ void MxDiskStreamController::FUN_100c7980() buffer = new MxDSBuffer(); if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBuffer::e_chunk) != SUCCESS) { - if (buffer) + if (buffer) { delete buffer; + } return; } action = VTable0x28(); if (!action) { - if (buffer) + if (buffer) { delete buffer; + } return; } @@ -228,8 +233,9 @@ MxResult MxDiskStreamController::FUN_100c7d10() MxAutoLocker lock(&this->m_criticalSection); MxDSStreamingAction* action = FUN_100c7db0(); - if (!action) + if (!action) { return FAILURE; + } if (FUN_100c8360(action) != SUCCESS) { VTable0x24(action); @@ -290,11 +296,13 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) FUN_100c7f40(action); - if (VTable0x2c(p_action, entry->GetUnknown94()) != SUCCESS) + if (VTable0x2c(p_action, entry->GetUnknown94()) != SUCCESS) { return FAILURE; + } } - else if (MxStreamController::VTable0x20(p_action) != SUCCESS) + else if (MxStreamController::VTable0x20(p_action) != SUCCESS) { return FAILURE; + } m_unk0x70 = TRUE; m_unk0xc4 = TRUE; @@ -312,8 +320,9 @@ void MxDiskStreamController::FUN_100c8120(MxDSAction* p_action) while (TRUE) { MxDSAction* found = m_unk0x54.Find(p_action, TRUE); - if (!found) + if (!found) { break; + } delete found; } } @@ -408,8 +417,9 @@ void MxDiskStreamController::FUN_100c8540() m_list0x74.erase(it++); FUN_100c7ce0(buf); } - else + else { it++; + } } if (m_nextActionList.empty()) { diff --git a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp index 7b4b6ef5..88f70c7d 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp @@ -19,8 +19,9 @@ MxU32 g_unk0x10102878 = 0; // FUNCTION: LEGO1 0x100d0f30 MxResult MxDiskStreamProviderThread::Run() { - if (m_target) + if (m_target) { ((MxDiskStreamProvider*) m_target)->WaitForWorkToComplete(); + } MxThread::Run(); // They should probably have writen "return MxThread::Run()" but they didn't. return SUCCESS; @@ -55,11 +56,13 @@ MxDiskStreamProvider::~MxDiskStreamProvider() m_list.PopFrontStreamingAction(action); } - if (!action) + if (!action) { break; + } - if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { g_unk0x10102878--; + } ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); } while (action); @@ -70,8 +73,9 @@ MxDiskStreamProvider::~MxDiskStreamProvider() m_thread.Terminate(); } - if (m_pFile) + if (m_pFile) { delete m_pFile; + } m_pFile = NULL; } @@ -91,8 +95,9 @@ MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource) path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si"; m_pFile->SetFileName(path.GetData()); - if (m_pFile->Open(0) != 0) + if (m_pFile->Open(0) != 0) { goto done; + } } m_remainingWork = TRUE; @@ -123,11 +128,13 @@ void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) m_list.PopFrontStreamingAction(action); } - if (!action) + if (!action) { return; + } - if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { g_unk0x10102878--; + } ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); } while (action); @@ -139,11 +146,13 @@ void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) action = (MxDSStreamingAction*) m_list.Find(p_action, TRUE); } - if (!action) + if (!action) { return; + } - if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { g_unk0x10102878--; + } ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); } while (action); @@ -155,8 +164,9 @@ MxResult MxDiskStreamProvider::WaitForWorkToComplete() { while (m_remainingWork) { m_busySemaphore.Wait(INFINITE); - if (m_unk0x35) + if (m_unk0x35) { PerformWork(); + } } return SUCCESS; @@ -165,14 +175,16 @@ MxResult MxDiskStreamProvider::WaitForWorkToComplete() // FUNCTION: LEGO1 0x100d1780 MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action) { - if (!m_remainingWork) + if (!m_remainingWork) { return FAILURE; + } if (p_action->GetUnknown9c() > 0 && !p_action->GetUnknowna0()) { MxDSBuffer* buffer = new MxDSBuffer(); - if (!buffer) + if (!buffer) { return FAILURE; + } if (buffer->AllocateBuffer(GetFileSize(), MxDSBuffer::e_allocate) != SUCCESS) { delete buffer; @@ -220,8 +232,9 @@ void MxDiskStreamProvider::PerformWork() { MxAutoLocker lock(&m_criticalSection); - if (!m_list.PopFrontStreamingAction(streamingAction)) + if (!m_list.PopFrontStreamingAction(streamingAction)) { goto done; + } } if (streamingAction->GetUnknowna0()->GetWriteOffset() < 0x20000) { @@ -276,15 +289,17 @@ MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) { MxDSBuffer* buffer = new MxDSBuffer(); - if (!buffer) + if (!buffer) { return FAILURE; + } MxU32 size = p_action->GetUnknowna0()->GetWriteOffset() - p_action->GetUnknown94() + p_action->GetBufferOffset() + (p_action->GetUnknowna4() ? p_action->GetUnknowna4()->GetWriteOffset() : 0); if (buffer->AllocateBuffer(size, MxDSBuffer::e_allocate) != SUCCESS) { - if (!buffer) + if (!buffer) { return FAILURE; + } delete buffer; return FAILURE; @@ -327,8 +342,9 @@ MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) size = ReadData(*pdata, buffer->GetWriteOffset()); MxDSBuffer* buffer3 = new MxDSBuffer(); - if (!buffer3) + if (!buffer3) { return FAILURE; + } if (buffer3->AllocateBuffer(size, MxDSBuffer::e_allocate) == SUCCESS) { memcpy(buffer3->GetBuffer(), p_action->GetUnknowna4()->GetBuffer(), size); @@ -342,8 +358,9 @@ MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) MxU8* data2 = buffer4->GetBuffer(); while (TRUE) { - if (*MxStreamChunk::IntoTime(data2) > p_action->GetUnknown9c()) + if (*MxStreamChunk::IntoTime(data2) > p_action->GetUnknown9c()) { break; + } data += MxDSChunk::Size(*MxDSChunk::IntoLength(data)); unk0x14 += MxDSChunk::Size(*MxDSChunk::IntoLength(data)); diff --git a/LEGO1/omni/src/stream/mxdsbuffer.cpp b/LEGO1/omni/src/stream/mxdsbuffer.cpp index 380cc1e0..697984e0 100644 --- a/LEGO1/omni/src/stream/mxdsbuffer.cpp +++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp @@ -56,7 +56,7 @@ MxDSBuffer::~MxDSBuffer() } case 0x80: { MxU32 a = - (m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10); + (m_pBuffer - streamer->GetSubclass2().GetBuffer()) / (streamer->GetSubclass2().GetSize() << 10); MxU32 bit = 1 << ((MxU8) a & 0x1f); MxU32 index = (a & ~0x18u) >> 3; @@ -164,19 +164,22 @@ MxResult MxDSBuffer::FUN_100c67b0( MxResult result = FAILURE; m_unk0x30 = (MxDSStreamingAction*) p_controller->GetUnk0x3c().Find(p_action, FALSE); - if (m_unk0x30 == NULL) + if (m_unk0x30 == NULL) { return FAILURE; + } MxU8* data; - while (data = (MxU8*) SkipToData()) { + while ((data = (MxU8*) SkipToData())) { if (*p_streamingAction == NULL) { result = CreateObject(p_controller, (MxU32*) data, p_action, p_streamingAction); - if (result == FAILURE) + if (result == FAILURE) { return result; + } // TODO: Not a MxResult value? - if (result == 1) + if (result == 1) { break; + } } else { MxDSBuffer* buffer = (*p_streamingAction)->GetUnknowna0(); @@ -226,8 +229,9 @@ MxResult MxDSBuffer::CreateObject( return FAILURE; } - if (*p_data == FOURCC('M', 'x', 'O', 'b')) + if (*p_data == FOURCC('M', 'x', 'O', 'b')) { return StartPresenterFromAction(p_controller, p_action, (MxDSAction*) header); + } else if (*p_data == FOURCC('M', 'x', 'C', 'h')) { MxStreamChunk* chunk = (MxStreamChunk*) header; if (!m_unk0x30->HasId((chunk)->GetObjectId())) { @@ -316,8 +320,9 @@ MxResult MxDSBuffer::ParseChunk( } } - if (buffer) + if (buffer) { delete buffer; + } delete p_header; return FAILURE; @@ -337,8 +342,9 @@ MxResult MxDSBuffer::ParseChunk( MxNextActionDataStart* data = p_controller->FindNextActionDataStartFromStreamingAction(m_unk0x30); - if (data) + if (data) { data->SetData(m_unk0x30->GetBufferOffset()); + } m_unk0x30->FUN_100cd2d0(); } @@ -472,8 +478,9 @@ MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) if (bytesRead <= m_bytesRemaining) { memcpy(m_pBuffer + m_writeOffset - m_bytesRemaining, ptr, bytesRead); - if (m_writeOffset == m_bytesRemaining) + if (m_writeOffset == m_bytesRemaining) { *(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoLength(m_pBuffer) + MxStreamChunk::GetHeaderSize(); + } m_bytesRemaining -= bytesRead; result = SUCCESS; @@ -510,14 +517,17 @@ MxU8* MxDSBuffer::FUN_100c6fa0(MxU8* p_data) break; case FOURCC('M', 'x', 'O', 'b'): case FOURCC('M', 'x', 'C', 'h'): - if (current != p_data) + if (current != p_data) { return current; + } current = ((MxU32) current & 1) + current; current += 8; break; case FOURCC('M', 'x', 'H', 'd'): current += (((MxU32*) current)[1] + 8); break; + default: + return NULL; } } diff --git a/LEGO1/omni/src/stream/mxdschunk.cpp b/LEGO1/omni/src/stream/mxdschunk.cpp index 61d794cc..a964d0fa 100644 --- a/LEGO1/omni/src/stream/mxdschunk.cpp +++ b/LEGO1/omni/src/stream/mxdschunk.cpp @@ -15,12 +15,13 @@ MxDSChunk::MxDSChunk() // FUNCTION: LEGO1 0x100be170 MxDSChunk::~MxDSChunk() { - if (m_flags & c_bit1) + if (m_flags & c_bit1) { delete[] m_data; + } } // FUNCTION: LEGO1 0x100be1e0 MxU32 MxDSChunk::GetHeaderSize() { - return 0xe; + return 0x0e; } diff --git a/LEGO1/omni/src/stream/mxdsfile.cpp b/LEGO1/omni/src/stream/mxdsfile.cpp index 3e03ad6e..9b6fa661 100644 --- a/LEGO1/omni/src/stream/mxdsfile.cpp +++ b/LEGO1/omni/src/stream/mxdsfile.cpp @@ -1,15 +1,14 @@ #include "mxdsfile.h" +#include "decomp.h" + #include #define SI_MAJOR_VERSION 2 #define SI_MINOR_VERSION 2 -// FUNCTION: LEGO1 0x100bfed0 -MxDSFile::~MxDSFile() -{ - Close(); -} +DECOMP_SIZE_ASSERT(MxDSFile::ChunkHeader, 0x0c) +DECOMP_SIZE_ASSERT(MxDSFile, 0x7c) // FUNCTION: LEGO1 0x100cc4b0 MxDSFile::MxDSFile(const char* p_filename, MxULong p_skipReadingChunks) @@ -37,10 +36,10 @@ MxLong MxDSFile::Open(MxULong p_uStyle) } if (longResult != 0) { - Close(); // vtable + 0x18 + Close(); } else { - Seek(0, 0); // vtable + 0x24 + Seek(0, 0); } return longResult; @@ -62,7 +61,7 @@ MxLong MxDSFile::ReadChunks() return -1; } - m_io.Read(&m_header, 0xc); + m_io.Read(&m_header, 0x0c); if ((m_header.m_majorVersion == SI_MAJOR_VERSION) && (m_header.m_minorVersion == SI_MINOR_VERSION)) { childChunk.ckid = FOURCC('M', 'x', 'O', 'f'); if (m_io.Descend(&childChunk, &topChunk, 0) != 0) { @@ -98,8 +97,9 @@ MxLong MxDSFile::Close() // FUNCTION: LEGO1 0x100cc780 MxResult MxDSFile::Read(unsigned char* p_buf, MxULong p_nbytes) { - if (m_io.Read(p_buf, p_nbytes) != p_nbytes) + if (m_io.Read(p_buf, p_nbytes) != p_nbytes) { return FAILURE; + } m_position += p_nbytes; return SUCCESS; diff --git a/LEGO1/omni/src/stream/mxdssubscriber.cpp b/LEGO1/omni/src/stream/mxdssubscriber.cpp index 82ca1730..18832493 100644 --- a/LEGO1/omni/src/stream/mxdssubscriber.cpp +++ b/LEGO1/omni/src/stream/mxdssubscriber.cpp @@ -16,17 +16,20 @@ MxDSSubscriber::MxDSSubscriber() // FUNCTION: LEGO1 0x100b7e00 MxDSSubscriber::~MxDSSubscriber() { - if (m_controller) + if (m_controller) { m_controller->RemoveSubscriber(this); + } - DeleteChunks(); + DestroyData(); - if (m_pendingChunkCursor) + if (m_pendingChunkCursor) { delete m_pendingChunkCursor; + } m_pendingChunkCursor = NULL; - if (m_consumedChunkCursor) + if (m_consumedChunkCursor) { delete m_consumedChunkCursor; + } m_consumedChunkCursor = NULL; } @@ -36,24 +39,27 @@ MxResult MxDSSubscriber::Create(MxStreamController* p_controller, MxU32 p_object m_objectId = p_objectId; m_unk0x48 = p_unk0x48; - if (!p_controller) + if (!p_controller) { return FAILURE; + } m_controller = p_controller; m_pendingChunkCursor = new MxStreamChunkListCursor(&m_pendingChunks); - if (!m_pendingChunkCursor) + if (!m_pendingChunkCursor) { return FAILURE; + } m_consumedChunkCursor = new MxStreamChunkListCursor(&m_consumedChunks); - if (!m_consumedChunkCursor) + if (!m_consumedChunkCursor) { return FAILURE; + } m_controller->AddSubscriber(this); return SUCCESS; } // FUNCTION: LEGO1 0x100b8030 -void MxDSSubscriber::DeleteChunks() +void MxDSSubscriber::DestroyData() { if (m_controller) { MxStreamChunk* chunk = NULL; @@ -71,25 +77,28 @@ void MxDSSubscriber::DeleteChunks() } // FUNCTION: LEGO1 0x100b8150 -MxResult MxDSSubscriber::AddChunk(MxStreamChunk* p_chunk, MxBool p_append) +MxResult MxDSSubscriber::AddData(MxStreamChunk* p_chunk, MxBool p_append) { if (m_pendingChunkCursor) { - if (p_append) + if (p_append) { m_pendingChunks.Append(p_chunk); - else + } + else { m_pendingChunks.Prepend(p_chunk); + } } return SUCCESS; } // FUNCTION: LEGO1 0x100b8250 -MxStreamChunk* MxDSSubscriber::NextChunk() +MxStreamChunk* MxDSSubscriber::PopData() { MxStreamChunk* chunk = NULL; - if (m_pendingChunkCursor) + if (m_pendingChunkCursor) { m_pendingChunkCursor->First(chunk); + } if (chunk) { m_pendingChunkCursor->Detach(); @@ -100,26 +109,29 @@ MxStreamChunk* MxDSSubscriber::NextChunk() } // FUNCTION: LEGO1 0x100b8360 -MxStreamChunk* MxDSSubscriber::CurrentChunk() +MxStreamChunk* MxDSSubscriber::PeekData() { MxStreamChunk* chunk = NULL; - if (m_pendingChunkCursor) + if (m_pendingChunkCursor) { m_pendingChunkCursor->First(chunk); + } return chunk; } // FUNCTION: LEGO1 0x100b8390 -void MxDSSubscriber::DestroyChunk(MxStreamChunk* p_chunk) +void MxDSSubscriber::FreeDataChunk(MxStreamChunk* p_chunk) { if (p_chunk) { if (m_consumedChunkCursor->Find(p_chunk)) { m_consumedChunkCursor->Detach(); - if (p_chunk) + if (p_chunk) { delete p_chunk; + } } - else if (p_chunk->GetFlags() & MxDSChunk::c_bit1 && p_chunk) + else if (p_chunk->GetFlags() & MxDSChunk::c_bit1 && p_chunk) { delete p_chunk; + } } } diff --git a/LEGO1/omni/src/stream/mxioinfo.cpp b/LEGO1/omni/src/stream/mxioinfo.cpp index 9951c174..ec666c31 100644 --- a/LEGO1/omni/src/stream/mxioinfo.cpp +++ b/LEGO1/omni/src/stream/mxioinfo.cpp @@ -72,8 +72,9 @@ MxU16 MXIOINFO::Close(MxLong p_unused) _lclose((HFILE) m_info.hmmio); m_info.hmmio = 0; - if (m_info.dwFlags & MMIO_ALLOCBUF) + if (m_info.dwFlags & MMIO_ALLOCBUF) { delete[] m_info.pchBuffer; + } m_info.pchEndWrite = 0; m_info.pchEndRead = 0; @@ -95,8 +96,9 @@ MxLong MXIOINFO::Read(void* p_buf, MxLong p_len) while (p_len > 0) { if (bytesLeft > 0) { - if (p_len < bytesLeft) + if (p_len < bytesLeft) { bytesLeft = p_len; + } memcpy(p_buf, m_info.pchNext, bytesLeft); p_len -= bytesLeft; @@ -105,12 +107,14 @@ MxLong MXIOINFO::Read(void* p_buf, MxLong p_len) bytesRead += bytesLeft; } - if (p_len <= 0 || Advance(0)) + if (p_len <= 0 || Advance(0)) { break; + } bytesLeft = m_info.pchEndRead - m_info.pchNext; - if (bytesLeft <= 0) + if (bytesLeft <= 0) { break; + } } } else if (m_info.hmmio && p_len > 0) { @@ -334,6 +338,7 @@ MxU16 MXIOINFO::Advance(MxU16 p_option) m_info.pchNext = m_info.pchBuffer; m_info.pchEndRead = m_info.pchBuffer; m_info.dwFlags &= ~MMIO_DIRTY; + goto skipSeek; } else { result = MMIOERR_CANNOTWRITE; @@ -343,6 +348,7 @@ MxU16 MXIOINFO::Advance(MxU16 p_option) m_info.lDiskOffset = _llseek((HFILE) m_info.hmmio, 0, SEEK_CUR); } + skipSeek: m_info.lBufOffset += cch; if ((!rwmode || rwmode == MMIO_READWRITE) && cch > 0) { if (m_info.lBufOffset != m_info.lDiskOffset) { @@ -381,8 +387,9 @@ MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU { MxU16 result = 0; - if (!p_chunkInfo) + if (!p_chunkInfo) { return MMIOERR_BASE; // ? + } if (!p_descend) { p_chunkInfo->dwFlags = 0; @@ -406,8 +413,9 @@ MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU else { MxULong ofs = MAXLONG; - if (p_parentInfo) + if (p_parentInfo) { ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset; + } BOOL running = TRUE; BOOL readOk = FALSE; @@ -452,8 +460,9 @@ MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU } } - if (!result) + if (!result) { memcpy(p_chunkInfo, &tmp, sizeof(MMCKINFO)); + } } return result; diff --git a/LEGO1/omni/src/stream/mxramstreamprovider.cpp b/LEGO1/omni/src/stream/mxramstreamprovider.cpp index ca091d12..472930c7 100644 --- a/LEGO1/omni/src/stream/mxramstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxramstreamprovider.cpp @@ -71,8 +71,9 @@ MxResult MxRAMStreamProvider::SetResourceToGet(MxStreamController* p_resource) path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si"; m_pFile->SetFileName(path.GetData()); - if (m_pFile->Open(0) != 0) + if (m_pFile->Open(0) != 0) { goto done; + } } m_fileSize = m_pFile->CalcFileSize(); @@ -131,23 +132,27 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size) MxDSBuffer::Append(data2, data3); continue; } - else + else { *MxStreamChunk::IntoFlags(data2) &= ~MxDSChunk::c_split; + } } data2 += MxDSChunk::Size(*MxDSChunk::IntoLength(data2)); memcpy(data2, data3, MxDSChunk::Size(*psize)); if (*MxStreamChunk::IntoObjectId(data2) == id && - (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::c_end)) + (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::c_end)) { break; + } } - else + else { data++; + } } } - else + else { data++; + } } while (data < end); } diff --git a/LEGO1/omni/src/stream/mxstreamchunk.cpp b/LEGO1/omni/src/stream/mxstreamchunk.cpp index ba833186..9d30e70d 100644 --- a/LEGO1/omni/src/stream/mxstreamchunk.cpp +++ b/LEGO1/omni/src/stream/mxstreamchunk.cpp @@ -59,7 +59,7 @@ MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, m_buffer = NULL; } - (*it)->AddChunk(this, p_append); + (*it)->AddData(this, p_append); return SUCCESS; } diff --git a/LEGO1/omni/src/stream/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp index 204bdab8..977db130 100644 --- a/LEGO1/omni/src/stream/mxstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp @@ -45,12 +45,14 @@ MxStreamController::~MxStreamController() MxAutoLocker lock(&m_criticalSection); MxDSSubscriber* subscriber; - while (m_subscriberList.PopFront(subscriber)) + while (m_subscriberList.PopFront(subscriber)) { delete subscriber; + } MxDSAction* action; - while (m_unk0x3c.PopFront(action)) + while (m_unk0x3c.PopFront(action)) { delete action; + } if (m_provider) { MxStreamProvider* provider = m_provider; @@ -71,8 +73,9 @@ MxStreamController::~MxStreamController() m_unk0x2c = NULL; } - while (m_unk0x54.PopFront(action)) + while (m_unk0x54.PopFront(action)) { delete action; + } } // FUNCTION: LEGO1 0x100c1520 @@ -109,13 +112,16 @@ MxResult MxStreamController::VTable0x20(MxDSAction* p_action) MxS32 objectId = p_action->GetObjectId(); MxStreamProvider* provider = m_provider; - if ((MxS32) provider->GetLengthInDWords() > objectId) + if ((MxS32) provider->GetLengthInDWords() > objectId) { offset = provider->GetBufferForDWords()[objectId]; + } - if (offset) + if (offset) { result = VTable0x2c(p_action, offset); - else + } + else { result = FAILURE; + } return result; } @@ -159,16 +165,18 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) for (MxStreamListMxDSAction::iterator it = m_unk0x54.begin(); it != m_unk0x54.end(); it++) { MxDSAction* action = *it; - if (action->GetObjectId() == p_action->GetObjectId()) + if (action->GetObjectId() == p_action->GetObjectId()) { newUnknown24 = Max(newUnknown24, action->GetUnknown24()); + } } if (newUnknown24 == -1) { for (MxStreamListMxDSAction::iterator it = m_unk0x3c.begin(); it != m_unk0x3c.end(); it++) { MxDSAction* action = *it; - if (action->GetObjectId() == p_action->GetObjectId()) + if (action->GetObjectId() == p_action->GetObjectId()) { newUnknown24 = Max(newUnknown24, action->GetUnknown24()); + } } if (newUnknown24 == -1) { @@ -176,8 +184,9 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) it++) { MxDSSubscriber* subscriber = *it; - if (subscriber->GetObjectId() == p_action->GetObjectId()) + if (subscriber->GetObjectId() == p_action->GetObjectId()) { newUnknown24 = Max(newUnknown24, subscriber->GetUnknown48()); + } } } } @@ -185,14 +194,16 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) p_action->SetUnknown24(newUnknown24 + 1); } else { - if (m_unk0x3c.Find(p_action, FALSE)) + if (m_unk0x3c.Find(p_action, FALSE)) { return FAILURE; + } } MxDSStreamingAction* streamingAction = new MxDSStreamingAction(*p_action, p_offset); - if (!streamingAction) + if (!streamingAction) { return FAILURE; + } MxU32 fileSize = m_provider->GetFileSize(); streamingAction->SetBufferOffset(fileSize * (p_offset / fileSize)); @@ -268,14 +279,16 @@ MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) MxU32 objectId = p_action->GetObjectId(); MxStreamChunk* chunk = new MxStreamChunk; - if (!chunk) + if (!chunk) { return FAILURE; + } chunk->SetFlags(MxDSChunk::c_bit3); chunk->SetObjectId(objectId); - if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS) + if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS) { delete chunk; + } if (p_action->IsA("MxDSMultiAction")) { MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); @@ -283,8 +296,9 @@ MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) MxDSAction* action; while (cursor.Next(action)) { - if (FUN_100c1f00(action) != SUCCESS) + if (FUN_100c1f00(action) != SUCCESS) { return FAILURE; + } } } @@ -300,8 +314,9 @@ MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingA // FUNCTION: LEGO1 0x100c20d0 MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj) { - if (m_subscriberList.Find(&p_obj)) + if (m_subscriberList.Find(&p_obj)) { return FALSE; + } if (p_obj.IsA("MxDSMultiAction")) { MxDSActionList* actions = ((MxDSMultiAction&) p_obj).GetActionList(); @@ -309,8 +324,9 @@ MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj) MxDSAction* action; while (cursor.Next(action)) { - if (!FUN_100c20d0(*action)) + if (!FUN_100c20d0(*action)) { return FALSE; + } } } diff --git a/LEGO1/omni/src/stream/mxstreamer.cpp b/LEGO1/omni/src/stream/mxstreamer.cpp index d8d64fb5..76aa7862 100644 --- a/LEGO1/omni/src/stream/mxstreamer.cpp +++ b/LEGO1/omni/src/stream/mxstreamer.cpp @@ -79,8 +79,9 @@ MxLong MxStreamer::Close(const char* p_name) if (!p_name || !strcmp(p_name, c->GetAtom().GetInternal())) { m_openStreams.erase(it); - if (c->FUN_100c20d0(ds)) + if (c->FUN_100c20d0(ds)) { delete c; + } else { #ifdef COMPAT_MODE { @@ -185,8 +186,9 @@ MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject) { MxStreamController* controller = GetOpenStream(p_dsObject.GetAtomId().GetInternal()); - if (controller) + if (controller) { return controller->FUN_100c20d0(p_dsObject); + } return TRUE; } @@ -200,8 +202,9 @@ MxLong MxStreamer::Notify(MxParam& p_param) MxStreamController* c = static_cast(p_param).GetController(); - if (c->FUN_100c20d0(ds)) + if (c->FUN_100c20d0(ds)) { delete c; + } else { #ifdef COMPAT_MODE { diff --git a/LEGO1/omni/src/stream/mxstreamlist.cpp b/LEGO1/omni/src/stream/mxstreamlist.cpp index 46e9841b..effa987a 100644 --- a/LEGO1/omni/src/stream/mxstreamlist.cpp +++ b/LEGO1/omni/src/stream/mxstreamlist.cpp @@ -1,9 +1,9 @@ #include "mxstreamlist.h" // Wrappers around STL list that are used by the MxStream* classes. -DECOMP_SIZE_ASSERT(MxStreamListMxDSAction, 0xc); -DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0xc); -DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0xc); +DECOMP_SIZE_ASSERT(MxStreamListMxDSAction, 0x0c); +DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0x0c); +DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0x0c); // FUNCTION: LEGO1 0x100b8450 MxDSSubscriber* MxStreamListMxDSSubscriber::Find(MxDSObject* p_object) @@ -36,8 +36,9 @@ MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) if (p_action->GetUnknown24() == -2 || p_action->GetUnknown24() == -3 || p_action->GetUnknown24() == (*it)->GetUnknown24()) { found = *it; - if (p_action->GetUnknown24() != -3) + if (p_action->GetUnknown24() != -3) { break; + } } } } @@ -53,8 +54,9 @@ MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) MxNextActionDataStart* MxStreamListMxNextActionDataStart::Find(MxU32 p_id, MxS16 p_value) { for (iterator it = begin(); it != end(); it++) { - if (p_id == (*it)->GetObjectId() && p_value == (*it)->GetUnknown24()) + if (p_id == (*it)->GetObjectId() && p_value == (*it)->GetUnknown24()) { return *it; + } } return NULL; diff --git a/LEGO1/omni/src/system/mxautolocker.cpp b/LEGO1/omni/src/system/mxautolocker.cpp index d5749ad5..3c5a2afb 100644 --- a/LEGO1/omni/src/system/mxautolocker.cpp +++ b/LEGO1/omni/src/system/mxautolocker.cpp @@ -4,13 +4,15 @@ MxAutoLocker::MxAutoLocker(MxCriticalSection* p_criticalSection) { this->m_criticalSection = p_criticalSection; - if (this->m_criticalSection != 0) + if (this->m_criticalSection != 0) { this->m_criticalSection->Enter(); + } } // FUNCTION: LEGO1 0x100b8ef0 MxAutoLocker::~MxAutoLocker() { - if (this->m_criticalSection != 0) + if (this->m_criticalSection != 0) { this->m_criticalSection->Leave(); + } } diff --git a/LEGO1/omni/src/system/mxsemaphore.cpp b/LEGO1/omni/src/system/mxsemaphore.cpp index 5692a888..daba60f4 100644 --- a/LEGO1/omni/src/system/mxsemaphore.cpp +++ b/LEGO1/omni/src/system/mxsemaphore.cpp @@ -15,8 +15,9 @@ MxSemaphore::MxSemaphore() MxResult MxSemaphore::Init(MxU32 p_initialCount, MxU32 p_maxCount) { MxResult result = FAILURE; - if (m_hSemaphore = CreateSemaphoreA(NULL, p_initialCount, p_maxCount, NULL)) + if ((m_hSemaphore = CreateSemaphoreA(NULL, p_initialCount, p_maxCount, NULL))) { result = SUCCESS; + } return result; } diff --git a/LEGO1/omni/src/system/mxthread.cpp b/LEGO1/omni/src/system/mxthread.cpp index 401860a1..14c4ea82 100644 --- a/LEGO1/omni/src/system/mxthread.cpp +++ b/LEGO1/omni/src/system/mxthread.cpp @@ -1,4 +1,3 @@ - #include "mxthread.h" #include "decomp.h" @@ -52,8 +51,9 @@ MxThread::MxThread() // FUNCTION: LEGO1 0x100bf5a0 MxThread::~MxThread() { - if (m_hThread) + if (m_hThread) { CloseHandle((HANDLE) m_hThread); + } } typedef unsigned(__stdcall* ThreadFunc)(void*); @@ -63,9 +63,10 @@ MxResult MxThread::Start(MxS32 p_stack, MxS32 p_flag) { MxResult result = FAILURE; if (m_semaphore.Init(0, 1) == SUCCESS) { - if (m_hThread = - _beginthreadex(NULL, p_stack << 2, (ThreadFunc) &MxThread::ThreadProc, this, p_flag, &m_threadId)) + if ((m_hThread = + _beginthreadex(NULL, p_stack << 2, (ThreadFunc) &MxThread::ThreadProc, this, p_flag, &m_threadId))) { result = SUCCESS; + } } return result; } diff --git a/LEGO1/omni/src/video/mxbitmap.cpp b/LEGO1/omni/src/video/mxbitmap.cpp index 0d83bba2..98f1f6b2 100644 --- a/LEGO1/omni/src/video/mxbitmap.cpp +++ b/LEGO1/omni/src/video/mxbitmap.cpp @@ -25,12 +25,15 @@ MxBitmap::MxBitmap() // FUNCTION: LEGO1 0x100bca10 MxBitmap::~MxBitmap() { - if (this->m_info) + if (this->m_info) { delete m_info; - if (this->m_data) + } + if (this->m_data) { delete m_data; - if (this->m_palette) + } + if (this->m_palette) { delete m_palette; + } } // FUNCTION: LEGO1 0x100bcaa0 @@ -152,11 +155,13 @@ MxLong MxBitmap::Read(const char* p_filename) HANDLE handle = CreateFileA(p_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (handle != INVALID_HANDLE_VALUE && !LoadFile(handle)) + if (handle != INVALID_HANDLE_VALUE && !LoadFile(handle)) { result = SUCCESS; + } - if (handle) + if (handle) { CloseHandle(handle); + } return result; } @@ -280,8 +285,9 @@ void MxBitmap::BitBltTransparent( for (MxS32 h = 0; h < p_height; h++) { for (MxS32 w = 0; w < p_width; w++) { - if (*srcStart) + if (*srcStart) { *dstStart = *srcStart; + } srcStart++; dstStart++; } @@ -302,15 +308,17 @@ MxPalette* MxBitmap::CreatePalette() case FALSE: palette = new MxPalette(this->m_paletteData); - if (!palette) + if (!palette) { goto done; + } break; case TRUE: palette = this->m_palette->Clone(); - if (!palette) + if (!palette) { goto done; + } break; default: @@ -361,8 +369,9 @@ MxResult MxBitmap::SetBitDepth(MxBool p_isHighColor) switch (p_isHighColor) { case FALSE: ImportColorsToPalette(m_paletteData, m_palette); - if (m_palette) + if (m_palette) { delete m_palette; + } m_palette = NULL; break; @@ -370,8 +379,9 @@ MxResult MxBitmap::SetBitDepth(MxBool p_isHighColor) pal = NULL; pal = new MxPalette(m_paletteData); - if (!pal) + if (!pal) { goto done; + } m_palette = pal; @@ -392,8 +402,9 @@ MxResult MxBitmap::SetBitDepth(MxBool p_isHighColor) done: // If we were unsuccessful overall but did manage to alloc // the MxPalette, free it. - if (ret && pal) + if (ret && pal) { delete pal; + } return ret; } @@ -438,13 +449,15 @@ MxResult MxBitmap::ImportColorsToPalette(RGBQUAD* p_rgbquad, MxPalette* p_palett PALETTEENTRY entries[256]; if (p_palette) { - if (p_palette->GetEntries(entries)) + if (p_palette->GetEntries(entries)) { goto done; + } } else { MxPalette palette; - if (palette.GetEntries(entries)) + if (palette.GetEntries(entries)) { goto done; + } } MxS32 i; diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index a9dc2608..0cb88f6d 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -81,8 +81,9 @@ MxU8 MxDisplaySurface::CountTotalBitsSetTo1(MxU32 p_param) { MxU8 count = 0; - for (; p_param; p_param >>= 1) + for (; p_param; p_param >>= 1) { count += ((MxU8) p_param & 1); + } return count; } @@ -92,8 +93,9 @@ MxU8 MxDisplaySurface::CountContiguousBitsSetTo1(MxU32 p_param) { MxU8 count = 0; - for (; (p_param & 1) == 0; p_param >>= 1) + for (; (p_param & 1) == 0; p_param >>= 1) { count++; + } return count; } @@ -117,8 +119,9 @@ MxResult MxDisplaySurface::Init( memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc); - if (this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) + if (this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) { result = FAILURE; + } return result; } @@ -134,8 +137,9 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) this->m_initialized = TRUE; this->m_videoParam = p_videoParam; - if (!this->m_videoParam.Flags().GetFullScreen()) + if (!this->m_videoParam.Flags().GetFullScreen()) { this->m_videoParam.Flags().SetFlipSurfaces(FALSE); + } if (!this->m_videoParam.Flags().GetFlipSurfaces()) { this->m_videoParam.SetBackBuffers(1); @@ -143,10 +147,12 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) else { MxU32 backBuffers = this->m_videoParam.GetBackBuffers(); - if (backBuffers < 1) + if (backBuffers < 1) { this->m_videoParam.SetBackBuffers(1); - else if (backBuffers > 2) + } + else if (backBuffers > 2) { this->m_videoParam.SetBackBuffers(2); + } this->m_videoParam.Flags().SetBackBuffers(TRUE); } @@ -155,20 +161,23 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) MxS32 width = this->m_videoParam.GetRect().GetWidth(); MxS32 height = this->m_videoParam.GetRect().GetHeight(); - if (lpDirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)) + if (lpDirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)) { goto done; + } memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - if (lpDirectDraw->GetDisplayMode(&ddsd)) + if (lpDirectDraw->GetDisplayMode(&ddsd)) { goto done; + } MxS32 bitdepth = !this->m_videoParam.Flags().Get16Bit() ? 8 : 16; if (ddsd.dwWidth != width || ddsd.dwHeight != height || ddsd.ddpfPixelFormat.dwRGBBitCount != bitdepth) { - if (lpDirectDraw->SetDisplayMode(width, height, bitdepth)) + if (lpDirectDraw->SetDisplayMode(width, height, bitdepth)) { goto done; + } } } @@ -179,13 +188,15 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; - if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) { goto done; + } ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; - if (this->m_ddSurface1->GetAttachedSurface(&ddsd.ddsCaps, &this->m_ddSurface2)) + if (this->m_ddSurface1->GetAttachedSurface(&ddsd.ddsCaps, &this->m_ddSurface2)) { goto done; + } } else { memset(&ddsd, 0, sizeof(ddsd)); @@ -193,8 +204,9 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) { goto done; + } memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); @@ -203,11 +215,13 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) ddsd.dwHeight = this->m_videoParam.GetRect().GetHeight(); ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN; - if (!this->m_videoParam.Flags().GetBackBuffers()) + if (!this->m_videoParam.Flags().GetBackBuffers()) { ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + } - if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface2, NULL)) + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface2, NULL)) { goto done; + } } memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); @@ -215,8 +229,9 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) if (!this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) { if (!lpDirectDraw->CreateClipper(0, &this->m_ddClipper, NULL) && !this->m_ddClipper->SetHWnd(0, hWnd) && - !this->m_ddSurface1->SetClipper(this->m_ddClipper)) + !this->m_ddSurface1->SetClipper(this->m_ddClipper)) { result = SUCCESS; + } } done: @@ -227,18 +242,22 @@ MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) void MxDisplaySurface::Destroy() { if (this->m_initialized) { - if (this->m_ddSurface2) + if (this->m_ddSurface2) { this->m_ddSurface2->Release(); + } - if (this->m_ddSurface1) + if (this->m_ddSurface1) { this->m_ddSurface1->Release(); + } - if (this->m_ddClipper) + if (this->m_ddClipper) { this->m_ddClipper->Release(); + } } - if (this->m_16bitPal) - delete this->m_16bitPal; + if (this->m_16bitPal) { + delete[] this->m_16bitPal; + } this->Init(); } @@ -273,8 +292,9 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette) } if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount == 16) { - if (!m_16bitPal) + if (!m_16bitPal) { m_16bitPal = new MxU16[256]; + } PALETTEENTRY palette[256]; p_palette->GetEntries(palette); @@ -287,9 +307,9 @@ void MxDisplaySurface::SetPalette(MxPalette* p_palette) MxU8 totalBitsBlue = CountTotalBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwBBitMask); for (MxS32 i = 0; i < 256; i++) { - m_16bitPal[i] = (((palette[i].peRed >> (8 - totalBitsRed & 0x1f)) << (contiguousBitsRed & 0x1f))) | - (((palette[i].peGreen >> (8 - totalBitsGreen & 0x1f)) << (contiguousBitsGreen & 0x1f))) | - (((palette[i].peBlue >> (8 - totalBitsBlue & 0x1f)) << (contiguousBitsBlue & 0x1f))); + m_16bitPal[i] = (((palette[i].peRed >> ((8 - totalBitsRed) & 0x1f)) << (contiguousBitsRed & 0x1f))) | + (((palette[i].peGreen >> ((8 - totalBitsGreen) & 0x1f)) << (contiguousBitsGreen & 0x1f))) | + (((palette[i].peBlue >> ((8 - totalBitsBlue) & 0x1f)) << (contiguousBitsBlue & 0x1f))); } } } @@ -528,8 +548,9 @@ void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p // FUNCTION: LEGO1 0x100bbc10 void MxDisplaySurface::GetDC(HDC* p_hdc) { - if (this->m_ddSurface2 && !this->m_ddSurface2->GetDC(p_hdc)) + if (this->m_ddSurface2 && !this->m_ddSurface2->GetDC(p_hdc)) { return; + } *p_hdc = NULL; } @@ -537,8 +558,9 @@ void MxDisplaySurface::GetDC(HDC* p_hdc) // FUNCTION: LEGO1 0x100bbc40 void MxDisplaySurface::ReleaseDC(HDC p_hdc) { - if (this->m_ddSurface2 && p_hdc) + if (this->m_ddSurface2 && p_hdc) { this->m_ddSurface2->ReleaseDC(p_hdc); + } } // FUNCTION: LEGO1 0x100bbc60 @@ -557,8 +579,9 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - if (draw->GetDisplayMode(&ddsd)) + if (draw->GetDisplayMode(&ddsd)) { return NULL; + } ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.dwWidth = p_bitmap->GetBmiWidth(); @@ -567,7 +590,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( *p_ret = 0; ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; - if (draw->CreateSurface(&ddsd, &surface, NULL) != S_OK) { + if (draw->CreateSurface(&ddsd, &surface, NULL) != DD_OK) { if (*p_ret) { *p_ret = 0; @@ -575,19 +598,20 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - if (draw->CreateSurface(&ddsd, &surface, NULL) != S_OK) { + if (draw->CreateSurface(&ddsd, &surface, NULL) != DD_OK) { surface = NULL; } } - else + else { surface = NULL; + } } if (surface) { memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT, 0) != S_OK) { + if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT, 0) != DD_OK) { surface->Release(); surface = NULL; goto done; @@ -604,8 +628,9 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( // TODO: Probably p_bitmap->GetAdjustedStride() MxS32 rowSeek = p_bitmap->GetBmiStride(); - if (p_bitmap->GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap->GetBmiHeight() >= 0) + if (p_bitmap->GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap->GetBmiHeight() >= 0) { rowSeek = -rowSeek; + } MxLong newPitch = ddsd.lPitch; switch (ddsd.ddpfPixelFormat.dwRGBBitCount) { @@ -679,6 +704,13 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( return surface; } +// STUB: LEGO1 0x100bbfb0 +LPDIRECTDRAWSURFACE MxDisplaySurface::FUN_100bbfb0(LPDIRECTDRAWSURFACE p_und) +{ + // TODO + return NULL; +} + // FUNCTION: LEGO1 0x100bc070 LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface() { @@ -690,7 +722,7 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface() memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - if (draw->GetDisplayMode(&ddsd) != S_OK) { + if (draw->GetDisplayMode(&ddsd) != DD_OK) { return NULL; } @@ -703,19 +735,21 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface() ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN; - if (draw->CreateSurface(&ddsd, &newSurface, NULL) != S_OK) { + if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) { ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; - if (draw->CreateSurface(&ddsd, &newSurface, NULL) != S_OK) + if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) { goto done; + } } memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != S_OK) + if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK) { goto done; + } else { MxU16* surface = (MxU16*) ddsd.lpSurface; MxLong pitch = ddsd.lPitch; @@ -725,10 +759,12 @@ LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface() MxU16* surface2 = surface; for (MxS32 y = 0; y < 16; y++) { if ((y > 10 || x) && (x > 10 || y) && x + y != 10) { - if (x + y > 10) + if (x + y > 10) { *surface2 = 31775; - else + } + else { *surface2 = -1; + } } else { *surface2 = 0; diff --git a/LEGO1/omni/src/video/mxflcpresenter.cpp b/LEGO1/omni/src/video/mxflcpresenter.cpp index 2e04885d..da7441a8 100644 --- a/LEGO1/omni/src/video/mxflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxflcpresenter.cpp @@ -12,9 +12,9 @@ DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); // FUNCTION: LEGO1 0x100b3310 MxFlcPresenter::MxFlcPresenter() { - this->m_flcHeader = NULL; - this->m_flags &= ~c_bit2; - this->m_flags &= ~c_bit3; + m_flcHeader = NULL; + SetBit1(FALSE); + SetBit2(FALSE); } // FUNCTION: LEGO1 0x100b3420 @@ -35,8 +35,9 @@ void MxFlcPresenter::LoadHeader(MxStreamChunk* p_chunk) // FUNCTION: LEGO1 0x100b34d0 void MxFlcPresenter::CreateBitmap() { - if (m_bitmap) + if (m_bitmap) { delete m_bitmap; + } m_bitmap = new MxBitmap; m_bitmap->SetSize(m_flcHeader->width, m_flcHeader->height, NULL, FALSE); @@ -62,8 +63,9 @@ void MxFlcPresenter::LoadFrame(MxStreamChunk* p_chunk) &decodedColorMap ); - if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && decodedColorMap) + if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && decodedColorMap) { RealizePalette(); + } for (MxS32 i = 0; i < rectCount; i++) { MxRect32 rect(rects[i]); diff --git a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp index 59540cb3..257e5a81 100644 --- a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp @@ -20,8 +20,8 @@ MxLoopingFlcPresenter::~MxLoopingFlcPresenter() void MxLoopingFlcPresenter::Init() { this->m_elapsedDuration = 0; - this->m_flags &= ~c_bit2; - this->m_flags &= ~c_bit3; + SetBit1(FALSE); + SetBit2(FALSE); } // FUNCTION: LEGO1 0x100b4430 @@ -31,8 +31,9 @@ void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor) Init(); m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxFlcPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b4470 @@ -40,22 +41,24 @@ void MxLoopingFlcPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::c_end) + if (chunk->GetFlags() & MxDSChunk::c_end) { ProgressTickleState(e_repeating); + } else { LoadFrame(chunk); LoopChunk(chunk); m_elapsedDuration += m_flcHeader->speed; } - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); } // FUNCTION: LEGO1 0x100b44c0 void MxLoopingFlcPresenter::VTable0x88() { - if (m_action->GetDuration() < m_elapsedDuration) + if (m_action->GetDuration() < m_elapsedDuration) { ProgressTickleState(e_unk5); + } else { MxStreamChunk* chunk; m_loopingChunkCursor->Current(chunk); @@ -81,8 +84,9 @@ void MxLoopingFlcPresenter::RepeatingTickle() time += m_flcHeader->speed; cursor.Reset(); - while (cursor.Next(chunk)) + while (cursor.Next(chunk)) { chunk->SetTime(chunk->GetTime() + time); + } m_loopingChunkCursor->Next(); } @@ -90,15 +94,17 @@ void MxLoopingFlcPresenter::RepeatingTickle() MxStreamChunk* chunk; m_loopingChunkCursor->Current(chunk); - if (m_action->GetElapsedTime() < chunk->GetTime()) + if (m_action->GetElapsedTime() < chunk->GetTime()) { break; + } VTable0x88(); m_loopingChunkCursor->Next(chunk); - if (m_currentTickleState != e_repeating) + if (m_currentTickleState != e_repeating) { break; + } } } @@ -114,8 +120,9 @@ MxResult MxLoopingFlcPresenter::AddToManager() result = SUCCESS; } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return result; } diff --git a/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp index 51ed74c8..9229afee 100644 --- a/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp @@ -20,9 +20,9 @@ MxLoopingSmkPresenter::~MxLoopingSmkPresenter() // FUNCTION: LEGO1 0x100b49b0 void MxLoopingSmkPresenter::Init() { - this->m_elapsedDuration = 0; - this->m_flags &= ~c_bit2; - this->m_flags &= ~c_bit3; + m_elapsedDuration = 0; + SetBit1(FALSE); + SetBit2(FALSE); } // FUNCTION: LEGO1 0x100b49d0 @@ -32,8 +32,9 @@ void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor) Init(); m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxSmkPresenter::Destroy(); + } } // FUNCTION: LEGO1 0x100b4a00 @@ -51,22 +52,24 @@ void MxLoopingSmkPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::c_end) + if (chunk->GetFlags() & MxDSChunk::c_end) { ProgressTickleState(e_repeating); + } else { LoadFrame(chunk); LoopChunk(chunk); m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); } - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); } // FUNCTION: LEGO1 0x100b4a90 void MxLoopingSmkPresenter::VTable0x8c() { - if (m_action->GetDuration() < m_elapsedDuration) + if (m_action->GetDuration() < m_elapsedDuration) { ProgressTickleState(e_unk5); + } else { MxStreamChunk* chunk; m_loopingChunkCursor->Current(chunk); @@ -92,8 +95,9 @@ void MxLoopingSmkPresenter::RepeatingTickle() time += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); cursor.Reset(); - while (cursor.Next(chunk)) + while (cursor.Next(chunk)) { chunk->SetTime(chunk->GetTime() + time); + } m_loopingChunkCursor->Next(); } @@ -101,15 +105,17 @@ void MxLoopingSmkPresenter::RepeatingTickle() MxStreamChunk* chunk; m_loopingChunkCursor->Current(chunk); - if (m_action->GetElapsedTime() < chunk->GetTime()) + if (m_action->GetElapsedTime() < chunk->GetTime()) { break; + } VTable0x8c(); m_loopingChunkCursor->Next(chunk); - if (m_currentTickleState != e_repeating) + if (m_currentTickleState != e_repeating) { break; + } } } diff --git a/LEGO1/omni/src/video/mxpalette.cpp b/LEGO1/omni/src/video/mxpalette.cpp index 8431fb76..6a677b90 100644 --- a/LEGO1/omni/src/video/mxpalette.cpp +++ b/LEGO1/omni/src/video/mxpalette.cpp @@ -110,21 +110,26 @@ LPDIRECTDRAWPALETTE MxPalette::CreateNativePalette() { MxS32 i; if (this->m_palette == NULL) { - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { this->m_entries[i].peFlags = 0x80; - for (i = 10; i < 136; i++) + } + for (i = 10; i < 136; i++) { this->m_entries[i].peFlags = 0x44; - for (i = 136; i < 140; i++) + } + for (i = 136; i < 140; i++) { this->m_entries[i].peFlags = 0x84; + } this->m_entries[140].peFlags = 0x84; this->m_entries[141].peFlags = 0x44; - for (i = 142; i < 246; i++) + for (i = 142; i < 246; i++) { this->m_entries[i].peFlags = 0x84; - for (i = 246; i < 256; i++) + } + for (i = 246; i < 256; i++) { this->m_entries[i].peFlags = 0x80; + } if (MVideoManager() && MVideoManager()->GetDirectDraw()) { - MVideoManager()->GetDirectDraw()->CreatePalette(4, this->m_entries, &this->m_palette, NULL); + MVideoManager()->GetDirectDraw()->CreatePalette(DDPCAPS_8BIT, this->m_entries, &this->m_palette, NULL); } } @@ -154,8 +159,9 @@ MxResult MxPalette::SetEntries(LPPALETTEENTRY p_entries) MxResult status = SUCCESS; if (this->m_palette) { - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { this->m_entries[i].peFlags = 0x80; + } for (i = 10; i < 136; i++) { this->m_entries[i].peFlags = 68; this->m_entries[i].peRed = p_entries[i].peRed; @@ -186,11 +192,13 @@ MxResult MxPalette::SetEntries(LPPALETTEENTRY p_entries) this->m_entries[i].peBlue = p_entries[i].peBlue; } - for (i = 246; i < 256; i++) + for (i = 246; i < 256; i++) { this->m_entries[i].peFlags = 0x80; + } - if (this->m_palette->SetEntries(0, 0, 256, this->m_entries)) + if (this->m_palette->SetEntries(0, 0, 256, this->m_entries)) { status = FAILURE; + } } return status; @@ -222,12 +230,15 @@ void MxPalette::Detach() MxBool MxPalette::operator==(MxPalette& p_other) { for (MxS32 i = 0; i < 256; i++) { - if (this->m_entries[i].peRed != p_other.m_entries[i].peRed) + if (this->m_entries[i].peRed != p_other.m_entries[i].peRed) { return FALSE; - if (this->m_entries[i].peGreen != p_other.m_entries[i].peGreen) + } + if (this->m_entries[i].peGreen != p_other.m_entries[i].peGreen) { return FALSE; - if (this->m_entries[i].peBlue != p_other.m_entries[i].peBlue) + } + if (this->m_entries[i].peBlue != p_other.m_entries[i].peBlue) { return FALSE; + } } return TRUE; } diff --git a/LEGO1/omni/src/video/mxregion.cpp b/LEGO1/omni/src/video/mxregion.cpp index ea7fab55..ca3698e9 100644 --- a/LEGO1/omni/src/video/mxregion.cpp +++ b/LEGO1/omni/src/video/mxregion.cpp @@ -22,8 +22,9 @@ MxBool MxRegion::VTable0x20() // FUNCTION: LEGO1 0x100c3690 MxRegion::~MxRegion() { - if (m_list) + if (m_list) { delete m_list; + } } // FUNCTION: LEGO1 0x100c3700 @@ -88,17 +89,20 @@ void MxRegion::VTable0x18(MxRect32& p_rect) // FUNCTION: LEGO1 0x100c3e20 MxBool MxRegion::VTable0x1c(MxRect32& p_rect) { - if (!m_rect.IntersectsWith(p_rect)) + if (!m_rect.IntersectsWith(p_rect)) { return FALSE; + } MxRegionTopBottomListCursor cursor(m_list); MxRegionTopBottom* topBottom; while (cursor.Next(topBottom)) { - if (topBottom->GetTop() >= p_rect.GetBottom()) + if (topBottom->GetTop() >= p_rect.GetBottom()) { return FALSE; - if (topBottom->GetBottom() > p_rect.GetTop() && topBottom->FUN_100c57b0(p_rect)) + } + if (topBottom->GetBottom() > p_rect.GetTop() && topBottom->FUN_100c57b0(p_rect)) { return TRUE; + } } return FALSE; @@ -130,27 +134,31 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right) MxRegionLeftRightListCursor b(m_leftRightList); MxRegionLeftRight* leftRight; - while (a.Next(leftRight) && leftRight->GetRight() < p_left) + while (a.Next(leftRight) && leftRight->GetRight() < p_left) { ; + } if (!a.HasMatch()) { MxRegionLeftRight* copy = new MxRegionLeftRight(p_left, p_right); m_leftRightList->Append(copy); } else { - if (p_left > leftRight->GetLeft()) + if (p_left > leftRight->GetLeft()) { p_left = leftRight->GetLeft(); + } while (leftRight->GetLeft() < p_right) { - if (p_right < leftRight->GetRight()) + if (p_right < leftRight->GetRight()) { p_right = leftRight->GetRight(); + } b = a; b.Next(); a.Destroy(); - if (!b.Current(leftRight)) + if (!b.Current(leftRight)) { break; + } a = b; } @@ -174,8 +182,9 @@ MxRegionTopBottom* MxRegionTopBottom::Clone() MxRegionLeftRightListCursor cursor(m_leftRightList); MxRegionLeftRight* leftRight; - while (cursor.Next(leftRight)) + while (cursor.Next(leftRight)) { clone->m_leftRightList->Append(leftRight->Clone()); + } return clone; } @@ -187,10 +196,12 @@ MxBool MxRegionTopBottom::FUN_100c57b0(MxRect32& p_rect) MxRegionLeftRight* leftRight; while (cursor.Next(leftRight)) { - if (p_rect.GetRight() <= leftRight->GetLeft()) + if (p_rect.GetRight() <= leftRight->GetLeft()) { return FALSE; - if (leftRight->GetRight() > p_rect.GetLeft()) + } + if (leftRight->GetRight() > p_rect.GetLeft()) { return TRUE; + } } return FALSE; diff --git a/LEGO1/omni/src/video/mxregioncursor.cpp b/LEGO1/omni/src/video/mxregioncursor.cpp index 89c90403..6b74ee3f 100644 --- a/LEGO1/omni/src/video/mxregioncursor.cpp +++ b/LEGO1/omni/src/video/mxregioncursor.cpp @@ -14,14 +14,17 @@ MxRegionCursor::MxRegionCursor(MxRegion* p_region) // FUNCTION: LEGO1 0x100c40b0 MxRegionCursor::~MxRegionCursor() { - if (m_rect) + if (m_rect) { delete m_rect; + } - if (m_topBottomCursor) + if (m_topBottomCursor) { delete m_topBottomCursor; + } - if (m_leftRightCursor) + if (m_leftRightCursor) { delete m_leftRightCursor; + } } // FUNCTION: LEGO1 0x100c4140 @@ -38,8 +41,9 @@ MxRect32* MxRegionCursor::VTable0x18() UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); } - else + else { Reset(); + } return m_rect; } @@ -58,8 +62,9 @@ MxRect32* MxRegionCursor::VTable0x20() UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); } - else + else { Reset(); + } return m_rect; } @@ -144,11 +149,13 @@ MxRect32* MxRegionCursor::VTable0x24(MxRect32& p_rect) UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); m_rect->Intersect(p_rect); } - else + else { FUN_100c4a20(p_rect); + } } - else + else { FUN_100c4a20(p_rect); + } return m_rect; } @@ -167,11 +174,13 @@ MxRect32* MxRegionCursor::VTable0x2c(MxRect32& p_rect) UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); m_rect->Intersect(p_rect); } - else + else { FUN_100c4b50(p_rect); + } } - else + else { FUN_100c4b50(p_rect); + } return m_rect; } @@ -195,8 +204,9 @@ void MxRegionCursor::Reset() // FUNCTION: LEGO1 0x100c46c0 void MxRegionCursor::FUN_100c46c0(MxRegionLeftRightList& p_leftRightList) { - if (m_leftRightCursor) + if (m_leftRightCursor) { delete m_leftRightCursor; + } m_leftRightCursor = new MxRegionLeftRightListCursor(&p_leftRightList); } @@ -204,8 +214,9 @@ void MxRegionCursor::FUN_100c46c0(MxRegionLeftRightList& p_leftRightList) // FUNCTION: LEGO1 0x100c4980 void MxRegionCursor::UpdateRect(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) { - if (!m_rect) + if (!m_rect) { m_rect = new MxRect32; + } m_rect->SetLeft(p_left); m_rect->SetTop(p_top); @@ -228,8 +239,9 @@ void MxRegionCursor::FUN_100c4a20(MxRect32& p_rect) MxRegionLeftRight* leftRight; while (m_leftRightCursor->Next(leftRight)) { - if (p_rect.GetRight() <= leftRight->GetLeft()) + if (p_rect.GetRight() <= leftRight->GetLeft()) { break; + } if (p_rect.GetLeft() < leftRight->GetRight()) { UpdateRect( @@ -263,8 +275,9 @@ void MxRegionCursor::FUN_100c4b50(MxRect32& p_rect) MxRegionLeftRight* leftRight; while (m_leftRightCursor->Prev(leftRight)) { - if (leftRight->GetRight() <= p_rect.GetLeft()) + if (leftRight->GetRight() <= p_rect.GetLeft()) { break; + } if (leftRight->GetLeft() < p_rect.GetRight()) { UpdateRect( diff --git a/LEGO1/omni/src/video/mxsmack.cpp b/LEGO1/omni/src/video/mxsmack.cpp index 551b87c9..8d1835fe 100644 --- a/LEGO1/omni/src/video/mxsmack.cpp +++ b/LEGO1/omni/src/video/mxsmack.cpp @@ -40,8 +40,9 @@ MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack) // TODO for (MxU32 i = 0; i < FRAME_COUNT(p_mxSmack); i++) { - if (p_mxSmack->m_maxFrameSize < frameSizes[i]) + if (p_mxSmack->m_maxFrameSize < frameSizes[i]) { p_mxSmack->m_maxFrameSize = frameSizes[i]; + } } frameTypes = new MxU8[FRAME_COUNT(p_mxSmack)]; @@ -54,8 +55,9 @@ MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack) p_data += FRAME_COUNT(p_mxSmack); MxU32 treeSize = p_mxSmack->m_smackTag.tablesize + 0x1000; - if (treeSize <= 0x2000) + if (treeSize <= 0x2000) { treeSize = 0x2000; + } huffmanTrees = new MxU8[treeSize]; @@ -127,16 +129,21 @@ MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack) // FUNCTION: LEGO1 0x100c5d40 void MxSmack::Destroy(MxSmack* p_mxSmack) { - if (p_mxSmack->m_frameSizes) + if (p_mxSmack->m_frameSizes) { delete[] p_mxSmack->m_frameSizes; - if (p_mxSmack->m_frameTypes) + } + if (p_mxSmack->m_frameTypes) { delete[] p_mxSmack->m_frameTypes; - if (p_mxSmack->m_huffmanTrees) + } + if (p_mxSmack->m_huffmanTrees) { delete[] p_mxSmack->m_huffmanTrees; - if (p_mxSmack->m_huffmanTables) + } + if (p_mxSmack->m_huffmanTables) { delete[] p_mxSmack->m_huffmanTables; - if (p_mxSmack->m_unk0x6b4) + } + if (p_mxSmack->m_unk0x6b4) { delete[] p_mxSmack->m_unk0x6b4; + } } // This should be refactored to somewhere else @@ -223,12 +230,14 @@ MxBool MxSmack::GetRect(MxU8* p_unk0x6b4, MxU16* p_und, u32* p_smackRect, MxRect { u32 left, bottom, top, right; - if (!*p_und) + if (!*p_und) { return FALSE; + } if (*p_und == 1) { - if (!SmackGetRect(p_unk0x6b4, p_smackRect)) + if (!SmackGetRect(p_unk0x6b4, p_smackRect)) { return FALSE; + } *p_und = 2; } @@ -238,10 +247,12 @@ MxBool MxSmack::GetRect(MxU8* p_unk0x6b4, MxU16* p_und, u32* p_smackRect, MxRect bottom = p_smackRect[3] + p_smackRect[1]; while (SmackGetRect(p_unk0x6b4, p_smackRect)) { - if (left > p_smackRect[0]) + if (left > p_smackRect[0]) { left = p_smackRect[0]; - if (right < p_smackRect[0] + p_smackRect[2]) + } + if (right < p_smackRect[0] + p_smackRect[2]) { right = p_smackRect[0] + p_smackRect[2]; + } bottom = p_smackRect[1] + p_smackRect[3]; } diff --git a/LEGO1/omni/src/video/mxsmkpresenter.cpp b/LEGO1/omni/src/video/mxsmkpresenter.cpp index b8001623..8bb2ed6f 100644 --- a/LEGO1/omni/src/video/mxsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxsmkpresenter.cpp @@ -23,8 +23,8 @@ void MxSmkPresenter::Init() { m_currentFrame = 0; memset(&m_mxSmack, 0, sizeof(m_mxSmack)); - m_flags &= ~c_bit2; - m_flags &= ~c_bit3; + SetBit1(FALSE); + SetBit2(FALSE); } // FUNCTION: LEGO1 0x100b3900 @@ -51,8 +51,9 @@ void MxSmkPresenter::LoadHeader(MxStreamChunk* p_chunk) // FUNCTION: LEGO1 0x100b3960 void MxSmkPresenter::CreateBitmap() { - if (m_bitmap) + if (m_bitmap) { delete m_bitmap; + } m_bitmap = new MxBitmap; m_bitmap->SetSize(m_mxSmack.m_smackTag.Width, m_mxSmack.m_smackTag.Height, NULL, FALSE); @@ -72,8 +73,9 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk) MxRectList list(TRUE); MxSmack::LoadFrame(bitmapInfo, bitmapData, &m_mxSmack, chunkData, paletteChanged, &list); - if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && paletteChanged) + if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && paletteChanged) { RealizePalette(); + } MxRect32 invalidateRect; MxRectListCursor cursor(&list); @@ -91,8 +93,9 @@ void MxSmkPresenter::VTable0x88() { if ((m_mxSmack.m_smackTag.SmackerType & 1) != 0) { MxU32 und = (m_currentFrame % m_mxSmack.m_smackTag.Frames); - if (1 < m_currentFrame && und == 1) + if (1 < m_currentFrame && und == 1) { m_currentFrame = 1; + } } else { if (m_mxSmack.m_smackTag.Frames == m_currentFrame) { diff --git a/LEGO1/omni/src/video/mxstillpresenter.cpp b/LEGO1/omni/src/video/mxstillpresenter.cpp index 4b81d6f1..049ad48c 100644 --- a/LEGO1/omni/src/video/mxstillpresenter.cpp +++ b/LEGO1/omni/src/video/mxstillpresenter.cpp @@ -19,21 +19,24 @@ void MxStillPresenter::Destroy(MxBool p_fromDestructor) { m_criticalSection.Enter(); - if (m_bitmapInfo) + if (m_bitmapInfo) { delete m_bitmapInfo; + } m_bitmapInfo = NULL; m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxVideoPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b9cc0 void MxStillPresenter::LoadHeader(MxStreamChunk* p_chunk) { - if (m_bitmapInfo) + if (m_bitmapInfo) { delete m_bitmapInfo; + } MxU8* data = new MxU8[p_chunk->GetLength()]; m_bitmapInfo = (MxBITMAPINFO*) data; @@ -43,8 +46,9 @@ void MxStillPresenter::LoadHeader(MxStreamChunk* p_chunk) // FUNCTION: LEGO1 0x100b9d10 void MxStillPresenter::CreateBitmap() { - if (m_bitmap) + if (m_bitmap) { delete m_bitmap; + } m_bitmap = new MxBitmap; m_bitmap->ImportBitmapInfo(m_bitmapInfo); @@ -58,7 +62,7 @@ void MxStillPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); LoadFrame(chunk); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); } // FUNCTION: LEGO1 0x100b9dd0 @@ -75,12 +79,12 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); - if (m_flags & c_bit2) { + if (GetBit1()) { undefined4 und = 0; m_unk0x58 = MxOmni::GetInstance()->GetVideoManager()->GetDisplaySurface()->VTable0x44( m_bitmap, &und, - (m_flags & c_bit4) / 8, + GetBit3(), m_action->GetFlags() & MxDSAction::c_bit4 ); @@ -90,10 +94,12 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) delete m_bitmap; m_bitmap = NULL; - if (m_unk0x58 && und) - m_flags |= c_bit3; - else - m_flags &= ~c_bit3; + if (m_unk0x58 && und) { + SetBit2(TRUE); + } + else { + SetBit2(FALSE); + } } } @@ -110,8 +116,9 @@ void MxStillPresenter::StartingTickle() { MxVideoPresenter::StartingTickle(); - if (m_currentTickleState == e_streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) + if (m_currentTickleState == e_streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) { RealizePalette(); + } } // FUNCTION: LEGO1 0x100b9f90 @@ -124,8 +131,9 @@ void MxStillPresenter::StreamingTickle() NextFrame(); ProgressTickleState(e_repeating); - if (m_action->GetDuration() == -1 && m_compositePresenter) + if (m_action->GetDuration() == -1 && m_compositePresenter) { m_compositePresenter->VTable0x60(this); + } } } @@ -133,13 +141,14 @@ void MxStillPresenter::StreamingTickle() void MxStillPresenter::RepeatingTickle() { if (m_action->GetDuration() != -1) { - if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) + if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) { ProgressTickleState(e_unk5); + } } } // FUNCTION: LEGO1 0x100ba040 -void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y) +void MxStillPresenter::SetPosition(MxS32 p_x, MxS32 p_y) { MxS32 x = m_location.GetX(); MxS32 y = m_location.GetY(); @@ -185,13 +194,15 @@ void MxStillPresenter::ParseExtra() { MxPresenter::ParseExtra(); - if (m_action->GetFlags() & MxDSAction::c_bit5) - m_flags |= c_bit4; + if (m_action->GetFlags() & MxDSAction::c_bit5) { + SetBit3(TRUE); + } MxU32 len = m_action->GetExtraLength(); - if (len == 0) + if (len == 0) { return; + } len &= MAXWORD; @@ -207,15 +218,55 @@ void MxStillPresenter::ParseExtra() } if (KeyValueStringParse(output, g_strBmpIsmap, buf)) { - m_flags |= c_bit5; - m_flags &= ~c_bit2; - m_flags &= ~c_bit3; + SetBit4(TRUE); + SetBit1(FALSE); + SetBit2(FALSE); } } -// STUB: LEGO1 0x100ba2c0 +// FUNCTION: LEGO1 0x100ba2c0 MxStillPresenter* MxStillPresenter::Clone() { - // TODO - return NULL; + MxResult result = FAILURE; + MxStillPresenter* presenter = new MxStillPresenter; + + if (presenter) { + if (presenter->AddToManager() == SUCCESS) { + MxDSAction* action = presenter->GetAction()->Clone(); + + if (action && presenter->StartAction(NULL, action) == SUCCESS) { + presenter->SetBit0(GetBit0()); + presenter->SetBit1(GetBit1()); + presenter->SetBit2(GetBit2()); + presenter->SetBit3(GetBit3()); + presenter->SetBit4(GetBit4()); + + if (m_bitmap) { + presenter->m_bitmap = new MxBitmap; + + if (!presenter->m_bitmap || presenter->m_bitmap->ImportBitmap(m_bitmap) != SUCCESS) { + goto done; + } + } + + if (m_unk0x58) { + presenter->m_unk0x58 = MxDisplaySurface::FUN_100bbfb0(m_unk0x58); + } + + if (m_alpha) { + presenter->m_alpha = new MxVideoPresenter::AlphaMask(*m_alpha); + } + + result = SUCCESS; + } + } + } + +done: + if (result != SUCCESS) { + delete presenter; + presenter = NULL; + } + + return presenter; } diff --git a/LEGO1/omni/src/video/mxvideomanager.cpp b/LEGO1/omni/src/video/mxvideomanager.cpp index 9a2a6cee..f2c9ddfa 100644 --- a/LEGO1/omni/src/video/mxvideomanager.cpp +++ b/LEGO1/omni/src/video/mxvideomanager.cpp @@ -42,32 +42,39 @@ void MxVideoManager::Destroy(MxBool p_fromDestructor) m_thread->Terminate(); delete m_thread; } - else + else { TickleManager()->UnregisterClient(this); + } m_criticalSection.Enter(); - if (m_displaySurface) + if (m_displaySurface) { delete m_displaySurface; + } - if (m_region) + if (m_region) { delete m_region; + } - if (m_videoParam.GetPalette()) + if (m_videoParam.GetPalette()) { delete m_videoParam.GetPalette(); + } if (m_unk0x60) { - if (m_pDirectDraw) + if (m_pDirectDraw) { m_pDirectDraw->Release(); - if (m_pDirect3D) + } + if (m_pDirect3D) { m_pDirect3D->Release(); + } } Init(); m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaManager::Destroy(); + } } // FUNCTION: LEGO1 0x100be3e0 @@ -85,8 +92,9 @@ void MxVideoManager::UpdateRegion() // FUNCTION: LEGO1 0x100be440 void MxVideoManager::SortPresenterList() { - if (this->m_presenters->GetCount() <= 1) + if (this->m_presenters->GetCount() <= 1) { return; + } MxPresenterListCursor a(this->m_presenters); MxPresenterListCursor b(this->m_presenters); @@ -132,8 +140,9 @@ MxResult MxVideoManager::VTable0x28( m_unk0x60 = FALSE; - if (MxMediaManager::InitPresenters() != SUCCESS) + if (MxMediaManager::InitPresenters() != SUCCESS) { goto done; + } m_criticalSection.Enter(); locked = TRUE; @@ -141,8 +150,9 @@ MxResult MxVideoManager::VTable0x28( m_videoParam = p_videoParam; m_region = new MxRegion(); - if (!m_region) + if (!m_region) { goto done; + } m_pDirectDraw = p_pDirectDraw; m_pDirect3D = p_pDirect3D; @@ -152,15 +162,17 @@ MxResult MxVideoManager::VTable0x28( palette = new MxPalette(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } else { palette = p_videoParam.GetPalette()->Clone(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } m_displaySurface = new MxDisplaySurface(); @@ -170,21 +182,25 @@ MxResult MxVideoManager::VTable0x28( if (p_createThread) { m_thread = new MxTickleThread(this, p_frequencyMS); - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; } done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return status; } @@ -197,8 +213,9 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, m_unk0x60 = TRUE; - if (MxMediaManager::InitPresenters() != SUCCESS) + if (MxMediaManager::InitPresenters() != SUCCESS) { goto done; + } m_criticalSection.Enter(); locked = TRUE; @@ -206,29 +223,34 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, m_videoParam = p_videoParam; m_region = new MxRegion(); - if (!m_region) + if (!m_region) { goto done; + } - if (DirectDrawCreate(NULL, &m_pDirectDraw, NULL) != DD_OK) + if (DirectDrawCreate(NULL, &m_pDirectDraw, NULL) != DD_OK) { goto done; + } - if (m_pDirectDraw->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DDSCL_NORMAL) != DD_OK) + if (m_pDirectDraw->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DDSCL_NORMAL) != DD_OK) { goto done; + } MxPalette* palette; if (p_videoParam.GetPalette() == NULL) { palette = new MxPalette(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } else { palette = p_videoParam.GetPalette()->Clone(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } m_displaySurface = new MxDisplaySurface(); @@ -238,21 +260,25 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, if (p_createThread) { m_thread = new MxTickleThread(this, p_frequencyMS); - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; } done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return status; } @@ -268,8 +294,9 @@ void MxVideoManager::InvalidateRect(MxRect32& p_rect) { m_criticalSection.Enter(); - if (m_region) + if (m_region) { m_region->VTable0x18(p_rect); + } m_criticalSection.Leave(); } @@ -284,13 +311,15 @@ MxResult MxVideoManager::Tickle() MxPresenter* presenter; MxPresenterListCursor cursor(this->m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->Tickle(); + } cursor.Reset(); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->PutData(); + } UpdateRegion(); m_region->Reset(); diff --git a/LEGO1/omni/src/video/mxvideoparam.cpp b/LEGO1/omni/src/video/mxvideoparam.cpp index c34e832c..8e48773f 100644 --- a/LEGO1/omni/src/video/mxvideoparam.cpp +++ b/LEGO1/omni/src/video/mxvideoparam.cpp @@ -21,12 +21,7 @@ MxVideoParam::MxVideoParam() } // FUNCTION: LEGO1 0x100beca0 -MxVideoParam::MxVideoParam( - COMPAT_CONST MxRect32& p_rect, - MxPalette* p_palette, - MxULong p_backBuffers, - COMPAT_CONST MxVideoParamFlags& p_flags -) +MxVideoParam::MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_backBuffers, MxVideoParamFlags& p_flags) { this->m_rect = p_rect; this->m_palette = p_palette; @@ -51,15 +46,17 @@ MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam) // FUNCTION: LEGO1 0x100bed50 MxVideoParam::~MxVideoParam() { - if (this->m_deviceId != NULL) + if (this->m_deviceId != NULL) { delete[] this->m_deviceId; + } } // FUNCTION: LEGO1 0x100bed70 void MxVideoParam::SetDeviceName(char* p_deviceId) { - if (this->m_deviceId != NULL) + if (this->m_deviceId != NULL) { delete[] this->m_deviceId; + } if (p_deviceId != NULL) { this->m_deviceId = new char[strlen(p_deviceId) + 1]; diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index ebc08487..36fad6d0 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -6,7 +6,7 @@ #include "mxvideomanager.h" DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); -DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0xc); +DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0x0c); // FUNCTION: LEGO1 0x100b24f0 MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) @@ -33,10 +33,12 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) switch (p_bitmap.GetBmiHeader()->biCompression) { case BI_RGB: { - if (p_bitmap.GetBmiHeight() < 0) + if (p_bitmap.GetBmiHeight() < 0) { rowsBeforeTop = 0; - else + } + else { rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; + } bitmapSrcPtr = p_bitmap.GetBitmapData() + (p_bitmap.GetBmiStride() * rowsBeforeTop); break; } @@ -44,10 +46,12 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) bitmapSrcPtr = p_bitmap.GetBitmapData(); break; default: { - if (p_bitmap.GetBmiHeight() < 0) + if (p_bitmap.GetBmiHeight() < 0) { rowsBeforeTop = 0; - else + } + else { rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; + } bitmapSrcPtr = p_bitmap.GetBitmapData() + (p_bitmap.GetBmiStride() * rowsBeforeTop); } } @@ -57,8 +61,9 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) // If this is a bottom-up DIB, we will walk it in reverse. // TODO: Same rounding trick as in MxBitmap MxS32 rowSeek = ((m_width + 3) & -4); - if (p_bitmap.GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap.GetBmiHeight() > 0) + if (p_bitmap.GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap.GetBmiHeight() > 0) { rowSeek = -rowSeek; + } // The actual offset into the m_bitmask array. The two for-loops // are just for counting the pixels. @@ -95,15 +100,17 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxVideoPresenter::AlphaMask& p_alph // FUNCTION: LEGO1 0x100b26d0 MxVideoPresenter::AlphaMask::~AlphaMask() { - if (m_bitmask) + if (m_bitmask) { delete[] m_bitmask; + } } // FUNCTION: LEGO1 0x100b26f0 MxS32 MxVideoPresenter::AlphaMask::IsHit(MxU32 p_x, MxU32 p_y) { - if (p_x >= m_width || p_y >= m_height) + if (p_x >= m_width || p_y >= m_height) { return 0; + } MxS32 pos = p_y * m_width + p_x; return m_bitmask[pos / 8] & (1 << abs(abs(pos) & 7)) ? 1 : 0; @@ -117,29 +124,30 @@ void MxVideoPresenter::Init() m_unk0x5c = 1; m_unk0x58 = NULL; m_unk0x60 = -1; - m_flags &= ~c_bit1; + SetBit0(FALSE); if (MVideoManager() != NULL) { MVideoManager(); - m_flags |= c_bit2; - m_flags &= ~c_bit3; + SetBit1(TRUE); + SetBit2(FALSE); } - m_flags &= ~c_bit4; - m_flags &= ~c_bit5; + SetBit3(FALSE); + SetBit4(FALSE); } // FUNCTION: LEGO1 0x100b27b0 void MxVideoPresenter::Destroy(MxBool p_fromDestructor) { - if (MVideoManager() != NULL) + if (MVideoManager() != NULL) { MVideoManager()->UnregisterPresenter(*this); + } if (m_unk0x58) { m_unk0x58->Release(); m_unk0x58 = NULL; - m_flags &= ~c_bit2; - m_flags &= ~c_bit3; + SetBit1(FALSE); + SetBit2(FALSE); } if (MVideoManager() && (m_alpha || m_bitmap)) { @@ -159,8 +167,9 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) Init(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b28b0 @@ -169,12 +178,12 @@ void MxVideoPresenter::NextFrame() MxStreamChunk* chunk = NextChunk(); if (chunk->GetFlags() & MxDSChunk::c_end) { - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); ProgressTickleState(e_repeating); } else { LoadFrame(chunk); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); } } @@ -183,11 +192,13 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) { MxDSAction* action = GetAction(); if ((action == NULL) || (((action->GetFlags() & MxDSAction::c_bit11) == 0) && !IsEnabled()) || - (!m_bitmap && !m_alpha)) + (!m_bitmap && !m_alpha)) { return FALSE; + } - if (!m_bitmap) + if (!m_bitmap) { return m_alpha->IsHit(p_x - m_location.GetX(), p_y - m_location.GetY()); + } MxLong heightAbs = m_bitmap->GetBmiHeightAbs(); @@ -197,8 +208,9 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) MxLong maxY = minY + heightAbs; MxLong maxX = minX + m_bitmap->GetBmiWidth(); - if (p_x < minX || p_x >= maxX || p_y < minY || p_y >= maxY) + if (p_x < minX || p_x >= maxX || p_y < minY || p_y >= maxY) { return FALSE; + } MxU8* pixel; @@ -230,12 +242,13 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) pixel = m_bitmap->GetBmiStride() * height + m_bitmap->GetBitmapData(); } - // DECOMP: m_flags is 1 byte, so no enum here - if (m_flags & 0x10) + if (GetBit4()) { return (MxBool) *pixel; + } - if ((GetAction()->GetFlags() & MxDSAction::c_bit4) && *pixel == 0) + if ((GetAction()->GetFlags() & MxDSAction::c_bit4) && *pixel == 0) { return FALSE; + } return TRUE; } @@ -243,32 +256,40 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) inline MxS32 MxVideoPresenter::PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc) { if (p_rectDest.GetTop() > 480 || p_rectDest.GetLeft() > 640 || p_rectSrc.GetTop() > 480 || - p_rectSrc.GetLeft() > 640) + p_rectSrc.GetLeft() > 640) { return -1; + } - if (p_rectDest.GetBottom() > 480) + if (p_rectDest.GetBottom() > 480) { p_rectDest.SetBottom(480); + } - if (p_rectDest.GetRight() > 640) + if (p_rectDest.GetRight() > 640) { p_rectDest.SetRight(640); + } - if (p_rectSrc.GetBottom() > 480) + if (p_rectSrc.GetBottom() > 480) { p_rectSrc.SetBottom(480); + } - if (p_rectSrc.GetRight() > 640) + if (p_rectSrc.GetRight() > 640) { p_rectSrc.SetRight(640); + } MxS32 height = p_rectDest.GetHeight(); - if (height <= 1) + if (height <= 1) { return -1; + } MxS32 width = p_rectDest.GetWidth(); - if (width <= 1) + if (width <= 1) { return -1; + } if (p_rectSrc.GetRight() - width - p_rectSrc.GetLeft() == -1 && - p_rectSrc.GetBottom() - height - p_rectSrc.GetTop() == -1) + p_rectSrc.GetBottom() - height - p_rectSrc.GetTop() == -1) { return 1; + } p_rectSrc.SetRight(p_rectSrc.GetLeft() + width - 1); p_rectSrc.SetBottom(p_rectSrc.GetTop() + height - 1); @@ -326,7 +347,7 @@ void MxVideoPresenter::PutFrame() MxRegionCursor cursor(region); MxRect32* regionRect; - while (regionRect = cursor.VTable0x24(rect)) { + while ((regionRect = cursor.VTable0x24(rect))) { if (regionRect->GetWidth() >= 1 && regionRect->GetHeight() >= 1) { if (m_unk0x58) { rectSrc.SetLeft(regionRect->GetLeft() - m_location.GetX()); @@ -342,8 +363,9 @@ void MxVideoPresenter::PutFrame() if (m_action->GetFlags() & MxDSAction::c_bit4) { if (m_unk0x58) { - if (PrepareRects(rectDest, rectSrc) >= 0) + if (PrepareRects(rectDest, rectSrc) >= 0) { ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL); + } } else { displaySurface->VTable0x30( @@ -359,8 +381,9 @@ void MxVideoPresenter::PutFrame() } } else if (m_unk0x58) { - if (PrepareRects(rectDest, rectSrc) >= 0) + if (PrepareRects(rectDest, rectSrc) >= 0) { ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, 0, NULL); + } } else { displaySurface->VTable0x28( @@ -385,7 +408,7 @@ void MxVideoPresenter::ReadyTickle() if (chunk) { LoadHeader(chunk); - m_subscriber->DestroyChunk(chunk); + m_subscriber->FreeDataChunk(chunk); ParseExtra(); ProgressTickleState(e_starting); } @@ -406,8 +429,9 @@ void MxVideoPresenter::StartingTickle() void MxVideoPresenter::StreamingTickle() { if (m_action->GetFlags() & MxDSAction::c_bit10) { - if (!m_currentChunk) + if (!m_currentChunk) { MxMediaPresenter::StreamingTickle(); + } if (m_currentChunk) { LoadFrame(m_currentChunk); @@ -419,24 +443,28 @@ void MxVideoPresenter::StreamingTickle() if (!m_currentChunk) { MxMediaPresenter::StreamingTickle(); - if (!m_currentChunk) + if (!m_currentChunk) { break; + } } - if (m_action->GetElapsedTime() < m_currentChunk->GetTime()) + if (m_action->GetElapsedTime() < m_currentChunk->GetTime()) { break; + } LoadFrame(m_currentChunk); - m_subscriber->DestroyChunk(m_currentChunk); + m_subscriber->FreeDataChunk(m_currentChunk); m_currentChunk = NULL; - m_flags |= c_bit1; + SetBit0(TRUE); - if (m_currentTickleState != e_streaming) + if (m_currentTickleState != e_streaming) { break; + } } - if (m_flags & c_bit1) + if (GetBit0()) { m_unk0x5c = 5; + } } } @@ -445,8 +473,9 @@ void MxVideoPresenter::RepeatingTickle() { if (IsEnabled()) { if (m_action->GetFlags() & MxDSAction::c_bit10) { - if (!m_currentChunk) + if (!m_currentChunk) { MxMediaPresenter::RepeatingTickle(); + } if (m_currentChunk) { LoadFrame(m_currentChunk); @@ -458,23 +487,27 @@ void MxVideoPresenter::RepeatingTickle() if (!m_currentChunk) { MxMediaPresenter::RepeatingTickle(); - if (!m_currentChunk) + if (!m_currentChunk) { break; + } } - if (m_action->GetElapsedTime() % m_action->GetLoopCount() < m_currentChunk->GetTime()) + if (m_action->GetElapsedTime() % m_action->GetLoopCount() < m_currentChunk->GetTime()) { break; + } LoadFrame(m_currentChunk); m_currentChunk = NULL; - m_flags |= c_bit1; + SetBit0(TRUE); - if (m_currentTickleState != e_repeating) + if (m_currentTickleState != e_repeating) { break; + } } - if (m_flags & c_bit1) + if (GetBit0()) { m_unk0x5c = 5; + } } } } @@ -486,14 +519,17 @@ void MxVideoPresenter::Unk5Tickle() if (sustainTime != -1) { if (sustainTime) { - if (m_unk0x60 == -1) + if (m_unk0x60 == -1) { m_unk0x60 = m_action->GetElapsedTime(); + } - if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) + if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) { ProgressTickleState(e_done); + } } - else + else { ProgressTickleState(e_done); + } } } @@ -535,8 +571,9 @@ MxResult MxVideoPresenter::PutData() { MxAutoLocker lock(&m_criticalSection); - if (IsEnabled() && m_currentTickleState >= e_streaming && m_currentTickleState <= e_unk5) + if (IsEnabled() && m_currentTickleState >= e_streaming && m_currentTickleState <= e_unk5) { PutFrame(); + } return SUCCESS; } diff --git a/LEGO1/realtime/matrix.cpp b/LEGO1/realtime/matrix.cpp index 806e6659..c1de1535 100644 --- a/LEGO1/realtime/matrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -2,4 +2,4 @@ #include "decomp.h" -DECOMP_SIZE_ASSERT(Matrix4, 0x8); +DECOMP_SIZE_ASSERT(Matrix4, 0x08); diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index 9a301a01..266b2fa6 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -10,7 +10,7 @@ struct UnknownMatrixType { }; // VTABLE: LEGO1 0x100d4350 -// SIZE 0x8 +// SIZE 0x08 class Matrix4 { public: inline Matrix4(float (*p_data)[4]) { SetData(p_data); } @@ -25,28 +25,28 @@ class Matrix4 { virtual void Equals(const Matrix4& p_matrix) { memcpy(m_data, p_matrix.m_data, sizeof(float) * 4 * 4); - }; // vtable+0x00 + } // vtable+0x00 // FUNCTION: LEGO1 0x10002360 virtual void SetData(float (*p_data)[4]) { m_data = p_data; } // vtable+0x0c // FUNCTION: LEGO1 0x10002370 - virtual void SetData(UnknownMatrixType& p_matrix) { m_data = p_matrix.m_data; }; // vtable+0x08 + virtual void SetData(UnknownMatrixType& p_matrix) { m_data = p_matrix.m_data; } // vtable+0x08 // FUNCTION: LEGO1 0x10002380 - virtual float (*GetData())[4] { return m_data; }; // vtable+0x14 + virtual float (*GetData())[4] { return m_data; } // vtable+0x14 // FUNCTION: LEGO1 0x10002390 - virtual float (*GetData() const)[4] { return m_data; }; // vtable+0x10 + virtual float (*GetData() const)[4] { return m_data; } // vtable+0x10 // FUNCTION: LEGO1 0x100023a0 virtual float* Element(int p_row, int p_col) { return &m_data[p_row][p_col]; } // vtable+0x1c // FUNCTION: LEGO1 0x100023c0 - virtual const float* Element(int p_row, int p_col) const { return &m_data[p_row][p_col]; }; // vtable+0x18 + virtual const float* Element(int p_row, int p_col) const { return &m_data[p_row][p_col]; } // vtable+0x18 // FUNCTION: LEGO1 0x100023e0 - virtual void Clear() { memset(m_data, 0, 16 * sizeof(float)); }; // vtable+0x20 + virtual void Clear() { memset(m_data, 0, 16 * sizeof(float)); } // vtable+0x20 // FUNCTION: LEGO1 0x100023f0 virtual void SetIdentity() @@ -64,8 +64,9 @@ class Matrix4 { // FUNCTION: LEGO1 0x10002430 virtual Matrix4& operator+=(float (*p_data)[4]) { - for (int i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) { ((float*) m_data)[i] += ((float*) p_data)[i]; + } return *this; } // vtable+0x2c @@ -98,7 +99,7 @@ class Matrix4 { cur++; } } - }; // vtable+0x3c + } // vtable+0x3c // FUNCTION: LEGO1 0x10002530 virtual void Product(const Matrix4& p_a, const Matrix4& p_b) { Product(p_a.m_data, p_b.m_data); } // vtable+0x38 diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp index 4f48c333..8a2e8a12 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -53,11 +53,12 @@ void OrientableROI::UpdateWorldData(const MxMatrix& p_transform) UpdateWorldVelocity(); // iterate over comps - if (m_comp) - for (CompoundObject::iterator iter = m_comp->begin(); !(iter == m_comp->end()); iter++) { + if (comp) { + for (CompoundObject::iterator iter = comp->begin(); !(iter == comp->end()); iter++) { ROI* child = *iter; static_cast(child)->UpdateWorldData(p_transform); } + } } // FUNCTION: LEGO1 0x100a5a50 diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index 36b8ae50..005ec4dc 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -16,9 +16,9 @@ class OrientableROI : public ROI { OrientableROI(); - virtual const float* GetWorldVelocity() const override; // vtable+0x8 - virtual const BoundingBox& GetWorldBoundingBox() const override; // vtable+0xc - virtual const BoundingSphere& GetWorldBoundingSphere() const override; // vtable+0x10 + const float* GetWorldVelocity() const override; // vtable+0x08 + const BoundingBox& GetWorldBoundingBox() const override; // vtable+0x0c + const BoundingSphere& GetWorldBoundingSphere() const override; // vtable+0x10 // FUNCTION: LEGO1 0x100a5db0 virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 @@ -32,6 +32,7 @@ class OrientableROI : public ROI { const float* GetWorldPosition() const { return m_local2world[3]; } const float* GetWorldDirection() const { return m_local2world[2]; } const float* GetWorldUp() const { return m_local2world[1]; } + OrientableROI* GetUnknown0xd4() const { return m_unk0xd4; } protected: MxMatrix m_local2world; // 0x10 @@ -46,7 +47,7 @@ class OrientableROI : public ROI { Mx3DPointFloat m_unk0x94; // 0x94 BoundingSphere m_world_bounding_sphere; // 0xa8 Mx3DPointFloat m_world_velocity; // 0xc0 - undefined4 m_unk0xd4; // 0xd4 + OrientableROI* m_unk0xd4; // 0xd4 undefined4 m_unk0xd8; // 0xd8 }; diff --git a/LEGO1/realtime/realtimeview.h b/LEGO1/realtime/realtimeview.h index 22183ced..f732c480 100644 --- a/LEGO1/realtime/realtimeview.h +++ b/LEGO1/realtime/realtimeview.h @@ -3,11 +3,11 @@ class RealtimeView { public: - __declspec(dllexport) static float GetPartsThreshold(); - __declspec(dllexport) static float GetUserMaxLOD(); - __declspec(dllexport) static void SetPartsThreshold(float); + static float GetPartsThreshold(); + static float GetUserMaxLOD(); + static void SetPartsThreshold(float); static void UpdateMaxLOD(); - __declspec(dllexport) static void SetUserMaxLOD(float); + static void SetUserMaxLOD(float); }; #endif // REALTIMEVIEW_H diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index 08db5080..33a9ce33 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -21,8 +21,8 @@ class BoundingBox { Mx3DPointFloat& Max() { return max; } private: - Mx3DPointFloat min; - Mx3DPointFloat max; + Mx3DPointFloat min; // 0x00 + Mx3DPointFloat max; // 0x14 }; /* @@ -37,8 +37,8 @@ class BoundingSphere { float& Radius() { return radius; } private: - Mx3DPointFloat center; - float radius; + Mx3DPointFloat center; // 0x00 + float radius; // 0x14 }; /* @@ -49,9 +49,9 @@ class LODObject { public: // LODObject(); virtual ~LODObject() {} - virtual float Cost(float pixels_covered) const = 0; // vtable+0x4 - virtual float AveragePolyArea() const = 0; // vtable+0x8 - virtual int NVerts() const = 0; // vtable+0xc + virtual float Cost(float pixels_covered) const = 0; // vtable+0x04 + virtual float AveragePolyArea() const = 0; // vtable+0x08 + virtual int NVerts() const = 0; // vtable+0x0c }; /* @@ -79,39 +79,45 @@ class ROI { public: ROI() { - m_comp = 0; - m_lods = 0; - m_unk0xc = 1; + comp = 0; + lods = 0; + m_unk0x0c = 1; } virtual ~ROI() { // if derived class set the comp and lods, it should delete them - assert(!m_comp); - assert(!m_lods); + assert(!comp); + assert(!lods); } - virtual float IntrinsicImportance() const = 0; // vtable+0x4 - virtual const float* GetWorldVelocity() const = 0; // vtable+0x8 - virtual const BoundingBox& GetWorldBoundingBox() const = 0; // vtable+0xc + virtual float IntrinsicImportance() const = 0; // vtable+0x04 + virtual const float* GetWorldVelocity() const = 0; // vtable+0x08 + virtual const BoundingBox& GetWorldBoundingBox() const = 0; // vtable+0x0c virtual const BoundingSphere& GetWorldBoundingSphere() const = 0; // vtable+0x10 - const LODListBase* GetLODs() const { return m_lods; } + const LODListBase* GetLODs() const { return lods; } const LODObject* GetLOD(int i) const { - assert(m_lods); - return (*m_lods)[i]; + assert(lods); + return (*lods)[i]; } - int GetLODCount() const { return m_lods ? m_lods->Size() : 0; } - const CompoundObject* GetComp() const { return m_comp; } + int GetLODCount() const { return lods ? lods->Size() : 0; } + const CompoundObject* GetComp() const { return comp; } + + inline undefined GetUnknown0x0c() { return m_unk0x0c; } + inline void SetUnknown0x0c(undefined p_unk0x0c) { m_unk0x0c = p_unk0x0c; } // SYNTHETIC: LEGO1 0x100a5d60 // ROI::`scalar deleting destructor' protected: - CompoundObject* m_comp; // 0x4 - LODListBase* m_lods; // 0x8 - undefined m_unk0xc; // 0xc + CompoundObject* comp; // 0x04 + LODListBase* lods; // 0x08 + undefined m_unk0x0c; // 0x0c }; +// TEMPLATE: LEGO1 0x10084930 +// list >::~list > + // SYNTHETIC: LEGO1 0x100a5d50 // ROI::~ROI diff --git a/LEGO1/realtime/vector.cpp b/LEGO1/realtime/vector.cpp index 57c93e66..ad09b0b0 100644 --- a/LEGO1/realtime/vector.cpp +++ b/LEGO1/realtime/vector.cpp @@ -2,6 +2,6 @@ #include "decomp.h" -DECOMP_SIZE_ASSERT(Vector2, 0x8); -DECOMP_SIZE_ASSERT(Vector3, 0x8); -DECOMP_SIZE_ASSERT(Vector4, 0x8); +DECOMP_SIZE_ASSERT(Vector2, 0x08); +DECOMP_SIZE_ASSERT(Vector3, 0x08); +DECOMP_SIZE_ASSERT(Vector4, 0x08); diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index eb03d29d..a28a9874 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -192,7 +192,7 @@ class Vector3 : public Vector2 { // Vector2 overrides // FUNCTION: LEGO1 0x10003a60 - virtual void AddImpl(float* p_value) override + void AddImpl(float* p_value) override { m_data[0] += p_value[0]; m_data[1] += p_value[1]; @@ -200,7 +200,7 @@ class Vector3 : public Vector2 { } // vtable+0x04 // FUNCTION: LEGO1 0x10003a90 - virtual void AddImpl(float p_value) override + void AddImpl(float p_value) override { m_data[0] += p_value; m_data[1] += p_value; @@ -208,7 +208,7 @@ class Vector3 : public Vector2 { } // vtable+0x00 // FUNCTION: LEGO1 0x10003ac0 - virtual void SubImpl(float* p_value) override + void SubImpl(float* p_value) override { m_data[0] -= p_value[0]; m_data[1] -= p_value[1]; @@ -216,7 +216,7 @@ class Vector3 : public Vector2 { } // vtable+0x08 // FUNCTION: LEGO1 0x10003b20 - virtual void MulScalarImpl(float* p_value) override + void MulScalarImpl(float* p_value) override { m_data[0] *= *p_value; m_data[1] *= *p_value; @@ -224,7 +224,7 @@ class Vector3 : public Vector2 { } // vtable+0x0c // FUNCTION: LEGO1 0x10003af0 - virtual void MulVectorImpl(float* p_value) override + void MulVectorImpl(float* p_value) override { m_data[0] *= p_value[0]; m_data[1] *= p_value[1]; @@ -232,7 +232,7 @@ class Vector3 : public Vector2 { } // vtable+0x10 // FUNCTION: LEGO1 0x10003b50 - virtual void DivScalarImpl(float* p_value) override + void DivScalarImpl(float* p_value) override { m_data[0] /= *p_value; m_data[1] /= *p_value; @@ -240,19 +240,19 @@ class Vector3 : public Vector2 { } // vtable+0x14 // FUNCTION: LEGO1 0x10003b80 - virtual float DotImpl(float* p_a, float* p_b) const override + float DotImpl(float* p_a, float* p_b) const override { return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; } // vtable+0x18 // FUNCTION: LEGO1 0x10003ba0 - virtual void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 3); } // vtable+0x20 + void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 3); } // vtable+0x20 // FUNCTION: LEGO1 0x10003bc0 - virtual void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c + void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c // FUNCTION: LEGO1 0x10003bd0 - virtual float LenSquared() const override + float LenSquared() const override { return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; } // vtable+0x40 @@ -263,7 +263,7 @@ class Vector3 : public Vector2 { }; // VTABLE: LEGO1 0x100d45a0 -// SIZE 0x8 +// SIZE 0x08 class Vector4 : public Vector3 { public: inline Vector4(float* p_data) : Vector3(p_data) {} @@ -289,7 +289,7 @@ class Vector4 : public Vector3 { // Vector3 overrides // FUNCTION: LEGO1 0x10002870 - virtual void AddImpl(float* p_value) override + void AddImpl(float* p_value) override { m_data[0] += p_value[0]; m_data[1] += p_value[1]; @@ -298,7 +298,7 @@ class Vector4 : public Vector3 { } // vtable+0x04 // FUNCTION: LEGO1 0x100028b0 - virtual void AddImpl(float p_value) override + void AddImpl(float p_value) override { m_data[0] += p_value; m_data[1] += p_value; @@ -307,7 +307,7 @@ class Vector4 : public Vector3 { } // vtable+0x00 // FUNCTION: LEGO1 0x100028f0 - virtual void SubImpl(float* p_value) override + void SubImpl(float* p_value) override { m_data[0] -= p_value[0]; m_data[1] -= p_value[1]; @@ -316,7 +316,7 @@ class Vector4 : public Vector3 { } // vtable+0x08 // FUNCTION: LEGO1 0x10002970 - virtual void MulScalarImpl(float* p_value) override + void MulScalarImpl(float* p_value) override { m_data[0] *= *p_value; m_data[1] *= *p_value; @@ -325,7 +325,7 @@ class Vector4 : public Vector3 { } // vtable+0x0c // FUNCTION: LEGO1 0x10002930 - virtual void MulVectorImpl(float* p_value) override + void MulVectorImpl(float* p_value) override { m_data[0] *= p_value[0]; m_data[1] *= p_value[1]; @@ -334,7 +334,7 @@ class Vector4 : public Vector3 { } // vtable+0x10 // FUNCTION: LEGO1 0x100029b0 - virtual void DivScalarImpl(float* p_value) override + void DivScalarImpl(float* p_value) override { m_data[0] /= *p_value; m_data[1] /= *p_value; @@ -343,25 +343,25 @@ class Vector4 : public Vector3 { } // vtable+0x14 // FUNCTION: LEGO1 0x100029f0 - virtual float DotImpl(float* p_a, float* p_b) const override + float DotImpl(float* p_a, float* p_b) const override { return p_a[0] * p_b[0] + p_a[2] * p_b[2] + (p_a[1] * p_b[1] + p_a[3] * p_b[3]); } // vtable+0x18 // FUNCTION: LEGO1 0x10002a20 - virtual void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 4); } // vtable+0x20 + void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 4); } // vtable+0x20 // FUNCTION: LEGO1 0x10002b00 - virtual void Clear() override { memset(m_data, 0, sizeof(float) * 4); } // vtable+0x2c + void Clear() override { memset(m_data, 0, sizeof(float) * 4); } // vtable+0x2c // FUNCTION: LEGO1 0x10002b20 - virtual float LenSquared() const override + float LenSquared() const override { return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2] + m_data[3] * m_data[3]; } // vtable+0x40 // FUNCTION: LEGO1 0x10002b40 - virtual void EqualsScalar(float* p_value) override + void EqualsScalar(float* p_value) override { m_data[0] = *p_value; m_data[1] = *p_value; diff --git a/LEGO1/tgl/d3drm/camera.cpp b/LEGO1/tgl/d3drm/camera.cpp index 9e000ba8..c7bc06f9 100644 --- a/LEGO1/tgl/d3drm/camera.cpp +++ b/LEGO1/tgl/d3drm/camera.cpp @@ -2,8 +2,8 @@ using namespace TglImpl; -DECOMP_SIZE_ASSERT(Camera, 0x4); -DECOMP_SIZE_ASSERT(CameraImpl, 0x8); +DECOMP_SIZE_ASSERT(Camera, 0x04); +DECOMP_SIZE_ASSERT(CameraImpl, 0x08); // FUNCTION: LEGO1 0x100a36f0 void* CameraImpl::ImplementationDataPtr() diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index 614b5f60..78b16641 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -40,16 +40,16 @@ class UnkImpl; class RendererImpl : public Renderer { public: RendererImpl() : m_data(0) {} - ~RendererImpl() { Destroy(); }; + ~RendererImpl() override { Destroy(); } - virtual void* ImplementationDataPtr() override; + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Device* CreateDevice(const DeviceDirectDrawCreateData&) override; - virtual Device* CreateDevice(const DeviceDirect3DCreateData&) override; + Device* CreateDevice(const DeviceDirectDrawCreateData&) override; + Device* CreateDevice(const DeviceDirect3DCreateData&) override; // vtable+0x10 - virtual View* CreateView( + View* CreateView( const Device*, const Camera*, unsigned long x, @@ -57,13 +57,13 @@ class RendererImpl : public Renderer { unsigned long width, unsigned long height ) override; - virtual Camera* CreateCamera() override; - virtual Light* CreateLight(LightType, float r, float g, float b) override; - virtual Group* CreateGroup(const Group* pParent) override; + Camera* CreateCamera() override; + Light* CreateLight(LightType, float r, float g, float b) override; + Group* CreateGroup(const Group* pParent) override; // vtable+0x20 - virtual Unk* CreateUnk() override; - virtual Texture* CreateTexture( + Unk* CreateUnk() override; + Texture* CreateTexture( int width, int height, int bitsPerTexel, @@ -72,12 +72,17 @@ class RendererImpl : public Renderer { int paletteEntryCount, const PaletteEntry* pEntries ) override; - virtual Texture* CreateTexture() override; + Texture* CreateTexture() override; - virtual Result SetTextureDefaultShadeCount(unsigned long) override; + Result SetTextureDefaultShadeCount(unsigned long) override; // vtable+0x30 - virtual Result SetTextureDefaultColorCount(unsigned long) override; + Result SetTextureDefaultColorCount(unsigned long) override; + + inline HRESULT CreateTextureFromSurface(LPDIRECTDRAWSURFACE pSurface, LPDIRECT3DRMTEXTURE2* pTexture2) + { + return m_data->CreateTextureFromSurface(pSurface, pTexture2); + } public: inline Result Create(); @@ -110,7 +115,7 @@ void RendererImpl::Destroy() class DeviceImpl : public Device { public: DeviceImpl() : m_data(0) {} - ~DeviceImpl() + ~DeviceImpl() override { if (m_data) { m_data->Release(); @@ -118,22 +123,22 @@ class DeviceImpl : public Device { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual unsigned long GetWidth(); - virtual unsigned long GetHeight(); + unsigned long GetWidth() override; + unsigned long GetHeight() override; // vtable+0x10 - virtual Result SetColorModel(ColorModel); - virtual Result SetShadingModel(ShadingModel); - virtual Result SetShadeCount(unsigned long); - virtual Result SetDither(int); + Result SetColorModel(ColorModel) override; + Result SetShadingModel(ShadingModel) override; + Result SetShadeCount(unsigned long) override; + Result SetDither(int) override; // vtable+0x20 - virtual Result Update(); - virtual void InitFromD3DDevice(Device*); - virtual void InitFromWindowsDevice(Device*); + Result Update() override; + void InitFromD3DDevice(Device*) override; + void InitFromWindowsDevice(Device*) override; inline IDirect3DRMDevice2* ImplementationData() const { return m_data; } @@ -147,7 +152,7 @@ class DeviceImpl : public Device { class ViewImpl : public View { public: ViewImpl() : m_data(0) {} - ~ViewImpl() + ~ViewImpl() override { if (m_data) { m_data->Release(); @@ -155,35 +160,35 @@ class ViewImpl : public View { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result Add(const Light*); - virtual Result Remove(const Light*); + Result Add(const Light*) override; + Result Remove(const Light*) override; // vtable+0x10 - virtual Result SetCamera(const Camera*); - virtual Result SetProjection(ProjectionType); - virtual Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees); - virtual Result SetBackgroundColor(float r, float g, float b); + Result SetCamera(const Camera*) override; + Result SetProjection(ProjectionType) override; + Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees) override; + Result SetBackgroundColor(float r, float g, float b) override; // vtable+0x20 - virtual Result GetBackgroundColor(float* r, float* g, float* b); - virtual Result Clear(); - virtual Result Render(const Light*); - virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height); + Result GetBackgroundColor(float* r, float* g, float* b) override; + Result Clear() override; + Result Render(const Group*) override; + Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) override; // vtable+0x30 - virtual Result TransformWorldToScreen(const float world[3], float screen[4]); - virtual Result TransformScreenToWorld(const float screen[4], float world[3]); - virtual Result Pick( + Result TransformWorldToScreen(const float world[3], float screen[4]) override; + Result TransformScreenToWorld(const float screen[4], float world[3]) override; + Result Pick( unsigned long x, unsigned long y, const Group** ppGroupsToPickFrom, int groupsToPickFromCount, const Group**& rppPickedGroups, int& rPickedGroupCount - ); + ) override; inline IDirect3DRMViewport* ImplementationData() const { return m_data; } @@ -199,7 +204,7 @@ class ViewImpl : public View { class CameraImpl : public Camera { public: CameraImpl() : m_data(0) {} - ~CameraImpl() + ~CameraImpl() override { if (m_data) { m_data->Release(); @@ -207,10 +212,10 @@ class CameraImpl : public Camera { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTransformation(FloatMatrix4&); + Result SetTransformation(FloatMatrix4&) override; inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -224,7 +229,7 @@ class CameraImpl : public Camera { class LightImpl : public Light { public: LightImpl() : m_data(0) {} - ~LightImpl() + ~LightImpl() override { if (m_data) { m_data->Release(); @@ -232,11 +237,11 @@ class LightImpl : public Light { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTransformation(FloatMatrix4&); - virtual Result SetColor(float r, float g, float b); + Result SetTransformation(FloatMatrix4&) override; + Result SetColor(float r, float g, float b) override; inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -250,7 +255,7 @@ class LightImpl : public Light { class MeshImpl : public Mesh { public: MeshImpl() : m_data(0) {} - ~MeshImpl() + ~MeshImpl() override { if (m_data) { delete m_data; @@ -258,20 +263,20 @@ class MeshImpl : public Mesh { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetColor(float r, float g, float b, float a); - virtual Result SetTexture(const Texture*); + Result SetColor(float r, float g, float b, float a) override; + Result SetTexture(const Texture*) override; // vtable+0x10 - virtual Result GetTexture(Texture*&); - virtual Result SetTextureMappingMode(ProjectionType); - virtual Result SetShadingModel(ShadingModel); - virtual Mesh* DeepClone(Unk*); + Result GetTexture(Texture*&) override; + Result SetTextureMappingMode(ProjectionType) override; + Result SetShadingModel(ShadingModel) override; + Mesh* DeepClone(Unk*) override; // vtable+0x20 - virtual Mesh* ShallowClone(Unk*); + Mesh* ShallowClone(Unk*) override; struct MeshData { IDirect3DRMMesh* groupMesh; @@ -290,7 +295,7 @@ class MeshImpl : public Mesh { class GroupImpl : public Group { public: GroupImpl() : m_data(0) {} - ~GroupImpl() + ~GroupImpl() override { if (m_data) { m_data->Release(); @@ -298,26 +303,28 @@ class GroupImpl : public Group { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTransformation(FloatMatrix4&); - virtual Result SetColor(float r, float g, float b, float a); + Result SetTransformation(FloatMatrix4&) override; + Result SetColor(float r, float g, float b, float a) override; // vtable+0x10 - virtual Result SetTexture(const Texture*); - virtual Result GetTexture(Texture*&); - virtual Result SetMaterialMode(MaterialMode); - virtual Result Add(const Mesh*); + Result SetTexture(const Texture*) override; + Result GetTexture(Texture*&) override; + Result SetMaterialMode(MaterialMode) override; + Result Add(const Mesh*) override; // vtable+0x20 - virtual Result Add(const Group*); - virtual Result Remove(const Mesh*); - virtual Result Remove(const Group*); - virtual Result RemoveAll(); + Result Add(const Group*) override; + Result Remove(const Mesh*) override; + Result Remove(const Group*) override; + Result RemoveAll() override; // vtable+0x30 - virtual Result Unknown(); + Result Unknown() override; + + inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } friend class RendererImpl; @@ -329,7 +336,7 @@ class GroupImpl : public Group { class UnkImpl : public Unk { public: UnkImpl() : m_data(0) {} - ~UnkImpl() + ~UnkImpl() override { if (m_data) { m_data->Release(); @@ -337,10 +344,10 @@ class UnkImpl : public Unk { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetMeshData( + Result SetMeshData( unsigned long faceCount, unsigned long vertexCount, const float (*pPositions)[3], @@ -348,11 +355,11 @@ class UnkImpl : public Unk { const float (*pTextureCoordinates)[2], unsigned long vertexPerFaceCount, unsigned long* pFaceData - ); - virtual Result GetBoundingBox(float min[3], float max[3]); + ) override; + Result GetBoundingBox(float min[3], float max[3]) override; // vtable+0x10 - virtual Unk* Clone(); + Unk* Clone() override; inline IDirect3DRMMesh* ImplementationData() const { return m_data; } @@ -389,7 +396,7 @@ class TglD3DRMIMAGE { class TextureImpl : public Texture { public: TextureImpl() : m_data(0) {} - ~TextureImpl() + ~TextureImpl() override { if (m_data) { m_data->Release(); @@ -397,23 +404,23 @@ class TextureImpl : public Texture { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels); - virtual void FillRowsOfTexture(int y, int height, void* pBuffer); + Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels) override; + void FillRowsOfTexture(int y, int height, void* pBuffer) override; // vtable+0x10 - virtual Result Changed(int texelsChanged, int paletteChanged); - virtual Result GetBufferAndPalette( + Result Changed(int texelsChanged, int paletteChanged) override; + Result GetBufferAndPalette( int* pWidth, int* pHeight, int* pDepth, void** ppBuffer, int* ppPaletteSize, PaletteEntry** ppPalette - ); - virtual Result SetPalette(int entryCount, PaletteEntry* entries); + ) override; + Result SetPalette(int entryCount, PaletteEntry* entries) override; inline IDirect3DRMTexture* ImplementationData() const { return m_data; } inline void SetImplementation(IDirect3DRMTexture* pData) { m_data = pData; } diff --git a/LEGO1/tgl/d3drm/light.cpp b/LEGO1/tgl/d3drm/light.cpp index dfc23b44..0fe66bfb 100644 --- a/LEGO1/tgl/d3drm/light.cpp +++ b/LEGO1/tgl/d3drm/light.cpp @@ -2,8 +2,8 @@ using namespace TglImpl; -DECOMP_SIZE_ASSERT(Light, 0x4); -DECOMP_SIZE_ASSERT(LightImpl, 0x8); +DECOMP_SIZE_ASSERT(Light, 0x04); +DECOMP_SIZE_ASSERT(LightImpl, 0x08); // FUNCTION: LEGO1 0x100a3770 void* LightImpl::ImplementationDataPtr() diff --git a/LEGO1/tgl/d3drm/mesh.cpp b/LEGO1/tgl/d3drm/mesh.cpp index f044d512..ceaf7079 100644 --- a/LEGO1/tgl/d3drm/mesh.cpp +++ b/LEGO1/tgl/d3drm/mesh.cpp @@ -4,8 +4,8 @@ using namespace TglImpl; DECOMP_SIZE_ASSERT(D3DRMVERTEX, 0x24); -DECOMP_SIZE_ASSERT(Mesh, 0x4); -DECOMP_SIZE_ASSERT(MeshImpl, 0x8); +DECOMP_SIZE_ASSERT(Mesh, 0x04); +DECOMP_SIZE_ASSERT(MeshImpl, 0x08); // FUNCTION: LEGO1 0x100a3ed0 void* MeshImpl::ImplementationDataPtr() diff --git a/LEGO1/tgl/d3drm/unk.cpp b/LEGO1/tgl/d3drm/unk.cpp index debc1484..038b0e9d 100644 --- a/LEGO1/tgl/d3drm/unk.cpp +++ b/LEGO1/tgl/d3drm/unk.cpp @@ -2,8 +2,8 @@ using namespace TglImpl; -DECOMP_SIZE_ASSERT(Unk, 0x4); -DECOMP_SIZE_ASSERT(UnkImpl, 0x8); +DECOMP_SIZE_ASSERT(Unk, 0x04); +DECOMP_SIZE_ASSERT(UnkImpl, 0x08); // FUNCTION: LEGO1 0x100a3830 void* UnkImpl::ImplementationDataPtr() diff --git a/LEGO1/tgl/d3drm/view.cpp b/LEGO1/tgl/d3drm/view.cpp index dcaa21ae..457c54d2 100644 --- a/LEGO1/tgl/d3drm/view.cpp +++ b/LEGO1/tgl/d3drm/view.cpp @@ -244,33 +244,40 @@ inline Result ViewPrepareFrameForRender( return result; } -// FUNCTION: LEGO1 0x100a2fd0 -Result ViewImpl::Render(const Light* pCamera) +inline Result ViewRender(IDirect3DRMViewport* pViewport, const IDirect3DRMFrame2* pGroup) { - ViewportAppData* appdata = ViewportGetData(m_data); + ViewportAppData* pViewportAppData; + Result result; - IDirect3DRMFrame2* light = static_cast(pCamera)->ImplementationData(); + pViewportAppData = reinterpret_cast(pViewport->GetAppData()); - IDirect3DRMFrame2* lastRendered = appdata->m_pLastRenderedFrame; - if (light != lastRendered) { - if (lastRendered) { - lastRendered->DeleteChild(appdata->m_pCamera); - // Some other call goes here, not sure what. - lastRendered->Release(); - } - appdata->m_pLastRenderedFrame = light; - if (light) { - light->SetSceneBackgroundRGB( - appdata->m_backgroundColorRed, - appdata->m_backgroundColorGreen, - appdata->m_backgroundColorBlue - ); - light->AddChild(appdata->m_pCamera); - // Some other call goes here, not sure what. - light->AddRef(); - } + if (pViewportAppData->m_pLastRenderedFrame != pGroup) { + result = ViewRestoreFrameAfterRender( + pViewportAppData->m_pLastRenderedFrame, + pViewportAppData->m_pCamera, + pViewportAppData->m_pLightFrame + ); + + pViewportAppData->m_pLastRenderedFrame = const_cast(pGroup); + + result = ViewPrepareFrameForRender( + pViewportAppData->m_pLastRenderedFrame, + pViewportAppData->m_pCamera, + pViewportAppData->m_pLightFrame, + pViewportAppData->m_backgroundColorRed, + pViewportAppData->m_backgroundColorGreen, + pViewportAppData->m_backgroundColorBlue + ); } - return ResultVal(m_data->Render(light)); + + result = ResultVal(pViewport->Render(const_cast(pGroup))); + return result; +} + +// FUNCTION: LEGO1 0x100a2fd0 +Result ViewImpl::Render(const Group* pGroup) +{ + return ViewRender(m_data, static_cast(pGroup)->ImplementationData()); } // FUNCTION: LEGO1 0x100a3080 diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index 630510b9..1067f863 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -101,6 +101,7 @@ class Unk; // VTABLE: LEGO1 0x100db980 class Object { public: + // FUNCTION: LEGO1 0x100a2240 virtual ~Object() {} virtual void* ImplementationDataPtr() = 0; @@ -146,6 +147,9 @@ class Renderer : public Object { // vtable+0x30 virtual Result SetTextureDefaultColorCount(unsigned long) = 0; + // SYNTHETIC: LEGO1 0x100a1770 + // Tgl::Renderer::~Renderer + // SYNTHETIC: LEGO1 0x100a17c0 // Tgl::Renderer::`scalar deleting destructor' }; @@ -170,6 +174,9 @@ class Device : public Object { virtual void InitFromD3DDevice(Device*) = 0; virtual void InitFromWindowsDevice(Device*) = 0; + // SYNTHETIC: LEGO1 0x100a2350 + // Tgl::Device::~Device + // SYNTHETIC: LEGO1 0x100a28e0 // Tgl::Device::`scalar deleting destructor' }; @@ -189,7 +196,7 @@ class View : public Object { // vtable+0x20 virtual Result GetBackgroundColor(float* r, float* g, float* b) = 0; virtual Result Clear() = 0; - virtual Result Render(const Light*) = 0; + virtual Result Render(const Group*) = 0; virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) = 0; // vtable+0x30 @@ -227,6 +234,9 @@ class View : public Object { int& rPickedGroupCount ) = 0; + // SYNTHETIC: LEGO1 0x100a2430 + // Tgl::View::~View + // SYNTHETIC: LEGO1 0x100a2950 // Tgl::View::`scalar deleting destructor' }; @@ -236,6 +246,9 @@ class Camera : public Object { public: virtual Result SetTransformation(FloatMatrix4&) = 0; + // SYNTHETIC: LEGO1 0x100a25f0 + // Tgl::Camera::~Camera + // SYNTHETIC: LEGO1 0x100a2a30 // Tgl::Camera::`scalar deleting destructor' }; @@ -246,6 +259,9 @@ class Light : public Object { virtual Result SetTransformation(FloatMatrix4&) = 0; virtual Result SetColor(float r, float g, float b) = 0; + // SYNTHETIC: LEGO1 0x100a26d0 + // Tgl::Light::~Light + // SYNTHETIC: LEGO1 0x100a2aa0 // Tgl::Light::`scalar deleting destructor' }; @@ -288,6 +304,9 @@ class Group : public Object { // to have been replaced by something else in the shipped code. virtual Result Unknown() = 0; + // SYNTHETIC: LEGO1 0x100a2510 + // Tgl::Group::~Group + // SYNTHETIC: LEGO1 0x100a29c0 // Tgl::Group::`scalar deleting destructor' }; @@ -310,6 +329,9 @@ class Unk : public Object { virtual Result GetBoundingBox(float min[3], float max[3]) = 0; virtual Unk* Clone() = 0; + // SYNTHETIC: LEGO1 0x100a27b0 + // Tgl::Unk::~Unk + // SYNTHETIC: LEGO1 0x100a2b10 // Tgl::Unk::`scalar deleting destructor' }; @@ -333,6 +355,9 @@ class Texture : public Object { ) = 0; virtual Result SetPalette(int entryCount, PaletteEntry* pEntries) = 0; + // SYNTHETIC: LEGO1 0x100a2890 + // Tgl::Texture::~Texture + // SYNTHETIC: LEGO1 0x100a2b80 // Tgl::Texture::`scalar deleting destructor' }; diff --git a/LEGO1/viewmanager/viewlodlist.h b/LEGO1/viewmanager/viewlodlist.h index df918350..d8516955 100644 --- a/LEGO1/viewmanager/viewlodlist.h +++ b/LEGO1/viewmanager/viewlodlist.h @@ -27,7 +27,7 @@ class ViewLODList : public LODList { protected: ViewLODList(size_t capacity); - ~ViewLODList(); + ~ViewLODList() override; public: inline int AddRef(); @@ -133,8 +133,9 @@ inline int ViewLODList::AddRef() inline int ViewLODList::Release() { assert(m_refCount > 0); - if (!--m_refCount) + if (!--m_refCount) { m_owner->Destroy(this); + } return m_refCount; } diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp index 3e7344d2..3e68f78e 100644 --- a/LEGO1/viewmanager/viewmanager.cpp +++ b/LEGO1/viewmanager/viewmanager.cpp @@ -1,5 +1,9 @@ #include "viewmanager.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(ViewManager, 0x1bc) + // STUB: LEGO1 0x100a5eb0 ViewManager::ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view) { diff --git a/LEGO1/viewmanager/viewmanager.h b/LEGO1/viewmanager/viewmanager.h index 8185c572..237a5f98 100644 --- a/LEGO1/viewmanager/viewmanager.h +++ b/LEGO1/viewmanager/viewmanager.h @@ -10,7 +10,7 @@ class ViewManager { ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view); virtual ~ViewManager(); - __declspec(dllexport) void RemoveAll(ViewROI*); + void RemoveAll(ViewROI*); void SetPOVSource(const OrientableROI* point_of_view); void SetResolution(int width, int height); @@ -20,8 +20,17 @@ class ViewManager { // SYNTHETIC: LEGO1 0x100a6000 // ViewManager::`scalar deleting destructor' + inline CompoundObject& GetUnknown0x08() { return m_unk0x08; } + + inline void AddToUnknown0x08(ViewROI* p_roi) { m_unk0x08.push_back(p_roi); } + private: - undefined m_pad[0x1b8]; + undefined4 m_unk0x04; // 0x04 + CompoundObject m_unk0x08; // 0x08 + undefined m_pad[0x1a8]; // 0x14 }; +// TEMPLATE: LEGO1 0x10022030 +// list >::insert + #endif // VIEWMANAGER_H diff --git a/LEGO1/viewmanager/viewroi.h b/LEGO1/viewmanager/viewroi.h index 8e6d78a9..544d3762 100644 --- a/LEGO1/viewmanager/viewroi.h +++ b/LEGO1/viewmanager/viewroi.h @@ -21,12 +21,15 @@ class ViewROI : public OrientableROI { SetLODList(lodList); geometry = pRenderer->CreateGroup(); } - inline ~ViewROI() + + // FUNCTION: LEGO1 0x100a9e20 + inline ~ViewROI() override { // SetLODList() will decrease refCount of LODList SetLODList(0); delete geometry; } + inline void SetLODList(ViewLODList* lodList) { // ??? inherently type unsafe - kind of... because, now, ROI @@ -34,28 +37,30 @@ class ViewROI : public OrientableROI { // solution: create pure virtual LODListBase* ROI::GetLODList() // and let derived ROI classes hold the LODList - if (m_lods) { - reinterpret_cast(m_lods)->Release(); + if (lods) { + reinterpret_cast(lods)->Release(); } - m_lods = lodList; + lods = lodList; - if (m_lods) { - reinterpret_cast(m_lods)->AddRef(); + if (lods) { + reinterpret_cast(lods)->AddRef(); } } - virtual float IntrinsicImportance() const override; // vtable+0x04 - virtual void VTable0x1c() override; // vtable+0x1c - virtual void SetLocalTransform(const Matrix4& p_transform) override; // vtable+0x20 - virtual void VTable0x24(const MxMatrix& p_transform) override; // vtable+0x24 - virtual const Tgl::Group* GetGeometry() const; // vtable+0x34 - virtual Tgl::Group* GetGeometry(); // vtable+0x30 + + float IntrinsicImportance() const override; // vtable+0x04 + void VTable0x1c() override; // vtable+0x1c + void SetLocalTransform(const Matrix4& p_transform) override; // vtable+0x20 + void VTable0x24(const MxMatrix& p_transform) override; // vtable+0x24 + virtual const Tgl::Group* GetGeometry() const; // vtable+0x34 + virtual Tgl::Group* GetGeometry(); // vtable+0x30 static undefined SetUnk101013d8(undefined p_flag); protected: - Tgl::Group* geometry; - void UpdateWorldData(const MxMatrix& parent2world); + void UpdateWorldData(const MxMatrix& parent2world) override; + + Tgl::Group* geometry; // 0xdc }; // SYNTHETIC: LEGO1 0x100aa250 diff --git a/tools/README.md b/tools/README.md index b24a8f50..6e6b046f 100644 --- a/tools/README.md +++ b/tools/README.md @@ -109,9 +109,9 @@ Classes should be annotated using the `SIZE` marker to indicate their size. If y // SIZE 0x1c class MxCriticalSection { public: - __declspec(dllexport) MxCriticalSection(); - __declspec(dllexport) ~MxCriticalSection(); - __declspec(dllexport) static void SetDoMutex(); + MxCriticalSection(); + ~MxCriticalSection(); + static void SetDoMutex(); ``` ## Member variables (**WIP**) diff --git a/tools/decomplint/decomplint.py b/tools/decomplint/decomplint.py old mode 100644 new mode 100755 index 2ceb42c2..cfe9155b --- a/tools/decomplint/decomplint.py +++ b/tools/decomplint/decomplint.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import os import sys import argparse @@ -92,8 +94,9 @@ def main(): would_fail = error_count > 0 or (warning_count > 0 and args.warnfail) if would_fail: - sys.exit(1) + return 1 + return 0 if __name__ == "__main__": - main() + raise SystemExit(main()) diff --git a/tools/isledecomp/isledecomp/bin.py b/tools/isledecomp/isledecomp/bin.py index 3b600af6..b103a143 100644 --- a/tools/isledecomp/isledecomp/bin.py +++ b/tools/isledecomp/isledecomp/bin.py @@ -1,6 +1,8 @@ import logging import struct -from typing import List, Optional +import bisect +from functools import cached_property +from typing import List, Optional, Tuple from dataclasses import dataclass from collections import namedtuple @@ -36,33 +38,44 @@ class InvalidVirtualAddressError(IndexError): ], ) +ImageSectionHeader = namedtuple( + "ImageSectionHeader", + [ + "name", + "virtual_size", + "virtual_address", + "size_of_raw_data", + "pointer_to_raw_data", + "pointer_to_relocations", + "pointer_to_line_numbers", + "number_of_relocations", + "number_of_line_numbers", + "characteristics", + ], +) + @dataclass -class ImageSectionHeader: - # pylint: disable=too-many-instance-attributes - # Most attributes are unused, but this is the struct format - name: bytes +class Section: + name: str virtual_size: int virtual_address: int - size_of_raw_data: int - pointer_to_raw_data: int - pointer_to_relocations: int - pointer_to_line_numbers: int - number_of_relocations: int - number_of_line_numbers: int - characteristics: int + view: memoryview - @property + @cached_property + def size_of_raw_data(self) -> int: + return len(self.view) + + @cached_property def extent(self): """Get the highest possible offset of this section""" return max(self.size_of_raw_data, self.virtual_size) def match_name(self, name: str) -> bool: - return self.name == struct.pack("8s", name.encode("ascii")) + return self.name == name def contains_vaddr(self, vaddr: int) -> bool: - ofs = vaddr - self.virtual_address - return 0 <= ofs < self.extent + return self.virtual_address <= vaddr < self.virtual_address + self.extent def addr_is_uninitialized(self, vaddr: int) -> bool: """We cannot rely on the IMAGE_SCN_CNT_UNINITIALIZED_DATA flag (0x80) in @@ -89,11 +102,11 @@ class Bin: def __init__(self, filename: str, find_str: bool = False) -> None: logger.debug('Parsing headers of "%s"... ', filename) self.filename = filename - self.file = None + self.view: memoryview = None self.imagebase = None self.entry = None - self.sections: List[ImageSectionHeader] = [] - self.last_section = None + self.sections: List[Section] = [] + self._section_vaddr: List[int] = [] self.find_str = find_str self._potential_strings = {} self._relocated_addrs = set() @@ -102,36 +115,51 @@ def __init__(self, filename: str, find_str: bool = False) -> None: def __enter__(self): logger.debug("Bin %s Enter", self.filename) - self.file = open(self.filename, "rb") + with open(self.filename, "rb") as f: + self.view = memoryview(f.read()) - (mz_str,) = struct.unpack("2s", self.file.read(2)) + (mz_str,) = struct.unpack("2s", self.view[0:2]) if mz_str != b"MZ": raise MZHeaderNotFoundError # Skip to PE header offset in MZ header. - self.file.seek(0x3C) - (pe_header_start,) = struct.unpack(" List[int]: return sorted(self._relocated_addrs) @@ -186,8 +210,8 @@ def _prepare_string_search(self): def is_ascii(b): return b" " <= b < b"\x7f" - sect_data = self._get_section_by_name(".data") - sect_rdata = self._get_section_by_name(".rdata") + sect_data = self.get_section_by_name(".data") + sect_rdata = self.get_section_by_name(".rdata") potentials = filter( lambda a: sect_data.contains_vaddr(a) or sect_rdata.contains_vaddr(a), self.get_relocated_addresses(), @@ -212,7 +236,8 @@ def _populate_relocations(self): One use case is to tell whether an immediate value in an operand represents a virtual address or just a big number.""" - ofs = self.get_section_offset_by_name(".reloc") + reloc = self.get_section_by_name(".reloc").view + ofs = 0 reloc_addrs = [] # Parse the structure in .reloc to get the list locations to check. @@ -223,12 +248,12 @@ def _populate_relocations(self): # If the entry read in is zero, we are at the end of this section and # these are padding bytes. while True: - (page_base, block_size) = struct.unpack("<2I", self.read(ofs, 8)) + (page_base, block_size) = struct.unpack("<2I", reloc[ofs : ofs + 8]) if block_size == 0: break # HACK: ignore the relocation type for now (the top 4 bits of the value). - values = list(struct.iter_unpack(" Section: section = next( filter(lambda section: section.match_name(name), self.sections), None, @@ -341,8 +355,12 @@ def _get_section_by_name(self, name: str): return section + def get_section_by_index(self, index: int) -> Section: + """Convert 1-based index into 0-based.""" + return self.sections[index - 1] + def get_section_extent_by_index(self, index: int) -> int: - return self.sections[index - 1].extent + return self.get_section_by_index(index).extent def get_section_offset_by_index(self, index: int) -> int: """The symbols output from cvdump gives addresses in this format: AAAA.BBBBBBBB @@ -350,14 +368,12 @@ def get_section_offset_by_index(self, index: int) -> int: This will return the virtual address for the start of the section at the given index so you can get the virtual address for whatever symbol you are looking at. """ - - section = self.sections[index - 1] - return section.virtual_address + return self.get_section_by_index(index).virtual_address def get_section_offset_by_name(self, name: str) -> int: """Same as above, but use the section name as the lookup""" - section = self._get_section_by_name(name) + section = self.get_section_by_name(name) return section.virtual_address def get_abs_addr(self, section: int, offset: int) -> int: @@ -365,35 +381,34 @@ def get_abs_addr(self, section: int, offset: int) -> int: into an absolute vaddr.""" return self.get_section_offset_by_index(section) + offset - def get_raw_addr(self, vaddr: int) -> int: - """Returns the raw offset in the PE binary for the given virtual address.""" - self._set_section_for_vaddr(vaddr) - return ( - vaddr - - self.last_section.virtual_address - + self.last_section.pointer_to_raw_data - ) + def get_relative_addr(self, addr: int) -> Tuple[int, int]: + """Convert an absolute address back into a (section, offset) pair.""" + i = bisect.bisect_right(self._section_vaddr, addr) - 1 + i = max(0, i) - def is_valid_section(self, section: int) -> bool: + section = self.sections[i] + if section.contains_vaddr(addr): + return (i + 1, addr - section.virtual_address) + + raise InvalidVirtualAddressError(f"{self.filename} : {hex(addr)}") + + def is_valid_section(self, section_id: int) -> bool: """The PDB will refer to sections that are not listed in the headers and so should ignore these references.""" try: - _ = self.sections[section - 1] + _ = self.get_section_by_index(section_id) return True except IndexError: return False def is_valid_vaddr(self, vaddr: int) -> bool: """Does this virtual address point to anything in the exe?""" - section = next( - filter( - lambda section: section.contains_vaddr(vaddr), - self.sections, - ), - None, - ) + try: + (_, __) = self.get_relative_addr(vaddr) + except InvalidVirtualAddressError: + return False - return section is not None + return True def read_string(self, offset: int, chunk_size: int = 1000) -> Optional[bytes]: """Read until we find a zero byte.""" @@ -407,23 +422,16 @@ def read_string(self, offset: int, chunk_size: int = 1000) -> Optional[bytes]: # No terminator found, just return what we have return b - def read(self, offset: int, size: int) -> Optional[bytes]: + def read(self, vaddr: int, size: int) -> Optional[bytes]: """Read (at most) the given number of bytes at the given virtual address. If we return None, the given address points to uninitialized data.""" - self._set_section_for_vaddr(offset) + (section_id, offset) = self.get_relative_addr(vaddr) + section = self.sections[section_id - 1] - if self.last_section.addr_is_uninitialized(offset): + if section.addr_is_uninitialized(vaddr): return None - raw_addr = self.get_raw_addr(offset) - self.file.seek(raw_addr) - # Clamp the read within the extent of the current section. # Reading off the end will most likely misrepresent the virtual addressing. - _size = min( - size, - self.last_section.pointer_to_raw_data - + self.last_section.size_of_raw_data - - raw_addr, - ) - return self.file.read(_size) + _size = min(size, section.size_of_raw_data - offset) + return bytes(section.view[offset : offset + _size]) diff --git a/tools/isledecomp/isledecomp/compare/asm/parse.py b/tools/isledecomp/isledecomp/compare/asm/parse.py index ef1ad2c2..35451fc6 100644 --- a/tools/isledecomp/isledecomp/compare/asm/parse.py +++ b/tools/isledecomp/isledecomp/compare/asm/parse.py @@ -1,14 +1,16 @@ """Converts x86 machine code into text (i.e. assembly). The end goal is to compare the code in the original and recomp binaries, using longest common subsequence (LCS), i.e. difflib.SequenceMatcher. -The capstone library takes the raw bytes and gives us the mnemnonic +The capstone library takes the raw bytes and gives us the mnemonic and operand(s) for each instruction. We need to "sanitize" the text further so that virtual addresses are replaced by symbol name or a generic placeholder string.""" import re +from functools import cache from typing import Callable, List, Optional, Tuple from collections import namedtuple +from isledecomp.bin import InvalidVirtualAddressError from capstone import Cs, CS_ARCH_X86, CS_MODE_32 disassembler = Cs(CS_ARCH_X86, CS_MODE_32) @@ -18,6 +20,7 @@ DisasmLiteInst = namedtuple("DisasmLiteInst", "address, size, mnemonic, op_str") +@cache def from_hex(string: str) -> Optional[int]: try: return int(string, 16) @@ -55,7 +58,11 @@ def is_relocated(self, addr: int) -> bool: def float_replace(self, addr: int, data_size: int) -> Optional[str]: if callable(self.float_lookup): - float_str = self.float_lookup(addr, data_size) + try: + float_str = self.float_lookup(addr, data_size) + except InvalidVirtualAddressError: + # probably caused by reading an invalid instruction + return None if float_str is not None: return f"{float_str} (FLOAT)" @@ -92,6 +99,9 @@ def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]: # Nothing to sanitize return (inst.mnemonic, "") + if "0x" not in inst.op_str: + return (inst.mnemonic, inst.op_str) + # For jumps or calls, if the entire op_str is a hex number, the value # is a relative offset. # Otherwise (i.e. it looks like `dword ptr [address]`) it is an @@ -162,32 +172,33 @@ def float_ptr_replace(match): else: op_str = ptr_replace_regex.sub(filter_out_ptr, inst.op_str) + def replace_immediate(chunk: str) -> str: + if (inttest := from_hex(chunk)) is not None: + # If this value is a virtual address, it is referenced absolutely, + # which means it must be in the relocation table. + if self.is_relocated(inttest): + return self.replace(inttest) + + return chunk + # Performance hack: # Skip this step if there is nothing left to consider replacing. if "0x" in op_str: # Replace immediate values with name or placeholder (where appropriate) - words = op_str.split(", ") - for i, word in enumerate(words): - try: - inttest = int(word, 16) - # If this value is a virtual address, it is referenced absolutely, - # which means it must be in the relocation table. - if self.is_relocated(inttest): - words[i] = self.replace(inttest) - except ValueError: - pass - op_str = ", ".join(words) + op_str = ", ".join(map(replace_immediate, op_str.split(", "))) return inst.mnemonic, op_str def parse_asm(self, data: bytes, start_addr: Optional[int] = 0) -> List[str]: asm = [] - for inst in disassembler.disasm_lite(data, start_addr): + for raw_inst in disassembler.disasm_lite(data, start_addr): # Use heuristics to disregard some differences that aren't representative # of the accuracy of a function (e.g. global offsets) - result = self.sanitize(DisasmLiteInst(*inst)) + inst = DisasmLiteInst(*raw_inst) + result = self.sanitize(inst) + # mnemonic + " " + op_str - asm.append(" ".join(result)) + asm.append((hex(inst.address), " ".join(result))) return asm diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index 84f9131f..de332e43 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -12,6 +12,7 @@ from isledecomp.types import SymbolType from isledecomp.compare.asm import ParseAsm, can_resolve_register_differences from .db import CompareDb, MatchInfo +from .diff import combined_diff from .lines import LinesDb @@ -20,6 +21,7 @@ @dataclass class DiffReport: + # pylint: disable=too-many-instance-attributes match_type: SymbolType orig_addr: int recomp_addr: int @@ -27,6 +29,7 @@ class DiffReport: udiff: Optional[List[str]] = None ratio: float = 0.0 is_effective_match: bool = False + is_stub: bool = False @property def effective_ratio(self) -> float: @@ -130,11 +133,29 @@ def _load_cvdump(self): raw = self.recomp_bin.read(addr, sym.size()) try: - sym.friendly_name = raw.decode("latin1").rstrip("\x00") + # We use the string length reported in the mangled symbol as the + # data size, but this is not always accurate with respect to the + # null terminator. + # e.g. ??_C@_0BA@EFDM@MxObjectFactory?$AA@ + # reported length: 16 (includes null terminator) + # c.f. ??_C@_03DPKJ@enz?$AA@ + # reported length: 3 (does NOT include terminator) + # This will handle the case where the entire string contains "\x00" + # because those are distinct from the empty string of length 0. + decoded_string = raw.decode("latin1") + rstrip_string = decoded_string.rstrip("\x00") + + if decoded_string != "" and rstrip_string != "": + sym.friendly_name = rstrip_string + else: + sym.friendly_name = decoded_string + except UnicodeDecodeError: pass - self._db.set_recomp_symbol(addr, sym.node_type, sym.name(), sym.size()) + self._db.set_recomp_symbol( + addr, sym.node_type, sym.name(), sym.decorated_name, sym.size() + ) for lineref in cv.lines: addr = self.recomp_bin.get_abs_addr(lineref.section, lineref.offset) @@ -160,15 +181,20 @@ def _load_markers(self): if recomp_addr is not None: self._db.set_function_pair(fun.offset, recomp_addr) if fun.should_skip(): - self._db.skip_compare(fun.offset) + self._db.mark_stub(fun.offset) for fun in codebase.iter_name_functions(): self._db.match_function(fun.offset, fun.name) if fun.should_skip(): - self._db.skip_compare(fun.offset) + self._db.mark_stub(fun.offset) for var in codebase.iter_variables(): - self._db.match_variable(var.offset, var.name) + if var.is_static and var.parent_function is not None: + self._db.match_static_variable( + var.offset, var.name, var.parent_function + ) + else: + self._db.match_variable(var.offset, var.name) for tbl in codebase.iter_vtables(): self._db.match_vtable(tbl.offset, tbl.name) @@ -248,15 +274,6 @@ def _match_thunks(self): self._db.skip_compare(thunk_from_orig) def _compare_function(self, match: MatchInfo) -> DiffReport: - if match.size == 0: - # Report a failed match to make the user aware of the empty function. - return DiffReport( - match_type=SymbolType.FUNCTION, - orig_addr=match.orig_addr, - recomp_addr=match.recomp_addr, - name=match.name, - ) - orig_raw = self.orig_bin.read(match.orig_addr, match.size) recomp_raw = self.recomp_bin.read(match.recomp_addr, match.size) @@ -291,8 +308,12 @@ def recomp_lookup(addr: int) -> Optional[str]: float_lookup=recomp_float, ) - orig_asm = orig_parse.parse_asm(orig_raw, match.orig_addr) - recomp_asm = recomp_parse.parse_asm(recomp_raw, match.recomp_addr) + orig_combined = orig_parse.parse_asm(orig_raw, match.orig_addr) + recomp_combined = recomp_parse.parse_asm(recomp_raw, match.recomp_addr) + + # Detach addresses from asm lines for the text diff. + orig_asm = [x[1] for x in orig_combined] + recomp_asm = [x[1] for x in recomp_combined] diff = difflib.SequenceMatcher(None, orig_asm, recomp_asm) ratio = diff.ratio() @@ -301,7 +322,9 @@ def recomp_lookup(addr: int) -> Optional[str]: # Check whether we can resolve register swaps which are actually # perfect matches modulo compiler entropy. is_effective_match = can_resolve_register_differences(orig_asm, recomp_asm) - unified_diff = difflib.unified_diff(orig_asm, recomp_asm, n=10) + unified_diff = combined_diff( + diff, orig_combined, recomp_combined, context_size=10 + ) else: is_effective_match = False unified_diff = [] @@ -336,9 +359,7 @@ def _compare_vtable(self, match: MatchInfo) -> DiffReport: [t for (t,) in struct.iter_unpack(" str: + def match_text(m: Optional[MatchInfo], raw_addr: Optional[int] = None) -> str: """Format the function reference at this vtable index as text. If we have not identified this function, we have the option to display the raw address. This is only worth doing for the original addr @@ -347,19 +368,18 @@ def match_text( should override the given function from the superclass, but we have not implemented this yet. """ - index = f"vtable0x{i*4:02x}" if m is not None: orig = hex(m.orig_addr) if m.orig_addr is not None else "no orig" recomp = ( hex(m.recomp_addr) if m.recomp_addr is not None else "no recomp" ) - return f"{index:>12} : ({orig:10} / {recomp:10}) : {m.name}" + return f"({orig} / {recomp}) : {m.name}" if raw_addr is not None: - return f"{index:>12} : 0x{raw_addr:x} from orig not annotated." + return f"0x{raw_addr:x} from orig not annotated." - return f"{index:>12} : (no match)" + return "(no match)" orig_text = [] recomp_text = [] @@ -379,14 +399,22 @@ def match_text( ratio += 1 n_entries += 1 - orig_text.append(match_text(i, orig, raw_orig)) - recomp_text.append(match_text(i, recomp)) + index = f"vtable0x{i*4:02x}" + orig_text.append((index, match_text(orig, raw_orig))) + recomp_text.append((index, match_text(recomp))) ratio = ratio / float(n_entries) if n_entries > 0 else 0 # n=100: Show the entire table if there is a diff to display. # Otherwise it would be confusing if the table got cut off. - unified_diff = difflib.unified_diff(orig_text, recomp_text, n=100) + + sm = difflib.SequenceMatcher( + None, + [x[1] for x in orig_text], + [x[1] for x in recomp_text], + ) + + unified_diff = combined_diff(sm, orig_text, recomp_text, context_size=100) return DiffReport( match_type=SymbolType.VTABLE, @@ -399,6 +427,23 @@ def match_text( def _compare_match(self, match: MatchInfo) -> Optional[DiffReport]: """Router for comparison type""" + + if match.size == 0: + return None + + options = self._db.get_match_options(match.orig_addr) + if options.get("skip", False): + return None + + if options.get("stub", False): + return DiffReport( + match_type=match.compare_type, + orig_addr=match.orig_addr, + recomp_addr=match.recomp_addr, + name=match.name, + is_stub=True, + ) + if match.compare_type == SymbolType.FUNCTION: return self._compare_function(match) @@ -409,6 +454,9 @@ def _compare_match(self, match: MatchInfo) -> Optional[DiffReport]: ## Public API + def get_all(self) -> List[MatchInfo]: + return self._db.get_all() + def get_functions(self) -> List[MatchInfo]: return self._db.get_matches_by_type(SymbolType.FUNCTION) @@ -430,7 +478,9 @@ def compare_all(self) -> Iterable[DiffReport]: def compare_functions(self) -> Iterable[DiffReport]: for match in self.get_functions(): - yield self._compare_match(match) + diff = self._compare_match(match) + if diff is not None: + yield diff def compare_variables(self): pass @@ -443,4 +493,6 @@ def compare_strings(self): def compare_vtables(self) -> Iterable[DiffReport]: for match in self.get_vtables(): - yield self._compare_match(match) + diff = self._compare_match(match) + if diff is not None: + yield self._compare_match(match) diff --git a/tools/isledecomp/isledecomp/compare/db.py b/tools/isledecomp/isledecomp/compare/db.py index 43d6811b..7e0546b8 100644 --- a/tools/isledecomp/isledecomp/compare/db.py +++ b/tools/isledecomp/isledecomp/compare/db.py @@ -7,16 +7,33 @@ _SETUP_SQL = """ DROP TABLE IF EXISTS `symbols`; + DROP TABLE IF EXISTS `match_options`; + CREATE TABLE `symbols` ( compare_type int, orig_addr int, recomp_addr int, name text, - size int, - should_skip int default(FALSE) + decorated_name text, + size int ); + + CREATE TABLE `match_options` ( + addr int not null, + name text not null, + value text, + primary key (addr, name) + ) without rowid; + + CREATE VIEW IF NOT EXISTS `match_info` + (compare_type, orig_addr, recomp_addr, name, size) AS + SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + ORDER BY orig_addr NULLS LAST; + CREATE INDEX `symbols_or` ON `symbols` (orig_addr); CREATE INDEX `symbols_re` ON `symbols` (recomp_addr); + CREATE INDEX `symbols_na` ON `symbols` (name); """ @@ -64,12 +81,18 @@ def set_recomp_symbol( addr: int, compare_type: Optional[SymbolType], name: Optional[str], + decorated_name: Optional[str], size: Optional[int], ): + # Ignore collisions here. The same recomp address can have + # multiple names (e.g. _strlwr and __strlwr) + if self.recomp_used(addr): + return + compare_value = compare_type.value if compare_type is not None else None self._db.execute( - "INSERT INTO `symbols` (recomp_addr, compare_type, name, size) VALUES (?,?,?,?)", - (addr, compare_value, name, size), + "INSERT INTO `symbols` (recomp_addr, compare_type, name, decorated_name, size) VALUES (?,?,?,?,?)", + (addr, compare_value, name, decorated_name, size), ) def get_unmatched_strings(self) -> List[str]: @@ -82,14 +105,17 @@ def get_unmatched_strings(self) -> List[str]: return [string for (string,) in cur.fetchall()] + def get_all(self) -> List[MatchInfo]: + cur = self._db.execute("SELECT * FROM `match_info`") + cur.row_factory = matchinfo_factory + + return cur.fetchall() + def get_matches(self) -> Optional[MatchInfo]: cur = self._db.execute( - """SELECT compare_type, orig_addr, recomp_addr, name, size - FROM `symbols` + """SELECT * FROM `match_info` WHERE orig_addr IS NOT NULL AND recomp_addr IS NOT NULL - AND should_skip IS FALSE - ORDER BY orig_addr """, ) cur.row_factory = matchinfo_factory @@ -98,11 +124,9 @@ def get_matches(self) -> Optional[MatchInfo]: def get_one_match(self, addr: int) -> Optional[MatchInfo]: cur = self._db.execute( - """SELECT compare_type, orig_addr, recomp_addr, name, size - FROM `symbols` + """SELECT * FROM `match_info` WHERE orig_addr = ? AND recomp_addr IS NOT NULL - AND should_skip IS FALSE """, (addr,), ) @@ -111,8 +135,7 @@ def get_one_match(self, addr: int) -> Optional[MatchInfo]: def get_by_orig(self, addr: int) -> Optional[MatchInfo]: cur = self._db.execute( - """SELECT compare_type, orig_addr, recomp_addr, name, size - FROM `symbols` + """SELECT * FROM `match_info` WHERE orig_addr = ? """, (addr,), @@ -122,8 +145,7 @@ def get_by_orig(self, addr: int) -> Optional[MatchInfo]: def get_by_recomp(self, addr: int) -> Optional[MatchInfo]: cur = self._db.execute( - """SELECT compare_type, orig_addr, recomp_addr, name, size - FROM `symbols` + """SELECT * FROM `match_info` WHERE recomp_addr = ? """, (addr,), @@ -133,13 +155,10 @@ def get_by_recomp(self, addr: int) -> Optional[MatchInfo]: def get_matches_by_type(self, compare_type: SymbolType) -> List[MatchInfo]: cur = self._db.execute( - """SELECT compare_type, orig_addr, recomp_addr, name, size - FROM `symbols` + """SELECT * FROM `match_info` WHERE compare_type = ? AND orig_addr IS NOT NULL AND recomp_addr IS NOT NULL - AND should_skip IS FALSE - ORDER BY orig_addr """, (compare_type.value,), ) @@ -147,9 +166,21 @@ def get_matches_by_type(self, compare_type: SymbolType) -> List[MatchInfo]: return cur.fetchall() + def orig_used(self, addr: int) -> bool: + cur = self._db.execute("SELECT 1 FROM symbols WHERE orig_addr = ?", (addr,)) + return cur.fetchone() is not None + + def recomp_used(self, addr: int) -> bool: + cur = self._db.execute("SELECT 1 FROM symbols WHERE recomp_addr = ?", (addr,)) + return cur.fetchone() is not None + def set_pair( self, orig: int, recomp: int, compare_type: Optional[SymbolType] = None ) -> bool: + if self.orig_used(orig): + logger.error("Original address %s not unique!", hex(orig)) + return False + compare_value = compare_type.value if compare_type is not None else None cur = self._db.execute( "UPDATE `symbols` SET orig_addr = ?, compare_type = ? WHERE recomp_addr = ?", @@ -160,14 +191,90 @@ def set_pair( def set_function_pair(self, orig: int, recomp: int) -> bool: """For lineref match or _entry""" - self.set_pair(orig, recomp, SymbolType.FUNCTION) - # TODO: Both ways required? + return self.set_pair(orig, recomp, SymbolType.FUNCTION) + + def _set_opt_bool(self, addr: int, option: str, enabled: bool = True): + if enabled: + self._db.execute( + """INSERT OR IGNORE INTO `match_options` + (addr, name) + VALUES (?, ?)""", + (addr, option), + ) + else: + self._db.execute( + """DELETE FROM `match_options` WHERE addr = ? AND name = ?""", + (addr, option), + ) + + def mark_stub(self, orig: int): + self._set_opt_bool(orig, "stub") def skip_compare(self, orig: int): - self._db.execute( - "UPDATE `symbols` SET should_skip = TRUE WHERE orig_addr = ?", (orig,) + self._set_opt_bool(orig, "skip") + + def get_match_options(self, addr: int) -> Optional[dict]: + cur = self._db.execute( + """SELECT name, value FROM `match_options` WHERE addr = ?""", (addr,) ) + return { + option: value if value is not None else True + for (option, value) in cur.fetchall() + } + + def _find_potential_match( + self, name: str, compare_type: SymbolType + ) -> Optional[int]: + """Name lookup""" + match_decorate = compare_type != SymbolType.STRING and name.startswith("?") + if match_decorate: + sql = """ + SELECT recomp_addr + FROM `symbols` + WHERE orig_addr IS NULL + AND decorated_name = ? + AND (compare_type IS NULL OR compare_type = ?) + LIMIT 1 + """ + else: + sql = """ + SELECT recomp_addr + FROM `symbols` + WHERE orig_addr IS NULL + AND name = ? + AND (compare_type IS NULL OR compare_type = ?) + LIMIT 1 + """ + + row = self._db.execute(sql, (name, compare_type.value)).fetchone() + return row[0] if row is not None else None + + def _find_static_variable( + self, variable_name: str, function_sym: str + ) -> Optional[int]: + """Get the recomp address of a static function variable. + Matches using a LIKE clause on the combination of: + 1. The variable name read from decomp marker. + 2. The decorated name of the enclosing function. + For example, the variable "g_startupDelay" from function "IsleApp::Tick" + has symbol: `?g_startupDelay@?1??Tick@IsleApp@@QAEXH@Z@4HA` + The function's decorated name is: `?Tick@IsleApp@@QAEXH@Z`""" + + row = self._db.execute( + """SELECT recomp_addr FROM `symbols` + WHERE decorated_name LIKE '%' || ? || '%' || ? || '%' + AND orig_addr IS NULL + AND (compare_type = ? OR compare_type = ? OR compare_type IS NULL)""", + ( + variable_name, + function_sym, + SymbolType.DATA.value, + SymbolType.POINTER.value, + ), + ).fetchone() + return row[0] if row is not None else None + def _match_on(self, compare_type: SymbolType, addr: int, name: str) -> bool: # Update the compare_type here too since the marker tells us what we should do @@ -177,16 +284,11 @@ def _match_on(self, compare_type: SymbolType, addr: int, name: str) -> bool: name = name[:255] logger.debug("Looking for %s %s", compare_type.name.lower(), name) - cur = self._db.execute( - """UPDATE `symbols` - SET orig_addr = ?, compare_type = ? - WHERE name = ? - AND orig_addr IS NULL - AND (compare_type = ? OR compare_type IS NULL)""", - (addr, compare_type.value, name, compare_type.value), - ) + recomp_addr = self._find_potential_match(name, compare_type) + if recomp_addr is None: + return False - return cur.rowcount > 0 + return self.set_pair(addr, recomp_addr, compare_type) def match_function(self, addr: int, name: str) -> bool: did_match = self._match_on(SymbolType.FUNCTION, addr, name) @@ -202,6 +304,39 @@ def match_vtable(self, addr: int, name: str) -> bool: return did_match + def match_static_variable(self, addr: int, name: str, function_addr: int) -> bool: + """Matching a static function variable by combining the variable name + with the decorated (mangled) name of its parent function.""" + + cur = self._db.execute( + """SELECT name, decorated_name + FROM `symbols` + WHERE orig_addr = ?""", + (function_addr,), + ) + + if (result := cur.fetchone()) is None: + logger.error("No function for static variable: %s", name) + return False + + # Get the friendly name for the "failed to match" error message + (function_name, decorated_name) = result + + recomp_addr = self._find_static_variable(name, decorated_name) + if recomp_addr is not None: + # TODO: This variable could be a pointer, but I don't think we + # have a way to tell that right now. + if self.set_pair(addr, recomp_addr, SymbolType.DATA): + return True + + logger.error( + "Failed to match static variable %s from function %s", + name, + function_name, + ) + + return False + def match_variable(self, addr: int, name: str) -> bool: did_match = self._match_on(SymbolType.DATA, addr, name) or self._match_on( SymbolType.POINTER, addr, name diff --git a/tools/isledecomp/isledecomp/compare/diff.py b/tools/isledecomp/isledecomp/compare/diff.py new file mode 100644 index 00000000..ad453191 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/diff.py @@ -0,0 +1,98 @@ +from difflib import SequenceMatcher +from typing import Dict, List, Tuple + +CombinedDiffInput = List[Tuple[str, str]] +CombinedDiffOutput = List[Tuple[str, List[Dict[str, Tuple[str, str]]]]] + + +def combined_diff( + diff: SequenceMatcher, + orig_combined: CombinedDiffInput, + recomp_combined: CombinedDiffInput, + context_size: int = 3, +) -> CombinedDiffOutput: + """We want to diff the original and recomp assembly. The "combined" assembly + input has two components: the address of the instruction and the assembly text. + We have already diffed the text only. This is the SequenceMatcher object. + The SequenceMatcher can generate "opcodes" that describe how to turn "Text A" + into "Text B". These refer to list indices of the original arrays, so we can + use those to create the final diff and include the address for each line of assembly. + This is almost the same procedure as the difflib.unified_diff function, but we + are reusing the already generated SequenceMatcher object. + """ + + unified_diff = [] + + for group in diff.get_grouped_opcodes(context_size): + subgroups = [] + + # Keep track of the addresses we've seen in this diff group. + # This helps create the "@@" line. (Does this have a name?) + # Do it this way because not every line in each list will have an + # address. If our context begins or ends on a line that does not + # have one, we will have an incomplete range string. + orig_addrs = set() + recomp_addrs = set() + + first, last = group[0], group[-1] + orig_range = len(orig_combined[first[1] : last[2]]) + recomp_range = len(recomp_combined[first[3] : last[4]]) + + for code, i1, i2, j1, j2 in group: + if code == "equal": + # The sections are equal, so the list slices are guaranteed + # to have the same length. We only need the diffed value (asm text) + # from one of the lists, but we need the addresses from both. + # Use zip to put the two lists together and then take out what we want. + both = [ + (a, b, c) + for ((a, b), (c, _)) in zip( + orig_combined[i1:i2], recomp_combined[j1:j2] + ) + ] + + for orig_addr, _, recomp_addr in both: + if orig_addr is not None: + orig_addrs.add(orig_addr) + + if recomp_addr is not None: + recomp_addrs.add(recomp_addr) + + subgroups.append({"both": both}) + else: + for orig_addr, _ in orig_combined[i1:i2]: + if orig_addr is not None: + orig_addrs.add(orig_addr) + + for recomp_addr, _ in recomp_combined[j1:j2]: + if recomp_addr is not None: + recomp_addrs.add(recomp_addr) + + subgroups.append( + { + "orig": orig_combined[i1:i2], + "recomp": recomp_combined[j1:j2], + } + ) + + orig_sorted = sorted(orig_addrs) + recomp_sorted = sorted(recomp_addrs) + + # We could get a diff group that has no original addresses. + # This might happen for a stub function where we are not able to + # produce even a single instruction from the original. + # In that case, show the best slug line that we can. + def peek_front(list_, default=""): + try: + return list_[0] + except IndexError: + return default + + orig_first = peek_front(orig_sorted) + recomp_first = peek_front(recomp_sorted) + + diff_slug = f"@@ -{orig_first},{orig_range} +{recomp_first},{recomp_range} @@" + + unified_diff.append((diff_slug, subgroups)) + + return unified_diff diff --git a/tools/isledecomp/isledecomp/compare/lines.py b/tools/isledecomp/isledecomp/compare/lines.py index ced3c117..0e9c4332 100644 --- a/tools/isledecomp/isledecomp/compare/lines.py +++ b/tools/isledecomp/isledecomp/compare/lines.py @@ -2,6 +2,7 @@ between FUNCTION markers and PDB analysis.""" import sqlite3 import logging +from functools import cache from typing import Optional from pathlib import Path from isledecomp.dir import PathResolver @@ -22,6 +23,16 @@ logger = logging.getLogger(__name__) +@cache +def my_samefile(path: str, source_path: str) -> bool: + return Path(path).samefile(source_path) + + +@cache +def my_basename_lower(path: str) -> str: + return Path(path).name.lower() + + class LinesDb: def __init__(self, code_dir) -> None: self._db = sqlite3.connect(":memory:") @@ -31,7 +42,7 @@ def __init__(self, code_dir) -> None: def add_line(self, path: str, line_no: int, addr: int): """To be added from the LINES section of cvdump.""" sourcepath = self._path_resolver.resolve_cvdump(path) - filename = Path(sourcepath).name.lower() + filename = my_basename_lower(sourcepath) self._db.execute( "INSERT INTO `lineref` (path, filename, line, addr) VALUES (?,?,?,?)", @@ -41,13 +52,13 @@ def add_line(self, path: str, line_no: int, addr: int): def search_line(self, path: str, line_no: int) -> Optional[int]: """Using path and line number from FUNCTION marker, get the address of this function in the recomp.""" - filename = Path(path).name.lower() + filename = my_basename_lower(path) cur = self._db.execute( "SELECT path, addr FROM `lineref` WHERE filename = ? AND line = ?", (filename, line_no), ) for source_path, addr in cur.fetchall(): - if Path(path).samefile(source_path): + if my_samefile(path, source_path): return addr logger.error( diff --git a/tools/isledecomp/isledecomp/cvdump/demangler.py b/tools/isledecomp/isledecomp/cvdump/demangler.py index 07fca42f..10984bff 100644 --- a/tools/isledecomp/isledecomp/cvdump/demangler.py +++ b/tools/isledecomp/isledecomp/cvdump/demangler.py @@ -68,4 +68,9 @@ def demangle_vtable(symbol: str) -> str: return f"{class_name}<{generic}>" + # If we have two classes listed, it is a namespace hierarchy. + # @@6B@ is a common generic suffix for these vtable symbols. + if t[1] != "" and t[1] != "6B": + return t[1] + "::" + t[0] + return t[0] diff --git a/tools/isledecomp/isledecomp/cvdump/parser.py b/tools/isledecomp/isledecomp/cvdump/parser.py index d14abe88..8d1c71bb 100644 --- a/tools/isledecomp/isledecomp/cvdump/parser.py +++ b/tools/isledecomp/isledecomp/cvdump/parser.py @@ -39,6 +39,9 @@ r"S_GDATA32: \[(?P
\w{4}):(?P\w{8})\], Type:\s*(?P\S+), (?P.+)" ) +# e.g. 0003 "CMakeFiles/isle.dir/ISLE/res/isle.rc.res" +# e.g. 0004 "C:\work\lego-island\isle\3rdparty\smartheap\SHLW32MT.LIB" "check.obj" +_module_regex = re.compile(r"(?P\w{4})(?: \"(?P.+?)\")?(?: \"(?P.+?)\")") # User functions only LinesEntry = namedtuple("LinesEntry", "filename line_no section offset") @@ -52,13 +55,16 @@ SymbolsEntry = namedtuple("SymbolsEntry", "type section offset size name") # (Estimated) size of any symbol -SizeRefEntry = namedtuple("SizeRefEntry", "section offset size") +SizeRefEntry = namedtuple("SizeRefEntry", "module section offset size") # global variables GdataEntry = namedtuple("GdataEntry", "section offset type name") +ModuleEntry = namedtuple("ModuleEntry", "id lib obj") + class CvdumpParser: + # pylint: disable=too-many-instance-attributes def __init__(self) -> None: self._section: str = "" self._lines_function: Tuple[str, int] = ("", 0) @@ -68,6 +74,7 @@ def __init__(self) -> None: self.symbols = [] self.sizerefs = [] self.globals = [] + self.modules = [] def _lines_section(self, line: str): """Parsing entries from the LINES section. We only care about the pairs of @@ -144,12 +151,26 @@ def _section_contributions(self, line: str): if (match := _section_contrib_regex.match(line)) is not None: self.sizerefs.append( SizeRefEntry( + module=int(match.group("module"), 16), section=int(match.group("section"), 16), offset=int(match.group("offset"), 16), size=int(match.group("size"), 16), ) ) + def _modules_section(self, line: str): + """Record the object file (and lib file, if used) linked into the binary. + The auto-incrementing id is cross-referenced in SECTION CONTRIBUTIONS + (and perhaps other locations)""" + if (match := _module_regex.match(line)) is not None: + self.modules.append( + ModuleEntry( + id=int(match.group("id"), 16), + lib=match.group("lib"), + obj=match.group("obj"), + ) + ) + def read_line(self, line: str): # Blank lines are there to help the reader; they have no context significance if line.strip() == "": @@ -174,6 +195,9 @@ def read_line(self, line: str): elif self._section == "GLOBALS": self._globals_section(line) + elif self._section == "MODULES": + self._modules_section(line) + def read_lines(self, lines: Iterable[str]): for line in lines: self.read_line(line) diff --git a/tools/isledecomp/isledecomp/cvdump/runner.py b/tools/isledecomp/isledecomp/cvdump/runner.py index f1c163b5..6b2c2ff4 100644 --- a/tools/isledecomp/isledecomp/cvdump/runner.py +++ b/tools/isledecomp/isledecomp/cvdump/runner.py @@ -13,6 +13,7 @@ class DumpOpt(Enum): GLOBALS = 2 PUBLICS = 3 SECTION_CONTRIB = 4 + MODULES = 5 cvdump_opt_map = { @@ -21,6 +22,7 @@ class DumpOpt(Enum): DumpOpt.GLOBALS: "-g", DumpOpt.PUBLICS: "-p", DumpOpt.SECTION_CONTRIB: "-seccontrib", + DumpOpt.MODULES: "-m", } @@ -49,6 +51,10 @@ def section_contributions(self): self._options.add(DumpOpt.SECTION_CONTRIB) return self + def modules(self): + self._options.add(DumpOpt.MODULES) + return self + def cmd_line(self) -> List[str]: cvdump_exe = lib_path_join("cvdump.exe") flags = [cvdump_opt_map[opt] for opt in self._options] diff --git a/tools/isledecomp/isledecomp/parser/error.py b/tools/isledecomp/isledecomp/parser/error.py index 81123381..9ced1498 100644 --- a/tools/isledecomp/isledecomp/parser/error.py +++ b/tools/isledecomp/isledecomp/parser/error.py @@ -47,6 +47,10 @@ class ParserError(Enum): # to ignore things like string literal that are not variables. GLOBAL_NOT_VARIABLE = 111 + # WARN: A marked static variable inside a function needs to have its + # function marked too, and in the same module. + ORPHANED_STATIC_VARIABLE = 112 + # This code or higher is an error, not a warning DECOMP_ERROR_START = 200 @@ -74,6 +78,11 @@ class ParserError(Enum): # they annotate are different. WRONG_STRING = 205 + # ERROR: This lineref FUNCTION marker is next to a function declaration or + # forward reference. The correct place for the marker is where the function + # is implemented so we can match with the PDB. + NO_IMPLEMENTATION = 206 + @dataclass class ParserAlert: diff --git a/tools/isledecomp/isledecomp/parser/node.py b/tools/isledecomp/isledecomp/parser/node.py index 71d4ebdd..eeaed713 100644 --- a/tools/isledecomp/isledecomp/parser/node.py +++ b/tools/isledecomp/isledecomp/parser/node.py @@ -50,6 +50,7 @@ def is_nameref(self) -> bool: @dataclass class ParserVariable(ParserSymbol): is_static: bool = False + parent_function: Optional[int] = None @dataclass diff --git a/tools/isledecomp/isledecomp/parser/parser.py b/tools/isledecomp/isledecomp/parser/parser.py index 3c955fc3..2e5daf07 100644 --- a/tools/isledecomp/isledecomp/parser/parser.py +++ b/tools/isledecomp/isledecomp/parser/parser.py @@ -8,9 +8,12 @@ get_synthetic_name, remove_trailing_comment, get_string_contents, + sanitize_code_line, + scopeDetectRegex, ) from .marker import ( DecompMarker, + MarkerCategory, match_marker, is_marker_exact, ) @@ -51,6 +54,9 @@ def insert(self, marker: DecompMarker) -> bool: self.markers[key] = marker return False + def query(self, category: MarkerCategory, module: str) -> Optional[DecompMarker]: + return self.markers.get((category, module)) + def iter(self) -> Iterator[DecompMarker]: for _, marker in self.markers.items(): yield marker @@ -59,6 +65,57 @@ def empty(self): self.markers = {} +class CurlyManager: + """Overly simplified scope manager""" + + def __init__(self): + self._stack = [] + + def reset(self): + self._stack = [] + + def _pop(self): + """Pop stack safely""" + try: + self._stack.pop() + except IndexError: + pass + + def get_prefix(self, name: Optional[str] = None) -> str: + """Return the prefix for where we are.""" + + scopes = [t for t in self._stack if t != "{"] + if len(scopes) == 0: + return name if name is not None else "" + + if name is not None and name not in scopes: + scopes.append(name) + + return "::".join(scopes) + + def read_line(self, raw_line: str): + """Read a line of code and update the stack.""" + line = sanitize_code_line(raw_line) + if (match := scopeDetectRegex.match(line)) is not None: + if not line.endswith(";"): + self._stack.append(match.group("name")) + + change = line.count("{") - line.count("}") + if change > 0: + for _ in range(change): + self._stack.append("{") + elif change < 0: + for _ in range(-change): + self._pop() + + if len(self._stack) == 0: + return + + last = self._stack[-1] + if last != "{": + self._pop() + + class DecompParser: # pylint: disable=too-many-instance-attributes # Could combine output lists into a single list to get under the limit, @@ -73,6 +130,8 @@ def __init__(self) -> None: self.last_line: str = "" + self.curly = CurlyManager() + # To allow for multiple markers where code is shared across different # modules, save lists of compatible markers that appear in sequence self.fun_markers = MarkerDict() @@ -110,6 +169,8 @@ def reset(self): self.function_start = 0 self.function_sig = "" + self.curly.reset() + @property def functions(self) -> List[ParserFunction]: return [s for s in self._symbols if isinstance(s, ParserFunction)] @@ -213,7 +274,7 @@ def _vtable_done(self, class_name: str = None): line_number=self.line_number, module=marker.module, offset=marker.offset, - name=class_name, + name=self.curly.get_prefix(class_name), ) ) @@ -248,14 +309,32 @@ def _variable_done( ) ) else: + parent_function = None + is_static = self.state == ReaderState.IN_FUNC_GLOBAL + + # If this is a static variable, we need to get the function + # where it resides so that we can match it up later with the + # mangled names of both variable and function from cvdump. + if is_static: + fun_marker = self.fun_markers.query( + MarkerCategory.FUNCTION, marker.module + ) + + if fun_marker is None: + self._syntax_warning(ParserError.ORPHANED_STATIC_VARIABLE) + continue + + parent_function = fun_marker.offset + self._symbols.append( ParserVariable( type=marker.type, line_number=self.line_number, module=marker.module, offset=marker.offset, - name=variable_name, - is_static=self.state == ReaderState.IN_FUNC_GLOBAL, + name=self.curly.get_prefix(variable_name), + is_static=is_static, + parent_function=parent_function, ) ) @@ -353,6 +432,8 @@ def read_line(self, line: str): self._handle_marker(marker) return + self.curly.read_line(line) + line_strip = line.strip() if self.state in ( ReaderState.IN_SYNTHETIC, @@ -406,6 +487,9 @@ def read_line(self, line: str): ): self._function_starts_here() self._function_done() + elif self.function_sig.endswith(");"): + # Detect forward reference or declaration + self._syntax_error(ParserError.NO_IMPLEMENTATION) else: self.state = ReaderState.WANT_CURLY @@ -451,8 +535,11 @@ def read_line(self, line: str): variable_name = get_variable_name(line) # This is out of our control for library variables, but all of our # variables should start with "g_". - if variable_name is not None and not variable_name.startswith("g_"): - self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) + if variable_name is not None: + # Before checking for the prefix, remove the + # namespace chain if there is one. + if not variable_name.split("::")[-1].startswith("g_"): + self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) string_name = get_string_contents(line) diff --git a/tools/isledecomp/isledecomp/parser/util.py b/tools/isledecomp/isledecomp/parser/util.py index dd90fd03..bfe3803c 100644 --- a/tools/isledecomp/isledecomp/parser/util.py +++ b/tools/isledecomp/isledecomp/parser/util.py @@ -7,15 +7,25 @@ # flexibility in the formatting seems OK templateCommentRegex = re.compile(r"\s*//\s+(.*)") - # To remove any comment (//) or block comment (/*) and its leading spaces # from the end of a code line trailingCommentRegex = re.compile(r"(\s*(?://|/\*).*)$") +# Get char contents, ignore escape characters +singleQuoteRegex = re.compile(r"('(?:[^\'\\]|\\.)')") + +# Match contents of block comment on one line +blockCommentRegex = re.compile(r"(/\*.*?\*/)") + +# Match contents of single comment on one line +regularCommentRegex = re.compile(r"(//.*)") # Get string contents, ignore escape characters that might interfere doubleQuoteRegex = re.compile(r"(\"(?:[^\"\\]|\\.)*\")") +# Detect a line that would cause us to enter a new scope +scopeDetectRegex = re.compile(r"(?:class|struct|namespace) (?P\w+).*(?:{)?") + def get_synthetic_name(line: str) -> Optional[str]: """Synthetic names appear on a single line comment on the line after the marker. @@ -28,6 +38,20 @@ def get_synthetic_name(line: str) -> Optional[str]: return None +def sanitize_code_line(line: str) -> str: + """Helper for scope manager. Removes sections from a code line + that would cause us to incorrectly detect curly brackets. + This is a very naive implementation and fails entirely on multi-line + strings or comments.""" + + line = singleQuoteRegex.sub("''", line) + line = doubleQuoteRegex.sub('""', line) + line = blockCommentRegex.sub("", line) + line = regularCommentRegex.sub("", line) + + return line.strip() + + def remove_trailing_comment(line: str) -> str: return trailingCommentRegex.sub("", line) @@ -75,8 +99,8 @@ def get_class_name(line: str) -> Optional[str]: return None -global_regex = re.compile(r"(?Pg_\w+)") -less_strict_global_regex = re.compile(r"(?P\w+)(?:\)\(|\[.*|\s*=.*|;)") +global_regex = re.compile(r"(?P(?:\w+::)*g_\w+)") +less_strict_global_regex = re.compile(r"(?P(?:\w+::)*\w+)(?:\)\(|\[.*|\s*=.*|;)") def get_variable_name(line: str) -> Optional[str]: diff --git a/tools/isledecomp/isledecomp/utils.py b/tools/isledecomp/isledecomp/utils.py index 637eee33..a8c6033b 100644 --- a/tools/isledecomp/isledecomp/utils.py +++ b/tools/isledecomp/isledecomp/utils.py @@ -1,9 +1,77 @@ import os import sys +from datetime import datetime +import logging import colorama +def print_combined_diff(udiff, plain: bool = False, show_both: bool = False): + if udiff is None: + return + + # We don't know how long the address string will be ahead of time. + # Set this value for each address to try to line things up. + padding_size = 0 + + for slug, subgroups in udiff: + if plain: + print("---") + print("+++") + print(slug) + else: + print(f"{colorama.Fore.RED}---") + print(f"{colorama.Fore.GREEN}+++") + print(f"{colorama.Fore.BLUE}{slug}") + print(colorama.Style.RESET_ALL, end="") + + for subgroup in subgroups: + equal = subgroup.get("both") is not None + + if equal: + for orig_addr, line, recomp_addr in subgroup["both"]: + padding_size = max(padding_size, len(orig_addr)) + if show_both: + print(f"{orig_addr} / {recomp_addr} : {line}") + else: + print(f"{orig_addr} : {line}") + else: + for orig_addr, line in subgroup["orig"]: + padding_size = max(padding_size, len(orig_addr)) + addr_prefix = ( + f"{orig_addr} / {'':{padding_size}}" if show_both else orig_addr + ) + + if plain: + print(f"{addr_prefix} : -{line}") + else: + print( + f"{addr_prefix} : {colorama.Fore.RED}-{line}{colorama.Style.RESET_ALL}" + ) + + for recomp_addr, line in subgroup["recomp"]: + padding_size = max(padding_size, len(recomp_addr)) + addr_prefix = ( + f"{'':{padding_size}} / {recomp_addr}" + if show_both + else " " * padding_size + ) + + if plain: + print(f"{addr_prefix} : +{line}") + else: + print( + f"{addr_prefix} : {colorama.Fore.GREEN}+{line}{colorama.Style.RESET_ALL}" + ) + + # Newline between each diff subgroup. + print() + + def print_diff(udiff, plain): + """Print diff in difflib.unified_diff format.""" + if udiff is None: + return False + has_diff = False for line in udiff: has_diff = True @@ -24,5 +92,217 @@ def print_diff(udiff, plain): return has_diff +def get_percent_color(value: float) -> str: + """Return colorama ANSI escape character for the given decimal value.""" + if value == 1.0: + return colorama.Fore.GREEN + if value > 0.8: + return colorama.Fore.YELLOW + + return colorama.Fore.RED + + +def percent_string( + ratio: float, is_effective: bool = False, is_plain: bool = False +) -> str: + """Helper to construct a percentage string from the given ratio. + If is_effective (i.e. effective match), indicate that with the asterisk. + If is_plain, don't use colorama ANSI codes.""" + + percenttext = f"{(ratio * 100):.2f}%" + effective_star = "*" if is_effective else "" + + if is_plain: + return percenttext + effective_star + + return "".join( + [ + get_percent_color(ratio), + percenttext, + colorama.Fore.RED if is_effective else "", + effective_star, + colorama.Style.RESET_ALL, + ] + ) + + +def diff_json_display(show_both_addrs: bool = False, is_plain: bool = False): + """Generate a function that will display the diff according to + the reccmp display preferences.""" + + def formatter(orig_addr, saved, new) -> str: + old_pct = "new" + new_pct = "gone" + name = "" + recomp_addr = "n/a" + + if new is not None: + new_pct = ( + "stub" + if new.get("stub", False) + else percent_string( + new["matching"], new.get("effective", False), is_plain + ) + ) + + # Prefer the current name of this function if we have it. + # We are using the original address as the key. + # A function being renamed is not of interest here. + name = new.get("name", "") + recomp_addr = new.get("recomp", "n/a") + + if saved is not None: + old_pct = ( + "stub" + if saved.get("stub", False) + else percent_string( + saved["matching"], saved.get("effective", False), is_plain + ) + ) + + if name == "": + name = saved.get("name", "") + + if show_both_addrs: + addr_string = f"{orig_addr} / {recomp_addr:10}" + else: + addr_string = orig_addr + + # The ANSI codes from colorama counted towards string length, + # so displaying this as an ascii-like spreadsheet + # (using f-string formatting) would take some effort. + return f"{addr_string} - {name} ({old_pct} -> {new_pct})" + + return formatter + + +def diff_json( + saved_data, + new_data, + orig_file: str, + show_both_addrs: bool = False, + is_plain: bool = False, +): + """Using a saved copy of the diff summary and the current data, print a + report showing which functions/symbols have changed match percentage.""" + + # Don't try to diff a report generated for a different binary file + base_file = os.path.basename(orig_file).lower() + + if saved_data.get("file") != base_file: + logging.getLogger().error( + "Diff report for '%s' does not match current file '%s'", + saved_data.get("file"), + base_file, + ) + return + + if "timestamp" in saved_data: + now = datetime.now().replace(microsecond=0) + then = datetime.fromtimestamp(saved_data["timestamp"]).replace(microsecond=0) + + print( + " ".join( + [ + "Saved diff report generated", + then.strftime("%B %d %Y, %H:%M:%S"), + f"({str(now - then)} ago)", + ] + ) + ) + + print() + + # Convert to dict, using orig_addr as key + saved_invert = {obj["address"]: obj for obj in saved_data["data"]} + new_invert = {obj["address"]: obj for obj in new_data} + + all_addrs = set(saved_invert.keys()).union(new_invert.keys()) + + # Put all the information in one place so we can decide how each item changed. + combined = { + addr: ( + saved_invert.get(addr), + new_invert.get(addr), + ) + for addr in sorted(all_addrs) + } + + # The criteria for diff judgement is in these dict comprehensions: + # Any function not in the saved file + new_functions = { + key: (saved, new) for key, (saved, new) in combined.items() if saved is None + } + + # Any function now missing from the saved file + # or a non-stub -> stub conversion + dropped_functions = { + key: (saved, new) + for key, (saved, new) in combined.items() + if new is None + or ( + new is not None + and saved is not None + and new.get("stub", False) + and not saved.get("stub", False) + ) + } + + # TODO: move these two into functions if the assessment gets more complex + # Any function with increased match percentage + # or stub -> non-stub conversion + improved_functions = { + key: (saved, new) + for key, (saved, new) in combined.items() + if saved is not None + and new is not None + and ( + new["matching"] > saved["matching"] + or (not new.get("stub", False) and saved.get("stub", False)) + ) + } + + # Any non-stub function with decreased match percentage + degraded_functions = { + key: (saved, new) + for key, (saved, new) in combined.items() + if saved is not None + and new is not None + and new["matching"] < saved["matching"] + and not saved.get("stub") + and not new.get("stub") + } + + # Any function with former or current "effective" match + entropy_functions = { + key: (saved, new) + for key, (saved, new) in combined.items() + if saved is not None + and new is not None + and new["matching"] == 1.0 + and saved["matching"] == 1.0 + and new.get("effective", False) != saved.get("effective", False) + } + + get_diff_str = diff_json_display(show_both_addrs, is_plain) + + for diff_name, diff_dict in [ + ("New", new_functions), + ("Increased", improved_functions), + ("Decreased", degraded_functions), + ("Dropped", dropped_functions), + ("Compiler entropy", entropy_functions), + ]: + if len(diff_dict) == 0: + continue + + print(f"{diff_name} ({len(diff_dict)}):") + + for addr, (saved, new) in diff_dict.items(): + print(get_diff_str(addr, saved, new)) + + print() + + def get_file_in_script_dir(fn): return os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), fn) diff --git a/tools/isledecomp/tests/conftest.py b/tools/isledecomp/tests/conftest.py new file mode 100644 index 00000000..9f56b8a7 --- /dev/null +++ b/tools/isledecomp/tests/conftest.py @@ -0,0 +1,3 @@ +def pytest_addoption(parser): + """Allow the option to run tests against the original LEGO1.DLL.""" + parser.addoption("--lego1", action="store", help="Path to LEGO1.DLL") diff --git a/tools/isledecomp/tests/test_compare_db.py b/tools/isledecomp/tests/test_compare_db.py new file mode 100644 index 00000000..55cb75a5 --- /dev/null +++ b/tools/isledecomp/tests/test_compare_db.py @@ -0,0 +1,82 @@ +"""Testing compare database behavior, particularly matching""" +import pytest +from isledecomp.compare.db import CompareDb + + +@pytest.fixture(name="db") +def fixture_db(): + return CompareDb() + + +def test_ignore_recomp_collision(db): + """Duplicate recomp addresses are ignored""" + db.set_recomp_symbol(0x1234, None, "hello", None, 100) + db.set_recomp_symbol(0x1234, None, "alias_for_hello", None, 100) + syms = db.get_all() + assert len(syms) == 1 + + +def test_orig_collision(db): + """Don't match if the original address is not unique""" + db.set_recomp_symbol(0x1234, None, "hello", None, 100) + assert db.match_function(0x5555, "hello") is True + + # Second run on same address fails + assert db.match_function(0x5555, "hello") is False + + # Call set_pair directly without wrapper + assert db.set_pair(0x5555, 0x1234) is False + + +def test_name_match(db): + db.set_recomp_symbol(0x1234, None, "hello", None, 100) + assert db.match_function(0x5555, "hello") is True + + match = db.get_by_orig(0x5555) + assert match.name == "hello" + assert match.recomp_addr == 0x1234 + + +def test_match_decorated(db): + """Should match using decorated name even though regular name is null""" + db.set_recomp_symbol(0x1234, None, None, "?_hello", 100) + assert db.match_function(0x5555, "?_hello") is True + match = db.get_by_orig(0x5555) + assert match is not None + + +def test_duplicate_name(db): + """If recomp name is not unique, match only one row""" + db.set_recomp_symbol(0x100, None, "_Construct", None, 100) + db.set_recomp_symbol(0x200, None, "_Construct", None, 100) + db.set_recomp_symbol(0x300, None, "_Construct", None, 100) + db.match_function(0x5555, "_Construct") + matches = db.get_matches() + # We aren't testing _which_ one would be matched, just that only one _was_ matched + assert len(matches) == 1 + + +def test_static_variable_match(db): + """Set up a situation where we can match a static function variable, then match it.""" + + # We need a matched function to start with. + db.set_recomp_symbol(0x1234, None, "Isle::Tick", "?Tick@IsleApp@@QAEXH@Z", 100) + db.match_function(0x5555, "Isle::Tick") + + # Decorated variable name from PDB. + db.set_recomp_symbol( + 0x2000, None, None, "?g_startupDelay@?1??Tick@IsleApp@@QAEXH@Z@4HA", 4 + ) + + # Provide variable name and orig function address from decomp markers + assert db.match_static_variable(0xBEEF, "g_startupDelay", 0x5555) is True + + +def test_match_options_bool(db): + """Test handling of boolean match options""" + + # You don't actually need an existing orig addr for this. + assert db.get_match_options(0x1234) == {} + + db.mark_stub(0x1234) + assert "stub" in db.get_match_options(0x1234) diff --git a/tools/isledecomp/tests/test_curly.py b/tools/isledecomp/tests/test_curly.py new file mode 100644 index 00000000..8328f5e9 --- /dev/null +++ b/tools/isledecomp/tests/test_curly.py @@ -0,0 +1,73 @@ +# nyuk nyuk nyuk +import pytest +from isledecomp.parser.parser import CurlyManager +from isledecomp.parser.util import sanitize_code_line + + +@pytest.fixture(name="curly") +def fixture_curly(): + return CurlyManager() + + +def test_simple(curly): + curly.read_line("namespace Test {") + assert curly.get_prefix() == "Test" + curly.read_line("}") + assert curly.get_prefix() == "" + + +def test_oneliner(curly): + """Should not go down into a scope for a class forward reference""" + curly.read_line("class LegoEntity;") + assert curly.get_prefix() == "" + # Now make sure that we still would not consider that class name + # even after reading the opening curly brace + curly.read_line("if (true) {") + assert curly.get_prefix() == "" + + +def test_ignore_comments(curly): + curly.read_line("namespace Test {") + curly.read_line("// }") + assert curly.get_prefix() == "Test" + + +@pytest.mark.xfail(reason="todo: need a real lexer") +def test_ignore_multiline_comments(curly): + curly.read_line("namespace Test {") + curly.read_line("/*") + curly.read_line("}") + curly.read_line("*/") + assert curly.get_prefix() == "Test" + curly.read_line("}") + assert curly.get_prefix() == "" + + +def test_nested(curly): + curly.read_line("namespace Test {") + curly.read_line("namespace Foo {") + assert curly.get_prefix() == "Test::Foo" + curly.read_line("}") + assert curly.get_prefix() == "Test" + + +sanitize_cases = [ + ("", ""), + (" ", ""), + ("{", "{"), + ("// comments {", ""), + ("{ // why comment here", "{"), + ("/* comments */ {", "{"), + ('"curly in a string {"', '""'), + ('if (!strcmp("hello { there }", g_test)) {', 'if (!strcmp("", g_test)) {'), + ("'{'", "''"), + ("weird_function('\"', hello, '\"')", "weird_function('', hello, '')"), +] + + +@pytest.mark.parametrize("start, end", sanitize_cases) +def test_sanitize(start: str, end: str): + """Make sure that we can remove curly braces in places where they should + not be considered as part of the semantic structure of the file. + i.e. inside strings or chars, and inside comments""" + assert sanitize_code_line(start) == end diff --git a/tools/isledecomp/tests/test_demangler.py b/tools/isledecomp/tests/test_demangler.py index 32cac502..e40d6e0c 100644 --- a/tools/isledecomp/tests/test_demangler.py +++ b/tools/isledecomp/tests/test_demangler.py @@ -15,6 +15,7 @@ True, ), ("??_C@_00A@?$AA@", 0, False), + ("??_C@_01A@?$AA?$AA@", 1, False), ] @@ -48,6 +49,7 @@ def test_invalid_encoded_number(): ("??_7LegoCarBuildAnimPresenter@@6B@", "LegoCarBuildAnimPresenter"), ("??_7?$MxCollection@PAVLegoWorld@@@@6B@", "MxCollection"), ("??_7?$MxPtrList@VLegoPathController@@@@6B@", "MxPtrList"), + ("??_7Renderer@Tgl@@6B@", "Tgl::Renderer"), ] diff --git a/tools/isledecomp/tests/test_islebin.py b/tools/isledecomp/tests/test_islebin.py new file mode 100644 index 00000000..ffb3c494 --- /dev/null +++ b/tools/isledecomp/tests/test_islebin.py @@ -0,0 +1,146 @@ +"""Tests for the Bin (or IsleBin) module that: +1. Parses relevant data from the PE header and other structures. +2. Provides an interface to read from the DLL or EXE using a virtual address. +These are some basic smoke tests.""" + +import hashlib +from typing import Tuple +import pytest +from isledecomp.bin import ( + Bin as IsleBin, + SectionNotFoundError, + InvalidVirtualAddressError, +) + + +# LEGO1.DLL: v1.1 English, September +LEGO1_SHA256 = "14645225bbe81212e9bc1919cd8a692b81b8622abb6561280d99b0fc4151ce17" + + +@pytest.fixture(name="binfile", scope="session") +def fixture_binfile(pytestconfig) -> IsleBin: + filename = pytestconfig.getoption("--lego1") + + # Skip this if we have not provided the path to LEGO1.dll. + if filename is None: + pytest.skip(allow_module_level=True, reason="No path to LEGO1") + + with open(filename, "rb") as f: + digest = hashlib.sha256(f.read()).hexdigest() + if digest != LEGO1_SHA256: + pytest.fail(reason="Did not match expected LEGO1.DLL") + + with IsleBin(filename, find_str=True) as islebin: + yield islebin + + +def test_basic(binfile: IsleBin): + assert binfile.entry == 0x1008C860 + assert len(binfile.sections) == 6 + + with pytest.raises(SectionNotFoundError): + binfile.get_section_by_name(".hello") + + +SECTION_INFO = ( + (".text", 0x10001000, 0xD2A66, 0xD2C00), + (".rdata", 0x100D4000, 0x1B5B6, 0x1B600), + (".data", 0x100F0000, 0x1A734, 0x12C00), + (".idata", 0x1010B000, 0x1006, 0x1200), + (".rsrc", 0x1010D000, 0x21D8, 0x2200), + (".reloc", 0x10110000, 0x10C58, 0x10E00), +) + + +@pytest.mark.parametrize("name, v_addr, v_size, raw_size", SECTION_INFO) +def test_sections(name: str, v_addr: int, v_size: int, raw_size: int, binfile: IsleBin): + section = binfile.get_section_by_name(name) + assert section.virtual_address == v_addr + assert section.virtual_size == v_size + assert section.size_of_raw_data == raw_size + + +DOUBLE_PI_BYTES = b"\x18\x2d\x44\x54\xfb\x21\x09\x40" + +# Now that's a lot of pi +PI_ADDRESSES = ( + 0x100D4000, + 0x100D4700, + 0x100D7180, + 0x100DB8F0, + 0x100DC030, +) + + +@pytest.mark.parametrize("addr", PI_ADDRESSES) +def test_read_pi(addr: int, binfile: IsleBin): + assert binfile.read(addr, 8) == DOUBLE_PI_BYTES + + +def test_unusual_reads(binfile: IsleBin): + """Reads that return an error or some specific value based on context""" + # Reading an address earlier than the imagebase + with pytest.raises(InvalidVirtualAddressError): + binfile.read(0, 1) + + # Really big address + with pytest.raises(InvalidVirtualAddressError): + binfile.read(0xFFFFFFFF, 1) + + # Uninitialized part of .data + assert binfile.read(0x1010A600, 4) is None + + # Past the end of virtual size in .text + assert binfile.read(0x100D3A70, 4) == b"\x00\x00\x00\x00" + + +STRING_ADDRESSES = ( + (0x100DB588, b"November"), + (0x100F0130, b"Helicopter"), + (0x100F0144, b"HelicopterState"), + (0x100F0BE4, b"valerie"), + (0x100F4080, b"TARGET"), +) + + +@pytest.mark.parametrize("addr, string", STRING_ADDRESSES) +def test_strings(addr: int, string: bytes, binfile: IsleBin): + """Test string read utility function and the string search feature""" + assert binfile.read_string(addr) == string + assert binfile.find_string(string) == addr + + +def test_relocation(binfile: IsleBin): + # n.b. This is not the number of *relocations* read from .reloc. + # It is the set of unique addresses in the binary that get relocated. + assert len(binfile.get_relocated_addresses()) == 14066 + + # Score::Score is referenced only by CALL instructions. No need to relocate. + assert binfile.is_relocated_addr(0x10001000) is False + + # MxEntity::SetEntityId is in the vtable and must be relocated. + assert binfile.is_relocated_addr(0x10001070) is True + + +# Not sanitizing dll name case. Do we care? +IMPORT_REFS = ( + ("KERNEL32.dll", "CreateMutexA", 0x1010B3D0), + ("WINMM.dll", "midiOutPrepareHeader", 0x1010B550), +) + + +@pytest.mark.parametrize("import_ref", IMPORT_REFS) +def test_imports(import_ref: Tuple[str, str, int], binfile: IsleBin): + assert import_ref in binfile.imports + + +# Location of the JMP instruction and the import address. +THUNKS = ( + (0x100D3728, 0x1010B32C), # DirectDrawCreate + (0x10098F9E, 0x1010B3D4), # RtlUnwind +) + + +@pytest.mark.parametrize("thunk_ref", THUNKS) +def test_thunks(thunk_ref: Tuple[int, int], binfile: IsleBin): + assert thunk_ref in binfile.thunks diff --git a/tools/isledecomp/tests/test_parser.py b/tools/isledecomp/tests/test_parser.py index 6d8b72b1..772a39c4 100644 --- a/tools/isledecomp/tests/test_parser.py +++ b/tools/isledecomp/tests/test_parser.py @@ -419,8 +419,7 @@ def test_static_variable(parser): """We can detect whether a variable is a static function variable based on the parser's state when we detect it. Checking for the word `static` alone is not a good test. - Static class variables are filed as S_GDATA32, same as regular globals. - Only function statics are filed as S_LDATA32.""" + Static class variables are filed as S_GDATA32, same as regular globals.""" parser.read_lines( [ @@ -436,7 +435,7 @@ def test_static_variable(parser): "// FUNCTION: TEST 0x5555", "void test_function() {", "// GLOBAL: TEST 0x8888", - "int g_internal = 0;", + "static int g_internal = 0;", "}", ] ) @@ -521,3 +520,194 @@ def test_string_ignore_g_prefix(parser): ) assert len(parser.strings) == 1 assert len(parser.alerts) == 0 + + +def test_class_variable(parser): + """We should accurately name static variables that are class members.""" + + parser.read_lines( + [ + "class Test {", + "protected:", + " // GLOBAL: TEST 0x1234", + " static int g_test;", + "};", + ] + ) + + assert len(parser.variables) == 1 + assert parser.variables[0].name == "Test::g_test" + + +def test_namespace_variable(parser): + """We should identify a namespace surrounding any global variables""" + + parser.read_lines( + [ + "namespace Test {", + "// GLOBAL: TEST 0x1234", + "int g_test = 1234;", + "}", + "// GLOBAL: TEST 0x5555", + "int g_second = 2;", + ] + ) + + assert len(parser.variables) == 2 + assert parser.variables[0].name == "Test::g_test" + assert parser.variables[1].name == "g_second" + + +def test_namespace_vtable(parser): + parser.read_lines( + [ + "namespace Tgl {", + "// VTABLE: TEST 0x1234", + "class Renderer {", + "};", + "}", + "// VTABLE: TEST 0x5555", + "class Hello { };", + ] + ) + + assert len(parser.vtables) == 2 + assert parser.vtables[0].name == "Tgl::Renderer" + assert parser.vtables[1].name == "Hello" + + +def test_global_prefix_namespace(parser): + """Should correctly identify namespaces before checking for the g_ prefix""" + + parser.read_lines( + [ + "class Test {", + " // GLOBAL: TEST 0x1234", + " static int g_count = 0;", + " // GLOBAL: TEST 0x5555", + " static int count = 0;", + "};", + ] + ) + + assert len(parser.variables) == 2 + assert parser.variables[0].name == "Test::g_count" + assert parser.variables[1].name == "Test::count" + + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.GLOBAL_MISSING_PREFIX + + +def test_nested_namespace(parser): + parser.read_lines( + [ + "namespace Tgl {", + "class Renderer {", + " // GLOBAL: TEST 0x1234", + " static int g_count = 0;", + "};", + "};", + ] + ) + + assert len(parser.variables) == 1 + assert parser.variables[0].name == "Tgl::Renderer::g_count" + + +def test_match_qualified_variable(parser): + """If a variable belongs to a scope and we use a fully qualified reference + below a GLOBAL marker, make sure we capture the full name.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "int MxTest::g_count = 0;", + ] + ) + + assert len(parser.variables) == 1 + assert parser.variables[0].name == "MxTest::g_count" + assert len(parser.alerts) == 0 + + +def test_static_variable_parent(parser): + """Report the address of the parent function that contains a static variable.""" + + parser.read_lines( + [ + "// FUNCTION: TEST 0x1234", + "void test()", + "{", + " // GLOBAL: TEST 0x5555", + " static int g_count = 0;", + "}", + ] + ) + + assert len(parser.variables) == 1 + assert parser.variables[0].is_static is True + assert parser.variables[0].parent_function == 0x1234 + + +@pytest.mark.xfail( + reason="""Without the FUNCTION marker we don't know that we are inside a function, + so we do not identify this variable as static.""" +) +def test_static_variable_no_parent(parser): + """If the function that contains a static variable is not marked, we + cannot match it with cvdump so we should skip it and report an error.""" + + parser.read_lines( + [ + "void test()", + "{", + " // GLOBAL: TEST 0x5555", + " static int g_count = 0;", + "}", + ] + ) + + # No way to match this variable so don't report it + assert len(parser.variables) == 0 + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.ORPHANED_STATIC_VARIABLE + + +def test_static_variable_incomplete_coverage(parser): + """If the function that contains a static variable is marked, but + not for each module used for the variable itself, this is an error.""" + + parser.read_lines( + [ + "// FUNCTION: HELLO 0x1234", + "void test()", + "{", + " // GLOBAL: HELLO 0x5555", + " // GLOBAL: TEST 0x5555", + " static int g_count = 0;", + "}", + ] + ) + + # Match for HELLO module + assert len(parser.variables) == 1 + + # Failed for TEST module + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.ORPHANED_STATIC_VARIABLE + + +def test_header_function_declaration(parser): + """This is either a forward reference or a declaration in a header file. + Meaning: The implementation is not here. This is not the correct place + for the FUNCTION marker and it will probably not match anything.""" + + parser.read_lines( + [ + "// FUNCTION: HELLO 0x1234", + "void sample_function(int);", + ] + ) + + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.NO_IMPLEMENTATION diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index ec7f46a0..f6d2de8e 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -2,7 +2,7 @@ configureLegoAnimationManager(MxS32): 'DLL exported function' configureLegoBuildingManager(MxS32): 'DLL exported function' configureLegoModelPresenter(MxS32): 'DLL exported function' configureLegoPartPresenter(MxS32, MxS32): 'DLL exported function' -configureLegoROI(MxS32): 'DLL exported function' +configureLegoROI(int): 'DLL exported function' configureLegoWorldPresenter(MxS32): 'DLL exported function' GetNoCD_SourceName(): 'DLL exported function' m_3dView: 'Allow this variable name' diff --git a/tools/patch_c2.py b/tools/patch_c2.py old mode 100644 new mode 100755 diff --git a/tools/reccmp/config.png b/tools/reccmp/config.png new file mode 100644 index 00000000..1f2050ad Binary files /dev/null and b/tools/reccmp/config.png differ diff --git a/tools/reccmp/reccmp.js b/tools/reccmp/reccmp.js new file mode 100644 index 00000000..1323ca10 --- /dev/null +++ b/tools/reccmp/reccmp.js @@ -0,0 +1,622 @@ +// reccmp.js +/* global data */ + +// Unwrap array of functions into a dictionary with address as the key. +const dataDict = Object.fromEntries(data.map(row => [row.address, row])); + +function getDataByAddr(addr) { + return dataDict[addr]; +} + +// +// Pure functions +// + +function formatAsm(entries, addrOption) { + const output = []; + + const createTh = (text) => { + const th = document.createElement('th'); + th.innerText = text; + return th; + }; + + const createTd = (text, className = '') => { + const td = document.createElement('td'); + td.innerText = text; + td.className = className; + return td; + }; + + entries.forEach(obj => { + // These won't all be present. You get "both" for an equal node + // and orig/recomp for a diff. + const { both = [], orig = [], recomp = [] } = obj; + + output.push(...both.map(([addr, line, recompAddr]) => { + const tr = document.createElement('tr'); + tr.appendChild(createTh(addr)); + tr.appendChild(createTh(recompAddr)); + tr.appendChild(createTd(line)); + return tr; + })); + + output.push(...orig.map(([addr, line]) => { + const tr = document.createElement('tr'); + tr.appendChild(createTh(addr)); + tr.appendChild(createTh('')); + tr.appendChild(createTd(`-${line}`, 'diffneg')); + return tr; + })); + + output.push(...recomp.map(([addr, line]) => { + const tr = document.createElement('tr'); + tr.appendChild(createTh('')); + tr.appendChild(createTh(addr)); + tr.appendChild(createTd(`+${line}`, 'diffpos')); + return tr; + })); + }); + + return output; +} + +function getMatchPercentText(row) { + if ('stub' in row) { + return 'stub'; + } + + if ('effective' in row) { + return '100.00%*'; + } + + return (row.matching * 100).toFixed(2) + '%'; +} + +// Helper for this set/remove attribute block +function setBooleanAttribute(element, attribute, value) { + if (value) { + element.setAttribute(attribute, ''); + } else { + element.removeAttribute(attribute); + } +} + +// +// Global state +// + +class ListingState { + constructor() { + this._query = ''; + this._sortCol = 'address'; + this._filterType = 1; + this.sortDesc = false; + this.hidePerfect = false; + this.hideStub = false; + } + + get filterType() { + return parseInt(this._filterType); + } + + set filterType(value) { + value = parseInt(value); + if (value >= 1 && value <= 3) { + this._filterType = value; + } + } + + get query() { + return this._query; + } + + set query(value) { + // Normalize search string + this._query = value.toLowerCase().trim(); + } + + get sortCol() { + return this._sortCol; + } + + set sortCol(column) { + if (column === this._sortCol) { + this.sortDesc = !this.sortDesc; + } else { + this._sortCol = column; + } + } +} + +const StateProxy = { + set(obj, prop, value) { + if (prop === 'onsort') { + this._onsort = value; + return true; + } + + if (prop === 'onfilter') { + this._onfilter = value; + return true; + } + + obj[prop] = value; + + if (prop === 'sortCol' || prop === 'sortDesc') { + this._onsort(); + } else { + this._onfilter(); + } + return true; + } +}; + +const appState = new Proxy(new ListingState(), StateProxy); + +// +// Stateful functions +// + +function addrShouldAppear(addr) { + // Destructuring sets defaults for optional values from this object. + const { + effective = false, + stub = false, + diff = '', + name, + address, + matching + } = getDataByAddr(addr); + + if (appState.hidePerfect && (effective || matching >= 1)) { + return false; + } + + if (appState.hideStub && stub) { + return false; + } + + if (appState.query === '') { + return true; + } + + // Name/addr search + if (appState.filterType === 1) { + return ( + address.includes(appState.query) || + name.toLowerCase().includes(appState.query) + ); + } + + // no diff for review. + if (diff === '') { + return false; + } + + // special matcher for combined diff + const anyLineMatch = ([addr, line]) => line.toLowerCase().trim().includes(appState.query); + + // Flatten all diff groups for the search + const diffs = diff.map(([slug, subgroups]) => subgroups).flat(); + for (const subgroup of diffs) { + const { both = [], orig = [], recomp = [] } = subgroup; + + // If search includes context + if (appState.filterType === 2 && both.some(anyLineMatch)) { + return true; + } + + if (orig.some(anyLineMatch) || recomp.some(anyLineMatch)) { + return true; + } + } + + return false; +} + +// Row comparator function, using our chosen sort column and direction. +// -1 (A before B) +// 1 (B before A) +// 0 (equal) +function rowSortOrder(addrA, addrB) { + const objA = getDataByAddr(addrA); + const objB = getDataByAddr(addrB); + const valA = objA[appState.sortCol]; + const valB = objB[appState.sortCol]; + + if (valA > valB) { + return appState.sortDesc ? -1 : 1; + } else if (valA < valB) { + return appState.sortDesc ? 1 : -1; + } + + return 0; +} + +// +// Custom elements +// + +// Sets sort indicator arrow based on element attributes. +class SortIndicator extends window.HTMLElement { + static observedAttributes = ['data-sort']; + + attributeChangedCallback(name, oldValue, newValue) { + if (newValue === null) { + this.textContent = ''; + } else { + this.innerHTML = newValue === 'asc' ? '▲' : '▼'; + } + } +} + +class FuncRow extends window.HTMLElement { + static observedAttributes = ['expanded']; + + constructor() { + super(); + + this.onclick = evt => (this.expanded = !this.expanded); + } + + connectedCallback() { + if (this.shadowRoot !== null) { + return; + } + + const template = document.querySelector('template#funcrow-template').content; + const shadow = this.attachShadow({ mode: 'open' }); + shadow.appendChild(template.cloneNode(true)); + } + + get address() { + return this.getAttribute('data-address'); + } + + get expanded() { + return this.getAttribute('expanded') !== null; + } + + set expanded(value) { + setBooleanAttribute(this, 'expanded', value); + } + + attributeChangedCallback(name, oldValue, newValue) { + if (name !== 'expanded') { + return; + } + + if (this.onchangeExpand) { + this.onchangeExpand(this.expanded); + } + } +} + +class NoDiffMessage extends window.HTMLElement { + connectedCallback() { + if (this.shadowRoot !== null) { + return; + } + + const template = document.querySelector('template#nodiff-template').content; + const shadow = this.attachShadow({ mode: 'open' }); + shadow.appendChild(template.cloneNode(true)); + } +} + +// Displays asm diff for the given @data-address value. +class DiffRow extends window.HTMLElement { + connectedCallback() { + if (this.shadowRoot !== null) { + return; + } + + const template = document.querySelector('template#diffrow-template').content; + const shadow = this.attachShadow({ mode: 'open' }); + shadow.appendChild(template.cloneNode(true)); + } + + get address() { + return this.getAttribute('data-address'); + } + + set address(value) { + this.setAttribute('data-address', value); + } +} + +class DiffDisplayOptions extends window.HTMLElement { + static observedAttributes = ['data-option']; + + connectedCallback() { + if (this.shadowRoot !== null) { + return; + } + + const shadow = this.attachShadow({ mode: 'open' }); + shadow.innerHTML = ` + +
+ Address display: + + + + + + +
`; + + shadow.querySelectorAll('input[type=radio]').forEach(radio => { + const checked = this.option === radio.getAttribute('value'); + setBooleanAttribute(radio, 'checked', checked); + + radio.addEventListener('change', evt => (this.option = evt.target.value)); + }); + } + + set option(value) { + this.setAttribute('data-option', parseInt(value)); + } + + get option() { + return this.getAttribute('data-option') ?? 1; + } + + attributeChangedCallback(name, oldValue, newValue) { + if (name !== 'data-option') { + return; + } + + this.dispatchEvent(new Event('change')); + } +} + +class DiffDisplay extends window.HTMLElement { + static observedAttributes = ['data-option']; + + connectedCallback() { + if (this.querySelector('diff-display-options') !== null) { + return; + } + + const optControl = new DiffDisplayOptions(); + optControl.option = this.option; + optControl.addEventListener('change', evt => (this.option = evt.target.option)); + this.appendChild(optControl); + + const div = document.createElement('div'); + const obj = getDataByAddr(this.address); + + const createHeaderLine = (text, className) => { + const div = document.createElement('div'); + div.textContent = text; + div.className = className; + return div; + }; + + const groups = obj.diff; + groups.forEach(([slug, subgroups]) => { + const secondTable = document.createElement('table'); + secondTable.classList.add('diffTable'); + + const hdr = document.createElement('div'); + hdr.appendChild(createHeaderLine('---', 'diffneg')); + hdr.appendChild(createHeaderLine('+++', 'diffpos')); + hdr.appendChild(createHeaderLine(slug, 'diffslug')); + div.appendChild(hdr); + + const tbody = document.createElement('tbody'); + secondTable.appendChild(tbody); + + const diffs = formatAsm(subgroups, this.option); + for (const el of diffs) { + tbody.appendChild(el); + } + + div.appendChild(secondTable); + }); + + this.appendChild(div); + } + + get address() { + return this.getAttribute('data-address'); + } + + set address(value) { + this.setAttribute('data-address', value); + } + + get option() { + return this.getAttribute('data-option') ?? 1; + } + + set option(value) { + this.setAttribute('data-option', value); + } +} + +// Main application. +class ListingTable extends window.HTMLElement { + constructor() { + super(); + + // Redraw the table on any changes. + appState.onsort = () => this.sortRows(); + appState.onfilter = () => this.filterRows(); + + const input = this.querySelector('input[type=search]'); + input.oninput = evt => (appState.query = evt.target.value); + + const hidePerf = this.querySelector('input#cbHidePerfect'); + hidePerf.onchange = evt => (appState.hidePerfect = evt.target.checked); + hidePerf.checked = appState.hidePerfect; + + const hideStub = this.querySelector('input#cbHideStub'); + hideStub.onchange = evt => (appState.hideStub = evt.target.checked); + hideStub.checked = appState.hideStub; + + this.querySelectorAll('input[name=filterType]').forEach(radio => { + const checked = appState.filterType === parseInt(radio.getAttribute('value')); + setBooleanAttribute(radio, 'checked', checked); + + radio.onchange = evt => (appState.filterType = radio.getAttribute('value')); + }); + } + + setRowExpand(address, shouldExpand) { + const tbody = this.querySelector('tbody'); + const funcrow = tbody.querySelector(`func-row[data-address="${address}"]`); + if (funcrow === null) { + return; + } + + const existing = tbody.querySelector(`diff-row[data-address="${address}"]`); + if (shouldExpand) { + if (existing === null) { + const diffrow = document.createElement('diff-row'); + diffrow.address = address; + + // Decide what goes inside the diff row. + const obj = getDataByAddr(address); + + if ('stub' in obj) { + const msg = document.createElement('no-diff'); + const p = document.createElement('div'); + p.innerText = 'Stub. No diff.'; + msg.appendChild(p); + diffrow.appendChild(msg); + } else if (obj.diff.length === 0) { + const msg = document.createElement('no-diff'); + const p = document.createElement('div'); + p.innerText = 'Identical function - no diff'; + msg.appendChild(p); + diffrow.appendChild(msg); + } else { + const dd = new DiffDisplay(); + dd.option = '1'; + dd.address = address; + diffrow.appendChild(dd); + } + + // Insert the diff row after the parent func row. + tbody.insertBefore(diffrow, funcrow.nextSibling); + } + } else { + if (existing !== null) { + tbody.removeChild(existing); + } + } + } + + connectedCallback() { + const thead = this.querySelector('thead'); + const headers = thead.querySelectorAll('th'); + headers.forEach(th => { + const col = th.getAttribute('data-col'); + if (col) { + th.onclick = evt => (appState.sortCol = col); + } + }); + + const tbody = this.querySelector('tbody'); + + for (const obj of data) { + const row = document.createElement('func-row'); + row.setAttribute('data-address', obj.address); // ? + + const items = [ + ['address', obj.address], + ['name', obj.name], + ['matching', getMatchPercentText(obj)] + ]; + + items.forEach(([slotName, content]) => { + const div = document.createElement('div'); + div.setAttribute('slot', slotName); + div.innerText = content; + row.appendChild(div); + }); + + row.onchangeExpand = shouldExpand => this.setRowExpand(obj.address, shouldExpand); + tbody.appendChild(row); + } + + this.sortRows(); + this.filterRows(); + } + + sortRows() { + const thead = this.querySelector('thead'); + const headers = thead.querySelectorAll('th'); + + // Update sort indicator + headers.forEach(th => { + const col = th.getAttribute('data-col'); + const indicator = th.querySelector('sort-indicator'); + if (appState.sortCol === col) { + indicator.setAttribute('data-sort', appState.sortDesc ? 'desc' : 'asc'); + } else { + indicator.removeAttribute('data-sort'); + } + }); + + // Select only the function rows and the diff child row. + // Exclude any nested tables used to *display* the diffs. + const tbody = this.querySelector('tbody'); + const rows = tbody.querySelectorAll('func-row[data-address], diff-row[data-address]'); + + // Sort all rows according to chosen order + const newRows = Array.from(rows); + newRows.sort((rowA, rowB) => { + const addrA = rowA.getAttribute('data-address'); + const addrB = rowB.getAttribute('data-address'); + + // Diff row always sorts after its parent row + if (addrA === addrB && rowB.className === 'diffRow') { + return -1; + } + + return rowSortOrder(addrA, addrB); + }); + + // Replace existing rows with updated order + newRows.forEach(row => tbody.appendChild(row)); + } + + filterRows() { + const tbody = this.querySelector('tbody'); + const rows = tbody.querySelectorAll('func-row[data-address], diff-row[data-address]'); + + rows.forEach(row => { + const addr = row.getAttribute('data-address'); + const hidden = !addrShouldAppear(addr); + setBooleanAttribute(row, 'hidden', hidden); + }); + + // Update row count + this.querySelector('#rowcount').textContent = `${tbody.querySelectorAll('func-row:not([hidden])').length}`; + } +} + +window.onload = () => { + window.customElements.define('listing-table', ListingTable); + window.customElements.define('diff-display', DiffDisplay); + window.customElements.define('diff-display-options', DiffDisplayOptions); + window.customElements.define('sort-indicator', SortIndicator); + window.customElements.define('func-row', FuncRow); + window.customElements.define('diff-row', DiffRow); + window.customElements.define('no-diff', NoDiffMessage); +}; diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index 69783cb2..711375d6 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -5,11 +5,14 @@ import json import logging import os +from datetime import datetime from isledecomp import ( Bin, get_file_in_script_dir, - print_diff, + print_combined_diff, + diff_json, + percent_string, ) from isledecomp.compare import Compare as IsleCompare from isledecomp.types import SymbolType @@ -19,9 +22,38 @@ colorama.init() +def gen_json(json_file: str, orig_file: str, data): + """Create a JSON file that contains the comparison summary""" + + # If the structure of the JSON file ever changes, we would run into a problem + # reading an older format file in the CI action. Mark which version we are + # generating so we could potentially address this down the road. + json_format_version = 1 + + # Remove the diff field + reduced_data = [ + {key: value for (key, value) in obj.items() if key != "diff"} for obj in data + ] + + with open(json_file, "w", encoding="utf-8") as f: + json.dump( + { + "file": os.path.basename(orig_file).lower(), + "format": json_format_version, + "timestamp": datetime.now().timestamp(), + "data": reduced_data, + }, + f, + ) + + def gen_html(html_file, data): + js_path = get_file_in_script_dir("reccmp.js") + with open(js_path, "r", encoding="utf-8") as f: + reccmp_js = f.read() + output_data = Renderer().render_path( - get_file_in_script_dir("template.html"), {"data": data} + get_file_in_script_dir("template.html"), {"data": data, "reccmp_js": reccmp_js} ) with open(html_file, "w", encoding="utf-8") as htmlfile: @@ -51,40 +83,6 @@ def gen_svg(svg_file, name_svg, icon, svg_implemented_funcs, total_funcs, raw_ac svgfile.write(output_data) -def get_percent_color(value: float) -> str: - """Return colorama ANSI escape character for the given decimal value.""" - if value == 1.0: - return colorama.Fore.GREEN - if value > 0.8: - return colorama.Fore.YELLOW - - return colorama.Fore.RED - - -def percent_string( - ratio: float, is_effective: bool = False, is_plain: bool = False -) -> str: - """Helper to construct a percentage string from the given ratio. - If is_effective (i.e. effective match), indicate that with the asterisk. - If is_plain, don't use colorama ANSI codes.""" - - percenttext = f"{(ratio * 100):.2f}%" - effective_star = "*" if is_effective else "" - - if is_plain: - return percenttext + effective_star - - return "".join( - [ - get_percent_color(ratio), - percenttext, - colorama.Fore.RED if is_effective else "", - effective_star, - colorama.Style.RESET_ALL, - ] - ) - - def print_match_verbose(match, show_both_addrs: bool = False, is_plain: bool = False): percenttext = percent_string( match.effective_ratio, match.is_effective_match, is_plain @@ -95,6 +93,10 @@ def print_match_verbose(match, show_both_addrs: bool = False, is_plain: bool = F else: addrs = hex(match.orig_addr) + if match.is_stub: + print(f"{addrs}: {match.name} is a stub. No diff.") + return + if match.effective_ratio == 1.0: ok_text = ( "OK!" @@ -108,7 +110,7 @@ def print_match_verbose(match, show_both_addrs: bool = False, is_plain: bool = F f"{addrs}: {match.name} Effective 100%% match. (Differs in register allocation only)\n\n{ok_text} (still differs in register allocation)\n\n" ) else: - print_diff(match.udiff, is_plain) + print_combined_diff(match.udiff, is_plain, show_both_addrs) print( f"\n{match.name} is only {percenttext} similar to the original, diff above" @@ -125,7 +127,10 @@ def print_match_oneline(match, show_both_addrs: bool = False, is_plain: bool = F else: addrs = hex(match.orig_addr) - print(f" {match.name} ({addrs}) is {percenttext} similar to the original") + if match.is_stub: + print(f" {match.name} ({addrs}) is a stub.") + else: + print(f" {match.name} ({addrs}) is {percenttext} similar to the original") def parse_args() -> argparse.Namespace: @@ -162,6 +167,16 @@ def virtual_address(value) -> int: type=virtual_address, help="Print assembly diff for specific function (original file's offset)", ) + parser.add_argument( + "--json", + metavar="", + help="Generate JSON file with match summary", + ) + parser.add_argument( + "--diff", + metavar="", + help="Diff against summary in JSON file", + ) parser.add_argument( "--html", "-H", @@ -180,6 +195,11 @@ def virtual_address(value) -> int: action="store_true", help="Print addresses of recompiled functions too", ) + parser.add_argument( + "--silent", + action="store_true", + help="Don't display text summary of matches", + ) parser.set_defaults(loglevel=logging.INFO) parser.add_argument( @@ -244,28 +264,53 @@ def main(): htmlinsert = [] for match in isle_compare.compare_all(): - print_match_oneline( - match, show_both_addrs=args.print_rec_addr, is_plain=args.no_color - ) + if not args.silent and args.diff is None: + print_match_oneline( + match, show_both_addrs=args.print_rec_addr, is_plain=args.no_color + ) - if match.match_type == SymbolType.FUNCTION: + if match.match_type == SymbolType.FUNCTION and not match.is_stub: function_count += 1 total_accuracy += match.ratio total_effective_accuracy += match.effective_ratio # If html, record the diffs to an HTML file - if args.html is not None: - htmlinsert.append( - { - "address": f"0x{match.orig_addr:x}", - "name": match.name, - "matching": match.effective_ratio, - "diff": "\n".join(match.udiff), - } + html_obj = { + "address": f"0x{match.orig_addr:x}", + "recomp": f"0x{match.recomp_addr:x}", + "name": match.name, + "matching": match.effective_ratio, + } + + if match.is_effective_match: + html_obj["effective"] = True + + if match.udiff is not None: + html_obj["diff"] = match.udiff + + if match.is_stub: + html_obj["stub"] = True + + htmlinsert.append(html_obj) + + # Compare with saved diff report. + if args.diff is not None: + with open(args.diff, "r", encoding="utf-8") as f: + saved_data = json.load(f) + + diff_json( + saved_data, + htmlinsert, + args.original, + show_both_addrs=args.print_rec_addr, + is_plain=args.no_color, ) ## Generate files and show summary. + if args.json is not None: + gen_json(args.json, args.original, htmlinsert) + if args.html is not None: gen_html(args.html, json.dumps(htmlinsert)) diff --git a/tools/reccmp/template.html b/tools/reccmp/template.html index 2ee17399..07082b9b 100644 --- a/tools/reccmp/template.html +++ b/tools/reccmp/template.html @@ -39,21 +39,22 @@ font-family: monospace; } - .funcrow:hover { + func-row:hover { background: #404040 !important; } - .funcrow:nth-child(odd), #listing th { + func-row:nth-child(odd of :not([hidden])), #listing > thead th { background: #282828; } - .funcrow:nth-child(even) { + func-row:nth-child(even of :not([hidden])) { background: #383838; } - #listing td, #listing th { + #listing > thead th { border: 1px #f0f0f0 solid; padding: 0.5em; + word-break: break-all !important; } .diffneg { @@ -64,211 +65,154 @@ color: #80FF80; } + .diffslug { + color: #8080FF; + } + .identical { font-style: italic; text-align: center; } - #sortind { + sort-indicator { margin: 0 0.5em; } .filters { + align-items: top; + display: flex; font-size: 10pt; - text-align: center; + justify-content: space-between; margin: 0.5em 0 1em 0; } + + .filters > fieldset { + /* checkbox and radio buttons v-aligned with text */ + align-items: center; + display: flex; + } + + .filters > fieldset > label { + margin-right: 10px; + } + + table.diffTable { + border-collapse: collapse; + } + + table.diffTable:not(:last-child) { + /* visual gap *between* diff context groups */ + margin-bottom: 40px; + } + + table.diffTable td, table.diffTable th { + border: 0 none; + padding: 0 10px 0 0; + } + + table.diffTable th { + /* don't break address if asm line is long */ + word-break: keep-all; + } + + diff-display[data-option="0"] th:nth-child(1) { + display: none; + } + + diff-display[data-option="0"] th:nth-child(2), + diff-display[data-option="1"] th:nth-child(2) { + display: none; + } + + label { + user-select: none; + } - +

Decompilation Status

- -
- - -
- - -
AddressNameMatching
+ + +
+
+ Options: + + + + +
+
+ Search filters on: + + + + + + +
+
+

Results:

+ + + + + + + + + + +
AddressNameMatching
+
+ + + diff --git a/tools/roadmap/roadmap.py b/tools/roadmap/roadmap.py new file mode 100644 index 00000000..379fcfc2 --- /dev/null +++ b/tools/roadmap/roadmap.py @@ -0,0 +1,482 @@ +"""For all addresses matched by code annotations or recomp pdb, +report how "far off" the recomp symbol is from its proper place +in the original binary.""" + +import os +import argparse +import logging +import statistics +import bisect +from typing import Iterator, List, Optional, Tuple +from collections import namedtuple +from isledecomp import Bin as IsleBin +from isledecomp.cvdump import Cvdump +from isledecomp.compare import Compare as IsleCompare +from isledecomp.types import SymbolType + +# Ignore all compare-db messages. +logging.getLogger("isledecomp.compare").addHandler(logging.NullHandler()) + + +def or_blank(value) -> str: + """Helper for dealing with potential None values in text output.""" + return "" if value is None else str(value) + + +class ModuleMap: + """Load a subset of sections from the pdb to allow you to look up the + module number based on the recomp address.""" + + def __init__(self, pdb, binfile) -> None: + cvdump = Cvdump(pdb).section_contributions().modules().run() + self.module_lookup = {m.id: (m.lib, m.obj) for m in cvdump.modules} + self.library_lookup = {m.obj: m.lib for m in cvdump.modules} + self.section_contrib = [ + ( + binfile.get_abs_addr(sizeref.section, sizeref.offset), + sizeref.size, + sizeref.module, + ) + for sizeref in cvdump.sizerefs + if binfile.is_valid_section(sizeref.section) + ] + + # For bisect performance enhancement + self.contrib_starts = [start for (start, _, __) in self.section_contrib] + + def get_lib_for_module(self, module: str) -> Optional[str]: + return self.library_lookup.get(module) + + def get_all_cmake_modules(self) -> List[str]: + return [ + obj + for (_, (__, obj)) in self.module_lookup.items() + if obj.startswith("CMakeFiles") + ] + + def get_module(self, addr: int) -> Optional[str]: + i = bisect.bisect_left(self.contrib_starts, addr) + # If the addr matches the section contribution start, we are in the + # right spot. Otherwise, we need to subtract one here. + # We don't want the insertion point given by bisect, but the + # section contribution that contains the address. + + (potential_start, _, __) = self.section_contrib[i] + if potential_start != addr: + i -= 1 + + # Safety catch: clamp to range of indices from section_contrib. + i = max(0, min(i, len(self.section_contrib) - 1)) + + (start, size, module_id) = self.section_contrib[i] + if start <= addr < start + size: + if (module := self.module_lookup.get(module_id)) is not None: + return module + + return None + + +def print_sections(sections): + print(" name | start | v.size | raw size") + print("---------|----------|----------|----------") + for sect in sections: + name = sect.name + print( + f"{name:>8} | {sect.virtual_address:8x} | {sect.virtual_size:8x} | {sect.size_of_raw_data:8x}" + ) + print() + + +ALLOWED_TYPE_ABBREVIATIONS = ["fun", "dat", "poi", "str", "vta"] + + +def match_type_abbreviation(mtype: Optional[SymbolType]) -> str: + """Return abbreviation of the given SymbolType name""" + if mtype is None: + return "" + + return mtype.name.lower()[:3] + + +def get_cmakefiles_prefix(module: str) -> str: + """For the given .obj, get the "CMakeFiles/something.dir/" prefix. + For lack of a better option, this is the library for this module.""" + if module.startswith("CMakeFiles"): + return "/".join(module.split("/", 2)[:2]) + "/" + + return module + + +def truncate_module_name(prefix: str, module: str) -> str: + """Remove the CMakeFiles prefix and the .obj suffix for the given module. + Input: CMakeFiles/lego1.dir/, CMakeFiles/lego1.dir/LEGO1/define.cpp.obj + Output: LEGO1/define.cpp""" + + if module.startswith(prefix): + module = module[len(prefix) :] + + if module.endswith(".obj"): + module = module[:-4] + + return module + + +def avg_remove_outliers(entries: List[int]) -> int: + """Compute the average from this list of entries (addresses) + after removing outlier values.""" + + if len(entries) == 1: + return entries[0] + + avg = statistics.mean(entries) + sd = statistics.pstdev(entries) + + return int(statistics.mean([e for e in entries if abs(e - avg) <= 2 * sd])) + + +RoadmapRow = namedtuple( + "RoadmapRow", + [ + "orig_sect_ofs", + "recomp_sect_ofs", + "orig_addr", + "recomp_addr", + "displacement", + "sym_type", + "size", + "name", + "module", + ], +) + + +class DeltaCollector: + """Reads each row of the results and aggregates information about the + placement of each module.""" + + def __init__(self, match_type: str = "fun") -> None: + # The displacement for each symbol from each module + self.disp_map = {} + + # Each address for each module + self.addresses = {} + + # The earliest address for each module + self.earliest = {} + + # String abbreviation for which symbol type we are checking + self.match_type = "fun" + + match_type = str(match_type).strip().lower()[:3] + if match_type in ALLOWED_TYPE_ABBREVIATIONS: + self.match_type = match_type + + def read_row(self, row: RoadmapRow): + if row.module is None: + return + + if row.sym_type != self.match_type: + return + + if row.orig_addr is not None: + if row.module not in self.addresses: + self.addresses[row.module] = [] + + self.addresses[row.module].append(row.orig_addr) + + if row.orig_addr < self.earliest.get(row.module, 0xFFFFFFFFF): + self.earliest[row.module] = row.orig_addr + + if row.displacement is not None: + if row.module not in self.disp_map: + self.disp_map[row.module] = [] + + self.disp_map[row.module].append(row.displacement) + + def iter_sorted(self) -> Iterator[Tuple[int, int]]: + """Compute the average address for each module, then generate them + in ascending order.""" + avg_address = { + mod: avg_remove_outliers(values) for mod, values in self.addresses.items() + } + for mod, avg in sorted(avg_address.items(), key=lambda x: x[1]): + yield (avg, mod) + + +def suggest_order(results: List[RoadmapRow], module_map: ModuleMap, match_type: str): + """Suggest the order of modules for CMakeLists.txt""" + + dc = DeltaCollector(match_type) + for row in results: + dc.read_row(row) + + # First, show the order of .obj files for the "CMake Modules" + # Meaning: the modules where the .obj file begins with "CMakeFiles". + # These are the libraries where we directly control the order. + # The library name (from cvdump) doesn't make it obvious that these are + # our libraries so we derive the name based on the CMakeFiles prefix. + leftover_modules = set(module_map.get_all_cmake_modules()) + + # A little convoluted, but we want to take the first two tokens + # of the string with '/' as the delimiter. + # i.e. CMakeFiles/isle.dir/ + # The idea is to print exactly what appears in CMakeLists.txt. + cmake_prefixes = sorted(set(get_cmakefiles_prefix(mod) for mod in leftover_modules)) + + # Save this off because we'll use it again later. + computed_order = list(dc.iter_sorted()) + + for prefix in cmake_prefixes: + print(prefix) + + last_earliest = 0 + # Show modules ordered by the computed average of addresses + for _, module in computed_order: + if not module.startswith(prefix): + continue + + leftover_modules.remove(module) + + avg_displacement = None + displacements = dc.disp_map.get(module) + if displacements is not None and len(displacements) > 0: + avg_displacement = int(statistics.mean(displacements)) + + # Call attention to any modules where ordering by earliest + # address is different from the computed order we display. + earliest = dc.earliest.get(module) + ooo_mark = "*" if earliest < last_earliest else " " + last_earliest = earliest + + code_file = truncate_module_name(prefix, module) + print(f"0x{earliest:08x}{ooo_mark} {avg_displacement:10} {code_file}") + + # These modules are included in the final binary (in some form) but + # don't contribute any symbols of the type we are checking. + # n.b. There could still be other modules that are part of + # CMakeLists.txt but are not included in the pdb for whatever reason. + # In other words: don't take the list we provide as the final word on + # what should or should not be included. + # This is merely a suggestion of the order. + for module in leftover_modules: + if not module.startswith(prefix): + continue + + # aligned with previous print + code_file = truncate_module_name(prefix, module) + print(f" no suggestion {code_file}") + + print() + + # Now display the order of all libaries in the final file. + library_order = {} + + for start, module in computed_order: + lib = module_map.get_lib_for_module(module) + if lib is None: + lib = get_cmakefiles_prefix(module) + + if start < library_order.get(lib, 0xFFFFFFFFF): + library_order[lib] = start + + print("Library order (average address shown):") + for lib, start in sorted(library_order.items(), key=lambda x: x[1]): + # Strip off any OS path for brevity + if not lib.startswith("CMakeFiles"): + lib = os.path.basename(lib) + + print(f"{lib:40} {start:08x}") + + +def print_text_report(results: List[RoadmapRow]): + """Print the result with original and recomp addresses.""" + for row in results: + print( + " ".join( + [ + f"{or_blank(row.orig_sect_ofs):14}", + f"{or_blank(row.recomp_sect_ofs):14}", + f"{or_blank(row.displacement):>8}", + f"{row.sym_type:3}", + f"{or_blank(row.size):6}", + or_blank(row.name), + ] + ) + ) + + +def print_diff_report(results: List[RoadmapRow]): + """Print only entries where we have the recomp address. + This is intended for generating a file to diff against. + The recomp addresses are always changing so we hide those.""" + for row in results: + if row.orig_addr is None or row.recomp_addr is None: + continue + + print( + " ".join( + [ + f"{or_blank(row.orig_sect_ofs):14}", + f"{or_blank(row.displacement):>8}", + f"{row.sym_type:3}", + f"{or_blank(row.size):6}", + or_blank(row.name), + ] + ) + ) + + +def export_to_csv(csv_file: str, results: List[RoadmapRow]): + with open(csv_file, "w+", encoding="utf-8") as f: + f.write( + "orig_sect_ofs,recomp_sect_ofs,orig_addr,recomp_addr,displacement,row_type,size,name,module\n" + ) + for row in results: + f.write(",".join(map(or_blank, row))) + f.write("\n") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Show all addresses from original and recomp." + ) + parser.add_argument( + "original", metavar="original-binary", help="The original binary" + ) + parser.add_argument( + "recompiled", metavar="recompiled-binary", help="The recompiled binary" + ) + parser.add_argument( + "pdb", metavar="recompiled-pdb", help="The PDB of the recompiled binary" + ) + parser.add_argument( + "decomp_dir", metavar="decomp-dir", help="The decompiled source tree" + ) + parser.add_argument("--csv", metavar="", help="If set, export to CSV") + parser.add_argument( + "--verbose", "-v", action="store_true", help="Show recomp addresses in output" + ) + parser.add_argument( + "--order", + const="fun", + nargs="?", + type=str, + help="Show suggested order of modules (using the specified symbol type)", + ) + + (args, _) = parser.parse_known_args() + + if not os.path.isfile(args.original): + parser.error(f"Original binary {args.original} does not exist") + + if not os.path.isfile(args.recompiled): + parser.error(f"Recompiled binary {args.recompiled} does not exist") + + if not os.path.isfile(args.pdb): + parser.error(f"Symbols PDB {args.pdb} does not exist") + + if not os.path.isdir(args.decomp_dir): + parser.error(f"Source directory {args.decomp_dir} does not exist") + + return args + + +def main(): + args = parse_args() + + with IsleBin(args.original, find_str=True) as orig_bin, IsleBin( + args.recompiled + ) as recomp_bin: + engine = IsleCompare(orig_bin, recomp_bin, args.pdb, args.decomp_dir) + + module_map = ModuleMap(args.pdb, recomp_bin) + + def is_same_section(orig: int, recomp: int) -> bool: + """Compare the section name instead of the index. + LEGO1.dll adds extra sections for some reason. (Smacker library?)""" + + try: + orig_name = orig_bin.sections[orig - 1].name + recomp_name = recomp_bin.sections[recomp - 1].name + return orig_name == recomp_name + except IndexError: + return False + + def to_roadmap_row(match): + orig_sect = None + orig_ofs = None + orig_sect_ofs = None + recomp_sect = None + recomp_ofs = None + recomp_sect_ofs = None + orig_addr = None + recomp_addr = None + displacement = None + module_name = None + + if match.recomp_addr is not None: + if (module_ref := module_map.get_module(match.recomp_addr)) is not None: + (_, module_name) = module_ref + + row_type = match_type_abbreviation(match.compare_type) + name = ( + repr(match.name) + if match.compare_type == SymbolType.STRING + else match.name + ) + + if match.orig_addr is not None: + orig_addr = match.orig_addr + (orig_sect, orig_ofs) = orig_bin.get_relative_addr(match.orig_addr) + orig_sect_ofs = f"{orig_sect:04}:{orig_ofs:08x}" + + if match.recomp_addr is not None: + recomp_addr = match.recomp_addr + (recomp_sect, recomp_ofs) = recomp_bin.get_relative_addr( + match.recomp_addr + ) + recomp_sect_ofs = f"{recomp_sect:04}:{recomp_ofs:08x}" + + if ( + orig_sect is not None + and recomp_sect is not None + and is_same_section(orig_sect, recomp_sect) + ): + displacement = recomp_ofs - orig_ofs + + return RoadmapRow( + orig_sect_ofs, + recomp_sect_ofs, + orig_addr, + recomp_addr, + displacement, + row_type, + match.size, + name, + module_name, + ) + + results = list(map(to_roadmap_row, engine.get_all())) + + if args.order is not None: + suggest_order(results, module_map, args.order) + return + + if args.csv is None: + if args.verbose: + print("ORIG sections:") + print_sections(orig_bin.sections) + + print("RECOMP sections:") + print_sections(recomp_bin.sections) + + print_text_report(results) + else: + print_diff_report(results) + + if args.csv is not None: + export_to_csv(args.csv, results) + + +if __name__ == "__main__": + main() diff --git a/tools/vtable/vtable.py b/tools/vtable/vtable.py old mode 100644 new mode 100755 index bdee080b..eb09412c --- a/tools/vtable/vtable.py +++ b/tools/vtable/vtable.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import os import argparse import logging @@ -5,7 +7,7 @@ import colorama from isledecomp.bin import Bin as IsleBin from isledecomp.compare import Compare as IsleCompare -from isledecomp.utils import print_diff +from isledecomp.utils import print_combined_diff # Ignore all compare-db messages. logging.getLogger("isledecomp.compare").addHandler(logging.NullHandler()) @@ -51,13 +53,8 @@ def parse_args() -> argparse.Namespace: return args -def show_vtable_diff(udiff: List[str], verbose: bool = False, plain: bool = False): - lines = [ - line - for line in udiff - if verbose or line.startswith("+") or line.startswith("-") - ] - print_diff(lines, plain) +def show_vtable_diff(udiff: List, _: bool = False, plain: bool = False): + print_combined_diff(udiff, plain) def print_summary(vtable_count: int, problem_count: int): diff --git a/util/compat.h b/util/compat.h index b38a1c7c..ea2a6507 100644 --- a/util/compat.h +++ b/util/compat.h @@ -7,14 +7,6 @@ #define COMPAT_MODE #endif -// Use `COMPAT_CONST` where something ought to be 'const', and a newer compiler would complain if it -// wasn't, but we know it isn't 'const' in the original code. -#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1100) -#define COMPAT_CONST const -#else -#define COMPAT_CONST -#endif - // Disable "identifier was truncated to '255' characters" warning. // Impossible to avoid this if using STL map or set. // This removes most (but not all) occurrences of the warning. diff --git a/util/decomp.h b/util/decomp.h index 3470fcc3..100f9f21 100644 --- a/util/decomp.h +++ b/util/decomp.h @@ -14,7 +14,7 @@ #endif #ifndef _countof -#define _countof(arr) sizeof(arr) / sizeof(arr[0]) +#define _countof(arr) (sizeof(arr) / sizeof(arr[0])) #endif typedef unsigned char undefined;