diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index e139b8bf..01b85f47 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: decomplint-isle: + name: 'ISLE annotations' runs-on: ubuntu-latest steps: @@ -18,6 +19,7 @@ jobs: python3 tools/decomplint/decomplint.py ISLE --module ISLE --warnfail decomplint-lego1: + name: 'LEGO1 annotations' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c285836..419033cc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,53 @@ name: Build on: [push, pull_request] jobs: + build-current-toolchain: + name: 'Current ${{ matrix.toolchain.name }}' + runs-on: windows-latest + defaults: + run: + shell: ${{ matrix.toolchain.shell }} + strategy: + fail-fast: false + matrix: + toolchain: + - { name: 'MSVC', shell: 'sh', setup-cmake: true, setup-ninja: true, setup-msvc: true } + - { name: 'msys2 mingw32', shell: 'msys2 {0}', setup-msys2: true } + + steps: + - name: Set up MSYS2 + if: matrix.toolchain.setup-msys2 + uses: msys2/setup-msys2@v2 + with: + msystem: mingw32 + install: >- + mingw-w64-i686-cc + mingw-w64-i686-cmake + mingw-w64-i686-ninja + + - name: Setup cmake + if: matrix.toolchain.setup-cmake + uses: jwlawson/actions-setup-cmake@v1.13 + + - name: Setup ninja + if: matrix.toolchain.setup-ninja + uses: ashutoshvarma/setup-ninja@master + + - name: Setup vcvars + if: matrix.toolchain.setup-msvc + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: amd64_x86 # Use the 64-bit x64-native cross tools to build 32-bit x86 code + + - uses: actions/checkout@v3 + + - name: Build + run: | + cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -GNinja -Werror=dev + cmake --build build + build: + name: 'MSVC 4.20' runs-on: windows-latest steps: @@ -28,10 +74,8 @@ jobs: shell: cmd run: | call .\msvc420\bin\VCVARS32.BAT x86 - mkdir build - cd build - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "NMake Makefiles" - cmake --build . + cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "NMake Makefiles" + cmake --build build - name: Upload Artifact uses: actions/upload-artifact@master @@ -44,6 +88,7 @@ jobs: build/LEGO1.PDB compare: + name: 'Compare with master' needs: build runs-on: windows-latest steps: @@ -109,6 +154,7 @@ jobs: LEGO1PROGRESS.* upload: + name: 'Upload artifacts' needs: [build, compare] runs-on: ubuntu-latest if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'isledecomp/isle' }} diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 07b646fb..ccec2b50 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: clang-format: + name: 'C++' runs-on: ubuntu-latest steps: @@ -19,6 +20,7 @@ jobs: -i python-format: + name: 'Python' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/naming.yml b/.github/workflows/naming.yml index 163354d5..a23275e1 100644 --- a/.github/workflows/naming.yml +++ b/.github/workflows/naming.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: ncc: + name: 'C++' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index 06446888..612ae3ae 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -1,9 +1,10 @@ -name: Unit Tests +name: Test on: [push, pull_request] jobs: pytest-win: + name: 'Python Windows' runs-on: windows-latest steps: @@ -20,6 +21,7 @@ jobs: pytest tools/isledecomp pytest-ubuntu: + name: 'Python Linux' runs-on: ubuntu-latest steps: diff --git a/CMakeLists.txt b/CMakeLists.txt index 483ba9db..61a8d165 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,24 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) project(isle CXX) +math(EXPR bits "8 * ${CMAKE_SIZEOF_VOID_P}") +message(STATUS "Building ${bits}-bit LEGO Island") +if (NOT bits EQUAL 32) + message(WARNING "Only 32-bit executables are supported") +endif() + +set(MSVC_FOR_DECOMP FALSE) +if (MSVC) + # Visual C++ 4.2 -> cl version 10.2.0 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "11.0") + set(MSVC_FOR_DECOMP TRUE) + endif() +endif() + +message(STATUS "MSVC for decompilation: ${MSVC_FOR_DECOMP}") + option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) -option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC}) +option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC_FOR_DECOMP}) option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" ON) add_library(lego1 SHARED @@ -42,7 +58,9 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/common/legoutil.cpp LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp + LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp LEGO1/lego/legoomni/src/entity/legoactor.cpp + LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp LEGO1/lego/legoomni/src/entity/legoanimactor.cpp LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -81,7 +99,7 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/isle/jukebox.cpp LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp LEGO1/lego/legoomni/src/isle/jukeboxstate.cpp - LEGO1/lego/legoomni/src/isle/motorcycle.cpp + LEGO1/lego/legoomni/src/isle/motocycle.cpp LEGO1/lego/legoomni/src/isle/radio.cpp LEGO1/lego/legoomni/src/isle/radiostate.cpp LEGO1/lego/legoomni/src/isle/skateboard.cpp @@ -123,8 +141,11 @@ add_library(lego1 SHARED 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 @@ -161,11 +182,9 @@ add_library(lego1 SHARED LEGO1/omni/src/common/mxutil.cpp LEGO1/omni/src/common/mxvariable.cpp LEGO1/omni/src/common/mxvariabletable.cpp - LEGO1/omni/src/control/mxcontrolpresenter.cpp LEGO1/omni/src/entity/mxentity.cpp LEGO1/omni/src/event/mxeventmanager.cpp LEGO1/omni/src/event/mxeventpresenter.cpp - LEGO1/omni/src/main/mxmain.cpp LEGO1/omni/src/main/mxomni.cpp LEGO1/omni/src/main/mxomnicreateflags.cpp LEGO1/omni/src/main/mxomnicreateparam.cpp @@ -275,6 +294,8 @@ if (ISLE_BUILD_APP) 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") @@ -300,6 +321,29 @@ if (ISLE_BUILD_APP) 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) + target_compile_definitions(isle 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) + target_compile_options(isle 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") + endif() +endif() + +if (MSVC_FOR_DECOMP) # These flags have been taken from the defaults for a Visual C++ 4.20 project (the compiler the # game was originally built with) and tweaked slightly to produce more debugging info for reccmp. # They ensure a recompilation that can be byte/instruction accurate to the original binaries. diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index d6f9c293..4a2a840b 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -614,8 +614,8 @@ MxResult IsleApp::SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine) LegoAnimationManager::configureLegoAnimationManager(m_islandQuality); if (LegoOmni::GetInstance()) { if (LegoOmni::GetInstance()->GetInputManager()) { - LegoOmni::GetInstance()->GetInputManager()->m_useJoystick = m_useJoystick; - LegoOmni::GetInstance()->GetInputManager()->m_joystickIndex = m_joystickIndex; + LegoOmni::GetInstance()->GetInputManager()->SetUseJoystick(m_useJoystick); + LegoOmni::GetInstance()->GetInputManager()->SetJoystickIndex(m_joystickIndex); } } if (m_fullScreen) { @@ -792,11 +792,11 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) LegoOmni::GetInstance()->CreateBackgroundAudio(); BackgroundAudioManager()->Enable(this->m_useMusic); - MxStreamController* stream = Streamer()->Open("\\lego\\scripts\\isle\\isle", MxStreamer::e_DiskStream); + MxStreamController* stream = Streamer()->Open("\\lego\\scripts\\isle\\isle", MxStreamer::e_diskStream); MxDSAction ds; if (!stream) { - stream = Streamer()->Open("\\lego\\scripts\\nocd", MxStreamer::e_DiskStream); + stream = Streamer()->Open("\\lego\\scripts\\nocd", MxStreamer::e_diskStream); if (!stream) { return; } diff --git a/ISLE/library_msvc.h b/ISLE/library_msvc.h new file mode 100644 index 00000000..a837fd3b --- /dev/null +++ b/ISLE/library_msvc.h @@ -0,0 +1,63 @@ +#ifdef 0 +// For ISLE symbols only + +// aka `operator new` +// LIBRARY: ISLE 0x402f80 +// ??2@YAPAXI@Z + +// aka `operator delete` +// LIBRARY: ISLE 0x402fa0 +// ??3@YAXPAX@Z + +// LIBRARY: ISLE 0x406dd0 +// _malloc + +// LIBRARY: ISLE 0x406f00 +// _free + +// LIBRARY: ISLE 0x407ec0 +// ___CxxFrameHandler + +// LIBRARY: ISLE 0x4081e0 +// _srand + +// LIBRARY: ISLE 0x4081f0 +// _rand + +// LIBRARY: ISLE 0x408220 +// _atol + +// LIBRARY: ISLE 0x4082d0 +// _atoi + +// LIBRARY: ISLE 0x4084c0 +// ?_query_new_handler@@YAP6AHI@ZXZ + +// LIBRARY: ISLE 0x4084d0 +// ?_query_new_mode@@YAHXZ + +// LIBRARY: ISLE 0x4085c0 +// _sprintf + +// LIBRARY: ISLE 0x408630 +// _abort + +// LIBRARY: ISLE 0x409110 +// __mtinit + +// LIBRARY: ISLE 0x409190 +// __getptd + +// GLOBAL: ISLE 0x4108e8 +// __osver + +// GLOBAL: ISLE 0x4108f0 +// __winmajor + +// GLOBAL: ISLE 0x4108f4 +// __winminor + +// GLOBAL: ISLE 0x410d50 +// __newmode + +#endif diff --git a/ISLE/library_smartheap.h b/ISLE/library_smartheap.h new file mode 100644 index 00000000..53ef5f0d --- /dev/null +++ b/ISLE/library_smartheap.h @@ -0,0 +1,312 @@ +#ifdef 0 + +// LIBRARY: ISLE 0x402f10 +// ?shi_New@@YAPAXKIPAU_SHI_Pool@@@Z + +// LIBRARY: ISLE 0x402fb0 +// _MemInitDefaultPool@0 + +// LIBRARY: ISLE 0x403020 +// _shi_call_new_handler_msc + +// LIBRARY: ISLE 0x403050 +// _MemPoolShrink@4 + +// LIBRARY: ISLE 0x403180 +// _MemPoolPreAllocate@12 + +// LIBRARY: ISLE 0x403300 +// @_shi_initPageHeaders@4 + +// LIBRARY: ISLE 0x403570 +// @shi_allocPageHeader@4 + +// LIBRARY: ISLE 0x4035a0 +// @shi_freePageHeader@8 + +// LIBRARY: ISLE 0x403750 +// @_shi_deletePage@8 + +// LIBRARY: ISLE 0x403830 +// @_shi_allocExternal@12 + +// LIBRARY: ISLE 0x403a50 +// @_shi_initPageVariable@8 + +// LIBRARY: ISLE 0x403b00 +// _MemAllocPtr@12 + +// LIBRARY: ISLE 0x403d60 +// @_shi_allocVar@12 + +// LIBRARY: ISLE 0x403ef0 +// @_shi_allocBlock@12 + +// LIBRARY: ISLE 0x4040c0 +// _MemFreePtr@4 + +// LIBRARY: ISLE 0x404170 +// @_shi_freeVar@4 + +// LIBRARY: ISLE 0x404260 +// _MemReAllocPtr@12 + +// LIBRARY: ISLE 0x4043b0 +// @_shi_resizeAny@16 + +// LIBRARY: ISLE 0x404650 +// @_shi_resizeVar@8 + +// LIBRARY: ISLE 0x404820 +// _MemSizePtr@4 + +// LIBRARY: ISLE 0x4048d0 +// @shi_findAllocAddress@4 + +// LIBRARY: ISLE 0x404910 +// @_shi_sysAlloc@8 + +// LIBRARY: ISLE 0x4049a0 +// @_shi_sysFree@4 + +// LIBRARY: ISLE 0x404a00 +// @_shi_sysRealloc@12 + +// LIBRARY: ISLE 0x404ab0 +// @_shi_sysResize@12 + +// LIBRARY: ISLE 0x404b90 +// @_shi_sysSize@4 + +// LIBRARY: ISLE 0x404bd0 +// @_shi_sysAllocNear@4 + +// LIBRARY: ISLE 0x404bf0 +// @_shi_sysFreeNear@4 + +// LIBRARY: ISLE 0x404c10 +// @_shi_sysValidatePtr@12 + +// LIBRARY: ISLE 0x404d10 +// @_shi_sysValidateFunction@4 + +// LIBRARY: ISLE 0x405300 +// @_shi_sysAllocPool@12 + +// LIBRARY: ISLE 0x405520 +// @_shi_sysResizePool@16 + +// LIBRARY: ISLE 0x405690 +// @_shi_sysFreePage@4 + +// LIBRARY: ISLE 0x4057b0 +// @_shi_sysSizePage@4 + +// LIBRARY: ISLE 0x4057e0 +// @_shi_sysSizePool@8 + +// LIBRARY: ISLE 0x405800 +// @_shi_registerShared@16 + +// LIBRARY: ISLE 0x405a00 +// @_shi_unregisterShared@8 + +// LIBRARY: ISLE 0x405b20 +// @_shi_getNextPool@4 + +// LIBRARY: ISLE 0x405b30 +// @shi_delNextPool@4 + +// LIBRARY: ISLE 0x405d30 +// @shi_createAndEnterMutexShr@12 + +// LIBRARY: ISLE 0x405e20 +// @shi_termPoolMutexShr@4 + +// LIBRARY: ISLE 0x405e40 +// @shi_enterPoolMutexShr@4 + +// LIBRARY: ISLE 0x405e60 +// @shi_leavePoolMutexShr@4 + +// LIBRARY: ISLE 0x405e80 +// __shi_enterCriticalSection@0 + +// LIBRARY: ISLE 0x405ea0 +// __shi_leaveCriticalSection@0 + +// LIBRARY: ISLE 0x405ec0 +// __shi_createAndEnterMutex + +// LIBRARY: ISLE 0x405ef0 +// _shi_enterPoolMutexSafely + +// LIBRARY: ISLE 0x405fd0 +// _shi_enterPoolInitMutexReader + +// LIBRARY: ISLE 0x406060 +// _shi_leavePoolInitMutexReader + +// LIBRARY: ISLE 0x406090 +// _shi_enterPoolInitMutexWriter + +// LIBRARY: ISLE 0x406160 +// _shi_leavePoolInitMutexWriter + +// LIBRARY: ISLE 0x406180 +// _shi_isNT + +// LIBRARY: ISLE 0x4061b0 +// _MemPoolInit@4 + +// LIBRARY: ISLE 0x406520 +// _MemPoolSetPageSize@8 + +// LIBRARY: ISLE 0x406630 +// _MemPoolSetBlockSizeFS@8 + +// LIBRARY: ISLE 0x406710 +// @_shi_poolFree@8 + +// LIBRARY: ISLE 0x4068c0 +// @_shi_invokeErrorHandler1@8 + +// LIBRARY: ISLE 0x406be0 +// _MemErrorUnwind@0 + +// LIBRARY: ISLE 0x406c30 +// _MemDefaultErrorHandler@4 + +// LIBRARY: ISLE 0x406cb0 +// @_shi_taskRemovePool@4 + +// LIBRARY: ISLE 0x406d50 +// @_shi_getCurrentThreadContext@8 + +// LIBRARY: ISLE 0x406db0 +// @_shi_deleteThreadContext@8 + +// LIBRARY: ISLE 0x406e40 +// _calloc + +// LIBRARY: ISLE 0x406ea0 +// _realloc + +// LIBRARY: ISLE 0x406f10 +// __expand + +// LIBRARY: ISLE 0x406f50 +// __heapadd + +// LIBRARY: ISLE 0x406f60 +// __heapwalk + +// LIBRARY: ISLE 0x406ff0 +// __heapused + +// LIBRARY: ISLE 0x407020 +// __heapmin + +// LIBRARY: ISLE 0x407040 +// __msize + +// LIBRARY: ISLE 0x407050 +// __heapchk + +// LIBRARY: ISLE 0x407080 +// __heapset + +// LIBRARY: ISLE 0x407090 +// @_shi_sysReportError@16 + +// LIBRARY: ISLE 0x407110 +// _MemPoolSize@4 + +// LIBRARY: ISLE 0x4071a0 +// _MemPoolWalk@8 + +// LIBRARY: ISLE 0x407240 +// @_shi_walkPool@16 + +// LIBRARY: ISLE 0x407540 +// @shi_isBlockInUseSmall@8 + +// LIBRARY: ISLE 0x407800 +// @_shi_isBlockInUseFS@12 + +// LIBRARY: ISLE 0x407880 +// _MemPoolCheck@4 + +// LIBRARY: ISLE 0x407b20 +// _MemCheckPtr@8 + +// LIBRARY: ISLE 0x4084e0 +// __except_handler3 + +// GLOBAL: ISLE 0x40f0a0 +// _szLibName + +// GLOBAL: ISLE 0x4102f4 +// ?_new_handler@@3P6AXXZA + +// GLOBAL: ISLE 0x4102fc +// _MemDefaultPool + +// GLOBAL: ISLE 0x41031c +// __shi_compactPoolFn + +// GLOBAL: ISLE 0x410320 +// __shi_compactPageFn + +// GLOBAL: ISLE 0x410324 +// _MemDefaultPoolFlags + +// GLOBAL: ISLE 0x41032c +// __shi_mutexGlobalInit + +// GLOBAL: ISLE 0x410330 +// __shi_mutexMovInit + +// GLOBAL: ISLE 0x410334 +// __shi_mutexMovLockCount + +// GLOBAL: ISLE 0x410338 +// _shi_initPoolReaders + +// GLOBAL: ISLE 0x41033c +// _shi_eventInitPool + +// GLOBAL: ISLE 0x410340 +// _shi_mutexMovShr + +// GLOBAL: ISLE 0x410368 +// _shi_deferFreePools + +// GLOBAL: ISLE 0x410378 +// __shi_poolTerminating + +// GLOBAL: ISLE 0x41037c +// _MemDefaultPoolBlockSizeFS + +// GLOBAL: ISLE 0x410380 +// _MemDefaultPoolPageSize + +// GLOBAL: ISLE 0x410384 +// _SmartHeap_malloc + +// GLOBAL: ISLE 0x4105b0 +// __shi_TaskRecord + +// GLOBAL: ISLE 0x4125f8 +// ?_pnhHeap@@3P6AHI@ZA + +// GLOBAL: ISLE 0x412830 +// __shi_mutexMov + +// GLOBAL: ISLE 0x412850 +// _shi_mutexPoolSynch + +// GLOBAL: ISLE 0x412870 +// __shi_mutexGlobal + +#endif diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 3f3f70ac..1e403a50 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -10,20 +10,26 @@ MxS32 g_mxcoreCount[101] = {0, -6643, -5643, -5058, -4643, -4321, -4058, -38 -358, -340, -321, -304, -286, -268, -251, -234, -217, -200, -184, -168, -152, -136, -120, -104, -89, -74, -58, -43, -29, -14, 0}; -// GLOBAL: LEGO1 0x10101eac -const char* g_parseExtraTokens = ":;"; - -// GLOBAL: LEGO1 0x10101edc -const char* g_strWORLD = "WORLD"; - -// GLOBAL: LEGO1 0x10101f20 -const char* g_strSOUND = "SOUND"; - -// GLOBAL: LEGO1 0x10101f58 -const char* g_strOBJECT = "OBJECT"; - -// GLOBAL: LEGO1 0x10102040 +// GLOBAL: LEGO1 0x10102048 +// STRING: LEGO1 0x10102040 const char* g_strACTION = "ACTION"; +// GLOBAL: LEGO1 0x1010209c +// STRING: LEGO1 0x10101f58 +const char* g_strOBJECT = "OBJECT"; + +// GLOBAL: LEGO1 0x101020b0 +// STRING: LEGO1 0x10101f20 +const char* g_strSOUND = "SOUND"; + // GLOBAL: LEGO1 0x101020cc +// STRING: LEGO1 0x100f3808 const char* g_strVISIBILITY = "VISIBILITY"; + +// GLOBAL: LEGO1 0x101020d0 +// STRING: LEGO1 0x10101edc +const char* g_strWORLD = "WORLD"; + +// GLOBAL: LEGO1 0x101020e4 +// STRING: LEGO1 0x10101eac +const char* g_parseExtraTokens = ":;"; diff --git a/LEGO1/lego/legoomni/include/act1state.h b/LEGO1/lego/legoomni/include/act1state.h index d0daec7d..84537e88 100644 --- a/LEGO1/lego/legoomni/include/act1state.h +++ b/LEGO1/lego/legoomni/include/act1state.h @@ -24,10 +24,21 @@ class Act1State : public LegoState { 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; } + + void FUN_10034d00(); 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 }; #endif // ACT1STATE_H diff --git a/LEGO1/lego/legoomni/include/elevatorbottom.h b/LEGO1/lego/legoomni/include/elevatorbottom.h index 64b3f221..e10b7727 100644 --- a/LEGO1/lego/legoomni/include/elevatorbottom.h +++ b/LEGO1/lego/legoomni/include/elevatorbottom.h @@ -1,9 +1,11 @@ #ifndef ELEVATORBOTTOM_H #define ELEVATORBOTTOM_H +#include "decomp.h" #include "legoworld.h" // VTABLE: LEGO1 0x100d5f20 +// SIZE: 0xfc (from inlined ctor at 0x1000a8aa) class ElevatorBottom : public LegoWorld { public: ElevatorBottom(); @@ -23,6 +25,9 @@ class ElevatorBottom : public LegoWorld { { return !strcmp(p_name, ElevatorBottom::ClassName()) || LegoWorld::IsA(p_name); } + +private: + undefined4 m_unk0xf8; // 0xf8 }; #endif // ELEVATORBOTTOM_H diff --git a/LEGO1/lego/legoomni/include/extra.h b/LEGO1/lego/legoomni/include/extra.h index e8aed106..35f08033 100644 --- a/LEGO1/lego/legoomni/include/extra.h +++ b/LEGO1/lego/legoomni/include/extra.h @@ -3,19 +3,21 @@ // Items related to the Extra string of key-value pairs found in MxOb -enum ExtraActionType { - ExtraActionType_none = 0, - ExtraActionType_opendisk = 1, - ExtraActionType_openram = 2, - ExtraActionType_close = 3, - ExtraActionType_start = 4, - ExtraActionType_stop = 5, - ExtraActionType_run = 6, - ExtraActionType_exit = 7, - ExtraActionType_enable = 8, - ExtraActionType_disable = 9, - ExtraActionType_notify = 10, - ExtraActionType_unknown = 11, +struct Extra { + enum ActionType { + e_none = 0, + e_opendisk, + e_openram, + e_close, + e_start, + e_stop, + e_run, + e_exit, + e_enable, + e_disable, + e_notify, + e_unknown, + }; }; #endif // EXTRA_H diff --git a/LEGO1/lego/legoomni/include/gasstation.h b/LEGO1/lego/legoomni/include/gasstation.h index 0617e161..11ff175a 100644 --- a/LEGO1/lego/legoomni/include/gasstation.h +++ b/LEGO1/lego/legoomni/include/gasstation.h @@ -1,7 +1,9 @@ #ifndef GASSTATION_H #define GASSTATION_H +#include "decomp.h" #include "legoworld.h" +#include "radio.h" // VTABLE: LEGO1 0x100d4650 // SIZE 0x128 @@ -26,6 +28,20 @@ class GasStation : public LegoWorld { { return !strcmp(p_name, GasStation::ClassName()) || LegoWorld::IsA(p_name); } + +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 }; #endif // GASSTATION_H diff --git a/LEGO1/lego/legoomni/include/helicopter.h b/LEGO1/lego/legoomni/include/helicopter.h index 7c5be4ea..ec4faa59 100644 --- a/LEGO1/lego/legoomni/include/helicopter.h +++ b/LEGO1/lego/legoomni/include/helicopter.h @@ -9,12 +9,12 @@ class HelicopterSubclass { public: inline HelicopterSubclass() : m_unk0x30(0) {} - MxResult FUN_100040a0(Vector4Impl& p_v, float p_f); + MxResult FUN_100040a0(Vector4& p_v, float p_f); private: - Vector4Data m_unk0x0; // 0x0 - Vector4Data m_unk0x18; // 0x18 - undefined4 m_unk0x30; // 0x30 + Mx4DPointFloat m_unk0x0; // 0x0 + Mx4DPointFloat m_unk0x18; // 0x18 + undefined4 m_unk0x30; // 0x30 }; // VTABLE: LEGO1 0x100d40f8 @@ -37,9 +37,9 @@ class Helicopter : public IslePathActor { return !strcmp(p_name, Helicopter::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 void VTable0x70(float p_float) override; // vtable+0x70 - void VTable0x74(Matrix4Impl& p_transform) override; // vtable+0x74 + 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 @@ -49,8 +49,8 @@ class Helicopter : public IslePathActor { // Helicopter::`scalar deleting destructor' protected: - Matrix4Data m_unk0x160; // 0x160 - Matrix4Data m_unk0x1a8; // 0x1a8 + MxMatrix m_unk0x160; // 0x160 + MxMatrix m_unk0x1a8; // 0x1a8 float m_unk0x1f0; // 0x1f0 HelicopterSubclass m_unk0x1f4; // 0x1f4 HelicopterState* m_state; // 0x228 diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index ec0be745..da17941b 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -2,11 +2,111 @@ #define INFOCENTER_H #include "legoworld.h" +#include "radio.h" + +class InfocenterState; + +// SIZE 0x18 +struct InfocenterUnkDataEntry { + // FUNCTION: LEGO1 0x1006ec80 + InfocenterUnkDataEntry() {} + + undefined m_pad[0x18]; +}; // VTABLE: LEGO1 0x100d9338 // SIZE 0x1d8 class Infocenter : public LegoWorld { public: + enum Cutscene { + e_noIntro = -1, + e_legoMovie, + e_mindscapeMovie, + e_introMovie, + e_outroMovie, + e_badEndMovie, + e_goodEndMovie + }; + + enum InfomainScript { + c_noInfomain = -1, + + c_welcomeDialogue = 500, + c_goodJobDialogue = 501, + + c_clickOnInfomanDialogue = 502, + c_tickleInfomanDialogue = 503, + + c_letsGetStartedDialogue = 504, + + c_clickOnObjectsGuidanceDialogue = 505, + c_arrowNavigationGuidanceDialogue = 506, + c_elevatorGuidanceDialogue = 507, + c_radioGuidanceDialogue = 508, + c_exitGuidanceDialogue1 = 509, + c_exitGuidanceDialogue2 = 510, + c_goOutsideGuidanceDialogue = 511, + c_experimentGuidanceDialogue = 512, + c_returnBackGuidanceDialogue1 = 513, + c_returnBackGuidanceDialogue2 = 514, + c_bricksterWarningDialogue = 515, + c_newGameGuidanceDialogue = 516, + c_returnBackGuidanceDialogue3 = 517, + + c_reenterInfoCenterDialogue1 = 518, + c_reenterInfoCenterDialogue2 = 519, + c_reenterInfoCenterDialogue3 = 520, + c_reenterInfoCenterDialogue4 = 521, + + c_exitConfirmationDialogue = 522, + c_saveGameOptionsDialogueUnused = 523, + c_exitGameDialogue = 524, + + c_bricksterEscapedDialogue1 = 525, + c_bricksterEscapedDialogue2 = 526, + c_bricksterEscapedDialogue3 = 527, + c_bricksterEscapedDialogue4 = 528, + c_bricksterEscapedDialogue5 = 529, + c_bricksterEscapedDialogue6 = 530, + c_bricksterEscapedDialogue7 = 531, + + c_infomanHiccup = 532, + c_infomanWalkOffScreenLeftUnused = 533, + c_infomanSneeze = 534, + c_infomanWalkOffScreenRightUnused = 535, + c_infomanLaughs = 536, + c_infomanLooksBehindAtScreenUnused = 537, + c_infomanReturnsFromScreenUnused = 538, + + c_goodEndingDialogue = 539, + c_badEndingDialogue = 540, + + c_pepperCharacterSelect = 541, + c_mamaCharacterSelect = 542, + c_papaCharacterSelect = 543, + c_nickCharacterSelect = 544, + c_lauraCharacterSelect = 545, + + c_creditsDialogue = 551, + + c_noCDDialogueUnused1 = 552, + c_noCDDialogueUnused2 = 553, + + c_leaveInfoCenterDialogue1 = 562, + c_leaveInfoCenterDialogue2 = 563, + c_leaveInfoCenterDialogue3 = 564, + c_leaveInfoCenterDialogue4 = 565, + + c_registerToContinueDialogue = 573, + + c_bricksterDialogue = 574, + c_bricksterLaughs = 575, + }; + + enum SndAmimScript { + c_bookWig = 400 + }; + Infocenter(); virtual ~Infocenter() override; @@ -26,11 +126,51 @@ class Infocenter : public LegoWorld { return !strcmp(p_name, Infocenter::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 - virtual void Stop() override; // vtable+0x50 + 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 + +private: + void InitializeBitmaps(); + + 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&); + + void FUN_10070dc0(MxBool); + void FUN_10070e90(); + + void PlayCutscene(Cutscene p_entityId, MxBool p_scale); + void StopCutscene(); + + void StartCredits(); + void StopCredits(); + + void PlayDialogue(InfomainScript p_objectId); + void StopCurrentDialogue(); + + 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 + MxU16 m_unk0x1d0; // 0x1d0 + MxU16 m_unk0x1d2; // 0x1d2 + MxU16 m_unk0x1d4; // 0x1d4 + MxU16 m_unk0x1d6; // 0x1d6 }; #endif // INFOCENTER_H diff --git a/LEGO1/lego/legoomni/include/infocenterstate.h b/LEGO1/lego/legoomni/include/infocenterstate.h index b1bce306..51dbac72 100644 --- a/LEGO1/lego/legoomni/include/infocenterstate.h +++ b/LEGO1/lego/legoomni/include/infocenterstate.h @@ -25,6 +25,9 @@ class InfocenterState : public LegoState { } inline MxU32 GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } + inline MxU32 GetUnknown0x74() { return m_unk0x74; } + + inline void SetUnknown0x74(MxU32 p_unk0x74) { m_unk0x74 = p_unk0x74; } private: // Members should be renamed with their offsets before use @@ -55,7 +58,8 @@ class InfocenterState : public LegoState { undefined4 unk13; */ - undefined m_pad[0x70]; + undefined m_pad[0x6c]; + MxU32 m_unk0x74; // 0x74 MxU32 m_buffer[7]; // 0x78 }; diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index c3579aec..5ebc5fab 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -12,7 +12,7 @@ class JukeBoxEntity; class Helicopter; class Bike; class DuneBuggy; -class Motorcycle; +class Motocycle; class SkateBoard; class RaceCar; class Jetski; @@ -40,8 +40,8 @@ class Isle : public LegoWorld { return !strcmp(p_name, Isle::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 - virtual void Stop() override; // vtable+50 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void VTable0x50() override; // vtable+50 virtual void VTable0x58(MxCore* p_object) override; // vtable+58 // FUNCTION: LEGO1 0x10030900 virtual MxBool VTable0x5c() override { return TRUE; } // vtable+5c @@ -57,6 +57,7 @@ class Isle : public LegoWorld { MxLong HandleType17Notification(MxParam& p_param); MxLong HandleType19Notification(MxParam& p_param); MxLong HandleTransitionEnd(); + void FUN_10032620(); protected: Act1State* m_act1state; // 0xf8 @@ -68,7 +69,7 @@ class Isle : public LegoWorld { Helicopter* m_helicopter; // 0x110 Bike* m_bike; // 0x114 DuneBuggy* m_dunebuggy; // 0x118 - Motorcycle* m_motorcycle; // 0x11c + Motocycle* m_motocycle; // 0x11c SkateBoard* m_skateboard; // 0x120 RaceCar* m_racecar; // 0x124 Jetski* m_jetski; // 0x128 diff --git a/LEGO1/lego/legoomni/include/isleactor.h b/LEGO1/lego/legoomni/include/isleactor.h index 8fd7d039..1c2ddc5c 100644 --- a/LEGO1/lego/legoomni/include/isleactor.h +++ b/LEGO1/lego/legoomni/include/isleactor.h @@ -20,4 +20,10 @@ class IsleActor : public LegoActor { } }; +// SYNTHETIC: LEGO1 0x1000e940 +// IsleActor::~IsleActor + +// SYNTHETIC: LEGO1 0x1000e990 +// IsleActor::`scalar deleting destructor' + #endif // ISLEACTOR_H diff --git a/LEGO1/lego/legoomni/include/islepathactor.h b/LEGO1/lego/legoomni/include/islepathactor.h index d7a8ff60..96a3dce7 100644 --- a/LEGO1/lego/legoomni/include/islepathactor.h +++ b/LEGO1/lego/legoomni/include/islepathactor.h @@ -13,6 +13,8 @@ class IslePathActor : public LegoPathActor { public: IslePathActor(); + + // FUNCTION: LEGO1 0x10002e10 inline virtual ~IslePathActor() override { IslePathActor::Destroy(TRUE); } // vtable+0x0 // FUNCTION: LEGO1 0x10002ea0 @@ -28,7 +30,8 @@ class IslePathActor : public LegoPathActor { return !strcmp(p_name, IslePathActor::ClassName()) || LegoPathActor::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c // FUNCTION: LEGO1 0x10002e70 virtual MxU32 VTable0xcc() { return 0; } // vtable+0xcc // FUNCTION: LEGO1 0x10002df0 diff --git a/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h b/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h index 746300a6..0cc18935 100644 --- a/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h @@ -9,7 +9,7 @@ // SIZE 0x68 class LegoActionControlPresenter : public MxMediaPresenter { public: - inline LegoActionControlPresenter() { m_unk0x50 = ExtraActionType_none; } + inline LegoActionControlPresenter() { m_unk0x50 = Extra::ActionType::e_none; } virtual ~LegoActionControlPresenter() override { Destroy(TRUE); }; // vtable+0x00 // FUNCTION: LEGO1 0x1000d0e0 @@ -32,9 +32,9 @@ class LegoActionControlPresenter : public MxMediaPresenter { virtual void Destroy(MxBool p_fromDestructor); // vtable+0x5c private: - ExtraActionType m_unk0x50; // 0x50 - MxString m_unk0x54; // 0x54 - undefined4 m_unk0x64; // 0x64 + Extra::ActionType m_unk0x50; // 0x50 + MxString m_unk0x54; // 0x54 + undefined4 m_unk0x64; // 0x64 }; // SYNTHETIC: LEGO1 0x1000d1d0 diff --git a/LEGO1/lego/legoomni/include/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h index 95c991df..a183a249 100644 --- a/LEGO1/lego/legoomni/include/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -9,6 +9,7 @@ class LegoActor : public LegoEntity { public: LegoActor(); + virtual ~LegoActor() override; // FUNCTION: LEGO1 0x1002d210 inline virtual const char* ClassName() const override // vtable+0x0c @@ -43,4 +44,7 @@ class LegoActor : public LegoEntity { MxU8 m_unk0x74; // 0x74 }; +// SYNTHETIC: LEGO1 0x1002d300 +// LegoActor::`scalar deleting destructor' + #endif // LEGOACTOR_H diff --git a/LEGO1/lego/legoomni/include/legoactorpresenter.h b/LEGO1/lego/legoomni/include/legoactorpresenter.h index a9709686..a9b8ae7e 100644 --- a/LEGO1/lego/legoomni/include/legoactorpresenter.h +++ b/LEGO1/lego/legoomni/include/legoactorpresenter.h @@ -7,6 +7,8 @@ // SIZE 0x50 class LegoActorPresenter : public LegoEntityPresenter { public: + virtual ~LegoActorPresenter() override{}; + // FUNCTION: LEGO1 0x1000cb10 inline virtual const char* ClassName() const override // vtable+0x0c { @@ -19,6 +21,13 @@ class LegoActorPresenter : public LegoEntityPresenter { { 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 }; +// SYNTHETIC: LEGO1 0x1000cc30 +// LegoActorPresenter::`scalar deleting destructor' + #endif // LEGOACTORPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index f943b062..a781128e 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -1,6 +1,7 @@ #ifndef LEGOANIMATIONMANAGER_H #define LEGOANIMATIONMANAGER_H +#include "decomp.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d8c18 @@ -26,7 +27,9 @@ class LegoAnimationManager : public MxCore { return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); } + void FUN_1005ef10(); void FUN_1005f6d0(MxBool); + void FUN_1005f720(undefined4); void FUN_10064670(MxBool); __declspec(dllexport) static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig); diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h index de8e91d9..5ff2f0c3 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -1,12 +1,19 @@ #ifndef LEGOANIMPRESENTER_H #define LEGOANIMPRESENTER_H +#include "mxgeometry/mxgeometry3d.h" #include "mxvideopresenter.h" +class LegoWorld; +class LegoMemoryStream; +class LegoAnimClass; + // VTABLE: LEGO1 0x100d90c8 +// SIZE 0xc0 class LegoAnimPresenter : public MxVideoPresenter { public: LegoAnimPresenter(); + virtual ~LegoAnimPresenter() override; // FUNCTION: LEGO1 0x10068530 inline virtual const char* ClassName() const override // vtable+0x0c @@ -21,8 +28,84 @@ class LegoAnimPresenter : public MxVideoPresenter { 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 ParseExtra() override; // vtable+0x30 + 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 + + // 6 more virtual functions here + private: void Init(); + void Destroy(MxBool p_fromDestructor); + + LegoAnimClass* m_unk0x64; // 0x64 + undefined4 m_unk0x68; // 0x68 + undefined4 m_unk0x6c; // 0x6c + undefined4 m_unk0x70; // 0x70 + undefined4 m_unk0x74; // 0x74 + undefined4 m_unk0x78; // 0x78 + undefined4 m_unk0x7c; // 0x7c + LegoWorld* m_currentWorld; // 0x80 + MxAtomId m_animAtom; // 0x84 + undefined4 m_unk0x88; // 0x88 + undefined4 m_unk0x8c; // 0x8c + undefined4 m_unk0x90; // 0x90 + undefined m_unk0x94; // 0x94 + undefined m_unk0x95; // 0x95 + undefined m_unk0x96; // 0x96 + undefined m_unk0x97; // 0x97 + undefined4 m_unk0x98; // 0x98 + MxS16 m_unk0x9c; // 0x9c + undefined4 m_unk0xa0; // 0xa0 + undefined4 m_unk0xa4; // 0xa4 + Mx3DPointFloat m_unk0xa8; // 0xa8 + undefined4 m_unk0xbc; // 0xbc }; +// 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/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index bb9c96bb..03fb2eeb 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -19,6 +19,8 @@ class LegoBuildingManager : public MxCore { __declspec(dllexport) static void configureLegoBuildingManager(MxS32); + void FUN_1002fa00(); + private: void Init(); }; diff --git a/LEGO1/lego/legoomni/include/legocameracontroller.h b/LEGO1/lego/legoomni/include/legocameracontroller.h index 05c974a3..7d038d02 100644 --- a/LEGO1/lego/legoomni/include/legocameracontroller.h +++ b/LEGO1/lego/legoomni/include/legocameracontroller.h @@ -3,9 +3,9 @@ #include "legopointofviewcontroller.h" #include "mxcore.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" #include "mxpoint32.h" -#include "realtime/matrix.h" -#include "realtime/vector.h" // VTABLE: LEGO1 0x100d57b0 // SIZE 0xc8 @@ -29,22 +29,22 @@ class LegoCameraController : public LegoPointOfViewController { return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); } - virtual void OnLButtonDown(MxPoint32 p_point) override; // vtable+0x30 - virtual void OnLButtonUp(MxPoint32 p_point) override; // vtable+0x34 - virtual void OnRButtonDown(MxPoint32 p_point) override; // vtable+0x38 - virtual void OnRButtonUp(MxPoint32 p_point) override; // vtable+0x3c - virtual void OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) override; // vtable+0x40 - virtual MxResult Create(); // vtable+0x44 + virtual void OnLButtonDown(MxPoint32 p_point); // vtable+0x30 + virtual void OnLButtonUp(MxPoint32 p_point); // vtable+0x34 + virtual void OnRButtonDown(MxPoint32 p_point); // vtable+0x38 + virtual void OnRButtonUp(MxPoint32 p_point); // vtable+0x3c + virtual void OnMouseMove(MxU8 p_modifier, MxPoint32 p_point); // vtable+0x40 + virtual MxResult Create(); // vtable+0x44 - void SetWorldTransform(Vector3Impl& p_at, Vector3Impl& p_dir, Vector3Impl& p_up); - void FUN_100123e0(Matrix4Data& p_transform, MxU32); - Vector3Data& FUN_10012740(); - Vector3Data& FUN_100127f0(); - Vector3Data& FUN_100128a0(); + void SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up); + void FUN_100123e0(const MxMatrix& p_transform, MxU32); + Mx3DPointFloat GetWorldUp(); + Mx3DPointFloat GetWorldLocation(); + Mx3DPointFloat GetWorldDirection(); private: - Matrix4Data m_matrix1; // 0x38 - Matrix4Data m_matrix2; // 0x80 + MxMatrix m_matrix1; // 0x38 + MxMatrix m_matrix2; // 0x80 }; // SYNTHETIC: LEGO1 0x10011f50 diff --git a/LEGO1/lego/legoomni/include/legocontrolmanager.h b/LEGO1/lego/legoomni/include/legocontrolmanager.h index 7bc8dc0f..f81ab6d2 100644 --- a/LEGO1/lego/legoomni/include/legocontrolmanager.h +++ b/LEGO1/lego/legoomni/include/legocontrolmanager.h @@ -2,6 +2,7 @@ #define LEGOCONTROLMANAGER_H #include "mxcore.h" +#include "mxpresenterlist.h" // VTABLE: LEGO1 0x100d6a80 class LegoControlManager : public MxCore { @@ -24,8 +25,10 @@ class LegoControlManager : public MxCore { return !strcmp(p_name, LegoControlManager::ClassName()) || MxCore::IsA(p_name); } + void FUN_10028df0(MxPresenterList* p_presenterList); void Register(MxCore* p_listener); void Unregister(MxCore* p_listener); + void FUN_100293c0(undefined4, const MxAtomId&, undefined2); }; #endif // LEGOCONTROLMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index ba0e1a7b..b775f840 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -3,7 +3,7 @@ #include "decomp.h" #include "extra.h" -#include "mxdsobject.h" +#include "mxdsaction.h" #include "mxentity.h" #include "realtime/vector.h" #include "roi/legoroi.h" @@ -12,10 +12,19 @@ // SIZE 0x68 (probably) class LegoEntity : public MxEntity { public: + enum { + c_bit1 = 0x01 + }; + // Inlined at 0x100853f7 inline LegoEntity() { Init(); } - __declspec(dllexport) virtual ~LegoEntity() override; // vtable+0x0 +#ifdef ISLE_APP + __declspec(dllexport) virtual ~LegoEntity() override; +#else + // FUNCTION: LEGO1 0x1000c290 + __declspec(dllexport) virtual ~LegoEntity() override { Destroy(TRUE); } +#endif virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 @@ -32,12 +41,13 @@ class LegoEntity : public MxEntity { return !strcmp(p_name, LegoEntity::ClassName()) || MxEntity::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject); // 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(Vector3Impl& p_loc, Vector3Impl& p_dir, Vector3Impl& 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 @@ -49,26 +59,31 @@ class LegoEntity : public MxEntity { virtual void VTable0x4c(); // vtable+0x4c void FUN_10010c30(); - void SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool); + void SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool); + + inline LegoROI* GetROI() { return m_roi; } protected: void Init(); void SetWorld(); - undefined m_unk0x10; - undefined m_unk0x11; - Vector3Data m_worldLocation; // 0x14 - Vector3Data m_worldDirection; // 0x28 - Vector3Data m_worldUp; // 0x3c - MxFloat m_worldSpeed; // 0x50 - LegoROI* m_roi; // 0x54 - MxBool m_cameraFlag; // 0x58 - undefined m_unk0x59; + undefined m_unk0x10; // 0x10 + MxU8 m_flags; // 0x11 + Mx3DPointFloat m_worldLocation; // 0x14 + Mx3DPointFloat m_worldDirection; // 0x28 + Mx3DPointFloat m_worldUp; // 0x3c + MxFloat m_worldSpeed; // 0x50 + LegoROI* m_roi; // 0x54 + MxBool m_cameraFlag; // 0x58 + undefined m_unk0x59; // 0x59 // For tokens from the extra string that look like this: // "Action:openram;\lego\scripts\Race\CarRaceR;0" - ExtraActionType m_actionType; // 0x5c - char* m_actionArgString; // 0x60 - MxS32 m_actionArgNumber; // 0x64 + Extra::ActionType m_actionType; // 0x5c + char* m_actionArgString; // 0x60 + MxS32 m_actionArgNumber; // 0x64 }; +// SYNTHETIC: LEGO1 0x1000c3b0 +// LegoEntity::`scalar deleting destructor' + #endif // LEGOENTITY_H diff --git a/LEGO1/lego/legoomni/include/legoentitylist.h b/LEGO1/lego/legoomni/include/legoentitylist.h new file mode 100644 index 00000000..1d29e65d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoentitylist.h @@ -0,0 +1,92 @@ +#ifndef LEGOENTITYLIST_H +#define LEGOENTITYLIST_H + +#include "mxlist.h" +#include "mxtypes.h" + +class LegoEntity; + +// VTABLE: LEGO1 0x100d6410 +// class MxCollection + +// VTABLE: LEGO1 0x100d6428 +// class MxList + +// VTABLE: LEGO1 0x100d6440 +// class MxPtrList + +// VTABLE: LEGO1 0x100d6458 +// SIZE 0x18 +class LegoEntityList : public MxPtrList { +public: + LegoEntityList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} + + // FUNCTION: LEGO1 0x1001e2d0 + virtual MxS8 Compare(LegoEntity* p_a, LegoEntity* p_b) override + { + return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; + }; // vtable+0x14 +}; + +// VTABLE: LEGO1 0x100d64e8 +// class MxListCursor + +// VTABLE: LEGO1 0x100d64b8 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d64d0 +// SIZE 0x10 +class LegoEntityListCursor : public MxPtrListCursor { +public: + LegoEntityListCursor(LegoEntityList* p_list) : MxPtrListCursor(p_list){}; +}; + +// TEMPLATE: LEGO1 0x1001e2f0 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1001e300 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1001e350 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1001e360 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x1001e3f0 +// MxPtrList::Destroy + +// SYNTHETIC: LEGO1 0x1001e400 +// LegoEntityList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001e470 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x1001e4c0 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e530 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e5e0 +// MxPtrList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f110 +// LegoEntityListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1001f180 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f1d0 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f240 +// MxPtrListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1001f2b0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001edc6 +// LegoEntityListCursor::~LegoEntityListCursor + +#endif // LEGOENTITYLIST_H diff --git a/LEGO1/lego/legoomni/include/legoentitypresenter.h b/LEGO1/lego/legoomni/include/legoentitypresenter.h index 72af0498..e3055991 100644 --- a/LEGO1/lego/legoomni/include/legoentitypresenter.h +++ b/LEGO1/lego/legoomni/include/legoentitypresenter.h @@ -26,20 +26,20 @@ class LegoEntityPresenter : public MxCompositePresenter { } virtual void ReadyTickle() override; // vtable+0x18 - virtual void RepeatingTickle(); // vtable+0x24 - virtual void ParseExtra(); // vtable+0x30 + 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 SetBackend(LegoEntity* p_unk0x4c); // vtable+0x6c + virtual undefined4 SetEntity(LegoEntity* p_entity); // vtable+0x6c - void SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up); + void SetEntityLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up); private: void Destroy(MxBool p_fromDestructor); protected: - LegoEntity* m_objectBackend; // 0x4c + LegoEntity* m_entity; // 0x4c }; #endif // LEGOENTITYPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h index c9087909..8805d9cd 100644 --- a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h +++ b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h @@ -7,9 +7,10 @@ #include // VTABLE: LEGO1 0x100d6aa0 +// SIZE 0x20 class LegoEventNotificationParam : public MxNotificationParam { public: - inline LegoEventNotificationParam() : MxNotificationParam(PARAM_NONE, NULL) {} + inline LegoEventNotificationParam() : MxNotificationParam(c_notificationType0, NULL) {} inline LegoEventNotificationParam( NotificationId p_type, MxCore* p_sender, @@ -22,8 +23,9 @@ class LegoEventNotificationParam : public MxNotificationParam { { } - virtual ~LegoEventNotificationParam() override {} // vtable+0x0 (scalar deleting destructor) inline MxU8 GetKey() const { return m_key; } + inline MxS32 GetX() const { return m_x; } + inline MxS32 GetY() const { return m_y; } protected: MxU8 m_modifier; // 0x0c @@ -33,4 +35,10 @@ class LegoEventNotificationParam : public MxNotificationParam { MxU32 m_unk0x1c; // 0x1c }; +// SYNTHETIC: LEGO1 0x10028770 +// LegoEventNotificationParam::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100287e0 +// LegoEventNotificationParam::~LegoEventNotificationParam + #endif // LEGOEVENTNOTIFICATIONPARAM_H diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 5f62b107..ae39654c 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -43,6 +43,7 @@ class LegoGameState { void SetSomeEnumState(undefined4 p_state); void FUN_1003ceb0(); + void FUN_10039780(MxU8); struct ScoreStruct { void WriteScoreHistory(); @@ -72,7 +73,7 @@ class LegoGameState { undefined m_unk0x41a[8]; // 0x41a - might be part of the structure at 0xa6 MxBool m_isDirty; // 0x420 undefined4 m_unk0x424; // 0x424 - undefined4 m_unk0x428; // 0x428 + undefined4 m_prevArea; // 0x428 undefined4 m_unk0x42c; // 0x42c }; diff --git a/LEGO1/lego/legoomni/include/legohideanimpresenter.h b/LEGO1/lego/legoomni/include/legohideanimpresenter.h index f6e86c2e..59449283 100644 --- a/LEGO1/lego/legoomni/include/legohideanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legohideanimpresenter.h @@ -1,6 +1,7 @@ #ifndef LEGOHIDEANIMPRESENTER_H #define LEGOHIDEANIMPRESENTER_H +#include "decomp.h" #include "legoloopinganimpresenter.h" // VTABLE: LEGO1 0x100d9278 @@ -8,6 +9,7 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { public: LegoHideAnimPresenter(); + virtual ~LegoHideAnimPresenter() override; // FUNCTION: LEGO1 0x1006d880 inline const char* ClassName() const override // vtable+0xc @@ -22,8 +24,16 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); } + virtual void Destroy() override; // vtable+0x38 + private: void Init(); + void Destroy(MxBool p_fromDestructor); + + undefined4* m_unk0xc0; // 0xc0 }; +// SYNTHETIC: LEGO1 0x1006d9d0 +// LegoHideAnimPresenter::`scalar deleting destructor' + #endif // LEGOHIDEANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 1d1d8f7e..03086cd3 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -53,7 +53,10 @@ class LegoInputManager : public MxPresenter { void ClearWorld(); inline void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; } + inline void SetUnknown335(MxBool p_unk0x335) { m_unk0x335 = p_unk0x335; } inline void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; } + inline void SetUseJoystick(MxBool p_useJoystick) { m_useJoystick = p_useJoystick; } + inline void SetJoystickIndex(MxS32 p_joystickIndex) { m_joystickIndex = p_joystickIndex; } inline void AllowEventProcessing() { @@ -68,7 +71,7 @@ class LegoInputManager : public MxPresenter { void ProcessEvents(); MxBool ProcessOneEvent(LegoEventNotificationParam& p_param); - // private: +private: MxCriticalSection m_criticalSection; MxList* m_unk0x5c; // list or hash table LegoCameraController* m_camera; @@ -101,6 +104,9 @@ class LegoInputManager : public MxPresenter { // TEMPLATE: LEGO1 0x1005bb80 // MxCollection::Compare +// TEMPLATE: LEGO1 0x1005bbe0 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x1005bc30 // MxCollection::Destroy @@ -116,6 +122,9 @@ class LegoInputManager : public MxPresenter { // SYNTHETIC: LEGO1 0x1005beb0 // LegoEventQueue::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x1005bf20 +// MxQueue::~MxQueue + // SYNTHETIC: LEGO1 0x1005bf70 // MxQueue::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h index a17c671c..844d1586 100644 --- a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h @@ -21,4 +21,10 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { } }; +// SYNTHETIC: LEGO1 0x1006d000 +// LegoLoopingAnimPresenter::~LegoLoopingAnimPresenter + +// SYNTHETIC: LEGO1 0x1000f440 +// LegoLoopingAnimPresenter::`scalar deleting destructor' + #endif // LEGOLOOPINGANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legometerpresenter.h b/LEGO1/lego/legoomni/include/legometerpresenter.h index 023a7bfa..33c7aa37 100644 --- a/LEGO1/lego/legoomni/include/legometerpresenter.h +++ b/LEGO1/lego/legoomni/include/legometerpresenter.h @@ -7,7 +7,30 @@ // SIZE 0x94 (from 0x1000a163) class LegoMeterPresenter : public MxStillPresenter { public: + LegoMeterPresenter(); + virtual ~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 + +private: + void FUN_10043a50(); + + MxU8* m_unk0x6c; // 0x6c + MxU16 m_type; // 0x70 + MxString m_variable; // 0x74 + MxFloat m_unk0x84; // 0x84 + MxU16 m_unk0x88; // 0x88 + MxU16 m_unk0x8a; // 0x8a + MxU16 m_unk0x8c; // 0x8c + MxU16 m_unk0x8e; // 0x8e + MxU16 m_layout; // 0x90 }; +// SYNTHETIC: LEGO1 0x10043760 +// LegoMeterPresenter::`scalar deleting destructor' + #endif // LEGOMETERPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legomodelpresenter.h b/LEGO1/lego/legoomni/include/legomodelpresenter.h index ca3e216f..fe2216d5 100644 --- a/LEGO1/lego/legoomni/include/legomodelpresenter.h +++ b/LEGO1/lego/legoomni/include/legomodelpresenter.h @@ -28,6 +28,10 @@ class LegoModelPresenter : public MxVideoPresenter { protected: void Destroy(MxBool p_fromDestructor); + +private: + undefined4 m_unk0x64; // 0x64 + MxBool m_addedToView; // 0x68 }; #endif // LEGOMODELPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoobjectfactory.h b/LEGO1/lego/legoomni/include/legoobjectfactory.h index 3a575c52..552b3cf8 100644 --- a/LEGO1/lego/legoomni/include/legoobjectfactory.h +++ b/LEGO1/lego/legoomni/include/legoobjectfactory.h @@ -70,7 +70,7 @@ X(RaceCar) \ X(Jetski) \ X(Bike) \ - X(Motorcycle) \ + X(Motocycle) \ X(Ambulance) \ X(AmbulanceMissionState) \ X(TowTrack) \ diff --git a/LEGO1/lego/legoomni/include/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h index cbdf0a41..1986f8f8 100644 --- a/LEGO1/lego/legoomni/include/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -115,11 +115,14 @@ class LegoOmni : public MxOmni { MxBackgroundAudioManager* GetBackgroundAudioManager() { return m_bkgAudioManager; } MxTransitionManager* GetTransitionManager() { return m_transitionManager; } MxDSAction& GetCurrentAction() { return m_action; } + LegoUnkSaveDataWriter* GetUnkSaveDataWriter() { return m_saveDataWriter; } 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 CloseMainWindow() { PostMessageA(m_windowHandle, WM_CLOSE, 0, 0); } + private: undefined4* m_unk0x68; // 0x68 ViewLODListManager* m_viewLODListManager; // 0x6c @@ -149,7 +152,6 @@ __declspec(dllexport) LegoOmni* Lego(); __declspec(dllexport) LegoEntity* PickEntity(MxLong, MxLong); __declspec(dllexport) LegoROI* PickROI(MxLong, MxLong); __declspec(dllexport) LegoSoundManager* SoundManager(); -__declspec(dllexport) MxResult Start(MxDSAction*); __declspec(dllexport) MxTransitionManager* TransitionManager(); __declspec(dllexport) LegoVideoManager* VideoManager(); @@ -159,14 +161,18 @@ LegoControlManager* ControlManager(); IslePathActor* GetCurrentVehicle(); LegoPlantManager* PlantManager(); LegoWorld* GetCurrentWorld(); +LegoUnkSaveDataWriter* GetUnkSaveDataWriter(); GifManager* GetGifManager(); void FUN_10015820(MxU32, MxU32); +void FUN_10015860(const char*, MxU8); LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid); 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 SetCurrentWorld(LegoWorld* p_world); #endif // LEGOOMNI_H diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index a3f5756c..5f67af4f 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -25,10 +25,10 @@ class LegoPathActor : public LegoActor { return !strcmp(p_name, LegoPathActor::ClassName()) || LegoActor::IsA(p_name); } - virtual void VTable0x68(); // vtable+0x68 - virtual void VTable0x6c(); // vtable+0x6c - virtual void VTable0x70(float p_float); // vtable+0x70 - virtual void VTable0x74(Matrix4Impl& p_transform); // vtable+0x74 + virtual void VTable0x68(); // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(float p_float); // vtable+0x70 + virtual void VTable0x74(Matrix4& p_transform); // vtable+0x74 // FUNCTION: LEGO1 0x10002d20 virtual void VTable0x78(MxU8 p_unk0xea) { m_unk0xea = p_unk0xea; } // vtable+0x78 // FUNCTION: LEGO1 0x10002d30 diff --git a/LEGO1/lego/legoomni/include/legopathpresenter.h b/LEGO1/lego/legoomni/include/legopathpresenter.h index de7b14d1..bc1bdcb5 100644 --- a/LEGO1/lego/legoomni/include/legopathpresenter.h +++ b/LEGO1/lego/legoomni/include/legopathpresenter.h @@ -8,6 +8,7 @@ class LegoPathPresenter : public MxMediaPresenter { public: LegoPathPresenter(); + virtual ~LegoPathPresenter() override; // FUNCTION: LEGO1 0x100449a0 inline const char* ClassName() const override // vtable+0xc @@ -22,6 +23,8 @@ 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 diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h index 7fd20746..e509e17e 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -1,6 +1,7 @@ #ifndef LEGOPLANTMANAGER_H #define LEGOPLANTMANAGER_H +#include "decomp.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6758 @@ -19,6 +20,8 @@ class LegoPlantManager : public MxCore { return "LegoPlantManager"; } + void FUN_10026360(undefined4 p_world); + private: void Init(); }; diff --git a/LEGO1/lego/legoomni/include/legopointofviewcontroller.h b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h index a7e92e97..99c213e2 100644 --- a/LEGO1/lego/legoomni/include/legopointofviewcontroller.h +++ b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "mxcore.h" +#include "mxpoint32.h" #include @@ -82,6 +83,7 @@ class LegoPointOfViewController : public LegoMouseController { virtual void SetEntity(LegoEntity* p_entity); // vtable+0x2c MxResult Create(Lego3DView* p_lego3DView); + void OnViewSize(int p_width, int p_height); inline LegoEntity* GetEntity() { return m_entity; } diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index 530c289c..504b4cbb 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -28,7 +28,7 @@ class LegoRace : public LegoWorld { return !strcmp(p_name, LegoRace::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + 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 diff --git a/LEGO1/lego/legoomni/include/legostream.h b/LEGO1/lego/legoomni/include/legostream.h index 8b0a57c1..601e94e2 100644 --- a/LEGO1/lego/legoomni/include/legostream.h +++ b/LEGO1/lego/legoomni/include/legostream.h @@ -18,7 +18,8 @@ class MxVariableTable; class LegoStream { public: LegoStream() : m_mode(0) {} - inline virtual ~LegoStream(){}; + // 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; @@ -29,9 +30,9 @@ class LegoStream { virtual MxBool IsReadMode(); enum OpenFlags { - ReadBit = 1, - WriteBit = 2, - BinaryBit = 4, + c_readBit = 1, + c_writeBit = 2, + c_binaryBit = 4, }; static MxResult __stdcall WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName); @@ -41,11 +42,14 @@ class LegoStream { MxU8 m_mode; }; +// SYNTHETIC: LEGO1 0x10045b00 +// LegoStream::`scalar deleting destructor' + // VTABLE: LEGO1 0x100db730 class LegoFileStream : public LegoStream { public: LegoFileStream(); - virtual ~LegoFileStream(); + virtual ~LegoFileStream() override; MxResult Read(void* p_buffer, MxU32 p_size) override; MxResult Write(const void* p_buffer, MxU32 p_size) override; @@ -60,11 +64,13 @@ class LegoFileStream : public LegoStream { FILE* m_hFile; }; +// SYNTHETIC: LEGO1 0x10099230 +// LegoFileStream::`scalar deleting destructor' + // VTABLE: LEGO1 0x100db710 class LegoMemoryStream : public LegoStream { public: LegoMemoryStream(char* p_buffer); - ~LegoMemoryStream() {} MxResult Read(void* p_buffer, MxU32 p_size) override; MxResult Write(const void* p_buffer, MxU32 p_size) override; @@ -76,4 +82,10 @@ class LegoMemoryStream : public LegoStream { 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/legounknown100d7c88.h b/LEGO1/lego/legoomni/include/legounknown100d7c88.h index a6004053..2fa960c8 100644 --- a/LEGO1/lego/legoomni/include/legounknown100d7c88.h +++ b/LEGO1/lego/legoomni/include/legounknown100d7c88.h @@ -4,6 +4,7 @@ #include "decomp.h" #include "mxstring.h" +// VTABLE: LEGO1 0x100d7c88 class LegoUnknown100d7c88 { public: ~LegoUnknown100d7c88(); diff --git a/LEGO1/lego/legoomni/include/legounknown100d9d00.h b/LEGO1/lego/legoomni/include/legounknown100d9d00.h index d31634fe..394ffbbd 100644 --- a/LEGO1/lego/legoomni/include/legounknown100d9d00.h +++ b/LEGO1/lego/legoomni/include/legounknown100d9d00.h @@ -27,9 +27,15 @@ class LegoUnknown100d9d00 : public MxList { // TEMPLATE: LEGO1 0x1007b300 // MxCollection::Compare +// TEMPLATE: LEGO1 0x1007b310 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x1007b360 // MxCollection::Destroy +// TEMPLATE: LEGO1 0x1007b370 +// MxList::~MxList + // SYNTHETIC: LEGO1 0x1007b400 // LegoUnknown100d9d00::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 039058e6..240bef11 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -4,6 +4,7 @@ #include "decomp.h" #include "mxtypes.h" +class LegoROI; class LegoStream; struct LegoSaveDataEntry3 { @@ -32,7 +33,9 @@ struct LegoSaveDataEntry3 { }; class LegoUnkSaveDataWriter { +public: MxResult WriteSaveData3(LegoStream* p_stream); + void FUN_10083db0(LegoROI* p_roi); }; #endif // LEGOUNKSAVEDATAWRITER_H diff --git a/LEGO1/lego/legoomni/include/legoutil.h b/LEGO1/lego/legoomni/include/legoutil.h index 1539f28f..6e9bb5ee 100644 --- a/LEGO1/lego/legoomni/include/legoutil.h +++ b/LEGO1/lego/legoomni/include/legoutil.h @@ -10,8 +10,8 @@ class MxAtomId; class LegoEntity; -ExtraActionType MatchActionString(const char*); -void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender); +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); MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); void FUN_1003ef00(MxBool); diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index 0783931a..6921e7d2 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -40,7 +40,8 @@ class LegoVideoManager : public MxVideoManager { inline Lego3DManager* Get3DManager() { return this->m_3dManager; } inline MxDirect3D* GetDirect3D() { return this->m_direct3d; } - inline void SetUnkE4(MxBool p_unk0xe4) { this->m_unk0xe4 = p_unk0xe4; } + inline void SetRender3D(MxBool p_render3d) { this->m_render3d = p_render3d; } + inline void SetUnk0x554(MxBool p_unk0x554) { this->m_unk0x554 = p_unk0x554; } private: MxResult CreateDirect3D(); @@ -55,7 +56,7 @@ class LegoVideoManager : public MxVideoManager { undefined4 m_unk0x70; // 0x70 MxDirect3D* m_direct3d; // 0x74 undefined4 m_unk0x78[27]; // 0x78 - MxBool m_unk0xe4; // 0xe4 + MxBool m_render3d; // 0xe4 MxBool m_unk0xe5; // 0xe5 MxBool m_unk0xe6; // 0xe6 PALETTEENTRY m_paletteEntries[256]; // 0xe7 @@ -65,7 +66,7 @@ class LegoVideoManager : public MxVideoManager { MxPalette* m_palette; // 0x4f0 MxStopWatch* m_stopWatch; // 0x4f4 double m_elapsedSeconds; // 0x4f8 - MxBool m_unk0x500; // 0x500 + MxBool m_fullScreenMovie; // 0x500 MxBool m_drawCursor; // 0x501 MxS32 m_cursorXCopy; // 0x504 MxS32 m_cursorYCopy; // 0x508 @@ -80,7 +81,7 @@ class LegoVideoManager : public MxVideoManager { SIZE m_fpsSize; // 0x544 undefined m_pad0x54c[8]; // 0x54c MxBool m_unk0x554; // 0x554 - MxBool m_initialized; // 0x555 + MxBool m_paused; // 0x555 undefined m_pad0x556[0x39]; // 0x556 }; diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index c4f53913..a423ec09 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -3,7 +3,9 @@ #include "legocameracontroller.h" #include "legoentity.h" +#include "legoentitylist.h" #include "legopathcontrollerlist.h" +#include "mxcorelist.h" #include "mxpresenter.h" #include "mxpresenterlist.h" @@ -33,37 +35,45 @@ class LegoWorld : public LegoEntity { return !strcmp(p_name, LegoWorld::ClassName()) || LegoEntity::IsA(p_name); } - virtual void Stop(); // vtable+50 - virtual void VTable0x54(); // vtable+54 - virtual void VTable0x58(MxCore* p_object); // vtable+58 - virtual MxBool VTable0x5c(); // vtable+5c - // FUNCTION: LEGO1 0x100010a0 - virtual void VTable0x60() {} // vtable+60 - virtual MxBool VTable0x64(); // vtable+64 - virtual void VTable0x68(MxBool p_add); // vtable+68 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void VTable0x50(); // vtable+0x50 + virtual LegoCameraController* VTable0x54(); // vtable+0x54 + virtual void VTable0x58(MxCore* p_object); // vtable+0x58 + virtual MxBool VTable0x5c(); // vtable+0x5c - inline LegoCameraController* GetCamera() { return m_camera; } + // FUNCTION: LEGO1 0x100010a0 + virtual void VTable0x60() {} // vtable+0x60 + + virtual MxBool VTable0x64(); // vtable+0x64 + virtual void VTable0x68(MxBool p_add); // vtable+0x68 + + inline LegoCameraController* GetCamera() { return m_cameraController; } + inline undefined4 GetUnknown0xec() { return m_unk0xec; } undefined FUN_100220e0(); - MxResult SetAsCurrentWorld(MxDSObject& p_dsObject); void EndAction(MxCore* p_object); void FUN_1001fc80(IslePathActor* p_actor); - MxBool FUN_100727e0(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up); - MxBool FUN_10072980(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up); + 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); protected: - LegoPathControllerList m_list0x68; // 0x68 - MxPresenterList m_list0x80; // 0x80 - LegoCameraController* m_camera; // 0x98 - undefined m_unk0x9c[0x1c]; // 0x9c - MxPresenterList m_list0xb8; // 0xb8 - undefined m_unk0xd0[0x24]; // 0xd0 - MxS16 m_unk0xf4; // 0xf4 - MxBool m_unk0xf6; // 0xf6 - undefined m_unk0xf7; // 0xf7 + 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 }; // SYNTHETIC: LEGO1 0x1001eed0 diff --git a/LEGO1/lego/legoomni/include/legoworldlist.h b/LEGO1/lego/legoomni/include/legoworldlist.h index 22cf5838..2e52de47 100644 --- a/LEGO1/lego/legoomni/include/legoworldlist.h +++ b/LEGO1/lego/legoomni/include/legoworldlist.h @@ -28,6 +28,31 @@ class LegoWorldList : public MxPtrList { }; // vtable+0x14 }; +// VTABLE: LEGO1 0x100d75b8 +// class MxListCursor + +// VTABLE: LEGO1 0x100d7588 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d75a0 +// SIZE 0x10 +class LegoWorldListCursor : public MxPtrListCursor { +public: + LegoWorldListCursor(LegoWorldList* p_list) : MxPtrListCursor(p_list){}; +}; + +// SYNTHETIC: LEGO1 0x1003e870 +// LegoWorldListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1003e8e0 +// MxPtrListCursor::~MxPtrListCursor + +// FUNCTION: LEGO1 0x1003ea10 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1003ea60 +// LegoWorldListCursor::~LegoWorldListCursor + // TEMPLATE: LEGO1 0x100598f0 // MxCollection::Compare diff --git a/LEGO1/lego/legoomni/include/motorcycle.h b/LEGO1/lego/legoomni/include/motocycle.h similarity index 69% rename from LEGO1/lego/legoomni/include/motorcycle.h rename to LEGO1/lego/legoomni/include/motocycle.h index af04b4ad..0c784027 100644 --- a/LEGO1/lego/legoomni/include/motorcycle.h +++ b/LEGO1/lego/legoomni/include/motocycle.h @@ -1,14 +1,14 @@ -#ifndef MOTORCYCLE_H -#define MOTORCYCLE_H +#ifndef MOTOCYCLE_H +#define MOTOCYCLE_H #include "decomp.h" #include "islepathactor.h" // VTABLE: LEGO1 0x100d7090 // SIZE 0x16c -class Motorcycle : public IslePathActor { +class Motocycle : public IslePathActor { public: - Motorcycle(); + Motocycle(); // FUNCTION: LEGO1 0x10035840 inline virtual const char* ClassName() const override // vtable+0x0c @@ -20,7 +20,7 @@ class Motorcycle : public IslePathActor { // FUNCTION: LEGO1 0x10035850 inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 { - return !strcmp(p_name, Motorcycle::ClassName()) || IslePathActor::IsA(p_name); + return !strcmp(p_name, Motocycle::ClassName()) || IslePathActor::IsA(p_name); } private: @@ -29,4 +29,4 @@ class Motorcycle : public IslePathActor { undefined m_unk0x168[4]; }; -#endif // MOTORCYCLE_H +#endif // MOTOCYCLE_H diff --git a/LEGO1/omni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h similarity index 92% rename from LEGO1/omni/include/mxcontrolpresenter.h rename to LEGO1/lego/legoomni/include/mxcontrolpresenter.h index 9779e45f..2db0a2e4 100644 --- a/LEGO1/omni/include/mxcontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h @@ -33,7 +33,8 @@ class MxControlPresenter : public MxCompositePresenter { 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_undefined); // vtable+0x68 + virtual void VTable0x68(MxBool p_unk0x50); // vtable+0x68 + virtual void VTable0x6c(undefined4); // vtable+0x6c private: MxBool FUN_10044270(undefined4, undefined4, undefined4*); diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h index ac87ffcc..b169f3bf 100644 --- a/LEGO1/lego/legoomni/include/mxtransitionmanager.h +++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h @@ -32,13 +32,13 @@ class MxTransitionManager : public MxCore { virtual MxResult GetDDrawSurfaceFromVideoManager(); // vtable+0x14 enum TransitionType { - NOT_TRANSITIONING, - NO_ANIMATION, - DISSOLVE, - PIXELATION, - SCREEN_WIPE, - WINDOWS, - BROKEN // Unknown what this is supposed to be, it locks the game up + e_notTransitioning = 0, + e_noAnimation, + e_dissolve, + e_pixelation, + e_screenWipe, + e_windows, + e_broken // Unknown what this is supposed to be, it locks the game up }; MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim); diff --git a/LEGO1/lego/legoomni/include/score.h b/LEGO1/lego/legoomni/include/score.h index c927863f..1e801aa3 100644 --- a/LEGO1/lego/legoomni/include/score.h +++ b/LEGO1/lego/legoomni/include/score.h @@ -31,8 +31,8 @@ class Score : public LegoWorld { // SYNTHETIC: LEGO1 0x100011e0 // Score::`scalar deleting destructor' - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+18 - virtual void Stop() override; // vtable+50 + 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 diff --git a/LEGO1/lego/legoomni/src/act1/act1state.cpp b/LEGO1/lego/legoomni/src/act1/act1state.cpp index c013b502..17f09277 100644 --- a/LEGO1/lego/legoomni/src/act1/act1state.cpp +++ b/LEGO1/lego/legoomni/src/act1/act1state.cpp @@ -2,6 +2,19 @@ // STUB: LEGO1 0x100334b0 Act1State::Act1State() +{ + // TODO + m_unk0x1e = 0; + m_unk0x18 = 1; + m_unk0x20 = 0; + m_unk0x1f = 0; + m_unk0x21 = TRUE; + m_unk0x22 = 0; + m_unk0x1c = 1; +} + +// STUB: LEGO1 0x10034d00 +void Act1State::FUN_10034d00() { // TODO } diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index 9fe20941..74f8c146 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -77,13 +77,13 @@ void MxBackgroundAudioManager::DestroyMusic() MxResult MxBackgroundAudioManager::Tickle() { switch (m_unk0x13c) { - case MxPresenter::TickleState_Starting: + case MxPresenter::e_starting: FadeInOrFadeOut(); return SUCCESS; - case MxPresenter::TickleState_Streaming: + case MxPresenter::e_streaming: FUN_1007ee70(); return SUCCESS; - case MxPresenter::TickleState_Repeating: + case MxPresenter::e_repeating: FUN_1007ef40(); return SUCCESS; default: diff --git a/LEGO1/lego/legoomni/src/build/helicopter.cpp b/LEGO1/lego/legoomni/src/build/helicopter.cpp index f4220183..d44abb15 100644 --- a/LEGO1/lego/legoomni/src/build/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/build/helicopter.cpp @@ -27,9 +27,9 @@ Helicopter::~Helicopter() } // FUNCTION: LEGO1 0x100032c0 -MxResult Helicopter::Create(MxDSObject& p_dsObject) +MxResult Helicopter::Create(MxDSAction& p_dsAction) { - MxResult result = IslePathActor::Create(p_dsObject); + MxResult result = IslePathActor::Create(p_dsAction); LegoWorld* world = GetCurrentWorld(); SetWorld(world); if (world->IsA("Act3")) { @@ -100,7 +100,7 @@ MxU32 Helicopter::VTable0xcc() VTable0xe8(0x29, TRUE, 7); ((Isle*) GetCurrentWorld())->SetUnknown13c(0x3c); FUN_10015820(1, 0); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, TRUE); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, TRUE); SetUnknownDC(4); PlayMusic(9); break; @@ -112,7 +112,7 @@ MxU32 Helicopter::VTable0xcc() break; } VTable0xe0(); - InvokeAction(ExtraActionType_start, m_script, 0x15, NULL); + InvokeAction(Extra::ActionType::e_start, m_script, 0x15, NULL); GetCurrentAction().SetObjectId(-1); ControlManager()->Register(this); return 1; @@ -139,7 +139,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) case 0x17: if (*g_act3Script == script) { ((Act3*) GetCurrentWorld())->SetUnkown4270(2); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, FALSE); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); } else if (m_state->GetUnkown8() != 0) break; @@ -155,7 +155,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) state->SetUnknown18(4); m_state->SetUnknown8(1); m_world->FUN_1001fc80(this); - InvokeAction(ExtraActionType_start, script, 0x20, NULL); + InvokeAction(Extra::ActionType::e_start, script, 0x20, NULL); SetUnknownDC(0); } ret = 1; @@ -167,7 +167,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) if (m_state->GetUnkown8() == 2) { m_state->SetUnknown8(3); m_world->FUN_1001fc80(this); - InvokeAction(ExtraActionType_start, script, 0x21, NULL); + InvokeAction(Extra::ActionType::e_start, script, 0x21, NULL); SetUnknownDC(4); } ret = 1; @@ -181,15 +181,15 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) if (*g_act3Script != script) break; if (m_world && m_world->GetCamera()) { - Vector3Data loc, dir, lookat; - loc.CopyFrom(m_world->GetCamera()->FUN_100127f0()); - dir.CopyFrom(m_world->GetCamera()->FUN_100128a0()); + Mx3DPointFloat loc, dir, lookat; + loc.CopyFrom(m_world->GetCamera()->GetWorldLocation()); + dir.CopyFrom(m_world->GetCamera()->GetWorldDirection()); lookat = dir; float scale = 3; lookat.Mul(scale); lookat.Add(&loc); - Vector3Data v68, v7c, v90(0, 1, 0), va4; - v68.CopyFrom(m_world->GetCamera()->FUN_10012740()); + Mx3DPointFloat v68, v7c, v90(0, 1, 0), va4; + v68.CopyFrom(m_world->GetCamera()->GetWorldUp()); va4.EqualsCross(v68, dir); v7c.EqualsCross(va4, v90); if (ret) @@ -203,7 +203,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) case 0x1c: if (GameState()->GetUnknown10() == 0) { ((Isle*) GetCurrentWorld())->SetUnknown13c(2); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, FALSE); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); VTable0xe4(); } ret = 1; @@ -219,6 +219,8 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) // FUNCTION: LEGO1 0x10003c20 MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) { + MxU32 ret = 0; + switch (m_state->GetUnkown8()) { case 1: { if (GameState()->GetUnknown10() == 0) { @@ -227,44 +229,54 @@ MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) } else VTable0xe8(0x31, TRUE, 7); + m_state->SetUnknown8(2); - Matrix4Data mat; - mat.SetIdentity(); - Matrix4 mat2 = mat.GetMatrix(); + + MxMatrix matrix; + matrix.SetIdentity(); + float s = sin(0.5235987901687622); // PI / 6, 30 deg float c = cos(0.5235987901687622); // PI / 6, 30 deg + + float matrixCopy[4][4]; + memcpy(matrixCopy, matrix.GetData(), sizeof(matrixCopy)); for (MxS32 i = 0; i < 4; i++) { - mat.GetMatrix()[i][1] = mat2[i][1] * c - mat2[i][2] * s; - mat.GetMatrix()[i][2] = mat2[i][2] * c + mat2[i][1] * s; + matrix.GetData()[i][1] = matrixCopy[i][1] * c - matrixCopy[i][2] * s; + matrix.GetData()[i][2] = matrixCopy[i][2] * c + matrixCopy[i][1] * s; } - Vector3Impl at(mat.GetMatrix()[3]), dir(mat.GetMatrix()[2]), up(mat.GetMatrix()[1]); + + Vector3 at(matrix[3]), dir(matrix[2]), up(matrix[1]); m_world->GetCamera()->SetWorldTransform(at, dir, up); FUN_10010c30(); + ret = 1; break; } case 3: { - Matrix4Data mat; - mat.SetIdentity(); - Vector3Impl at(mat.GetMatrix()[3]), dir(mat.GetMatrix()[2]), up(mat.GetMatrix()[1]); + MxMatrix matrix; + matrix.SetIdentity(); + + Vector3 at(matrix[3]), dir(matrix[2]), up(matrix[1]); at[1] = 1.25; m_world->GetCamera()->SetWorldTransform(at, dir, up); + if (GameState()->GetUnknown10() == 0) { ((Act1State*) GameState()->GetState("Act1State"))->SetUnknown18(0); VTable0xe8(0x29, TRUE, 7); } else VTable0xe8(0x30, TRUE, 7); + m_state->SetUnknown8(0); + ret = 1; break; } - default: - return 0; } - return 1; + + return ret; } // FUNCTION: LEGO1 0x10003e90 -void Helicopter::VTable0x74(Matrix4Impl& p_transform) +void Helicopter::VTable0x74(Matrix4& p_transform) { if (m_unk0xea != 0) { m_roi->FUN_100a46b0(p_transform); @@ -295,13 +307,13 @@ void Helicopter::VTable0x70(float p_float) f2 = 0; if (1.0f < f2) f2 = 1.0f; - Vector3Impl v(m_unk0x160.GetMatrix()[3]); - Matrix4Data mat; - Vector3Impl v2(m_unk0x1a8.GetMatrix()[3]); - float* loc = m_unk0x1a8.GetMatrix()[3]; + Vector3 v(m_unk0x160[3]); + MxMatrix mat; + Vector3 v2(m_unk0x1a8[3]); + float* loc = m_unk0x1a8[3]; mat.SetIdentity(); float fa[4]; - Vector4Impl v3(fa); + Vector4 v3(fa); if (m_unk0x1f4.FUN_100040a0(v3, f2) == SUCCESS) { mat.FromQuaternion(v3); } @@ -322,18 +334,17 @@ void Helicopter::VTable0x70(float p_float) } // FUNCTION: LEGO1 0x100040a0 -MxResult HelicopterSubclass::FUN_100040a0(Vector4Impl& p_v, float p_f) +MxResult HelicopterSubclass::FUN_100040a0(Vector4& p_v, float p_f) { MxU32 state = m_unk0x30; if (state == 1) { - p_v.EqualsImpl(m_unk0x0.GetVector().elements); + p_v.EqualsImpl(m_unk0x0.GetData()); p_v[3] = acos(p_v[3]) * (1 - p_f) * 2.0; return p_v.NormalizeQuaternion(); } else if (state == 2) { - p_v.EqualsImpl(m_unk0x18.GetVector().elements); + p_v.EqualsImpl(m_unk0x18.GetData()); p_v[3] = acos(p_v[3]) * p_f * 2.0; - p_v.NormalizeQuaternion(); return p_v.NormalizeQuaternion(); } else if (state == 3) { diff --git a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index 34652509..3e6c4d7b 100644 --- a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -26,3 +26,9 @@ void LegoBuildingManager::Init() { // TODO } + +// STUB: LEGO1 0x1002fa00 +void LegoBuildingManager::FUN_1002fa00() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/common/gifmanager.cpp b/LEGO1/lego/legoomni/src/common/gifmanager.cpp index 0fc25b96..e9b10d49 100644 --- a/LEGO1/lego/legoomni/src/common/gifmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/gifmanager.cpp @@ -6,6 +6,7 @@ DECOMP_SIZE_ASSERT(GifMap, 0x08); DECOMP_SIZE_ASSERT(GifManagerBase, 0x14); DECOMP_SIZE_ASSERT(GifManager, 0x30); +// GLOBAL: LEGO1 0x100f0100 GifMapEntry* g_unk0x100f0100; // FUNCTION: LEGO1 0x10001cc0 diff --git a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp index 953aef36..1407de1b 100644 --- a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp @@ -19,8 +19,7 @@ void LegoActionControlPresenter::ReadyTickle() if (chunk) { ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); m_subscriber->DestroyChunk(chunk); if (m_compositePresenter) { @@ -39,9 +38,15 @@ void LegoActionControlPresenter::RepeatingTickle() ParseExtra(); } - InvokeAction(m_unk0x50, MxAtomId(m_unk0x54.GetData(), LookupMode_LowerCase2), m_unk0x64, NULL); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; +#ifdef COMPAT_MODE + { + MxAtomId atom(m_unk0x54.GetData(), e_lowerCase2); + InvokeAction(m_unk0x50, atom, m_unk0x64, NULL); + } +#else + InvokeAction(m_unk0x50, MxAtomId(m_unk0x54.GetData(), e_lowerCase2), m_unk0x64, NULL); +#endif + ProgressTickleState(e_done); } } @@ -87,11 +92,11 @@ void LegoActionControlPresenter::ParseExtra() char output[1024]; if (KeyValueStringParse(output, g_strACTION, buf)) { m_unk0x50 = MatchActionString(strtok(output, g_parseExtraTokens)); - if (m_unk0x50 != ExtraActionType_exit) { + if (m_unk0x50 != Extra::ActionType::e_exit) { MakeSourceName(buf, strtok(NULL, g_parseExtraTokens)); m_unk0x54 = buf; m_unk0x54.ToLowerCase(); - if (m_unk0x50 != ExtraActionType_run) { + if (m_unk0x50 != Extra::ActionType::e_run) { m_unk0x64 = atoi(strtok(NULL, g_parseExtraTokens)); } } diff --git a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp index e682356b..5d594eaa 100644 --- a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp +++ b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp @@ -7,8 +7,16 @@ DECOMP_SIZE_ASSERT(LegoBackgroundColor, 0x30) -const char* g_delimiter = "\t"; +// GLOBAL: LEGO1 0x100f3fb0 +// STRING: LEGO1 0x100f3a18 +const char* g_delimiter = " \t"; + +// GLOBAL: LEGO1 0x100f3fb4 +// STRING: LEGO1 0x100f3bf0 const char* g_set = "set"; + +// GLOBAL: LEGO1 0x100f3fb8 +// STRING: LEGO1 0x100f0cdc const char* g_reset = "reset"; // FUNCTION: LEGO1 0x1003bfb0 diff --git a/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp b/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp index 110a88d0..b10b285f 100644 --- a/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp +++ b/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp @@ -7,10 +7,12 @@ DECOMP_SIZE_ASSERT(LegoFullScreenMovie, 0x24) -// GLOBAL: LEGO1 0x100f3be8 +// GLOBAL: LEGO1 0x100f3fbc +// STRING: LEGO1 0x100f3be8 const char* g_strEnable = "enable"; -// GLOBAL: LEGO1 0x100f3bf4 +// GLOBAL: LEGO1 0x100f3fc0 +// STRING: LEGO1 0x100f3bf4 const char* g_strDisable = "disable"; // FUNCTION: LEGO1 0x1003c500 @@ -29,7 +31,6 @@ void LegoFullScreenMovie::SetValue(const char* p_option) LegoVideoManager* videomanager = VideoManager(); if (videomanager) { - if (!strcmp(m_value.GetData(), g_strEnable)) { videomanager->EnableFullScreenMovie(TRUE); return; diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index a081248c..a470732e 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -1,9 +1,13 @@ #include "legogamestate.h" #include "infocenterstate.h" +#include "legoanimationmanager.h" #include "legoomni.h" #include "legostate.h" #include "legostream.h" +#include "legoutil.h" +#include "legovideomanager.h" +#include "mxbackgroundaudiomanager.h" #include "mxobjectfactory.h" #include "mxstring.h" #include "mxvariabletable.h" @@ -15,14 +19,17 @@ // There may be other members that come after. DECOMP_SIZE_ASSERT(LegoGameState, 0x430) -// GLOBAL: LEGO1 0x100f3e24 -const char* g_historyGSI = "History.gsi"; +// GLOBAL: LEGO1 0x100f3e40 +// STRING: LEGO1 0x100f3e3c +const char* g_fileExtensionGS = ".GS"; -// GLOBAL: LEGO1 0x100f3e30 +// GLOBAL: LEGO1 0x100f3e44 +// STRING: LEGO1 0x100f3e30 const char* g_playersGSI = "Players.gsi"; -// GLOBAL: LEGO1 0x100f3e40 -const char* g_fileExtensionGS = ".GS"; +// GLOBAL: LEGO1 0x100f3e48 +// STRING: LEGO1 0x100f3e24 +const char* g_historyGSI = "History.gsi"; // GLOBAL: LEGO1 0x100f3e58 ColorStringStruct g_colorSaveData[43] = { @@ -85,11 +92,18 @@ LegoGameState::~LegoGameState() delete[] m_savePath; } +// STUB: LEGO1 0x10039780 +void LegoGameState::FUN_10039780(MxU8) +{ + // TODO +} + // FUNCTION: LEGO1 0x10039980 MxResult LegoGameState::Save(MxULong p_slot) { MxResult result; InfocenterState* infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); + if (!infocenterState || infocenterState->GetInfocenterBufferElement(0) == 0) result = SUCCESS; else { @@ -98,7 +112,7 @@ MxResult LegoGameState::Save(MxULong p_slot) MxString savePath; GetFileSavePath(&savePath, p_slot); LegoFileStream fileStream; - if (fileStream.Open(savePath.GetData(), LegoStream::WriteBit) != FAILURE) { + if (fileStream.Open(savePath.GetData(), LegoStream::c_writeBit) != FAILURE) { MxU32 maybeVersion = 0x1000C; fileStream.Write(&maybeVersion, 4); fileStream.Write(&m_unk0x24, 2); @@ -164,7 +178,7 @@ void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) strcpy(path, m_savePath); // Slot: "G0", "G1", ... - strcat(path, "G"); + strcat(path, "\\G"); baseForSlot[0] += p_slotn; strcat(path, baseForSlot); @@ -186,9 +200,30 @@ void LegoGameState::FUN_1003a720(MxU32) } // STUB: LEGO1 0x1003b060 -void LegoGameState::HandleAction(MxU32) +void LegoGameState::HandleAction(MxU32 p_area) { - // TODO + 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 + } + + InvokeAction(Extra::ActionType::e_opendisk, *script, 0, NULL); } // FUNCTION: LEGO1 0x1003bac0 @@ -282,7 +317,7 @@ void LegoGameState::SerializeScoreHistory(MxS16 p_flags) savePath += "\\"; savePath += g_historyGSI; - if (p_flags == LegoStream::WriteBit) { + if (p_flags == LegoStream::c_writeBit) { m_unk0xa6.WriteScoreHistory(); } diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp index ff52bad1..8e3d7526 100644 --- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -68,7 +68,7 @@ #include "doors.h" #include "jetski.h" #include "legoanimmmpresenter.h" -#include "motorcycle.h" +#include "motocycle.h" #include "racecar.h" #include "towtrack.h" #include "towtrackmissionstate.h" @@ -106,7 +106,7 @@ // FUNCTION: LEGO1 0x10006e40 LegoObjectFactory::LegoObjectFactory() { -#define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact); +#define X(V) this->m_id##V = MxAtomId(#V, e_exact); FOR_LEGOOBJECTFACTORY_OBJECTS(X) #undef X } @@ -114,7 +114,7 @@ LegoObjectFactory::LegoObjectFactory() // FUNCTION: LEGO1 0x10009a90 MxCore* LegoObjectFactory::Create(const char* p_name) { - MxAtomId atom(p_name, LookupMode_Exact); + MxAtomId atom(p_name, e_exact); #define X(V) \ if (this->m_id##V == atom) { \ diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 4b93d8d7..193f5c8a 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -18,6 +18,12 @@ void LegoPlantManager::Init() // TODO } +// STUB: LEGO1 0x10026360 +void LegoPlantManager::FUN_10026360(undefined4 p_world) +{ + // TODO +} + // STUB: LEGO1 0x10026e00 MxResult LegoPlantManager::Tickle() { diff --git a/LEGO1/lego/legoomni/src/common/legostream.cpp b/LEGO1/lego/legoomni/src/common/legostream.cpp index 0cfe0a51..f54d5982 100644 --- a/LEGO1/lego/legoomni/src/common/legostream.cpp +++ b/LEGO1/lego/legoomni/src/common/legostream.cpp @@ -10,6 +10,7 @@ // 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. @@ -166,18 +167,18 @@ MxResult LegoFileStream::Open(const char* p_filename, OpenFlags p_mode) fclose(m_hFile); modeString[0] = '\0'; - if (p_mode & ReadBit) { + if (p_mode & c_readBit) { m_mode = LEGOSTREAM_MODE_READ; strcat(modeString, "r"); } - if (p_mode & WriteBit) { + if (p_mode & c_writeBit) { if (m_mode != LEGOSTREAM_MODE_READ) m_mode = LEGOSTREAM_MODE_WRITE; strcat(modeString, "w"); } - if ((p_mode & 4) != 0) + if ((p_mode & c_binaryBit) != 0) strcat(modeString, "b"); else strcat(modeString, "t"); diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index 2e4d1804..a6e7e135 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -47,3 +47,9 @@ MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream* p_stream) } return result; } + +// STUB: LEGO1 0x10083db0 +void LegoUnkSaveDataWriter::FUN_10083db0(LegoROI* p_roi) +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/common/legoutil.cpp b/LEGO1/lego/legoomni/src/common/legoutil.cpp index 4941d968..fb207f50 100644 --- a/LEGO1/lego/legoomni/src/common/legoutil.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutil.cpp @@ -11,30 +11,30 @@ #include // FUNCTION: LEGO1 0x1003e300 -ExtraActionType MatchActionString(const char* p_str) +Extra::ActionType MatchActionString(const char* p_str) { - ExtraActionType result = ExtraActionType_unknown; + Extra::ActionType result = Extra::ActionType::e_unknown; if (!strcmpi("openram", p_str)) - result = ExtraActionType_openram; + result = Extra::ActionType::e_openram; else if (!strcmpi("opendisk", p_str)) - result = ExtraActionType_opendisk; + result = Extra::ActionType::e_opendisk; else if (!strcmpi("close", p_str)) - result = ExtraActionType_close; + result = Extra::ActionType::e_close; else if (!strcmpi("start", p_str)) - result = ExtraActionType_start; + result = Extra::ActionType::e_start; else if (!strcmpi("stop", p_str)) - result = ExtraActionType_stop; + result = Extra::ActionType::e_stop; else if (!strcmpi("run", p_str)) - result = ExtraActionType_run; + result = Extra::ActionType::e_run; else if (!strcmpi("exit", p_str)) - result = ExtraActionType_exit; + result = Extra::ActionType::e_exit; else if (!strcmpi("enable", p_str)) - result = ExtraActionType_enable; + result = Extra::ActionType::e_enable; else if (!strcmpi("disable", p_str)) - result = ExtraActionType_disable; + result = Extra::ActionType::e_disable; else if (!strcmpi("notify", p_str)) - result = ExtraActionType_notify; + result = Extra::ActionType::e_notify; return result; } @@ -43,54 +43,54 @@ MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_enti void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender); // FUNCTION: LEGO1 0x1003e430 -void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender) +void InvokeAction(Extra::ActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender) { MxDSAction action; action.SetAtomId(p_pAtom); action.SetObjectId(p_targetEntityId); switch (p_actionId) { - case ExtraActionType_opendisk: + case Extra::ActionType::e_opendisk: if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { - Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_DiskStream); + Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_diskStream); Start(&action); } break; - case ExtraActionType_openram: + case Extra::ActionType::e_openram: if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_RAMStream); Start(&action); } break; - case ExtraActionType_close: + case Extra::ActionType::e_close: action.SetUnknown24(-2); DeleteObject(action); Streamer()->Close(p_pAtom.GetInternal()); break; - case ExtraActionType_start: + case Extra::ActionType::e_start: if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { Start(&action); } break; - case ExtraActionType_stop: + case Extra::ActionType::e_stop: action.SetUnknown24(-2); if (!FUN_1003ee00(p_pAtom, p_targetEntityId)) { DeleteObject(action); } break; - case ExtraActionType_run: + case Extra::ActionType::e_run: _spawnl(0, "\\lego\\sources\\main\\main.exe", "\\lego\\sources\\main\\main.exe", "/script", &p_pAtom, 0); break; - case ExtraActionType_exit: + case Extra::ActionType::e_exit: Lego()->SetExit(TRUE); break; - case ExtraActionType_enable: + case Extra::ActionType::e_enable: CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId); break; - case ExtraActionType_disable: + case Extra::ActionType::e_disable: CheckIfEntityExists(FALSE, p_pAtom.GetInternal(), p_targetEntityId); break; - case ExtraActionType_notify: + case Extra::ActionType::e_notify: NotifyEntity(p_pAtom.GetInternal(), p_targetEntityId, p_sender); break; } @@ -99,8 +99,7 @@ void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEnt // FUNCTION: LEGO1 0x1003e670 MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId) { - LegoWorld* world = - (LegoWorld*) FindEntityByAtomIdOrEntityId(MxAtomId(p_filename, LookupMode_LowerCase2), p_entityId); + LegoWorld* world = (LegoWorld*) FindEntityByAtomIdOrEntityId(MxAtomId(p_filename, e_lowerCase2), p_entityId); if (world) { world->VTable0x68(p_enable); return TRUE; diff --git a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp index 2a15d445..d3971150 100644 --- a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp @@ -16,13 +16,13 @@ MxCompositeMediaPresenter::MxCompositeMediaPresenter() { m_unk0x4c = 0; m_unk0x4e = FALSE; - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); } // FUNCTION: LEGO1 0x10074020 MxCompositeMediaPresenter::~MxCompositeMediaPresenter() { - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); } // FUNCTION: LEGO1 0x10074090 @@ -55,12 +55,12 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller if (presenter && presenter->AddToManager() == SUCCESS) { presenter->SetCompositePresenter(this); if (presenter->StartAction(p_controller, action) == SUCCESS) { - presenter->SetTickleState(TickleState_Idle); + presenter->SetTickleState(e_idle); if (presenter->IsA("MxVideoPresenter")) - VideoManager()->RemovePresenter(*presenter); + VideoManager()->UnregisterPresenter(*presenter); else if (presenter->IsA("MxAudioPresenter")) - SoundManager()->RemovePresenter(*presenter); + SoundManager()->UnregisterPresenter(*presenter); success = TRUE; } @@ -75,7 +75,7 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller } if (!m_compositePresenter) { - SetTickleState(TickleState_Ready); + SetTickleState(e_ready); MxLong time = Timer()->GetTime(); m_action->SetUnknown90(time); } @@ -93,10 +93,10 @@ void MxCompositeMediaPresenter::StartingTickle() if (!m_unk0x4e) { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { - if ((*it)->GetCurrentTickleState() < TickleState_Streaming) { + if ((*it)->GetCurrentTickleState() < e_streaming) { (*it)->Tickle(); - if ((*it)->GetCurrentTickleState() == TickleState_Streaming || + if ((*it)->GetCurrentTickleState() == e_streaming || ((*it)->GetAction() && (*it)->GetAction()->GetStartTime())) m_unk0x4c++; } @@ -115,16 +115,15 @@ void MxCompositeMediaPresenter::StartingTickle() else { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { if (!(*it)->GetAction()->GetStartTime() && ((MxMediaPresenter*) *it)->CurrentChunk() && - !((*it)->GetAction()->GetFlags() & MxDSAction::Flag_Bit9)) { + !((*it)->GetAction()->GetFlags() & MxDSAction::c_bit9)) { (*it)->Tickle(); - (*it)->GetAction()->SetFlags((*it)->GetAction()->GetFlags() | MxDSAction::Flag_Bit9); + (*it)->GetAction()->SetFlags((*it)->GetAction()->GetFlags() | MxDSAction::c_bit9); m_unk0x4c--; } } if (!m_unk0x4c) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); MxLong time = Timer()->GetTime(); m_action->SetUnknown90(time); } @@ -137,16 +136,15 @@ MxResult MxCompositeMediaPresenter::Tickle() MxAutoLocker lock(&m_criticalSection); switch (m_currentTickleState) { - case TickleState_Ready: - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; - case TickleState_Starting: + case e_ready: + ProgressTickleState(e_starting); + case e_starting: StartingTickle(); break; - case TickleState_Streaming: - case TickleState_Repeating: - case TickleState_unk5: - case TickleState_Done: { + case e_streaming: + case e_repeating: + case e_unk5: + case e_done: { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) (*it)->Tickle(); break; @@ -163,7 +161,7 @@ MxResult MxCompositeMediaPresenter::PutData() { MxAutoLocker lock(&m_criticalSection); - if (m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_Done) { + if (m_currentTickleState >= e_streaming && m_currentTickleState <= e_done) { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) (*it)->PutData(); } diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index f3c70c50..64c19cd5 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -12,6 +12,12 @@ LegoControlManager::~LegoControlManager() // TODO } +// STUB: LEGO1 0x10028df0 +void LegoControlManager::FUN_10028df0(MxPresenterList* p_presenterList) +{ + // TODO +} + // STUB: LEGO1 0x10028e10 void LegoControlManager::Register(MxCore* p_listener) { @@ -24,6 +30,11 @@ void LegoControlManager::Unregister(MxCore* p_listener) // TODO } +// STUB: LEGO1 0x100293c0 +void LegoControlManager::FUN_100293c0(undefined4, const MxAtomId&, undefined2) +{ +} + // STUB: LEGO1 0x10029600 MxResult LegoControlManager::Tickle() { diff --git a/LEGO1/omni/src/control/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp similarity index 52% rename from LEGO1/omni/src/control/mxcontrolpresenter.cpp rename to LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp index 2c7fb81d..7a204a78 100644 --- a/LEGO1/omni/src/control/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp @@ -1,6 +1,7 @@ #include "mxcontrolpresenter.h" #include "mxticklemanager.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) @@ -28,9 +29,9 @@ MxBool MxControlPresenter::VTable0x64(undefined4 p_undefined) } // FUNCTION: LEGO1 0x10043ff0 -void MxControlPresenter::VTable0x68(MxBool p_undefined) +void MxControlPresenter::VTable0x68(MxBool p_unk0x50) { - m_unk0x50 = p_undefined; + m_unk0x50 = p_unk0x50; } // FUNCTION: LEGO1 0x10044110 @@ -47,11 +48,28 @@ MxResult MxControlPresenter::AddToManager() return SUCCESS; } -// STUB: LEGO1 0x10044190 -MxResult MxControlPresenter::StartAction(MxStreamController*, MxDSAction*) +// FUNCTION: LEGO1 0x10044190 +MxResult MxControlPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { - // TODO - return SUCCESS; + MxResult result = MxCompositePresenter::StartAction(p_controller, p_action); + + FUN_100b7220(m_action, MxDSAction::c_world | MxDSAction::c_looping, TRUE); + ParseExtra(); + + MxS16 i = 0; + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + (*it)->Enable((m_unk0x4c != 3 || m_unk0x4e) && IsEnabled() ? m_unk0x4e == i : FALSE); + i++; + } + + if (m_unk0x4c == 3) { + MxDSAction* action = (*m_list.begin())->GetAction(); + action->SetFlags(action->GetFlags() | MxDSAction::c_bit11); + } + + TickleManager()->RegisterClient(this, 200); + + return result; } // FUNCTION: LEGO1 0x10044260 @@ -78,7 +96,7 @@ MxBool MxControlPresenter::FUN_10044480(undefined4, undefined4*) } // STUB: LEGO1 0x10044540 -void MxControlPresenter::FUN_10044540(undefined2) +void MxControlPresenter::VTable0x6c(undefined4) { // TODO } @@ -88,9 +106,7 @@ void MxControlPresenter::ReadyTickle() { MxPresenter::ParseExtra(); TickleManager()->UnregisterClient(this); - - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); } // STUB: LEGO1 0x10044640 @@ -99,15 +115,34 @@ void MxControlPresenter::ParseExtra() // TODO } -// STUB: LEGO1 0x10044820 +// FUNCTION: LEGO1 0x10044820 void MxControlPresenter::Enable(MxBool p_enable) { - // TODO + if (MxPresenter::IsEnabled() != p_enable) { + MxPresenter::Enable(p_enable); + + MxS16 i = 0; + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + if (i == m_unk0x4e) { + (*it)->Enable((m_unk0x4c != 3 || i != 0) ? p_enable : 0); + break; + } + + i++; + } + + if (!p_enable) { + m_unk0x4e = 0; + } + } } -// STUB: LEGO1 0x100448a0 +// FUNCTION: LEGO1 0x100448a0 MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState) { - // TODO - return TRUE; + MxCompositePresenterList::iterator it = m_list.begin(); + 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 46f59a77..e9010ef4 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -11,3 +11,9 @@ LegoActor::LegoActor() m_unk0x10 = 0; m_unk0x74 = 0; } + +// STUB: LEGO1 0x1002d320 +LegoActor::~LegoActor() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp new file mode 100644 index 00000000..927677fe --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp @@ -0,0 +1,39 @@ +#include "legoactorpresenter.h" + +#include "legoentity.h" +#include "legoomni.h" + +// FUNCTION: LEGO1 0x10076c30 +void LegoActorPresenter::ReadyTickle() +{ + if (GetCurrentWorld()) { + m_entity = (LegoEntity*) CreateEntity("LegoActor"); + if (m_entity) { + SetEntityLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); + m_entity->Create(*m_action); + } + ProgressTickleState(e_starting); + } +} + +// FUNCTION: LEGO1 0x10076c90 +void LegoActorPresenter::StartingTickle() +{ + if (m_entity->GetROI()) { + ProgressTickleState(e_streaming); + ParseExtra(); + } +} + +// FUNCTION: LEGO1 0x10076cc0 +void LegoActorPresenter::ParseExtra() +{ + char buffer[512]; + char* extraData = m_action->GetExtraData(); + if (m_action->GetExtraLength()) { + memcpy(buffer, extraData, m_action->GetExtraLength()); + buffer[m_action->GetExtraLength()] = 0; + + m_entity->ParseAction(buffer); + } +} diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index 34afaac0..d48d22ff 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -10,7 +10,7 @@ DECOMP_SIZE_ASSERT(LegoCameraController, 0xc8); // FUNCTION: LEGO1 0x10011d50 LegoCameraController::LegoCameraController() { - SetWorldTransform(Vector3Data(0, 0, 0), Vector3Data(0, 0, 1), Vector3Data(0, 1, 0)); + SetWorldTransform(Mx3DPointFloat(0, 0, 0), Mx3DPointFloat(0, 0, 1), Mx3DPointFloat(0, 1, 0)); } // FUNCTION: LEGO1 0x10011f70 @@ -71,37 +71,49 @@ void LegoCameraController::OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) } // FUNCTION: LEGO1 0x10012260 -void LegoCameraController::SetWorldTransform(Vector3Impl& p_at, Vector3Impl& p_dir, Vector3Impl& p_up) +void LegoCameraController::SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up) { CalcLocalTransform(p_at, p_dir, p_up, m_matrix1); m_matrix2 = m_matrix1; } // STUB: LEGO1 0x100123e0 -void LegoCameraController::FUN_100123e0(Matrix4Data& p_transform, MxU32) +void LegoCameraController::FUN_100123e0(const MxMatrix& p_transform, MxU32) { } -// STUB: LEGO1 0x10012740 -Vector3Data& LegoCameraController::FUN_10012740() +// FUNCTION: LEGO1 0x10012740 +Mx3DPointFloat LegoCameraController::GetWorldUp() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldUp(); + return Mx3DPointFloat(vec[0], vec[1], vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } -// STUB: LEGO1 0x100127f0 -Vector3Data& LegoCameraController::FUN_100127f0() +// FUNCTION: LEGO1 0x100127f0 +Mx3DPointFloat LegoCameraController::GetWorldLocation() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldPosition(); + return Mx3DPointFloat(vec[0], vec[1] - m_entityOffsetUp, vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } -// STUB: LEGO1 0x100128a0 -Vector3Data& LegoCameraController::FUN_100128a0() +// FUNCTION: LEGO1 0x100128a0 +Mx3DPointFloat LegoCameraController::GetWorldDirection() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldDirection(); + return Mx3DPointFloat(vec[0], vec[1], vec[2]); + } + 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 0f813029..2c482715 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -2,17 +2,13 @@ #include "define.h" #include "legoomni.h" +#include "legounksavedatawriter.h" #include "legoutil.h" +#include "legovideomanager.h" #include "legoworld.h" DECOMP_SIZE_ASSERT(LegoEntity, 0x68) -// FUNCTION: LEGO1 0x1000c290 -LegoEntity::~LegoEntity() -{ - Destroy(TRUE); -} - // FUNCTION: LEGO1 0x100105f0 void LegoEntity::Init() { @@ -20,11 +16,11 @@ void LegoEntity::Init() m_worldDirection.Fill(0); m_worldSpeed = 0; m_roi = NULL; - m_cameraFlag = 0; + m_cameraFlag = FALSE; m_actionArgString = NULL; m_unk0x10 = 0; - m_unk0x11 = 0; - m_actionType = ExtraActionType_unknown; + m_flags = 0; + m_actionType = Extra::ActionType::e_unknown; m_actionArgNumber = -1; m_unk0x59 = 4; } @@ -36,25 +32,34 @@ void LegoEntity::ResetWorldTransform(MxBool p_inVehicle) } // STUB: LEGO1 0x10010790 -void LegoEntity::SetWorldTransform(Vector3Impl& p_loc, Vector3Impl& p_dir, Vector3Impl& p_up) +void LegoEntity::SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, const Vector3& p_up) { // TODO } // FUNCTION: LEGO1 0x100107e0 -MxResult LegoEntity::Create(MxDSObject& p_dsObject) +MxResult LegoEntity::Create(MxDSAction& p_dsAction) { - m_mxEntityId = p_dsObject.GetObjectId(); - m_atom = p_dsObject.GetAtomId(); - Init(); + m_mxEntityId = p_dsAction.GetObjectId(); + m_atom = p_dsAction.GetAtomId(); + SetWorld(); return SUCCESS; } -// STUB: LEGO1 0x10010810 +// FUNCTION: LEGO1 0x10010810 void LegoEntity::Destroy(MxBool p_fromDestructor) { if (m_roi) { - // TODO + if (m_flags & c_bit1) { + if (m_roi->GetUnknown0x104() == this) + m_roi->SetUnknown0x104(NULL); + + GetUnkSaveDataWriter()->FUN_10083db0(m_roi); + } + else { + VideoManager()->Get3DManager()->GetLego3DView()->Remove(*m_roi); + delete m_roi; + } } delete[] m_actionArgString; @@ -77,14 +82,18 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) } // STUB: LEGO1 0x100109b0 -void LegoEntity::SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool) +void LegoEntity::SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool) { // TODO } -// STUB: LEGO1 0x10010c30 +// FUNCTION: LEGO1 0x10010c30 void LegoEntity::FUN_10010c30() { + LegoWorld* world = GetCurrentWorld(); + + if (m_cameraFlag && world && world->GetCamera() && m_roi) + world->GetCamera()->FUN_100123e0(m_roi->GetLocal2World(), 1); } // FUNCTION: LEGO1 0x10010e10 @@ -97,13 +106,13 @@ void LegoEntity::ParseAction(char* p_extra) if (KeyValueStringParse(actionValue, g_strACTION, copy)) { m_actionType = MatchActionString(strtok(actionValue, g_parseExtraTokens)); - if (m_actionType != ExtraActionType_exit) { + if (m_actionType != Extra::ActionType::e_exit) { char* token = strtok(NULL, g_parseExtraTokens); m_actionArgString = new char[strlen(token) + 1]; strcpy(m_actionArgString, token); - if (m_actionType != ExtraActionType_run) { + if (m_actionType != Extra::ActionType::e_run) { m_actionArgNumber = atoi(strtok(NULL, g_parseExtraTokens)); } } diff --git a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp index 7a586c80..0da082cd 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp @@ -15,7 +15,7 @@ LegoEntityPresenter::LegoEntityPresenter() // FUNCTION: LEGO1 0x100535c0 void LegoEntityPresenter::Init() { - m_objectBackend = 0; + m_entity = NULL; } // FUNCTION: LEGO1 0x100535d0 @@ -25,9 +25,9 @@ LegoEntityPresenter::~LegoEntityPresenter() } // FUNCTION: LEGO1 0x10053630 -undefined4 LegoEntityPresenter::SetBackend(LegoEntity* p_backend) +undefined4 LegoEntityPresenter::SetEntity(LegoEntity* p_entity) { - m_objectBackend = p_backend; + m_entity = p_entity; return 0; } @@ -35,7 +35,7 @@ undefined4 LegoEntityPresenter::SetBackend(LegoEntity* p_backend) void LegoEntityPresenter::Destroy(MxBool p_fromDestructor) { if (VideoManager()) { - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); } Init(); @@ -53,7 +53,7 @@ MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDS MxResult result = MxCompositePresenter::StartAction(p_controller, p_action); if (VideoManager()) { - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); } return result; @@ -63,14 +63,13 @@ MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDS void LegoEntityPresenter::ReadyTickle() { if (GetCurrentWorld()) { - m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoEntity"); - if (m_objectBackend) { - m_objectBackend->Create(*m_action); - m_objectBackend->SetLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), TRUE); + m_entity = (LegoEntity*) MxPresenter::CreateEntity("LegoEntity"); + if (m_entity) { + m_entity->Create(*m_action); + m_entity->SetLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), TRUE); ParseExtra(); } - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -83,10 +82,14 @@ void LegoEntityPresenter::RepeatingTickle() } // FUNCTION: LEGO1 0x10053730 -void LegoEntityPresenter::SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up) +void LegoEntityPresenter::SetEntityLocation( + Mx3DPointFloat& p_location, + Mx3DPointFloat& p_direction, + Mx3DPointFloat& p_up +) { - if (m_objectBackend) { - m_objectBackend->SetLocation(p_location, p_direction, p_up, TRUE); + if (m_entity) { + m_entity->SetLocation(p_location, p_direction, p_up, TRUE); } } @@ -100,6 +103,6 @@ void LegoEntityPresenter::ParseExtra() data[len] = 0; len &= MAXWORD; - m_objectBackend->ParseAction(data); + m_entity->ParseAction(data); } } diff --git a/LEGO1/lego/legoomni/src/entity/legopathactor.cpp b/LEGO1/lego/legoomni/src/entity/legopathactor.cpp index f6d0a10d..472f2e4b 100644 --- a/LEGO1/lego/legoomni/src/entity/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legopathactor.cpp @@ -39,7 +39,7 @@ void LegoPathActor::VTable0x8c() } // STUB: LEGO1 0x1002e740 -void LegoPathActor::VTable0x74(Matrix4Impl& p_transform) +void LegoPathActor::VTable0x74(Matrix4& p_transform) { // TODO } diff --git a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp index a2e1bb04..f656022d 100644 --- a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp @@ -100,6 +100,12 @@ MxResult LegoPointOfViewController::Create(Lego3DView* p_lego3DView) return SUCCESS; } +// FUNCTION: LEGO1 0x100658a0 +void LegoPointOfViewController::OnViewSize(int p_width, int p_height) +{ + m_nav->SetControlMax(p_width, p_height); +} + // FUNCTION: LEGO1 0x100658c0 void LegoPointOfViewController::LeftDown(int p_x, int p_y) { diff --git a/LEGO1/lego/legoomni/src/entity/legorace.cpp b/LEGO1/lego/legoomni/src/entity/legorace.cpp index d5eefbd5..79565966 100644 --- a/LEGO1/lego/legoomni/src/entity/legorace.cpp +++ b/LEGO1/lego/legoomni/src/entity/legorace.cpp @@ -62,7 +62,7 @@ MxBool LegoRace::VTable0x64() } // STUB: LEGO1 0x10015ce0 -MxResult LegoRace::Create(MxDSObject& p_dsObject) +MxResult LegoRace::Create(MxDSAction& p_dsAction) { // TODO return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index ff3969bd..9611713c 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -1,21 +1,27 @@ #include "legoworld.h" +#include "legocontrolmanager.h" #include "legoinputmanager.h" #include "legoomni.h" #include "legoutil.h" +#include "legovideomanager.h" #include "mxactionnotificationparam.h" #include "mxnotificationmanager.h" #include "mxnotificationparam.h" #include "mxomni.h" #include "mxticklemanager.h" -DECOMP_SIZE_ASSERT(LegoWorld, 0xf8); +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) // STUB: LEGO1 0x1001ca40 LegoWorld::LegoWorld() : m_list0x68(TRUE) { // TODO - m_unk0xf6 = FALSE; + m_worldStarted = FALSE; m_unk0xf4 = 4; NotificationManager()->Register(this); } @@ -38,10 +44,36 @@ LegoWorld::~LegoWorld() // TODO } -// STUB: LEGO1 0x1001e0b0 -MxResult LegoWorld::SetAsCurrentWorld(MxDSObject& p_dsObject) +// FUNCTION: LEGO1 0x1001e0b0 +MxResult LegoWorld::Create(MxDSAction& p_dsAction) { - // TODO + MxEntity::Create(p_dsAction); + + m_entityList = new LegoEntityList(TRUE); + + if (!m_entityList) + return FAILURE; + + m_coreList = new MxCoreList(TRUE); + + if (!m_coreList) + return FAILURE; + + if (!VTable0x54()) + return FAILURE; + + if (p_dsAction.GetFlags() & MxDSAction::c_enabled) { + if (GetCurrentWorld()) { + GetCurrentWorld()->VTable0x68(0); + } + + SetCurrentWorld(this); + ControlManager()->FUN_10028df0(&m_list0xb8); + } + + SetIsWorldActive(TRUE); + m_unk0xec = -1; + return SUCCESS; } @@ -63,10 +95,37 @@ MxLong LegoWorld::Notify(MxParam& p_param) return ret; } -// STUB: LEGO1 0x1001f630 -void LegoWorld::VTable0x54() +// FUNCTION: LEGO1 0x1001f630 +LegoCameraController* LegoWorld::VTable0x54() { - // TODO + MxBool success = FALSE; + + if (!VideoManager()) { + goto done; + } + if (!(m_cameraController = new LegoCameraController())) { + goto done; + } + if (m_cameraController->Create() != SUCCESS) { + goto done; + } + + m_cameraController->OnViewSize( + VideoManager()->GetVideoParam().GetRect().GetWidth(), + VideoManager()->GetVideoParam().GetRect().GetHeight() + ); + + success = TRUE; + +done: + if (!success) { + if (m_cameraController) { + delete m_cameraController; + m_cameraController = NULL; + } + } + + return m_cameraController; } // STUB: LEGO1 0x1001fc80 @@ -92,6 +151,12 @@ void LegoWorld::EndAction(MxCore* p_object) { } +// STUB: LEGO1 0x100213a0 +MxPresenter* LegoWorld::FindPresenter(const char* p_presenter, const char* p_name) +{ + return NULL; +} + // STUB: LEGO1 0x10021a70 void LegoWorld::VTable0x68(MxBool p_add) { @@ -101,12 +166,12 @@ void LegoWorld::VTable0x68(MxBool p_add) // FUNCTION: LEGO1 0x10022080 MxResult LegoWorld::Tickle() { - if (!m_unk0xf6) { + if (!m_worldStarted) { switch (m_unk0xf4) { case 0: - m_unk0xf6 = TRUE; + m_worldStarted = TRUE; SetAppCursor(0); - Stop(); + VTable0x50(); return TRUE; case 2: if (FUN_100220e0() == 1) @@ -121,23 +186,23 @@ MxResult LegoWorld::Tickle() // STUB: LEGO1 0x100220e0 undefined LegoWorld::FUN_100220e0() { - return TRUE; + return 0; } // FUNCTION: LEGO1 0x10022340 -void LegoWorld::Stop() +void LegoWorld::VTable0x50() { TickleManager()->UnregisterClient(this); } // STUB: LEGO1 0x100727e0 -MxBool LegoWorld::FUN_100727e0(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) +MxBool LegoWorld::FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) { return FALSE; } // STUB: LEGO1 0x10072980 -MxBool LegoWorld::FUN_10072980(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) +MxBool LegoWorld::FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) { return FALSE; } diff --git a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp index 02578675..180c86e8 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp @@ -1,12 +1,18 @@ #include "legoworldpresenter.h" +#include "legoanimationmanager.h" +#include "legobuildingmanager.h" #include "legoentity.h" #include "legoomni.h" +#include "legoplantmanager.h" #include "legovideomanager.h" +#include "legoworld.h" #include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxdsactionlist.h" +#include "mxdsmediaaction.h" #include "mxdsmultiaction.h" +#include "mxnotificationmanager.h" #include "mxobjectfactory.h" #include "mxpresenter.h" #include "mxstl/stlcompat.h" @@ -26,10 +32,32 @@ LegoWorldPresenter::LegoWorldPresenter() m_unk0x50 = 50000; } -// STUB: LEGO1 0x10066770 +// FUNCTION: LEGO1 0x10066770 LegoWorldPresenter::~LegoWorldPresenter() { - // TODO + MxBool result = FALSE; + if (m_entity) { + undefined4 world = ((LegoWorld*) m_entity)->GetUnknown0xec(); + PlantManager()->FUN_10026360(world); + AnimationManager()->FUN_1005f720(world); + BuildingManager()->FUN_1002fa00(); + result = ((LegoWorld*) m_entity)->VTable0x5c(); + } + + if (result == FALSE) { + FUN_10015820(0, 7); + } + + if (m_entity) { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationNewPresenter, NULL); + NotificationManager()->Send(m_entity, ¶m); + } +#else + NotificationManager()->Send(m_entity, &MxNotificationParam(c_notificationNewPresenter, NULL)); +#endif + } } // FUNCTION: LEGO1 0x10066870 @@ -63,7 +91,7 @@ MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSA if (presenter && presenter->AddToManager() == SUCCESS) { presenter->SetCompositePresenter(this); if (presenter->StartAction(p_controller, action) == SUCCESS) { - presenter->SetTickleState(TickleState_Idle); + presenter->SetTickleState(e_idle); success = TRUE; } } @@ -76,7 +104,7 @@ MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSA delete presenter; } - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); result = SUCCESS; } @@ -87,16 +115,15 @@ MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSA // FUNCTION: LEGO1 0x10066a50 void LegoWorldPresenter::ReadyTickle() { - m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoWorld"); - if (m_objectBackend) { - m_objectBackend->Create(*m_action); - Lego()->AddWorld((LegoWorld*) m_objectBackend); - SetBackendLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); + m_entity = (LegoEntity*) MxPresenter::CreateEntity("LegoWorld"); + if (m_entity) { + m_entity->Create(*m_action); + Lego()->AddWorld((LegoWorld*) m_entity); + SetEntityLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); } ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } // FUNCTION: LEGO1 0x10066ac0 @@ -104,25 +131,42 @@ void LegoWorldPresenter::StartingTickle() { if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *m_list.begin(); - if (presenter->GetCurrentTickleState() == TickleState_Idle) { - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) { + presenter->SetTickleState(e_ready); } } else { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { - if ((*it)->GetCurrentTickleState() == TickleState_Idle) { - (*it)->SetTickleState(TickleState_Ready); + if ((*it)->GetCurrentTickleState() == e_idle) { + (*it)->SetTickleState(e_ready); } } } - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); } -// STUB: LEGO1 0x10067a70 +// FUNCTION: LEGO1 0x10067a70 void LegoWorldPresenter::VTable0x60(MxPresenter* p_presenter) { + MxCompositePresenter::VTable0x60(p_presenter); + MxDSAction* action = p_presenter->GetAction(); + + if (action->GetDuration() != -1 && (action->GetFlags() & MxDSAction::c_looping) == 0) { + if (!action->IsA("MxDSMediaAction")) { + return; + } + + if (((MxDSMediaAction*) action)->GetSustainTime() != -1) { + return; + } + } + + if (!p_presenter->IsA("LegoAnimPresenter") && !p_presenter->IsA("MxControlPresenter") && + !p_presenter->IsA("MxCompositePresenter")) { + p_presenter->SendToCompositePresenter(Lego()); + ((LegoWorld*) m_entity)->VTable0x58(p_presenter); + } } // STUB: LEGO1 0x10067b00 diff --git a/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp index 24325511..7f7aff11 100644 --- a/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp @@ -1,9 +1,22 @@ #include "gasstation.h" -// STUB: LEGO1 0x100046a0 +#include "mxnotificationmanager.h" + +// FUNCTION: LEGO1 0x100046a0 GasStation::GasStation() { - // TODO + 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; + + NotificationManager()->Register(this); } // STUB: LEGO1 0x100048c0 diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp index 247defb0..1dbb8a67 100644 --- a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -1,15 +1,28 @@ #include "elevatorbottom.h" -// STUB: LEGO1 0x10017e90 +DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) + +#include "legocontrolmanager.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "mxnotificationmanager.h" +#include "mxomni.h" + +// FUNCTION: LEGO1 0x10017e90 ElevatorBottom::ElevatorBottom() { - // TODO + NotificationManager()->Register(this); + this->m_unk0xf8 = 0; } -// STUB: LEGO1 0x10018060 +// FUNCTION: LEGO1 0x10018060 ElevatorBottom::~ElevatorBottom() { - // TODO + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } // STUB: LEGO1 0x10018150 diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index 8c6bcb8d..0cba8908 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -1,9 +1,49 @@ #include "infocenter.h" -// STUB: LEGO1 0x1006ea20 +#include "infocenterstate.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "legoutil.h" +#include "legovideomanager.h" +#include "mxactionnotificationparam.h" +#include "mxbackgroundaudiomanager.h" +#include "mxnotificationmanager.h" +#include "mxstillpresenter.h" +#include "mxtransitionmanager.h" + +DECOMP_SIZE_ASSERT(Infocenter, 0x1d8) +DECOMP_SIZE_ASSERT(InfocenterUnkDataEntry, 0x18) + +// GLOBAL: LEGO1 0x100f76a0 +const char* g_object2x4red = "2x4red"; + +// GLOBAL: LEGO1 0x100f76a4 +const char* g_object2x4grn = "2x4grn"; + +// FUNCTION: LEGO1 0x1006ea20 Infocenter::Infocenter() { - // TODO + m_unk0xfc = 0; + m_unk0x11c = 0; + m_infocenterState = NULL; + m_unk0x1cc = 0; + m_unk0x11c = 0; + m_unk0x104 = 0; + m_currentInfomainScript = c_noInfomain; + m_currentCutscene = e_noIntro; + + memset(&m_entries, 0, sizeof(InfocenterUnkDataEntry) * 7); + + m_unk0x1c8 = -1; + SetAppCursor(1); + NotificationManager()->Register(this); + + m_unk0x1d0 = 0; + m_unk0x1d2 = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; } // STUB: LEGO1 0x1006ec90 @@ -13,35 +53,423 @@ Infocenter::~Infocenter() } // STUB: LEGO1 0x1006ed90 -MxResult Infocenter::Create(MxDSObject& p_dsObject) +MxResult Infocenter::Create(MxDSAction& p_dsAction) { - return FAILURE; + if (LegoWorld::Create(p_dsAction) == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + LegoGameState* gs = GameState(); + m_infocenterState = (InfocenterState*) gs->GetState("InfocenterState"); + if (!m_infocenterState) { + m_infocenterState = (InfocenterState*) gs->CreateState("InfocenterState"); + m_infocenterState->SetUnknown0x74(3); + } + else { + // TODO + } + + // TODO + InputManager()->Register(this); + SetIsWorldActive(FALSE); + return SUCCESS; } -// STUB: LEGO1 0x1006ef10 +// FUNCTION: LEGO1 0x1006ef10 MxLong Infocenter::Notify(MxParam& p_param) { - // TODO - return 0; + MxLong result = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationType0: + result = HandleNotification0(p_param); + break; + case c_notificationEndAction: + result = HandleEndAction(p_param); + break; + case c_notificationKeyPress: + result = HandleKeyPress(((LegoEventNotificationParam&) p_param).GetKey()); + break; + case c_notificationButtonUp: + result = HandleButtonUp( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ); + break; + case c_notificationMouseMove: + result = HandleMouseMove( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ); + break; + case c_notificationType17: + result = HandleNotification17(p_param); + break; + case c_notificationTransitioned: + StopBookAnimation(); + m_unk0x1d2 = 0; + + if (m_infocenterState->GetUnknown0x74() == 0xc) { + StartCredits(); + m_infocenterState->SetUnknown0x74(0xd); + } + else if (m_unk0x104 != 0) { + BackgroundAudioManager()->RaiseVolume(); + GameState()->HandleAction(m_unk0x104); + m_unk0x104 = 0; + } + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x1006f080 +MxLong Infocenter::HandleEndAction(MxParam& p_param) +{ + MxDSAction* action = ((MxEndActionNotificationParam&) p_param).GetAction(); + if (action->GetAtomId() == *g_creditsScript && action->GetObjectId() == 499) { + Lego()->CloseMainWindow(); + return 1; + } + + if (action->GetAtomId() == m_atom && + (action->GetObjectId() == 40 || action->GetObjectId() == 41 || action->GetObjectId() == 42 || + action->GetObjectId() == 43 || action->GetObjectId() == 44)) { + if (m_unk0x1d4) { + m_unk0x1d4--; + } + + if (!m_unk0x1d4) { + PlayMusic(11); + GameState()->FUN_10039780(m_unk0xfc); + + switch (m_unk0xfc) { + case 1: + PlayDialogue(c_pepperCharacterSelect); + break; + case 2: + PlayDialogue(c_mamaCharacterSelect); + break; + case 3: + PlayDialogue(c_papaCharacterSelect); + break; + case 4: + PlayDialogue(c_nickCharacterSelect); + break; + case 5: + PlayDialogue(c_lauraCharacterSelect); + break; + default: + break; + } + + FUN_10070dc0(TRUE); + } + } + + MxLong result = m_radio.Notify(p_param); + + if (result || (action->GetAtomId() != m_atom && action->GetAtomId() != *g_introScript)) + return result; + + if (action->GetObjectId() == c_returnBackGuidanceDialogue2) { + ControlManager()->FUN_100293c0(0x10, action->GetAtomId(), 0); + m_unk0x1d6 = 0; + } + + switch (m_infocenterState->GetUnknown0x74()) { + case 0: + switch (m_currentCutscene) { + case e_legoMovie: + PlayCutscene(e_mindscapeMovie, FALSE); + return 1; + case e_mindscapeMovie: + PlayCutscene(e_introMovie, TRUE); + return 1; + case e_badEndMovie: + StopCutscene(); + m_infocenterState->SetUnknown0x74(11); + PlayDialogue(c_badEndingDialogue); + m_currentCutscene = e_noIntro; + return 1; + case e_goodEndMovie: + StopCutscene(); + m_infocenterState->SetUnknown0x74(11); + PlayDialogue(c_goodEndingDialogue); + m_currentCutscene = e_noIntro; + return 1; + } + + // default / 2nd case probably? + StopCutscene(); + m_infocenterState->SetUnknown0x74(11); + PlayDialogue(c_welcomeDialogue); + m_currentCutscene = e_noIntro; + + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_unk0x1d2 = 1; + return 1; + } + break; + case 1: + m_infocenterState->SetUnknown0x74(11); + + switch (m_currentCutscene) { + case e_badEndMovie: + PlayDialogue(c_badEndingDialogue); + break; + case e_goodEndMovie: + PlayDialogue(c_goodEndingDialogue); + break; + default: + PlayDialogue(c_welcomeDialogue); + } + + m_currentCutscene = e_noIntro; + return 1; + case 2: + FUN_10015860(g_object2x4red, 0); + FUN_10015860(g_object2x4grn, 0); + BackgroundAudioManager()->RaiseVolume(); + return 1; + case 4: + if (action->GetObjectId() == 70 || action->GetObjectId() == 71) { + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_infocenterState->SetUnknown0x74(14); + return 1; + } + break; + case 5: + if (action->GetObjectId() == m_currentInfomainScript) { + if (GameState()->GetUnknown10() != 2 && m_unk0xfc != 0) { + GameState()->FUN_10039780(m_unk0xfc); + } + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_infocenterState->SetUnknown0x74(14); + return 1; + } + break; + case 11: + if (m_infocenterState->GetInfocenterBufferElement(0) == 0 && m_currentInfomainScript != 40 && + m_currentInfomainScript != 41 && m_currentInfomainScript != 42 && m_currentInfomainScript != 43 && + m_currentInfomainScript != 44) { + m_unk0x1d0 = 1; + PlayMusic(11); + } + + m_infocenterState->SetUnknown0x74(2); + FUN_10015860("infoman", 1); + return 1; + case 12: + if (action->GetObjectId() == m_currentInfomainScript) { + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + } + } + + result = 1; + + return result; } // STUB: LEGO1 0x1006f4e0 -void Infocenter::Stop() +void Infocenter::VTable0x50() { - // TODO + m_unk0x1d0 = 0; + m_unk0x1d2 = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; + + MxStillPresenter* bg = (MxStillPresenter*) FindPresenter("MxStillPresenter", "Background_Bitmap"); + MxStillPresenter* bgRed = (MxStillPresenter*) FindPresenter("MxStillPresenter", "BackgroundRed_Bitmap"); + + switch (GameState()->GetUnknown10()) { + case 0: + // bg->Enable(1); // TODO: Uncomment once LegoWorld::FindPresenter and LegoWorld::VTable0x58 are implemented. + InitializeBitmaps(); + switch (m_infocenterState->GetUnknown0x74()) { + case 3: + PlayCutscene(e_legoMovie, TRUE); + m_infocenterState->SetUnknown0x74(0); + return; + case 4: + m_infocenterState->SetUnknown0x74(2); + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_unk0x1d2 = 1; + } + + PlayDialogue(c_letsGetStartedDialogue); + PlayMusic(11); + FUN_10015820(0, 7); + return; + default: + PlayMusic(11); + // TODO + break; + case 8: + PlayMusic(11); + PlayDialogue(c_exitConfirmationDialogue); + FUN_10015820(0, 7); + return; + case 0xf: + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_unk0x1d2 = 1; + } + + PlayDialogue(c_clickOnInfomanDialogue); + PlayMusic(11); + FUN_10015820(0, 7); + return; + } + break; + case 1: + // TODO + break; + case 2: + // TODO + break; + default: + m_infocenterState->SetUnknown0x74(11); + FUN_10015820(0, 7); + return; + } } -// STUB: LEGO1 0x10070aa0 +// STUB: LEGO1 0x1006f9a0 +void Infocenter::InitializeBitmaps() +{ + // TODO: Infocenter class size is wrong +} + +// STUB: LEGO1 0x1006fd00 +MxU8 Infocenter::HandleMouseMove(MxS32 p_x, MxS32 p_y) +{ + return 1; +} + +// FUNCTION: LEGO1 0x1006fda0 +MxLong Infocenter::HandleKeyPress(MxS8 p_key) +{ + MxLong result = 0; + + if (p_key == ' ' && m_worldStarted) { + switch (m_infocenterState->GetUnknown0x74()) { + case 0: + StopCutscene(); + m_infocenterState->SetUnknown0x74(1); + + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_unk0x1d2 = 1; + return 1; + } + break; + case 1: + case 4: + break; + default: { + InfomainScript script = m_currentInfomainScript; + StopCurrentDialogue(); + + switch (m_infocenterState->GetUnknown0x74()) { + case 5: + case 12: + m_currentInfomainScript = script; + return 1; + default: + m_infocenterState->SetUnknown0x74(2); + return 1; + case 8: + case 11: + break; + } + } + case 13: + StopCredits(); + break; + } + + result = 1; + } + + return result; +} + +// STUB: LEGO1 0x1006feb0 +MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) +{ + return 1; +} + +// STUB: LEGO1 0x10070370 +MxU8 Infocenter::HandleNotification17(MxParam&) +{ + return 1; +} + +// STUB: LEGO1 0x10070870 +MxLong Infocenter::HandleNotification0(MxParam&) +{ + return 1; +} + +// FUNCTION: LEGO1 0x10070aa0 void Infocenter::VTable0x68(MxBool p_add) { - // TODO + LegoWorld::VTable0x68(p_add); + + if (p_add) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } } // STUB: LEGO1 0x10070af0 MxResult Infocenter::Tickle() { // TODO - return 0; + return LegoWorld::Tickle(); +} + +// FUNCTION: LEGO1 0x10070c20 +void Infocenter::PlayCutscene(Cutscene p_entityId, MxBool p_scale) +{ + m_currentCutscene = p_entityId; + + VideoManager()->EnableFullScreenMovie(TRUE, p_scale); + InputManager()->SetUnknown336(TRUE); + InputManager()->SetUnknown335(TRUE); + SetAppCursor(0xb); // Hide cursor + VideoManager()->GetDisplaySurface()->ClearScreen(); + + if (m_currentCutscene != e_noIntro) { + // check if the cutscene is not an ending + if (m_currentCutscene >= e_badEndMovie && m_currentCutscene <= e_goodEndMovie) { + FUN_10070e90(); + } + InvokeAction(Extra::ActionType::e_opendisk, *g_introScript, m_currentCutscene, NULL); + } +} + +// FUNCTION: LEGO1 0x10070cb0 +void Infocenter::StopCutscene() +{ + if (m_currentCutscene != e_noIntro) { + InvokeAction(Extra::ActionType::e_close, *g_introScript, m_currentCutscene, NULL); + } + + VideoManager()->EnableFullScreenMovie(FALSE); + InputManager()->SetUnknown335(FALSE); + SetAppCursor(0); // Restore cursor to arrow + FUN_10015820(0, 7); } // FUNCTION: LEGO1 0x10070d00 @@ -50,8 +478,79 @@ MxBool Infocenter::VTable0x5c() return TRUE; } +// STUB: LEGO1 0x10070dc0 +void Infocenter::FUN_10070dc0(MxBool) +{ +} + +// STUB: LEGO1 0x10070e90 +void Infocenter::FUN_10070e90() +{ +} + // STUB: LEGO1 0x10070f60 MxBool Infocenter::VTable0x64() { return FALSE; } + +// STUB: LEGO1 0x10071030 +void Infocenter::StartCredits() +{ + // TODO +} + +// FUNCTION: LEGO1 0x10071250 +void Infocenter::StopCredits() +{ + MxDSAction action; + action.SetObjectId(499); + action.SetAtomId(*g_creditsScript); + action.SetUnknown24(-2); + DeleteObject(action); +} + +// FUNCTION: LEGO1 0x10071300 +void Infocenter::PlayDialogue(InfomainScript p_objectId) +{ + MxDSAction action; + action.SetObjectId(p_objectId); + action.SetAtomId(*g_infomainScript); + StopCurrentDialogue(); + + m_currentInfomainScript = p_objectId; + BackgroundAudioManager()->LowerVolume(); + Start(&action); +} + +// FUNCTION: LEGO1 0x100713d0 +void Infocenter::StopCurrentDialogue() +{ + if (m_currentInfomainScript != c_noInfomain) { + MxDSAction action; + action.SetObjectId(m_currentInfomainScript); + action.SetAtomId(*g_infomainScript); + action.SetUnknown24(-2); + DeleteObject(action); + m_currentInfomainScript = c_noInfomain; + } +} + +// FUNCTION: LEGO1 0x100714a0 +void Infocenter::PlayBookAnimation() +{ + MxDSAction action; + action.SetObjectId(c_bookWig); + action.SetAtomId(*g_sndAnimScript); + Start(&action); +} + +// FUNCTION: LEGO1 0x10071550 +void Infocenter::StopBookAnimation() +{ + MxDSAction action; + action.SetObjectId(c_bookWig); + action.SetAtomId(*g_sndAnimScript); + action.SetUnknown24(-2); + DeleteObject(action); +} diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp index 47a31fbb..96e47c55 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp @@ -6,6 +6,7 @@ DECOMP_SIZE_ASSERT(InfocenterState, 0x94); InfocenterState::InfocenterState() { // TODO + memset(m_buffer, 0, sizeof(m_buffer)); } // STUB: LEGO1 0x10071920 diff --git a/LEGO1/lego/legoomni/src/infocenter/score.cpp b/LEGO1/lego/legoomni/src/infocenter/score.cpp index dcc39f02..ce593ac1 100644 --- a/LEGO1/lego/legoomni/src/infocenter/score.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/score.cpp @@ -39,9 +39,9 @@ Score::~Score() } // FUNCTION: LEGO1 0x100012a0 -MxResult Score::Create(MxDSObject& p_dsObject) +MxResult Score::Create(MxDSAction& p_dsAction) { - MxResult result = SetAsCurrentWorld(p_dsObject); + MxResult result = LegoWorld::Create(p_dsAction); if (result == SUCCESS) { InputManager()->SetWorld(this); @@ -76,7 +76,7 @@ MxLong Score::Notify(MxParam& p_param) { MxLong ret = 0; LegoWorld::Notify(p_param); - if (m_unk0xf6) { + if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationStartAction: ret = 1; @@ -90,10 +90,10 @@ MxLong Score::Notify(MxParam& p_param) DeleteScript(); // Shutting down ret = 1; break; - case TYPE17: + case c_notificationType17: ret = FUN_100016d0((MxType17NotificationParam&) p_param); break; - case MXTRANSITIONMANAGER_TRANSITIONENDED: + case c_notificationTransitioned: DeleteObjects(g_infoscorScript, 7, 9); if (m_unk0xf8) GameState()->HandleAction(m_unk0xf8); @@ -116,7 +116,7 @@ MxLong Score::FUN_10001510(MxEndActionNotificationParam& p_param) switch (action->GetObjectId()) { case 10: m_unk0xf8 = 0x38; - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 0x32, 0, 0); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; case 0x1f5: PlayMusic(11); @@ -128,9 +128,9 @@ MxLong Score::FUN_10001510(MxEndActionNotificationParam& p_param) } // FUNCTION: LEGO1 0x10001580 -void Score::Stop() +void Score::VTable0x50() { - LegoWorld::Stop(); + LegoWorld::VTable0x50(); MxDSAction action; action.SetObjectId(0x1f4); @@ -160,12 +160,12 @@ MxLong Score::FUN_100016d0(MxType17NotificationParam& p_param) case 1: m_unk0xf8 = 2; DeleteScript(); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 0x32, 0, 0); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; case 2: m_unk0xf8 = 3; DeleteScript(); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 0x32, 0, 0); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; case 3: { LegoInputManager* im = InputManager(); diff --git a/LEGO1/lego/legoomni/src/isle/isle.cpp b/LEGO1/lego/legoomni/src/isle/isle.cpp index 2d1d856a..0da6189f 100644 --- a/LEGO1/lego/legoomni/src/isle/isle.cpp +++ b/LEGO1/lego/legoomni/src/isle/isle.cpp @@ -26,7 +26,7 @@ Isle::Isle() m_helicopter = NULL; m_bike = NULL; m_dunebuggy = NULL; - m_motorcycle = NULL; + m_motocycle = NULL; m_skateboard = NULL; m_racecar = NULL; m_jetski = NULL; @@ -54,11 +54,11 @@ Isle::~Isle() } // FUNCTION: LEGO1 0x10030b20 -MxResult Isle::Create(MxDSObject& p_dsObject) +MxResult Isle::Create(MxDSAction& p_dsAction) { GameState()->FUN_1003ceb0(); - MxResult result = LegoWorld::SetAsCurrentWorld(p_dsObject); + MxResult result = LegoWorld::Create(p_dsAction); if (result == SUCCESS) { ControlManager()->Register(this); InputManager()->SetWorld(this); @@ -99,7 +99,7 @@ MxLong Isle::Notify(MxParam& p_param) MxLong result = 0; LegoWorld::Notify(p_param); - if (m_unk0xf6) { + if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationEndAction: result = StopAction(p_param); @@ -115,10 +115,10 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case TYPE17: + case c_notificationType17: result = HandleType17Notification(p_param); break; - case TYPE18: + case c_notificationType18: switch (m_act1state->GetUnknown18()) { case 4: result = GetCurrentVehicle()->Notify(p_param); @@ -131,13 +131,13 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case TYPE19: + case c_notificationType19: result = HandleType19Notification(p_param); break; - case TYPE20: + case c_notificationType20: VTable0x68(TRUE); break; - case MXTRANSITIONMANAGER_TRANSITIONENDED: + case c_notificationTransitioned: result = HandleTransitionEnd(); break; } @@ -152,10 +152,22 @@ MxLong Isle::StopAction(MxParam& p_param) return 0; } -// STUB: LEGO1 0x10030fc0 -void Isle::Stop() +// FUNCTION: LEGO1 0x10030fc0 +void Isle::VTable0x50() { - // TODO + LegoWorld::VTable0x50(); + + if (m_act1state->GetUnknown21()) { + GameState()->HandleAction(2); + m_act1state->SetUnknown18(0); + m_act1state->SetUnknown21(0); + } + else if (GameState()->GetCurrentAct()) { + FUN_1003ef00(TRUE); + FUN_10032620(); + m_act1state->FUN_10034d00(); + FUN_10015820(0, 7); + } } // STUB: LGEO1 0x10031030 @@ -176,6 +188,12 @@ void Isle::VTable0x68(MxBool p_add) // TODO } +// STUB: LEGO1 0x10032620 +void Isle::FUN_10032620() +{ + // TODO +} + // STUB: LEGO1 0x100327a0 MxLong Isle::HandleTransitionEnd() { @@ -212,7 +230,7 @@ void Isle::VTable0x58(MxCore* p_object) m_dunebuggy = (DuneBuggy*) p_object; } else if (p_object->IsA("Motorcycle")) { - m_motorcycle = (Motorcycle*) p_object; + m_motocycle = (Motocycle*) p_object; } else if (p_object->IsA("SkateBoard")) { m_skateboard = (SkateBoard*) p_object; diff --git a/LEGO1/lego/legoomni/src/isle/islepathactor.cpp b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp index 528bbde8..76ec41bd 100644 --- a/LEGO1/lego/legoomni/src/isle/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp @@ -12,9 +12,16 @@ IslePathActor::IslePathActor() } // FUNCTION: LEGO1 0x1001a280 -MxResult IslePathActor::Create(MxDSObject& p_dsObject) +MxResult IslePathActor::Create(MxDSAction& p_dsAction) { - return MxEntity::Create(p_dsObject); + return MxEntity::Create(p_dsAction); +} + +// FUNCTION: LEGO1 0x1001a2a0 +void IslePathActor::Destroy(MxBool p_fromDestructor) +{ + if (!p_fromDestructor) + LegoPathActor::Destroy(FALSE); } // STUB: LEGO1 0x1001a350 diff --git a/LEGO1/lego/legoomni/src/isle/motorcycle.cpp b/LEGO1/lego/legoomni/src/isle/motocycle.cpp similarity index 60% rename from LEGO1/lego/legoomni/src/isle/motorcycle.cpp rename to LEGO1/lego/legoomni/src/isle/motocycle.cpp index 18fabd8a..2628d7ce 100644 --- a/LEGO1/lego/legoomni/src/isle/motorcycle.cpp +++ b/LEGO1/lego/legoomni/src/isle/motocycle.cpp @@ -1,9 +1,9 @@ -#include "motorcycle.h" +#include "motocycle.h" -DECOMP_SIZE_ASSERT(Motorcycle, 0x16c); +DECOMP_SIZE_ASSERT(Motocycle, 0x16c); // FUNCTION: LEGO1 0x100357b0 -Motorcycle::Motorcycle() +Motocycle::Motocycle() { this->m_unk0x13c = 40.0; this->m_unk0x150 = 1.75; diff --git a/LEGO1/lego/legoomni/src/main/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp index c4f64c91..a57f27d7 100644 --- a/LEGO1/lego/legoomni/src/main/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -23,6 +23,7 @@ #include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(LegoWorldList, 0x18); +DECOMP_SIZE_ASSERT(LegoWorldListCursor, 0x10); // GLOBAL: LEGO1 0x100f451c MxAtomId* g_copterScript = NULL; @@ -99,7 +100,7 @@ MxAtomId* g_testScript = NULL; // GLOBAL: LEGO1 0x100f457c MxAtomId* g_jukeboxwScript = NULL; -// GLOBAL: LEGO1 0x100f4580c +// GLOBAL: LEGO1 0x100f4580 MxAtomId* g_sndAnimScript = NULL; // GLOBAL: LEGO1 0x100f4584 @@ -109,6 +110,7 @@ MxAtomId* g_creditsScript = NULL; MxAtomId* g_nocdSourceName = NULL; // GLOBAL: LEGO1 0x100f6718 +// STRING: LEGO1 0x100f6710 const char* g_current = "current"; // GLOBAL: LEGO1 0x100f4c58 @@ -117,7 +119,7 @@ MxBool g_isWorldActive = TRUE; // FUNCTION: LEGO1 0x10015700 LegoOmni* Lego() { - return (LegoOmni*) MxOmni::GetInstance(); + return LegoOmni::GetInstance(); } // FUNCTION: LEGO1 0x10015710 @@ -180,6 +182,12 @@ LegoWorld* GetCurrentWorld() return LegoOmni::GetInstance()->GetCurrentOmniWorld(); } +// FUNCTION: LEGO1 0x100157b0 +LegoUnkSaveDataWriter* GetUnkSaveDataWriter() +{ + return LegoOmni::GetInstance()->GetUnkSaveDataWriter(); +} + // FUNCTION: LEGO1 0x100157e0 LegoPlantManager* PlantManager() { @@ -204,6 +212,12 @@ void FUN_10015820(MxU32, MxU32) // TODO } +// STUB: LEGO1 0x10015860 +void FUN_10015860(const char*, MxU8) +{ + // TODO +} + // FUNCTION: LEGO1 0x100158c0 LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid) { @@ -216,6 +230,12 @@ MxDSAction& GetCurrentAction() return LegoOmni::GetInstance()->GetCurrentAction(); } +// FUNCTION: LEGO1 0x100158f0 +void SetCurrentWorld(LegoWorld* p_world) +{ + LegoOmni::GetInstance()->SetWorld(p_world); +} + // FUNCTION: LEGO1 0x10015900 MxTransitionManager* TransitionManager() { @@ -241,6 +261,20 @@ void SetIsWorldActive(MxBool p_isWorldActive) g_isWorldActive = p_isWorldActive; } +// FUNCTION: LEGO1 0x100159e0 +void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last) +{ + MxDSAction action; + + action.SetAtomId(*p_id); + action.SetUnknown24(-2); + + for (MxS32 first = p_first, last = p_last; first <= last; first++) { + action.SetObjectId(first); + DeleteObject(action); + } +} + // STUB: LEGO1 0x1001a700 void FUN_1001a700() { @@ -265,34 +299,34 @@ LegoEntity* PickEntity(MxLong, MxLong) // FUNCTION: LEGO1 0x100528e0 void RegisterScripts() { - g_copterScript = new MxAtomId("\\lego\\scripts\\build\\copter", LookupMode_LowerCase2); - g_dunecarScript = new MxAtomId("\\lego\\scripts\\build\\dunecar", LookupMode_LowerCase2); - g_jetskiScript = new MxAtomId("\\lego\\scripts\\build\\jetski", LookupMode_LowerCase2); - g_racecarScript = new MxAtomId("\\lego\\scripts\\build\\racecar", LookupMode_LowerCase2); - g_carraceScript = new MxAtomId("\\lego\\scripts\\race\\carrace", LookupMode_LowerCase2); - g_carracerScript = new MxAtomId("\\lego\\scripts\\race\\carracer", LookupMode_LowerCase2); - g_jetraceScript = new MxAtomId("\\lego\\scripts\\race\\jetrace", LookupMode_LowerCase2); - g_jetracerScript = new MxAtomId("\\lego\\scripts\\race\\jetracer", LookupMode_LowerCase2); - g_isleScript = new MxAtomId("\\lego\\scripts\\isle\\isle", LookupMode_LowerCase2); - g_elevbottScript = new MxAtomId("\\lego\\scripts\\infocntr\\elevbott", LookupMode_LowerCase2); - g_infodoorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infodoor", LookupMode_LowerCase2); - g_infomainScript = new MxAtomId("\\lego\\scripts\\infocntr\\infomain", LookupMode_LowerCase2); - g_infoscorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infoscor", LookupMode_LowerCase2); - g_regbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\regbook", LookupMode_LowerCase2); - g_histbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\histbook", LookupMode_LowerCase2); - g_hospitalScript = new MxAtomId("\\lego\\scripts\\hospital\\hospital", LookupMode_LowerCase2); - g_policeScript = new MxAtomId("\\lego\\scripts\\police\\police", LookupMode_LowerCase2); - g_garageScript = new MxAtomId("\\lego\\scripts\\garage\\garage", LookupMode_LowerCase2); - g_act2mainScript = new MxAtomId("\\lego\\scripts\\act2\\act2main", LookupMode_LowerCase2); - g_act3Script = new MxAtomId("\\lego\\scripts\\act3\\act3", LookupMode_LowerCase2); - g_jukeboxScript = new MxAtomId("\\lego\\scripts\\isle\\jukebox", LookupMode_LowerCase2); - g_pz5Script = new MxAtomId("\\lego\\scripts\\isle\\pz5", LookupMode_LowerCase2); - g_introScript = new MxAtomId("\\lego\\scripts\\intro", LookupMode_LowerCase2); - g_testScript = new MxAtomId("\\lego\\scripts\\test\\test", LookupMode_LowerCase2); - g_jukeboxwScript = new MxAtomId("\\lego\\scripts\\isle\\jukeboxw", LookupMode_LowerCase2); - g_sndAnimScript = new MxAtomId("\\lego\\scripts\\sndanim", LookupMode_LowerCase2); - g_creditsScript = new MxAtomId("\\lego\\scripts\\credits", LookupMode_LowerCase2); - g_nocdSourceName = new MxAtomId("\\lego\\scripts\\nocd", LookupMode_LowerCase2); + g_copterScript = new MxAtomId("\\lego\\scripts\\build\\copter", e_lowerCase2); + g_dunecarScript = new MxAtomId("\\lego\\scripts\\build\\dunecar", e_lowerCase2); + g_jetskiScript = new MxAtomId("\\lego\\scripts\\build\\jetski", e_lowerCase2); + g_racecarScript = new MxAtomId("\\lego\\scripts\\build\\racecar", e_lowerCase2); + g_carraceScript = new MxAtomId("\\lego\\scripts\\race\\carrace", e_lowerCase2); + g_carracerScript = new MxAtomId("\\lego\\scripts\\race\\carracer", e_lowerCase2); + g_jetraceScript = new MxAtomId("\\lego\\scripts\\race\\jetrace", e_lowerCase2); + g_jetracerScript = new MxAtomId("\\lego\\scripts\\race\\jetracer", e_lowerCase2); + g_isleScript = new MxAtomId("\\lego\\scripts\\isle\\isle", e_lowerCase2); + g_elevbottScript = new MxAtomId("\\lego\\scripts\\infocntr\\elevbott", e_lowerCase2); + g_infodoorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infodoor", e_lowerCase2); + g_infomainScript = new MxAtomId("\\lego\\scripts\\infocntr\\infomain", e_lowerCase2); + g_infoscorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infoscor", e_lowerCase2); + g_regbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\regbook", e_lowerCase2); + g_histbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\histbook", e_lowerCase2); + g_hospitalScript = new MxAtomId("\\lego\\scripts\\hospital\\hospital", e_lowerCase2); + g_policeScript = new MxAtomId("\\lego\\scripts\\police\\police", e_lowerCase2); + g_garageScript = new MxAtomId("\\lego\\scripts\\garage\\garage", e_lowerCase2); + g_act2mainScript = new MxAtomId("\\lego\\scripts\\act2\\act2main", e_lowerCase2); + g_act3Script = new MxAtomId("\\lego\\scripts\\act3\\act3", e_lowerCase2); + g_jukeboxScript = new MxAtomId("\\lego\\scripts\\isle\\jukebox", e_lowerCase2); + g_pz5Script = new MxAtomId("\\lego\\scripts\\isle\\pz5", e_lowerCase2); + g_introScript = new MxAtomId("\\lego\\scripts\\intro", e_lowerCase2); + g_testScript = new MxAtomId("\\lego\\scripts\\test\\test", e_lowerCase2); + g_jukeboxwScript = new MxAtomId("\\lego\\scripts\\isle\\jukeboxw", e_lowerCase2); + g_sndAnimScript = new MxAtomId("\\lego\\scripts\\sndanim", e_lowerCase2); + g_creditsScript = new MxAtomId("\\lego\\scripts\\credits", e_lowerCase2); + g_nocdSourceName = new MxAtomId("\\lego\\scripts\\nocd", e_lowerCase2); } // FUNCTION: LEGO1 0x100530c0 @@ -577,10 +611,20 @@ void LegoOmni::RemoveWorld(const MxAtomId&, MxLong) // TODO } -// STUB: LEGO1 0x1005b0c0 +// FUNCTION: LEGO1 0x1005b0c0 LegoEntity* LegoOmni::FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid) { - // TODO + if (m_worldList) { + LegoWorld* world; + LegoWorldListCursor cursor(m_worldList); + + while (cursor.Next(world)) { + if ((p_entityid == -1 || world->GetEntityId() == p_entityid) && + (!p_atom.GetInternal() || world->GetAtom() == p_atom)) + return world; + } + } + return NULL; } @@ -595,7 +639,7 @@ MxEntity* LegoOmni::FindWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p { LegoWorld* foundEntity = NULL; if (strcmpi(p_id, g_current)) { - foundEntity = (LegoWorld*) FindByEntityIdOrAtomId(MxAtomId(p_id, LookupMode_LowerCase2), p_entityId); + foundEntity = (LegoWorld*) FindByEntityIdOrAtomId(MxAtomId(p_id, e_lowerCase2), p_entityId); } else { foundEntity = this->m_currentWorld; @@ -687,7 +731,7 @@ MxLong LegoOmni::Notify(MxParam& p_param) MxLong result = MxOmni::Notify(p_param); if (isCD) { // Exit the game if nocd.si ended - PostMessageA(m_windowHandle, WM_CLOSE, 0, 0); + CloseMainWindow(); } return result; @@ -706,9 +750,3 @@ void LegoOmni::StopTimer() MxOmni::StopTimer(); SetAppCursor(0); } - -// FUNCTION: LEGO1 0x100acf50 -MxResult Start(MxDSAction* p_dsAction) -{ - return MxOmni::GetInstance()->Start(p_dsAction); -} diff --git a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp index b8ab8faf..48d592a3 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp @@ -17,13 +17,19 @@ void LegoPathPresenter::Init() { } +// FUNCTION: LEGO1 0x10044ac0 +LegoPathPresenter::~LegoPathPresenter() +{ + Destroy(TRUE); +} + // FUNCTION: LEGO1 0x10044b40 MxResult LegoPathPresenter::AddToManager() { MxResult status = FAILURE; if (VideoManager()) { - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); status = SUCCESS; } @@ -34,7 +40,7 @@ MxResult LegoPathPresenter::AddToManager() void LegoPathPresenter::Destroy(MxBool p_fromDestructor) { if (VideoManager()) - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); { MxAutoLocker lock(&this->m_criticalSection); @@ -51,6 +57,27 @@ void LegoPathPresenter::Destroy() Destroy(FALSE); } +// STUB: LEGO1 0x10044c20 +void LegoPathPresenter::ReadyTickle() +{ + // TODO + ProgressTickleState(e_starting); // Allow initialization process to continue +} + +// FUNCTION: LEGO1 0x10044d00 +void LegoPathPresenter::StreamingTickle() +{ + MxStreamChunk* chunk = m_subscriber->NextChunk(); + + if (chunk) { + if (chunk->GetFlags() & MxStreamChunk::c_end) { + ProgressTickleState(e_repeating); + } + + m_subscriber->DestroyChunk(chunk); + } +} + // FUNCTION: LEGO1 0x10044d40 void LegoPathPresenter::RepeatingTickle() { diff --git a/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp index 444eeccf..476c6291 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp @@ -21,6 +21,11 @@ LegoAnimationManager::~LegoAnimationManager() // TODO } +// STUB: LEGO1 0x1005ef10 +void LegoAnimationManager::FUN_1005ef10() +{ +} + // STUB: LEGO1 0x1005f130 void LegoAnimationManager::Init() { @@ -33,6 +38,12 @@ void LegoAnimationManager::FUN_1005f6d0(MxBool) // TODO } +// STUB: LEGO1 0x1005f720 +void LegoAnimationManager::FUN_1005f720(undefined4) +{ + // TODO +} + // STUB: LEGO1 0x100619f0 MxLong LegoAnimationManager::Notify(MxParam& p_param) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 2bdd7475..31fe68b3 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1,13 +1,243 @@ #include "legoanimpresenter.h" -// STUB: LEGO1 0x10068420 +#include "legoomni.h" +#include "legostream.h" +#include "legoworld.h" +#include "mxcompositepresenter.h" +#include "mxdsanim.h" +#include "mxstreamchunk.h" + +DECOMP_SIZE_ASSERT(LegoAnimPresenter, 0xc0) +DECOMP_SIZE_ASSERT(LegoAnimClassBase, 0x08) +DECOMP_SIZE_ASSERT(LegoAnimClass, 0x18) + +// FUNCTION: LEGO1 0x10068420 LegoAnimPresenter::LegoAnimPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x10068670 +LegoAnimPresenter::~LegoAnimPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x100686f0 +void LegoAnimPresenter::Init() +{ + m_unk0x64 = NULL; + m_unk0x68 = 0; + m_unk0x6c = 0; + m_unk0x74 = 0; + m_unk0x70 = 0; + m_unk0x78 = 0; + m_unk0x7c = 0; + m_unk0xa8.Clear(); + m_unk0xa4 = 0; + m_currentWorld = NULL; + m_unk0x95 = 0; + m_unk0x88 = -1; + m_unk0x98 = 0; + m_animAtom.Clear(); + m_unk0x9c = 0; + m_unk0x8c = 0; + m_unk0x90 = 0; + m_unk0x94 = 0; + m_unk0x96 = 1; + m_unk0xa0 = 0; +} + +// STUB: LEGO1 0x10068770 +void LegoAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + // TODO + MxVideoPresenter::Destroy(p_fromDestructor); +} + +// FUNCTION: LEGO1 0x10068fb0 +MxResult LegoAnimPresenter::VTable0x88(MxStreamChunk* p_chunk) +{ + MxResult result = FAILURE; + LegoMemoryStream stream((char*) p_chunk->GetData()); + + MxS32 magicSig; + MxS32 val2 = 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 (result != SUCCESS) { + delete m_unk0x64; + Init(); + } + + return result; +} + +// STUB: LEGO1 0x1006ad30 +void LegoAnimPresenter::PutFrame() { // TODO } -// STUB: LEGO1 0x100686f0 -void LegoAnimPresenter::Init() +// FUNCTION: LEGO1 0x1006b550 +void LegoAnimPresenter::ReadyTickle() +{ + m_currentWorld = GetCurrentWorld(); + + if (m_currentWorld) { + MxStreamChunk* chunk = m_subscriber->CurrentChunk(); + + if (chunk && chunk->GetTime() + m_action->GetStartTime() <= m_action->GetElapsedTime()) { + chunk = m_subscriber->NextChunk(); + MxResult result = VTable0x88(chunk); + m_subscriber->DestroyChunk(chunk); + + if (result == SUCCESS) { + ProgressTickleState(e_starting); + ParseExtra(); + } + else { + EndAction(); + } + } + } +} + +// STUB: LEGO1 0x1006b5e0 +void LegoAnimPresenter::StartingTickle() +{ + // TODO + ProgressTickleState(e_streaming); + EndAction(); // Allow game to start +} + +// FUNCTION: LEGO1 0x1006b840 +void LegoAnimPresenter::StreamingTickle() +{ + if (m_subscriber->CurrentChunk()) { + MxStreamChunk* chunk = m_subscriber->NextChunk(); + m_subscriber->DestroyChunk(chunk); + } + + if (m_unk0x95 == 0) { + if (m_unk0x64->m_unk0x8 + m_action->GetStartTime() < m_action->GetElapsedTime()) { + m_unk0x95 = 1; + } + } + else { + ProgressTickleState(e_done); + if (m_compositePresenter) { + if (m_compositePresenter->IsA("LegoAnimMMPresenter")) { + m_compositePresenter->VTable0x60(this); + } + } + } +} + +// FUNCTION: LEGO1 0x1006b8e0 +void LegoAnimPresenter::Destroy() +{ + Destroy(FALSE); +} + +// STUB: LEGO1 0x1006bac0 +void LegoAnimPresenter::ParseExtra() +{ + // TODO +} + +// FUNCTION: LEGO1 0x1006c620 +MxResult LegoAnimPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + MxResult result = MxVideoPresenter::StartAction(p_controller, p_action); + m_displayZ = 0; + return result; +} + +// STUB: LEGO1 0x1006c640 +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 f13165cc..00718629 100644 --- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp @@ -1,12 +1,43 @@ #include "legohideanimpresenter.h" +DECOMP_SIZE_ASSERT(LegoHideAnimPresenter, 0xc4) + // FUNCTION: LEGO1 0x1006d7e0 LegoHideAnimPresenter::LegoHideAnimPresenter() { Init(); } -// STUB: LEGO1 0x1006da50 +// FUNCTION: LEGO1 0x1006d9f0 +LegoHideAnimPresenter::~LegoHideAnimPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x1006da50 void LegoHideAnimPresenter::Init() { + m_unk0xc0 = NULL; +} + +// FUNCTION: LEGO1 0x1006da60 +void LegoHideAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + m_criticalSection.Enter(); + + 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) + LegoHideAnimPresenter::Destroy(); +} + +// FUNCTION: LEGO1 0x1006dac0 +void LegoHideAnimPresenter::Destroy() +{ + Destroy(FALSE); } diff --git a/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp index 6314a4fd..5be9d0d6 100644 --- a/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp @@ -1,6 +1,126 @@ #include "legometerpresenter.h" #include "decomp.h" +#include "mxbitmap.h" +#include "mxutil.h" -// Uncomment when member class variables are fleshed out. -// DECOMP_SIZE_ASSERT(LegoMeterPresenter, 0x94); // 0x1000a163 +DECOMP_SIZE_ASSERT(LegoMeterPresenter, 0x94) + +// GLOBAL: LEGO1 0x1010207c +// STRING: LEGO1 0x10101fb4 +const char* g_filterIndex = "FILTER_INDEX"; + +// GLOBAL: LEGO1 0x10102094 +// STRING: LEGO1 0x10101f70 +const char* g_type = "TYPE"; + +// GLOBAL: LEGO1 0x10102088 +// STRING: LEGO1 0x10101f94 +const char* g_leftToRight = "LEFT_TO_RIGHT"; + +// GLOBAL: LEGO1 0x101020ac +// STRING: LEGO1 0x10101f28 +const char* g_rightToLeft = "RIGHT_TO_LEFT"; + +// GLOBAL: LEGO1 0x1010205c +// STRING: LEGO1 0x10102000 +const char* g_bottomToTop = "BOTTOM_TO_TOP"; + +// GLOBAL: LEGO1 0x101020c0 +// STRING: LEGO1 0x10101f00 +const char* g_topToBottom = "TOP_TO_BOTTOM"; + +// GLOBAL: LEGO1 0x101020c8 +// STRING: LEGO1 0x10101ee4 +const char* g_variable = "VARIABLE"; + +// FUNCTION: LEGO1 0x10043430 +LegoMeterPresenter::LegoMeterPresenter() +{ + m_layout = 0; + m_unk0x6c = 0; + m_unk0x84 = 0; + m_type = 1; + m_flags &= ~c_bit2; +} + +// FUNCTION: LEGO1 0x10043780 +LegoMeterPresenter::~LegoMeterPresenter() +{ + delete m_unk0x6c; +} + +// FUNCTION: LEGO1 0x10043800 +void LegoMeterPresenter::ParseExtra() +{ + char buffer[256]; + + MxStillPresenter::ParseExtra(); + *((MxU16*) &buffer[0]) = m_action->GetExtraLength(); + char* extraData = m_action->GetExtraData(); + + if (*((MxU16*) &buffer[0])) { + MxU16 len = *((MxU16*) &buffer[0]); + memcpy(buffer, extraData, len); + buffer[len] = '\0'; + + char result[256]; + if (KeyValueStringParse(buffer, g_type, result)) { + if (!strcmpi(result, g_leftToRight)) { + m_layout = 0; + } + else if (!strcmpi(result, g_rightToLeft)) { + m_layout = 1; + } + else if (!strcmpi(result, g_bottomToTop)) { + m_layout = 2; + } + else if (!strcmpi(result, g_topToBottom)) { + m_layout = 3; + } + } + + if (KeyValueStringParse(buffer, g_filterIndex, result)) { + m_type = atoi(result); + } + + if (KeyValueStringParse(buffer, g_variable, result)) { + m_variable = result; + } + else { + EndAction(); + } + } + else { + EndAction(); + } +} + +// FUNCTION: LEGO1 0x10043990 +void LegoMeterPresenter::StreamingTickle() +{ + MxStillPresenter::StreamingTickle(); + m_unk0x6c = new MxU8[m_bitmap->GetBmiStride() * m_bitmap->GetBmiHeightAbs()]; + if (m_unk0x6c == NULL) { + EndAction(); + } + + memcpy(m_unk0x6c, m_bitmap->GetBitmapData(), m_bitmap->GetBmiStride() * m_bitmap->GetBmiHeightAbs()); + + m_unk0x88 = 0; + m_unk0x8a = 0; + m_unk0x8c = m_bitmap->GetBmiWidth() - 1; + m_unk0x8e = m_bitmap->GetBmiHeightAbs() - 1; +} + +// FUNCTION: LEGO1 0x10043a30 +void LegoMeterPresenter::RepeatingTickle() +{ + FUN_10043a50(); + MxStillPresenter::RepeatingTickle(); +} + +// STUB: LEGO1 0x10043a50 +void LegoMeterPresenter::FUN_10043a50() +{ +} diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index d9608461..4f835212 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -15,16 +15,23 @@ void LegoModelPresenter::configureLegoModelPresenter(MxS32 p_modelPresenterConfi g_modelPresenterConfig = p_modelPresenterConfig; } -// STUB: LEGO1 0x1007f670 +// FUNCTION: LEGO1 0x1007f670 void LegoModelPresenter::Destroy(MxBool p_fromDestructor) { - // TODO + m_criticalSection.Enter(); + m_unk0x64 = 0; + m_addedToView = FALSE; + m_criticalSection.Leave(); + if (!p_fromDestructor) { + MxVideoPresenter::Destroy(FALSE); + } } // STUB: LEGO1 0x10080050 void LegoModelPresenter::ReadyTickle() { // TODO + SetTickleState(e_starting); } // STUB: LEGO1 0x100801b0 diff --git a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp index 821942b9..ce352f7e 100644 --- a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp @@ -49,12 +49,13 @@ void LegoPalettePresenter::Destroy() MxResult LegoPalettePresenter::ParsePalette(MxStreamChunk* p_chunk) { MxU8 buffer[40]; - RGBQUAD palleteData[256]; + RGBQUAD palette[256]; MxResult result = FAILURE; + LegoMemoryStream stream((char*) p_chunk->GetData()); - if (stream.Read(buffer, 40) == SUCCESS) { - if (stream.Read(palleteData, sizeof(RGBQUAD) * 256) == SUCCESS) { - m_palette = new MxPalette(palleteData); + if (stream.Read(buffer, sizeof(buffer)) == SUCCESS) { + if (stream.Read(palette, sizeof(palette)) == SUCCESS) { + m_palette = new MxPalette(palette); if (m_palette) { result = SUCCESS; } @@ -76,8 +77,8 @@ void LegoPalettePresenter::ReadyTickle() if (chunk) { if (chunk->GetTime() <= m_action->GetElapsedTime()) { ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); + chunk = m_subscriber->NextChunk(); MxResult result = ParsePalette(chunk); m_subscriber->DestroyChunk(chunk); diff --git a/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp index 6d0cbe8c..e376966f 100644 --- a/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp @@ -7,13 +7,13 @@ // FUNCTION: LEGO1 0x1004eb40 LegoTexturePresenter::~LegoTexturePresenter() { - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); } // FUNCTION: LEGO1 0x1004ebb0 MxResult LegoTexturePresenter::AddToManager() { - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); return SUCCESS; } @@ -28,7 +28,7 @@ MxResult LegoTexturePresenter::PutData() void LegoTexturePresenter::DoneTickle() { if (this->m_compositePresenter && !this->m_compositePresenter->VTable0x64(2)) { - SetTickleState(TickleState_Idle); + SetTickleState(e_idle); return; } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 43cdde24..eba51d79 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -10,6 +10,7 @@ DECOMP_SIZE_ASSERT(LegoVideoManager, 0x590); DECOMP_SIZE_ASSERT(MxStopWatch, 0x18); +DECOMP_SIZE_ASSERT(MxFrequencyMeter, 0x20); // FUNCTION: LEGO1 0x1007aa20 LegoVideoManager::LegoVideoManager() @@ -17,7 +18,7 @@ LegoVideoManager::LegoVideoManager() m_renderer = NULL; m_3dManager = NULL; m_viewROI = NULL; - m_direct3d = 0; + m_direct3d = NULL; m_unk0xe6 = FALSE; memset(m_unk0x78, 0, sizeof(m_unk0x78)); m_unk0x78[0] = 0x6c; @@ -29,14 +30,14 @@ LegoVideoManager::LegoVideoManager() m_cursorX = m_cursorY; m_cursorYCopy = m_cursorY; m_cursorXCopy = m_cursorY; - m_unk0x514 = 0; - m_unk0x500 = FALSE; + m_unk0x514 = NULL; + m_fullScreenMovie = FALSE; m_drawFPS = FALSE; m_unk0x528 = 0; m_arialFont = NULL; m_unk0xe5 = FALSE; m_unk0x554 = FALSE; - m_initialized = FALSE; + m_paused = FALSE; } // FUNCTION: LEGO1 0x1007ab40 @@ -64,10 +65,10 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM MxResult result = FAILURE; MxDeviceEnumerate100d9cc8 deviceEnumerate; - Vector3Data posVec(0.0, 1.25, -50.0); - Vector3Data dirVec(0.0, 0.0, 1.0); - Vector3Data upVec(0.0, 1.0, 0.0); - Matrix4Data outMatrix; + Mx3DPointFloat posVec(0.0, 1.25, -50.0); + Mx3DPointFloat dirVec(0.0, 0.0, 1.0); + Mx3DPointFloat upVec(0.0, 1.0, 0.0); + MxMatrix outMatrix; HWND hwnd = MxOmni::GetInstance()->GetWindowHandle(); MxS32 bits = p_videoParam.Flags().Get16Bit() ? 16 : 8; MxS32 deviceNum = -1; @@ -179,7 +180,7 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM m_3dManager->SetPointOfView(*m_viewROI); m_unk0x100d9d00 = new LegoUnknown100d9d00; - m_unk0xe4 = FALSE; + m_render3d = FALSE; m_stopWatch = new MxStopWatch; m_stopWatch->Start(); @@ -229,7 +230,7 @@ void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) MxResult LegoVideoManager::Tickle() { if (m_unk0x554 && !m_videoParam.Flags().GetFlipSurfaces() && - TransitionManager()->GetTransitionType() == MxTransitionManager::NOT_TRANSITIONING) + TransitionManager()->GetTransitionType() == MxTransitionManager::e_notTransitioning) Sleep(30); m_stopWatch->Stop(); @@ -247,13 +248,13 @@ MxResult LegoVideoManager::Tickle() while (cursor.Next(presenter)) presenter->Tickle(); - if (m_unk0xe4 && !m_initialized) + 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); - if (!m_initialized && (m_unk0xe4 || m_unk0xe5)) { + if (!m_paused && (m_render3d || m_unk0xe5)) { cursor.Reset(); while (cursor.Next(presenter) && presenter->GetDisplayZ() >= 0) @@ -275,7 +276,7 @@ MxResult LegoVideoManager::Tickle() if (m_drawFPS) DrawFPS(); } - else if (m_unk0x500) { + else if (m_fullScreenMovie) { MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); @@ -283,8 +284,8 @@ MxResult LegoVideoManager::Tickle() presenter->PutData(); } - if (!m_initialized) { - if (m_unk0xe4 && m_videoParam.Flags().GetFlipSurfaces()) { + if (!m_paused) { + if (m_render3d && m_videoParam.Flags().GetFlipSurfaces()) { m_3dManager->GetLego3DView() ->GetView() ->ForceUpdate(0, 0, m_videoParam.GetRect().GetWidth(), m_videoParam.GetRect().GetHeight()); @@ -364,11 +365,11 @@ void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); - m_unk0xe4 = FALSE; - m_unk0x500 = TRUE; + m_render3d = FALSE; + m_fullScreenMovie = TRUE; } else { - m_displaySurface->FUN_100ba640(); + m_displaySurface->ClearScreen(); m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); // restore previous pallete @@ -388,8 +389,8 @@ void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) UpdateRegion(); OverrideSkyColor(TRUE); - m_unk0xe4 = TRUE; - m_unk0x500 = FALSE; + m_render3d = TRUE; + m_fullScreenMovie = FALSE; } } @@ -431,7 +432,7 @@ void LegoVideoManager::VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_h p_height = m_videoParam.GetRect().GetHeight(); } - if (!m_initialized) { + if (!m_paused) { m_3dManager->GetLego3DView()->GetView()->ForceUpdate(p_x, p_y, p_width, p_height); } } @@ -461,7 +462,7 @@ MxResult LegoVideoManager::ConfigureD3DRM() MxAssignedDevice* assignedDevice = m_direct3d->GetAssignedDevice(); - if (assignedDevice && assignedDevice->GetFlags() & MxAssignedDevice::Flag_HardwareMode) { + if (assignedDevice && assignedDevice->GetFlags() & MxAssignedDevice::c_hardwareMode) { if (assignedDevice->GetDesc().dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) d3drm->SetTextureQuality(D3DRMTEXTURE_LINEAR); diff --git a/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp index 565908a0..677837bf 100644 --- a/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp @@ -17,7 +17,7 @@ RECT g_fullScreenRect = {0, 0, 640, 480}; MxTransitionManager::MxTransitionManager() { m_animationTimer = 0; - m_transitionType = NOT_TRANSITIONING; + m_transitionType = e_notTransitioning; m_ddSurface = NULL; m_waitIndicator = NULL; m_copyBuffer = NULL; @@ -57,22 +57,22 @@ MxResult MxTransitionManager::Tickle() this->m_systemTime = timeGetTime(); switch (this->m_transitionType) { - case NO_ANIMATION: + case e_noAnimation: TransitionNone(); break; - case DISSOLVE: + case e_dissolve: TransitionDissolve(); break; - case PIXELATION: + case e_pixelation: TransitionPixelation(); break; - case SCREEN_WIPE: + case e_screenWipe: TransitionWipe(); break; - case WINDOWS: + case e_windows: TransitionWindows(); break; - case BROKEN: + case e_broken: TransitionBroken(); break; } @@ -87,7 +87,7 @@ MxResult MxTransitionManager::StartTransition( MxBool p_playMusicInAnim ) { - if (this->m_transitionType == NOT_TRANSITIONING) { + if (this->m_transitionType == e_notTransitioning) { if (!p_playMusicInAnim) { MxBackgroundAudioManager* backgroundAudioManager = BackgroundAudioManager(); backgroundAudioManager->Stop(); @@ -102,7 +102,7 @@ MxResult MxTransitionManager::StartTransition( MxDSAction* action = m_waitIndicator->GetAction(); action->SetLoopCount(10000); - action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit10); + action->SetFlags(action->GetFlags() | MxDSAction::c_bit10); } MxU32 time = timeGetTime(); @@ -114,11 +114,11 @@ MxResult MxTransitionManager::StartTransition( tickleManager->RegisterClient(this, p_speed); LegoInputManager* inputManager = InputManager(); - inputManager->m_unk0x88 = TRUE; - inputManager->m_unk0x336 = FALSE; + inputManager->SetUnknown88(TRUE); + inputManager->SetUnknown336(FALSE); LegoVideoManager* videoManager = VideoManager(); - videoManager->SetUnkE4(FALSE); + videoManager->SetRender3D(FALSE); SetAppCursor(1); return SUCCESS; @@ -129,8 +129,8 @@ MxResult MxTransitionManager::StartTransition( // FUNCTION: LEGO1 0x1004bc30 void MxTransitionManager::EndTransition(MxBool p_notifyWorld) { - if (m_transitionType != NOT_TRANSITIONING) { - m_transitionType = NOT_TRANSITIONING; + if (m_transitionType != e_notTransitioning) { + m_transitionType = e_notTransitioning; m_copyFlags.m_bit0 = FALSE; @@ -142,11 +142,11 @@ void MxTransitionManager::EndTransition(MxBool p_notifyWorld) if (world) { #ifdef COMPAT_MODE { - MxNotificationParam param(MXTRANSITIONMANAGER_TRANSITIONENDED, this); + MxNotificationParam param(c_notificationTransitioned, this); world->Notify(param); } #else - world->Notify(MxNotificationParam(MXTRANSITIONMANAGER_TRANSITIONENDED, this)); + world->Notify(MxNotificationParam(c_notificationTransitioned, this)); #endif } } @@ -157,7 +157,7 @@ void MxTransitionManager::EndTransition(MxBool p_notifyWorld) void MxTransitionManager::TransitionNone() { LegoVideoManager* videoManager = VideoManager(); - videoManager->GetDisplaySurface()->FUN_100ba640(); + videoManager->GetDisplaySurface()->ClearScreen(); EndTransition(TRUE); } @@ -475,7 +475,7 @@ void MxTransitionManager::SetWaitIndicator(MxVideoPresenter* p_waitIndicator) { // End current wait indicator if (m_waitIndicator != NULL) { - m_waitIndicator->GetAction()->SetFlags(m_waitIndicator->GetAction()->GetFlags() & ~MxDSAction::Flag_World); + m_waitIndicator->GetAction()->SetFlags(m_waitIndicator->GetAction()->GetFlags() & ~MxDSAction::c_world); m_waitIndicator->EndAction(); m_waitIndicator = NULL; } @@ -486,9 +486,9 @@ void MxTransitionManager::SetWaitIndicator(MxVideoPresenter* p_waitIndicator) m_waitIndicator = p_waitIndicator; LegoVideoManager* videoManager = VideoManager(); - videoManager->RemovePresenter(*m_waitIndicator); + videoManager->UnregisterPresenter(*m_waitIndicator); - if (m_waitIndicator->GetCurrentTickleState() < MxPresenter::TickleState_Streaming) { + if (m_waitIndicator->GetCurrentTickleState() < MxPresenter::e_streaming) { m_waitIndicator->Tickle(); } } @@ -542,7 +542,7 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) m_waitIndicator->Tickle(); // Check if wait indicator has started - if (m_waitIndicator->GetCurrentTickleState() >= MxPresenter::TickleState_Streaming) { + if (m_waitIndicator->GetCurrentTickleState() >= MxPresenter::e_streaming) { // Setup the copy rect MxU32 copyPitch = (p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8) * (m_copyRect.right - m_copyRect.left + 1); // This uses m_copyRect, seemingly erroneously @@ -576,7 +576,7 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) } // Setup display surface - if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::Flag_Bit5) != 0) { + if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::c_bit5) != 0) { MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface(); MxBool und = FALSE; displaySurface->VTable0x2c( diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.h b/LEGO1/lego/sources/3dmanager/lego3dmanager.h index 8445800b..ab2bdefc 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dmanager.h +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.h @@ -4,8 +4,12 @@ #include "assert.h" #include "lego3dview.h" -class Tgl::Renderer; -class Tgl::Group; +namespace Tgl +{ +class Renderer; +class Group; +} // namespace Tgl + class ViewROI; // ??? for now diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.cpp b/LEGO1/lego/sources/3dmanager/lego3dview.cpp index 04c9ea22..37b8215e 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.cpp +++ b/LEGO1/lego/sources/3dmanager/lego3dview.cpp @@ -10,11 +10,12 @@ DECOMP_SIZE_ASSERT(Lego3DView, 0xa8) ///////////////////////////////////////////////////////////////////////////// // Lego3DView -// STUB: LEGO1 0x100aae90 +// FUNCTION: LEGO1 0x100aae90 Lego3DView::Lego3DView() { m_pViewManager = 0; m_previousRenderTime = 0; + m_unk0x98 = 0; m_pPointOfView = 0; } @@ -24,27 +25,31 @@ Lego3DView::~Lego3DView() Destroy(); } -// STUB: LEGO1 0x100aaf90 +// FUNCTION: LEGO1 0x100aaf90 BOOL Lego3DView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) { double viewAngle = 45; - double frontClippingDistance = 1; - double backClippingDistance = 5000; + if (rCreateStruct.m_isWideViewAngle) + viewAngle = 90; + + float frontClippingDistance = 0.1; + float backClippingDistance = 500; if (!LegoView1::Create(rCreateStruct, pRenderer)) { return FALSE; } - // assert(GetView()); - // GetView()->SetFrustrum(frontClippingDistance, backClippingDistance, viewAngle); + assert(GetView()); + GetView()->SetFrustrum(frontClippingDistance, backClippingDistance, viewAngle); - // assert(GetScene()); - // assert(!m_pViewManager); + assert(GetScene()); + assert(!m_pViewManager); - // m_pViewManager = new ViewManager(GetScene(), 0); - // m_pViewManager->SetResolution(GetWidth(), GetHeight()); - // m_pViewManager->SetFrustrum(viewAngle, -frontClippingDistance, -backClippingDistance); - // m_previousRenderTime = 0; + m_pViewManager = new ViewManager(pRenderer, GetScene(), 0); + m_pViewManager->SetResolution(GetWidth(), GetHeight()); + m_pViewManager->SetFrustrum(viewAngle, frontClippingDistance, backClippingDistance); + m_previousRenderTime = 0; + m_unk0x98 = 0; // // NOTE: a derived class must inform view manager when it configures // // its (Tgl) view: calling Tgl::View::SetFrustrum() should be @@ -53,12 +58,12 @@ BOOL Lego3DView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Rend return TRUE; } -// STUB: LEGO1 0x100ab0b0 +// FUNCTION: LEGO1 0x100ab0b0 void Lego3DView::Destroy() { if (m_pPointOfView) { m_pPointOfView = 0; - // m_pViewManager->SetPOVSource(0); + m_pViewManager->SetPOVSource(0); } delete m_pViewManager; diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.h b/LEGO1/lego/sources/3dmanager/lego3dview.h index 986d652c..7e68bdcb 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.h +++ b/LEGO1/lego/sources/3dmanager/lego3dview.h @@ -3,9 +3,7 @@ #include "decomp.h" #include "legoview1.h" - -class ViewROI; -class ViewManager; +#include "viewmanager/viewmanager.h" ///////////////////////////////////////////////////////////////////////////// // Lego3DView @@ -35,11 +33,9 @@ class Lego3DView : public LegoView1 { private: ViewManager* m_pViewManager; // 0x88 - double m_previousRenderTime; // 0x8c - - ViewROI* m_pPointOfView; // 0x90 - - undefined m_unk0x94[0x0c]; // 0x94 + double m_previousRenderTime; // 0x90 + double m_unk0x98; // 0x98 + ViewROI* m_pPointOfView; // 0xa0 }; // SYNTHETIC: LEGO1 0x100aaf10 diff --git a/LEGO1/lego/sources/3dmanager/legoview1.cpp b/LEGO1/lego/sources/3dmanager/legoview1.cpp index 3705eb33..97114469 100644 --- a/LEGO1/lego/sources/3dmanager/legoview1.cpp +++ b/LEGO1/lego/sources/3dmanager/legoview1.cpp @@ -4,13 +4,24 @@ #include "legoview1.h" #include "decomp.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" #include "realtime/realtime.h" -#include // SETMAT4 +#include DECOMP_SIZE_ASSERT(LegoView, 0x78); DECOMP_SIZE_ASSERT(LegoView1, 0x88); +// GLOBAL: LEGO1 0x101013e4 +float g_sunLightRGB = 1.0; + +// GLOBAL: LEGO1 0x101013e8 +float g_directionalLightRGB = 1.0; + +// GLOBAL: LEGO1 0x101013ec +float g_ambientLightRGB = 0.3; + ///////////////////////////////////////////////////////////////////////////// // LegoView @@ -112,51 +123,39 @@ BOOL LegoView1::AddLightsToViewport() return TRUE; } -// STUB: LEGO1 0x100ab860 +// FUNCTION: LEGO1 0x100ab860 BOOL LegoView1::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) { - double position[3] = {0, 0, 0}; - double direction[3]; - double up[3] = {0, 1, 0}; - if (!LegoView::Create(rCreateStruct, pRenderer)) { return FALSE; } // lights - m_pSunLight = pRenderer->CreateLight(Tgl::Directional, .9, .9, .9); - m_pDirectionalLight = pRenderer->CreateLight(Tgl::Directional, .4, .4, .4); - m_pAmbientLight = pRenderer->CreateLight(Tgl::Ambient, .3, .3, .3); + m_pSunLight = pRenderer->CreateLight(Tgl::Point, g_sunLightRGB, g_sunLightRGB, g_sunLightRGB); + m_pDirectionalLight = + pRenderer->CreateLight(Tgl::Directional, g_directionalLightRGB, g_directionalLightRGB, g_directionalLightRGB); + m_pAmbientLight = pRenderer->CreateLight(Tgl::Ambient, g_ambientLightRGB, g_ambientLightRGB, g_ambientLightRGB); -#if 0 - direction[0] = 1, direction[1] = -1, direction[2] = 2; - m_pSunLight->SetOrientation(direction, up); - direction[0] = -1, direction[1] = -2, direction[2] = -1; - m_pDirectionalLight->SetOrientation(direction, up); -#else - { - // Change everything to float and proper Matrix types - /* - Tgl::FloatMatrix4 transformation; - Matrix4Data transform; + Mx3DPointFloat direction(0.0, -1.0, 0.0); + Mx3DPointFloat position(0.0, 0.0, 0.0); + Mx3DPointFloat up(1.0, 0.0, 0.0); - direction[0] = 1, direction[1] = -1, direction[2] = 2; - CalcLocalTransform(position, direction, up, transform); - SETMAT4(transformation, transform); - m_pSunLight->SetTransformation(transformation); + Tgl::FloatMatrix4 matrix; + Matrix4 in(matrix); + MxMatrix transform; - direction[0] = -1, direction[1] = -2, direction[2] = -1; - CalcLocalTransform(position, direction, up, transform); - SETMAT4(transformation, transform); - m_pDirectionalLight->SetTransformation(transformation); - */ - } -#endif + CalcLocalTransform(position, direction, up, transform); + SETMAT4(in, transform); + m_pDirectionalLight->SetTransformation(matrix); + + direction[0] = 0, direction[1] = 150, direction[2] = -150; + CalcLocalTransform(position, direction, up, transform); + SETMAT4(in, transform); + m_pSunLight->SetTransformation(matrix); assert(GetView()); - AddLightsToViewport(); - return TRUE; + return AddLightsToViewport(); } // FUNCTION: LEGO1 0x100abad0 diff --git a/LEGO1/lego/sources/3dmanager/legoview1.h b/LEGO1/lego/sources/3dmanager/legoview1.h index 20ccadfa..4060e54f 100644 --- a/LEGO1/lego/sources/3dmanager/legoview1.h +++ b/LEGO1/lego/sources/3dmanager/legoview1.h @@ -2,14 +2,18 @@ #define _LegoView1_h #include "compat.h" +#include "decomp.h" #include "tglsurface.h" -class Tgl::Camera; +namespace Tgl +{ +class Camera; +} ///////////////////////////////////////////////////////////////////////////// // LegoView -// VTABLE: 0x100dc000 +// VTABLE: LEGO1 0x100dc000 // SIZE 0x78 class LegoView : public TglSurface { public: diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.cpp b/LEGO1/lego/sources/3dmanager/tglsurface.cpp index 2493e00c..394e03e5 100644 --- a/LEGO1/lego/sources/3dmanager/tglsurface.cpp +++ b/LEGO1/lego/sources/3dmanager/tglsurface.cpp @@ -195,7 +195,12 @@ double TglSurface::Render() #ifdef _DEBUG { +#if 0 + // FIXME: Tgl::Device::GetDrawnTriangleCount does not exist unsigned long triangleCount = m_pDevice->GetDrawnTriangleCount(); +#else + unsigned long triangleCount = 0; +#endif m_triangleRateMeter.IncreaseOperationCount(triangleCount - m_triangleCount - 1); m_triangleCount = triangleCount; diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.h b/LEGO1/lego/sources/3dmanager/tglsurface.h index 2ea4cf12..2b97db50 100644 --- a/LEGO1/lego/sources/3dmanager/tglsurface.h +++ b/LEGO1/lego/sources/3dmanager/tglsurface.h @@ -4,10 +4,13 @@ #include "mxdirectx/mxstopwatch.h" #include "tgl/tgl.h" -class Tgl::Renderer; -class Tgl::Device; -class Tgl::View; -class Tgl::Group; +namespace Tgl +{ +class Renderer; +class Device; +class View; +class Group; +} // namespace Tgl ///////////////////////////////////////////////////////////////////////////// // TglSurface diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index dab06a1a..9d530b16 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -38,18 +38,18 @@ MxS32 g_roiConfig = 100; ROIHandler g_someHandlerFunction = NULL; // FUNCTION: LEGO1 0x100a46a0 -void LegoROI::WrappedSetLocalTransform(Matrix4Impl& p_transform) +void LegoROI::WrappedSetLocalTransform(Matrix4& p_transform) { SetLocalTransform(p_transform); } // STUB: LEGO1 0x100a46b0 -void LegoROI::FUN_100a46b0(Matrix4Impl& p_transform) +void LegoROI::FUN_100a46b0(Matrix4& p_transform) { } // STUB: LEGO1 0x100a58f0 -void LegoROI::FUN_100a58f0(Matrix4Impl& p_transform) +void LegoROI::FUN_100a58f0(Matrix4& p_transform) { } diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index d84e8df4..d257398e 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -6,6 +6,8 @@ typedef MxBool (*ROIHandler)(char*, char*, MxU32); +class LegoEntity; + // Note: There is an extra class between LegoROI and ViewROI, // maybe called "AutoROI". VTABLE 0x100dbe38 @@ -15,6 +17,9 @@ class LegoROI : public ViewROI { public: LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, MxTime p_time); + // Note: Actually part of parent class (doesn't exist yet) + virtual void UpdateWorldBoundingVolumes() override; // vtable+0x18 + __declspec(dllexport) void SetDisplayBB(MxS32 p_displayBB); __declspec(dllexport) static void configureLegoROI(MxS32 p_roi); @@ -28,16 +33,17 @@ class LegoROI : public ViewROI { ); static MxBool ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green, MxFloat& p_blue, MxFloat& p_other); - void WrappedSetLocalTransform(Matrix4Impl& p_transform); - void FUN_100a46b0(Matrix4Impl& p_transform); - void FUN_100a58f0(Matrix4Impl& p_transform); + void WrappedSetLocalTransform(Matrix4& p_transform); + void FUN_100a46b0(Matrix4& p_transform); + void FUN_100a58f0(Matrix4& p_transform); - // Note: Actually part of parent class (doesn't exist yet) - virtual void UpdateWorldBoundingVolumes() override; // vtable+0x18 + inline LegoEntity* GetUnknown0x104() { return m_unk0x104; } + inline void SetUnknown0x104(LegoEntity* p_unk0x104) { m_unk0x104 = p_unk0x104; } private: - undefined m_pad[0x28]; // 0xe0 - MxTime m_time; // 0x108 + undefined m_pad[0x24]; // 0xe0 + LegoEntity* m_unk0x104; // 0x104 + MxTime m_time; // 0x108 }; #endif // LEGOROI_H diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 20ae06ef..30cb9dcd 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -1,49 +1,108 @@ #ifdef 0 +// For LEGO1 symbols only // aka `operator new` -// LIBRARY: ISLE 0x402f80 // LIBRARY: LEGO1 0x10086240 // ??2@YAPAXI@Z // aka `operator delete` -// LIBRARY: ISLE 0x402fa0 // LIBRARY: LEGO1 0x10086260 // ??3@YAXPAX@Z -// LIBRARY: ISLE 0x406dd0 // LIBRARY: LEGO1 0x1008a090 // _malloc -// LIBRARY: ISLE 0x406f00 // LIBRARY: LEGO1 0x1008a1c0 // _free -// LIBRARY: ISLE 0x408220 +// LIBRARY: LEGO1 0x1008b020 +// ___CxxFrameHandler + // LIBRARY: LEGO1 0x1008b400 // _atol -// LIBRARY: ISLE 0x4082d0 // LIBRARY: LEGO1 0x1008b4b0 // _atoi // LIBRARY: LEGO1 0x1008b4c0 // _strtok -// LIBRARY: ISLE 0x4085c0 // LIBRARY: LEGO1 0x1008b5a0 // _sprintf -// LIBRARY: ISLE 0x4081e0 +// LIBRARY: LEGO1 0x1008b608 +// __ftol + +// LIBRARY: LEGO1 0x1008b630 // _srand -// LIBRARY: ISLE 0x4081f0 // LIBRARY: LEGO1 0x1008b640 // _rand -// LIBRARY: ISLE 0x409110 -// __mtinit +// LIBRARY: LEGO1 0x1008b680 +// _strncmp -// LIBRARY: ISLE 0x409190 -// __getptd +// LIBRARY: LEGO1 0x1008b730 +// _fprintf + +// LIBRARY: LEGO1 0x1008b780 +// _fwrite + +// LIBRARY: LEGO1 0x1008b950 +// _fread + +// LIBRARY: LEGO1 0x1008bbd0 +// _fclose + +// LIBRARY: LEGO1 0x1008bdd0 +// _ftell + +// LIBRARY: LEGO1 0x1008bff0 +// _fopen + +// LIBRARY: LEGO1 0x1008c010 +// _strncpy + +// LIBRARY: LEGO1 0x1008c110 +// __strcmpi + +// LIBRARY: LEGO1 0x1008c1e0 +// __spawnl + +// LIBRARY: LEGO1 0x1008c200 +// _sscanf + +// LIBRARY: LEGO1 0x1008c410 +// _strlwr + +// LIBRARY: LEGO1 0x1008c5c0 +// _fseek + +// LIBRARY: LEGO1 0x1008ca60 +// _abort + +// LIBRARY: LEGO1 0x100977c0 +// _itoa + +// LIBRARY: LEGO1 0x10097b10 +// _strchr + +// LIBRARY: LEGO1 0x100d1ed0 +// _strnicmp + +// LIBRARY: LEGO1 0x100d1fd0 +// _strupr + +// LIBRARY: LEGO1 0x100d2130 +// _vsprintf + +// LIBRARY: LEGO1 0x100d21c2 +// __CIpow + +// LIBRARY: LEGO1 0x100d21f0 +// _strstr + +// LIBRARY: LEGO1 0x100d2270 +// __beginthreadex #endif diff --git a/LEGO1/omni/src/main/mxmain.cpp b/LEGO1/main.cpp similarity index 100% rename from LEGO1/omni/src/main/mxmain.cpp rename to LEGO1/main.cpp diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index c97ad0a9..b2166ca1 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -113,7 +113,7 @@ BOOL MxDirect3D::CreateIDirect3D() // FUNCTION: LEGO1 0x1009b310 BOOL MxDirect3D::D3DSetMode() { - if (m_assignedDevice->m_flags & MxAssignedDevice::Flag_HardwareMode) { + if (m_assignedDevice->m_flags & MxAssignedDevice::c_hardwareMode) { if (m_bOnlySoftRender) { Error("Failed to place vital surfaces in video memory for hardware driver", DDERR_GENERIC); return FALSE; @@ -265,7 +265,7 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri ); if (i == 0) - assignedDevice->m_flags |= MxAssignedDevice::Flag_PrimaryDevice; + assignedDevice->m_flags |= MxAssignedDevice::c_primaryDevice; for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { MxDevice& device = *it2; @@ -276,7 +276,7 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri D3DDEVICEDESC* desc; if (device.m_HWDesc.dcmColorModel) { - assignedDevice->m_flags |= MxAssignedDevice::Flag_HardwareMode; + assignedDevice->m_flags |= MxAssignedDevice::c_hardwareMode; desc = &device.m_HWDesc; } else diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index f0c87c69..09047f0a 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -13,8 +13,8 @@ class MxDirect3D; class MxAssignedDevice { public: enum { - Flag_HardwareMode = 0x01, - Flag_PrimaryDevice = 0x02 + c_hardwareMode = 0x01, + c_primaryDevice = 0x02 }; MxAssignedDevice(); @@ -158,11 +158,15 @@ struct MxDriver { // List::~List // Compiler-generated copy ctor -// Part of this function are two more synthetic sub-routines, -// LEGO1 0x1009c400 and LEGO1 0x1009c460 // SYNTHETIC: LEGO1 0x1009c290 // MxDriver::MxDriver +// SYNTHETIC: LEGO1 0x1009c400 +// list >::insert + +// SYNTHETIC: LEGO1 0x1009c460 +// list >::insert + // SYNTHETIC: LEGO1 0x1009d450 // MxDriver::`scalar deleting destructor' @@ -223,4 +227,7 @@ class MxDeviceEnumerate { // SIZE 0x14 class MxDeviceEnumerate100d9cc8 : public MxDeviceEnumerate {}; +// SYNTHETIC: LEGO1 0x1007b590 +// MxDeviceEnumerate100d9cc8::~MxDeviceEnumerate100d9cc8 + #endif // MXDIRECT3D_H diff --git a/LEGO1/mxdirectx/mxstopwatch.h b/LEGO1/mxdirectx/mxstopwatch.h index 7e7fcc38..0630d2f6 100644 --- a/LEGO1/mxdirectx/mxstopwatch.h +++ b/LEGO1/mxdirectx/mxstopwatch.h @@ -97,6 +97,9 @@ inline double MxStopWatch::ElapsedSeconds() const return m_elapsedSeconds; } +// SYNTHETIC: LEGO1 0x100a6fc0 +// MxStopWatch::~MxStopWatch + ////////////////////////////////////////////////////////////////////////////// // // MxFrequencyMeter @@ -182,4 +185,7 @@ inline double MxFrequencyMeter::ElapsedSeconds() const return m_stopWatch.ElapsedSeconds(); } +// SYNTHETIC: LEGO1 0x100abd10 +// MxFrequencyMeter::~MxFrequencyMeter + #endif /* _MxStopWatch_h */ diff --git a/LEGO1/mxgeometry/mxgeometry3d.cpp b/LEGO1/mxgeometry/mxgeometry3d.cpp new file mode 100644 index 00000000..03ce60eb --- /dev/null +++ b/LEGO1/mxgeometry/mxgeometry3d.cpp @@ -0,0 +1,6 @@ +#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 new file mode 100644 index 00000000..13781722 --- /dev/null +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -0,0 +1,48 @@ +#ifndef MXGEOMETRY3D_H +#define MXGEOMETRY3D_H + +#include "realtime/vector.h" + +// VTABLE: LEGO1 0x100d4488 +// SIZE 0x14 +class Mx3DPointFloat : public Vector3 { +public: + inline Mx3DPointFloat() : Vector3(m_elements) {} + inline Mx3DPointFloat(float p_x, float p_y, float p_z) : Vector3(m_elements) + { + m_elements[0] = p_x; + m_elements[1] = p_y; + m_elements[2] = p_z; + } + + // FUNCTION: LEGO1 0x10003c10 + virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88 + + inline void CopyFrom(const Mx3DPointFloat& p_other) + { + // ALPHA: 0x10010860, multiple indirections to this call + EqualsImpl(p_other.m_data); + + float* dest = m_elements; + const float* src = p_other.m_elements; + 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); } + +private: + float m_elements[3]; +}; + +// VTABLE: LEGO1 0x100d41e8 +// SIZE 0x18 +class Mx4DPointFloat : public Vector4 { +public: + inline Mx4DPointFloat() : Vector4(m_elements) {} + +private: + float m_elements[4]; +}; + +#endif // MXGEOMETRY3D_H diff --git a/LEGO1/mxgeometry/mxmatrix.cpp b/LEGO1/mxgeometry/mxmatrix.cpp new file mode 100644 index 00000000..fc768f38 --- /dev/null +++ b/LEGO1/mxgeometry/mxmatrix.cpp @@ -0,0 +1,5 @@ +#include "mxmatrix.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxMatrix, 0x48); diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h new file mode 100644 index 00000000..2db07671 --- /dev/null +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -0,0 +1,22 @@ +#ifndef MXMATRIX_H +#define MXMATRIX_H + +#include "realtime/matrix.h" + +// VTABLE: LEGO1 0x100d4300 +// SIZE 0x48 +class MxMatrix : public Matrix4 { +public: + inline MxMatrix() : Matrix4(m_elements) {} + inline MxMatrix(const MxMatrix& p_matrix) : Matrix4(m_elements) { Equals(p_matrix); } + + // 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? + // FUNCTION: LEGO1 0x10002860 + virtual void operator=(const MxMatrix& p_matrix) { Equals(p_matrix); } // vtable+0x48 + +private: + float m_elements[4][4]; +}; + +#endif // MXMATRIX_H diff --git a/LEGO1/omni/include/mxactionnotificationparam.h b/LEGO1/omni/include/mxactionnotificationparam.h index 24d9e5e1..5628cf7b 100644 --- a/LEGO1/omni/include/mxactionnotificationparam.h +++ b/LEGO1/omni/include/mxactionnotificationparam.h @@ -43,7 +43,11 @@ class MxActionNotificationParam : public MxNotificationParam { delete this->m_action; } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + // FUNCTION: LEGO1 0x100510c0 + virtual MxNotificationParam* Clone() override + { + return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc); + }; // vtable+0x4 inline MxDSAction* GetAction() { return m_action; } @@ -83,7 +87,16 @@ class MxEndActionNotificationParam : public MxActionNotificationParam { { } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + // FUNCTION: LEGO1 0x10051270 + virtual MxNotificationParam* Clone() override + { + return new MxEndActionNotificationParam( + c_notificationEndAction, + this->m_sender, + this->m_action, + this->m_realloc + ); + }; // vtable+0x4 }; // VTABLE: LEGO1 0x100dc208 @@ -91,7 +104,7 @@ class MxEndActionNotificationParam : public MxActionNotificationParam { class MxType4NotificationParam : public MxActionNotificationParam { public: inline MxType4NotificationParam(MxCore* p_sender, MxDSAction* p_action, MxPresenter* p_unk0x14) - : MxActionNotificationParam(TYPE4, p_sender, p_action, FALSE) + : MxActionNotificationParam(c_notificationType4, p_sender, p_action, FALSE) { m_unk0x14 = p_unk0x14; } @@ -102,13 +115,25 @@ class MxType4NotificationParam : public MxActionNotificationParam { MxPresenter* m_unk0x14; // 0x14 }; +// SYNTHETIC: LEGO1 0x100511e0 +// MxActionNotificationParam::`scalar deleting destructor' + // SYNTHETIC: LEGO1 0x100513a0 // MxEndActionNotificationParam::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x10051410 +// MxEndActionNotificationParam::~MxEndActionNotificationParam + // SYNTHETIC: LEGO1 0x100b0430 // MxStartActionNotificationParam::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x100b04a0 +// MxStartActionNotificationParam::~MxStartActionNotificationParam + // SYNTHETIC: LEGO1 0x100b05c0 // MxType4NotificationParam::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x100b0630 +// MxType4NotificationParam::~MxType4NotificationParam + #endif diff --git a/LEGO1/omni/include/mxatomid.h b/LEGO1/omni/include/mxatomid.h index 3abe6479..388ffce3 100644 --- a/LEGO1/omni/include/mxatomid.h +++ b/LEGO1/omni/include/mxatomid.h @@ -5,12 +5,13 @@ #include "mxtypes.h" enum LookupMode { - LookupMode_Exact = 0, - LookupMode_LowerCase = 1, - LookupMode_UpperCase = 2, - LookupMode_LowerCase2 = 3 + e_exact = 0, + e_lowerCase, + e_upperCase, + e_lowerCase2, }; +// SIZE 0x04 class MxAtomId { public: __declspec(dllexport) MxAtomId(const char*, LookupMode); @@ -30,7 +31,7 @@ class MxAtomId { MxAtomIdCounter* GetCounter(const char*, LookupMode); void Destroy(); - const char* m_internal; + const char* m_internal; // 0x00 }; #endif // MXATOMID_H diff --git a/LEGO1/omni/include/mxatomidcounter.h b/LEGO1/omni/include/mxatomidcounter.h index f2c4fb3f..79a98f34 100644 --- a/LEGO1/omni/include/mxatomidcounter.h +++ b/LEGO1/omni/include/mxatomidcounter.h @@ -43,4 +43,50 @@ struct MxAtomIdCounterCompare { class MxAtomIdCounterSet : public set {}; +// SYNTHETIC: LEGO1 0x100ad170 +// MxAtomIdCounter::~MxAtomIdCounter + +// clang-format off +// TEMPLATE: LEGO1 0x100ad480 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::iterator::_Dec +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100ad780 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::_Lbound +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100ad4d0 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::_Insert +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100af6d0 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::~_Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::iterator::_Inc +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100af7e0 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::erase +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100afc40 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::_Erase +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100afc80 +// set >::~set > +// clang-format on + +// TEMPLATE: LEGO1 0x100afe40 +// Set::~Set + #endif // MXATOMIDCOUNTER_H diff --git a/LEGO1/omni/include/mxaudiomanager.h b/LEGO1/omni/include/mxaudiomanager.h index c910a493..a7b58fd0 100644 --- a/LEGO1/omni/include/mxaudiomanager.h +++ b/LEGO1/omni/include/mxaudiomanager.h @@ -5,6 +5,7 @@ #include "mxmediamanager.h" // VTABLE: LEGO1 0x100dc6e0 +// SIZE 0x30 class MxAudioManager : public MxMediaManager { public: MxAudioManager(); @@ -12,8 +13,11 @@ class MxAudioManager : public MxMediaManager { virtual MxResult InitPresenters() override; // vtable+14 virtual void Destroy() override; // vtable+18 - virtual MxS32 GetVolume(); // vtable+28 - virtual void SetVolume(MxS32 p_volume); // vtable+2c + + // FUNCTION: LEGO1 0x10029910 + virtual MxS32 GetVolume() { return this->m_volume; }; // vtable+28 + + virtual void SetVolume(MxS32 p_volume); // vtable+2c private: void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxaudiopresenter.h b/LEGO1/omni/include/mxaudiopresenter.h index 73024aac..82e4b48a 100644 --- a/LEGO1/omni/include/mxaudiopresenter.h +++ b/LEGO1/omni/include/mxaudiopresenter.h @@ -23,11 +23,20 @@ class MxAudioPresenter : public MxMediaPresenter { return !strcmp(p_name, MxAudioPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual MxS32 GetVolume(); // vtable+0x5c - virtual void SetVolume(MxS32 p_volume); // vtable+0x60 + // FUNCTION: LEGO1 0x1000d260 + virtual MxS32 GetVolume() { return m_volume; }; // vtable+0x5c + + // FUNCTION: LEGO1 0x1000d270 + virtual void SetVolume(MxS32 p_volume) { m_volume = p_volume; }; // vtable+0x60 protected: MxS32 m_volume; }; +// SYNTHETIC: LEGO1 0x1000d370 +// MxAudioPresenter::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1000d3e0 +// MxAudioPresenter::~MxAudioPresenter + #endif // MXAUDIOPRESENTER_H diff --git a/LEGO1/omni/include/mxbitmap.h b/LEGO1/omni/include/mxbitmap.h index d9fda78d..d756b865 100644 --- a/LEGO1/omni/include/mxbitmap.h +++ b/LEGO1/omni/include/mxbitmap.h @@ -42,7 +42,10 @@ class MxBitmap : public MxCore { 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 int VTable0x28(int); + + // FUNCTION: LEGO1 0x1004e0d0 + virtual int VTable0x28(int) { return -1; }; + virtual void VTable0x2c(int, int, int, int, int, int, int); virtual void VTable0x30(int, int, int, int, int, int, int); __declspec(dllexport) virtual MxPalette* CreatePalette(); // vtable+34 diff --git a/LEGO1/omni/include/mxcompositepresenter.h b/LEGO1/omni/include/mxcompositepresenter.h index 6f14e615..33d00dc8 100644 --- a/LEGO1/omni/include/mxcompositepresenter.h +++ b/LEGO1/omni/include/mxcompositepresenter.h @@ -37,7 +37,14 @@ class MxCompositePresenter : public MxPresenter { virtual void VTable0x58(MxEndActionNotificationParam& p_param); // vtable+0x58 virtual void VTable0x5c(MxNotificationParam& p_param); // vtable+0x5c virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 - virtual MxBool VTable0x64(undefined4 p_undefined); // vtable+0x64 + + // FUNCTION: LEGO1 0x1000caf0 + virtual MxBool VTable0x64(undefined4 p_undefined) + { + if (m_compositePresenter) + return m_compositePresenter->VTable0x64(p_undefined); + return TRUE; + }; // vtable+0x64 protected: MxCompositePresenterList m_list; // 0x40 diff --git a/LEGO1/omni/include/mxcore.h b/LEGO1/omni/include/mxcore.h index db812bba..22c06d32 100644 --- a/LEGO1/omni/include/mxcore.h +++ b/LEGO1/omni/include/mxcore.h @@ -15,7 +15,9 @@ class MxCore { __declspec(dllexport) MxCore(); __declspec(dllexport) virtual ~MxCore(); // vtable+00 __declspec(dllexport) virtual MxLong Notify(MxParam& p_param); // vtable+04 - virtual MxResult Tickle(); // vtable+08 + + // FUNCTION: LEGO1 0x10001f70 + 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 new file mode 100644 index 00000000..15ae7c9b --- /dev/null +++ b/LEGO1/omni/include/mxcorelist.h @@ -0,0 +1,95 @@ +#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/mxdiskstreamcontroller.h b/LEGO1/omni/include/mxdiskstreamcontroller.h index 01ddc78a..52c0d8b4 100644 --- a/LEGO1/omni/include/mxdiskstreamcontroller.h +++ b/LEGO1/omni/include/mxdiskstreamcontroller.h @@ -42,10 +42,12 @@ class MxDiskStreamController : public MxStreamController { inline MxBool GetUnk0xc4() const { return m_unk0xc4; } - void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); - void FUN_100c8670(MxDSStreamingAction* p_streamingAction); - void InsertToList74(MxDSBuffer* p_buffer); + MxResult FUN_100c7890(MxDSStreamingAction* p_action); void FUN_100c7cb0(MxDSStreamingAction* p_action); + void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); + void FUN_100c8120(MxDSAction* p_action); + void InsertToList74(MxDSBuffer* p_buffer); + void FUN_100c8670(MxDSStreamingAction* p_streamingAction); private: MxStreamListMxDSAction m_list0x64; // 0x64 @@ -58,7 +60,6 @@ class MxDiskStreamController : public MxStreamController { MxStreamListMxDSAction m_list0xb8; // 0xb8 MxBool m_unk0xc4; // 0xc4 - MxResult FUN_100c7890(MxDSStreamingAction* p_action); void FUN_100c7970(); void FUN_100c7ce0(MxDSBuffer* p_buffer); MxResult FUN_100c7d10(); @@ -69,6 +70,9 @@ class MxDiskStreamController : public MxStreamController { void FUN_100c8720(); }; +// TEMPLATE: LEGO1 0x100c14d0 +// list >::erase + // TEMPLATE: LEGO1 0x100c7330 // list >::_Buynode @@ -84,4 +88,7 @@ class MxDiskStreamController : public MxStreamController { // TEMPLATE: LEGO1 0x100c74e0 // List::~List +// TEMPLATE: LEGO1 0x100c7ef0 +// list::insert + #endif // MXDISKSTREAMCONTROLLER_H diff --git a/LEGO1/omni/include/mxdiskstreamprovider.h b/LEGO1/omni/include/mxdiskstreamprovider.h index 2557eaf9..517fa463 100644 --- a/LEGO1/omni/include/mxdiskstreamprovider.h +++ b/LEGO1/omni/include/mxdiskstreamprovider.h @@ -64,6 +64,12 @@ class MxDiskStreamProvider : public MxStreamProvider { MxStreamListMxDSAction m_list; // 0x54 }; +// SYNTHETIC: LEGO1 0x100d10a0 +// MxDiskStreamProviderThread::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100d1110 +// MxDiskStreamProviderThread::~MxDiskStreamProviderThread + // SYNTHETIC: LEGO1 0x100d1220 // MxDiskStreamProvider::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h index 25fe95aa..c841fccc 100644 --- a/LEGO1/omni/include/mxdisplaysurface.h +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -85,7 +85,7 @@ class MxDisplaySurface : public MxCore { virtual void ReleaseDC(HDC p_hdc); // vtable+0x40 virtual LPDIRECTDRAWSURFACE VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4); // vtable+0x44 - void FUN_100ba640(); + void ClearScreen(); static LPDIRECTDRAWSURFACE FUN_100bc070(); inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h index c32dd4aa..35abcb81 100644 --- a/LEGO1/omni/include/mxdsaction.h +++ b/LEGO1/omni/include/mxdsaction.h @@ -2,8 +2,8 @@ #define MXDSACTION_H #include "mxdsobject.h" +#include "mxgeometry/mxgeometry3d.h" #include "mxtypes.h" -#include "realtime/vector.h" class MxOmni; @@ -12,16 +12,16 @@ class MxOmni; class MxDSAction : public MxDSObject { public: enum { - Flag_Looping = 0x01, - Flag_Bit3 = 0x04, - Flag_Bit4 = 0x08, - Flag_Bit5 = 0x10, - Flag_Enabled = 0x20, - Flag_Bit7 = 0x40, - Flag_World = 0x80, - Flag_Bit9 = 0x100, - Flag_Bit10 = 0x200, - Flag_Bit11 = 0x400, + c_looping = 0x01, + c_bit3 = 0x04, + c_bit4 = 0x08, + c_bit5 = 0x10, + c_enabled = 0x20, + c_bit7 = 0x40, + c_world = 0x80, + c_bit9 = 0x100, + c_bit10 = 0x200, + c_bit11 = 0x400, }; __declspec(dllexport) MxDSAction(); @@ -43,6 +43,7 @@ class MxDSAction : public MxDSObject { 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; @@ -63,40 +64,40 @@ class MxDSAction : public MxDSObject { inline MxLong GetStartTime() const { return m_startTime; } inline MxS32 GetLoopCount() { return m_loopCount; } inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } - inline Vector3Data& GetLocation() { return m_location; } - inline Vector3Data& GetDirection() { return m_direction; } - inline Vector3Data& GetUp() { return m_up; } + inline Mx3DPointFloat& GetLocation() { return m_location; } + inline Mx3DPointFloat& GetDirection() { return m_direction; } + inline Mx3DPointFloat& GetUp() { return m_up; } inline MxCore* GetUnknown84() { return m_unk0x84; } inline void SetUnknown84(MxCore* p_unk0x84) { m_unk0x84 = p_unk0x84; } inline MxCore* GetOrigin() { return m_origin; } inline void SetOrigin(MxCore* p_origin) { m_origin = p_origin; } - inline MxBool IsLooping() const { return m_flags & Flag_Looping; } - inline MxBool IsBit3() const { return m_flags & Flag_Bit3; } + inline MxBool IsLooping() const { return m_flags & c_looping; } + inline MxBool IsBit3() const { return m_flags & c_bit3; } inline void CopyFlags(MxU32 p_flags) { - if (p_flags & MxDSAction::Flag_Looping) - SetFlags(GetFlags() | MxDSAction::Flag_Looping); - else if (p_flags & MxDSAction::Flag_Bit3) - SetFlags(GetFlags() | MxDSAction::Flag_Bit3); + if (p_flags & MxDSAction::c_looping) + SetFlags(GetFlags() | MxDSAction::c_looping); + else if (p_flags & MxDSAction::c_bit3) + SetFlags(GetFlags() | MxDSAction::c_bit3); } protected: - MxU32 m_sizeOnDisk; // 0x2c - MxU32 m_flags; // 0x30 - MxLong m_startTime; // 0x34 - MxLong m_duration; // 0x38 - MxS32 m_loopCount; // 0x3c - Vector3Data m_location; // 0x40 - Vector3Data m_direction; // 0x54 - Vector3Data m_up; // 0x68 - char* m_extraData; // 0x7c - MxU16 m_extraLength; // 0x80 - MxCore* m_unk0x84; // 0x84 - undefined4 m_unk0x88; // 0x88 - MxCore* m_origin; // 0x8c - MxLong m_unk0x90; // 0x90 + MxU32 m_sizeOnDisk; // 0x2c + MxU32 m_flags; // 0x30 + MxLong m_startTime; // 0x34 + MxLong m_duration; // 0x38 + MxS32 m_loopCount; // 0x3c + Mx3DPointFloat m_location; // 0x40 + Mx3DPointFloat m_direction; // 0x54 + Mx3DPointFloat m_up; // 0x68 + char* m_extraData; // 0x7c + MxU16 m_extraLength; // 0x80 + MxCore* m_unk0x84; // 0x84 + undefined4 m_unk0x88; // 0x88 + MxCore* m_origin; // 0x8c + MxLong m_unk0x90; // 0x90 }; #endif // MXDSACTION_H diff --git a/LEGO1/omni/include/mxdsactionlist.h b/LEGO1/omni/include/mxdsactionlist.h index fbccd5cf..7ae9ab56 100644 --- a/LEGO1/omni/include/mxdsactionlist.h +++ b/LEGO1/omni/include/mxdsactionlist.h @@ -35,6 +35,7 @@ class MxDSActionList : public MxList { // class MxListCursor // VTABLE: LEGO1 0x100d7e50 +// SIZE 0x10 class MxDSActionListCursor : public MxListCursor { public: MxDSActionListCursor(MxDSActionList* p_list) : MxListCursor(p_list){}; @@ -43,6 +44,9 @@ class MxDSActionListCursor : public MxListCursor { // TEMPLATE: LEGO1 0x100c9cc0 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100c9cd0 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100c9d20 // MxCollection::Destroy diff --git a/LEGO1/omni/include/mxdsbuffer.h b/LEGO1/omni/include/mxdsbuffer.h index daa3263e..27770f5f 100644 --- a/LEGO1/omni/include/mxdsbuffer.h +++ b/LEGO1/omni/include/mxdsbuffer.h @@ -10,17 +10,17 @@ class MxDSStreamingAction; class MxStreamChunk; class MxDSChunk; -enum MxDSBufferType { - MxDSBufferType_Chunk = 0, - MxDSBufferType_Allocate = 1, - MxDSBufferType_Preallocated = 2, - MxDSBufferType_Unknown = 3, -}; - // VTABLE: LEGO1 0x100dcca0 // SIZE 0x34 class MxDSBuffer : public MxCore { public: + enum Type { + e_chunk = 0, + e_allocate = 1, + e_preallocated = 2, + e_unknown = 3, + }; + MxDSBuffer(); virtual ~MxDSBuffer() override; @@ -31,8 +31,8 @@ class MxDSBuffer : public MxCore { return "MxDSBuffer"; } - MxResult AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode); - MxResult SetBufferPointer(MxU32* p_buffer, MxU32 p_size); + MxResult AllocateBuffer(MxU32 p_bufferSize, Type p_mode); + MxResult SetBufferPointer(MxU8* p_buffer, MxU32 p_size); MxResult FUN_100c67b0( MxStreamController* p_controller, MxDSAction* p_action, @@ -52,20 +52,27 @@ class MxDSBuffer : public MxCore { MxDSStreamingAction** p_streamingAction, MxStreamChunk* p_header ); - static MxCore* ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags); MxU8* SkipToData(); MxU8 ReleaseRef(MxDSChunk*); void AddRef(MxDSChunk* p_chunk); MxResult CalcBytesRemaining(MxU8* p_data); void FUN_100c6f80(MxU32 p_writeOffset); + MxU8* FUN_100c6fa0(MxU8* p_data); + MxResult FUN_100c7090(MxDSBuffer* p_buf); + + static MxCore* ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags); + static MxResult Append(MxU8* p_buffer1, MxU8* p_buffer2); inline MxU8* GetBuffer() { return m_pBuffer; } + inline MxU8** GetBufferRef() { return &m_pBuffer; } + inline undefined4 GetUnknown14() { return m_unk0x14; } + inline MxU16 GetRefCount() { return m_refcount; } + inline Type GetMode() { return m_mode; } inline MxU32 GetWriteOffset() { return m_writeOffset; } inline MxU32 GetBytesRemaining() { return m_bytesRemaining; } - inline MxU16 GetRefCount() { return m_refcount; } - inline MxDSBufferType GetMode() { return m_mode; } inline void SetUnknown14(undefined4 p_unk0x14) { m_unk0x14 = p_unk0x14; } inline void SetUnknown1c(undefined4 p_unk0x1c) { m_unk0x1c = p_unk0x1c; } + inline void SetMode(Type p_mode) { m_mode = p_mode; } inline void SetUnk30(MxDSStreamingAction* p_unk0x30) { m_unk0x30 = p_unk0x30; } private: @@ -76,7 +83,7 @@ class MxDSBuffer : public MxCore { undefined4 m_unk0x18; // 0x18 undefined4 m_unk0x1c; // 0x1c MxU16 m_refcount; // 0x20 - MxDSBufferType m_mode; // 0x24 + Type m_mode; // 0x24 MxU32 m_writeOffset; // 0x28 MxU32 m_bytesRemaining; // 0x2c MxDSStreamingAction* m_unk0x30; // 0x30 diff --git a/LEGO1/omni/include/mxdschunk.h b/LEGO1/omni/include/mxdschunk.h index 83693bc0..cd0816a0 100644 --- a/LEGO1/omni/include/mxdschunk.h +++ b/LEGO1/omni/include/mxdschunk.h @@ -10,11 +10,11 @@ class MxDSChunk : public MxCore { public: enum { - Flag_Bit1 = 0x01, - Flag_End = 0x02, - Flag_Bit3 = 0x04, - Flag_Split = 0x10, - Flag_Bit16 = 0x8000 + c_bit1 = 0x01, + c_end = 0x02, + c_bit3 = 0x04, + c_split = 0x10, + c_bit16 = 0x8000 }; MxDSChunk(); @@ -33,7 +33,11 @@ class MxDSChunk : public MxCore { return !strcmp(p_name, MxDSChunk::ClassName()) || MxCore::IsA(p_name); } - static MxU32 ReturnE(); + static MxU32 GetHeaderSize(); + inline static MxU32* IntoType(MxU8* p_buffer) { return (MxU32*) p_buffer; } + inline static MxU32* IntoLength(MxU8* p_buffer) { return (MxU32*) (p_buffer + 4); } + inline static MxU32 Size(MxU32 p_dataSize) { return (p_dataSize & 1) + p_dataSize + 8; } + inline static MxU8* End(MxU8* p_buffer) { return p_buffer + Size(*IntoLength(p_buffer)); } inline void SetFlags(MxU16 p_flags) { m_flags = p_flags; } inline void SetObjectId(undefined4 p_objectid) { m_objectId = p_objectid; } diff --git a/LEGO1/omni/include/mxdsevent.h b/LEGO1/omni/include/mxdsevent.h index 01cf1fa4..5d002a88 100644 --- a/LEGO1/omni/include/mxdsevent.h +++ b/LEGO1/omni/include/mxdsevent.h @@ -3,6 +3,7 @@ #include "mxdsmediaaction.h" +// VTABLE: LEGO1 0x100dce18 class MxDSEvent : public MxDSMediaAction { public: MxDSEvent(); diff --git a/LEGO1/omni/include/mxdsmediaaction.h b/LEGO1/omni/include/mxdsmediaaction.h index 1f1b97d5..7422ec2d 100644 --- a/LEGO1/omni/include/mxdsmediaaction.h +++ b/LEGO1/omni/include/mxdsmediaaction.h @@ -28,8 +28,13 @@ class MxDSMediaAction : public MxDSAction { return !strcmp(p_name, MxDSMediaAction::ClassName()) || MxDSAction::IsA(p_name); } + // 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; void CopyMediaSrcPath(const char* p_mediaSrcPath); diff --git a/LEGO1/omni/include/mxdsobject.h b/LEGO1/omni/include/mxdsobject.h index a05d319b..b5bfd470 100644 --- a/LEGO1/omni/include/mxdsobject.h +++ b/LEGO1/omni/include/mxdsobject.h @@ -4,7 +4,6 @@ #include "decomp.h" #include "mxatomid.h" #include "mxcore.h" -#include "mxdstypes.h" class MxPresenter; @@ -12,6 +11,21 @@ class MxPresenter; // SIZE 0x2c class MxDSObject : public MxCore { public: + enum Type { + e_object = 0, + e_action, + e_mediaAction, + e_anim, + e_sound, + e_multiAction, + e_serialAction, + e_parallelAction, + e_event, + e_selectAction, + e_still, + e_objectAction, + }; + MxDSObject(); virtual ~MxDSObject() override; @@ -35,14 +49,14 @@ class MxDSObject : public MxCore { virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24); // vtable+1c; inline virtual void SetAtomId(MxAtomId p_atomId) { this->m_atomId = p_atomId; } // vtable+20; - inline MxDSType GetType() const { return (MxDSType) this->m_type; } + inline Type GetType() const { return (Type) this->m_type; } inline const char* GetSourceName() const { return this->m_sourceName; } inline MxU32 GetObjectId() { return this->m_objectId; } inline const MxAtomId& GetAtomId() { return this->m_atomId; } inline MxS16 GetUnknown24() { return this->m_unk0x24; } inline MxPresenter* GetUnknown28() { return this->m_unk0x28; } - inline void SetType(MxDSType p_type) { this->m_type = p_type; } + inline void SetType(Type p_type) { this->m_type = p_type; } inline void SetObjectId(MxU32 p_objectId) { this->m_objectId = p_objectId; } inline void SetUnknown24(MxS16 p_unk0x24) { this->m_unk0x24 = p_unk0x24; } inline void SetUnknown28(MxPresenter* p_unk0x28) { this->m_unk0x28 = p_unk0x28; } diff --git a/LEGO1/omni/include/mxdsparallelaction.h b/LEGO1/omni/include/mxdsparallelaction.h index 89fc1df0..0386de7f 100644 --- a/LEGO1/omni/include/mxdsparallelaction.h +++ b/LEGO1/omni/include/mxdsparallelaction.h @@ -26,8 +26,15 @@ class MxDSParallelAction : public MxDSMultiAction { return !strcmp(p_name, MxDSParallelAction::ClassName()) || MxDSMultiAction::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100cb020 + // MxDSParallelAction::`scalar deleting destructor' + virtual MxLong GetDuration() override; // vtable+24; - virtual MxDSAction* Clone() override; // vtable+2c; + + // FUNCTION: LEGO1 0x100caef0 + virtual void SetDuration(MxLong p_duration) override { m_duration = p_duration; } // vtable+0x28 + + virtual MxDSAction* Clone() override; // vtable+2c; }; #endif // MXDSPARALLELACTION_H diff --git a/LEGO1/omni/include/mxdssource.h b/LEGO1/omni/include/mxdssource.h index db009fb4..143b9c78 100644 --- a/LEGO1/omni/include/mxdssource.h +++ b/LEGO1/omni/include/mxdssource.h @@ -11,6 +11,9 @@ class MxDSSource : public MxCore { public: MxDSSource() : m_lengthInDWords(0), m_pBuffer(NULL), m_position(-1) {} + // FUNCTION: LEGO1 0x100bff60 + virtual ~MxDSSource() override { delete[] m_pBuffer; } + // FUNCTION: LEGO1 0x100c0010 inline virtual const char* ClassName() const override // vtable+0x0c { @@ -41,4 +44,7 @@ class MxDSSource : public MxCore { MxLong m_position; // 0x10 }; +// SYNTHETIC: LEGO1 0x100c00a0 +// MxDSSource::`scalar deleting destructor' + #endif // MXDSSOURCE_H diff --git a/LEGO1/omni/include/mxdsstreamingaction.h b/LEGO1/omni/include/mxdsstreamingaction.h index 00cd13aa..ab21bac2 100644 --- a/LEGO1/omni/include/mxdsstreamingaction.h +++ b/LEGO1/omni/include/mxdsstreamingaction.h @@ -41,6 +41,7 @@ class MxDSStreamingAction : public MxDSAction { inline void SetUnknown94(MxU32 p_unk0x94) { m_unk0x94 = p_unk0x94; } inline void SetUnknown9c(MxS32 p_unk0x9c) { m_unk0x9c = p_unk0x9c; } inline void SetUnknowna0(MxDSBuffer* p_unk0xa0) { m_unk0xa0 = p_unk0xa0; } + inline void SetUnknowna4(MxDSBuffer* p_unk0xa4) { m_unk0xa4 = p_unk0xa4; } inline void SetBufferOffset(MxU32 p_bufferOffset) { m_bufferOffset = p_bufferOffset; } private: diff --git a/LEGO1/omni/include/mxdstypes.h b/LEGO1/omni/include/mxdstypes.h deleted file mode 100644 index f43742b9..00000000 --- a/LEGO1/omni/include/mxdstypes.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MXDSTYPES_H -#define MXDSTYPES_H - -enum MxDSType { - MxDSType_Object = 0, - MxDSType_Action = 1, - MxDSType_MediaAction = 2, - MxDSType_Anim = 3, - MxDSType_Sound = 4, - MxDSType_MultiAction = 5, - MxDSType_SerialAction = 6, - MxDSType_ParallelAction = 7, - MxDSType_Event = 8, - MxDSType_SelectAction = 9, - MxDSType_Still = 10, - MxDSType_ObjectAction = 11, -}; - -#endif // MXDSTYPES_H diff --git a/LEGO1/omni/include/mxentity.h b/LEGO1/omni/include/mxentity.h index 64a003ee..cc77cea2 100644 --- a/LEGO1/omni/include/mxentity.h +++ b/LEGO1/omni/include/mxentity.h @@ -4,15 +4,18 @@ #include "decomp.h" #include "mxatomid.h" #include "mxcore.h" -#include "mxdsobject.h" +#include "mxdsaction.h" #include "mxtypes.h" // VTABLE: LEGO1 0x100d5390 // SIZE 0x10 class MxEntity : public MxCore { public: - MxEntity(); - virtual ~MxEntity() override; + // FUNCTION: LEGO1 0x1001d190 + MxEntity() { this->m_mxEntityId = -1; } + + // FUNCTION: LEGO1 0x1000c110 + virtual ~MxEntity() override{}; // FUNCTION: LEGO1 0x1000c180 inline virtual const char* ClassName() const override // vtable+0xc @@ -27,14 +30,24 @@ class MxEntity : public MxCore { return !strcmp(p_name, MxEntity::ClassName()) || MxCore::IsA(p_name); } - virtual MxResult Create(MxS32 p_id, const MxAtomId& p_atom); // vtable+0x14 - inline MxResult Create(MxDSObject& p_dsObject) + // FUNCTION: LEGO1 0x10001070 + virtual MxResult Create(MxS32 p_id, const MxAtomId& p_atom) { - m_mxEntityId = p_dsObject.GetObjectId(); - m_atom = p_dsObject.GetAtomId(); + this->m_mxEntityId = p_id; + this->m_atom = p_atom; + return SUCCESS; + }; // vtable+0x14 + + inline MxResult Create(MxDSAction& p_dsAction) + { + m_mxEntityId = p_dsAction.GetObjectId(); + m_atom = p_dsAction.GetAtomId(); return SUCCESS; } + inline MxS32 GetEntityId() { return m_mxEntityId; } + inline MxAtomId& GetAtom() { return m_atom; } + protected: MxS32 m_mxEntityId; // 0x8 MxAtomId m_atom; // 0xc diff --git a/LEGO1/omni/include/mxhashtable.h b/LEGO1/omni/include/mxhashtable.h index 8d6be0cf..056ff402 100644 --- a/LEGO1/omni/include/mxhashtable.h +++ b/LEGO1/omni/include/mxhashtable.h @@ -32,10 +32,10 @@ class MxHashTableNode { template class MxHashTable : protected MxCollection { public: - enum HashTableOpt { - HashTableOpt_NoExpand = 0, - HashTableOpt_ExpandAdd = 1, - HashTableOpt_ExpandMultiply = 2, + enum Option { + e_noExpand = 0, + e_expandAll, + e_expandMultiply, }; MxHashTable() @@ -43,7 +43,7 @@ class MxHashTable : protected MxCollection { m_numSlots = HASH_TABLE_INIT_SIZE; m_slots = new MxHashTableNode*[HASH_TABLE_INIT_SIZE]; memset(m_slots, 0, sizeof(MxHashTableNode*) * m_numSlots); - m_resizeOption = HashTableOpt_NoExpand; + m_resizeOption = e_noExpand; } virtual ~MxHashTable() override; @@ -62,7 +62,7 @@ class MxHashTable : protected MxCollection { MxHashTableNode** m_slots; // 0x10 MxU32 m_numSlots; // 0x14 MxU32 m_autoResizeRatio; // 0x18 - HashTableOpt m_resizeOption; // 0x1c + Option m_resizeOption; // 0x1c // FIXME: or FIXME? This qword is used as an integer or double depending // on the value of m_resizeOption. Hard to say whether this is how the devs // did it, but a simple cast in either direction doesn't match. @@ -177,10 +177,10 @@ inline void MxHashTable::Resize() MxHashTableNode** oldTable = m_slots; switch (m_resizeOption) { - case HashTableOpt_ExpandAdd: + case e_expandAll: m_numSlots += m_increaseAmount; break; - case HashTableOpt_ExpandMultiply: + case e_expandMultiply: m_numSlots *= m_increaseFactor; break; } diff --git a/LEGO1/omni/include/mxlist.h b/LEGO1/omni/include/mxlist.h index 911d5a36..99330975 100644 --- a/LEGO1/omni/include/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -69,6 +69,7 @@ class MxList : protected MxCollection { MxListEntry* InsertEntry(T, MxListEntry*, MxListEntry*); }; +// SIZE 0x18 template class MxPtrList : public MxList { public: @@ -82,6 +83,7 @@ class MxPtrList : public MxList { } }; +// SIZE 0x10 template class MxListCursor : public MxCore { public: @@ -128,6 +130,7 @@ class MxListCursor : public MxCore { MxListEntry* m_match; // 0x0c }; +// SIZE 0x10 template class MxPtrListCursor : public MxListCursor { public: diff --git a/LEGO1/omni/include/mxmediamanager.h b/LEGO1/omni/include/mxmediamanager.h index 47f7f0d1..aefbd9f6 100644 --- a/LEGO1/omni/include/mxmediamanager.h +++ b/LEGO1/omni/include/mxmediamanager.h @@ -14,17 +14,17 @@ class MxMediaManager : public MxCore { MxMediaManager(); virtual ~MxMediaManager() override; - virtual MxResult Tickle() override; // vtable+08 - virtual MxResult InitPresenters(); // vtable+14 - virtual void Destroy(); // vtable+18 - virtual void AddPresenter(MxPresenter& p_presenter); // vtable+1c - virtual void RemovePresenter(MxPresenter& p_presenter); // vtable+20 - virtual void StopPresenters(); // vtable+24 + virtual MxResult Tickle() override; // vtable+08 + virtual MxResult InitPresenters(); // vtable+14 + virtual void Destroy(); // vtable+18 + virtual void RegisterPresenter(MxPresenter& p_presenter); // vtable+1c + virtual void UnregisterPresenter(MxPresenter& p_presenter); // vtable+20 + virtual void StopPresenters(); // vtable+24 MxResult Init(); protected: - MxPresenterList* m_presenters; + MxPresenterList* m_presenters; // 0x8 MxThread* m_thread; // 0xc MxCriticalSection m_criticalSection; // 0x10 }; diff --git a/LEGO1/omni/include/mxmediapresenter.h b/LEGO1/omni/include/mxmediapresenter.h index 64baa409..360e978e 100644 --- a/LEGO1/omni/include/mxmediapresenter.h +++ b/LEGO1/omni/include/mxmediapresenter.h @@ -11,7 +11,9 @@ class MxMediaPresenter : public MxPresenter { public: inline MxMediaPresenter() { Init(); } - virtual ~MxMediaPresenter() override; + + // FUNCTION: LEGO1 0x1000c550 + virtual ~MxMediaPresenter() override { Destroy(TRUE); }; virtual MxResult Tickle() override; // vtable+0x8 @@ -28,10 +30,13 @@ class MxMediaPresenter : public MxPresenter { 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 - virtual void Destroy() override; // vtable+0x38 + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void DoneTickle() override; // vtable+0x2c + + // FUNCTION: LEGO1 0x1000c5b0 + virtual 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 diff --git a/LEGO1/omni/include/mxnotificationmanager.h b/LEGO1/omni/include/mxnotificationmanager.h index 4a3d8726..b93cc7c8 100644 --- a/LEGO1/omni/include/mxnotificationmanager.h +++ b/LEGO1/omni/include/mxnotificationmanager.h @@ -52,4 +52,34 @@ class MxNotificationManager : public MxCore { void FlushPending(MxCore* p_listener); }; +// TEMPLATE: LEGO1 0x100ac320 +// list >::~list > + +// FUNCTION: LEGO1 0x100ac3b0 +// MxIdList::~MxIdList + +// TEMPLATE: LEGO1 0x100ac400 +// List::~List + +// TEMPLATE: LEGO1 0x100ac540 +// List::~List + +// TEMPLATE: LEGO1 0x100ac590 +// list >::~list > + +// TEMPLATE: LEGO1 0x100acbf0 +// list >::begin + +// TEMPLATE: LEGO1 0x100acc00 +// list >::insert + +// TEMPLATE: LEGO1 0x100acc50 +// list >::erase + +// TEMPLATE: LEGO1 0x100acca0 +// list >::_Buynode + +// SYNTHETIC: LEGO1 0x100accd0 +// MxNotificationPtrList::~MxNotificationPtrList + #endif // MXNOTIFICATIONMANAGER_H diff --git a/LEGO1/omni/include/mxnotificationparam.h b/LEGO1/omni/include/mxnotificationparam.h index 66f9dd95..e990abe6 100644 --- a/LEGO1/omni/include/mxnotificationparam.h +++ b/LEGO1/omni/include/mxnotificationparam.h @@ -8,48 +8,55 @@ class MxCore; enum NotificationId { - PARAM_NONE = 0, + c_notificationType0 = 0, c_notificationStartAction = 1, // 100dc210:100d8350 c_notificationEndAction = 2, // 100d8358:100d8350 - TYPE4 = 4, // 100dc208:100d8350 - MXPRESENTER_NOTIFICATION = 5, - MXSTREAMER_DELETE_NOTIFY = 6, // 100dc760 + c_notificationType4 = 4, // 100dc208:100d8350 + c_notificationPresenter = 5, + c_notificationStreamer = 6, // 100dc760 c_notificationKeyPress = 7, // 100d6aa0 c_notificationButtonUp = 8, // 100d6aa0 c_notificationButtonDown = 9, // 100d6aa0 c_notificationMouseMove = 10, // 100d6aa0 - TYPE11 = 11, // 100d6aa0 + c_notificationType11 = 11, // 100d6aa0 c_notificationDragEnd = 12, c_notificationDragStart = 13, c_notificationDrag = 14, c_notificationTimer = 15, // 100d6aa0 - TYPE17 = 17, - TYPE18 = 18, // 100d7e80 - TYPE19 = 19, // 100d6230 - TYPE20 = 20, + c_notificationType17 = 17, + c_notificationType18 = 18, // 100d7e80 + c_notificationType19 = 19, // 100d6230 + c_notificationType20 = 20, c_notificationNewPresenter = 21, - TYPE22 = 22, - TYPE23 = 23, - MXTRANSITIONMANAGER_TRANSITIONENDED = 24 + c_notificationType22 = 22, + c_notificationType23 = 23, + c_notificationTransitioned = 24 }; // VTABLE: LEGO1 0x100d56e0 +// SIZE 0x0c class MxNotificationParam : public MxParam { public: inline MxNotificationParam(NotificationId p_type, MxCore* p_sender) : MxParam(), m_type(p_type), m_sender(p_sender) { } - virtual ~MxNotificationParam() override {} // vtable+0x0 (scalar deleting destructor) - virtual MxNotificationParam* Clone(); // vtable+0x4 + // FUNCTION: LEGO1 0x10010390 + virtual MxNotificationParam* Clone() { return new MxNotificationParam(m_type, m_sender); }; // vtable+0x4 inline NotificationId GetNotification() const { return m_type; } inline MxCore* GetSender() const { return m_sender; } inline NotificationId GetType() const { return m_type; } protected: - NotificationId m_type; // 0x4 - MxCore* m_sender; // 0x8 + NotificationId m_type; // 0x04 + MxCore* m_sender; // 0x08 }; +// SYNTHETIC: LEGO1 0x10010430 +// MxNotificationParam::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100104a0 +// MxNotificationParam::~MxNotificationParam + #endif // MXNOTIFICATIONPARAM_H diff --git a/LEGO1/omni/include/mxomni.h b/LEGO1/omni/include/mxomni.h index 7bac0723..9f448c26 100644 --- a/LEGO1/omni/include/mxomni.h +++ b/LEGO1/omni/include/mxomni.h @@ -52,7 +52,9 @@ class MxOmni : public MxCore { virtual void NotifyCurrentEntity(MxNotificationParam* p_param); // vtable+34 virtual void StartTimer(); // vtable+38 virtual void StopTimer(); // vtable+3c - virtual MxBool IsTimerRunning(); // vtable+40 + + // FUNCTION: LEGO1 0x10058a90 + virtual MxBool IsTimerRunning() { return m_timerRunning; }; // vtable+40 static void SetInstance(MxOmni* p_instance); static MxBool FUN_100b06b0(MxDSAction* p_action, const char* p_name); @@ -98,12 +100,12 @@ __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(); MxVideoManager* MVideoManager(); MxAtomIdCounterSet* AtomIdCounterSet(); MxObjectFactory* ObjectFactory(); void DeleteObject(MxDSAction& p_dsAction); -void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last); #endif // MXOMNI_H diff --git a/LEGO1/omni/include/mxomnicreateflags.h b/LEGO1/omni/include/mxomnicreateflags.h index a94ed45a..24b1e942 100644 --- a/LEGO1/omni/include/mxomnicreateflags.h +++ b/LEGO1/omni/include/mxomnicreateflags.h @@ -6,84 +6,76 @@ class MxOmniCreateFlags { public: enum LowFlags { - Flag_CreateObjectFactory = 0x01, - Flag_CreateVariableTable = 0x02, - Flag_CreateTickleManager = 0x04, - Flag_CreateNotificationManager = 0x08, - Flag_CreateVideoManager = 0x10, - Flag_CreateSoundManager = 0x20, - Flag_CreateMusicManager = 0x40, - Flag_CreateEventManager = 0x80 + c_createObjectFactory = 0x01, + c_createVariableTable = 0x02, + c_createTickleManager = 0x04, + c_createNotificationManager = 0x08, + c_createVideoManager = 0x10, + c_createSoundManager = 0x20, + c_createMusicManager = 0x40, + c_createEventManager = 0x80 }; enum HighFlags { - Flag_CreateTimer = 0x02, - Flag_CreateStreamer = 0x04 + c_createTimer = 0x02, + c_createStreamer = 0x04 }; __declspec(dllexport) MxOmniCreateFlags(); - inline const MxBool CreateObjectFactory() const { return this->m_flags1 & Flag_CreateObjectFactory; } - inline const MxBool CreateVariableTable() const { return this->m_flags1 & Flag_CreateVariableTable; } - inline const MxBool CreateTickleManager() const { return this->m_flags1 & Flag_CreateTickleManager; } - inline const MxBool CreateNotificationManager() const { return this->m_flags1 & Flag_CreateNotificationManager; } - inline const MxBool CreateVideoManager() const { return this->m_flags1 & Flag_CreateVideoManager; } - inline const MxBool CreateSoundManager() const { return this->m_flags1 & Flag_CreateSoundManager; } - inline const MxBool CreateMusicManager() const { return this->m_flags1 & Flag_CreateMusicManager; } - inline const MxBool CreateEventManager() const { return this->m_flags1 & Flag_CreateEventManager; } + inline const MxBool CreateObjectFactory() const { return this->m_flags1 & c_createObjectFactory; } + inline const MxBool CreateVariableTable() const { return this->m_flags1 & c_createVariableTable; } + inline const MxBool CreateTickleManager() const { return this->m_flags1 & c_createTickleManager; } + inline const MxBool CreateNotificationManager() const { return this->m_flags1 & c_createNotificationManager; } + inline const MxBool CreateVideoManager() const { return this->m_flags1 & c_createVideoManager; } + inline const MxBool CreateSoundManager() const { return this->m_flags1 & c_createSoundManager; } + inline const MxBool CreateMusicManager() const { return this->m_flags1 & c_createMusicManager; } + inline const MxBool CreateEventManager() const { return this->m_flags1 & c_createEventManager; } - inline const MxBool CreateTimer() const { return this->m_flags2 & Flag_CreateTimer; } - inline const MxBool CreateStreamer() const { return this->m_flags2 & Flag_CreateStreamer; } + inline const MxBool CreateTimer() const { return this->m_flags2 & c_createTimer; } + inline const MxBool CreateStreamer() const { return this->m_flags2 & c_createStreamer; } inline void CreateObjectFactory(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateObjectFactory : this->m_flags1 & ~Flag_CreateObjectFactory); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createObjectFactory : this->m_flags1 & ~c_createObjectFactory); } inline void CreateVariableTable(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateVariableTable : this->m_flags1 & ~Flag_CreateVariableTable); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createVariableTable : this->m_flags1 & ~c_createVariableTable); } inline void CreateTickleManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateTickleManager : this->m_flags1 & ~Flag_CreateTickleManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createTickleManager : this->m_flags1 & ~c_createTickleManager); } inline void CreateNotificationManager(MxBool p_enable) { this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateNotificationManager - : this->m_flags1 & ~Flag_CreateNotificationManager); + (p_enable ? this->m_flags1 | c_createNotificationManager : this->m_flags1 & ~c_createNotificationManager); } inline void CreateVideoManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateVideoManager : this->m_flags1 & ~Flag_CreateVideoManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createVideoManager : this->m_flags1 & ~c_createVideoManager); } inline void CreateSoundManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateSoundManager : this->m_flags1 & ~Flag_CreateSoundManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createSoundManager : this->m_flags1 & ~c_createSoundManager); } inline void CreateMusicManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateMusicManager : this->m_flags1 & ~Flag_CreateMusicManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createMusicManager : this->m_flags1 & ~c_createMusicManager); } inline void CreateEventManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateEventManager : this->m_flags1 & ~Flag_CreateEventManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createEventManager : this->m_flags1 & ~c_createEventManager); } inline void CreateTimer(MxBool p_enable) { - this->m_flags2 = (p_enable ? this->m_flags2 | Flag_CreateTimer : this->m_flags2 & ~Flag_CreateTimer); + this->m_flags2 = (p_enable ? this->m_flags2 | c_createTimer : this->m_flags2 & ~c_createTimer); } inline void CreateStreamer(MxBool p_enable) { - this->m_flags2 = (p_enable ? this->m_flags2 | Flag_CreateStreamer : this->m_flags2 & ~Flag_CreateStreamer); + this->m_flags2 = (p_enable ? this->m_flags2 | c_createStreamer : this->m_flags2 & ~c_createStreamer); } private: diff --git a/LEGO1/omni/include/mxomnicreateparam.h b/LEGO1/omni/include/mxomnicreateparam.h index 825b5053..5404f39a 100644 --- a/LEGO1/omni/include/mxomnicreateparam.h +++ b/LEGO1/omni/include/mxomnicreateparam.h @@ -8,6 +8,7 @@ #include +// VTABLE: LEGO1 0x100dc218 class MxOmniCreateParam : public MxParam { public: __declspec(dllexport) MxOmniCreateParam( @@ -30,4 +31,7 @@ class MxOmniCreateParam : public MxParam { MxOmniCreateFlags m_createFlags; }; +// SYNTHETIC: ISLE 0x4014b0 +// MxOmniCreateParam::~MxOmniCreateParam + #endif // MXOMNICREATEPARAM_H diff --git a/LEGO1/omni/include/mxparam.h b/LEGO1/omni/include/mxparam.h index 19e92e0e..a266b12b 100644 --- a/LEGO1/omni/include/mxparam.h +++ b/LEGO1/omni/include/mxparam.h @@ -1,9 +1,18 @@ #ifndef MXPARAM_H #define MXPARAM_H +// VTABLE: ISLE 0x40f018 +// VTABLE: LEGO1 0x100d56e8 +// SIZE 0x04 class MxParam { public: + // FUNCTION: ISLE 0x401530 + // FUNCTION: LEGO1 0x10010360 virtual ~MxParam() {} }; +// SYNTHETIC: ISLE 0x401540 +// SYNTHETIC: LEGO1 0x10010370 +// MxParam::`scalar deleting destructor' + #endif // MXPARAM_H diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h index bc327c1f..d50e9818 100644 --- a/LEGO1/omni/include/mxpresenter.h +++ b/LEGO1/omni/include/mxpresenter.h @@ -17,19 +17,25 @@ class MxEntity; class MxPresenter : public MxCore { public: enum TickleState { - TickleState_Idle = 0, - TickleState_Ready, - TickleState_Starting, - TickleState_Streaming, - TickleState_Repeating, - TickleState_unk5, - TickleState_Done, + e_idle = 0, + e_ready, + e_starting, + e_streaming, + e_repeating, + e_unk5, + e_done, }; MxPresenter() { Init(); } - __declspec(dllexport) virtual ~MxPresenter(); // vtable+0x0 - __declspec(dllexport) virtual MxResult Tickle() override; // vtable+0x8 +#ifdef ISLE_APP + __declspec(dllexport) virtual ~MxPresenter() override; // vtable+0x00 +#else + // FUNCTION: LEGO1 0x1000bf00 + __declspec(dllexport) virtual ~MxPresenter() override{}; // vtable+0x00 +#endif + + __declspec(dllexport) virtual MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1000bfe0 inline virtual const char* ClassName() const override // vtable+0xc @@ -44,29 +50,73 @@ class MxPresenter : public MxCore { return !strcmp(p_name, MxPresenter::ClassName()) || MxCore::IsA(p_name); } - virtual void VTable0x14(); // vtable+0x14 - virtual void ReadyTickle(); // vtable+0x18 - virtual void StartingTickle(); // vtable+0x1c - virtual void StreamingTickle(); // vtable+0x20 - virtual void RepeatingTickle(); // vtable+0x24 - virtual void Unk5Tickle(); // vtable+0x28 + // FUNCTION: LEGO1 0x1000be30 + virtual void VTable0x14() {} // vtable+0x14 + + // FUNCTION: LEGO1 0x1000be40 + virtual void ReadyTickle() + { + ParseExtra(); + ProgressTickleState(e_starting); + } // vtable+0x18 + + // FUNCTION: LEGO1 0x1000be60 + virtual void StartingTickle() { ProgressTickleState(e_streaming); } // vtable+0x1c + + // FUNCTION: LEGO1 0x1000be80 + virtual void StreamingTickle() { ProgressTickleState(e_repeating); }; // vtable+0x20 + + // FUNCTION: LEGO1 0x1000bea0 + virtual void RepeatingTickle() { ProgressTickleState(e_unk5); }; // vtable+0x24 + + // FUNCTION: LEGO1 0x1000bec0 + 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 + __declspec(dllexport) virtual void ParseExtra(); // vtable+0x30 + inline void ProgressTickleState(TickleState p_tickleState) + { + m_previousTickleStates |= 1 << (MxU8) m_currentTickleState; + m_currentTickleState = p_tickleState; + } + public: - virtual MxResult AddToManager(); // vtable+0x34 - virtual void Destroy(); // vtable+0x38 + // FUNCTION: LEGO1 0x1000bf70 + virtual MxResult AddToManager() { return SUCCESS; }; // vtable+0x34 + + // FUNCTION: LEGO1 0x1000bf80 + virtual void Destroy() { Init(); }; // vtable+0x38 + __declspec(dllexport) virtual MxResult StartAction(MxStreamController*, MxDSAction*); // vtable+0x3c __declspec(dllexport) virtual void EndAction(); // vtable+0x40 - virtual void SetTickleState(TickleState p_tickleState); // vtable+0x44 - virtual MxBool HasTickleStatePassed(TickleState p_tickleState); // vtable+0x48 - virtual MxResult PutData(); // vtable+0x4c - virtual MxBool IsHit(MxS32 p_x, MxS32 p_y); // vtable+0x50 - __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 - MxEntity* CreateEntityBackend(const char* p_name); + // FUNCTION: LEGO1 0x1000bf90 + virtual void SetTickleState(TickleState p_tickleState) { ProgressTickleState(p_tickleState); } // vtable+0x44 + + // FUNCTION: LEGO1 0x1000bfb0 + virtual MxBool HasTickleStatePassed(TickleState p_tickleState) + { + return m_previousTickleStates & (1 << (MxU8) p_tickleState); + }; // vtable+0x48 + + // FUNCTION: LEGO1 0x1000bfc0 + virtual MxResult PutData() { return SUCCESS; }; // vtable+0x4c + + // FUNCTION: LEGO1 0x1000bfd0 + virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) { return FALSE; }; // vtable+0x50 + + __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 + + MxEntity* CreateEntity(const char* p_name); + void SendToCompositePresenter(MxOmni*); MxBool IsEnabled(); inline MxS32 GetCurrentTickleState() const { return this->m_currentTickleState; } @@ -81,7 +131,6 @@ class MxPresenter : public MxCore { protected: __declspec(dllexport) void Init(); - void SendToCompositePresenter(MxOmni*); TickleState m_currentTickleState; // 0x8 MxU32 m_previousTickleStates; // 0x0c diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index d8b74a3f..f346e645 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -53,6 +53,9 @@ class MxPresenterListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x1001ce20 // MxList::~MxList +// TEMPLATE: LEGO1 0x1001cf20 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x1001cf70 // MxCollection::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxramstreamprovider.h b/LEGO1/omni/include/mxramstreamprovider.h index 5c8bf59c..f5ac0897 100644 --- a/LEGO1/omni/include/mxramstreamprovider.h +++ b/LEGO1/omni/include/mxramstreamprovider.h @@ -29,17 +29,19 @@ class MxRAMStreamProvider : public MxStreamProvider { virtual MxU32 GetLengthInDWords() override; // vtable+0x24 virtual MxU32* GetBufferForDWords() override; // vtable+0x28 - inline MxU32* GetBufferOfFileSize() { return m_pBufferOfFileSize; } + inline MxU8* GetBufferOfFileSize() { return m_pBufferOfFileSize; } protected: - MxU32 m_bufferSize; // 0x10 - MxU32 m_fileSize; // 0x14 - MxU32* m_pBufferOfFileSize; // 0x18 - MxU32 m_lengthInDWords; // 0x1c - MxU32* m_bufferForDWords; // 0x20 + MxU32 m_bufferSize; // 0x10 + MxU32 m_fileSize; // 0x14 + MxU8* m_pBufferOfFileSize; // 0x18 + MxU32 m_lengthInDWords; // 0x1c + MxU32* m_bufferForDWords; // 0x20 }; // SYNTHETIC: LEGO1 0x100d0a30 // MxRAMStreamProvider::`scalar deleting destructor' +MxU32 ReadData(MxU8* p_fileSizeBuffer, MxU32 p_fileSize); + #endif // MXRAMSTREAMPROVIDER_H diff --git a/LEGO1/omni/include/mxrectlist.h b/LEGO1/omni/include/mxrectlist.h index e19c4994..c25c2483 100644 --- a/LEGO1/omni/include/mxrectlist.h +++ b/LEGO1/omni/include/mxrectlist.h @@ -53,6 +53,9 @@ class MxRectListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x100b3d80 // MxRectList::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x100b3df0 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x100b3e40 // MxCollection::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxregionlist.h b/LEGO1/omni/include/mxregionlist.h index 7c6da5c2..679ccebc 100644 --- a/LEGO1/omni/include/mxregionlist.h +++ b/LEGO1/omni/include/mxregionlist.h @@ -116,12 +116,21 @@ class MxRegionTopBottomListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x100c32e0 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100c32f0 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100c3340 // MxCollection::Destroy +// TEMPLATE: LEGO1 0x100c3350 +// MxList::~MxList + // TEMPLATE: LEGO1 0x100c33e0 // MxPtrList::Destroy +// TEMPLATE: LEGO1 0x100c3480 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x100c34d0 // MxCollection::`scalar deleting destructor' @@ -167,9 +176,18 @@ class MxRegionTopBottomListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x100c4d80 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100c4d90 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100c4de0 // MxCollection::Destroy +// TEMPLATE: LEGO1 0x100c4df0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x100c4f00 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x100c4f50 // MxCollection::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxsemaphore.h b/LEGO1/omni/include/mxsemaphore.h index ecb6509c..4e692395 100644 --- a/LEGO1/omni/include/mxsemaphore.h +++ b/LEGO1/omni/include/mxsemaphore.h @@ -5,12 +5,13 @@ #include +// VTABLE: LEGO1 0x100dccf0 // SIZE 0x08 class MxSemaphore { public: MxSemaphore(); - // Inlined only, no offset + // FUNCTION: LEGO1 0x100c87e0 ~MxSemaphore() { CloseHandle(m_hSemaphore); } virtual MxResult Init(MxU32 p_initialCount, MxU32 p_maxCount); diff --git a/LEGO1/omni/include/mxsoundpresenter.h b/LEGO1/omni/include/mxsoundpresenter.h index d61d8088..1d49204a 100644 --- a/LEGO1/omni/include/mxsoundpresenter.h +++ b/LEGO1/omni/include/mxsoundpresenter.h @@ -8,7 +8,8 @@ // SIZE 0x54 class MxSoundPresenter : public MxAudioPresenter { public: - virtual ~MxSoundPresenter() override; + // FUNCTION: LEGO1 0x1000d430 + virtual ~MxSoundPresenter() override { Destroy(TRUE); }; // FUNCTION: LEGO1 0x1000d4a0 inline virtual const char* ClassName() const // vtable+0x0c @@ -24,7 +25,9 @@ class MxSoundPresenter : public MxAudioPresenter { }; virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + + // FUNCTION: LEGO1 0x1000d490 + virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 protected: void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxstillpresenter.h b/LEGO1/omni/include/mxstillpresenter.h index 828f58b7..0fa48bf3 100644 --- a/LEGO1/omni/include/mxstillpresenter.h +++ b/LEGO1/omni/include/mxstillpresenter.h @@ -25,11 +25,14 @@ class MxStillPresenter : public MxVideoPresenter { 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 - virtual void Destroy() override; // vtable+0x38 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void ParseExtra() override; // vtable+0x30 + + // FUNCTION: LEGO1 0x100435b0 + virtual 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 diff --git a/LEGO1/omni/include/mxstreamchunklist.h b/LEGO1/omni/include/mxstreamchunklist.h index 02dcd2d9..2d1ce119 100644 --- a/LEGO1/omni/include/mxstreamchunklist.h +++ b/LEGO1/omni/include/mxstreamchunklist.h @@ -29,6 +29,7 @@ class MxStreamChunkList : public MxList { }; // VTABLE: LEGO1 0x100dc510 +// SIZE 0x10 class MxStreamChunkListCursor : public MxListCursor { public: MxStreamChunkListCursor(MxStreamChunkList* p_list) : MxListCursor(p_list){}; @@ -40,6 +41,9 @@ class MxStreamChunkListCursor : public MxListCursor { // TEMPLATE: LEGO1 0x100b5930 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100b5940 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100b5990 // MxCollection::Destroy diff --git a/LEGO1/omni/include/mxstreamer.h b/LEGO1/omni/include/mxstreamer.h index 02f97d12..f22e343f 100644 --- a/LEGO1/omni/include/mxstreamer.h +++ b/LEGO1/omni/include/mxstreamer.h @@ -24,6 +24,7 @@ class MxStreamerSubClass1 { } } + // FUNCTION: LEGO1 0x100b9110 ~MxStreamerSubClass1() { delete[] m_buffer; } undefined4 GetSize() const { return m_size; } @@ -48,6 +49,7 @@ class MxStreamerSubClass3 : public MxStreamerSubClass1 { inline MxStreamerSubClass3() : MxStreamerSubClass1(0x80) {} }; +// VTABLE: LEGO1 0x100dc760 class MxStreamerNotification : public MxNotificationParam { public: inline MxStreamerNotification(NotificationId p_type, MxCore* p_sender, MxStreamController* p_ctrlr) @@ -56,8 +58,6 @@ class MxStreamerNotification : public MxNotificationParam { m_controller = p_ctrlr; } - virtual ~MxStreamerNotification() override {} - virtual MxNotificationParam* Clone() override; MxStreamController* GetController() { return m_controller; } @@ -71,7 +71,7 @@ class MxStreamerNotification : public MxNotificationParam { class MxStreamer : public MxCore { public: enum OpenMode { - e_DiskStream, + e_diskStream = 0, e_RAMStream }; @@ -100,6 +100,7 @@ class MxStreamer : public MxCore { MxBool FUN_100b9b30(MxDSObject& p_dsObject); MxStreamController* GetOpenStream(const char* p_name); + void FUN_100b98f0(MxDSAction* p_action); MxResult AddStreamControllerToOpenList(MxStreamController* p_stream); MxResult FUN_100b99b0(MxDSAction* p_action); MxResult DeleteObject(MxDSAction* p_dsAction); @@ -113,7 +114,21 @@ class MxStreamer : public MxCore { MxStreamerSubClass3 m_subclass2; // 0x20 }; +// clang-format off +// TEMPLATE: LEGO1 0x100b9090 +// list >::~list > +// clang-format on + // SYNTHETIC: LEGO1 0x100b9120 // MxStreamer::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x100b9140 +// List::~List + +// SYNTHETIC: LEGO1 0x100b97b0 +// MxStreamerNotification::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100b9820 +// MxStreamerNotification::~MxStreamerNotification + #endif // MXSTREAMER_H diff --git a/LEGO1/omni/include/mxstreamprovider.h b/LEGO1/omni/include/mxstreamprovider.h index 17bba38d..803038e3 100644 --- a/LEGO1/omni/include/mxstreamprovider.h +++ b/LEGO1/omni/include/mxstreamprovider.h @@ -41,4 +41,7 @@ class MxStreamProvider : public MxCore { // SYNTHETIC: LEGO1 0x100d0870 // MxStreamProvider::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x100d08e0 +// MxStreamProvider::~MxStreamProvider + #endif // MXSTREAMPROVIDER_H diff --git a/LEGO1/omni/include/mxstringlist.h b/LEGO1/omni/include/mxstringlist.h index 6e75683d..2a61f530 100644 --- a/LEGO1/omni/include/mxstringlist.h +++ b/LEGO1/omni/include/mxstringlist.h @@ -9,23 +9,39 @@ class MxStringList : public MxList {}; // VTABLE: LEGO1 0x100dd058 +// SIZE 0x10 class MxStringListCursor : public MxListCursor { public: MxStringListCursor(MxStringList* p_list) : MxListCursor(p_list){}; }; +// VTABLE: LEGO1 0x100dd010 +// class MxCollection + +// VTABLE: LEGO1 0x100dd028 +// class MxList + // VTABLE: LEGO1 0x100dd070 // class MxListCursor // TEMPLATE: LEGO1 0x100cb3c0 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100cb420 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100cb470 // MxCollection::Destroy // TEMPLATE: LEGO1 0x100cb4c0 // MxList::~MxList +// SYNTHETIC: LEGO1 0x100cb590 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100cb600 +// MxList::`scalar deleting destructor' + // TEMPLATE: LEGO1 0x100cbb40 // MxList::Append diff --git a/LEGO1/omni/include/mxticklemanager.h b/LEGO1/omni/include/mxticklemanager.h index 44694a61..0fdb648a 100644 --- a/LEGO1/omni/include/mxticklemanager.h +++ b/LEGO1/omni/include/mxticklemanager.h @@ -50,4 +50,10 @@ class MxTickleManager : public MxCore { #define TICKLE_MANAGER_NOT_FOUND 0x80000000 +// TEMPLATE: LEGO1 0x1005a4a0 +// list >::~list > + +// TEMPLATE: LEGO1 0x1005a530 +// List::~List + #endif // MXTICKLEMANAGER_H diff --git a/LEGO1/omni/include/mxutil.h b/LEGO1/omni/include/mxutil.h index f9febef1..bd0247fd 100644 --- a/LEGO1/omni/include/mxutil.h +++ b/LEGO1/omni/include/mxutil.h @@ -3,8 +3,11 @@ #include "mxtypes.h" +#include + class MxDSFile; class MxDSObject; +class MxDSAction; template inline T Abs(T p_t) @@ -68,6 +71,7 @@ MxBool FUN_100b6e10( __declspec(dllexport) void MakeSourceName(char*, const char*); __declspec(dllexport) void SetOmniUserMessage(void (*)(const char*, int)); +void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags); __declspec(dllexport) 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 d1434467..e09d449c 100644 --- a/LEGO1/omni/include/mxvariable.h +++ b/LEGO1/omni/include/mxvariable.h @@ -20,15 +20,24 @@ class MxVariable { m_key.ToUpperCase(); m_value = p_value; } - virtual MxString* GetValue(); - virtual void SetValue(const char* p_value); - virtual void Destroy(); + + // FUNCTION: LEGO1 0x1003bea0 + virtual MxString* GetValue() { return &m_value; }; + + // FUNCTION: LEGO1 0x1003beb0 + virtual void SetValue(const char* p_value) { m_value = p_value; }; + + // FUNCTION: LEGO1 0x1003bec0 + virtual void Destroy() { delete this; }; inline const MxString* GetKey() const { return &m_key; } protected: - MxString m_key; - MxString m_value; + MxString m_key; // 0x04 + MxString m_value; // 0x14 }; +// SYNTHETIC: LEGO1 0x1003bf40 +// MxVariable::~MxVariable + #endif // MXVARIABLE_H diff --git a/LEGO1/omni/include/mxvariabletable.h b/LEGO1/omni/include/mxvariabletable.h index 7821311e..0d79570c 100644 --- a/LEGO1/omni/include/mxvariabletable.h +++ b/LEGO1/omni/include/mxvariabletable.h @@ -26,6 +26,9 @@ class MxVariableTable : public MxHashTable { // VTABLE: LEGO1 0x100dc1e8 // class MxHashTable +// VTABLE: LEGO1 0x100dc680 +// class MxHashTableCursor + // TEMPLATE: LEGO1 0x100afcd0 // MxCollection::Compare @@ -50,6 +53,9 @@ class MxVariableTable : public MxHashTable { // SYNTHETIC: LEGO1 0x100b0ca0 // MxHashTable::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x100b7680 +// MxHashTableCursor::~MxHashTableCursor + // TEMPLATE: LEGO1 0x100b7ab0 // MxHashTable::Resize diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index f02f3f08..f91f2eb7 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -11,15 +11,17 @@ class MxVideoPresenter : public MxMediaPresenter { public: enum { - Flag_Bit1 = 0x01, - Flag_Bit2 = 0x02, - Flag_Bit3 = 0x04, - Flag_Bit4 = 0x08, - Flag_Bit5 = 0x10, + c_bit1 = 0x01, + c_bit2 = 0x02, + c_bit3 = 0x04, + c_bit4 = 0x08, + c_bit5 = 0x10, }; MxVideoPresenter() { Init(); } - virtual ~MxVideoPresenter() override; // vtable+0x0 + + // FUNCTION: LEGO1 0x1000c740 + virtual ~MxVideoPresenter() override { Destroy(TRUE); }; // vtable+0x0 // FUNCTION: LEGO1 0x1000c820 inline virtual const char* ClassName() const override // vtable+0x0c @@ -34,28 +36,51 @@ class MxVideoPresenter : public MxMediaPresenter { 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 - virtual void Destroy() override; // vtable+0x38 + 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 + + // FUNCTION: LEGO1 0x1000c7a0 + virtual 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 - virtual void LoadHeader(MxStreamChunk* p_chunk); // vtable+0x5c - virtual void CreateBitmap(); // vtable+0x60 - virtual void NextFrame(); // vtable+0x64 - virtual void LoadFrame(MxStreamChunk* p_chunk); // vtable+0x68 - virtual void PutFrame(); // vtable+0x6c - virtual void RealizePalette(); // vtable+0x70 - virtual undefined VTable0x74(); // vtable+0x74 - virtual LPDIRECTDRAWSURFACE VTable0x78(); // vtable+0x78 - virtual MxBool VTable0x7c(); // vtable+0x7c - virtual MxS32 GetWidth(); // vtable+0x80 - virtual MxS32 GetHeight(); // vtable+0x84 + // FUNCTION: LEGO1 0x1000c700 + virtual void LoadHeader(MxStreamChunk* p_chunk){}; // vtable+0x5c + + // FUNCTION: LEGO1 0x1000c710 + virtual void CreateBitmap(){}; // vtable+0x60 + + virtual void NextFrame(); // vtable+0x64 + + // FUNCTION: LEGO1 0x1000c720 + virtual void LoadFrame(MxStreamChunk* p_chunk){}; // vtable+0x68 + + virtual void PutFrame(); // vtable+0x6c + + // FUNCTION: LEGO1 0x1000c730 + virtual void RealizePalette(){}; // vtable+0x70 + + virtual undefined VTable0x74(); // vtable+0x74 + + // FUNCTION: LEGO1 0x1000c7b0 + virtual LPDIRECTDRAWSURFACE VTable0x78() { return m_unk0x58; }; // vtable+0x78 + + // FUNCTION: LEGO1 0x1000c7c0 + 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 + + // FUNCTION: LEGO1 0x1000c800 + virtual MxS32 GetHeight() { return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs(); }; // vtable+0x84 + + // VTABLE: LEGO1 0x100dc2bc // SIZE 0xc struct AlphaMask { MxU8* m_bitmask; diff --git a/LEGO1/omni/include/mxwavepresenter.h b/LEGO1/omni/include/mxwavepresenter.h index 383659ab..3bdf734f 100644 --- a/LEGO1/omni/include/mxwavepresenter.h +++ b/LEGO1/omni/include/mxwavepresenter.h @@ -11,7 +11,9 @@ class MxWavePresenter : public MxSoundPresenter { public: MxWavePresenter() { Init(); } - virtual ~MxWavePresenter() override; // vtable+0x00 + + // FUNCTION: LEGO1 0x1000d640 + virtual ~MxWavePresenter() override { Destroy(TRUE); }; // vtable+0x00 // FUNCTION: LEGO1 0x1000d6c0 inline virtual const char* ClassName() const override // vtable+0x0c @@ -26,13 +28,16 @@ class MxWavePresenter : public MxSoundPresenter { 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 - virtual void Destroy() override; // vtable+0x38 + 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 + + // FUNCTION: LEGO1 0x1000d6a0 + virtual 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 @@ -40,7 +45,9 @@ class MxWavePresenter : public MxSoundPresenter { virtual void SetVolume(MxS32 p_volume) override; // vtable+0x60 virtual void Pause(); // vtable+0x64 virtual void Resume(); // vtable+0x68 - virtual MxBool IsPaused(); // vtable+0x6c + + // FUNCTION: LEGO1 0x1000d6b0 + virtual MxBool IsPaused() { return m_paused; }; // vtable+0x6c // Reference: https://github.com/itsmattkc/SIEdit/blob/master/lib/othertypes.h // SIZE 0x1c diff --git a/LEGO1/omni/src/action/mxdsaction.cpp b/LEGO1/omni/src/action/mxdsaction.cpp index b24ff347..cea02696 100644 --- a/LEGO1/omni/src/action/mxdsaction.cpp +++ b/LEGO1/omni/src/action/mxdsaction.cpp @@ -15,14 +15,14 @@ MxU16 g_sep = TWOCC(',', ' '); // FUNCTION: LEGO1 0x100ad810 MxDSAction::MxDSAction() { - this->m_flags = MxDSAction::Flag_Enabled; + this->m_flags = MxDSAction::c_enabled; this->m_startTime = INT_MIN; this->m_extraData = NULL; this->m_extraLength = 0; this->m_duration = INT_MIN; this->m_loopCount = -1; - this->SetType(MxDSType_Action); + this->SetType(e_action); this->m_location.Fill(FLT_MAX); this->m_direction.Fill(FLT_MAX); this->m_up.Fill(FLT_MAX); @@ -88,6 +88,12 @@ void MxDSAction::CopyFrom(MxDSAction& p_dsAction) this->m_unk0x90 = p_dsAction.m_unk0x90; } +// FUNCTION: LEGO1 0x100adbd0 +undefined4 MxDSAction::VTable0x14() +{ + return MxDSObject::VTable0x14(); +} + // FUNCTION: LEGO1 0x100adbe0 MxU32 MxDSAction::GetSizeOnDisk() { diff --git a/LEGO1/omni/src/action/mxdsanim.cpp b/LEGO1/omni/src/action/mxdsanim.cpp index c62be34c..cef2321c 100644 --- a/LEGO1/omni/src/action/mxdsanim.cpp +++ b/LEGO1/omni/src/action/mxdsanim.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSAnim, 0xb8) // FUNCTION: LEGO1 0x100c8ff0 MxDSAnim::MxDSAnim() { - this->SetType(MxDSType_Anim); + this->SetType(e_anim); } // FUNCTION: LEGO1 0x100c91a0 diff --git a/LEGO1/omni/src/action/mxdsevent.cpp b/LEGO1/omni/src/action/mxdsevent.cpp index 198c9ca0..bc925369 100644 --- a/LEGO1/omni/src/action/mxdsevent.cpp +++ b/LEGO1/omni/src/action/mxdsevent.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSEvent, 0xb8) // FUNCTION: LEGO1 0x100c95f0 MxDSEvent::MxDSEvent() { - this->SetType(MxDSType_Event); + this->SetType(e_event); } // FUNCTION: LEGO1 0x100c97a0 diff --git a/LEGO1/omni/src/action/mxdsmediaaction.cpp b/LEGO1/omni/src/action/mxdsmediaaction.cpp index c631dec8..fda2721a 100644 --- a/LEGO1/omni/src/action/mxdsmediaaction.cpp +++ b/LEGO1/omni/src/action/mxdsmediaaction.cpp @@ -15,7 +15,7 @@ MxDSMediaAction::MxDSMediaAction() this->m_paletteManagement = 1; this->m_unk0xb4 = -1; this->m_sustainTime = 0; - this->SetType(MxDSType_MediaAction); + this->SetType(e_mediaAction); } // FUNCTION: LEGO1 0x100c8cf0 @@ -47,6 +47,17 @@ MxDSMediaAction& MxDSMediaAction::operator=(MxDSMediaAction& p_dsMediaAction) return *this; } +// FUNCTION: LEGO1 0x100c8df0 +MxDSAction* MxDSMediaAction::Clone() +{ + MxDSMediaAction* clone = new MxDSMediaAction(); + + if (clone) + *clone = *this; + + return clone; +} + // FUNCTION: LEGO1 0x100c8e80 void MxDSMediaAction::CopyMediaSrcPath(const char* p_mediaSrcPath) { @@ -64,6 +75,12 @@ void MxDSMediaAction::CopyMediaSrcPath(const char* p_mediaSrcPath) this->m_mediaSrcPath = NULL; } +// FUNCTION: LEGO1 0x100c8f00 +undefined4 MxDSMediaAction::VTable0x14() +{ + return MxDSAction::VTable0x14(); +} + // FUNCTION: LEGO1 0x100c8f10 MxU32 MxDSMediaAction::GetSizeOnDisk() { diff --git a/LEGO1/omni/src/action/mxdsmultiaction.cpp b/LEGO1/omni/src/action/mxdsmultiaction.cpp index b986c23d..64e20a55 100644 --- a/LEGO1/omni/src/action/mxdsmultiaction.cpp +++ b/LEGO1/omni/src/action/mxdsmultiaction.cpp @@ -7,7 +7,7 @@ DECOMP_SIZE_ASSERT(MxDSActionListCursor, 0x10); // FUNCTION: LEGO1 0x100c9b90 MxDSMultiAction::MxDSMultiAction() { - this->SetType(MxDSType_MultiAction); + this->SetType(e_multiAction); this->m_actions = new MxDSActionList; this->m_actions->SetDestroy(MxDSActionList::Destroy); } diff --git a/LEGO1/omni/src/action/mxdsobject.cpp b/LEGO1/omni/src/action/mxdsobject.cpp index 7ee92937..6d11476d 100644 --- a/LEGO1/omni/src/action/mxdsobject.cpp +++ b/LEGO1/omni/src/action/mxdsobject.cpp @@ -11,7 +11,6 @@ #include "mxdsserialaction.h" #include "mxdssound.h" #include "mxdsstill.h" -#include "mxdstypes.h" #include "mxutil.h" #include @@ -22,7 +21,7 @@ DECOMP_SIZE_ASSERT(MxDSObject, 0x2c); // FUNCTION: LEGO1 0x100bf6a0 MxDSObject::MxDSObject() { - this->SetType(MxDSType_Object); + this->SetType(e_object); this->m_sourceName = NULL; this->m_unk0x14 = 0; this->m_objectName = NULL; @@ -148,40 +147,40 @@ MxDSObject* DeserializeDSObjectDispatch(MxU8** p_source, MxS16 p_flags) switch (type) { default: return NULL; - case MxDSType_Object: + case MxDSObject::e_object: obj = new MxDSObject(); break; - case MxDSType_Action: + case MxDSObject::e_action: obj = new MxDSAction(); break; - case MxDSType_MediaAction: + case MxDSObject::e_mediaAction: obj = new MxDSMediaAction(); break; - case MxDSType_Anim: + case MxDSObject::e_anim: obj = new MxDSAnim(); break; - case MxDSType_Sound: + case MxDSObject::e_sound: obj = new MxDSSound(); break; - case MxDSType_MultiAction: + case MxDSObject::e_multiAction: obj = new MxDSMultiAction(); break; - case MxDSType_SerialAction: + case MxDSObject::e_serialAction: obj = new MxDSSerialAction(); break; - case MxDSType_ParallelAction: + case MxDSObject::e_parallelAction: obj = new MxDSParallelAction(); break; - case MxDSType_Event: + case MxDSObject::e_event: obj = new MxDSEvent(); break; - case MxDSType_SelectAction: + case MxDSObject::e_selectAction: obj = new MxDSSelectAction(); break; - case MxDSType_Still: + case MxDSObject::e_still: obj = new MxDSStill(); break; - case MxDSType_ObjectAction: + case MxDSObject::e_objectAction: obj = new MxDSObjectAction(); break; } diff --git a/LEGO1/omni/src/action/mxdsobjectaction.cpp b/LEGO1/omni/src/action/mxdsobjectaction.cpp index 1155d3a5..db8b149f 100644 --- a/LEGO1/omni/src/action/mxdsobjectaction.cpp +++ b/LEGO1/omni/src/action/mxdsobjectaction.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSObjectAction, 0xb8) // FUNCTION: LEGO1 0x100c8870 MxDSObjectAction::MxDSObjectAction() { - this->SetType(MxDSType_ObjectAction); + this->SetType(e_objectAction); } // FUNCTION: LEGO1 0x100c8a20 diff --git a/LEGO1/omni/src/action/mxdsparallelaction.cpp b/LEGO1/omni/src/action/mxdsparallelaction.cpp index 07b0fef2..a14a326f 100644 --- a/LEGO1/omni/src/action/mxdsparallelaction.cpp +++ b/LEGO1/omni/src/action/mxdsparallelaction.cpp @@ -7,7 +7,7 @@ DECOMP_SIZE_ASSERT(MxDSParallelAction, 0x9c) // FUNCTION: LEGO1 0x100cae80 MxDSParallelAction::MxDSParallelAction() { - this->SetType(MxDSType_ParallelAction); + this->SetType(e_parallelAction); } // FUNCTION: LEGO1 0x100cb040 diff --git a/LEGO1/omni/src/action/mxdsselectaction.cpp b/LEGO1/omni/src/action/mxdsselectaction.cpp index 27f3a9cf..ddadde84 100644 --- a/LEGO1/omni/src/action/mxdsselectaction.cpp +++ b/LEGO1/omni/src/action/mxdsselectaction.cpp @@ -5,12 +5,14 @@ #include "mxvariabletable.h" DECOMP_SIZE_ASSERT(MxDSSelectAction, 0xb0) +DECOMP_SIZE_ASSERT(MxStringList, 0x18) +DECOMP_SIZE_ASSERT(MxStringListCursor, 0x10) DECOMP_SIZE_ASSERT(MxListEntry, 0x18) // FUNCTION: LEGO1 0x100cb2b0 MxDSSelectAction::MxDSSelectAction() { - this->SetType(MxDSType_SelectAction); + this->SetType(e_selectAction); this->m_unk0xac = new MxStringList; } diff --git a/LEGO1/omni/src/action/mxdsserialaction.cpp b/LEGO1/omni/src/action/mxdsserialaction.cpp index 59cda938..24513f48 100644 --- a/LEGO1/omni/src/action/mxdsserialaction.cpp +++ b/LEGO1/omni/src/action/mxdsserialaction.cpp @@ -7,7 +7,7 @@ DECOMP_SIZE_ASSERT(MxDSSerialAction, 0xa8) // FUNCTION: LEGO1 0x100ca9d0 MxDSSerialAction::MxDSSerialAction() { - this->SetType(MxDSType_SerialAction); + this->SetType(e_serialAction); this->m_cursor = new MxDSActionListCursor(this->m_actions); this->m_unk0xa0 = 0; } diff --git a/LEGO1/omni/src/action/mxdssound.cpp b/LEGO1/omni/src/action/mxdssound.cpp index 49806ce0..61022cab 100644 --- a/LEGO1/omni/src/action/mxdssound.cpp +++ b/LEGO1/omni/src/action/mxdssound.cpp @@ -8,7 +8,7 @@ DECOMP_SIZE_ASSERT(MxDSSound, 0xc0) MxDSSound::MxDSSound() { this->m_volume = 0x4f; - this->SetType(MxDSType_Sound); + this->SetType(e_sound); } // FUNCTION: LEGO1 0x100c9470 diff --git a/LEGO1/omni/src/action/mxdsstill.cpp b/LEGO1/omni/src/action/mxdsstill.cpp index 6ee1ede3..59a78ffc 100644 --- a/LEGO1/omni/src/action/mxdsstill.cpp +++ b/LEGO1/omni/src/action/mxdsstill.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSStill, 0xb8) // FUNCTION: LEGO1 0x100c98c0 MxDSStill::MxDSStill() { - this->SetType(MxDSType_Still); + this->SetType(e_still); } // FUNCTION: LEGO1 0x100c9a70 diff --git a/LEGO1/omni/src/audio/mxaudiomanager.cpp b/LEGO1/omni/src/audio/mxaudiomanager.cpp index 318a8446..a2d6072a 100644 --- a/LEGO1/omni/src/audio/mxaudiomanager.cpp +++ b/LEGO1/omni/src/audio/mxaudiomanager.cpp @@ -5,12 +5,6 @@ DECOMP_SIZE_ASSERT(MxAudioManager, 0x30); // GLOBAL: LEGO1 0x10102108 MxS32 MxAudioManager::g_count = 0; -// FUNCTION: LEGO1 0x10029910 -MxS32 MxAudioManager::GetVolume() -{ - return this->m_volume; -} - // FUNCTION: LEGO1 0x100b8d00 MxAudioManager::MxAudioManager() { diff --git a/LEGO1/omni/src/audio/mxaudiopresenter.cpp b/LEGO1/omni/src/audio/mxaudiopresenter.cpp index 1ef74dea..ac634362 100644 --- a/LEGO1/omni/src/audio/mxaudiopresenter.cpp +++ b/LEGO1/omni/src/audio/mxaudiopresenter.cpp @@ -3,15 +3,3 @@ #include "decomp.h" DECOMP_SIZE_ASSERT(MxAudioPresenter, 0x54); - -// FUNCTION: LEGO1 0x1000d260 -MxS32 MxAudioPresenter::GetVolume() -{ - return m_volume; -} - -// FUNCTION: LEGO1 0x1000d270 -void MxAudioPresenter::SetVolume(MxS32 p_volume) -{ - m_volume = p_volume; -} diff --git a/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp index 84b33229..2ad286e1 100644 --- a/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp @@ -20,10 +20,8 @@ void MxLoopingMIDIPresenter::StreamingTickle() return; } - if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; - } + if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) + ProgressTickleState(e_done); } // FUNCTION: LEGO1 0x100c2ae0 @@ -40,7 +38,7 @@ MxResult MxLoopingMIDIPresenter::PutData() { m_criticalSection.Enter(); - if (m_currentTickleState == TickleState_Streaming && m_chunk && !MusicManager()->GetMIDIInitialized()) { + if (m_currentTickleState == e_streaming && m_chunk && !MusicManager()->GetMIDIInitialized()) { SetVolume(((MxDSSound*) m_action)->GetVolume()); MusicManager()->FUN_100c09c0(m_chunk->GetData(), !m_action->GetLoopCount() ? -1 : m_action->GetLoopCount()); } diff --git a/LEGO1/omni/src/audio/mxmidipresenter.cpp b/LEGO1/omni/src/audio/mxmidipresenter.cpp index 95add150..8757e6af 100644 --- a/LEGO1/omni/src/audio/mxmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxmidipresenter.cpp @@ -52,8 +52,7 @@ void MxMIDIPresenter::ReadyTickle() if (chunk) { m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -62,19 +61,15 @@ void MxMIDIPresenter::StartingTickle() { MxStreamChunk* chunk = CurrentChunk(); - if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; - } + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) + ProgressTickleState(e_streaming); } // FUNCTION: LEGO1 0x100c2910 void MxMIDIPresenter::StreamingTickle() { - if (m_chunk) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; - } + if (m_chunk) + ProgressTickleState(e_done); else m_chunk = NextChunk(); } @@ -97,7 +92,7 @@ MxResult MxMIDIPresenter::PutData() { m_criticalSection.Enter(); - if (m_currentTickleState == TickleState_Streaming && m_chunk && !MusicManager()->GetMIDIInitialized()) { + if (m_currentTickleState == e_streaming && m_chunk && !MusicManager()->GetMIDIInitialized()) { SetVolume(((MxDSSound*) m_action)->GetVolume()); if (MusicManager()->FUN_100c09c0(m_chunk->GetData(), 1)) diff --git a/LEGO1/omni/src/audio/mxmusicpresenter.cpp b/LEGO1/omni/src/audio/mxmusicpresenter.cpp index dc2f4b7f..437cd52d 100644 --- a/LEGO1/omni/src/audio/mxmusicpresenter.cpp +++ b/LEGO1/omni/src/audio/mxmusicpresenter.cpp @@ -27,7 +27,7 @@ void MxMusicPresenter::Init() void MxMusicPresenter::Destroy(MxBool p_fromDestructor) { if (MusicManager()) { - MusicManager()->RemovePresenter(*this); + MusicManager()->UnregisterPresenter(*this); } m_criticalSection.Enter(); @@ -46,7 +46,7 @@ MxResult MxMusicPresenter::AddToManager() if (MusicManager()) { result = SUCCESS; - MusicManager()->AddPresenter(*this); + MusicManager()->RegisterPresenter(*this); } return result; diff --git a/LEGO1/omni/src/audio/mxsoundpresenter.cpp b/LEGO1/omni/src/audio/mxsoundpresenter.cpp index 1065fc99..b0376331 100644 --- a/LEGO1/omni/src/audio/mxsoundpresenter.cpp +++ b/LEGO1/omni/src/audio/mxsoundpresenter.cpp @@ -5,23 +5,11 @@ DECOMP_SIZE_ASSERT(MxSoundPresenter, 0x54) -// FUNCTION: LEGO1 0x1000d430 -MxSoundPresenter::~MxSoundPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000d490 -void MxSoundPresenter::Destroy() -{ - Destroy(FALSE); -} - // FUNCTION: LEGO1 0x100b1a50 void MxSoundPresenter::Destroy(MxBool p_fromDestructor) { if (MSoundManager()) - MSoundManager()->RemovePresenter(*this); + MSoundManager()->UnregisterPresenter(*this); this->m_criticalSection.Enter(); MxMediaPresenter::Init(); @@ -38,7 +26,7 @@ MxResult MxSoundPresenter::AddToManager() if (MSoundManager()) { ret = SUCCESS; - MSoundManager()->AddPresenter(*this); + MSoundManager()->RegisterPresenter(*this); } return ret; diff --git a/LEGO1/omni/src/audio/mxwavepresenter.cpp b/LEGO1/omni/src/audio/mxwavepresenter.cpp index d77ccac2..831e0043 100644 --- a/LEGO1/omni/src/audio/mxwavepresenter.cpp +++ b/LEGO1/omni/src/audio/mxwavepresenter.cpp @@ -11,24 +11,6 @@ DECOMP_SIZE_ASSERT(MxWavePresenter, 0x6c); DECOMP_SIZE_ASSERT(MxWavePresenter::WaveFormat, 0x1c); -// FUNCTION: LEGO1 0x1000d640 -MxWavePresenter::~MxWavePresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000d6a0 -void MxWavePresenter::Destroy() -{ - Destroy(FALSE); -} - -// FUNCTION: LEGO1 0x1000d6b0 -MxBool MxWavePresenter::IsPaused() -{ - return m_paused; -} - // FUNCTION: LEGO1 0x100b1ad0 void MxWavePresenter::Init() { @@ -104,7 +86,7 @@ void MxWavePresenter::WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length) } if (dwStatus != DSBSTATUS_BUFFERLOST) { - if (m_action->GetFlags() & MxDSAction::Flag_Looping) { + if (m_action->GetFlags() & MxDSAction::c_looping) { m_writtenChunks++; m_lockSize = p_length; } @@ -117,7 +99,7 @@ void MxWavePresenter::WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length) DS_OK) { memcpy(pvAudioPtr1, p_audioPtr, p_length); - if (m_lockSize > p_length && !(m_action->GetFlags() & MxDSAction::Flag_Looping)) { + if (m_lockSize > p_length && !(m_action->GetFlags() & MxDSAction::c_looping)) { memset((MxU8*) pvAudioPtr1 + p_length, m_silenceData, m_lockSize - p_length); } @@ -136,8 +118,7 @@ void MxWavePresenter::ReadyTickle() memcpy(m_waveFormat, chunk->GetData(), chunk->GetLength()); m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -175,7 +156,7 @@ void MxWavePresenter::StartingTickle() else desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME; - if (m_action->GetFlags() & MxDSAction::Flag_Looping) + if (m_action->GetFlags() & MxDSAction::c_looping) desc.dwBufferBytes = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec * (m_action->GetDuration() / m_action->GetLoopCount()) / 1000; else @@ -188,8 +169,7 @@ void MxWavePresenter::StartingTickle() } else { SetVolume(((MxDSSound*) m_action)->GetVolume()); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); } } } @@ -198,11 +178,11 @@ void MxWavePresenter::StartingTickle() void MxWavePresenter::StreamingTickle() { if (!m_currentChunk) { - if (!(m_action->GetFlags() & MxDSAction::Flag_Looping)) { + if (!(m_action->GetFlags() & MxDSAction::c_looping)) { MxStreamChunk* chunk = CurrentChunk(); - if (chunk && chunk->GetFlags() & MxDSChunk::Flag_End && !(chunk->GetFlags() & MxDSChunk::Flag_Bit16)) { - chunk->SetFlags(chunk->GetFlags() | MxDSChunk::Flag_Bit16); + if (chunk && chunk->GetFlags() & MxDSChunk::c_end && !(chunk->GetFlags() & MxDSChunk::c_bit16)) { + chunk->SetFlags(chunk->GetFlags() | MxDSChunk::c_bit16); m_currentChunk = new MxStreamChunk; MxU8* data = new MxU8[m_chunkLength]; @@ -212,7 +192,7 @@ void MxWavePresenter::StreamingTickle() m_currentChunk->SetLength(m_chunkLength); m_currentChunk->SetData(data); m_currentChunk->SetTime(chunk->GetTime() + 1000); - m_currentChunk->SetFlags(MxDSChunk::Flag_Bit1); + m_currentChunk->SetFlags(MxDSChunk::c_bit1); } } @@ -228,7 +208,7 @@ void MxWavePresenter::DoneTickle() m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor); MxS8 playedChunks = dwCurrentPlayCursor / m_chunkLength; - if (m_action->GetFlags() & MxDSAction::Flag_Bit7 || m_action->GetFlags() & MxDSAction::Flag_Looping || + if (m_action->GetFlags() & MxDSAction::c_bit7 || m_action->GetFlags() & MxDSAction::c_looping || m_writtenChunks != playedChunks || m_lockSize + (m_chunkLength * playedChunks) <= dwCurrentPlayCursor) MxMediaPresenter::DoneTickle(); } @@ -251,7 +231,7 @@ MxResult MxWavePresenter::PutData() if (IsEnabled()) { switch (m_currentTickleState) { - case TickleState_Streaming: + case e_streaming: if (m_currentChunk && FUN_100b1ba0()) { WriteToSoundBuffer(m_currentChunk->GetData(), m_currentChunk->GetLength()); m_subscriber->DestroyChunk(m_currentChunk); @@ -265,7 +245,7 @@ MxResult MxWavePresenter::PutData() m_started = TRUE; } break; - case TickleState_Repeating: + case e_repeating: if (m_started) break; @@ -359,13 +339,13 @@ void MxWavePresenter::Resume() if (m_paused) { if (m_dsBuffer && m_started) { switch (m_currentTickleState) { - case TickleState_Streaming: + case e_streaming: m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING); break; - case TickleState_Repeating: + case e_repeating: m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1); break; - case TickleState_Done: + case e_done: m_dsBuffer->Play(0, 0, 0); } } diff --git a/LEGO1/omni/src/common/mxatomid.cpp b/LEGO1/omni/src/common/mxatomid.cpp index ae57c820..6c400eed 100644 --- a/LEGO1/omni/src/common/mxatomid.cpp +++ b/LEGO1/omni/src/common/mxatomid.cpp @@ -55,7 +55,7 @@ MxAtomId& MxAtomId::operator=(const MxAtomId& p_atomId) Destroy(); if (p_atomId.m_internal && MxOmni::GetInstance() && AtomIdCounterSet()) { - MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, LookupMode_Exact); + MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, e_exact); counter->Inc(); } @@ -71,11 +71,11 @@ MxAtomIdCounter* MxAtomId::GetCounter(const char* p_str, LookupMode p_mode) MxAtomIdCounter* counter = new MxAtomIdCounter(p_str); switch (p_mode) { - case LookupMode_LowerCase: - case LookupMode_LowerCase2: + case e_lowerCase: + case e_lowerCase2: counter->GetKey()->ToLowerCase(); break; - case LookupMode_UpperCase: + case e_upperCase: counter->GetKey()->ToUpperCase(); break; } diff --git a/LEGO1/omni/src/common/mxcompositepresenter.cpp b/LEGO1/omni/src/common/mxcompositepresenter.cpp index d22c979d..5c5b612e 100644 --- a/LEGO1/omni/src/common/mxcompositepresenter.cpp +++ b/LEGO1/omni/src/common/mxcompositepresenter.cpp @@ -8,14 +8,6 @@ DECOMP_SIZE_ASSERT(MxCompositePresenter, 0x4c); -// FUNCTION: LEGO1 0x1000caf0 -MxBool MxCompositePresenter::VTable0x64(undefined4 p_undefined) -{ - if (m_compositePresenter) - return m_compositePresenter->VTable0x64(p_undefined); - return TRUE; -} - // FUNCTION: LEGO1 0x100b60b0 MxCompositePresenter::MxCompositePresenter() { @@ -120,7 +112,7 @@ MxLong MxCompositePresenter::Notify(MxParam& p_param) case c_notificationEndAction: VTable0x58((MxEndActionNotificationParam&) p_param); break; - case MXPRESENTER_NOTIFICATION: + case c_notificationPresenter: VTable0x5c((MxNotificationParam&) p_param); } @@ -163,8 +155,8 @@ void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param) else { if (m_action->IsA("MxDSSerialAction") && it != m_list.end()) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); } } } @@ -179,8 +171,8 @@ void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param) if (*it == presenter) { m_list.erase(it++); - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); MxDSActionList* actions = ((MxDSMultiAction*) m_action)->GetActionList(); MxDSActionListCursor cursor(actions); @@ -194,8 +186,8 @@ void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param) else { if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); } } @@ -218,8 +210,8 @@ void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter) } else if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); } return; } @@ -229,14 +221,13 @@ void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter) // FUNCTION: LEGO1 0x100b6bc0 void MxCompositePresenter::SetTickleState(TickleState p_tickleState) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = p_tickleState; + ProgressTickleState(p_tickleState); for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { MxPresenter* presenter = *it; presenter->SetTickleState(p_tickleState); - if (m_action->IsA("MxDSSerialAction") && p_tickleState == TickleState_Ready) + if (m_action->IsA("MxDSSerialAction") && p_tickleState == e_ready) return; } } diff --git a/LEGO1/omni/src/common/mxcore.cpp b/LEGO1/omni/src/common/mxcore.cpp index 237ed1da..1266a1cb 100644 --- a/LEGO1/omni/src/common/mxcore.cpp +++ b/LEGO1/omni/src/common/mxcore.cpp @@ -2,12 +2,6 @@ #include "define.h" -// FUNCTION: LEGO1 0x10001f70 -MxResult MxCore::Tickle() -{ - return SUCCESS; -} - // FUNCTION: LEGO1 0x100ae1a0 MxCore::MxCore() { diff --git a/LEGO1/omni/src/common/mxmediamanager.cpp b/LEGO1/omni/src/common/mxmediamanager.cpp index e9b4fe6d..778d7f86 100644 --- a/LEGO1/omni/src/common/mxmediamanager.cpp +++ b/LEGO1/omni/src/common/mxmediamanager.cpp @@ -75,7 +75,7 @@ MxResult MxMediaManager::Tickle() } // FUNCTION: LEGO1 0x100b88c0 -void MxMediaManager::AddPresenter(MxPresenter& p_presenter) +void MxMediaManager::RegisterPresenter(MxPresenter& p_presenter) { MxAutoLocker lock(&this->m_criticalSection); @@ -83,7 +83,7 @@ void MxMediaManager::AddPresenter(MxPresenter& p_presenter) } // FUNCTION: LEGO1 0x100b8980 -void MxMediaManager::RemovePresenter(MxPresenter& p_presenter) +void MxMediaManager::UnregisterPresenter(MxPresenter& p_presenter) { MxAutoLocker lock(&this->m_criticalSection); MxPresenterListCursor cursor(this->m_presenters); diff --git a/LEGO1/omni/src/common/mxmediapresenter.cpp b/LEGO1/omni/src/common/mxmediapresenter.cpp index a9383e4d..2abc5007 100644 --- a/LEGO1/omni/src/common/mxmediapresenter.cpp +++ b/LEGO1/omni/src/common/mxmediapresenter.cpp @@ -11,18 +11,6 @@ DECOMP_SIZE_ASSERT(MxMediaPresenter, 0x50); DECOMP_SIZE_ASSERT(MxStreamChunkList, 0x18); DECOMP_SIZE_ASSERT(MxStreamChunkListCursor, 0x10); -// FUNCTION: LEGO1 0x1000c550 -MxMediaPresenter::~MxMediaPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000c5b0 -void MxMediaPresenter::Destroy() -{ - Destroy(FALSE); -} - // FUNCTION: LEGO1 0x100b54e0 void MxMediaPresenter::Init() { @@ -72,13 +60,12 @@ MxStreamChunk* MxMediaPresenter::CurrentChunk() if (m_subscriber) { chunk = m_subscriber->CurrentChunk(); - if (chunk && chunk->GetFlags() & MxDSChunk::Flag_Bit3) { - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); + if (chunk && chunk->GetFlags() & MxDSChunk::c_bit3) { + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_bit7); m_subscriber->NextChunk(); m_subscriber->DestroyChunk(chunk); chunk = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } } @@ -93,12 +80,11 @@ MxStreamChunk* MxMediaPresenter::NextChunk() if (m_subscriber) { chunk = m_subscriber->NextChunk(); - if (chunk && chunk->GetFlags() & MxDSChunk::Flag_Bit3) { - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); + if (chunk && chunk->GetFlags() & MxDSChunk::c_bit3) { + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_bit7); m_subscriber->DestroyChunk(chunk); chunk = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } } @@ -112,7 +98,7 @@ MxResult MxMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAct MxAutoLocker lock(&m_criticalSection); if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) { - if (m_action->GetFlags() & MxDSAction::Flag_Looping) { + if (m_action->GetFlags() & MxDSAction::c_looping) { m_loopingChunks = new MxStreamChunkList; m_loopingChunkCursor = new MxStreamChunkListCursor(m_loopingChunks); @@ -145,10 +131,9 @@ void MxMediaPresenter::EndAction() m_currentChunk = NULL; - if (m_action->GetFlags() & MxDSAction::Flag_World && - (!m_compositePresenter || !m_compositePresenter->VTable0x64(2))) { + if (m_action->GetFlags() & MxDSAction::c_world && (!m_compositePresenter || !m_compositePresenter->VTable0x64(2))) { MxPresenter::Enable(FALSE); - SetTickleState(TickleState_Idle); + SetTickleState(e_idle); } else { MxDSAction* action = m_action; @@ -192,13 +177,12 @@ void MxMediaPresenter::StreamingTickle() m_currentChunk = NextChunk(); if (m_currentChunk) { - if (m_currentChunk->GetFlags() & MxDSChunk::Flag_End) { + if (m_currentChunk->GetFlags() & MxDSChunk::c_end) { m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); } - else if (m_action->GetFlags() & MxDSAction::Flag_Looping) { + else if (m_action->GetFlags() & MxDSAction::c_looping) { LoopChunk(m_currentChunk); if (!IsEnabled()) { @@ -220,16 +204,12 @@ void MxMediaPresenter::RepeatingTickle() if (m_currentChunk) { MxLong time = m_currentChunk->GetTime(); - if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) + ProgressTickleState(e_unk5); } else { - if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) + ProgressTickleState(e_unk5); } } } @@ -238,7 +218,7 @@ void MxMediaPresenter::RepeatingTickle() void MxMediaPresenter::DoneTickle() { m_previousTickleStates |= 1 << m_currentTickleState; - m_currentTickleState = TickleState_Idle; + m_currentTickleState = e_idle; EndAction(); } @@ -265,13 +245,13 @@ void MxMediaPresenter::Enable(MxBool p_enable) if (p_enable) { MxLong time = Timer()->GetTime(); m_action->SetUnknown90(time); - SetTickleState(TickleState_Repeating); + SetTickleState(e_repeating); } else { if (m_loopingChunkCursor) m_loopingChunkCursor->Reset(); m_currentChunk = NULL; - SetTickleState(TickleState_Done); + SetTickleState(e_done); } } } diff --git a/LEGO1/omni/src/common/mxobjectfactory.cpp b/LEGO1/omni/src/common/mxobjectfactory.cpp index a4e5efd1..93f2e0a0 100644 --- a/LEGO1/omni/src/common/mxobjectfactory.cpp +++ b/LEGO1/omni/src/common/mxobjectfactory.cpp @@ -19,7 +19,7 @@ DECOMP_SIZE_ASSERT(MxObjectFactory, 0x38); // 100af1db // FUNCTION: LEGO1 0x100b0d80 MxObjectFactory::MxObjectFactory() { -#define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact); +#define X(V) this->m_id##V = MxAtomId(#V, e_exact); FOR_MXOBJECTFACTORY_OBJECTS(X) #undef X } @@ -28,7 +28,7 @@ MxObjectFactory::MxObjectFactory() MxCore* MxObjectFactory::Create(const char* p_name) { MxCore* object = NULL; - MxAtomId atom(p_name, LookupMode_Exact); + MxAtomId atom(p_name, e_exact); if (0) { } diff --git a/LEGO1/omni/src/common/mxpresenter.cpp b/LEGO1/omni/src/common/mxpresenter.cpp index 0595aee7..9d074278 100644 --- a/LEGO1/omni/src/common/mxpresenter.cpp +++ b/LEGO1/omni/src/common/mxpresenter.cpp @@ -18,101 +18,10 @@ DECOMP_SIZE_ASSERT(MxPresenter, 0x40); -// FUNCTION: LEGO1 0x1000be30 -void MxPresenter::VTable0x14() -{ -} - -// FUNCTION: LEGO1 0x1000be40 -void MxPresenter::ReadyTickle() -{ - ParseExtra(); - - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; -} - -// FUNCTION: LEGO1 0x1000be60 -void MxPresenter::StartingTickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; -} - -// FUNCTION: LEGO1 0x1000be80 -void MxPresenter::StreamingTickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; -} - -// FUNCTION: LEGO1 0x1000bea0 -void MxPresenter::RepeatingTickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; -} - -// FUNCTION: LEGO1 0x1000bec0 -void MxPresenter::Unk5Tickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; -} - -// FUNCTION: LEGO1 0x1000bee0 -void MxPresenter::DoneTickle() -{ - m_previousTickleStates |= 1 << m_currentTickleState; - m_currentTickleState = TickleState_Idle; -} - -// FUNCTION: LEGO1 0x1000bf00 -MxPresenter::~MxPresenter() -{ -} - -// FUNCTION: LEGO1 0x1000bf70 -MxResult MxPresenter::AddToManager() -{ - return SUCCESS; -} - -// FUNCTION: LEGO1 0x1000bf80 -void MxPresenter::Destroy() -{ - Init(); -} - -// FUNCTION: LEGO1 0x1000bf90 -void MxPresenter::SetTickleState(TickleState p_tickleState) -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = p_tickleState; -} - -// FUNCTION: LEGO1 0x1000bfb0 -MxBool MxPresenter::HasTickleStatePassed(TickleState p_tickleState) -{ - return m_previousTickleStates & (1 << (unsigned char) p_tickleState); -} - -// FUNCTION: LEGO1 0x1000bfc0 -MxResult MxPresenter::PutData() -{ - return SUCCESS; -} - -// FUNCTION: LEGO1 0x1000bfd0 -MxBool MxPresenter::IsHit(MxS32 p_x, MxS32 p_y) -{ - return FALSE; -} - // FUNCTION: LEGO1 0x100b4d50 void MxPresenter::Init() { - m_currentTickleState = TickleState_Idle; + m_currentTickleState = e_idle; m_action = NULL; m_location = MxPoint32(0, 0); m_displayZ = 0; @@ -127,13 +36,12 @@ MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action) this->m_action = p_action; - const Vector3Data& location = this->m_action->GetLocation(); + const Mx3DPointFloat& location = this->m_action->GetLocation(); MxS32 previousTickleState = this->m_currentTickleState; this->m_location = MxPoint32(this->m_action->GetLocation()[0], this->m_action->GetLocation()[1]); this->m_displayZ = this->m_action->GetLocation()[2]; - this->m_previousTickleStates |= 1 << (unsigned char) previousTickleState; - this->m_currentTickleState = TickleState_Ready; + ProgressTickleState(e_ready); return SUCCESS; } @@ -162,7 +70,7 @@ void MxPresenter::EndAction() this->m_action = NULL; MxS32 previousTickleState = 1 << m_currentTickleState; this->m_previousTickleStates |= previousTickleState; - this->m_currentTickleState = TickleState_Idle; + this->m_currentTickleState = e_idle; } // FUNCTION: LEGO1 0x100b4fc0 @@ -188,7 +96,7 @@ void MxPresenter::ParseExtra() MxS32 val = token ? atoi(token) : 0; MxEntity* result = MxOmni::GetInstance()->FindWorld(buf, val, this); - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_World); + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_world); if (result) SendToCompositePresenter(MxOmni::GetInstance()); @@ -204,11 +112,11 @@ void MxPresenter::SendToCompositePresenter(MxOmni* p_omni) #ifdef COMPAT_MODE { - MxNotificationParam param(MXPRESENTER_NOTIFICATION, this); + MxNotificationParam param(c_notificationPresenter, this); NotificationManager()->Send(m_compositePresenter, ¶m); } #else - NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(MXPRESENTER_NOTIFICATION, this)); + NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(c_notificationPresenter, this)); #endif m_action->SetOrigin(p_omni ? p_omni : MxOmni::GetInstance()); @@ -222,32 +130,32 @@ MxResult MxPresenter::Tickle() MxAutoLocker lock(&this->m_criticalSection); switch (this->m_currentTickleState) { - case TickleState_Ready: + case e_ready: this->ReadyTickle(); - if (m_currentTickleState != TickleState_Starting) + if (m_currentTickleState != e_starting) break; - case TickleState_Starting: + case e_starting: this->StartingTickle(); - if (m_currentTickleState != TickleState_Streaming) + if (m_currentTickleState != e_streaming) break; - case TickleState_Streaming: + case e_streaming: this->StreamingTickle(); - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) break; - case TickleState_Repeating: + case e_repeating: this->RepeatingTickle(); - if (m_currentTickleState != TickleState_unk5) + if (m_currentTickleState != e_unk5) break; - case TickleState_unk5: + case e_unk5: this->Unk5Tickle(); - if (m_currentTickleState != TickleState_Done) + if (m_currentTickleState != e_done) break; - case TickleState_Done: + case e_done: this->DoneTickle(); default: break; @@ -263,9 +171,9 @@ void MxPresenter::Enable(MxBool p_enable) MxU32 flags = this->m_action->GetFlags(); if (p_enable) - this->m_action->SetFlags(flags | MxDSAction::Flag_Enabled); + this->m_action->SetFlags(flags | MxDSAction::c_enabled); else - this->m_action->SetFlags(flags & ~MxDSAction::Flag_Enabled); + this->m_action->SetFlags(flags & ~MxDSAction::c_enabled); } } @@ -277,7 +185,7 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) if (!name || strlen(name) == 0) { switch (p_action.GetType()) { - case MxDSType_Anim: + case MxDSObject::e_anim: format = ((MxDSAnim&) p_action).GetMediaFormat(); switch (format) { case FOURCC(' ', 'F', 'L', 'C'): @@ -289,7 +197,7 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) } break; - case MxDSType_Sound: + case MxDSObject::e_sound: format = ((MxDSSound&) p_action).GetMediaFormat(); switch (format) { case FOURCC(' ', 'M', 'I', 'D'): @@ -301,17 +209,17 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) } break; - case MxDSType_SerialAction: - case MxDSType_ParallelAction: - case MxDSType_SelectAction: + case MxDSObject::e_serialAction: + case MxDSObject::e_parallelAction: + case MxDSObject::e_selectAction: name = "MxCompositePresenter"; break; - case MxDSType_Event: + case MxDSObject::e_event: name = "MxEventPresenter"; break; - case MxDSType_Still: + case MxDSObject::e_still: name = "MxStillPresenter"; break; } @@ -321,7 +229,7 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) } // FUNCTION: LEGO1 0x100b5410 -MxEntity* MxPresenter::CreateEntityBackend(const char* p_name) +MxEntity* MxPresenter::CreateEntity(const char* p_name) { char buffer[512]; char buffer2[512]; @@ -344,5 +252,5 @@ MxEntity* MxPresenter::CreateEntityBackend(const char* p_name) // FUNCTION: LEGO1 0x100b54c0 MxBool MxPresenter::IsEnabled() { - return this->m_action && this->m_action->GetFlags() & MxDSAction::Flag_Enabled; + return this->m_action && this->m_action->GetFlags() & MxDSAction::c_enabled; } diff --git a/LEGO1/omni/src/common/mxutil.cpp b/LEGO1/omni/src/common/mxutil.cpp index 538368d1..ababdc02 100644 --- a/LEGO1/omni/src/common/mxutil.cpp +++ b/LEGO1/omni/src/common/mxutil.cpp @@ -1,6 +1,9 @@ #include "mxutil.h" +#include "mxdsaction.h" +#include "mxdsactionlist.h" #include "mxdsfile.h" +#include "mxdsmultiaction.h" #include "mxdsobject.h" #include "mxrect32.h" @@ -112,6 +115,21 @@ void SetOmniUserMessage(void (*p_userMsg)(const char*, int)) g_omniUserMessage = p_userMsg; } +// FUNCTION: LEGO1 0x100b7220 +void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags) +{ + p_action->SetFlags(!p_setFlags ? p_action->GetFlags() & ~p_newFlags : p_action->GetFlags() | p_newFlags); + + if (p_action->IsA("MxDSMultiAction")) { + MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList()); + MxDSAction* action; + + while (cursor.Next(action)) { + FUN_100b7220(action, p_newFlags, p_setFlags); + } + } +} + // Should probably be somewhere else // FUNCTION: LEGO1 0x100c0280 MxDSObject* CreateStreamObject(MxDSFile* p_file, MxS16 p_ofs) diff --git a/LEGO1/omni/src/common/mxvariable.cpp b/LEGO1/omni/src/common/mxvariable.cpp index a60051fd..7b0a46c1 100644 --- a/LEGO1/omni/src/common/mxvariable.cpp +++ b/LEGO1/omni/src/common/mxvariable.cpp @@ -4,21 +4,3 @@ #include "mxstring.h" DECOMP_SIZE_ASSERT(MxVariable, 0x24) - -// FUNCTION: LEGO1 0x1003bea0 -MxString* MxVariable::GetValue() -{ - return &m_value; -} - -// FUNCTION: LEGO1 0x1003beb0 -void MxVariable::SetValue(const char* p_value) -{ - m_value = p_value; -} - -// FUNCTION: LEGO1 0x1003bec0 -void MxVariable::Destroy() -{ - delete this; -} diff --git a/LEGO1/omni/src/common/mxvariabletable.cpp b/LEGO1/omni/src/common/mxvariabletable.cpp index d7c6f54f..9503ee5e 100644 --- a/LEGO1/omni/src/common/mxvariabletable.cpp +++ b/LEGO1/omni/src/common/mxvariabletable.cpp @@ -50,6 +50,8 @@ void MxVariableTable::SetVariable(MxVariable* p_var) // FUNCTION: LEGO1 0x100b78f0 const char* MxVariableTable::GetVariable(const char* p_key) { + // STRING: ISLE 0x41008c + // STRING: LEGO1 0x100f01d4 const char* value = ""; MxHashTableCursor cursor(this); MxVariable* var = new MxVariable(p_key); diff --git a/LEGO1/omni/src/entity/mxentity.cpp b/LEGO1/omni/src/entity/mxentity.cpp index 1f507257..2edc65f6 100644 --- a/LEGO1/omni/src/entity/mxentity.cpp +++ b/LEGO1/omni/src/entity/mxentity.cpp @@ -1,22 +1,3 @@ #include "mxentity.h" DECOMP_SIZE_ASSERT(MxEntity, 0x10) - -// FUNCTION: LEGO1 0x10001070 -MxResult MxEntity::Create(MxS32 p_id, const MxAtomId& p_atom) -{ - this->m_mxEntityId = p_id; - this->m_atom = p_atom; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x1000c110 -MxEntity::~MxEntity() -{ -} - -// FUNCTION: LEGO1 0x1001d190 -MxEntity::MxEntity() -{ - this->m_mxEntityId = -1; -} diff --git a/LEGO1/omni/src/event/mxeventpresenter.cpp b/LEGO1/omni/src/event/mxeventpresenter.cpp index 6a0a0cbd..03b0de14 100644 --- a/LEGO1/omni/src/event/mxeventpresenter.cpp +++ b/LEGO1/omni/src/event/mxeventpresenter.cpp @@ -33,7 +33,7 @@ MxResult MxEventPresenter::AddToManager() if (EventManager()) { ret = SUCCESS; - EventManager()->AddPresenter(*this); + EventManager()->RegisterPresenter(*this); } return ret; @@ -43,7 +43,7 @@ MxResult MxEventPresenter::AddToManager() void MxEventPresenter::Destroy() { if (EventManager()) - EventManager()->RemovePresenter(*this); + EventManager()->UnregisterPresenter(*this); m_criticalSection.Enter(); @@ -71,20 +71,17 @@ void MxEventPresenter::ReadyTickle() CopyData(chunk); m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } // FUNCTION: LEGO1 0x100c2eb0 void MxEventPresenter::StartingTickle() { - MxStreamChunk* chunk = NextChunk(); + MxStreamChunk* chunk = CurrentChunk(); - if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; - } + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) + ProgressTickleState(e_streaming); } // FUNCTION: LEGO1 0x100c2ef0 @@ -93,8 +90,8 @@ MxResult MxEventPresenter::PutData() MxAutoLocker lock(&m_criticalSection); if (IsEnabled()) { - if (m_currentTickleState >= TickleState_Streaming && - (m_currentTickleState <= TickleState_Repeating || m_currentTickleState == TickleState_Done)) { + if (m_currentTickleState >= e_streaming && + (m_currentTickleState <= e_repeating || m_currentTickleState == e_done)) { if (m_currentChunk && m_currentChunk->GetLength()) { if (m_data[12] == 2) { const char* data = (const char*) m_currentChunk->GetData(); @@ -106,7 +103,7 @@ MxResult MxEventPresenter::PutData() variableTable->SetVariable(key, value); } - if (m_currentTickleState == TickleState_Streaming) + if (m_currentTickleState == e_streaming) m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; } diff --git a/LEGO1/omni/src/main/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp index 377ba481..6df6d009 100644 --- a/LEGO1/omni/src/main/mxomni.cpp +++ b/LEGO1/omni/src/main/mxomni.cpp @@ -27,26 +27,6 @@ MxBool g_use3dSound; // GLOBAL: LEGO1 0x101015b0 MxOmni* MxOmni::g_instance = NULL; -// FUNCTION: LEGO1 0x100159e0 -void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last) -{ - MxDSAction action; - - action.SetAtomId(*p_id); - action.SetUnknown24(-2); - - for (MxS32 first = p_first, last = p_last; first <= last; first++) { - action.SetObjectId(first); - DeleteObject(action); - } -} - -// FUNCTION: LEGO1 0x10058a90 -MxBool MxOmni::IsTimerRunning() -{ - return m_timerRunning; -} - // FUNCTION: LEGO1 0x100acea0 MxObjectFactory* ObjectFactory() { @@ -113,6 +93,12 @@ MxEventManager* EventManager() return MxOmni::GetInstance()->GetEventManager(); } +// FUNCTION: LEGO1 0x100acf50 +MxResult Start(MxDSAction* p_dsAction) +{ + return MxOmni::GetInstance()->Start(p_dsAction); +} + // FUNCTION: LEGO1 0x100acf70 void DeleteObject(MxDSAction& p_dsAction) { diff --git a/LEGO1/omni/src/notify/mxactionnotificationparam.cpp b/LEGO1/omni/src/notify/mxactionnotificationparam.cpp index 5573677f..c5f816e7 100644 --- a/LEGO1/omni/src/notify/mxactionnotificationparam.cpp +++ b/LEGO1/omni/src/notify/mxactionnotificationparam.cpp @@ -3,18 +3,6 @@ DECOMP_SIZE_ASSERT(MxActionNotificationParam, 0x14) DECOMP_SIZE_ASSERT(MxEndActionNotificationParam, 0x14) -// FUNCTION: LEGO1 0x100510c0 -MxNotificationParam* MxActionNotificationParam::Clone() -{ - return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc); -} - -// FUNCTION: LEGO1 0x10051270 -MxNotificationParam* MxEndActionNotificationParam::Clone() -{ - return new MxEndActionNotificationParam(c_notificationEndAction, this->m_sender, this->m_action, this->m_realloc); -} - // FUNCTION: LEGO1 0x100b0300 MxNotificationParam* MxStartActionNotificationParam::Clone() { diff --git a/LEGO1/omni/src/notify/mxnotificationparam.cpp b/LEGO1/omni/src/notify/mxnotificationparam.cpp index 0797c9f1..cb15a2df 100644 --- a/LEGO1/omni/src/notify/mxnotificationparam.cpp +++ b/LEGO1/omni/src/notify/mxnotificationparam.cpp @@ -3,9 +3,3 @@ #include "decomp.h" DECOMP_SIZE_ASSERT(MxNotificationParam, 0xc); - -// FUNCTION: LEGO1 0x10010390 -MxNotificationParam* MxNotificationParam::Clone() -{ - return new MxNotificationParam(m_type, m_sender); -} diff --git a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp index c0708acc..5833d18f 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp @@ -129,7 +129,7 @@ void MxDiskStreamController::FUN_100c7980() if (m_unk0x3c.size() && m_unk0x8c < m_provider->GetStreamBuffersNum()) { buffer = new MxDSBuffer(); - if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBufferType_Chunk) != SUCCESS) { + if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBuffer::e_chunk) != SUCCESS) { if (buffer) delete buffer; return; @@ -213,10 +213,10 @@ void MxDiskStreamController::FUN_100c7cb0(MxDSStreamingAction* p_action) void MxDiskStreamController::FUN_100c7ce0(MxDSBuffer* p_buffer) { switch (p_buffer->GetMode()) { - case MxDSBufferType_Chunk: + case MxDSBuffer::e_chunk: m_unk0x8c--; - case MxDSBufferType_Allocate: - case MxDSBufferType_Unknown: + case MxDSBuffer::e_allocate: + case MxDSBuffer::e_unknown: delete p_buffer; break; } @@ -301,6 +301,23 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) return SUCCESS; } +// FUNCTION: LEGO1 0x100c8120 +void MxDiskStreamController::FUN_100c8120(MxDSAction* p_action) +{ + VTable0x30(p_action); + + if (m_provider) { + m_provider->VTable0x20(p_action); + } + + while (TRUE) { + MxDSAction* found = m_unk0x54.Find(p_action, TRUE); + if (!found) + break; + delete found; + } +} + // FUNCTION: LEGO1 0x100c8160 MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action) { diff --git a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp index b9ed63d0..7b4b6ef5 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp @@ -5,6 +5,7 @@ #include "mxdsbuffer.h" #include "mxdsstreamingaction.h" #include "mxomni.h" +#include "mxramstreamprovider.h" #include "mxstreamcontroller.h" #include "mxstring.h" #include "mxthread.h" @@ -173,7 +174,7 @@ MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action) if (!buffer) return FAILURE; - if (buffer->AllocateBuffer(GetFileSize(), MxDSBufferType_Allocate) != SUCCESS) { + if (buffer->AllocateBuffer(GetFileSize(), MxDSBuffer::e_allocate) != SUCCESS) { delete buffer; return FAILURE; } @@ -214,18 +215,20 @@ void MxDiskStreamProvider::PerformWork() } } + MxDSBuffer* buffer; + { MxAutoLocker lock(&m_criticalSection); if (!m_list.PopFrontStreamingAction(streamingAction)) - return; + goto done; } if (streamingAction->GetUnknowna0()->GetWriteOffset() < 0x20000) { g_unk0x10102878--; } - MxDSBuffer* buffer = streamingAction->GetUnknowna0(); + buffer = streamingAction->GetUnknowna0(); if (m_pFile->GetPosition() == streamingAction->GetBufferOffset() || m_pFile->Seek(streamingAction->GetBufferOffset(), 0) == 0) { @@ -250,6 +253,7 @@ void MxDiskStreamProvider::PerformWork() } } +done: if (streamingAction) { controller->FUN_100c8670(streamingAction); } @@ -267,10 +271,105 @@ MxBool MxDiskStreamProvider::FUN_100d1af0(MxDSStreamingAction* p_action) return TRUE; } -// STUB: LEGO1 0x100d1b20 +// FUNCTION: LEGO1 0x100d1b20 MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) { - return FAILURE; + MxDSBuffer* buffer = new MxDSBuffer(); + + 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) + return FAILURE; + + delete buffer; + return FAILURE; + } + + MxDSBuffer* buffer2 = p_action->GetUnknowna4(); + MxU8** pdata; + MxU8* data; + + if (buffer2 == NULL) { + pdata = buffer->GetBufferRef(); + + memcpy( + data = *pdata, + p_action->GetUnknowna0()->GetBuffer() - p_action->GetBufferOffset() + p_action->GetUnknown94(), + size + ); + } + else { + buffer->FUN_100c7090(buffer2); + pdata = buffer->GetBufferRef(); + + memcpy( + data = (p_action->GetUnknowna4()->GetWriteOffset() + *pdata), + p_action->GetUnknowna0()->GetBuffer(), + p_action->GetUnknowna0()->GetWriteOffset() + ); + + delete p_action->GetUnknowna4(); + } + + p_action->SetUnknowna4(buffer); + + while (data) { + if (*MxDSChunk::IntoType(data) != FOURCC('M', 'x', 'O', 'b')) { + if (*MxStreamChunk::IntoTime(data) > p_action->GetUnknown9c()) { + *MxDSChunk::IntoType(data) = FOURCC('p', 'a', 'd', ' '); + + memcpy(data + 8, *pdata, buffer->GetWriteOffset() + *pdata - data - 8); + size = ReadData(*pdata, buffer->GetWriteOffset()); + + MxDSBuffer* buffer3 = new MxDSBuffer(); + if (!buffer3) + return FAILURE; + + if (buffer3->AllocateBuffer(size, MxDSBuffer::e_allocate) == SUCCESS) { + memcpy(buffer3->GetBuffer(), p_action->GetUnknowna4()->GetBuffer(), size); + p_action->GetUnknowna4()->SetMode(MxDSBuffer::e_allocate); + delete p_action->GetUnknowna4(); + + buffer3->SetMode(MxDSBuffer::e_unknown); + p_action->SetUnknowna4(buffer3); + MxDSBuffer* buffer4 = p_action->GetUnknowna0(); + MxU32 unk0x14 = buffer4->GetUnknown14(); + MxU8* data2 = buffer4->GetBuffer(); + + while (TRUE) { + if (*MxStreamChunk::IntoTime(data2) > p_action->GetUnknown9c()) + break; + + data += MxDSChunk::Size(*MxDSChunk::IntoLength(data)); + unk0x14 += MxDSChunk::Size(*MxDSChunk::IntoLength(data)); + } + + p_action->SetUnknown94(unk0x14); + p_action->SetBufferOffset(p_action->GetUnknowna0()->GetUnknown14()); + delete p_action->GetUnknowna0(); + p_action->SetUnknowna0(NULL); + ((MxDiskStreamController*) m_pLookup)->FUN_100c7890(p_action); + return SUCCESS; + } + else { + delete buffer3; + return FAILURE; + } + } + } + + data = buffer->FUN_100c6fa0(data); + } + + p_action->SetUnknown94(GetFileSize() + p_action->GetBufferOffset()); + p_action->SetBufferOffset(GetFileSize() + p_action->GetBufferOffset()); + FUN_100d1780(p_action); + return SUCCESS; } // FUNCTION: LEGO1 0x100d1e90 diff --git a/LEGO1/omni/src/stream/mxdsbuffer.cpp b/LEGO1/omni/src/stream/mxdsbuffer.cpp index 5e4b277d..380cc1e0 100644 --- a/LEGO1/omni/src/stream/mxdsbuffer.cpp +++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp @@ -22,7 +22,7 @@ MxDSBuffer::MxDSBuffer() m_unk0x1c = 0; m_writeOffset = 0; m_bytesRemaining = 0; - m_mode = MxDSBufferType_Preallocated; + m_mode = e_preallocated; m_unk0x30 = 0; } @@ -31,12 +31,12 @@ MxDSBuffer::~MxDSBuffer() { if (m_pBuffer != NULL) { switch (m_mode) { - case MxDSBufferType_Allocate: - case MxDSBufferType_Unknown: + case e_allocate: + case e_unknown: delete[] m_pBuffer; break; - case MxDSBufferType_Chunk: { + case e_chunk: { MxU32 offset = m_writeOffset / 1024; MxStreamer* streamer = Streamer(); @@ -77,16 +77,16 @@ MxDSBuffer::~MxDSBuffer() } // FUNCTION: LEGO1 0x100c6640 -MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode) +MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, Type p_mode) { MxResult result = FAILURE; switch (p_mode) { - case MxDSBufferType_Allocate: + case e_allocate: m_pBuffer = new MxU8[p_bufferSize]; break; - case MxDSBufferType_Chunk: { + case e_chunk: { MxStreamer* streamer = Streamer(); switch (p_bufferSize / 1024) { @@ -143,14 +143,14 @@ MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode) } // FUNCTION: LEGO1 0x100c6780 -MxResult MxDSBuffer::SetBufferPointer(MxU32* p_buffer, MxU32 p_size) +MxResult MxDSBuffer::SetBufferPointer(MxU8* p_buffer, MxU32 p_size) { - m_pBuffer = (MxU8*) p_buffer; - m_pIntoBuffer = (MxU8*) p_buffer; - m_pIntoBuffer2 = (MxU8*) p_buffer; + m_pBuffer = p_buffer; + m_pIntoBuffer = p_buffer; + m_pIntoBuffer2 = p_buffer; m_bytesRemaining = p_size; m_writeOffset = p_size; - m_mode = MxDSBufferType_Preallocated; + m_mode = e_preallocated; return SUCCESS; } @@ -291,24 +291,24 @@ MxResult MxDSBuffer::ParseChunk( { MxResult result = SUCCESS; - if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && m_unk0x30->GetUnknowna8() && p_header->GetTime() < 0) { + if (m_unk0x30->GetFlags() & MxDSAction::c_bit3 && m_unk0x30->GetUnknowna8() && p_header->GetTime() < 0) { delete p_header; return SUCCESS; } p_header->SetTime(p_header->GetTime() + m_unk0x30->GetUnknowna8()); - if (p_header->GetFlags() & MxDSChunk::Flag_Split) { - MxU32 length = p_header->GetLength() + MxDSChunk::ReturnE() + 8; + if (p_header->GetFlags() & MxDSChunk::c_split) { + MxU32 length = p_header->GetLength() + MxDSChunk::GetHeaderSize() + 8; MxDSBuffer* buffer = new MxDSBuffer(); - if (buffer && buffer->AllocateBuffer(length, MxDSBufferType_Allocate) == SUCCESS && + if (buffer && buffer->AllocateBuffer(length, e_allocate) == SUCCESS && buffer->CalcBytesRemaining((MxU8*) p_data) == SUCCESS) { *p_streamingAction = new MxDSStreamingAction((MxDSStreamingAction&) *p_action); if (*p_streamingAction) { MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer()); - *flags = p_header->GetFlags() & ~MxDSChunk::Flag_Split; + *flags = p_header->GetFlags() & ~MxDSChunk::c_split; delete p_header; (*p_streamingAction)->SetUnknowna0(buffer); @@ -323,9 +323,9 @@ MxResult MxDSBuffer::ParseChunk( return FAILURE; } else { - if (p_header->GetFlags() & MxDSChunk::Flag_End) { + if (p_header->GetFlags() & MxDSChunk::c_end) { if (m_unk0x30->HasId(p_header->GetObjectId())) { - if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && + if (m_unk0x30->GetFlags() & MxDSAction::c_bit3 && (m_unk0x30->GetLoopCount() > 1 || m_unk0x30->GetDuration() == -1)) { if (p_action->GetObjectId() == p_header->GetObjectId()) { @@ -456,7 +456,7 @@ MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) { MxResult result = FAILURE; - if (m_mode == MxDSBufferType_Allocate && m_bytesRemaining != 0) { + if (m_mode == e_allocate && m_bytesRemaining != 0) { MxU32 bytesRead; MxU8* ptr; @@ -465,15 +465,15 @@ MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) ptr = p_data; } else { - ptr = &p_data[MxStreamChunk::ReturnE() + 8]; - bytesRead = (*(MxU32*) (p_data + 4)) - MxStreamChunk::ReturnE(); + ptr = &p_data[MxStreamChunk::GetHeaderSize() + 8]; + bytesRead = (*(MxU32*) (p_data + 4)) - MxStreamChunk::GetHeaderSize(); } if (bytesRead <= m_bytesRemaining) { memcpy(m_pBuffer + m_writeOffset - m_bytesRemaining, ptr, bytesRead); if (m_writeOffset == m_bytesRemaining) - *(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoLength(m_pBuffer) + MxStreamChunk::ReturnE(); + *(MxU32*) (m_pBuffer + 4) = *MxStreamChunk::IntoLength(m_pBuffer) + MxStreamChunk::GetHeaderSize(); m_bytesRemaining -= bytesRead; result = SUCCESS; @@ -491,3 +491,61 @@ void MxDSBuffer::FUN_100c6f80(MxU32 p_writeOffset) m_pIntoBuffer = m_pBuffer + p_writeOffset; } } + +// FUNCTION: LEGO1 0x100c6fa0 +MxU8* MxDSBuffer::FUN_100c6fa0(MxU8* p_data) +{ + MxU8* current = p_data ? p_data : m_pBuffer; + MxU8* end = m_writeOffset + m_pBuffer - 8; + + while (current <= end) { + switch (*((MxU32*) current)) { + case FOURCC('L', 'I', 'S', 'T'): + case FOURCC('R', 'I', 'F', 'F'): + current += 12; + break; + case FOURCC('M', 'x', 'D', 'a'): + case FOURCC('M', 'x', 'S', 't'): + current += 8; + break; + case FOURCC('M', 'x', 'O', 'b'): + case FOURCC('M', 'x', 'C', 'h'): + 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; + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x100c7090 +MxResult MxDSBuffer::FUN_100c7090(MxDSBuffer* p_buf) +{ + MxResult result = FAILURE; + + if (m_writeOffset >= p_buf->m_writeOffset) { + memcpy(m_pBuffer, p_buf->m_pBuffer, p_buf->m_writeOffset); + result = SUCCESS; + } + + m_unk0x1c = p_buf->m_unk0x1c; + return result; +} + +// FUNCTION: LEGO1 0x100c70d0 +MxResult MxDSBuffer::Append(MxU8* p_buffer1, MxU8* p_buffer2) +{ + if (p_buffer1 && p_buffer2) { + MxU32 size = ((MxU32*) p_buffer2)[1] - MxDSChunk::GetHeaderSize(); + memcpy(p_buffer1 + ((MxU32*) p_buffer1)[1] + 8, p_buffer2 + MxDSChunk::GetHeaderSize() + 8, size); + ((MxU32*) p_buffer1)[1] += size; + return SUCCESS; + } + return FAILURE; +} diff --git a/LEGO1/omni/src/stream/mxdschunk.cpp b/LEGO1/omni/src/stream/mxdschunk.cpp index bee247d2..61d794cc 100644 --- a/LEGO1/omni/src/stream/mxdschunk.cpp +++ b/LEGO1/omni/src/stream/mxdschunk.cpp @@ -15,12 +15,12 @@ MxDSChunk::MxDSChunk() // FUNCTION: LEGO1 0x100be170 MxDSChunk::~MxDSChunk() { - if (m_flags & Flag_Bit1) + if (m_flags & c_bit1) delete[] m_data; } // FUNCTION: LEGO1 0x100be1e0 -MxU32 MxDSChunk::ReturnE() +MxU32 MxDSChunk::GetHeaderSize() { return 0xe; } diff --git a/LEGO1/omni/src/stream/mxdssubscriber.cpp b/LEGO1/omni/src/stream/mxdssubscriber.cpp index f93969e1..82ca1730 100644 --- a/LEGO1/omni/src/stream/mxdssubscriber.cpp +++ b/LEGO1/omni/src/stream/mxdssubscriber.cpp @@ -119,7 +119,7 @@ void MxDSSubscriber::DestroyChunk(MxStreamChunk* p_chunk) if (p_chunk) delete p_chunk; } - else if (p_chunk->GetFlags() & MxDSChunk::Flag_Bit1 && p_chunk) + else if (p_chunk->GetFlags() & MxDSChunk::c_bit1 && p_chunk) delete p_chunk; } } diff --git a/LEGO1/omni/src/stream/mxramstreamcontroller.cpp b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp index 71ee1b92..b480255c 100644 --- a/LEGO1/omni/src/stream/mxramstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp @@ -6,8 +6,6 @@ DECOMP_SIZE_ASSERT(MxRAMStreamController, 0x98); -undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize); - // FUNCTION: LEGO1 0x100c6110 MxResult MxRAMStreamController::Open(const char* p_filename) { @@ -95,9 +93,3 @@ MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action) return result == SUCCESS ? SUCCESS : FAILURE; } - -// STUB: LEGO1 0x100d0d80 -undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize) -{ - return NULL; -} diff --git a/LEGO1/omni/src/stream/mxramstreamprovider.cpp b/LEGO1/omni/src/stream/mxramstreamprovider.cpp index fc20bf33..ca091d12 100644 --- a/LEGO1/omni/src/stream/mxramstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxramstreamprovider.cpp @@ -1,6 +1,7 @@ #include "mxramstreamprovider.h" #include "decomp.h" +#include "mxdsbuffer.h" #include "mxomni.h" #include "mxstreamcontroller.h" @@ -46,12 +47,12 @@ MxRAMStreamProvider::~MxRAMStreamProvider() m_bufferSize = 0; m_fileSize = 0; - free(m_pBufferOfFileSize); + delete[] m_pBufferOfFileSize; m_pBufferOfFileSize = NULL; m_lengthInDWords = 0; - free(m_bufferForDWords); + delete[] m_bufferForDWords; m_bufferForDWords = NULL; } @@ -77,7 +78,7 @@ MxResult MxRAMStreamProvider::SetResourceToGet(MxStreamController* p_resource) m_fileSize = m_pFile->CalcFileSize(); if (m_fileSize != 0) { m_bufferSize = m_pFile->GetBufferSize(); - m_pBufferOfFileSize = (MxU32*) new MxU8[m_fileSize]; + m_pBufferOfFileSize = new MxU8[m_fileSize]; if (m_pBufferOfFileSize != NULL && m_pFile->Read((unsigned char*) m_pBufferOfFileSize, m_fileSize) == SUCCESS) { m_lengthInDWords = m_pFile->GetLengthInDWords(); @@ -96,3 +97,60 @@ MxResult MxRAMStreamProvider::SetResourceToGet(MxStreamController* p_resource) m_pFile = NULL; return result; } + +// FUNCTION: LEGO1 0x100d0d80 +MxU32 ReadData(MxU8* p_buffer, MxU32 p_size) +{ + MxU32 id; + MxU8* data = p_buffer; + MxU8* end = p_buffer + p_size; + MxU8* data2; + + if (p_buffer < end) { + do { + if (*MxDSChunk::IntoType(data) == FOURCC('M', 'x', 'O', 'b')) { + data2 = data; + data += 8; + + MxDSObject* obj = DeserializeDSObjectDispatch(&data, -1); + id = obj->GetObjectId(); + delete obj; + + data = MxDSChunk::End(data2); + while (data < end) { + if (*MxDSChunk::IntoType(data) == FOURCC('M', 'x', 'C', 'h')) { + MxU8* data3 = data; + MxU32* psize = MxDSChunk::IntoLength(data); + data += MxDSChunk::Size(*psize); + + if ((*MxDSChunk::IntoType(data2) == FOURCC('M', 'x', 'C', 'h')) && + (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::c_split)) { + if (*MxStreamChunk::IntoObjectId(data2) == *MxStreamChunk::IntoObjectId(data3) && + (*MxStreamChunk::IntoFlags(data3) & MxDSChunk::c_split) && + *MxStreamChunk::IntoTime(data2) == *MxStreamChunk::IntoTime(data3)) { + MxDSBuffer::Append(data2, data3); + continue; + } + 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)) + break; + } + else + data++; + } + } + else + data++; + } while (data < end); + } + + *MxStreamChunk::IntoFlags(data2) &= ~MxDSChunk::c_split; + return MxDSChunk::End(data2) - p_buffer; +} diff --git a/LEGO1/omni/src/stream/mxstreamchunk.cpp b/LEGO1/omni/src/stream/mxstreamchunk.cpp index 4dceabec..ba833186 100644 --- a/LEGO1/omni/src/stream/mxstreamchunk.cpp +++ b/LEGO1/omni/src/stream/mxstreamchunk.cpp @@ -54,7 +54,7 @@ MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, { for (MxStreamListMxDSSubscriber::iterator it = p_subscriberList.begin(); it != p_subscriberList.end(); it++) { if ((*it)->GetObjectId() == m_objectId && (*it)->GetUnknown48() == p_obj24val) { - if (m_flags & MxDSChunk::Flag_End && m_buffer) { + if (m_flags & MxDSChunk::c_end && m_buffer) { m_buffer->ReleaseRef(this); m_buffer = NULL; } diff --git a/LEGO1/omni/src/stream/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp index caacbb5f..204bdab8 100644 --- a/LEGO1/omni/src/stream/mxstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp @@ -82,7 +82,7 @@ MxResult MxStreamController::Open(const char* p_filename) MxAutoLocker lock(&m_criticalSection); MakeSourceName(sourceName, p_filename); - this->m_atom = MxAtomId(sourceName, LookupMode_LowerCase2); + this->m_atom = MxAtomId(sourceName, e_lowerCase2); return SUCCESS; } @@ -271,7 +271,7 @@ MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) if (!chunk) return FAILURE; - chunk->SetFlags(MxDSChunk::Flag_Bit3); + chunk->SetFlags(MxDSChunk::c_bit3); chunk->SetObjectId(objectId); if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS) diff --git a/LEGO1/omni/src/stream/mxstreamer.cpp b/LEGO1/omni/src/stream/mxstreamer.cpp index 245a757f..d8d64fb5 100644 --- a/LEGO1/omni/src/stream/mxstreamer.cpp +++ b/LEGO1/omni/src/stream/mxstreamer.cpp @@ -50,7 +50,7 @@ MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType) if (!GetOpenStream(p_name)) { switch (p_lookupType) { - case e_DiskStream: + case e_diskStream: stream = new MxDiskStreamController(); break; case e_RAMStream: @@ -84,11 +84,11 @@ MxLong MxStreamer::Close(const char* p_name) else { #ifdef COMPAT_MODE { - MxStreamerNotification notification(MXSTREAMER_DELETE_NOTIFY, NULL, c); + MxStreamerNotification notification(c_notificationStreamer, NULL, c); NotificationManager()->Send(this, ¬ification); } #else - NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c)); + NotificationManager()->Send(this, &MxStreamerNotification(c_notificationStreamer, NULL, c)); #endif } @@ -121,6 +121,15 @@ MxStreamController* MxStreamer::GetOpenStream(const char* p_name) return NULL; } +// FUNCTION: LEGO1 0x100b98f0 +void MxStreamer::FUN_100b98f0(MxDSAction* p_action) +{ + MxStreamController* controller = GetOpenStream(p_action->GetAtomId().GetInternal()); + if (controller && controller->IsA("MxDiskStreamController")) { + ((MxDiskStreamController*) controller)->FUN_100c8120(p_action); + } +} + // FUNCTION: LEGO1 0x100b9930 MxResult MxStreamer::AddStreamControllerToOpenList(MxStreamController* p_stream) { @@ -184,7 +193,7 @@ MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject) // FUNCTION: LEGO1 0x100b9b60 MxLong MxStreamer::Notify(MxParam& p_param) { - if (((MxNotificationParam&) p_param).GetNotification() == MXSTREAMER_DELETE_NOTIFY) { + if (((MxNotificationParam&) p_param).GetNotification() == c_notificationStreamer) { MxDSAction ds; ds.SetUnknown24(-2); @@ -196,11 +205,11 @@ MxLong MxStreamer::Notify(MxParam& p_param) else { #ifdef COMPAT_MODE { - MxStreamerNotification notification(MXSTREAMER_DELETE_NOTIFY, NULL, c); + MxStreamerNotification notification(c_notificationStreamer, NULL, c); NotificationManager()->Send(this, ¬ification); } #else - NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c)); + NotificationManager()->Send(this, &MxStreamerNotification(c_notificationStreamer, NULL, c)); #endif } } diff --git a/LEGO1/omni/src/video/mxbitmap.cpp b/LEGO1/omni/src/video/mxbitmap.cpp index 4f2393cf..9e21e449 100644 --- a/LEGO1/omni/src/video/mxbitmap.cpp +++ b/LEGO1/omni/src/video/mxbitmap.cpp @@ -10,12 +10,6 @@ DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428); // (1998) GLOBAL: LEGO1 0x10102184 MxU16 g_bitmapSignature = TWOCC('B', 'M'); -// FUNCTION: LEGO1 0x1004e0d0 -int MxBitmap::VTable0x28(int) -{ - return -1; -} - // FUNCTION: LEGO1 0x100bc980 MxBitmap::MxBitmap() { @@ -109,7 +103,7 @@ MxResult MxBitmap::ImportBitmapInfo(MxBITMAPINFO* p_info) } if (this->m_data) { - delete this->m_data; + delete[] this->m_data; this->m_data = NULL; } } diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index e05b0816..d744accd 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -7,6 +7,7 @@ DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); +// GLOBAL: LEGO1 0x1010215c MxU32 g_unk0x1010215c = 0; // FUNCTION: LEGO1 0x100ba500 @@ -33,7 +34,7 @@ void MxDisplaySurface::Init() } // FUNCTION: LEGO1 0x100ba640 -void MxDisplaySurface::FUN_100ba640() +void MxDisplaySurface::ClearScreen() { MxS32 backBuffers; DDSURFACEDESC desc; diff --git a/LEGO1/omni/src/video/mxflcpresenter.cpp b/LEGO1/omni/src/video/mxflcpresenter.cpp index 76cc7efe..de334852 100644 --- a/LEGO1/omni/src/video/mxflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxflcpresenter.cpp @@ -12,8 +12,8 @@ DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); MxFlcPresenter::MxFlcPresenter() { this->m_flicHeader = NULL; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; + this->m_flags &= ~c_bit2; + this->m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b3420 diff --git a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp index fdd991a9..dcdeba96 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_unk0x68 = 0; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; + this->m_flags &= ~c_bit2; + this->m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b4430 @@ -40,10 +40,8 @@ void MxLoopingFlcPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::Flag_End) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; - } + if (chunk->GetFlags() & MxDSChunk::c_end) + ProgressTickleState(e_repeating); else { LoadFrame(chunk); LoopChunk(chunk); diff --git a/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp index efa758cd..51ed74c8 100644 --- a/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp @@ -21,8 +21,8 @@ MxLoopingSmkPresenter::~MxLoopingSmkPresenter() void MxLoopingSmkPresenter::Init() { this->m_elapsedDuration = 0; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; + this->m_flags &= ~c_bit2; + this->m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b49d0 @@ -51,10 +51,8 @@ void MxLoopingSmkPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::Flag_End) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; - } + if (chunk->GetFlags() & MxDSChunk::c_end) + ProgressTickleState(e_repeating); else { LoadFrame(chunk); LoopChunk(chunk); @@ -67,10 +65,8 @@ void MxLoopingSmkPresenter::NextFrame() // FUNCTION: LEGO1 0x100b4a90 void MxLoopingSmkPresenter::VTable0x8c() { - if (m_action->GetDuration() < m_elapsedDuration) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (m_action->GetDuration() < m_elapsedDuration) + ProgressTickleState(e_unk5); else { MxStreamChunk* chunk; m_loopingChunkCursor->Current(chunk); @@ -112,7 +108,7 @@ void MxLoopingSmkPresenter::RepeatingTickle() m_loopingChunkCursor->Next(chunk); - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) break; } } diff --git a/LEGO1/omni/src/video/mxsmkpresenter.cpp b/LEGO1/omni/src/video/mxsmkpresenter.cpp index 17985fdd..b8001623 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 &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags &= ~c_bit2; + m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b3900 diff --git a/LEGO1/omni/src/video/mxstillpresenter.cpp b/LEGO1/omni/src/video/mxstillpresenter.cpp index 20e6b3a2..f3d0ef67 100644 --- a/LEGO1/omni/src/video/mxstillpresenter.cpp +++ b/LEGO1/omni/src/video/mxstillpresenter.cpp @@ -10,15 +10,10 @@ DECOMP_SIZE_ASSERT(MxStillPresenter, 0x6c); -// GLOBAL: LEGO1 0x10101eb0 +// GLOBAL: LEGO1 0x101020e0 +// STRING: LEGO1 0x10101eb0 const char* g_strBmpIsmap = "BMP_ISMAP"; -// FUNCTION: LEGO1 0x100435b0 -void MxStillPresenter::Destroy() -{ - Destroy(FALSE); -} - // FUNCTION: LEGO1 0x100b9c70 void MxStillPresenter::Destroy(MxBool p_fromDestructor) { @@ -80,13 +75,13 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); - if (m_flags & Flag_Bit2) { + if (m_flags & c_bit2) { undefined4 und = 0; m_unk0x58 = MxOmni::GetInstance()->GetVideoManager()->GetDisplaySurface()->VTable0x44( m_bitmap, &und, - (m_flags & Flag_Bit4) / 8, - m_action->GetFlags() & MxDSAction::Flag_Bit4 + (m_flags & c_bit4) / 8, + m_action->GetFlags() & MxDSAction::c_bit4 ); delete m_alpha; @@ -96,9 +91,9 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) m_bitmap = NULL; if (m_unk0x58 && und) - m_flags |= Flag_Bit3; + m_flags |= c_bit3; else - m_flags &= ~Flag_Bit3; + m_flags &= ~c_bit3; } } @@ -115,7 +110,7 @@ void MxStillPresenter::StartingTickle() { MxVideoPresenter::StartingTickle(); - if (m_currentTickleState == TickleState_Streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) + if (m_currentTickleState == e_streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) RealizePalette(); } @@ -127,8 +122,7 @@ void MxStillPresenter::StreamingTickle() if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { m_chunkTime = chunk->GetTime(); NextFrame(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); if (m_action->GetDuration() == -1 && m_compositePresenter) m_compositePresenter->VTable0x60(this); @@ -139,10 +133,8 @@ void MxStillPresenter::StreamingTickle() void MxStillPresenter::RepeatingTickle() { if (m_action->GetDuration() != -1) { - if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) + ProgressTickleState(e_unk5); } } @@ -173,7 +165,7 @@ void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y) // FUNCTION: LEGO1 0x100ba140 void MxStillPresenter::Enable(MxBool p_enable) { - MxVideoPresenter::Enable(p_enable); + MxPresenter::Enable(p_enable); if (MVideoManager() && (m_alpha || m_bitmap)) { // MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); @@ -193,8 +185,8 @@ void MxStillPresenter::ParseExtra() { MxPresenter::ParseExtra(); - if (m_action->GetFlags() & MxDSAction::Flag_Bit5) - m_flags |= Flag_Bit4; + if (m_action->GetFlags() & MxDSAction::c_bit5) + m_flags |= c_bit4; MxU32 len = m_action->GetExtraLength(); @@ -215,9 +207,9 @@ void MxStillPresenter::ParseExtra() } if (KeyValueStringParse(output, g_strBmpIsmap, buf)) { - m_flags |= Flag_Bit5; - m_flags &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags |= c_bit5; + m_flags &= ~c_bit2; + m_flags &= ~c_bit3; } } diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index 23c12cfb..9fbf2cee 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -8,66 +8,6 @@ DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0xc); -// FUNCTION: LEGO1 0x1000c700 -void MxVideoPresenter::LoadHeader(MxStreamChunk* p_chunk) -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c710 -void MxVideoPresenter::CreateBitmap() -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c720 -void MxVideoPresenter::LoadFrame(MxStreamChunk* p_chunk) -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c730 -void MxVideoPresenter::RealizePalette() -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c740 -MxVideoPresenter::~MxVideoPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000c7a0 -void MxVideoPresenter::Destroy() -{ - Destroy(FALSE); -} - -// FUNCTION: LEGO1 0x1000c7b0 -LPDIRECTDRAWSURFACE MxVideoPresenter::VTable0x78() -{ - return m_unk0x58; -} - -// FUNCTION: LEGO1 0x1000c7c0 -MxBool MxVideoPresenter::VTable0x7c() -{ - return (m_bitmap != NULL) || (m_alpha != NULL); -} - -// FUNCTION: LEGO1 0x1000c7e0 -MxS32 MxVideoPresenter::GetWidth() -{ - return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiWidth(); -} - -// FUNCTION: LEGO1 0x1000c800 -MxS32 MxVideoPresenter::GetHeight() -{ - return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs(); -} - // FUNCTION: LEGO1 0x100b24f0 MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) { @@ -80,7 +20,6 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) m_bitmask = new MxU8[size]; memset(m_bitmask, 0, size); - MxU32 biCompression = p_bitmap.GetBmiHeader()->biCompression; MxU32 rowsBeforeTop; MxU8* bitmapSrcPtr; @@ -92,36 +31,25 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) // Reminder: Negative biHeight means this is a top-down DIB. // Otherwise it is bottom-up. - if (biCompression == BI_RGB) { - // DECOMP: I think this must be an OR. If not, the check for - // biCompression == 16 gets optimized away. - if (biCompression == BI_RGB_TOPDOWN || p_bitmap.GetBmiHeight() < 0) { + switch (p_bitmap.GetBmiHeader()->biCompression) { + case BI_RGB: { + if (p_bitmap.GetBmiHeight() < 0) rowsBeforeTop = 0; - } - else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs(); - rowsBeforeTop--; - } - - goto seek_to_last_row; + else + rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; + bitmapSrcPtr = p_bitmap.GetBitmapData() + (p_bitmap.GetBmiStride() * rowsBeforeTop); + break; } - else if (biCompression == BI_RGB_TOPDOWN) { - // DECOMP: This is the only condition where we skip the - // calculation below. + case BI_RGB_TOPDOWN: bitmapSrcPtr = p_bitmap.GetBitmapData(); - } - else { - if (p_bitmap.GetBmiHeight() < 0) { + break; + default: { + if (p_bitmap.GetBmiHeight() < 0) rowsBeforeTop = 0; - } - else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs(); - rowsBeforeTop--; - } - - // TODO: would prefer not to use goto if we can figure this structure out - seek_to_last_row: - bitmapSrcPtr = p_bitmap.GetBmiStride() * rowsBeforeTop + p_bitmap.GetBitmapData(); + else + rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; + bitmapSrcPtr = p_bitmap.GetBitmapData() + (p_bitmap.GetBmiStride() * rowsBeforeTop); + } } // How many bytes are there for each row of the bitmap? @@ -129,15 +57,15 @@ 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.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. MxS32 offset = 0; - MxU8* tPtr = bitmapSrcPtr; for (MxS32 j = 0; j < m_height; j++) { + MxU8* tPtr = bitmapSrcPtr; for (MxS32 i = 0; i < m_width; i++) { if (*tPtr) { // TODO: Second CDQ instruction for abs() should not be there. @@ -189,29 +117,29 @@ void MxVideoPresenter::Init() m_unk0x5c = 1; m_unk0x58 = NULL; m_unk0x60 = -1; - m_flags &= ~Flag_Bit1; + m_flags &= ~c_bit1; if (MVideoManager() != NULL) { MVideoManager(); - m_flags |= Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags |= c_bit2; + m_flags &= ~c_bit3; } - m_flags &= ~Flag_Bit4; - m_flags &= ~Flag_Bit5; + m_flags &= ~c_bit4; + m_flags &= ~c_bit5; } // FUNCTION: LEGO1 0x100b27b0 void MxVideoPresenter::Destroy(MxBool p_fromDestructor) { if (MVideoManager() != NULL) - MVideoManager()->RemovePresenter(*this); + MVideoManager()->UnregisterPresenter(*this); if (m_unk0x58) { m_unk0x58->Release(); m_unk0x58 = NULL; - m_flags &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags &= ~c_bit2; + m_flags &= ~c_bit3; } if (MVideoManager() && (m_alpha || m_bitmap)) { @@ -240,10 +168,9 @@ void MxVideoPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::Flag_End) { + if (chunk->GetFlags() & MxDSChunk::c_end) { m_subscriber->DestroyChunk(chunk); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); } else { LoadFrame(chunk); @@ -255,7 +182,7 @@ void MxVideoPresenter::NextFrame() MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) { MxDSAction* action = GetAction(); - if ((action == NULL) || (((action->GetFlags() & MxDSAction::Flag_Bit11) == 0) && !IsEnabled()) || + if ((action == NULL) || (((action->GetFlags() & MxDSAction::c_bit11) == 0) && !IsEnabled()) || (!m_bitmap && !m_alpha)) return FALSE; @@ -307,7 +234,7 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) if (m_flags & 0x10) return (MxBool) *pixel; - if ((GetAction()->GetFlags() & MxDSAction::Flag_Bit4) && *pixel == 0) + if ((GetAction()->GetFlags() & MxDSAction::c_bit4) && *pixel == 0) return FALSE; return TRUE; @@ -357,7 +284,7 @@ void MxVideoPresenter::PutFrame() LPDIRECTDRAWSURFACE ddSurface = displaySurface->GetDirectDrawSurface2(); MxRect32 rectSrc, rectDest; - if (m_action->GetFlags() & MxDSAction::Flag_Bit5) { + if (m_action->GetFlags() & MxDSAction::c_bit5) { if (m_unk0x58) { // TODO: Match rectSrc.SetPoint(MxPoint32(0, 0)); @@ -413,7 +340,7 @@ void MxVideoPresenter::PutFrame() rectDest.SetBottom(rectDest.GetTop() + regionRect->GetHeight()); } - if (m_action->GetFlags() & MxDSAction::Flag_Bit4) { + if (m_action->GetFlags() & MxDSAction::c_bit4) { if (m_unk0x58) { if (PrepareRects(rectDest, rectSrc) >= 0) ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL); @@ -460,8 +387,7 @@ void MxVideoPresenter::ReadyTickle() LoadHeader(chunk); m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -472,15 +398,14 @@ void MxVideoPresenter::StartingTickle() if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { CreateBitmap(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); } } // FUNCTION: LEGO1 0x100b2fe0 void MxVideoPresenter::StreamingTickle() { - if (m_action->GetFlags() & MxDSAction::Flag_Bit10) { + if (m_action->GetFlags() & MxDSAction::c_bit10) { if (!m_currentChunk) MxMediaPresenter::StreamingTickle(); @@ -504,13 +429,13 @@ void MxVideoPresenter::StreamingTickle() LoadFrame(m_currentChunk); m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; - m_flags |= Flag_Bit1; + m_flags |= c_bit1; - if (m_currentTickleState != TickleState_Streaming) + if (m_currentTickleState != e_streaming) break; } - if (m_flags & Flag_Bit1) + if (m_flags & c_bit1) m_unk0x5c = 5; } } @@ -519,7 +444,7 @@ void MxVideoPresenter::StreamingTickle() void MxVideoPresenter::RepeatingTickle() { if (IsEnabled()) { - if (m_action->GetFlags() & MxDSAction::Flag_Bit10) { + if (m_action->GetFlags() & MxDSAction::c_bit10) { if (!m_currentChunk) MxMediaPresenter::RepeatingTickle(); @@ -542,13 +467,13 @@ void MxVideoPresenter::RepeatingTickle() LoadFrame(m_currentChunk); m_currentChunk = NULL; - m_flags |= Flag_Bit1; + m_flags |= c_bit1; - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) break; } - if (m_flags & Flag_Bit1) + if (m_flags & c_bit1) m_unk0x5c = 5; } } @@ -564,15 +489,11 @@ void MxVideoPresenter::Unk5Tickle() if (m_unk0x60 == -1) m_unk0x60 = m_action->GetElapsedTime(); - if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; - } - } - else { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) + ProgressTickleState(e_done); } + else + ProgressTickleState(e_done); } } @@ -583,7 +504,7 @@ MxResult MxVideoPresenter::AddToManager() if (MVideoManager()) { result = SUCCESS; - MVideoManager()->AddPresenter(*this); + MVideoManager()->RegisterPresenter(*this); } return result; @@ -614,7 +535,7 @@ MxResult MxVideoPresenter::PutData() { MxAutoLocker lock(&m_criticalSection); - if (IsEnabled() && m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_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 818650eb..806e6659 100644 --- a/LEGO1/realtime/matrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -1,180 +1,5 @@ - #include "matrix.h" #include "decomp.h" -#include "math.h" -#include - -DECOMP_SIZE_ASSERT(Matrix4, 0x40); -DECOMP_SIZE_ASSERT(Matrix4Impl, 0x8); -DECOMP_SIZE_ASSERT(Matrix4Data, 0x48); - -// FUNCTION: LEGO1 0x10002320 -void Matrix4Impl::EqualsMatrixData(const Matrix4& p_matrix) -{ - *m_data = p_matrix; -} - -// FUNCTION: LEGO1 0x10002340 -void Matrix4Impl::EqualsMatrixImpl(const Matrix4Impl* p_other) -{ - *m_data = *p_other->m_data; -} - -// FUNCTION: LEGO1 0x10002360 -void Matrix4Impl::AnotherSetData(Matrix4& p_data) -{ - m_data = &p_data; -} - -// FUNCTION: LEGO1 0x10002380 -const Matrix4* Matrix4Impl::GetData() const -{ - return m_data; -} - -// FUNCTION: LEGO1 0x10002390 -Matrix4* Matrix4Impl::GetData() -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100023a0 -const float* Matrix4Impl::Element(int p_row, int p_col) const -{ - return &(*m_data)[p_row][p_col]; -} - -// FUNCTION: LEGO1 0x100023c0 -float* Matrix4Impl::Element(int p_row, int p_col) -{ - return &(*m_data)[p_row][p_col]; -} - -// FUNCTION: LEGO1 0x100023e0 -void Matrix4Impl::Clear() -{ - memset(m_data, 0, 16 * sizeof(float)); -} - -// FUNCTION: LEGO1 0x100023f0 -void Matrix4Impl::SetIdentity() -{ - Clear(); - (*m_data)[0][0] = 1.0f; - (*m_data)[1][1] = 1.0f; - (*m_data)[2][2] = 1.0f; - (*m_data)[3][3] = 1.0f; -} - -// FUNCTION: LEGO1 0x10002430 -Matrix4Impl* Matrix4Impl::operator+=(const Matrix4& p_matrix) -{ - for (int i = 0; i < 16; ++i) - ((float*) m_data)[i] += ((float*) &p_matrix)[i]; - return this; -} - -// Matches but instructions are significantly out of order. Probably not wrong -// code given that the very similar SetTranslation does match. -// FUNCTION: LEGO1 0x10002460 -void Matrix4Impl::TranslateBy(const float* p_x, const float* p_y, const float* p_z) -{ - ((float*) m_data)[12] += *p_x; - ((float*) m_data)[13] += *p_y; - ((float*) m_data)[14] += *p_z; -} - -// FUNCTION: LEGO1 0x100024a0 -void Matrix4Impl::SetTranslation(const float* p_x, const float* p_y, const float* p_z) -{ - (*m_data)[3][0] = *p_x; - (*m_data)[3][1] = *p_y; - (*m_data)[3][2] = *p_z; -} - -// FUNCTION: LEGO1 0x100024d0 -void Matrix4Impl::EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b) -{ - float* cur = (float*) m_data; - for (int row = 0; row < 4; ++row) { - for (int col = 0; col < 4; ++col) { - *cur = 0.0f; - for (int k = 0; k < 4; ++k) { - *cur += p_a[row][k] * p_b[k][col]; - } - cur++; - } - } -} - -// FUNCTION: LEGO1 0x10002530 -void Matrix4Impl::EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b) -{ - EqualsDataProduct(*p_a->m_data, *p_b->m_data); -} - -// Not close, Ghidra struggles understinging this method so it will have to -// be manually worked out. Included since I at least figured out what it was -// doing with rotateIndex and what overall operation it's trying to do. -// STUB: LEGO1 0x10002550 -void Matrix4Impl::ToQuaternion(Vector4Impl* p_outQuat) -{ - /* - float trace = m_data[0] + m_data[5] + m_data[10]; - if (trace > 0) { - trace = sqrt(trace + 1.0); - p_outQuat->GetData()[3] = trace * 0.5f; - p_outQuat->GetData()[0] = (m_data[9] - m_data[6]) * trace; - p_outQuat->GetData()[1] = (m_data[2] - m_data[8]) * trace; - p_outQuat->GetData()[2] = (m_data[4] - m_data[1]) * trace; - return; - } - - // ~GLOBAL: LEGO1 0x100d4090 - static int rotateIndex[] = {1, 2, 0}; - - // Largest element along the trace - int largest = m_data[0] < m_data[5]; - if (*Element(largest, largest) < m_data[10]) - largest = 2; - - int next = rotateIndex[largest]; - int nextNext = rotateIndex[next]; - float valueA = *Element(nextNext, nextNext); - float valueB = *Element(next, next); - float valueC = *Element(largest, largest); - - // Above is somewhat decomped, below is pure speculation since the automatic - // decomp becomes very garbled. - float traceValue = sqrt(valueA - valueB - valueC + 1.0); - - p_outQuat->GetData()[largest] = traceValue * 0.5f; - traceValue = 0.5f / traceValue; - - p_outQuat->GetData()[3] = (m_data[next + 4 * nextNext] - m_data[nextNext + 4 * next]) * traceValue; - p_outQuat->GetData()[next] = (m_data[next + 4 * largest] + m_data[largest + 4 * next]) * traceValue; - p_outQuat->GetData()[nextNext] = (m_data[nextNext + 4 * largest] + m_data[largest + 4 * nextNext]) * traceValue; - */ -} - -// No idea what this function is doing and it will be hard to tell until -// we have a confirmed usage site. -// STUB: LEGO1 0x10002710 -int Matrix4Impl::FromQuaternion(const Vector4Impl& p_vec) -{ - return -1; -} - -// FUNCTION: LEGO1 0x10002850 -void Matrix4Impl::operator=(const Matrix4Impl& p_other) -{ - EqualsMatrixImpl(&p_other); -} - -// FUNCTION: LEGO1 0x10002860 -void Matrix4Data::operator=(const Matrix4Data& p_other) -{ - EqualsMatrixImpl(&p_other); -} +DECOMP_SIZE_ASSERT(Matrix4, 0x8); diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index c087d331..4e661ddb 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -3,90 +3,166 @@ #include "vector.h" -/* - * A simple array of four Vector4s that can be indexed into. - */ -class Matrix4 { -public: - float rows[4][4]; // storage is public for easy access +#include - inline Matrix4() {} - /* - Matrix4(const Vector4& x_axis, const Vector4& y_axis, const Vector4& z_axis, const Vector4& position) - { - rows[0] = x_axis; - rows[1] = y_axis; - rows[2] = z_axis; - rows[3] = position; - } - Matrix4(const float m[4][4]) - { - rows[0] = m[0]; - rows[1] = m[1]; - rows[2] = m[2]; - rows[3] = m[3]; - } - */ - const float* operator[](long i) const { return rows[i]; } - float* operator[](long i) { return rows[i]; } +struct UnknownMatrixType { + float m_data[4][4]; }; // VTABLE: LEGO1 0x100d4350 // SIZE 0x8 -class Matrix4Impl { +class Matrix4 { public: - inline Matrix4Impl(Matrix4& p_data) { SetData(p_data); } + inline Matrix4(float (*p_data)[4]) { SetData(p_data); } + + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. + + // FUNCTION: LEGO1 0x10002320 + virtual void Equals(float (*p_data)[4]) { memcpy(m_data, p_data, sizeof(float) * 4 * 4); } // vtable+0x04 + + // FUNCTION: LEGO1 0x10002340 + virtual void Equals(const Matrix4& p_matrix) + { + memcpy(m_data, p_matrix.m_data, sizeof(float) * 4 * 4); + }; // vtable+0x00 + + // FUNCTION: LEGO1 0x10002360 + virtual void SetData(float (*p_data)[4]) { m_data = p_data; } // vtable+0x0c - // vtable + 0x00 - virtual void EqualsMatrixImpl(const Matrix4Impl* p_other); - virtual void EqualsMatrixData(const Matrix4& p_matrix); // FUNCTION: LEGO1 0x10002370 - virtual void SetData(Matrix4& p_data) { m_data = &p_data; } - virtual void AnotherSetData(Matrix4& p_data); + virtual void SetData(UnknownMatrixType& p_matrix) { m_data = p_matrix.m_data; }; // vtable+0x08 - // vtable + 0x10 - virtual Matrix4* GetData(); - virtual const Matrix4* GetData() const; - virtual float* Element(int p_row, int p_col); - virtual const float* Element(int p_row, int p_col) const; + // FUNCTION: LEGO1 0x10002380 + virtual float (*GetData())[4] { return m_data; }; // vtable+0x14 - // vtable + 0x20 - virtual void Clear(); - virtual void SetIdentity(); - virtual void operator=(const Matrix4Impl& p_other); - virtual Matrix4Impl* operator+=(const Matrix4& p_matrix); + // FUNCTION: LEGO1 0x10002390 + virtual float (*GetData() const)[4] { return m_data; }; // vtable+0x10 - // vtable + 0x30 - virtual void TranslateBy(const float* p_x, const float* p_y, const float* p_z); - virtual void SetTranslation(const float* p_x, const float* p_y, const float* p_z); - virtual void EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b); - virtual void EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b); + // FUNCTION: LEGO1 0x100023a0 + virtual float* Element(int p_row, int p_col) { return &m_data[p_row][p_col]; } // vtable+0x1c - // vtable + 0x40 - virtual void ToQuaternion(Vector4Impl* p_resultQuat); - virtual int FromQuaternion(const Vector4Impl& p_vec); + // FUNCTION: LEGO1 0x100023c0 + virtual const float* Element(int p_row, int p_col) const { return &m_data[p_row][p_col]; }; // vtable+0x18 - inline float& operator[](size_t idx) { return ((float*) m_data)[idx]; } + // FUNCTION: LEGO1 0x100023e0 + virtual void Clear() { memset(m_data, 0, 16 * sizeof(float)); }; // vtable+0x20 + + // FUNCTION: LEGO1 0x100023f0 + virtual void SetIdentity() + { + Clear(); + m_data[0][0] = 1.0f; + m_data[1][1] = 1.0f; + m_data[2][2] = 1.0f; + m_data[3][3] = 1.0f; + } // vtable+0x24 + + // FUNCTION: LEGO1 0x10002850 + virtual void operator=(const Matrix4& p_matrix) { Equals(p_matrix); } // vtable+0x28 + + // FUNCTION: LEGO1 0x10002430 + virtual Matrix4& operator+=(float (*p_data)[4]) + { + for (int i = 0; i < 16; i++) + ((float*) m_data)[i] += ((float*) p_data)[i]; + return *this; + } // vtable+0x2c + + // FUNCTION: LEGO1 0x10002460 + virtual void TranslateBy(const float* p_x, const float* p_y, const float* p_z) + { + m_data[3][0] += *p_x; + m_data[3][1] += *p_y; + m_data[3][2] += *p_z; + } // vtable+0x30 + + // FUNCTION: LEGO1 0x100024a0 + virtual void SetTranslation(const float* p_x, const float* p_y, const float* p_z) + { + m_data[3][0] = *p_x; + m_data[3][1] = *p_y; + m_data[3][2] = *p_z; + } // vtable+0x34 + + // FUNCTION: LEGO1 0x100024d0 + virtual void Product(float (*p_a)[4], float (*p_b)[4]) + { + float* cur = (float*) m_data; + for (int row = 0; row < 4; row++) { + for (int col = 0; col < 4; col++) { + *cur = 0.0f; + for (int k = 0; k < 4; k++) { + *cur += p_a[row][k] * p_b[k][col]; + } + cur++; + } + } + }; // 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 + + inline virtual void ToQuaternion(Vector4& p_resultQuat); // vtable+0x40 + inline virtual int FromQuaternion(const Vector4& p_vec); // vtable+0x44 + + float* operator[](size_t idx) { return m_data[idx]; } + const float* operator[](size_t idx) const { return m_data[idx]; } protected: - // TODO: Currently unclear whether this class contains a Matrix4* or float*. - Matrix4* m_data; + float (*m_data)[4]; }; -// VTABLE: LEGO1 0x100d4300 -// SIZE 0x48 -class Matrix4Data : public Matrix4Impl { -public: - inline Matrix4Data() : Matrix4Impl(m_matrix) {} - inline Matrix4Data(Matrix4Data& p_other) : Matrix4Impl(m_matrix) { m_matrix = *p_other.m_data; } - inline Matrix4& GetMatrix() { return *m_data; } +// Not close, Ghidra struggles understinging this method so it will have to +// be manually worked out. Included since I at least figured out what it was +// doing with rotateIndex and what overall operation it's trying to do. +// STUB: LEGO1 0x10002550 +inline void Matrix4::ToQuaternion(Vector4& p_outQuat) +{ + /* + float trace = m_data[0] + m_data[5] + m_data[10]; + if (trace > 0) { + trace = sqrt(trace + 1.0); + p_outQuat->GetData()[3] = trace * 0.5f; + p_outQuat->GetData()[0] = (m_data[9] - m_data[6]) * trace; + p_outQuat->GetData()[1] = (m_data[2] - m_data[8]) * trace; + p_outQuat->GetData()[2] = (m_data[4] - m_data[1]) * trace; + return; + } - // 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? - // vtable + 0x44 - virtual void operator=(const Matrix4Data& p_other); + // ~GLOBAL: LEGO1 0x100d4090 + static int rotateIndex[] = {1, 2, 0}; - Matrix4 m_matrix; -}; + // Largest element along the trace + int largest = m_data[0] < m_data[5]; + if (*Element(largest, largest) < m_data[10]) + largest = 2; + + int next = rotateIndex[largest]; + int nextNext = rotateIndex[next]; + float valueA = *Element(nextNext, nextNext); + float valueB = *Element(next, next); + float valueC = *Element(largest, largest); + + // Above is somewhat decomped, below is pure speculation since the automatic + // decomp becomes very garbled. + float traceValue = sqrt(valueA - valueB - valueC + 1.0); + + p_outQuat->GetData()[largest] = traceValue * 0.5f; + traceValue = 0.5f / traceValue; + + p_outQuat->GetData()[3] = (m_data[next + 4 * nextNext] - m_data[nextNext + 4 * next]) * traceValue; + p_outQuat->GetData()[next] = (m_data[next + 4 * largest] + m_data[largest + 4 * next]) * traceValue; + p_outQuat->GetData()[nextNext] = (m_data[nextNext + 4 * largest] + m_data[largest + 4 * nextNext]) * traceValue; + */ +} + +// No idea what this function is doing and it will be hard to tell until +// we have a confirmed usage site. +// STUB: LEGO1 0x10002710 +inline int Matrix4::FromQuaternion(const Vector4& p_vec) +{ + return -1; +} #endif // MATRIX_H diff --git a/LEGO1/realtime/orientableroi.cpp b/LEGO1/realtime/orientableroi.cpp index e03b78cb..4f48c333 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -2,8 +2,24 @@ #include "decomp.h" +#include + DECOMP_SIZE_ASSERT(OrientableROI, 0xdc) +// FUNCTION: LEGO1 0x100a4420 +OrientableROI::OrientableROI() +{ + FILLVEC3(m_world_bounding_box.Min(), 888888.8); + FILLVEC3(m_world_bounding_box.Max(), -888888.8); + ZEROVEC3(m_world_bounding_sphere.Center()); + m_world_bounding_sphere.Radius() = 0.0; + ZEROVEC3(m_world_velocity); + IDENTMAT4(m_local2world); + + m_unk0xd4 = 0; + m_unk0xd8 |= c_bit1 | c_bit2; +} + // FUNCTION: LEGO1 0x100a5910 void OrientableROI::VTable0x1c() { @@ -12,27 +28,27 @@ void OrientableROI::VTable0x1c() } // FUNCTION: LEGO1 0x100a5930 -void OrientableROI::SetLocalTransform(const Matrix4Impl& p_transform) +void OrientableROI::SetLocalTransform(const Matrix4& p_transform) { - reinterpret_cast(m_local2world) = p_transform; + reinterpret_cast(m_local2world) = p_transform; UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); } // FUNCTION: LEGO1 0x100a5960 -void OrientableROI::VTable0x24(const Matrix4Data& p_transform) +void OrientableROI::VTable0x24(const MxMatrix& p_transform) { - Matrix4Data l_matrix(m_local2world); - m_local2world.EqualsMxProduct(&p_transform, &l_matrix); + MxMatrix l_matrix(m_local2world); + m_local2world.Product(p_transform, l_matrix); UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); } // FUNCTION: LEGO1 0x100a59b0 -void OrientableROI::UpdateWorldData(const Matrix4Data& p_transform) +void OrientableROI::UpdateWorldData(const MxMatrix& p_transform) { - Matrix4Data l_matrix(m_local2world); - m_local2world.EqualsMxProduct(&l_matrix, &p_transform); + MxMatrix l_matrix(m_local2world); + m_local2world.Product(l_matrix, p_transform); UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); @@ -50,9 +66,9 @@ void OrientableROI::UpdateWorldVelocity() } // FUNCTION: LEGO1 0x100a5d80 -const Vector3& OrientableROI::GetWorldVelocity() const +const float* OrientableROI::GetWorldVelocity() const { - return (Vector3&) *m_world_velocity.GetData(); + return m_world_velocity.GetData(); } // FUNCTION: LEGO1 0x100a5d90 diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index 82db8271..36b8ae50 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -1,47 +1,59 @@ #ifndef ORIENTABLEROI_H #define ORIENTABLEROI_H -#include "matrix.h" +#include "decomp.h" +#include "mxgeometry/mxmatrix.h" #include "roi.h" // VTABLE: LEGO1 0x100dbc08 // SIZE 0xdc class OrientableROI : public ROI { public: - // FUNCTION: LEGO1 0x100a4420 - OrientableROI() - { - FILLVEC3(m_world_bounding_box.Min(), 888888.8); - FILLVEC3(m_world_bounding_box.Max(), -888888.8); - ZEROVEC3(m_world_bounding_sphere.Center()); - m_world_bounding_sphere.Radius() = 0.0; - ZEROVEC3(m_world_velocity); - IDENTMAT4(m_local2world.GetMatrix()); - } + enum { + c_bit1 = 0x01, + c_bit2 = 0x02 + }; - virtual const Vector3& GetWorldVelocity() const override; // vtable+0x8 + 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 // FUNCTION: LEGO1 0x100a5db0 - virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 - virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 - virtual void VTable0x1c(); // vtable+0x1c - virtual void SetLocalTransform(const Matrix4Impl& p_transform); // vtable+0x20 - virtual void VTable0x24(const Matrix4Data& p_transform); // vtable+0x24 - virtual void UpdateWorldData(const Matrix4Data& p_transform); // vtable+0x28 - virtual void UpdateWorldVelocity(); // vtable+0x2c + virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 + virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 + virtual void VTable0x1c(); // vtable+0x1c + virtual void SetLocalTransform(const Matrix4& p_transform); // vtable+0x20 + virtual void VTable0x24(const MxMatrix& p_transform); // vtable+0x24 + virtual void UpdateWorldData(const MxMatrix& p_transform); // vtable+0x28 + virtual void UpdateWorldVelocity(); // vtable+0x2c - // SYNTHETIC: LEGO1 0x100a4630 - // OrientableROI::`scalar deleting destructor' + const MxMatrix& GetLocal2World() const { return m_local2world; } + const float* GetWorldPosition() const { return m_local2world[3]; } + const float* GetWorldDirection() const { return m_local2world[2]; } + const float* GetWorldUp() const { return m_local2world[1]; } protected: - char m_unk0xc; // 0xc - Matrix4Data m_local2world; // 0x10 - BoundingBox m_world_bounding_box; // 0x58 + MxMatrix m_local2world; // 0x10 + BoundingBox m_world_bounding_box; // 0x58 + + // Unclear whether the following vectors are: + // 1) Part of m_world_bounding_box; + // 2) A second BoundingBox; + // 3) Standalone vectors + + Mx3DPointFloat m_unk0x80; // 0x80 + Mx3DPointFloat m_unk0x94; // 0x94 BoundingSphere m_world_bounding_sphere; // 0xa8 - Vector3Data m_world_velocity; // 0xc0 - unsigned int m_unk0xd4; // 0xd4 - unsigned int m_unk0xd8; // 0xd8 + Mx3DPointFloat m_world_velocity; // 0xc0 + undefined4 m_unk0xd4; // 0xd4 + undefined4 m_unk0xd8; // 0xd8 }; +// SYNTHETIC: LEGO1 0x100a4630 +// OrientableROI::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100aa2f0 +// OrientableROI::~OrientableROI + #endif // ORIENTABLEROI_H diff --git a/LEGO1/realtime/realtime.cpp b/LEGO1/realtime/realtime.cpp index 750082ec..829b2271 100644 --- a/LEGO1/realtime/realtime.cpp +++ b/LEGO1/realtime/realtime.cpp @@ -1,45 +1,20 @@ #include "realtime.h" +#include + // FUNCTION: LEGO1 0x100a5b40 -void CalcLocalTransform( - const Vector3Impl& p_posVec, - const Vector3Impl& p_dirVec, - const Vector3Impl& p_upVec, - Matrix4Impl& p_outMatrix -) +void CalcLocalTransform(const Vector3& p_posVec, const Vector3& p_dirVec, const Vector3& p_upVec, Matrix4& p_outMatrix) { float x_axis[3], y_axis[3], z_axis[3]; - // This is an unrolled version of the "NORMVEC3" macro, - // used here to apply a silly hack to get a 100% match - { - const float dirVec1Operation = (p_dirVec)[1] * (p_dirVec)[1]; - double len = sqrt(((p_dirVec)[0] * (p_dirVec)[0] + dirVec1Operation + (p_dirVec)[2] * (p_dirVec)[2])); - ((z_axis)[0] = (p_dirVec)[0] / (len), (z_axis)[1] = (p_dirVec)[1] / (len), (z_axis)[2] = (p_dirVec)[2] / (len)); - } - + NORMVEC3(z_axis, p_dirVec); NORMVEC3(y_axis, p_upVec) - VXV3(x_axis, y_axis, z_axis); - - // Exact same thing as pointed out by the above comment - { - const float axis2Operation = (x_axis)[2] * (x_axis)[2]; - double len = sqrt(((x_axis)[0] * (x_axis)[0] + axis2Operation + (x_axis)[1] * (x_axis)[1])); - ((x_axis)[0] = (x_axis)[0] / (len), (x_axis)[1] = (x_axis)[1] / (len), (x_axis)[2] = (x_axis)[2] / (len)); - } - + NORMVEC3(x_axis, x_axis); VXV3(y_axis, z_axis, x_axis); - - // Again, the same thing - { - const float axis2Operation = (y_axis)[2] * (y_axis)[2]; - double len = sqrt(((y_axis)[0] * (y_axis)[0] + axis2Operation + (y_axis)[1] * (y_axis)[1])); - ((y_axis)[0] = (y_axis)[0] / (len), (y_axis)[1] = (y_axis)[1] / (len), (y_axis)[2] = (y_axis)[2] / (len)); - } - - SET4from3(&p_outMatrix[0], x_axis, 0); - SET4from3(&p_outMatrix[4], y_axis, 0); - SET4from3(&p_outMatrix[8], z_axis, 0); - SET4from3(&p_outMatrix[12], p_posVec, 1); + NORMVEC3(y_axis, y_axis); + SET4from3(p_outMatrix[0], x_axis, 0); + SET4from3(p_outMatrix[1], y_axis, 0); + SET4from3(p_outMatrix[2], z_axis, 0); + SET4from3(p_outMatrix[3], p_posVec, 1); } diff --git a/LEGO1/realtime/realtime.h b/LEGO1/realtime/realtime.h index ae166dfa..cb8298a1 100644 --- a/LEGO1/realtime/realtime.h +++ b/LEGO1/realtime/realtime.h @@ -9,11 +9,6 @@ VDS3(dst, src, len); \ } -void CalcLocalTransform( - const Vector3Impl& p_posVec, - const Vector3Impl& p_dirVec, - const Vector3Impl& p_upVec, - Matrix4Impl& p_outMatrix -); +void CalcLocalTransform(const Vector3& p_posVec, const Vector3& p_dirVec, const Vector3& p_upVec, Matrix4& p_outMatrix); #endif // REALTIME_H diff --git a/LEGO1/realtime/realtimeview.cpp b/LEGO1/realtime/realtimeview.cpp index 5d1fc1a6..9522d1c1 100644 --- a/LEGO1/realtime/realtimeview.cpp +++ b/LEGO1/realtime/realtimeview.cpp @@ -30,8 +30,7 @@ void RealtimeView::SetPartsThreshold(float p_threshold) // FUNCTION: LEGO1 0x100a5e00 float RealtimeView::GetUserMaxLOD() { - // TODO - return 0; + return g_userMaxLod; } // FUNCTION: LEGO1 0x100a5e10 diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index c8458cd7..2cdf943a 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -5,39 +5,39 @@ #include "compat.h" #include "lodlist.h" +#include "mxgeometry/mxgeometry3d.h" #include "mxstl/stlcompat.h" #include "realtime/realtime.h" -#include "vector.h" /* * A simple bounding box object with Min and Max accessor methods. */ +// SIZE 0x28 class BoundingBox { public: - const Vector3Data& Min() const { return min; } - Vector3Data& Min() { return min; } - const Vector3Data& Max() const { return max; } - Vector3Data& Max() { return max; } + const Mx3DPointFloat& Min() const { return min; } + Mx3DPointFloat& Min() { return min; } + const Mx3DPointFloat& Max() const { return max; } + Mx3DPointFloat& Max() { return max; } private: - Vector3Data min; - Vector3Data max; - Vector3Data m_unk0x28; - Vector3Data m_unk0x3c; + Mx3DPointFloat min; + Mx3DPointFloat max; }; /* * A simple bounding sphere object with center and radius accessor methods. */ +// SIZE 0x18 class BoundingSphere { public: - const Vector3Data& Center() const { return center; } - Vector3Data& Center() { return center; } + const Mx3DPointFloat& Center() const { return center; } + Mx3DPointFloat& Center() { return center; } const float& Radius() const { return radius; } float& Radius() { return radius; } private: - Vector3Data center; + Mx3DPointFloat center; float radius; }; @@ -74,13 +74,14 @@ typedef vector ROIList; typedef vector IntList; // VTABLE: LEGO1 0x100dbc38 -// SIZE 0xc +// SIZE 0x10 class ROI { public: ROI() { m_comp = 0; m_lods = 0; + m_unk0xc = 1; } virtual ~ROI() { @@ -89,7 +90,7 @@ class ROI { assert(!m_lods); } virtual float IntrinsicImportance() const = 0; // vtable+0x4 - virtual const Vector3& GetWorldVelocity() const = 0; // vtable+0x8 + virtual const float* GetWorldVelocity() const = 0; // vtable+0x8 virtual const BoundingBox& GetWorldBoundingBox() const = 0; // vtable+0xc virtual const BoundingSphere& GetWorldBoundingSphere() const = 0; // vtable+0x10 @@ -105,5 +106,10 @@ class ROI { protected: CompoundObject* m_comp; // 0x4 LODListBase* m_lods; // 0x8 + undefined m_unk0xc; // 0xc }; + +// SYNTHETIC: LEGO1 0x100a5d50 +// ROI::~ROI + #endif // ROI_H diff --git a/LEGO1/realtime/vector.cpp b/LEGO1/realtime/vector.cpp index 390cfdd9..57c93e66 100644 --- a/LEGO1/realtime/vector.cpp +++ b/LEGO1/realtime/vector.cpp @@ -1,457 +1,7 @@ - #include "vector.h" #include "decomp.h" -#include -#include - -DECOMP_SIZE_ASSERT(Vector2Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector3Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector4Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector3Data, 0x14); -DECOMP_SIZE_ASSERT(Vector4Data, 0x18); - -// FUNCTION: LEGO1 0x10001f80 -void Vector2Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; -} - -// FUNCTION: LEGO1 0x10001fa0 -void Vector2Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; -} - -// FUNCTION: LEGO1 0x10001fc0 -void Vector2Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; -} - -// FUNCTION: LEGO1 0x10001fe0 -void Vector2Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; -} - -// FUNCTION: LEGO1 0x10002000 -void Vector2Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; -} - -// FUNCTION: LEGO1 0x10002020 -void Vector2Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; -} - -// FUNCTION: LEGO1 0x10002040 -float Vector2Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_b[0] * p_a[0] + p_b[1] * p_a[1]; -} - -// FUNCTION: LEGO1 0x10002070 -void Vector2Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; -} - -// FUNCTION: LEGO1 0x10002090 -float* Vector2Impl::GetData() -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100020a0 -const float* Vector2Impl::GetData() const -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100020b0 -void Vector2Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; -} - -// FUNCTION: LEGO1 0x100020d0 -float Vector2Impl::Dot(float* p_a, float* p_b) const -{ - return DotImpl(p_a, p_b); -} - -// FUNCTION: LEGO1 0x100020f0 -float Vector2Impl::Dot(Vector2Impl* p_a, Vector2Impl* p_b) const -{ - return DotImpl(p_a->m_data, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002110 -float Vector2Impl::Dot(float* p_a, Vector2Impl* p_b) const -{ - return DotImpl(p_a, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002130 -float Vector2Impl::Dot(Vector2Impl* p_a, float* p_b) const -{ - return DotImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002150 -float Vector2Impl::LenSquared() const -{ - return m_data[0] * m_data[0] + m_data[1] * m_data[1]; -} - -// FUNCTION: LEGO1 0x10002160 -int Vector2Impl::Unitize() -{ - float sq = LenSquared(); - if (sq > 0.0f) { - float root = sqrt(sq); - if (root > 0) { - DivScalarImpl(&root); - return 0; - } - } - return -1; -} - -// FUNCTION: LEGO1 0x100021c0 -void Vector2Impl::Add(float p_value) -{ - AddScalarImpl(p_value); -} - -// FUNCTION: LEGO1 0x100021d0 -void Vector2Impl::Add(float* p_other) -{ - AddVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x100021e0 -void Vector2Impl::Add(Vector2Impl* p_other) -{ - AddVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x100021f0 -void Vector2Impl::Sub(float* p_other) -{ - SubVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002200 -void Vector2Impl::Sub(Vector2Impl* p_other) -{ - SubVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002210 -void Vector2Impl::Mul(float* p_other) -{ - MullVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002220 -void Vector2Impl::Mul(Vector2Impl* p_other) -{ - MullVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002230 -void Vector2Impl::Mul(float& p_value) -{ - MullScalarImpl(&p_value); -} - -// FUNCTION: LEGO1 0x10002240 -void Vector2Impl::Div(float& p_value) -{ - DivScalarImpl(&p_value); -} - -// FUNCTION: LEGO1 0x10002250 -void Vector2Impl::SetVector(float* p_other) -{ - EqualsImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002260 -void Vector2Impl::SetVector(Vector2Impl* p_other) -{ - EqualsImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002270 -void Vector3Impl::EqualsCrossImpl(float* p_a, float* p_b) -{ - m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; - m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; - m_data[2] = p_a[0] * p_b[1] - p_a[1] * p_b[0]; -} - -// FUNCTION: LEGO1 0x100022c0 -void Vector3Impl::EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b) -{ - EqualsCrossImpl(p_a->m_data, p_b->m_data); -} - -// FUNCTION: LEGO1 0x100022e0 -void Vector3Impl::EqualsCross(Vector3Impl* p_a, float* p_b) -{ - EqualsCrossImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002300 -void Vector3Impl::EqualsCross(float* p_a, Vector3Impl* p_b) -{ - EqualsCrossImpl(p_a, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002870 -void Vector4Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; - m_data[2] += p_value[2]; - m_data[3] += p_value[3]; -} - -// FUNCTION: LEGO1 0x100028b0 -void Vector4Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; - m_data[2] += p_value; - m_data[3] += p_value; -} - -// FUNCTION: LEGO1 0x100028f0 -void Vector4Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; - m_data[2] -= p_value[2]; - m_data[3] -= p_value[3]; -} - -// FUNCTION: LEGO1 0x10002930 -void Vector4Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; - m_data[2] *= p_value[2]; - m_data[3] *= p_value[3]; -} - -// FUNCTION: LEGO1 0x10002970 -void Vector4Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; - m_data[2] *= *p_value; - m_data[3] *= *p_value; -} - -// FUNCTION: LEGO1 0x100029b0 -void Vector4Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; - m_data[2] /= *p_value; - m_data[3] /= *p_value; -} - -// FUNCTION: LEGO1 0x100029f0 -float Vector4Impl::DotImpl(float* p_a, float* p_b) const -{ - 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]); -} - -// FUNCTION: LEGO1 0x10002a20 -void Vector4Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; - vec[2] = p_data[2]; - vec[3] = p_data[3]; -} - -// FUNCTION: LEGO1 0x10002a40 -void Vector4Impl::SetMatrixProductImpl(float* p_vec, float* p_mat) -{ - m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; - m_data[1] = p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; - m_data[2] = p_vec[0] * p_mat[2] + p_vec[1] * p_mat[6] + p_vec[2] * p_mat[10] + p_vec[4] * p_mat[14]; - m_data[3] = p_vec[0] * p_mat[3] + p_vec[1] * p_mat[7] + p_vec[2] * p_mat[11] + p_vec[4] * p_mat[15]; -} - -// FUNCTION: LEGO1 0x10002ae0 -void Vector4Impl::SetMatrixProduct(Vector4Impl* p_a, float* p_b) -{ - SetMatrixProductImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002b00 -void Vector4Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 0.0f; - vec[3] = 0.0f; -} - -// FUNCTION: LEGO1 0x10002b20 -float Vector4Impl::LenSquared() const -{ - 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]; -} - -// FUNCTION: LEGO1 0x10002b40 -void Vector4Impl::EqualsScalar(float* p_value) -{ - m_data[0] = *p_value; - m_data[1] = *p_value; - m_data[2] = *p_value; - m_data[3] = *p_value; -} - -// Note close yet, included because I'm at least confident I know what operation -// it's trying to do. -// STUB: LEGO1 0x10002b70 -int Vector4Impl::NormalizeQuaternion() -{ - float* v = m_data; - float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; - if (magnitude > 0.0f) { - float theta = v[3] * 0.5f; - v[3] = cos(theta); - float frac = sin(theta); - magnitude = frac / sqrt(magnitude); - v[0] *= magnitude; - v[1] *= magnitude; - v[2] *= magnitude; - return 0; - } - return -1; -} - -// FUNCTION: LEGO1 0x10002bf0 -void Vector4Impl::UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b) -{ - float* bDat = p_b->m_data; - float* aDat = p_a->m_data; - - this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); - this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; - this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; - this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; - - m_data[0] = p_b->m_data[3] * p_a->m_data[0] + p_a->m_data[3] * p_b->m_data[0] + m_data[0]; - m_data[1] = p_b->m_data[1] * p_a->m_data[3] + p_a->m_data[1] * p_b->m_data[3] + m_data[1]; - m_data[2] = p_b->m_data[2] * p_a->m_data[3] + p_a->m_data[2] * p_b->m_data[3] + m_data[2]; -} - -// FUNCTION: LEGO1 0x10003a60 -void Vector3Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; - m_data[2] += p_value[2]; -} - -// FUNCTION: LEGO1 0x10003a90 -void Vector3Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; - m_data[2] += p_value; -} - -// FUNCTION: LEGO1 0x10003ac0 -void Vector3Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; - m_data[2] -= p_value[2]; -} - -// FUNCTION: LEGO1 0x10003af0 -void Vector3Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; - m_data[2] *= p_value[2]; -} - -// FUNCTION: LEGO1 0x10003b20 -void Vector3Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; - m_data[2] *= *p_value; -} - -// FUNCTION: LEGO1 0x10003b50 -void Vector3Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; - m_data[2] /= *p_value; -} - -// FUNCTION: LEGO1 0x10003b80 -float Vector3Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; -} - -// FUNCTION: LEGO1 0x10003ba0 -void Vector3Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; - vec[2] = p_data[2]; -} - -// FUNCTION: LEGO1 0x10003bc0 -void Vector3Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 0.0f; -} - -// FUNCTION: LEGO1 0x10003bd0 -float Vector3Impl::LenSquared() const -{ - return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; -} - -// FUNCTION: LEGO1 0x10003bf0 -void Vector3Impl::EqualsScalar(float* p_value) -{ - m_data[0] = *p_value; - m_data[1] = *p_value; - m_data[2] = *p_value; -} +DECOMP_SIZE_ASSERT(Vector2, 0x8); +DECOMP_SIZE_ASSERT(Vector3, 0x8); +DECOMP_SIZE_ASSERT(Vector4, 0x8); diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 1af21c9a..eb03d29d 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -1,115 +1,145 @@ #ifndef VECTOR_H #define VECTOR_H -#include +#include "compat.h" -/* - * A simple array of three floats that can be indexed into. - */ -class Vector3 { -public: - float elements[3]; // storage is public for easy access - - Vector3() {} - Vector3(float x, float y, float z) - { - elements[0] = x; - elements[1] = y; - elements[2] = z; - } - - Vector3(const float v[3]) - { - elements[0] = v[0]; - elements[1] = v[1]; - elements[2] = v[2]; - } - - const float& operator[](long i) const { return elements[i]; } - float& operator[](long i) { return elements[i]; } -}; - -/* - * A simple array of four floats that can be indexed into. - */ -struct Vector4 { -public: - float elements[4]; // storage is public for easy access - - inline Vector4() {} - Vector4(float x, float y, float z, float w) - { - elements[0] = x; - elements[1] = y; - elements[2] = z; - elements[3] = w; - } - Vector4(const float v[4]) - { - elements[0] = v[0]; - elements[1] = v[1]; - elements[2] = v[2]; - elements[3] = v[3]; - } - - const float& operator[](long i) const { return elements[i]; } - float& operator[](long i) { return elements[i]; } -}; +#include +#include // VTABLE: LEGO1 0x100d4288 -// SIZE 0x8 -class Vector2Impl { +// SIZE 0x08 +class Vector2 { public: // FUNCTION: LEGO1 0x1000c0f0 - inline Vector2Impl(float* p_data) { SetData(p_data); } + inline Vector2(float* p_data) { SetData(p_data); } - // vtable + 0x00 (no virtual destructor) - virtual void AddScalarImpl(float p_value) = 0; - virtual void AddVectorImpl(float* p_value) = 0; - virtual void SubVectorImpl(float* p_value) = 0; - virtual void MullScalarImpl(float* p_value) = 0; + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. + + // FUNCTION: LEGO1 0x10001f80 + virtual void AddImpl(float* p_value) + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x10001fa0 + virtual void AddImpl(float p_value) + { + m_data[0] += p_value; + m_data[1] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x10001fc0 + virtual void SubImpl(float* p_value) + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + } // vtable+0x08 + + // Those are also overloads in all likelihood, + // but we need a type to do that. + + // FUNCTION: LEGO1 0x10002000 + virtual void MulScalarImpl(float* p_value) + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10001fe0 + virtual void MulVectorImpl(float* p_value) + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x10002020 + virtual void DivScalarImpl(float* p_value) + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x10002040 + virtual float DotImpl(float* p_a, float* p_b) const { return p_b[0] * p_a[0] + p_b[1] * p_a[1]; } // vtable+0x18 - // vtable + 0x10 - virtual void MullVectorImpl(float* p_value) = 0; - virtual void DivScalarImpl(float* p_value) = 0; - virtual float DotImpl(float* p_a, float* p_b) const = 0; // FUNCTION: LEGO1 0x10002060 - virtual void SetData(float* p_data) { m_data = p_data; } + virtual void SetData(float* p_data) { m_data = p_data; } // vtable+0x1c - // vtable + 0x20 - virtual void EqualsImpl(float* p_data) = 0; - virtual float* GetData(); - virtual const float* GetData() const; - virtual void Clear() = 0; + // FUNCTION: LEGO1 0x10002070 + virtual void EqualsImpl(float* p_data) { memcpy(m_data, p_data, sizeof(float) * 2); } // vtable+0x20 - // vtable + 0x30 - virtual float Dot(Vector2Impl* p_a, float* p_b) const; - virtual float Dot(float* p_a, Vector2Impl* p_b) const; - virtual float Dot(Vector2Impl* p_a, Vector2Impl* p_b) const; - virtual float Dot(float* p_a, float* p_b) const; + // FUNCTION: LEGO1 0x10002090 + virtual float* GetData() { return m_data; } // vtable+0x28 - // vtable + 0x40 - virtual float LenSquared() const = 0; - virtual int Unitize(); + // FUNCTION: LEGO1 0x100020a0 + virtual const float* GetData() const { return m_data; } // vtable+0x24 - // vtable + 0x48 - virtual void Add(Vector2Impl* p_other); - virtual void Add(float* p_other); - virtual void Add(float p_value); + // FUNCTION: LEGO1 0x100020b0 + virtual void Clear() { memset(m_data, 0, sizeof(float) * 2); } // vtable+0x2c - // vtable + 0x54 - virtual void Sub(Vector2Impl* p_other); - virtual void Sub(float* p_other); + // FUNCTION: LEGO1 0x100020d0 + virtual float Dot(float* p_a, float* p_b) const { return DotImpl(p_a, p_b); } // vtable+0x3c - // vtable + 0x5C - virtual void Mul(float* p_value); - virtual void Mul(Vector2Impl* p_other); - virtual void Mul(float& p_other); - virtual void Div(float& p_value); + // FUNCTION: LEGO1 0x100020f0 + virtual float Dot(Vector2* p_a, Vector2* p_b) const { return DotImpl(p_a->m_data, p_b->m_data); } // vtable+0x38 - // vtable + 0x6C - virtual void SetVector(Vector2Impl* p_other); - virtual void SetVector(float* p_other); + // FUNCTION: LEGO1 0x10002110 + virtual float Dot(float* p_a, Vector2* p_b) const { return DotImpl(p_a, p_b->m_data); } // vtable+0x34 + + // FUNCTION: LEGO1 0x10002130 + virtual float Dot(Vector2* p_a, float* p_b) const { return DotImpl(p_a->m_data, p_b); } // vtable+0x30 + + // FUNCTION: LEGO1 0x10002150 + virtual float LenSquared() const { return m_data[0] * m_data[0] + m_data[1] * m_data[1]; } // vtable+0x40 + + // FUNCTION: LEGO1 0x10002160 + virtual int Unitize() + { + float sq = LenSquared(); + if (sq > 0.0f) { + float root = sqrt(sq); + if (root > 0) { + DivScalarImpl(&root); + return 0; + } + } + return -1; + } // vtable+0x44 + + // FUNCTION: LEGO1 0x100021c0 + virtual void Add(float p_value) { AddImpl(p_value); } // vtable+0x50 + + // FUNCTION: LEGO1 0x100021d0 + virtual void Add(float* p_other) { AddImpl(p_other); } // vtable+0x4c + + // FUNCTION: LEGO1 0x100021e0 + virtual void Add(Vector2* p_other) { AddImpl(p_other->m_data); } // vtable+0x48 + + // FUNCTION: LEGO1 0x100021f0 + virtual void Sub(float* p_other) { SubImpl(p_other); } // vtable+0x58 + + // FUNCTION: LEGO1 0x10002200 + virtual void Sub(Vector2* p_other) { SubImpl(p_other->m_data); } // vtable+0x54 + + // FUNCTION: LEGO1 0x10002210 + virtual void Mul(float* p_other) { MulVectorImpl(p_other); } // vtable+0x64 + + // FUNCTION: LEGO1 0x10002220 + virtual void Mul(Vector2* p_other) { MulVectorImpl(p_other->m_data); } // vtable+0x60 + + // FUNCTION: LEGO1 0x10002230 + virtual void Mul(float& p_value) { MulScalarImpl(&p_value); } // vtable+0x5c + + // FUNCTION: LEGO1 0x10002240 + virtual void Div(float& p_value) { DivScalarImpl(&p_value); } // vtable+0x68 + + // FUNCTION: LEGO1 0x10002250 + virtual void SetVector(float* p_other) { EqualsImpl(p_other); } // vtable+0x70 + + // FUNCTION: LEGO1 0x10002260 + virtual void SetVector(Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c inline float& operator[](size_t idx) { return m_data[idx]; } inline const float& operator[](size_t idx) const { return m_data[idx]; } @@ -119,100 +149,261 @@ class Vector2Impl { }; // VTABLE: LEGO1 0x100d4518 -// SIZE 0x8 -class Vector3Impl : public Vector2Impl { +// SIZE 0x08 +class Vector3 : public Vector2 { public: - inline Vector3Impl(float* p_data) : Vector2Impl(p_data) {} + // FUNCTION: LEGO1 0x1001d150 + inline Vector3(float* p_data) : Vector2(p_data) {} - void AddScalarImpl(float p_value); + // Hack: Some code initializes a Vector3 from a (most likely) const float* source. + // Example: LegoCameraController::GetWorldUp + // Vector3 however is a class that can mutate its underlying source, making + // initialization with a const source fundamentally incompatible. + inline Vector3(const float* p_data) : Vector2((float*) p_data) {} - void AddVectorImpl(float* p_value); + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. - void SubVectorImpl(float* p_value); - void MullScalarImpl(float* p_value); - void MullVectorImpl(float* p_value); - void DivScalarImpl(float* p_value); - float DotImpl(float* p_a, float* p_b) const; + // FUNCTION: LEGO1 0x10002270 + virtual void EqualsCrossImpl(float* p_a, float* p_b) + { + m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; + m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; + m_data[2] = p_a[0] * p_b[1] - p_a[1] * p_b[0]; + } // vtable+0x74 - void EqualsImpl(float* p_data); + // FUNCTION: LEGO1 0x100022c0 + virtual void EqualsCross(Vector3* p_a, Vector3* p_b) { EqualsCrossImpl(p_a->m_data, p_b->m_data); } // vtable+0x80 - void Clear(); + // FUNCTION: LEGO1 0x100022e0 + virtual void EqualsCross(Vector3* p_a, float* p_b) { EqualsCrossImpl(p_a->m_data, p_b); } // vtable+0x7c - float LenSquared() const; + // FUNCTION: LEGO1 0x10002300 + virtual void EqualsCross(float* p_a, Vector3* p_b) { EqualsCrossImpl(p_a, p_b->m_data); } // vtable+0x78 - // vtable + 0x74 - virtual void EqualsCrossImpl(float* p_a, float* p_b); - virtual void EqualsCross(float* p_a, Vector3Impl* p_b); - virtual void EqualsCross(Vector3Impl* p_a, float* p_b); - virtual void EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b); - virtual void EqualsScalar(float* p_value); + // FUNCTION: LEGO1 0x10003bf0 + virtual void EqualsScalar(float* p_value) + { + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; + } // vtable+0x84 + + // Vector2 overrides + + // FUNCTION: LEGO1 0x10003a60 + virtual void AddImpl(float* p_value) override + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x10003a90 + virtual void AddImpl(float p_value) override + { + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x10003ac0 + virtual void SubImpl(float* p_value) override + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; + } // vtable+0x08 + + // FUNCTION: LEGO1 0x10003b20 + virtual void MulScalarImpl(float* p_value) override + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10003af0 + virtual void MulVectorImpl(float* p_value) override + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x10003b50 + virtual void DivScalarImpl(float* p_value) override + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x10003b80 + virtual 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 + + // FUNCTION: LEGO1 0x10003bc0 + virtual void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10003bd0 + virtual 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 inline void Fill(float p_value) { EqualsScalar(&p_value); } + + friend class Mx3DPointFloat; }; // VTABLE: LEGO1 0x100d45a0 // SIZE 0x8 -class Vector4Impl : public Vector3Impl { +class Vector4 : public Vector3 { public: - inline Vector4Impl(float* p_data) : Vector3Impl(p_data) {} + inline Vector4(float* p_data) : Vector3(p_data) {} - void AddScalarImpl(float p_value); + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. - void AddVectorImpl(float* p_value); - - void SubVectorImpl(float* p_value); - void MullScalarImpl(float* p_value); - void MullVectorImpl(float* p_value); - void DivScalarImpl(float* p_value); - float DotImpl(float* p_a, float* p_b) const; - - void EqualsImpl(float* p_data); - - void Clear(); - - float LenSquared() const; - - void EqualsScalar(float* p_value); - - // vtable + 0x88 - virtual void SetMatrixProduct(Vector4Impl* p_a, float* p_b); - virtual void SetMatrixProductImpl(float* p_vec, float* p_mat); - virtual int NormalizeQuaternion(); - virtual void UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b); - - inline Vector4& GetVector() { return *((Vector4*) m_data); } -}; - -// VTABLE: LEGO1 0x100d4488 -// SIZE 0x14 -class Vector3Data : public Vector3Impl { -public: - inline Vector3Data() : Vector3Impl(m_vector.elements) {} - inline Vector3Data(float p_x, float p_y, float p_z) : Vector3Impl(m_vector.elements), m_vector(p_x, p_y, p_z) {} - - void CopyFrom(Vector3Data& p_other) + // FUNCTION: LEGO1 0x10002a40 + virtual void SetMatrixProduct(float* p_vec, float* p_mat) { - EqualsImpl(p_other.m_data); + m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; + m_data[1] = p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; + m_data[2] = p_vec[0] * p_mat[2] + p_vec[1] * p_mat[6] + p_vec[2] * p_mat[10] + p_vec[4] * p_mat[14]; + m_data[3] = p_vec[0] * p_mat[3] + p_vec[1] * p_mat[7] + p_vec[2] * p_mat[11] + p_vec[4] * p_mat[15]; + } // vtable+0x8c - float* dest = m_vector.elements; - float* src = p_other.m_vector.elements; - for (size_t i = sizeof(m_vector) / sizeof(float); i > 0; --i) - *dest++ = *src++; + // FUNCTION: LEGO1 0x10002ae0 + virtual void SetMatrixProduct(Vector4* p_a, float* p_b) { SetMatrixProduct(p_a->m_data, p_b); } // vtable+0x88 + + inline virtual int NormalizeQuaternion(); // vtable+90 + inline virtual void UnknownQuaternionOp(Vector4* p_a, Vector4* p_b); // vtable+94 + + // Vector3 overrides + + // FUNCTION: LEGO1 0x10002870 + virtual void AddImpl(float* p_value) override + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; + m_data[3] += p_value[3]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x100028b0 + virtual void AddImpl(float p_value) override + { + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; + m_data[3] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x100028f0 + virtual void SubImpl(float* p_value) override + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; + m_data[3] -= p_value[3]; + } // vtable+0x08 + + // FUNCTION: LEGO1 0x10002970 + virtual void MulScalarImpl(float* p_value) override + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; + m_data[3] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10002930 + virtual void MulVectorImpl(float* p_value) override + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; + m_data[3] *= p_value[3]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x100029b0 + virtual void DivScalarImpl(float* p_value) override + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; + m_data[3] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x100029f0 + virtual 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 + + // FUNCTION: LEGO1 0x10002b00 + virtual void Clear() override { memset(m_data, 0, sizeof(float) * 4); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10002b20 + virtual 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 + { + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; + m_data[3] = *p_value; + } // vtable+0x84 +}; + +// Note close yet, included because I'm at least confident I know what operation +// it's trying to do. +// STUB: LEGO1 0x10002b70 +inline int Vector4::NormalizeQuaternion() +{ + float* v = m_data; + float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; + if (magnitude > 0.0f) { + float theta = v[3] * 0.5f; + v[3] = cos(theta); + float frac = sin(theta); + magnitude = frac / sqrt(magnitude); + v[0] *= magnitude; + v[1] *= magnitude; + v[2] *= magnitude; + return 0; } - inline void EqualsCross(Vector3Data& p_a, Vector3Data& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } + return -1; +} -private: - Vector3 m_vector; -}; +// FUNCTION: LEGO1 0x10002bf0 +inline void Vector4::UnknownQuaternionOp(Vector4* p_a, Vector4* p_b) +{ + float* bDat = p_b->m_data; + float* aDat = p_a->m_data; -// VTABLE: LEGO1 0x100d41e8 -// SIZE 0x18 -class Vector4Data : public Vector4Impl { -public: - inline Vector4Data() : Vector4Impl(m_vector.elements) {} + this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); + this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; + this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; + this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; -private: - Vector4 m_vector; -}; + m_data[0] = p_b->m_data[3] * p_a->m_data[0] + p_a->m_data[3] * p_b->m_data[0] + m_data[0]; + m_data[1] = p_b->m_data[1] * p_a->m_data[3] + p_a->m_data[1] * p_b->m_data[3] + m_data[1]; + m_data[2] = p_b->m_data[2] * p_a->m_data[3] + p_a->m_data[2] * p_b->m_data[3] + m_data[2]; +} #endif // VECTOR_H diff --git a/LEGO1/res/resource.h b/LEGO1/res/resource.h index 5a51e019..2402acad 100644 --- a/LEGO1/res/resource.h +++ b/LEGO1/res/resource.h @@ -8,5 +8,3 @@ #define LEGO1_LEAF5 108 #define LEGO1_LEAF3 109 #define LEGO1_BUSY 111 - -#define APP_ICON 105 diff --git a/LEGO1/tgl/d3drm/camera.cpp b/LEGO1/tgl/d3drm/camera.cpp index 5084c2ca..9e000ba8 100644 --- a/LEGO1/tgl/d3drm/camera.cpp +++ b/LEGO1/tgl/d3drm/camera.cpp @@ -12,7 +12,7 @@ void* CameraImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a3700 -Result CameraImpl::SetTransformation(const FloatMatrix4& matrix) +Result CameraImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* pTransformation = Translate(matrix, helper); diff --git a/LEGO1/tgl/d3drm/group.cpp b/LEGO1/tgl/d3drm/group.cpp index 022dc757..4b966cd2 100644 --- a/LEGO1/tgl/d3drm/group.cpp +++ b/LEGO1/tgl/d3drm/group.cpp @@ -9,7 +9,7 @@ void* GroupImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a31e0 -Result GroupImpl::SetTransformation(const FloatMatrix4& matrix) +Result GroupImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper); diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index 4c76a365..1e017cf2 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -36,7 +36,7 @@ class MeshImpl; class TextureImpl; class UnkImpl; -// VTABLE 0x100db910 +// VTABLE: LEGO1 0x100db910 class RendererImpl : public Renderer { public: RendererImpl() : m_data(0) {} @@ -105,7 +105,7 @@ void RendererImpl::Destroy() } } -// VTABLE 0x100db988 +// VTABLE: LEGO1 0x100db988 class DeviceImpl : public Device { public: DeviceImpl() : m_data(0) {} @@ -142,7 +142,7 @@ class DeviceImpl : public Device { IDirect3DRMDevice2* m_data; }; -// VTABLE 0x100db9e8 +// VTABLE: LEGO1 0x100db9e8 class ViewImpl : public View { public: ViewImpl() : m_data(0) {} @@ -194,7 +194,7 @@ class ViewImpl : public View { IDirect3DRMViewport* m_data; }; -// VTABLE 0x100dbad8 +// VTABLE: LEGO1 0x100dbad8 class CameraImpl : public Camera { public: CameraImpl() : m_data(0) {} @@ -209,7 +209,7 @@ class CameraImpl : public Camera { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -219,7 +219,7 @@ class CameraImpl : public Camera { IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbaf8 +// VTABLE: LEGO1 0x100dbaf8 class LightImpl : public Light { public: LightImpl() : m_data(0) {} @@ -234,7 +234,7 @@ class LightImpl : public Light { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); virtual Result SetColor(float r, float g, float b); inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -245,7 +245,7 @@ class LightImpl : public Light { IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbb88 +// VTABLE: LEGO1 0x100dbb88 class MeshImpl : public Mesh { public: MeshImpl() : m_data(0) {} @@ -285,7 +285,7 @@ class MeshImpl : public Mesh { MeshData* m_data; }; -// VTABLE 0x100dba68 +// VTABLE: LEGO1 0x100dba68 class GroupImpl : public Group { public: GroupImpl() : m_data(0) {} @@ -300,7 +300,7 @@ class GroupImpl : public Group { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); virtual Result SetColor(float r, float g, float b, float a); // vtable+0x10 @@ -324,7 +324,7 @@ class GroupImpl : public Group { IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbb18 +// VTABLE: LEGO1 0x100dbb18 class UnkImpl : public Unk { public: UnkImpl() : m_data(0) {} @@ -384,7 +384,7 @@ class TglD3DRMIMAGE { int m_texelsAllocatedByClient; }; -// VTABLE 0x100dbb48 +// VTABLE: LEGO1 0x100dbb48 class TextureImpl : public Texture { public: TextureImpl() : m_data(0) {} @@ -474,7 +474,7 @@ inline D3DRMPROJECTIONTYPE Translate(ProjectionType tglProjectionType) // Yes this function serves no purpose, originally they intended it to // convert from doubles to floats but ended up using floats throughout // the software stack. -inline D3DRMMATRIX4D* Translate(const FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4) +inline D3DRMMATRIX4D* Translate(FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4) { for (int i = 0; i < (sizeof(rD3DRMMatrix4x4) / sizeof(rD3DRMMatrix4x4[0])); i++) { for (int j = 0; j < (sizeof(rD3DRMMatrix4x4[0]) / sizeof(rD3DRMMatrix4x4[0][0])); j++) { diff --git a/LEGO1/tgl/d3drm/light.cpp b/LEGO1/tgl/d3drm/light.cpp index 5ceafa4b..dfc23b44 100644 --- a/LEGO1/tgl/d3drm/light.cpp +++ b/LEGO1/tgl/d3drm/light.cpp @@ -12,7 +12,7 @@ void* LightImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a3780 -Result LightImpl::SetTransformation(const FloatMatrix4& matrix) +Result LightImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper); diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index dfc18f3f..137a78ff 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -98,7 +98,7 @@ class Mesh; class Texture; class Unk; -// VTABLE 0x100db980 +// VTABLE: LEGO1 0x100db980 class Object { public: virtual ~Object() {} @@ -106,7 +106,7 @@ class Object { virtual void* ImplementationDataPtr() = 0; }; -// VTABLE 0x100db948 +// VTABLE: LEGO1 0x100db948 class Renderer : public Object { public: // vtable+0x08 @@ -146,7 +146,7 @@ class Renderer : public Object { Renderer* CreateRenderer(); -// VTABLE 0x100db9b8 +// VTABLE: LEGO1 0x100db9b8 class Device : public Object { public: // vtable+0x08 @@ -165,7 +165,7 @@ class Device : public Object { virtual void InitFromWindowsDevice(Device*) = 0; }; -// VTABLE 0x100dba28 +// VTABLE: LEGO1 0x100dba28 class View : public Object { public: virtual Result Add(const Light*) = 0; @@ -219,20 +219,20 @@ class View : public Object { ) = 0; }; -// VTABLE 0x100dbae8 +// VTABLE: LEGO1 0x100dbae8 class Camera : public Object { public: - virtual Result SetTransformation(const FloatMatrix4&) = 0; + virtual Result SetTransformation(FloatMatrix4&) = 0; }; -// VTABLE 0x100dbb08 +// VTABLE: LEGO1 0x100dbb08 class Light : public Object { public: - virtual Result SetTransformation(const FloatMatrix4&) = 0; + virtual Result SetTransformation(FloatMatrix4&) = 0; virtual Result SetColor(float r, float g, float b) = 0; }; -// VTABLE 0x100dbbb0 +// VTABLE: LEGO1 0x100dbbb0 class Mesh : public Object { public: virtual Result SetColor(float r, float g, float b, float a) = 0; @@ -249,10 +249,10 @@ class Mesh : public Object { virtual Mesh* ShallowClone(Unk*) = 0; }; -// VTABLE 0x100dbaa0 +// VTABLE: LEGO1 0x100dbaa0 class Group : public Object { public: - virtual Result SetTransformation(const FloatMatrix4&) = 0; + virtual Result SetTransformation(FloatMatrix4&) = 0; virtual Result SetColor(float r, float g, float b, float a) = 0; virtual Result SetTexture(const Texture*) = 0; virtual Result GetTexture(Texture*&) = 0; @@ -271,7 +271,7 @@ class Group : public Object { // Don't know what this is. Seems like another Tgl object which // was not in the leaked Tgl code. My suspicion is that it's // some kind of builder class for creating meshes. -// VTABLE 0x100dbb30 +// VTABLE: LEGO1 0x100dbb30 class Unk : public Object { public: virtual Result SetMeshData( @@ -287,7 +287,7 @@ class Unk : public Object { virtual Unk* Clone() = 0; }; -// VTABLE 0x100dbb68 +// VTABLE: LEGO1 0x100dbb68 class Texture : public Object { public: // vtable+0x08 diff --git a/LEGO1/tgl/tglvector.h b/LEGO1/tgl/tglvector.h index 78255937..8612724f 100644 --- a/LEGO1/tgl/tglvector.h +++ b/LEGO1/tgl/tglvector.h @@ -1,8 +1,5 @@ #ifndef _tglVector_h #define _tglVector_h -// Note: This file is almost an exact copy of the one from -// the leak but using floats instead of doubles, hence the -// strange formatting in some places. #include "math.h" // sin() in RotateAroundY() @@ -26,253 +23,7 @@ inline float RadiansToDegrees(float radians) return (radians / Constant::Pi) * 180.0; } -////////////////////////////////////////////////////////////////////////////// -// -// Array - -template -class Array { -public: - Array() {} - Array(const Array& rArray) { *this = rArray; } - ~Array() {} - - const T& operator[](int i) const { return m_elements[i]; }; - T& operator[](int i) { return m_elements[i]; }; - - Array& operator=(const Array&); - void operator+=(const Array&); - -protected: - T m_elements[N]; -}; - -////////////////////////////////////////////////////////////////////////////// -// -// Array implementation - -template -inline Array& Array::operator=(const Array& rArray) -{ - int i; - - for (i = 0; i < N; i++) { - m_elements[i] = rArray.m_elements[i]; - } - - return *this; -} - -template -inline void Array::operator+=(const Array& rArray) -{ - int i; - - for (i = 0; i < N; i++) { - m_elements[i] += rArray.m_elements[i]; - } -} - -////////////////////////////////////////////////////////////////////////////// -// -// FloatMatrix4 - -class FloatMatrix4 : public Array, 4> { -public: - FloatMatrix4() {} - FloatMatrix4(const FloatMatrix4& rMatrix) { *this = rMatrix; } - FloatMatrix4(const FloatMatrix4&, const FloatMatrix4&); - - void operator*=(const FloatMatrix4&); -}; - -////////////////////////////////////////////////////////////////////////////// -// -// FloatMatrix4 implementation - -inline FloatMatrix4::FloatMatrix4(const FloatMatrix4& rMatrix1, const FloatMatrix4& rMatrix2) -{ - for (int row = 0; row < 4; row++) { - for (int column = 0; column < 4; column++) { - float element = 0; - - for (int i = 0; i < 4; i++) { - element += rMatrix1[row][i] * rMatrix2[i][column]; - } - - m_elements[row][column] = element; - } - } -} - -inline void FloatMatrix4::operator*=(const FloatMatrix4& rMatrix) -{ - FloatMatrix4 temp(*this, rMatrix); - - // *this = FloatMatrix4(*this, rMatrix); - *this = temp; -} - -////////////////////////////////////////////////////////////////////////////// -// -// Transformation matrices - -class Translation : public FloatMatrix4 { -public: - Translation(const float[3]); - Translation(float x, float y, float z); - -protected: - void Init(float x, float y, float z); -}; - -class Scale : public FloatMatrix4 { -public: - Scale(const float[3]); - Scale(float x, float y, float z); - Scale(float); - -protected: - void Init(float x, float y, float z); -}; - -class RotationX : public FloatMatrix4 { -public: - RotationX(float radians); -}; - -class RotationY : public FloatMatrix4 { -public: - RotationY(float radians); -}; -////////////////////////////////////////////////////////////////////////////// -// -// Transformation matrices implementation - -inline Translation::Translation(const float vector[3]) -{ - Init(vector[0], vector[1], vector[2]); -} - -inline Translation::Translation(float x, float y, float z) -{ - Init(x, y, z); -} - -inline void Translation::Init(float x, float y, float z) -{ - m_elements[0][0] = 1; - m_elements[0][1] = 0; - m_elements[0][2] = 0; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = 1; - m_elements[1][2] = 0; - m_elements[1][3] = 0; - - m_elements[2][0] = 0; - m_elements[2][1] = 0; - m_elements[2][2] = 1; - m_elements[2][3] = 0; - - m_elements[3][0] = x; - m_elements[3][1] = y; - m_elements[3][2] = z; - m_elements[3][3] = 1; -} - -inline Scale::Scale(const float vector[3]) -{ - Init(vector[0], vector[1], vector[2]); -} - -inline Scale::Scale(float x, float y, float z) -{ - Init(x, y, z); -} - -inline Scale::Scale(float scale) -{ - Init(scale, scale, scale); -} - -inline void Scale::Init(float x, float y, float z) -{ - m_elements[0][0] = x; - m_elements[0][1] = 0; - m_elements[0][2] = 0; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = y; - m_elements[1][2] = 0; - m_elements[1][3] = 0; - - m_elements[2][0] = 0; - m_elements[2][1] = 0; - m_elements[2][2] = z; - m_elements[2][3] = 0; - - m_elements[3][0] = 0; - m_elements[3][1] = 0; - m_elements[3][2] = 0; - m_elements[3][3] = 1; -} - -inline RotationX::RotationX(float radians) -{ - float cosRadians = cos(radians); - float sinRadians = sin(radians); - - m_elements[0][0] = 1; - m_elements[0][1] = 0; - m_elements[0][2] = 0; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = cosRadians; - m_elements[1][2] = -sinRadians; - m_elements[1][3] = 0; - - m_elements[2][0] = 0; - m_elements[2][1] = sinRadians; - m_elements[2][2] = cosRadians; - m_elements[2][3] = 0; - - m_elements[3][0] = 0; - m_elements[3][1] = 0; - m_elements[3][2] = 0; - m_elements[3][3] = 1; -} - -inline RotationY::RotationY(float radians) -{ - float cosRadians = cos(radians); - float sinRadians = sin(radians); - - m_elements[0][0] = cosRadians; - m_elements[0][1] = 0; - m_elements[0][2] = sinRadians; - m_elements[0][3] = 0; - - m_elements[1][0] = 0; - m_elements[1][1] = 1; - m_elements[1][2] = 0; - m_elements[1][3] = 0; - - m_elements[2][0] = -sinRadians; - m_elements[2][1] = 0; - m_elements[2][2] = cosRadians; - m_elements[2][3] = 0; - - m_elements[3][0] = 0; - m_elements[3][1] = 0; - m_elements[3][2] = 0; - m_elements[3][3] = 1; -} - -////////////////////////////////////////////////////////////////////////////// +typedef float FloatMatrix4[4][4]; } // namespace Tgl diff --git a/LEGO1/viewmanager/viewlodlist.h b/LEGO1/viewmanager/viewlodlist.h index 9dc06d7b..1ecec3f8 100644 --- a/LEGO1/viewmanager/viewlodlist.h +++ b/LEGO1/viewmanager/viewlodlist.h @@ -93,6 +93,22 @@ class ViewLODListManager { ViewLODListMap m_map; }; +// FUNCTION: LEGO1 0x1001dde0 +// _Lockit::~_Lockit + +// clang-format off +// TEMPLATE: LEGO1 0x100a7890 +// _Tree,map >::_Kfn,ROINameComparator,allocator >::~_Tree,map >::~map > +// clang-format on + +// TEMPLATE: LEGO1 0x100a70e0 +// Map::~Map + ////////////////////////////////////////////////////////////////////////////// // // ViewLODList implementation @@ -119,4 +135,11 @@ inline int ViewLODList::Release() return m_refCount; } +#ifdef _DEBUG +inline void ViewLODList::Dump(void (*pTracer)(const char*, ...)) const +{ + // FIXME: dump something +} +#endif + #endif // VIEWLODLIST_H diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp index 8ec2aad2..7d412641 100644 --- a/LEGO1/viewmanager/viewmanager.cpp +++ b/LEGO1/viewmanager/viewmanager.cpp @@ -1,7 +1,32 @@ #include "viewmanager.h" +// STUB: LEGO1 0x100a5eb0 +ViewManager::ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view) +{ +} + +// STUB: LEGO1 0x100a60c0 +ViewManager::~ViewManager() +{ +} + // STUB: LEGO1 0x100a64d0 void ViewManager::RemoveAll(ViewROI*) { // TODO } + +// STUB: LEGO1 0x100a6d50 +void ViewManager::SetResolution(int width, int height) +{ +} + +// STUB: LEGO1 0x100a6d70 +void ViewManager::SetFrustrum(float fov, float front, float back) +{ +} + +// STUB: LEGO1 0x100a6da0 +void ViewManager::SetPOVSource(const OrientableROI* point_of_view) +{ +} diff --git a/LEGO1/viewmanager/viewmanager.h b/LEGO1/viewmanager/viewmanager.h index 2b0d102e..03b23366 100644 --- a/LEGO1/viewmanager/viewmanager.h +++ b/LEGO1/viewmanager/viewmanager.h @@ -1,11 +1,23 @@ #ifndef VIEWMANAGER_H #define VIEWMANAGER_H -class ViewROI; +#include "viewroi.h" +// VTABLE: LEGO1 0x100dbd88 +// SIZE 0x1bc class ViewManager { public: + ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view); + virtual ~ViewManager(); + __declspec(dllexport) void RemoveAll(ViewROI*); + + void SetPOVSource(const OrientableROI* point_of_view); + void SetResolution(int width, int height); + void SetFrustrum(float fov, float front, float back); + +private: + undefined m_pad[0x1b8]; }; #endif // VIEWMANAGER_H diff --git a/LEGO1/viewmanager/viewroi.cpp b/LEGO1/viewmanager/viewroi.cpp index 523814a2..ff846394 100644 --- a/LEGO1/viewmanager/viewroi.cpp +++ b/LEGO1/viewmanager/viewroi.cpp @@ -2,6 +2,8 @@ #include "decomp.h" +#include + DECOMP_SIZE_ASSERT(ViewROI, 0xe0) // GLOBAL: LEGO1 0x101013d8 @@ -26,13 +28,15 @@ Tgl::Group* ViewROI::GetGeometry() } // FUNCTION: LEGO1 0x100a9ee0 -void ViewROI::UpdateWorldData(const Matrix4Data& parent2world) +void ViewROI::UpdateWorldData(const MxMatrix& parent2world) { OrientableROI::UpdateWorldData(parent2world); + if (geometry) { - Tgl::FloatMatrix4 mat; - SETMAT4(mat, m_local2world.GetMatrix()); - Tgl::Result result = geometry->SetTransformation(mat); + Tgl::FloatMatrix4 matrix; + Matrix4 in(matrix); + SETMAT4(in, m_local2world); + Tgl::Result result = geometry->SetTransformation(matrix); // assert(Tgl::Succeeded(result)); } } diff --git a/LEGO1/viewmanager/viewroi.h b/LEGO1/viewmanager/viewroi.h index 02d69ab5..7157033a 100644 --- a/LEGO1/viewmanager/viewroi.h +++ b/LEGO1/viewmanager/viewroi.h @@ -52,7 +52,7 @@ class ViewROI : public OrientableROI { protected: Tgl::Group* geometry; - void UpdateWorldData(const Matrix4Data& parent2world); + void UpdateWorldData(const MxMatrix& parent2world); }; // SYNTHETIC: LEGO1 0x100aa250 diff --git a/tools/isledecomp/isledecomp/bin.py b/tools/isledecomp/isledecomp/bin.py index 26dd00f8..3b600af6 100644 --- a/tools/isledecomp/isledecomp/bin.py +++ b/tools/isledecomp/isledecomp/bin.py @@ -97,6 +97,8 @@ def __init__(self, filename: str, find_str: bool = False) -> None: self.find_str = find_str self._potential_strings = {} self._relocated_addrs = set() + self.imports = [] + self.thunks = [] def __enter__(self): logger.debug("Bin %s Enter", self.filename) @@ -132,6 +134,8 @@ def __enter__(self): sect.virtual_address += self.imagebase self._populate_relocations() + self._populate_imports() + self._populate_thunks() # This is a (semi) expensive lookup that is not necesssary in every case. # We can find strings in the original if we have coverage using STRING markers. @@ -238,6 +242,78 @@ def _populate_relocations(self): (relocated_addr,) = struct.unpack(" bool: return section is not None + def read_string(self, offset: int, chunk_size: int = 1000) -> Optional[bytes]: + """Read until we find a zero byte.""" + b = self.read(offset, chunk_size) + if b is None: + return None + + try: + return b[: b.index(b"\x00")] + except ValueError: + # No terminator found, just return what we have + return b + def read(self, offset: 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.""" diff --git a/tools/isledecomp/isledecomp/compare/asm/__init__.py b/tools/isledecomp/isledecomp/compare/asm/__init__.py new file mode 100644 index 00000000..3fd22f6e --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/asm/__init__.py @@ -0,0 +1,2 @@ +from .parse import ParseAsm +from .swap import can_resolve_register_differences diff --git a/tools/isledecomp/isledecomp/compare/asm/parse.py b/tools/isledecomp/isledecomp/compare/asm/parse.py new file mode 100644 index 00000000..ee9c9154 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/asm/parse.py @@ -0,0 +1,152 @@ +"""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 +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 typing import Callable, List, Optional, Tuple +from collections import namedtuple +from capstone import Cs, CS_ARCH_X86, CS_MODE_32 + +disassembler = Cs(CS_ARCH_X86, CS_MODE_32) + +ptr_replace_regex = re.compile(r"ptr \[(0x[0-9a-fA-F]+)\]") + +DisasmLiteInst = namedtuple("DisasmLiteInst", "address, size, mnemonic, op_str") + + +def from_hex(string: str) -> Optional[int]: + try: + return int(string, 16) + except ValueError: + pass + + return None + + +class ParseAsm: + def __init__( + self, + relocate_lookup: Optional[Callable[[int], bool]] = None, + name_lookup: Optional[Callable[[int], str]] = None, + ) -> None: + self.relocate_lookup = relocate_lookup + self.name_lookup = name_lookup + self.replacements = {} + self.number_placeholders = True + + def reset(self): + self.replacements = {} + + def is_relocated(self, addr: int) -> bool: + if callable(self.relocate_lookup): + return self.relocate_lookup(addr) + + return False + + def lookup(self, addr: int) -> Optional[str]: + """Return a replacement name for this address if we find one.""" + if (cached := self.replacements.get(addr, None)) is not None: + return cached + + if callable(self.name_lookup): + if (name := self.name_lookup(addr)) is not None: + self.replacements[addr] = name + return name + + return None + + def replace(self, addr: int) -> str: + """Same function as lookup above, but here we return a placeholder + if there is no better name to use.""" + if (name := self.lookup(addr)) is not None: + return name + + # The placeholder number corresponds to the number of addresses we have + # already replaced. This is so the number will be consistent across the diff + # if we can replace some symbols with actual names in recomp but not orig. + idx = len(self.replacements) + 1 + placeholder = f"" if self.number_placeholders else "" + self.replacements[addr] = placeholder + return placeholder + + def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]: + if len(inst.op_str) == 0: + # Nothing to sanitize + return (inst.mnemonic, "") + + # 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 + # absolute indirect that we will handle below. + # Providing the starting address of the function to capstone.disasm has + # automatically resolved relative offsets to an absolute address. + # We will have to undo this for some of the jumps or they will not match. + op_str_address = from_hex(inst.op_str) + + if op_str_address is not None: + if inst.mnemonic == "call": + return (inst.mnemonic, self.replace(op_str_address)) + + if inst.mnemonic == "jmp": + # The unwind section contains JMPs to other functions. + # If we have a name for this address, use it. If not, + # do not create a new placeholder. We will instead + # fall through to generic jump handling below. + potential_name = self.lookup(op_str_address) + if potential_name is not None: + return (inst.mnemonic, potential_name) + + if inst.mnemonic.startswith("j"): + # i.e. if this is any jump + # Show the jump offset rather than the absolute address + jump_displacement = op_str_address - (inst.address + inst.size) + return (inst.mnemonic, hex(jump_displacement)) + + def filter_out_ptr(match): + """Helper for re.sub, see below""" + offset = from_hex(match.group(1)) + + if offset is not None: + # We assume this is always an address to replace + placeholder = self.replace(offset) + return f"ptr [{placeholder}]" + + # Strict regex should ensure we can read the hex number. + # But just in case: return the string with no changes + return match.group(0) + + op_str = ptr_replace_regex.sub(filter_out_ptr, inst.op_str) + + # 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) + + 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): + # 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)) + # mnemonic + " " + op_str + asm.append(" ".join(result)) + + return asm diff --git a/tools/isledecomp/isledecomp/compare/asm/swap.py b/tools/isledecomp/isledecomp/compare/asm/swap.py new file mode 100644 index 00000000..599444cf --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/asm/swap.py @@ -0,0 +1,80 @@ +import re + +REGISTER_LIST = set( + [ + "ax", + "bp", + "bx", + "cx", + "di", + "dx", + "eax", + "ebp", + "ebx", + "ecx", + "edi", + "edx", + "esi", + "esp", + "si", + "sp", + ] +) +WORDS = re.compile(r"\w+") + + +def get_registers(line: str): + to_replace = [] + # use words regex to find all matching positions: + for match in WORDS.finditer(line): + reg = match.group(0) + if reg in REGISTER_LIST: + to_replace.append((reg, match.start())) + return to_replace + + +def replace_register( + lines: list[str], start_line: int, reg: str, replacement: str +) -> list[str]: + return [ + line.replace(reg, replacement) if i >= start_line else line + for i, line in enumerate(lines) + ] + + +# Is it possible to make new_asm the same as original_asm by swapping registers? +def can_resolve_register_differences(original_asm, new_asm): + # Split the ASM on spaces to get more granularity, and so + # that we don't modify the original arrays passed in. + original_asm = [part for line in original_asm for part in line.split()] + new_asm = [part for line in new_asm for part in line.split()] + + # Swapping ain't gonna help if the lengths are different + if len(original_asm) != len(new_asm): + return False + + # Look for the mismatching lines + for i, original_line in enumerate(original_asm): + new_line = new_asm[i] + if new_line != original_line: + # Find all the registers to replace + to_replace = get_registers(original_line) + + for replace in to_replace: + (reg, reg_index) = replace + replacing_reg = new_line[reg_index : reg_index + len(reg)] + if replacing_reg in REGISTER_LIST: + if replacing_reg != reg: + # Do a three-way swap replacing in all the subsequent lines + temp_reg = "&" * len(reg) + new_asm = replace_register(new_asm, i, replacing_reg, temp_reg) + new_asm = replace_register(new_asm, i, reg, replacing_reg) + new_asm = replace_register(new_asm, i, temp_reg, reg) + else: + # No replacement to do, different code, bail out + return False + # Check if the lines are now the same + for i, original_line in enumerate(original_asm): + if new_asm[i] != original_line: + return False + return True diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index 07860203..c8ae7809 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -1,11 +1,14 @@ import os import logging -from typing import List, Optional +import difflib +from dataclasses import dataclass +from typing import Iterable, List, Optional from isledecomp.cvdump.demangler import demangle_string_const from isledecomp.cvdump import Cvdump, CvdumpAnalysis from isledecomp.parser import DecompCodebase from isledecomp.dir import walk_source_dir from isledecomp.types import SymbolType +from isledecomp.compare.asm import ParseAsm, can_resolve_register_differences from .db import CompareDb, MatchInfo from .lines import LinesDb @@ -13,6 +16,24 @@ logger = logging.getLogger(__name__) +@dataclass +class DiffReport: + orig_addr: int + recomp_addr: int + name: str + udiff: Optional[List[str]] = None + ratio: float = 0.0 + is_effective_match: bool = False + + @property + def effective_ratio(self) -> float: + return 1.0 if self.is_effective_match else self.ratio + + def __str__(self) -> str: + """For debug purposes. Proper diff printing (with coloring) is in another module.""" + return f"{self.name} (0x{self.orig_addr:x}) {self.ratio*100:.02f}%{'*' if self.is_effective_match else ''}" + + class Compare: # pylint: disable=too-many-instance-attributes def __init__(self, orig_bin, recomp_bin, pdb_file, code_dir): @@ -27,6 +48,7 @@ def __init__(self, orig_bin, recomp_bin, pdb_file, code_dir): self._load_cvdump() self._load_markers() self._find_original_strings() + self._match_thunks() def _load_cvdump(self): logger.info("Parsing %s ...", self.pdb_file) @@ -63,13 +85,19 @@ def _load_cvdump(self): if sym.node_type == SymbolType.STRING: string_info = demangle_string_const(sym.decorated_name) + if string_info is None: + logger.debug( + "Could not demangle string symbol: %s", sym.decorated_name + ) + continue + # TODO: skip unicode for now. will need to handle these differently. if string_info.is_utf16: continue raw = self.recomp_bin.read(addr, sym.size()) try: - sym.friendly_name = raw.decode("latin1") + sym.friendly_name = raw.decode("latin1").rstrip("\x00") except UnicodeDecodeError: pass @@ -112,6 +140,26 @@ def _load_markers(self): for tbl in codebase.iter_vtables(): self._db.match_vtable(tbl.offset, tbl.name) + for string in codebase.iter_strings(): + # Not that we don't trust you, but we're checking the string + # annotation to make sure it is accurate. + try: + # TODO: would presumably fail for wchar_t strings + orig = self.orig_bin.read_string(string.offset).decode("latin1") + string_correct = string.name == orig + except UnicodeDecodeError: + string_correct = False + + if not string_correct: + logger.error( + "Data at 0x%x does not match string %s", + string.offset, + repr(string.name), + ) + continue + + self._db.match_string(string.offset, string.name) + def _find_original_strings(self): """Go to the original binary and look for the specified string constants to find a match. This is a (relatively) expensive operation so we only @@ -126,6 +174,46 @@ def _find_original_strings(self): self._db.match_string(addr, string) + def _match_thunks(self): + orig_byaddr = { + addr: (dll.upper(), name) for (dll, name, addr) in self.orig_bin.imports + } + recomp_byname = { + (dll.upper(), name): addr for (dll, name, addr) in self.recomp_bin.imports + } + # Combine these two dictionaries. We don't care about imports from recomp + # not found in orig because: + # 1. They shouldn't be there + # 2. They are already identified via cvdump + orig_to_recomp = { + addr: recomp_byname.get(pair, None) for addr, pair in orig_byaddr.items() + } + + # Now: we have the IAT offset in each matched up, so we need to make + # the connection between the thunk functions. + # We already have the symbol name we need from the PDB. + orig_thunks = { + iat_ofs: func_ofs for (func_ofs, iat_ofs) in self.orig_bin.thunks + } + recomp_thunks = { + iat_ofs: func_ofs for (func_ofs, iat_ofs) in self.recomp_bin.thunks + } + + for orig, recomp in orig_to_recomp.items(): + self._db.set_pair(orig, recomp, SymbolType.POINTER) + thunk_from_orig = orig_thunks.get(orig, None) + thunk_from_recomp = recomp_thunks.get(recomp, None) + + if thunk_from_orig is not None and thunk_from_recomp is not None: + self._db.set_function_pair(thunk_from_orig, thunk_from_recomp) + # Don't compare thunk functions for now. The comparison isn't + # "useful" in the usual sense. We are only looking at the 6 + # bytes of the jmp instruction and not the larger context of + # where this function is. Also: these will always match 100% + # because we are searching for a match to register this as a + # function in the first place. + self._db.skip_compare(thunk_from_orig) + def get_one_function(self, addr: int) -> Optional[MatchInfo]: """i.e. verbose mode for reccmp""" return self._db.get_one_function(addr) @@ -133,8 +221,84 @@ def get_one_function(self, addr: int) -> Optional[MatchInfo]: def get_functions(self) -> List[MatchInfo]: return self._db.get_matches(SymbolType.FUNCTION) - def compare_functions(self): - pass + 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( + 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) + + def orig_should_replace(addr: int) -> bool: + return addr > self.orig_bin.imagebase and self.orig_bin.is_relocated_addr( + addr + ) + + def recomp_should_replace(addr: int) -> bool: + return ( + addr > self.recomp_bin.imagebase + and self.recomp_bin.is_relocated_addr(addr) + ) + + def orig_lookup(addr: int) -> Optional[str]: + m = self._db.get_by_orig(addr) + if m is None: + return None + + return m.match_name() + + def recomp_lookup(addr: int) -> Optional[str]: + m = self._db.get_by_recomp(addr) + if m is None: + return None + + return m.match_name() + + orig_parse = ParseAsm( + relocate_lookup=orig_should_replace, name_lookup=orig_lookup + ) + recomp_parse = ParseAsm( + relocate_lookup=recomp_should_replace, name_lookup=recomp_lookup + ) + + orig_asm = orig_parse.parse_asm(orig_raw, match.orig_addr) + recomp_asm = recomp_parse.parse_asm(recomp_raw, match.recomp_addr) + + diff = difflib.SequenceMatcher(None, orig_asm, recomp_asm) + ratio = diff.ratio() + + if ratio != 1.0: + # 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) + else: + is_effective_match = False + unified_diff = [] + + return DiffReport( + orig_addr=match.orig_addr, + recomp_addr=match.recomp_addr, + name=match.name, + udiff=unified_diff, + ratio=ratio, + is_effective_match=is_effective_match, + ) + + def compare_function(self, addr: int) -> Optional[DiffReport]: + match = self.get_one_function(addr) + if match is None: + return None + + return self._compare_function(match) + + def compare_functions(self) -> Iterable[DiffReport]: + for match in self.get_functions(): + yield self._compare_function(match) def compare_variables(self): pass diff --git a/tools/isledecomp/isledecomp/compare/db.py b/tools/isledecomp/isledecomp/compare/db.py index 850f25fd..d2c2cbf9 100644 --- a/tools/isledecomp/isledecomp/compare/db.py +++ b/tools/isledecomp/isledecomp/compare/db.py @@ -2,7 +2,6 @@ addresses/symbols that we want to compare between the original and recompiled binaries.""" import sqlite3 import logging -from collections import namedtuple from typing import List, Optional from isledecomp.types import SymbolType @@ -16,12 +15,36 @@ size int, should_skip int default(FALSE) ); + CREATE INDEX `symbols_or` ON `symbols` (orig_addr); CREATE INDEX `symbols_re` ON `symbols` (recomp_addr); - CREATE INDEX `symbols_na` ON `symbols` (compare_type, name); """ -MatchInfo = namedtuple("MatchInfo", "orig_addr, recomp_addr, size, name") +class MatchInfo: + def __init__( + self, + ctype: Optional[int], + orig: Optional[int], + recomp: Optional[int], + name: Optional[str], + size: Optional[int], + ) -> None: + self.compare_type = SymbolType(ctype) if ctype is not None else None + self.orig_addr = orig + self.recomp_addr = recomp + self.name = name + self.size = size + + def match_name(self) -> str: + """Combination of the name and compare type. + Intended for name substitution in the diff. If there is a diff, + it will be more obvious what this symbol indicates.""" + if self.name is None: + return None + + ctype = self.compare_type.name if self.compare_type is not None else "UNK" + name = repr(self.name) if ctype == "STRING" else self.name + return f"{name} ({ctype})" def matchinfo_factory(_, row): @@ -61,7 +84,7 @@ def get_unmatched_strings(self) -> List[str]: def get_one_function(self, addr: int) -> Optional[MatchInfo]: cur = self._db.execute( - """SELECT orig_addr, recomp_addr, size, name + """SELECT compare_type, orig_addr, recomp_addr, name, size FROM `symbols` WHERE compare_type = ? AND orig_addr = ? @@ -74,9 +97,31 @@ def get_one_function(self, addr: int) -> Optional[MatchInfo]: cur.row_factory = matchinfo_factory return cur.fetchone() + def get_by_orig(self, addr: int) -> Optional[MatchInfo]: + cur = self._db.execute( + """SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + WHERE orig_addr = ? + """, + (addr,), + ) + cur.row_factory = matchinfo_factory + return cur.fetchone() + + def get_by_recomp(self, addr: int) -> Optional[MatchInfo]: + cur = self._db.execute( + """SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + WHERE recomp_addr = ? + """, + (addr,), + ) + cur.row_factory = matchinfo_factory + return cur.fetchone() + def get_matches(self, compare_type: SymbolType) -> List[MatchInfo]: cur = self._db.execute( - """SELECT orig_addr, recomp_addr, size, name + """SELECT compare_type, orig_addr, recomp_addr, name, size FROM `symbols` WHERE compare_type = ? AND orig_addr IS NOT NULL @@ -90,14 +135,20 @@ def get_matches(self, compare_type: SymbolType) -> List[MatchInfo]: return cur.fetchall() - def set_function_pair(self, orig: int, recomp: int) -> bool: - """For lineref match or _entry""" + def set_pair( + self, orig: int, recomp: int, compare_type: Optional[SymbolType] = None + ) -> bool: + 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 = ?", - (orig, SymbolType.FUNCTION.value, recomp), + (orig, compare_value, recomp), ) return cur.rowcount > 0 + + 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? def skip_compare(self, orig: int): @@ -147,3 +198,5 @@ def match_string(self, addr: int, value: str) -> bool: if not did_match: escaped = repr(value) logger.error("Failed to find string: %s", escaped) + + return did_match diff --git a/tools/isledecomp/isledecomp/cvdump/analysis.py b/tools/isledecomp/isledecomp/cvdump/analysis.py index 720593be..330429dd 100644 --- a/tools/isledecomp/isledecomp/cvdump/analysis.py +++ b/tools/isledecomp/isledecomp/cvdump/analysis.py @@ -94,7 +94,11 @@ def set_decorated(self, name: str): def name(self) -> Optional[str]: """Prefer "friendly" name if we have it. This is what we have been using to match functions.""" - return self.friendly_name or self.decorated_name + return ( + self.friendly_name + if self.friendly_name is not None + else self.decorated_name + ) def size(self) -> Optional[int]: if self.confirmed_size is not None: diff --git a/tools/isledecomp/isledecomp/cvdump/demangler.py b/tools/isledecomp/isledecomp/cvdump/demangler.py index 340f19a3..07fca42f 100644 --- a/tools/isledecomp/isledecomp/cvdump/demangler.py +++ b/tools/isledecomp/isledecomp/cvdump/demangler.py @@ -4,6 +4,7 @@ """ import re from collections import namedtuple +from typing import Optional class InvalidEncodedNumberError(Exception): @@ -30,13 +31,12 @@ def parse_encoded_number(string: str) -> int: StringConstInfo = namedtuple("StringConstInfo", "len is_utf16") -def demangle_string_const(symbol: str) -> StringConstInfo: +def demangle_string_const(symbol: str) -> Optional[StringConstInfo]: """Don't bother to decode the string text from the symbol. We can just read it from the binary once we have the length.""" match = string_const_regex.match(symbol) if match is None: - # See below - return StringConstInfo(0, False) + return None try: strlen = ( @@ -45,10 +45,7 @@ def demangle_string_const(symbol: str) -> StringConstInfo: else int(match.group("len")) ) except (ValueError, InvalidEncodedNumberError): - # This would be an annoying error to fail on if we get a bad symbol. - # For now, just assume a zero length string because this will probably - # raise some eyebrows during the comparison. - strlen = 0 + return None is_utf16 = match.group("is_utf16") == "1" return StringConstInfo(len=strlen, is_utf16=is_utf16) diff --git a/tools/isledecomp/isledecomp/cvdump/parser.py b/tools/isledecomp/isledecomp/cvdump/parser.py index 613cd4a4..d14abe88 100644 --- a/tools/isledecomp/isledecomp/cvdump/parser.py +++ b/tools/isledecomp/isledecomp/cvdump/parser.py @@ -36,7 +36,7 @@ # e.g. `S_GDATA32: [0003:000004A4], Type: T_32PRCHAR(0470), g_set` _gdata32_regex = re.compile( - r"S_GDATA32: \[(?P
\w{4}):(?P\w{8})\], Type:\s*(?P\S+), (?P\S+)" + r"S_GDATA32: \[(?P
\w{4}):(?P\w{8})\], Type:\s*(?P\S+), (?P.+)" ) diff --git a/tools/isledecomp/isledecomp/parser/codebase.py b/tools/isledecomp/isledecomp/parser/codebase.py index 54ab4035..184b1256 100644 --- a/tools/isledecomp/isledecomp/parser/codebase.py +++ b/tools/isledecomp/isledecomp/parser/codebase.py @@ -6,6 +6,7 @@ ParserFunction, ParserVtable, ParserVariable, + ParserString, ) @@ -42,3 +43,6 @@ def iter_vtables(self) -> Iterator[ParserVtable]: def iter_variables(self) -> Iterator[ParserVariable]: return filter(lambda s: isinstance(s, ParserVariable), self._symbols) + + def iter_strings(self) -> Iterator[ParserString]: + return filter(lambda s: isinstance(s, ParserString), self._symbols) diff --git a/tools/isledecomp/isledecomp/parser/error.py b/tools/isledecomp/isledecomp/parser/error.py index eb1aa7b8..81123381 100644 --- a/tools/isledecomp/isledecomp/parser/error.py +++ b/tools/isledecomp/isledecomp/parser/error.py @@ -70,6 +70,10 @@ class ParserError(Enum): # a comment -- i.e. VTABLE or GLOBAL -- could not extract the name NO_SUITABLE_NAME = 204 + # ERROR: Two STRING markers have the same module and offset, but the strings + # they annotate are different. + WRONG_STRING = 205 + @dataclass class ParserAlert: diff --git a/tools/isledecomp/isledecomp/parser/linter.py b/tools/isledecomp/isledecomp/parser/linter.py index 54406ce9..b44487df 100644 --- a/tools/isledecomp/isledecomp/parser/linter.py +++ b/tools/isledecomp/isledecomp/parser/linter.py @@ -1,7 +1,7 @@ from typing import List, Optional from .parser import DecompParser from .error import ParserAlert, ParserError -from .node import ParserSymbol +from .node import ParserSymbol, ParserString def get_checkorder_filter(module): @@ -19,6 +19,9 @@ def __init__(self) -> None: # This is _not_ reset between files and is intended to report offset reuse # when scanning the entire directory. self._offsets_used = set() + # Keep track of strings we have seen. Persists across files. + # Module/offset can be repeated for string markers but the strings must match. + self._strings = {} def reset(self, full_reset: bool = False): self.alerts = [] @@ -28,6 +31,7 @@ def reset(self, full_reset: bool = False): if full_reset: self._offsets_used.clear() + self._strings = {} def file_is_header(self): return self._filename.lower().endswith(".h") @@ -36,17 +40,31 @@ def _load_offsets_from_list(self, marker_list: List[ParserSymbol]): """Helper for loading (module, offset) tuples while the DecompParser has them broken up into three different lists.""" for marker in marker_list: + is_string = isinstance(marker, ParserString) + value = (marker.module, marker.offset) if value in self._offsets_used: - self.alerts.append( - ParserAlert( - code=ParserError.DUPLICATE_OFFSET, - line_number=marker.line_number, - line=f"0x{marker.offset:08x}", + if is_string: + if self._strings[value] != marker.name: + self.alerts.append( + ParserAlert( + code=ParserError.WRONG_STRING, + line_number=marker.line_number, + line=f"0x{marker.offset:08x}, {repr(self._strings[value])} vs. {repr(marker.name)}", + ) + ) + else: + self.alerts.append( + ParserAlert( + code=ParserError.DUPLICATE_OFFSET, + line_number=marker.line_number, + line=f"0x{marker.offset:08x}", + ) ) - ) else: self._offsets_used.add(value) + if is_string: + self._strings[value] = marker.name def _check_function_order(self): """Rules: @@ -82,6 +100,7 @@ def _check_offset_uniqueness(self): self._load_offsets_from_list(self._parser.functions) self._load_offsets_from_list(self._parser.vtables) self._load_offsets_from_list(self._parser.variables) + self._load_offsets_from_list(self._parser.strings) def _check_byname_allowed(self): if self.file_is_header(): diff --git a/tools/isledecomp/isledecomp/parser/marker.py b/tools/isledecomp/isledecomp/parser/marker.py index d2e181dd..de8c6f05 100644 --- a/tools/isledecomp/isledecomp/parser/marker.py +++ b/tools/isledecomp/isledecomp/parser/marker.py @@ -3,6 +3,19 @@ from enum import Enum +class MarkerCategory(Enum): + """For the purposes of grouping multiple different DecompMarkers together, + assign a rough "category" for the MarkerType values below. + It's really only the function types that have to get folded down, but + we'll do that in a structured way to permit future expansion.""" + + FUNCTION = 1 + VARIABLE = 2 + STRING = 3 + VTABLE = 4 + ADDRESS = 100 # i.e. no comparison required or possible + + class MarkerType(Enum): UNKNOWN = -100 FUNCTION = 1 @@ -51,6 +64,23 @@ def module(self) -> str: def offset(self) -> int: return self._offset + @property + def category(self) -> MarkerCategory: + if self.is_vtable(): + return MarkerCategory.VTABLE + + if self.is_variable(): + return MarkerCategory.VARIABLE + + if self.is_string(): + return MarkerCategory.STRING + + # TODO: worth another look if we add more types, but this covers it + if self.is_regular_function() or self.is_explicit_byname(): + return MarkerCategory.FUNCTION + + return MarkerCategory.ADDRESS + def is_regular_function(self) -> bool: """Regular function, meaning: not an explicit byname lookup. FUNCTION markers can be _implicit_ byname. diff --git a/tools/isledecomp/isledecomp/parser/node.py b/tools/isledecomp/isledecomp/parser/node.py index b6561fd6..71d4ebdd 100644 --- a/tools/isledecomp/isledecomp/parser/node.py +++ b/tools/isledecomp/isledecomp/parser/node.py @@ -55,3 +55,8 @@ class ParserVariable(ParserSymbol): @dataclass class ParserVtable(ParserSymbol): pass + + +@dataclass +class ParserString(ParserSymbol): + pass diff --git a/tools/isledecomp/isledecomp/parser/parser.py b/tools/isledecomp/isledecomp/parser/parser.py index d4153b3c..3c955fc3 100644 --- a/tools/isledecomp/isledecomp/parser/parser.py +++ b/tools/isledecomp/isledecomp/parser/parser.py @@ -3,11 +3,11 @@ from typing import List, Iterable, Iterator, Optional from enum import Enum from .util import ( - is_blank_or_comment, get_class_name, get_variable_name, get_synthetic_name, remove_trailing_comment, + get_string_contents, ) from .marker import ( DecompMarker, @@ -19,6 +19,7 @@ ParserFunction, ParserVariable, ParserVtable, + ParserString, ) from .error import ParserAlert, ParserError @@ -43,17 +44,16 @@ def __init__(self) -> None: def insert(self, marker: DecompMarker) -> bool: """Return True if this insert would overwrite""" - module = marker.module - if module in self.markers: + key = (marker.category, marker.module) + if key in self.markers: return True - # TODO: type converted back to string version here instead of using enum - self.markers[module] = (marker.type.name, marker.offset) + self.markers[key] = marker return False def iter(self) -> Iterator[DecompMarker]: - for module, (marker_type, offset) in self.markers.items(): - yield DecompMarker(marker_type, module, offset) + for _, marker in self.markers.items(): + yield marker def empty(self): self.markers = {} @@ -111,17 +111,21 @@ def reset(self): self.function_sig = "" @property - def functions(self) -> List[ParserSymbol]: + def functions(self) -> List[ParserFunction]: return [s for s in self._symbols if isinstance(s, ParserFunction)] @property - def vtables(self) -> List[ParserSymbol]: + def vtables(self) -> List[ParserVtable]: return [s for s in self._symbols if isinstance(s, ParserVtable)] @property - def variables(self) -> List[ParserSymbol]: + def variables(self) -> List[ParserVariable]: return [s for s in self._symbols if isinstance(s, ParserVariable)] + @property + def strings(self) -> List[ParserString]: + return [s for s in self._symbols if isinstance(s, ParserString)] + def iter_symbols(self, module: Optional[str] = None) -> Iterator[ParserSymbol]: for s in self._symbols: if module is None or s.module == module: @@ -225,21 +229,35 @@ def _variable_marker(self, marker: DecompMarker): else: self.state = ReaderState.IN_GLOBAL - def _variable_done(self, name: str): - if not name.startswith("g_"): - self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) + def _variable_done( + self, variable_name: Optional[str] = None, string_value: Optional[str] = None + ): + if variable_name is None and string_value is None: + self._syntax_error(ParserError.NO_SUITABLE_NAME) + return for marker in self.var_markers.iter(): - self._symbols.append( - ParserVariable( - type=marker.type, - line_number=self.line_number, - module=marker.module, - offset=marker.offset, - name=name, - is_static=self.state == ReaderState.IN_FUNC_GLOBAL, + if marker.is_string(): + self._symbols.append( + ParserString( + type=marker.type, + line_number=self.line_number, + module=marker.module, + offset=marker.offset, + name=string_value, + ) + ) + else: + 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, + ) ) - ) self.var_markers.empty() if self.state == ReaderState.IN_FUNC_GLOBAL: @@ -298,20 +316,8 @@ def _handle_marker(self, marker: DecompMarker): else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker.is_string(): - # TODO: We are ignoring string markers for the moment. - # We already have a lot of them in the codebase, though, so we'll - # hang onto them for now in case we can use them later. - # To match up string constants, the strategy will be: - # 1. Use cvdump to find all string constants in the recomp - # 2. In the original binary, look at relocated vaddrs from .rdata - # 3. Try to match up string data from #1 with locations in #2 - - # Throw the syntax error we would throw if we were parsing these - if self.state not in (ReaderState.SEARCH, ReaderState.IN_FUNC): - self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - - elif marker.is_variable(): + # Strings and variables are almost the same thing + elif marker.is_string() or marker.is_variable(): if self.state in ( ReaderState.SEARCH, ReaderState.IN_GLOBAL, @@ -418,24 +424,39 @@ def read_line(self, line: str): # function we have already parsed if state == IN_FUNC_GLOBAL. # However, we are not tolerant of _any_ syntax problems in our # CI actions, so the solution is to just fix the invalid marker. - if is_blank_or_comment(line): - self._syntax_error(ParserError.NO_SUITABLE_NAME) + variable_name = None + + global_markers_queued = any( + m.is_variable() for m in self.var_markers.iter() + ) + + if len(line_strip) == 0: + self._syntax_warning(ParserError.UNEXPECTED_BLANK_LINE) return - # We don't have a foolproof mechanism to tell what is and is not a variable. - # If the GLOBAL is being declared on a `return` statement, though, this is - # not correct. It is either a string literal (which will be handled differently) - # or it is not the variable declaration, which is incorrect decomp syntax. - if line.strip().startswith("return"): - self._syntax_error(ParserError.GLOBAL_NOT_VARIABLE) - return + if global_markers_queued: + # Not the greatest solution, but a consequence of combining GLOBAL and + # STRING markers together. If the marker precedes a return statement, it is + # valid for a STRING marker to be here, but not a GLOBAL. We need to look + # ahead and tell whether this *would* fail. + if line_strip.startswith("return"): + self._syntax_error(ParserError.GLOBAL_NOT_VARIABLE) + return + if line_strip.startswith("//"): + # If we found a comment, assume implicit lookup-by-name + # function and end here. We know this is not a decomp marker + # because it would have been handled already. + variable_name = get_synthetic_name(line) + else: + 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) - name = get_variable_name(line) - if name is None: - self._syntax_error(ParserError.NO_SUITABLE_NAME) - return + string_name = get_string_contents(line) - self._variable_done(name) + self._variable_done(variable_name, string_name) elif self.state == ReaderState.IN_VTABLE: vtable_class = get_class_name(line) diff --git a/tools/isledecomp/isledecomp/parser/util.py b/tools/isledecomp/isledecomp/parser/util.py index a106d841..dd90fd03 100644 --- a/tools/isledecomp/isledecomp/parser/util.py +++ b/tools/isledecomp/isledecomp/parser/util.py @@ -1,6 +1,7 @@ # C++ Parser utility functions and data structures import re from typing import Optional +from ast import literal_eval # The goal here is to just read whatever is on the next line, so some # flexibility in the formatting seems OK @@ -12,6 +13,10 @@ trailingCommentRegex = re.compile(r"(\s*(?://|/\*).*)$") +# Get string contents, ignore escape characters that might interfere +doubleQuoteRegex = re.compile(r"(\"(?:[^\"\\]|\\.)*\")") + + def get_synthetic_name(line: str) -> Optional[str]: """Synthetic names appear on a single line comment on the line after the marker. If that's not what we have, return None""" @@ -86,3 +91,20 @@ def get_variable_name(line: str) -> Optional[str]: return match.group("name") return None + + +def get_string_contents(line: str) -> Optional[str]: + """Return the first C string seen on this line. + We have to unescape the string, and a simple way to do that is to use + python's ast.literal_eval. I'm sure there are many pitfalls to doing + it this way, but hopefully the regex will ensure reasonably sane input.""" + + try: + if (match := doubleQuoteRegex.search(line)) is not None: + return literal_eval(match.group(1)) + # pylint: disable=broad-exception-caught + # No way to predict what kind of exception could occur. + except Exception: + pass + + return None diff --git a/tools/isledecomp/isledecomp/utils.py b/tools/isledecomp/isledecomp/utils.py index ce4896fd..637eee33 100644 --- a/tools/isledecomp/isledecomp/utils.py +++ b/tools/isledecomp/isledecomp/utils.py @@ -26,17 +26,3 @@ def print_diff(udiff, plain): def get_file_in_script_dir(fn): return os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), fn) - - -class OffsetPlaceholderGenerator: - def __init__(self): - self.counter = 0 - self.replacements = {} - - def get(self, replace_addr): - if replace_addr in self.replacements: - return self.replacements[replace_addr] - self.counter += 1 - replacement = f"" - self.replacements[replace_addr] = replacement - return replacement diff --git a/tools/isledecomp/tests/test_demangler.py b/tools/isledecomp/tests/test_demangler.py index 5343bdcc..32cac502 100644 --- a/tools/isledecomp/tests/test_demangler.py +++ b/tools/isledecomp/tests/test_demangler.py @@ -14,6 +14,7 @@ 14, True, ), + ("??_C@_00A@?$AA@", 0, False), ] diff --git a/tools/isledecomp/tests/test_linter.py b/tools/isledecomp/tests/test_linter.py index 84ce6495..95d19515 100644 --- a/tools/isledecomp/tests/test_linter.py +++ b/tools/isledecomp/tests/test_linter.py @@ -112,3 +112,33 @@ def test_duplicate_offsets(linter): # Full reset will forget seen offsets. linter.reset(True) assert linter.check_lines(lines, "test.h", "TEST") is True + + +def test_duplicate_strings(linter): + """Duplicate string markers are okay if the string value is the same.""" + string_lines = [ + "// STRING: TEST 0x1000", + 'return "hello world";', + ] + + # No problem to use this marker twice. + assert linter.check_lines(string_lines, "test.h", "TEST") is True + assert linter.check_lines(string_lines, "test.h", "TEST") is True + + different_string = [ + "// STRING: TEST 0x1000", + 'return "hi there";', + ] + + # Same address but the string is different + assert linter.check_lines(different_string, "greeting.h", "TEST") is False + assert len(linter.alerts) == 1 + assert linter.alerts[0].code == ParserError.WRONG_STRING + + same_addr_reused = [ + "// GLOBAL:TEXT 0x1000", + "int g_test = 123;", + ] + + # This will fail like any other offset reuse. + assert linter.check_lines(same_addr_reused, "other.h", "TEST") is False diff --git a/tools/isledecomp/tests/test_parser.py b/tools/isledecomp/tests/test_parser.py index 853e773d..6d8b72b1 100644 --- a/tools/isledecomp/tests/test_parser.py +++ b/tools/isledecomp/tests/test_parser.py @@ -442,3 +442,82 @@ def test_static_variable(parser): ) assert len(parser.variables) == 2 assert parser.variables[1].is_static is True + + +def test_reject_global_return(parser): + """Previously we had annotated strings with the GLOBAL marker. + For example: if a function returned a string. We now want these to be + annotated with the STRING marker.""" + + parser.read_lines( + [ + "// FUNCTION: TEST 0x5555", + "void test_function() {", + " // GLOBAL: TEST 0x8888", + ' return "test";', + "}", + ] + ) + assert len(parser.variables) == 0 + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.GLOBAL_NOT_VARIABLE + + +def test_global_string(parser): + """We now allow GLOBAL and STRING markers for the same item.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "// STRING: TEXT 0x5555", + 'char* g_test = "hello";', + ] + ) + assert len(parser.variables) == 1 + assert len(parser.strings) == 1 + assert len(parser.alerts) == 0 + + assert parser.variables[0].name == "g_test" + assert parser.strings[0].name == "hello" + + +def test_comment_variables(parser): + """Match on hidden variables from libraries.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "// g_test", + ] + ) + assert len(parser.variables) == 1 + assert parser.variables[0].name == "g_test" + + +def test_flexible_variable_prefix(parser): + """Don't alert to library variables that lack the g_ prefix. + This is out of our control.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "// some_other_variable", + ] + ) + assert len(parser.variables) == 1 + assert len(parser.alerts) == 0 + assert parser.variables[0].name == "some_other_variable" + + +def test_string_ignore_g_prefix(parser): + """String annotations above a regular variable should not alert to + the missing g_ prefix. This is only required for GLOBAL markers.""" + + parser.read_lines( + [ + "// STRING: TEST 0x1234", + 'const char* value = "";', + ] + ) + assert len(parser.strings) == 1 + assert len(parser.alerts) == 0 diff --git a/tools/isledecomp/tests/test_parser_statechange.py b/tools/isledecomp/tests/test_parser_statechange.py index cb54cf0a..be37e3c8 100644 --- a/tools/isledecomp/tests/test_parser_statechange.py +++ b/tools/isledecomp/tests/test_parser_statechange.py @@ -15,7 +15,7 @@ (_rs.SEARCH, "TEMPLATE", _rs.IN_TEMPLATE, None), (_rs.SEARCH, "VTABLE", _rs.IN_VTABLE, None), (_rs.SEARCH, "LIBRARY", _rs.IN_LIBRARY, None), - (_rs.SEARCH, "STRING", _rs.SEARCH, None), + (_rs.SEARCH, "STRING", _rs.IN_GLOBAL, None), (_rs.WANT_SIG, "FUNCTION", _rs.WANT_SIG, None), (_rs.WANT_SIG, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -33,7 +33,7 @@ (_rs.IN_FUNC, "TEMPLATE", _rs.IN_TEMPLATE, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "VTABLE", _rs.IN_VTABLE, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "LIBRARY", _rs.IN_LIBRARY, _pe.MISSED_END_OF_FUNCTION), - (_rs.IN_FUNC, "STRING", _rs.IN_FUNC, None), + (_rs.IN_FUNC, "STRING", _rs.IN_FUNC_GLOBAL, None), (_rs.IN_TEMPLATE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -60,7 +60,7 @@ (_rs.IN_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), - (_rs.IN_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_GLOBAL, "STRING", _rs.IN_GLOBAL, None), (_rs.IN_FUNC_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), @@ -69,7 +69,7 @@ (_rs.IN_FUNC_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), - (_rs.IN_FUNC_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_FUNC_GLOBAL, "STRING", _rs.IN_FUNC_GLOBAL, None), (_rs.IN_VTABLE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), diff --git a/tools/isledecomp/tests/test_parser_util.py b/tools/isledecomp/tests/test_parser_util.py index af102fc2..8a403710 100644 --- a/tools/isledecomp/tests/test_parser_util.py +++ b/tools/isledecomp/tests/test_parser_util.py @@ -10,6 +10,7 @@ is_blank_or_comment, get_class_name, get_variable_name, + get_string_contents, ) @@ -158,3 +159,18 @@ def test_get_class_name_none(line: str): @pytest.mark.parametrize("line,name", variable_name_cases) def test_get_variable_name(line: str, name: str): assert get_variable_name(line) == name + + +string_match_cases = [ + ('return "hello world";', "hello world"), + ('"hello\\\\"', "hello\\"), + ('"hello \\"world\\""', 'hello "world"'), + ('"hello\\nworld"', "hello\nworld"), + # Only match first string if there are multiple options + ('Method("hello", "world");', "hello"), +] + + +@pytest.mark.parametrize("line, string", string_match_cases) +def test_get_string_contents(line: str, string: str): + assert get_string_contents(line) == string diff --git a/tools/isledecomp/tests/test_sanitize.py b/tools/isledecomp/tests/test_sanitize.py new file mode 100644 index 00000000..67d95b4f --- /dev/null +++ b/tools/isledecomp/tests/test_sanitize.py @@ -0,0 +1,179 @@ +from typing import Optional +import pytest +from isledecomp.compare.asm.parse import DisasmLiteInst, ParseAsm + + +def mock_inst(mnemonic: str, op_str: str) -> DisasmLiteInst: + """Mock up the named tuple DisasmLite from just a mnemonic and op_str. + To be used for tests on sanitize that do not require the instruction address + or size. i.e. any non-jump instruction.""" + return DisasmLiteInst(0, 0, mnemonic, op_str) + + +identity_cases = [ + ("", ""), + ("sti", ""), + ("push", "ebx"), + ("ret", ""), + ("ret", "4"), + ("mov", "eax, 0x1234"), +] + + +@pytest.mark.parametrize("mnemonic, op_str", identity_cases) +def test_identity(mnemonic, op_str): + """Confirm that nothing is substituted.""" + p = ParseAsm() + inst = mock_inst(mnemonic, op_str) + result = p.sanitize(inst) + assert result == (mnemonic, op_str) + + +ptr_replace_cases = [ + ("byte ptr [0x5555]", "byte ptr []"), + ("word ptr [0x5555]", "word ptr []"), + ("dword ptr [0x5555]", "dword ptr []"), + ("qword ptr [0x5555]", "qword ptr []"), + ("eax, dword ptr [0x5555]", "eax, dword ptr []"), + ("dword ptr [0x5555], eax", "dword ptr [], eax"), + ("dword ptr [0x5555], 0", "dword ptr [], 0"), + ("dword ptr [0x5555], 8", "dword ptr [], 8"), + # Same value, assumed to be an addr in the first appearance + # because it is designated as 'ptr', but we have not provided the + # relocation table lookup method so we do not replace the second appearance. + ("dword ptr [0x5555], 0x5555", "dword ptr [], 0x5555"), +] + + +@pytest.mark.parametrize("start, end", ptr_replace_cases) +def test_ptr_replace(start, end): + """Anything in square brackets (with the 'ptr' prefix) will always be replaced.""" + p = ParseAsm() + inst = mock_inst("", start) + (_, op_str) = p.sanitize(inst) + assert op_str == end + + +call_replace_cases = [ + ("ebx", "ebx"), + ("0x1234", ""), + ("dword ptr [0x1234]", "dword ptr []"), + ("dword ptr [ecx + 0x10]", "dword ptr [ecx + 0x10]"), +] + + +@pytest.mark.parametrize("start, end", call_replace_cases) +def test_call_replace(start, end): + """Call with hex operand is always replaced. + Otherwise, ptr replacement rules apply, but skip `this` calls.""" + p = ParseAsm() + inst = mock_inst("call", start) + (_, op_str) = p.sanitize(inst) + assert op_str == end + + +def test_jump_displacement(): + """Display jump displacement (offset from end of jump instruction) + instead of destination address.""" + p = ParseAsm() + inst = DisasmLiteInst(0x1000, 2, "je", "0x1000") + (_, op_str) = p.sanitize(inst) + assert op_str == "-0x2" + + +@pytest.mark.xfail(reason="Not implemented yet") +def test_jmp_table(): + """Should detect the characteristic jump table instruction + (for a switch statement) and use placeholder.""" + p = ParseAsm() + inst = mock_inst("jmp", "dword ptr [eax*4 + 0x5555]") + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr [eax*4 + ]" + + +name_replace_cases = [ + ("byte ptr [0x5555]", "byte ptr [_substitute_]"), + ("word ptr [0x5555]", "word ptr [_substitute_]"), + ("dword ptr [0x5555]", "dword ptr [_substitute_]"), + ("qword ptr [0x5555]", "qword ptr [_substitute_]"), +] + + +@pytest.mark.parametrize("start, end", name_replace_cases) +def test_name_replace(start, end): + """Make sure the name lookup function is called if present""" + + def substitute(_: int) -> str: + return "_substitute_" + + p = ParseAsm(name_lookup=substitute) + inst = mock_inst("mov", start) + (_, op_str) = p.sanitize(inst) + assert op_str == end + + +def test_replacement_cache(): + p = ParseAsm() + inst = mock_inst("inc", "dword ptr [0x1234]") + + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr []" + + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr []" + + +def test_replacement_numbering(): + """If we can use the name lookup for the first address but not the second, + the second replacement should be not .""" + + def substitute_1234(addr: int) -> Optional[str]: + return "_substitute_" if addr == 0x1234 else None + + p = ParseAsm(name_lookup=substitute_1234) + + (_, op_str) = p.sanitize(mock_inst("inc", "dword ptr [0x1234]")) + assert op_str == "dword ptr [_substitute_]" + + (_, op_str) = p.sanitize(mock_inst("inc", "dword ptr [0x5555]")) + assert op_str == "dword ptr []" + + +def test_relocate_lookup(): + """Immediate values would be relocated if they are actually addresses. + So we can use the relocation table to check whether a given value is an + address or just some number.""" + + def relocate_lookup(addr: int) -> bool: + return addr == 0x1234 + + p = ParseAsm(relocate_lookup=relocate_lookup) + (_, op_str) = p.sanitize(mock_inst("mov", "eax, 0x1234")) + assert op_str == "eax, " + + (_, op_str) = p.sanitize(mock_inst("mov", "eax, 0x5555")) + assert op_str == "eax, 0x5555" + + +def test_jump_to_function(): + """A jmp instruction can lead us directly to a function. This can be found + in the unwind section at the end of a function. However: we do not want to + assume this is the case for all jumps. Only replace the jump with a name + if we can find it using our lookup.""" + + def substitute_1234(addr: int) -> Optional[str]: + return "_substitute_" if addr == 0x1234 else None + + p = ParseAsm(name_lookup=substitute_1234) + inst = DisasmLiteInst(0x1000, 2, "jmp", "0x1234") + (_, op_str) = p.sanitize(inst) + assert op_str == "_substitute_" + + # Should not replace this jump. + # 0x1000 (start addr) + # + 2 (size of jump instruction) + # + 0x5555 (displacement, the value we want) + # = 0x6557 + inst = DisasmLiteInst(0x1000, 2, "jmp", "0x6557") + (_, op_str) = p.sanitize(inst) + assert op_str == "0x5555" diff --git a/tools/ncc/ncc.style b/tools/ncc/ncc.style index 57bc8dd7..8dc0091b 100644 --- a/tools/ncc/ncc.style +++ b/tools/ncc/ncc.style @@ -1,7 +1,7 @@ ClassName: '^[A-Z][a-zA-Z0-9]+$' CppMethod: '^operator|^FUN_[a-f0-9]{8}$|^VTable0x[a-f0-9]{1,8}$|^(?!VTable)[A-Z][a-zA-Z0-9]+$' -# EnumConstantName EnumName: '^\(unnamed|^[A-Z][a-zA-Z0-9]+$' +EnumConstantName: '^(c_|e_)[a-z][a-zA-Z0-9]+$' FunctionName: '^operator|^FUN_[a-f0-9]{8}$|^VTable0x[a-f0-9]{1,8}$|^(?!VTable)[A-Z][a-zA-Z0-9]+$' ParameterName: '^p_(unk0x[a-f0-9]{1,8}$|(?!unk)[a-z][a-zA-Z0-9]*)$|^$' StructName: '^\(anon|^\(unnamed|^[A-Z][a-zA-Z0-9]+$' diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index fa8546d9..ec7f46a0 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -12,6 +12,7 @@ m_HWDesc: 'Allow this variable name' m_HELDesc: 'Allow this variable name' p_HWDesc: 'Allow this variable name' p_HELDesc: 'Allow this variable name' +e_RAMStream: 'Allow this enum constant' p_milliseconds: 'Probably a bug with function call' m_increaseAmount: "Can't currently detect member in union" -m_increaseFactor: "Can't currently detect member in union" +m_increaseFactor: "Can't currently detect member in union" \ No newline at end of file diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index b7027435..66bb0f66 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -2,167 +2,20 @@ import argparse import base64 -import difflib import json import logging import os -import re from isledecomp import ( Bin, get_file_in_script_dir, - OffsetPlaceholderGenerator, print_diff, ) from isledecomp.compare import Compare as IsleCompare - -from capstone import Cs, CS_ARCH_X86, CS_MODE_32 -import colorama from pystache import Renderer +import colorama - -REGISTER_LIST = set( - [ - "ax", - "bp", - "bx", - "cx", - "di", - "dx", - "eax", - "ebp", - "ebx", - "ecx", - "edi", - "edx", - "esi", - "esp", - "si", - "sp", - ] -) -WORDS = re.compile(r"\w+") - - -def sanitize(file, placeholder_generator, mnemonic, op_str): - op_str_is_number = False - try: - int(op_str, 16) - op_str_is_number = True - except ValueError: - pass - - if (mnemonic in ["call", "jmp"]) and op_str_is_number: - # Filter out "calls" because the offsets we're not currently trying to - # match offsets. As long as there's a call in the right place, it's - # probably accurate. - op_str = placeholder_generator.get(int(op_str, 16)) - else: - - def filter_out_ptr(ptype, op_str): - try: - ptrstr = ptype + " ptr [" - start = op_str.index(ptrstr) + len(ptrstr) - end = op_str.index("]", start) - - # This will throw ValueError if not hex - inttest = int(op_str[start:end], 16) - - return ( - op_str[0:start] + placeholder_generator.get(inttest) + op_str[end:] - ) - except ValueError: - return op_str - - # Filter out dword ptrs where the pointer is to an offset - op_str = filter_out_ptr("dword", op_str) - op_str = filter_out_ptr("word", op_str) - op_str = filter_out_ptr("byte", op_str) - - # Use heuristics to filter out any args that look like offsets - words = op_str.split(" ") - for i, word in enumerate(words): - try: - inttest = int(word, 16) - if file.is_relocated_addr(inttest): - words[i] = placeholder_generator.get(inttest) - except ValueError: - pass - op_str = " ".join(words) - - return mnemonic, op_str - - -def parse_asm(disassembler, file, asm_addr, size): - asm = [] - data = file.read(asm_addr, size) - placeholder_generator = OffsetPlaceholderGenerator() - for i in disassembler.disasm(data, 0): - # Use heuristics to disregard some differences that aren't representative - # of the accuracy of a function (e.g. global offsets) - mnemonic, op_str = sanitize(file, placeholder_generator, i.mnemonic, i.op_str) - if op_str is None: - asm.append(mnemonic) - else: - asm.append(f"{mnemonic} {op_str}") - return asm - - -def get_registers(line: str): - to_replace = [] - # use words regex to find all matching positions: - for match in WORDS.finditer(line): - reg = match.group(0) - if reg in REGISTER_LIST: - to_replace.append((reg, match.start())) - return to_replace - - -def replace_register( - lines: list[str], start_line: int, reg: str, replacement: str -) -> list[str]: - return [ - line.replace(reg, replacement) if i >= start_line else line - for i, line in enumerate(lines) - ] - - -# Is it possible to make new_asm the same as original_asm by swapping registers? -def can_resolve_register_differences(original_asm, new_asm): - # Split the ASM on spaces to get more granularity, and so - # that we don't modify the original arrays passed in. - original_asm = [part for line in original_asm for part in line.split()] - new_asm = [part for line in new_asm for part in line.split()] - - # Swapping ain't gonna help if the lengths are different - if len(original_asm) != len(new_asm): - return False - - # Look for the mismatching lines - for i, original_line in enumerate(original_asm): - new_line = new_asm[i] - if new_line != original_line: - # Find all the registers to replace - to_replace = get_registers(original_line) - - for replace in to_replace: - (reg, reg_index) = replace - replacing_reg = new_line[reg_index : reg_index + len(reg)] - if replacing_reg in REGISTER_LIST: - if replacing_reg != reg: - # Do a three-way swap replacing in all the subsequent lines - temp_reg = "&" * len(reg) - new_asm = replace_register(new_asm, i, replacing_reg, temp_reg) - new_asm = replace_register(new_asm, i, reg, replacing_reg) - new_asm = replace_register(new_asm, i, temp_reg, reg) - else: - # No replacement to do, different code, bail out - return False - # Check if the lines are now the same - for i, original_line in enumerate(original_asm): - if new_asm[i] != original_line: - return False - return True +colorama.init() def gen_html(html_file, data): @@ -197,9 +50,88 @@ def gen_svg(svg_file, name_svg, icon, svg_implemented_funcs, total_funcs, raw_ac svgfile.write(output_data) -# Do the actual work -def main(): - # pylint: disable=too-many-locals, too-many-nested-blocks, too-many-branches, too-many-statements +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 + ) + + if show_both_addrs: + addrs = f"0x{match.orig_addr:x} / 0x{match.recomp_addr:x}" + else: + addrs = hex(match.orig_addr) + + if match.effective_ratio == 1.0: + ok_text = ( + "OK!" + if is_plain + else (colorama.Fore.GREEN + "✨ OK! ✨" + colorama.Style.RESET_ALL) + ) + if match.ratio == 1.0: + print(f"{addrs}: {match.name} 100% match.\n\n{ok_text}\n\n") + else: + print( + 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( + f"\n{match.name} is only {percenttext} similar to the original, diff above" + ) + + +def print_match_oneline(match, show_both_addrs: bool = False, is_plain: bool = False): + percenttext = percent_string( + match.effective_ratio, match.is_effective_match, is_plain + ) + + if show_both_addrs: + addrs = f"0x{match.orig_addr:x} / 0x{match.recomp_addr:x}" + else: + addrs = hex(match.orig_addr) + + print(f" {match.name} ({addrs}) is {percenttext} similar to the original") + + +def parse_args() -> argparse.Namespace: + def virtual_address(value) -> int: + """Helper method for argparse, verbose parameter""" + return int(value, 16) + parser = argparse.ArgumentParser( allow_abbrev=False, description="Recompilation Compare: compare an original EXE with a recompiled EXE + PDB.", @@ -226,6 +158,7 @@ def main(): "--verbose", "-v", metavar="", + type=virtual_address, help="Print assembly diff for specific function (original file's offset)", ) parser.add_argument( @@ -258,198 +191,103 @@ def main(): args = parser.parse_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() logging.basicConfig(level=args.loglevel, format="[%(levelname)s] %(message)s") - colorama.init() - - verbose = None - found_verbose_target = False - if args.verbose: - try: - verbose = int(args.verbose, 16) - except ValueError: - parser.error("invalid verbose argument") - html_path = args.html - - plain = args.no_color - - original = args.original - if not os.path.isfile(original): - parser.error(f"Original binary {original} does not exist") - - recomp = args.recompiled - if not os.path.isfile(recomp): - parser.error(f"Recompiled binary {recomp} does not exist") - - syms = args.pdb - if not os.path.isfile(syms): - parser.error(f"Symbols PDB {syms} does not exist") - - source = args.decomp_dir - if not os.path.isdir(source): - parser.error(f"Source directory {source} does not exist") - - svg = args.svg - - with Bin(original, find_str=True) as origfile, Bin(recomp) as recompfile: - if verbose is not None: + with Bin(args.original, find_str=True) as origfile, Bin( + args.recompiled + ) as recompfile: + if args.verbose is not None: # Mute logger events from compare engine logging.getLogger("isledecomp.compare.db").setLevel(logging.CRITICAL) logging.getLogger("isledecomp.compare.lines").setLevel(logging.CRITICAL) - isle_compare = IsleCompare(origfile, recompfile, syms, source) + isle_compare = IsleCompare(origfile, recompfile, args.pdb, args.decomp_dir) print() - capstone_disassembler = Cs(CS_ARCH_X86, CS_MODE_32) + ### Compare one or none. + + if args.verbose is not None: + match = isle_compare.compare_function(args.verbose) + if match is None: + print(f"Failed to find the function with address 0x{args.verbose:x}") + return + + print_match_verbose( + match, show_both_addrs=args.print_rec_addr, is_plain=args.no_color + ) + return + + ### Compare everything. function_count = 0 total_accuracy = 0 total_effective_accuracy = 0 htmlinsert = [] - matches = [] - if verbose is not None: - match = isle_compare.get_one_function(verbose) - if match is not None: - found_verbose_target = True - matches = [match] - else: - matches = isle_compare.get_functions() - - for match in matches: - # The effective_ratio is the ratio when ignoring differing register - # allocation vs the ratio is the true ratio. - ratio = 0.0 - effective_ratio = 0.0 - if match.size: - origasm = parse_asm( - capstone_disassembler, - origfile, - match.orig_addr, - match.size, - ) - recompasm = parse_asm( - capstone_disassembler, - recompfile, - match.recomp_addr, - match.size, - ) - - diff = difflib.SequenceMatcher(None, origasm, recompasm) - ratio = diff.ratio() - effective_ratio = ratio - - if ratio != 1.0: - # Check whether we can resolve register swaps which are actually - # perfect matches modulo compiler entropy. - if can_resolve_register_differences(origasm, recompasm): - effective_ratio = 1.0 - else: - ratio = 0 - - percenttext = f"{(effective_ratio * 100):.2f}%" - if not plain: - if effective_ratio == 1.0: - percenttext = ( - colorama.Fore.GREEN + percenttext + colorama.Style.RESET_ALL - ) - elif effective_ratio > 0.8: - percenttext = ( - colorama.Fore.YELLOW + percenttext + colorama.Style.RESET_ALL - ) - else: - percenttext = ( - colorama.Fore.RED + percenttext + colorama.Style.RESET_ALL - ) - - if effective_ratio == 1.0 and ratio != 1.0: - if plain: - percenttext += "*" - else: - percenttext += colorama.Fore.RED + "*" + colorama.Style.RESET_ALL - - if args.print_rec_addr: - addrs = f"0x{match.orig_addr:x} / 0x{match.recomp_addr:x}" - else: - addrs = hex(match.orig_addr) - - if not verbose: - print( - f" {match.name} ({addrs}) is {percenttext} similar to the original" - ) + for match in isle_compare.compare_functions(): + print_match_oneline( + match, show_both_addrs=args.print_rec_addr, is_plain=args.no_color + ) function_count += 1 - total_accuracy += ratio - total_effective_accuracy += effective_ratio + total_accuracy += match.ratio + total_effective_accuracy += match.effective_ratio - if match.size: - udiff = difflib.unified_diff(origasm, recompasm, n=10) - - # If verbose, print the diff for that function to the output - if verbose: - if effective_ratio == 1.0: - ok_text = ( - "OK!" - if plain - else ( - colorama.Fore.GREEN - + "✨ OK! ✨" - + colorama.Style.RESET_ALL - ) - ) - if ratio == 1.0: - print(f"{addrs}: {match.name} 100% match.\n\n{ok_text}\n\n") - else: - print( - 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(udiff, plain) - - print( - f"\n{match.name} is only {percenttext} similar to the original, diff above" - ) - - # If html, record the diffs to an HTML file - if html_path: - htmlinsert.append( - { - "address": f"0x{match.orig_addr:x}", - "name": match.name, - "matching": effective_ratio, - "diff": "\n".join(udiff), - } - ) - - if html_path: - gen_html(html_path, json.dumps(htmlinsert)) - - if verbose: - if not found_verbose_target: - print(f"Failed to find the function with address 0x{verbose:x}") - else: - implemented_funcs = function_count - - if args.total: - function_count = int(args.total) - - if function_count > 0: - effective_accuracy = total_effective_accuracy / function_count * 100 - actual_accuracy = total_accuracy / function_count * 100 - print( - f"\nTotal effective accuracy {effective_accuracy:.2f}% across {function_count} functions ({actual_accuracy:.2f}% actual accuracy)" + # 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), + } ) - if svg: - gen_svg( - svg, - os.path.basename(original), - args.svg_icon, - implemented_funcs, - function_count, - total_effective_accuracy, - ) + ## Generate files and show summary. + + if args.html is not None: + gen_html(args.html, json.dumps(htmlinsert)) + + implemented_funcs = function_count + + if args.total: + function_count = int(args.total) + + if function_count > 0: + effective_accuracy = total_effective_accuracy / function_count * 100 + actual_accuracy = total_accuracy / function_count * 100 + print( + f"\nTotal effective accuracy {effective_accuracy:.2f}% across {function_count} functions ({actual_accuracy:.2f}% actual accuracy)" + ) + + if args.svg is not None: + gen_svg( + args.svg, + os.path.basename(args.original), + args.svg_icon, + implemented_funcs, + function_count, + total_effective_accuracy, + ) if __name__ == "__main__": diff --git a/util/compat.h b/util/compat.h index 3c83def6..b38a1c7c 100644 --- a/util/compat.h +++ b/util/compat.h @@ -3,13 +3,13 @@ // Various macros to enable compiling with other/newer compilers. -#ifdef __MINGW32__ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1100) #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. -#ifdef __MINGW32__ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1100) #define COMPAT_CONST const #else #define COMPAT_CONST diff --git a/util/decomp.h b/util/decomp.h index 4e539eaf..3470fcc3 100644 --- a/util/decomp.h +++ b/util/decomp.h @@ -1,7 +1,7 @@ #ifndef DECOMP_H #define DECOMP_H -#if defined(_MSC_VER) +#if defined(ENABLE_DECOMP_ASSERTS) #define DECOMP_STATIC_ASSERT(V) \ namespace \ { \