diff --git a/.clang-format b/.clang-format index 19e35762..5d97094c 100644 --- a/.clang-format +++ b/.clang-format @@ -30,6 +30,7 @@ QualifierOrder: - const - volatile - type +RemoveSemicolon: true SpaceAfterCStyleCast: true TabWidth: 4 UseTab: ForContinuationAndIndentation diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 00000000..189ddf5a --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,6 @@ +Checks: > + -*, + readability-braces-around-statements, + modernize-use-override +WarningsAsErrors: '-*,readability-braces-around-statements,modernize-use-override' +HeaderFilterRegex: ".*" diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index e139b8bf..dec8b191 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -4,10 +4,11 @@ on: [push, pull_request] jobs: decomplint-isle: + name: 'ISLE annotations' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install python libraries run: | @@ -18,10 +19,11 @@ jobs: python3 tools/decomplint/decomplint.py ISLE --module ISLE --warnfail decomplint-lego1: + name: 'LEGO1 annotations' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install python libraries run: | diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c285836..9a21e56e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,13 +3,66 @@ 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}', msystem: mingw32, msys-env: mingw-w64-i686, clang-tidy: true, werror: true } + - { name: 'msys2 clang32', shell: 'msys2 {0}', msystem: clang32, msys-env: mingw-w64-clang-i686, clang-tidy: true, werror: true, no-dx5-libs: true } + + steps: + - name: Set up MSYS2 + if: ${{ !!matrix.toolchain.msystem }} + uses: msys2/setup-msys2@v2 + with: + msystem: ${{ matrix.toolchain.msystem }} + install: >- + ${{ matrix.toolchain.msys-env }}-cc + ${{ matrix.toolchain.msys-env }}-cmake + ${{ matrix.toolchain.msys-env }}-ninja + ${{ matrix.toolchain.msys-env }}-clang-tools-extra + + - name: Setup cmake + if: matrix.toolchain.setup-cmake + 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@v4 + + - name: Build + run: | + cmake -S . -B build -GNinja \ + -DCMAKE_BUILD_TYPE=Debug \ + -DISLE_USE_DX5_LIBS=${{ !matrix.toolchain.no-dx5-libs }} \ + -DENABLE_CLANG_TIDY=${{ !!matrix.toolchain.clang-tidy }} \ + -DISLE_WERROR=${{ !!matrix.toolchain.werror }} \ + -Werror=dev + cmake --build build -- -k0 + build: + name: 'MSVC 4.20' runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'itsmattkc/msvc420' path: msvc420 @@ -28,10 +81,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 +95,7 @@ jobs: build/LEGO1.PDB compare: + name: 'Compare with master' needs: build runs-on: windows-latest steps: @@ -100,6 +152,12 @@ jobs: run: | python3 tools/verexp/verexp.py legobin/LEGO1.DLL build/LEGO1.DLL + - name: Check Vtables + shell: bash + run: | + python3 tools/vtable/vtable.py legobin/ISLE.EXE build/ISLE.EXE build/ISLE.PDB . + python3 tools/vtable/vtable.py legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB . + - name: Upload Artifact uses: actions/upload-artifact@master with: @@ -109,11 +167,12 @@ 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' }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'probonopd/uploadtool' diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 22b39806..10e85e0d 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -4,35 +4,32 @@ on: [push, pull_request] jobs: clang-format: + name: 'C++' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Run clang-format run: | + find LEGO1 ISLE -iname '*.h' -o -iname '*.cpp' | xargs \ pipx run "clang-format>=17,<18" \ --Werror \ --dry-run \ --style=file \ - ISLE/*.cpp ISLE/*.h \ - LEGO1/*.cpp LEGO1/*.h \ - LEGO1/mxstl/*.h \ - LEGO1/realtime/*.cpp LEGO1/realtime/*.h \ - LEGO1/tgl/*.h \ - LEGO1/tgl/d3drm/*.cpp LEGO1/tgl/d3drm/*.h \ - LEGO1/viewmanager/*.cpp LEGO1/viewmanager/*.h + -i python-format: + name: 'Python' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install python libraries shell: bash run: | - pip install black pylint pytest -r tools/requirements.txt + pip install black==23.* pylint==3.* pytest==7.* -r tools/requirements.txt - name: Run pylint and black shell: bash diff --git a/.github/workflows/naming.yml b/.github/workflows/naming.yml index 11738779..b010e69f 100644 --- a/.github/workflows/naming.yml +++ b/.github/workflows/naming.yml @@ -4,10 +4,11 @@ on: [push, pull_request] jobs: ncc: + name: 'C++' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install LLVM and Clang uses: KyleMayes/install-llvm-action@v1 @@ -22,8 +23,14 @@ jobs: run: | python3 tools/ncc/ncc.py \ --clang-lib ${{ env.LLVM_PATH }}/lib/libclang.so \ + --recurse \ --style tools/ncc/ncc.style \ --skip tools/ncc/skip.yml \ - --definition WINAPI FAR HWND__=HWND \ - --include util \ - --path LEGO1 + --definition WINAPI FAR BOOL CALLBACK HWND__=HWND \ + --include \ + util \ + LEGO1 \ + LEGO1/omni/include \ + LEGO1/lego/legoomni/include \ + LEGO1/lego/sources \ + --path LEGO1/omni LEGO1/lego/legoomni diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index 06446888..3e1b12d8 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -1,13 +1,14 @@ -name: Unit Tests +name: Test on: [push, pull_request] jobs: pytest-win: + name: 'Python Windows' runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install python libraries shell: bash @@ -20,10 +21,11 @@ jobs: pytest tools/isledecomp pytest-ubuntu: + name: 'Python Linux' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install python libraries shell: bash diff --git a/.gitignore b/.gitignore index 72d6fef6..7e16a6ce 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ env.bak/ venv.bak/ ISLE.EXE LEGO1.DLL -build/ +/build/ *.swp LEGO1PROGRESS.* ISLEPROGRESS.* diff --git a/3rdparty/dx5/inc/d3drmdef.h b/3rdparty/dx5/inc/d3drmdef.h index aadf2644..109b2674 100644 --- a/3rdparty/dx5/inc/d3drmdef.h +++ b/3rdparty/dx5/inc/d3drmdef.h @@ -136,8 +136,8 @@ typedef struct _D3DRMIMAGE int bytes_per_line; /* number of bytes of memory for a scanline. This must be a multiple of 4. */ - void* buffer1; /* memory to render into (first buffer). */ - void* buffer2; /* second rendering buffer for double + char* buffer1; /* memory to render into (first buffer). */ + char* buffer2; /* second rendering buffer for double buffering, set to NULL for single buffering. */ unsigned long red_mask; diff --git a/3rdparty/flic/flic.asm b/3rdparty/flic/flic.asm new file mode 100644 index 00000000..e7a5f028 --- /dev/null +++ b/3rdparty/flic/flic.asm @@ -0,0 +1,866 @@ +.486 +.387 +option dotname +.model flat, c +assume fs:nothing + +public FUN_100bd530 +public FUN_100bd580 +public FUN_100bd600 +public FUN_100bd680 +public FUN_100bd6e0 +public FUN_100bd760 +public FUN_100bd880 +public FUN_100bd8a0 +public FUN_100bd8f0 +public FUN_100bd940 +public FUN_100bd960 +public FUN_100bda10 +public FUN_100bdac0 +public FUN_100bdc00 +public FUN_100bdc90 +public DecodeFLCFrame + +; This is so reccmp can detect the end of DecodeFLCFrame +public EndOfSection + +.text SEGMENT BYTE PUBLIC 'CODE' + +FUN_100bd530 LABEL NEAR + mov ax, word ptr [esp+0CH] ; 100BD530 _ 66: 8B. 44 24, 0C + push esi ; 100BD535 _ 56 + test ax, ax ; 100BD536 _ 66: 85. C0 + push edi ; 100BD539 _ 57 + jl ?_25163 ; 100BD53A _ 7C, 34 + mov cx, word ptr [esp+18H] ; 100BD53C _ 66: 8B. 4C 24, 18 + test cx, cx ; 100BD541 _ 66: 85. C9 + jl ?_25163 ; 100BD544 _ 7C, 2A + mov edx, dword ptr [esp+0CH] ; 100BD546 _ 8B. 54 24, 0C + movsx edi, ax ; 100BD54A _ 0F BF. F8 + mov esi, dword ptr [edx+4H] ; 100BD54D _ 8B. 72, 04 + cmp esi, edi ; 100BD550 _ 3B. F7 + jle ?_25163 ; 100BD552 _ 7E, 1C + movsx eax, cx ; 100BD554 _ 0F BF. C1 + cmp dword ptr [edx+8H], eax ; 100BD557 _ 39. 42, 08 + jle ?_25163 ; 100BD55A _ 7E, 14 + add esi, 3 ; 100BD55C _ 83. C6, 03 + mov cl, byte ptr [esp+1CH] ; 100BD55F _ 8A. 4C 24, 1C + and esi, 0FFFFFFFCH ; 100BD563 _ 83. E6, FC + imul esi, eax ; 100BD566 _ 0F AF. F0 + add esi, dword ptr [esp+10H] ; 100BD569 _ 03. 74 24, 10 + mov byte ptr [esi+edi], cl ; 100BD56D _ 88. 0C 3E +?_25163:pop edi ; 100BD570 _ 5F + pop esi ; 100BD571 _ 5E + ret ; 100BD572 _ C3 + +; Filling space: 0DH +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bd580 LABEL NEAR + lea eax, [esp+18H] ; 100BD580 _ 8D. 44 24, 18 + push esi ; 100BD584 _ 56 + mov si, word ptr [esp+10H] ; 100BD585 _ 66: 8B. 74 24, 10 + push edi ; 100BD58A _ 57 + lea ecx, [esp+18H] ; 100BD58B _ 8D. 4C 24, 18 + push eax ; 100BD58F _ 50 + lea edx, [esp+18H] ; 100BD590 _ 8D. 54 24, 18 + push ecx ; 100BD594 _ 51 + mov edi, dword ptr [esp+14H] ; 100BD595 _ 8B. 7C 24, 14 + push edx ; 100BD599 _ 52 + push edi ; 100BD59A _ 57 + call FUN_100bd600 ; 100BD59B _ E8, 00000060 + add esp, 16 ; 100BD5A0 _ 83. C4, 10 + test eax, eax ; 100BD5A3 _ 85. C0 + jz ?_25167 ; 100BD5A5 _ 74, 4A + mov ax, word ptr [esp+14H] ; 100BD5A7 _ 66: 8B. 44 24, 14 + sub ax, si ; 100BD5AC _ 66: 2B. C6 + jz ?_25165 ; 100BD5AF _ 74, 0B + movsx eax, ax ; 100BD5B1 _ 0F BF. C0 + mov esi, dword ptr [esp+1CH] ; 100BD5B4 _ 8B. 74 24, 1C + add esi, eax ; 100BD5B8 _ 03. F0 + jmp ?_25166 ; 100BD5BA _ EB, 04 + +?_25165:mov esi, dword ptr [esp+1CH] ; 100BD5BC _ 8B. 74 24, 1C +?_25166:movsx edx, word ptr [esp+20H] ; 100BD5C0 _ 0F BF. 54 24, 20 + mov ecx, dword ptr [edi+4H] ; 100BD5C5 _ 8B. 4F, 04 + movsx eax, word ptr [esp+18H] ; 100BD5C8 _ 0F BF. 44 24, 18 + add ecx, 3 ; 100BD5CD _ 83. C1, 03 + and ecx, 0FFFFFFFCH ; 100BD5D0 _ 83. E1, FC + movsx edi, word ptr [esp+14H] ; 100BD5D3 _ 0F BF. 7C 24, 14 + imul ecx, eax ; 100BD5D8 _ 0F AF. C8 + add ecx, edi ; 100BD5DB _ 03. CF + mov edi, dword ptr [esp+10H] ; 100BD5DD _ 8B. 7C 24, 10 + add edi, ecx ; 100BD5E1 _ 03. F9 + mov ecx, edx ; 100BD5E3 _ 8B. CA + shr ecx, 2 ; 100BD5E5 _ C1. E9, 02 + rep movsd ; 100BD5E8 _ F3: A5 + mov ecx, edx ; 100BD5EA _ 8B. CA + and ecx, 03H ; 100BD5EC _ 83. E1, 03 + rep movsb ; 100BD5EF _ F3: A4 +?_25167:pop edi ; 100BD5F1 _ 5F + pop esi ; 100BD5F2 _ 5E + ret ; 100BD5F3 _ C3 + +; Filling space: 0CH +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bd600 LABEL NEAR + mov ecx, dword ptr [esp+8H] ; 100BD600 _ 8B. 4C 24, 08 + push ebx ; 100BD604 _ 53 + mov bx, word ptr [ecx] ; 100BD605 _ 66: 8B. 19 + push esi ; 100BD608 _ 56 + mov eax, dword ptr [esp+14H] ; 100BD609 _ 8B. 44 24, 14 + push edi ; 100BD60D _ 57 + mov ax, word ptr [eax] ; 100BD60E _ 66: 8B. 00 + push ebp ; 100BD611 _ 55 + test ax, ax ; 100BD612 _ 66: 85. C0 + mov edx, dword ptr [esp+20H] ; 100BD615 _ 8B. 54 24, 20 + mov si, word ptr [edx] ; 100BD619 _ 66: 8B. 32 + lea edi, [ebx+esi] ; 100BD61C _ 8D. 3C 33 + jl ?_25171 ; 100BD61F _ 7C, 50 + movsx ebp, ax ; 100BD621 _ 0F BF. E8 + mov eax, dword ptr [esp+14H] ; 100BD624 _ 8B. 44 24, 14 + cmp dword ptr [eax+8H], ebp ; 100BD628 _ 39. 68, 08 + jle ?_25171 ; 100BD62B _ 7E, 44 + test di, di ; 100BD62D _ 66: 85. FF + jl ?_25171 ; 100BD630 _ 7C, 3F + movsx ebp, bx ; 100BD632 _ 0F BF. EB + cmp ebp, dword ptr [eax+4H] ; 100BD635 _ 3B. 68, 04 + jge ?_25171 ; 100BD638 _ 7D, 37 + test bx, bx ; 100BD63A _ 66: 85. DB + jge ?_25169 ; 100BD63D _ 7D, 0B + mov si, di ; 100BD63F _ 66: 8B. F7 + mov word ptr [edx], di ; 100BD642 _ 66: 89. 3A +; Note: Length-changing prefix causes delay on Intel processors + mov word ptr [ecx], 0 ; 100BD645 _ 66: C7. 01, 0000 +?_25169:movsx ecx, di ; 100BD64A _ 0F BF. CF + mov eax, dword ptr [eax+4H] ; 100BD64D _ 8B. 40, 04 + cmp ecx, eax ; 100BD650 _ 3B. C8 + jle ?_25170 ; 100BD652 _ 7E, 09 + sub si, di ; 100BD654 _ 66: 2B. F7 + add si, ax ; 100BD657 _ 66: 03. F0 + mov word ptr [edx], si ; 100BD65A _ 66: 89. 32 +?_25170:test si, si ; 100BD65D _ 66: 85. F6 + mov eax, 0 ; 100BD660 _ B8, 00000000 + jl ?_25172 ; 100BD665 _ 7C, 0C + pop ebp ; 100BD667 _ 5D + mov eax, 1 ; 100BD668 _ B8, 00000001 + pop edi ; 100BD66D _ 5F + pop esi ; 100BD66E _ 5E + pop ebx ; 100BD66F _ 5B + ret ; 100BD670 _ C3 + +?_25171:xor eax, eax ; 100BD671 _ 33. C0 +?_25172:pop ebp ; 100BD673 _ 5D + pop edi ; 100BD674 _ 5F + pop esi ; 100BD675 _ 5E + pop ebx ; 100BD676 _ 5B + ret ; 100BD677 _ C3 + +; Filling space: 8H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bd680 LABEL NEAR + lea eax, [esp+18H] ; 100BD680 _ 8D. 44 24, 18 + push esi ; 100BD684 _ 56 + lea ecx, [esp+14H] ; 100BD685 _ 8D. 4C 24, 14 + push eax ; 100BD689 _ 50 + lea edx, [esp+14H] ; 100BD68A _ 8D. 54 24, 14 + push ecx ; 100BD68E _ 51 + mov esi, dword ptr [esp+10H] ; 100BD68F _ 8B. 74 24, 10 + push edx ; 100BD693 _ 52 + push esi ; 100BD694 _ 56 + call FUN_100bd600 ; 100BD695 _ E8, FFFFFF66 + add esp, 16 ; 100BD69A _ 83. C4, 10 + test eax, eax ; 100BD69D _ 85. C0 + jz ?_25175 ; 100BD69F _ 74, 33 + movsx eax, word ptr [esp+14H] ; 100BD6A1 _ 0F BF. 44 24, 14 + mov ecx, dword ptr [esi+4H] ; 100BD6A6 _ 8B. 4E, 04 + add ecx, 3 ; 100BD6A9 _ 83. C1, 03 + and ecx, 0FFFFFFFCH ; 100BD6AC _ 83. E1, FC + movsx edx, word ptr [esp+10H] ; 100BD6AF _ 0F BF. 54 24, 10 + imul ecx, eax ; 100BD6B4 _ 0F AF. C8 + add ecx, edx ; 100BD6B7 _ 03. CA + mov eax, dword ptr [esp+0CH] ; 100BD6B9 _ 8B. 44 24, 0C + add eax, ecx ; 100BD6BD _ 03. C1 + dec word ptr [esp+1CH] ; 100BD6BF _ 66: FF. 4C 24, 1C + js ?_25175 ; 100BD6C4 _ 78, 0E + mov cl, byte ptr [esp+18H] ; 100BD6C6 _ 8A. 4C 24, 18 +?_25174:mov byte ptr [eax], cl ; 100BD6CA _ 88. 08 + inc eax ; 100BD6CC _ 40 + dec word ptr [esp+1CH] ; 100BD6CD _ 66: FF. 4C 24, 1C + jns ?_25174 ; 100BD6D2 _ 79, F6 +?_25175:pop esi ; 100BD6D4 _ 5E + ret ; 100BD6D5 _ C3 + +; Filling space: 0AH +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH + +FUN_100bd6e0 LABEL NEAR + lea eax, [esp+18H] ; 100BD6E0 _ 8D. 44 24, 18 + push ebx ; 100BD6E4 _ 53 + lea ecx, [esp+14H] ; 100BD6E5 _ 8D. 4C 24, 14 + push esi ; 100BD6E9 _ 56 + lea edx, [esp+14H] ; 100BD6EA _ 8D. 54 24, 14 + push eax ; 100BD6EE _ 50 + mov esi, dword ptr [esp+10H] ; 100BD6EF _ 8B. 74 24, 10 + push ecx ; 100BD6F3 _ 51 + shl word ptr [esp+28H], 1 ; 100BD6F4 _ 66: C1. 64 24, 28, 01 + push edx ; 100BD6FA _ 52 + push esi ; 100BD6FB _ 56 + call FUN_100bd600 ; 100BD6FC _ E8, FFFFFEFF + add esp, 16 ; 100BD701 _ 83. C4, 10 + test eax, eax ; 100BD704 _ 85. C0 + jz ?_25179 ; 100BD706 _ 74, 52 + mov dx, word ptr [esp+20H] ; 100BD708 _ 66: 8B. 54 24, 20 + mov ecx, dword ptr [esi+4H] ; 100BD70D _ 8B. 4E, 04 + and dx, 01H ; 100BD710 _ 66: 83. E2, 01 + add ecx, 3 ; 100BD714 _ 83. C1, 03 + movsx eax, word ptr [esp+18H] ; 100BD717 _ 0F BF. 44 24, 18 + movsx ebx, word ptr [esp+14H] ; 100BD71C _ 0F BF. 5C 24, 14 + and ecx, 0FFFFFFFCH ; 100BD721 _ 83. E1, FC + sar word ptr [esp+20H], 1 ; 100BD724 _ 66: C1. 7C 24, 20, 01 + imul ecx, eax ; 100BD72A _ 0F AF. C8 + add ecx, ebx ; 100BD72D _ 03. CB + mov eax, dword ptr [esp+10H] ; 100BD72F _ 8B. 44 24, 10 + add eax, ecx ; 100BD733 _ 03. C1 + mov bl, byte ptr [esp+1CH] ; 100BD735 _ 8A. 5C 24, 1C + dec word ptr [esp+20H] ; 100BD739 _ 66: FF. 4C 24, 20 + js ?_25178 ; 100BD73E _ 78, 13 +?_25177:mov cx, word ptr [esp+1CH] ; 100BD740 _ 66: 8B. 4C 24, 1C + add eax, 2 ; 100BD745 _ 83. C0, 02 + mov word ptr [eax-2H], cx ; 100BD748 _ 66: 89. 48, FE + dec word ptr [esp+20H] ; 100BD74C _ 66: FF. 4C 24, 20 + jns ?_25177 ; 100BD751 _ 79, ED +?_25178:test dx, dx ; 100BD753 _ 66: 85. D2 + jz ?_25179 ; 100BD756 _ 74, 02 + mov byte ptr [eax], bl ; 100BD758 _ 88. 18 +?_25179:pop esi ; 100BD75A _ 5E + pop ebx ; 100BD75B _ 5B + ret ; 100BD75C _ C3 + +; Filling space: 3H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH + +FUN_100bd760 LABEL NEAR + mov eax, dword ptr [esp+18H] ; 100BD760 _ 8B. 44 24, 18 + sub esp, 4 ; 100BD764 _ 83. EC, 04 +; Note: Length-changing prefix causes delay on Intel processors + mov word ptr [esp+2H], 0 ; 100BD767 _ 66: C7. 44 24, 02, 0000 + mov ecx, dword ptr [esp+14H] ; 100BD76E _ 8B. 4C 24, 14 + push ebx ; 100BD772 _ 53 + push esi ; 100BD773 _ 56 + mov byte ptr [eax], 0 ; 100BD774 _ C6. 00, 00 + cmp word ptr [ecx+6H], 0 ; 100BD777 _ 66: 83. 79, 06, 00 + push edi ; 100BD77C _ 57 + push ebp ; 100BD77D _ 55 + jle ?_25191 ; 100BD77E _ 0F 8E, 000000C1 + mov esi, dword ptr [esp+18H] ; 100BD784 _ 8B. 74 24, 18 + mov edi, dword ptr [esp+1CH] ; 100BD788 _ 8B. 7C 24, 1C + mov ebx, dword ptr [esp+20H] ; 100BD78C _ 8B. 5C 24, 20 + mov ebp, dword ptr [esp+28H] ; 100BD790 _ 8B. 6C 24, 28 +?_25181:mov ecx, ebp ; 100BD794 _ 8B. CD + xor edx, edx ; 100BD796 _ 33. D2 + mov dx, word ptr [ecx+4H] ; 100BD798 _ 66: 8B. 51, 04 + add ebp, dword ptr [ebp] ; 100BD79C _ 03. 6D, 00 + sub edx, 4 ; 100BD79F _ 83. EA, 04 + cmp edx, 12 ; 100BD7A2 _ 83. FA, 0C + ja ?_25190 ; 100BD7A5 _ 0F 87, 00000082 + xor eax, eax ; 100BD7AB _ 33. C0 + mov al, byte ptr [?_25193+edx] ; 100BD7AD _ 8A. 82, 100BD870(d) + jmp dword ptr [?_25192+eax*4] ; 100BD7B3 _ FF. 24 85, 100BD850(d) + +?_25182 LABEL NEAR + add ecx, 6 ; 100BD7BA _ 83. C1, 06 + push ecx ; 100BD7BD _ 51 + push esi ; 100BD7BE _ 56 + call FUN_100bd880 ; 100BD7BF _ E8, 000000BC + mov eax, dword ptr [esp+34H] ; 100BD7C4 _ 8B. 44 24, 34 + add esp, 8 ; 100BD7C8 _ 83. C4, 08 + mov byte ptr [eax], 1 ; 100BD7CB _ C6. 00, 01 + jmp ?_25190 ; 100BD7CE _ EB, 5D + +?_25183 LABEL NEAR + push ebx ; 100BD7D0 _ 53 + add ecx, 6 ; 100BD7D1 _ 83. C1, 06 + push ecx ; 100BD7D4 _ 51 + push edi ; 100BD7D5 _ 57 + push esi ; 100BD7D6 _ 56 + call FUN_100bdac0 ; 100BD7D7 _ E8, 000002E4 + jmp ?_25189 ; 100BD7DC _ EB, 4C + +?_25184 LABEL NEAR + add ecx, 6 ; 100BD7DE _ 83. C1, 06 + push ecx ; 100BD7E1 _ 51 + push esi ; 100BD7E2 _ 56 + call FUN_100bd940 ; 100BD7E3 _ E8, 00000158 + mov eax, dword ptr [esp+34H] ; 100BD7E8 _ 8B. 44 24, 34 + add esp, 8 ; 100BD7EC _ 83. C4, 08 + mov byte ptr [eax], 1 ; 100BD7EF _ C6. 00, 01 + jmp ?_25190 ; 100BD7F2 _ EB, 39 + +?_25185 LABEL NEAR + push ebx ; 100BD7F4 _ 53 + add ecx, 6 ; 100BD7F5 _ 83. C1, 06 + push ecx ; 100BD7F8 _ 51 + push edi ; 100BD7F9 _ 57 + push esi ; 100BD7FA _ 56 + call FUN_100bda10 ; 100BD7FB _ E8, 00000210 + jmp ?_25189 ; 100BD800 _ EB, 28 + +?_25186 LABEL NEAR + push ebx ; 100BD802 _ 53 + add ecx, 6 ; 100BD803 _ 83. C1, 06 + push ecx ; 100BD806 _ 51 + push edi ; 100BD807 _ 57 + push esi ; 100BD808 _ 56 + call FUN_100bdc00 ; 100BD809 _ E8, 000003F2 + jmp ?_25189 ; 100BD80E _ EB, 1A + +?_25187 LABEL NEAR + push ebx ; 100BD810 _ 53 + add ecx, 6 ; 100BD811 _ 83. C1, 06 + push ecx ; 100BD814 _ 51 + push edi ; 100BD815 _ 57 + push esi ; 100BD816 _ 56 + call FUN_100bd960 ; 100BD817 _ E8, 00000144 + jmp ?_25189 ; 100BD81C _ EB, 0C + +?_25188 LABEL NEAR + push ebx ; 100BD81E _ 53 + add ecx, 6 ; 100BD81F _ 83. C1, 06 + push ecx ; 100BD822 _ 51 + push edi ; 100BD823 _ 57 + push esi ; 100BD824 _ 56 + call FUN_100bdc90 ; 100BD825 _ E8, 00000466 +?_25189:add esp, 16 ; 100BD82A _ 83. C4, 10 + +?_25190 LABEL NEAR + inc word ptr [esp+12H] ; 100BD82D _ 66: FF. 44 24, 12 + mov eax, dword ptr [esp+24H] ; 100BD832 _ 8B. 44 24, 24 + mov cx, word ptr [esp+12H] ; 100BD836 _ 66: 8B. 4C 24, 12 + cmp word ptr [eax+6H], cx ; 100BD83B _ 66: 39. 48, 06 + jg ?_25181 ; 100BD83F _ 0F 8F, FFFFFF4F +?_25191:xor ax, ax ; 100BD845 _ 66: 33. C0 + pop ebp ; 100BD848 _ 5D + pop edi ; 100BD849 _ 5F + pop esi ; 100BD84A _ 5E + pop ebx ; 100BD84B _ 5B + add esp, 4 ; 100BD84C _ 83. C4, 04 + ret ; 100BD84F _ C3 + +?_25192 label dword ; switch/case jump table + dd ?_25182 ; 100BD850 _ 100BD7BA (d) + dd ?_25183 ; 100BD854 _ 100BD7D0 (d) + dd ?_25184 ; 100BD858 _ 100BD7DE (d) + dd ?_25185 ; 100BD85C _ 100BD7F4 (d) + dd ?_25186 ; 100BD860 _ 100BD802 (d) + dd ?_25187 ; 100BD864 _ 100BD810 (d) + dd ?_25188 ; 100BD868 _ 100BD81E (d) + dd ?_25190 ; 100BD86C _ 100BD82D (d) + +?_25193 db 00H, 07H, 07H, 01H, 07H, 07H, 07H, 02H ; 100BD870 _ ........ + db 03H, 04H, 07H, 05H, 06H, 0CCH, 0CCH, 0CCH ; 100BD878 _ ........ + +FUN_100bd880 LABEL NEAR + mov eax, dword ptr [esp+8H] ; 100BD880 _ 8B. 44 24, 08 + mov ecx, dword ptr [esp+4H] ; 100BD884 _ 8B. 4C 24, 04 + push eax ; 100BD888 _ 50 + push ecx ; 100BD889 _ 51 + call FUN_100bd8a0 ; 100BD88A _ E8, 00000011 + add esp, 8 ; 100BD88F _ 83. C4, 08 + ret ; 100BD892 _ C3 + +; Filling space: 0DH +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bd8a0 LABEL NEAR + mov eax, dword ptr [esp+8H] ; 100BD8A0 _ 8B. 44 24, 08 + push ebx ; 100BD8A4 _ 53 + mov bx, word ptr [eax] ; 100BD8A5 _ 66: 8B. 18 + push esi ; 100BD8A8 _ 56 + xor si, si ; 100BD8A9 _ 66: 33. F6 + push edi ; 100BD8AC _ 57 + dec bx ; 100BD8AD _ 66: 4B + push ebp ; 100BD8AF _ 55 + lea edi, [eax+2H] ; 100BD8B0 _ 8D. 78, 02 + js ?_25198 ; 100BD8B3 _ 78, 36 +?_25196:movzx ax, byte ptr [edi] ; 100BD8B5 _ 66: 0F B6. 07 + movzx bp, byte ptr [edi+1H] ; 100BD8B9 _ 66: 0F B6. 6F, 01 + add si, ax ; 100BD8BE _ 66: 03. F0 + inc edi ; 100BD8C1 _ 47 + inc edi ; 100BD8C2 _ 47 + test bp, bp ; 100BD8C3 _ 66: 85. ED + jnz ?_25197 ; 100BD8C6 _ 75, 04 +; Note: Length-changing prefix causes delay on Intel processors + mov bp, 256 ; 100BD8C8 _ 66: BD, 0100 +?_25197:mov eax, dword ptr [esp+14H] ; 100BD8CC _ 8B. 44 24, 14 + push ebp ; 100BD8D0 _ 55 + push esi ; 100BD8D1 _ 56 + push edi ; 100BD8D2 _ 57 + add si, bp ; 100BD8D3 _ 66: 03. F5 + push eax ; 100BD8D6 _ 50 + call FUN_100bd8f0 ; 100BD8D7 _ E8, 00000014 + movsx eax, bp ; 100BD8DC _ 0F BF. C5 + add esp, 16 ; 100BD8DF _ 83. C4, 10 + lea ecx, [eax+eax*2] ; 100BD8E2 _ 8D. 0C 40 + add edi, ecx ; 100BD8E5 _ 03. F9 + dec bx ; 100BD8E7 _ 66: 4B + jns ?_25196 ; 100BD8E9 _ 79, CA +?_25198:pop ebp ; 100BD8EB _ 5D + pop edi ; 100BD8EC _ 5F + pop esi ; 100BD8ED _ 5E + pop ebx ; 100BD8EE _ 5B + ret ; 100BD8EF _ C3 + +FUN_100bd8f0 LABEL NEAR + mov dx, word ptr [esp+10H] ; 100BD8F0 _ 66: 8B. 54 24, 10 + push esi ; 100BD8F5 _ 56 + movsx ecx, word ptr [esp+10H] ; 100BD8F6 _ 0F BF. 4C 24, 10 + shl ecx, 2 ; 100BD8FB _ C1. E1, 02 + mov eax, dword ptr [esp+8H] ; 100BD8FE _ 8B. 44 24, 08 + add ecx, dword ptr [eax] ; 100BD902 _ 03. 08 + lea esi, [ecx+eax] ; 100BD904 _ 8D. 34 01 + mov ax, dx ; 100BD907 _ 66: 8B. C2 + dec dx ; 100BD90A _ 66: 4A + test ax, ax ; 100BD90C _ 66: 85. C0 + jz ?_25201 ; 100BD90F _ 74, 25 + mov eax, dword ptr [esp+0CH] ; 100BD911 _ 8B. 44 24, 0C +?_25200:mov cl, byte ptr [eax] ; 100BD915 _ 8A. 08 + add esi, 4 ; 100BD917 _ 83. C6, 04 + add eax, 3 ; 100BD91A _ 83. C0, 03 + mov byte ptr [esi-2H], cl ; 100BD91D _ 88. 4E, FE + mov cl, byte ptr [eax-2H] ; 100BD920 _ 8A. 48, FE + mov byte ptr [esi-3H], cl ; 100BD923 _ 88. 4E, FD + mov cl, byte ptr [eax-1H] ; 100BD926 _ 8A. 48, FF + mov byte ptr [esi-4H], cl ; 100BD929 _ 88. 4E, FC + mov cx, dx ; 100BD92C _ 66: 8B. CA + dec dx ; 100BD92F _ 66: 4A + test cx, cx ; 100BD931 _ 66: 85. C9 + jnz ?_25200 ; 100BD934 _ 75, DF +?_25201:pop esi ; 100BD936 _ 5E + ret ; 100BD937 _ C3 + +; Filling space: 8H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bd940 LABEL NEAR + mov eax, dword ptr [esp+8H] ; 100BD940 _ 8B. 44 24, 08 + mov ecx, dword ptr [esp+4H] ; 100BD944 _ 8B. 4C 24, 04 + push eax ; 100BD948 _ 50 + push ecx ; 100BD949 _ 51 + call FUN_100bd8a0 ; 100BD94A _ E8, FFFFFF51 + add esp, 8 ; 100BD94F _ 83. C4, 08 + ret ; 100BD952 _ C3 + +; Filling space: 0DH +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bd960 LABEL NEAR + mov eax, dword ptr [esp+10H] ; 100BD960 _ 8B. 44 24, 10 + sub esp, 8 ; 100BD964 _ 83. EC, 08 + mov dx, word ptr [eax+8H] ; 100BD967 _ 66: 8B. 50, 08 + push ebx ; 100BD96B _ 53 + mov ecx, dword ptr [esp+18H] ; 100BD96C _ 8B. 4C 24, 18 + push esi ; 100BD970 _ 56 + push edi ; 100BD971 _ 57 + push ebp ; 100BD972 _ 55 + mov di, word ptr [eax+0AH] ; 100BD973 _ 66: 8B. 78, 0A + mov eax, dword ptr [esp+1CH] ; 100BD977 _ 8B. 44 24, 1C + mov esi, dword ptr [eax+4H] ; 100BD97B _ 8B. 70, 04 + movsx eax, di ; 100BD97E _ 0F BF. C7 + add esi, 3 ; 100BD981 _ 83. C6, 03 + dec eax ; 100BD984 _ 48 + and esi, 0FFFFFFFCH ; 100BD985 _ 83. E6, FC + imul esi, eax ; 100BD988 _ 0F AF. F0 + add esi, dword ptr [esp+20H] ; 100BD98B _ 03. 74 24, 20 + dec di ; 100BD98F _ 66: 4F + mov word ptr [esp+12H], di ; 100BD991 _ 66: 89. 7C 24, 12 + js ?_25212 ; 100BD996 _ 78, 64 + movsx eax, dx ; 100BD998 _ 0F BF. C2 + mov dword ptr [esp+14H], eax ; 100BD99B _ 89. 44 24, 14 +?_25204:xor di, di ; 100BD99F _ 66: 33. FF + inc ecx ; 100BD9A2 _ 41 + test dx, dx ; 100BD9A3 _ 66: 85. D2 + jle ?_25211 ; 100BD9A6 _ 7E, 3A +?_25205:mov al, byte ptr [ecx] ; 100BD9A8 _ 8A. 01 + inc ecx ; 100BD9AA _ 41 + test al, al ; 100BD9AB _ 84. C0 + jl ?_25208 ; 100BD9AD _ 7C, 13 + jle ?_25207 ; 100BD9AF _ 7E, 0E + movsx bp, al ; 100BD9B1 _ 66: 0F BE. E8 +?_25206:mov bl, byte ptr [ecx] ; 100BD9B5 _ 8A. 19 + inc esi ; 100BD9B7 _ 46 + dec bp ; 100BD9B8 _ 66: 4D + mov byte ptr [esi-1H], bl ; 100BD9BA _ 88. 5E, FF + jnz ?_25206 ; 100BD9BD _ 75, F6 +?_25207:inc ecx ; 100BD9BF _ 41 + jmp ?_25210 ; 100BD9C0 _ EB, 14 + +?_25208:neg al ; 100BD9C2 _ F6. D8 + test al, al ; 100BD9C4 _ 84. C0 + jle ?_25210 ; 100BD9C6 _ 7E, 0E + movsx bp, al ; 100BD9C8 _ 66: 0F BE. E8 +?_25209:mov bl, byte ptr [ecx] ; 100BD9CC _ 8A. 19 + inc ecx ; 100BD9CE _ 41 + mov byte ptr [esi], bl ; 100BD9CF _ 88. 1E + inc esi ; 100BD9D1 _ 46 + dec bp ; 100BD9D2 _ 66: 4D + jnz ?_25209 ; 100BD9D4 _ 75, F6 +?_25210:movsx ax, al ; 100BD9D6 _ 66: 0F BE. C0 + add di, ax ; 100BD9DA _ 66: 03. F8 + cmp dx, di ; 100BD9DD _ 66: 3B. D7 + jg ?_25205 ; 100BD9E0 _ 7F, C6 +?_25211:mov eax, dword ptr [esp+1CH] ; 100BD9E2 _ 8B. 44 24, 1C + mov eax, dword ptr [eax+4H] ; 100BD9E6 _ 8B. 40, 04 + add eax, 3 ; 100BD9E9 _ 83. C0, 03 + and eax, 0FFFFFFFCH ; 100BD9EC _ 83. E0, FC + add eax, dword ptr [esp+14H] ; 100BD9EF _ 03. 44 24, 14 + sub esi, eax ; 100BD9F3 _ 2B. F0 + dec word ptr [esp+12H] ; 100BD9F5 _ 66: FF. 4C 24, 12 + jns ?_25204 ; 100BD9FA _ 79, A3 +?_25212:pop ebp ; 100BD9FC _ 5D + pop edi ; 100BD9FD _ 5F + pop esi ; 100BD9FE _ 5E + pop ebx ; 100BD9FF _ 5B + add esp, 8 ; 100BDA00 _ 83. C4, 08 + ret ; 100BDA03 _ C3 + +; Filling space: 0CH +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bda10 LABEL NEAR + mov ecx, dword ptr [esp+0CH] ; 100BDA10 _ 8B. 4C 24, 0C + sub esp, 4 ; 100BDA14 _ 83. EC, 04 + mov eax, dword ptr [esp+14H] ; 100BDA17 _ 8B. 44 24, 14 + push ebx ; 100BDA1B _ 53 + mov ax, word ptr [eax+0AH] ; 100BDA1C _ 66: 8B. 40, 0A + push esi ; 100BDA20 _ 56 + sub ax, word ptr [ecx] ; 100BDA21 _ 66: 2B. 01 + push edi ; 100BDA24 _ 57 + dec ax ; 100BDA25 _ 66: 48 + push ebp ; 100BDA27 _ 55 + mov word ptr [esp+12H], ax ; 100BDA28 _ 66: 89. 44 24, 12 + lea esi, [ecx+4H] ; 100BDA2D _ 8D. 71, 04 + mov ax, word ptr [ecx+2H] ; 100BDA30 _ 66: 8B. 41, 02 + dec ax ; 100BDA34 _ 66: 48 + mov word ptr [esp+10H], ax ; 100BDA36 _ 66: 89. 44 24, 10 + js ?_25219 ; 100BDA3B _ 78, 78 +?_25214:xor di, di ; 100BDA3D _ 66: 33. FF + mov bl, byte ptr [esi] ; 100BDA40 _ 8A. 1E + inc esi ; 100BDA42 _ 46 + test bl, bl ; 100BDA43 _ 84. DB + jz ?_25218 ; 100BDA45 _ 74, 62 +?_25215:movzx ax, byte ptr [esi] ; 100BDA47 _ 66: 0F B6. 06 + add di, ax ; 100BDA4B _ 66: 03. F8 + inc esi ; 100BDA4E _ 46 + mov al, byte ptr [esi] ; 100BDA4F _ 8A. 06 + inc esi ; 100BDA51 _ 46 + test al, al ; 100BDA52 _ 84. C0 + jge ?_25216 ; 100BDA54 _ 7D, 27 + mov ecx, esi ; 100BDA56 _ 8B. CE + mov edx, dword ptr [esp+1CH] ; 100BDA58 _ 8B. 54 24, 1C + neg al ; 100BDA5C _ F6. D8 + movsx bp, al ; 100BDA5E _ 66: 0F BE. E8 + inc esi ; 100BDA62 _ 46 + push ebp ; 100BDA63 _ 55 + mov al, byte ptr [ecx] ; 100BDA64 _ 8A. 01 + mov ecx, dword ptr [esp+16H] ; 100BDA66 _ 8B. 4C 24, 16 + push eax ; 100BDA6A _ 50 + push ecx ; 100BDA6B _ 51 + mov eax, dword ptr [esp+24H] ; 100BDA6C _ 8B. 44 24, 24 + push edi ; 100BDA70 _ 57 + push edx ; 100BDA71 _ 52 + push eax ; 100BDA72 _ 50 + call FUN_100bd680 ; 100BDA73 _ E8, FFFFFC08 + add esp, 24 ; 100BDA78 _ 83. C4, 18 + jmp ?_25217 ; 100BDA7B _ EB, 23 + +?_25216:mov ecx, dword ptr [esp+1CH] ; 100BDA7D _ 8B. 4C 24, 1C + mov edx, dword ptr [esp+18H] ; 100BDA81 _ 8B. 54 24, 18 + movsx bp, al ; 100BDA85 _ 66: 0F BE. E8 + mov eax, dword ptr [esp+12H] ; 100BDA89 _ 8B. 44 24, 12 + push ebp ; 100BDA8D _ 55 + push esi ; 100BDA8E _ 56 + push eax ; 100BDA8F _ 50 + push edi ; 100BDA90 _ 57 + push ecx ; 100BDA91 _ 51 + push edx ; 100BDA92 _ 52 + call FUN_100bd580 ; 100BDA93 _ E8, FFFFFAE8 + movsx ecx, bp ; 100BDA98 _ 0F BF. CD + add esp, 24 ; 100BDA9B _ 83. C4, 18 + add esi, ecx ; 100BDA9E _ 03. F1 +?_25217:add di, bp ; 100BDAA0 _ 66: 03. FD + dec bl ; 100BDAA3 _ FE. CB + test bl, bl ; 100BDAA5 _ 84. DB + jnz ?_25215 ; 100BDAA7 _ 75, 9E +?_25218:dec word ptr [esp+12H] ; 100BDAA9 _ 66: FF. 4C 24, 12 + dec word ptr [esp+10H] ; 100BDAAE _ 66: FF. 4C 24, 10 + jns ?_25214 ; 100BDAB3 _ 79, 88 +?_25219:pop ebp ; 100BDAB5 _ 5D + pop edi ; 100BDAB6 _ 5F + pop esi ; 100BDAB7 _ 5E + pop ebx ; 100BDAB8 _ 5B + add esp, 4 ; 100BDAB9 _ 83. C4, 04 + ret ; 100BDABC _ C3 + +; Filling space: 3H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH + +FUN_100bdac0 LABEL NEAR + mov edx, dword ptr [esp+10H] ; 100BDAC0 _ 8B. 54 24, 10 + sub esp, 8 ; 100BDAC4 _ 83. EC, 08 + mov ax, word ptr [edx+8H] ; 100BDAC7 _ 66: 8B. 42, 08 + push ebx ; 100BDACB _ 53 + dec ax ; 100BDACC _ 66: 48 + push esi ; 100BDACE _ 56 + mov word ptr [esp+8H], ax ; 100BDACF _ 66: 89. 44 24, 08 + push edi ; 100BDAD4 _ 57 + mov si, word ptr [edx+0AH] ; 100BDAD5 _ 66: 8B. 72, 0A + push ebp ; 100BDAD9 _ 55 + dec si ; 100BDADA _ 66: 4E + mov ecx, dword ptr [esp+24H] ; 100BDADC _ 8B. 4C 24, 24 + mov bx, word ptr [ecx] ; 100BDAE0 _ 66: 8B. 19 + add ecx, 2 ; 100BDAE3 _ 83. C1, 02 + mov word ptr [esp+12H], bx ; 100BDAE6 _ 66: 89. 5C 24, 12 + mov dword ptr [esp+14H], ecx ; 100BDAEB _ 89. 4C 24, 14 +?_25221:mov eax, dword ptr [esp+14H] ; 100BDAEF _ 8B. 44 24, 14 + mov bx, word ptr [eax] ; 100BDAF3 _ 66: 8B. 18 + add dword ptr [esp+14H], 2 ; 100BDAF6 _ 83. 44 24, 14, 02 + test bx, bx ; 100BDAFB _ 66: 85. DB + jge ?_25223 ; 100BDAFE _ 7D, 49 + test bh, 40H ; 100BDB00 _ F6. C7, 40 + jz ?_25222 ; 100BDB03 _ 74, 05 + add si, bx ; 100BDB05 _ 66: 03. F3 + jmp ?_25221 ; 100BDB08 _ EB, E5 + +?_25222:mov eax, dword ptr [esp+10H] ; 100BDB0A _ 8B. 44 24, 10 + push ebx ; 100BDB0E _ 53 + mov ecx, dword ptr [esp+24H] ; 100BDB0F _ 8B. 4C 24, 24 + push esi ; 100BDB13 _ 56 + mov edx, dword ptr [esp+24H] ; 100BDB14 _ 8B. 54 24, 24 + push eax ; 100BDB18 _ 50 + push ecx ; 100BDB19 _ 51 + push edx ; 100BDB1A _ 52 + call FUN_100bd530 ; 100BDB1B _ E8, FFFFFA10 + mov ecx, dword ptr [esp+28H] ; 100BDB20 _ 8B. 4C 24, 28 + add esp, 20 ; 100BDB24 _ 83. C4, 14 + mov bx, word ptr [ecx] ; 100BDB27 _ 66: 8B. 19 + add dword ptr [esp+14H], 2 ; 100BDB2A _ 83. 44 24, 14, 02 + test bx, bx ; 100BDB2F _ 66: 85. DB + jnz ?_25223 ; 100BDB32 _ 75, 15 + dec si ; 100BDB34 _ 66: 4E + dec word ptr [esp+12H] ; 100BDB36 _ 66: FF. 4C 24, 12 + cmp word ptr [esp+12H], 0 ; 100BDB3B _ 66: 83. 7C 24, 12, 00 + jle ?_25226 ; 100BDB41 _ 0F 8E, 000000AE + jmp ?_25221 ; 100BDB47 _ EB, A6 + +?_25223:xor di, di ; 100BDB49 _ 66: 33. FF +?_25224:mov ecx, dword ptr [esp+14H] ; 100BDB4C _ 8B. 4C 24, 14 + movzx ax, byte ptr [ecx] ; 100BDB50 _ 66: 0F B6. 01 + add di, ax ; 100BDB54 _ 66: 03. F8 + inc dword ptr [esp+14H] ; 100BDB57 _ FF. 44 24, 14 + mov ecx, dword ptr [esp+14H] ; 100BDB5B _ 8B. 4C 24, 14 + movsx bp, byte ptr [ecx] ; 100BDB5F _ 66: 0F BE. 29 + add bp, bp ; 100BDB63 _ 66: 03. ED + inc dword ptr [esp+14H] ; 100BDB66 _ FF. 44 24, 14 + test bp, bp ; 100BDB6A _ 66: 85. ED + jl ?_25225 ; 100BDB6D _ 7C, 3C + mov eax, dword ptr [esp+14H] ; 100BDB6F _ 8B. 44 24, 14 + push ebp ; 100BDB73 _ 55 + mov ecx, dword ptr [esp+24H] ; 100BDB74 _ 8B. 4C 24, 24 + push eax ; 100BDB78 _ 50 + mov edx, dword ptr [esp+24H] ; 100BDB79 _ 8B. 54 24, 24 + push esi ; 100BDB7D _ 56 + push edi ; 100BDB7E _ 57 + push ecx ; 100BDB7F _ 51 + add di, bp ; 100BDB80 _ 66: 03. FD + push edx ; 100BDB83 _ 52 + call FUN_100bd580 ; 100BDB84 _ E8, FFFFF9F7 + movsx ecx, bp ; 100BDB89 _ 0F BF. CD + add dword ptr [esp+2CH], ecx ; 100BDB8C _ 01. 4C 24, 2C + add esp, 24 ; 100BDB90 _ 83. C4, 18 + dec bx ; 100BDB93 _ 66: 4B + jnz ?_25224 ; 100BDB95 _ 75, B5 + dec si ; 100BDB97 _ 66: 4E + dec word ptr [esp+12H] ; 100BDB99 _ 66: FF. 4C 24, 12 + cmp word ptr [esp+12H], 0 ; 100BDB9E _ 66: 83. 7C 24, 12, 00 + jle ?_25226 ; 100BDBA4 _ 7E, 4F + jmp ?_25221 ; 100BDBA6 _ E9, FFFFFF44 + +?_25225:mov eax, dword ptr [esp+14H] ; 100BDBAB _ 8B. 44 24, 14 + mov edx, dword ptr [esp+20H] ; 100BDBAF _ 8B. 54 24, 20 + neg bp ; 100BDBB3 _ 66: F7. DD + add dword ptr [esp+14H], 2 ; 100BDBB6 _ 83. 44 24, 14, 02 + mov cx, bp ; 100BDBBB _ 66: 8B. CD + sar cx, 1 ; 100BDBBE _ 66: C1. F9, 01 + mov ax, word ptr [eax] ; 100BDBC2 _ 66: 8B. 00 + push ecx ; 100BDBC5 _ 51 + mov ecx, dword ptr [esp+20H] ; 100BDBC6 _ 8B. 4C 24, 20 + push eax ; 100BDBCA _ 50 + push esi ; 100BDBCB _ 56 + push edi ; 100BDBCC _ 57 + add di, bp ; 100BDBCD _ 66: 03. FD + push edx ; 100BDBD0 _ 52 + push ecx ; 100BDBD1 _ 51 + call FUN_100bd6e0 ; 100BDBD2 _ E8, FFFFFB09 + add esp, 24 ; 100BDBD7 _ 83. C4, 18 + dec bx ; 100BDBDA _ 66: 4B + jne ?_25224 ; 100BDBDC _ 0F 85, FFFFFF6A + dec si ; 100BDBE2 _ 66: 4E + dec word ptr [esp+12H] ; 100BDBE4 _ 66: FF. 4C 24, 12 + cmp word ptr [esp+12H], 0 ; 100BDBE9 _ 66: 83. 7C 24, 12, 00 + jg ?_25221 ; 100BDBEF _ 0F 8F, FFFFFEFA +?_25226:pop ebp ; 100BDBF5 _ 5D + pop edi ; 100BDBF6 _ 5F + pop esi ; 100BDBF7 _ 5E + pop ebx ; 100BDBF8 _ 5B + add esp, 8 ; 100BDBF9 _ 83. C4, 08 + ret ; 100BDBFC _ C3 + +; Filling space: 3H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH + +FUN_100bdc00 LABEL NEAR + mov eax, dword ptr [esp+10H] ; 100BDC00 _ 8B. 44 24, 10 + sub esp, 8 ; 100BDC04 _ 83. EC, 08 + mov cx, word ptr [eax+8H] ; 100BDC07 _ 66: 8B. 48, 08 + push ebx ; 100BDC0B _ 53 + mov word ptr [esp+6H], cx ; 100BDC0C _ 66: 89. 4C 24, 06 + push esi ; 100BDC11 _ 56 + push edi ; 100BDC12 _ 57 + xor ecx, ecx ; 100BDC13 _ 33. C9 + mov byte ptr [esp+0DH], cl ; 100BDC15 _ 88. 4C 24, 0D + push ebp ; 100BDC19 _ 55 + mov bp, word ptr [eax+0AH] ; 100BDC1A _ 66: 8B. 68, 0A + mov byte ptr [esp+10H], cl ; 100BDC1E _ 88. 4C 24, 10 + dec bp ; 100BDC22 _ 66: 4D + js ?_25230 ; 100BDC24 _ 78, 56 + movsx eax, word ptr [esp+12H] ; 100BDC26 _ 0F BF. 44 24, 12 + mov si, word ptr [esp+12H] ; 100BDC2B _ 66: 8B. 74 24, 12 + mov edi, dword ptr [esp+1CH] ; 100BDC30 _ 8B. 7C 24, 1C + cdq ; 100BDC34 _ 99 + and si, 01H ; 100BDC35 _ 66: 83. E6, 01 + sub eax, edx ; 100BDC39 _ 2B. C2 + sar eax, 1 ; 100BDC3B _ C1. F8, 01 + mov ebx, dword ptr [esp+20H] ; 100BDC3E _ 8B. 5C 24, 20 + mov word ptr [esp+14H], ax ; 100BDC42 _ 66: 89. 44 24, 14 +?_25228:mov eax, dword ptr [esp+14H] ; 100BDC47 _ 8B. 44 24, 14 + mov ecx, dword ptr [esp+10H] ; 100BDC4B _ 8B. 4C 24, 10 + push eax ; 100BDC4F _ 50 + push ecx ; 100BDC50 _ 51 + push ebp ; 100BDC51 _ 55 + push 0 ; 100BDC52 _ 6A, 00 + push ebx ; 100BDC54 _ 53 + push edi ; 100BDC55 _ 57 + call FUN_100bd6e0 ; 100BDC56 _ E8, FFFFFA85 + add esp, 24 ; 100BDC5B _ 83. C4, 18 + test si, si ; 100BDC5E _ 66: 85. F6 + jz ?_25229 ; 100BDC61 _ 74, 15 + mov ax, word ptr [esp+12H] ; 100BDC63 _ 66: 8B. 44 24, 12 + push 0 ; 100BDC68 _ 6A, 00 + dec ax ; 100BDC6A _ 66: 48 + push ebp ; 100BDC6C _ 55 + push eax ; 100BDC6D _ 50 + push ebx ; 100BDC6E _ 53 + push edi ; 100BDC6F _ 57 + call FUN_100bd530 ; 100BDC70 _ E8, FFFFF8BB + add esp, 20 ; 100BDC75 _ 83. C4, 14 +?_25229:dec bp ; 100BDC78 _ 66: 4D + jns ?_25228 ; 100BDC7A _ 79, CB +?_25230:pop ebp ; 100BDC7C _ 5D + pop edi ; 100BDC7D _ 5F + pop esi ; 100BDC7E _ 5E + pop ebx ; 100BDC7F _ 5B + add esp, 8 ; 100BDC80 _ 83. C4, 08 + ret ; 100BDC83 _ C3 + +; Filling space: 0CH +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + db 0CCH, 0CCH, 0CCH, 0CCH + +FUN_100bdc90 LABEL NEAR + mov eax, dword ptr [esp+10H] ; 100BDC90 _ 8B. 44 24, 10 + sub esp, 4 ; 100BDC94 _ 83. EC, 04 + push ebx ; 100BDC97 _ 53 + push esi ; 100BDC98 _ 56 + mov bx, word ptr [eax+0AH] ; 100BDC99 _ 66: 8B. 58, 0A + push edi ; 100BDC9D _ 57 + mov di, word ptr [eax+8H] ; 100BDC9E _ 66: 8B. 78, 08 + push ebp ; 100BDCA2 _ 55 + dec bx ; 100BDCA3 _ 66: 4B + js ?_25233 ; 100BDCA5 _ 78, 2A + mov esi, dword ptr [esp+18H] ; 100BDCA7 _ 8B. 74 24, 18 + mov ebp, dword ptr [esp+20H] ; 100BDCAB _ 8B. 6C 24, 20 + movsx eax, di ; 100BDCAF _ 0F BF. C7 + mov dword ptr [esp+10H], eax ; 100BDCB2 _ 89. 44 24, 10 +?_25232:mov eax, dword ptr [esp+1CH] ; 100BDCB6 _ 8B. 44 24, 1C + push edi ; 100BDCBA _ 57 + push ebp ; 100BDCBB _ 55 + push ebx ; 100BDCBC _ 53 + push 0 ; 100BDCBD _ 6A, 00 + push eax ; 100BDCBF _ 50 + push esi ; 100BDCC0 _ 56 + call FUN_100bd580 ; 100BDCC1 _ E8, FFFFF8BA + add ebp, dword ptr [esp+28H] ; 100BDCC6 _ 03. 6C 24, 28 + add esp, 24 ; 100BDCCA _ 83. C4, 18 + dec bx ; 100BDCCD _ 66: 4B + jns ?_25232 ; 100BDCCF _ 79, E5 +?_25233:pop ebp ; 100BDCD1 _ 5D + pop edi ; 100BDCD2 _ 5F + pop esi ; 100BDCD3 _ 5E + pop ebx ; 100BDCD4 _ 5B + add esp, 4 ; 100BDCD5 _ 83. C4, 04 + ret ; 100BDCD8 _ C3 + +; Filling space: 7H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH, 0CCH + +DecodeFLCFrame LABEL NEAR + mov ecx, dword ptr [esp+10H] ; 100BDCE0 _ 8B. 4C 24, 10 +; Note: Length-changing prefix causes delay on Intel processors + cmp word ptr [ecx+4H], -3590 ; 100BDCE4 _ 66: 81. 79, 04, F1FA + jnz ?_25235 ; 100BDCEA _ 75, 21 + mov eax, dword ptr [esp+14H] ; 100BDCEC _ 8B. 44 24, 14 + lea edx, [ecx+10H] ; 100BDCF0 _ 8D. 51, 10 + push eax ; 100BDCF3 _ 50 + push edx ; 100BDCF4 _ 52 + mov eax, dword ptr [esp+10H] ; 100BDCF5 _ 8B. 44 24, 10 + push ecx ; 100BDCF9 _ 51 + mov ecx, dword ptr [esp+18H] ; 100BDCFA _ 8B. 4C 24, 18 + mov edx, dword ptr [esp+10H] ; 100BDCFE _ 8B. 54 24, 10 + push ecx ; 100BDD02 _ 51 + push eax ; 100BDD03 _ 50 + push edx ; 100BDD04 _ 52 + call FUN_100bd760 ; 100BDD05 _ E8, FFFFFA56 + add esp, 24 ; 100BDD0A _ 83. C4, 18 +?_25235:ret ; 100BDD0D _ C3 + +; Filling space: 2H +; Filler type: INT 3 Debug breakpoint + db 0CCH, 0CCH + +EndOfSection LABEL NEAR + +.text ENDS + +END diff --git a/3rdparty/flic/flic.h b/3rdparty/flic/flic.h index 6d8495f4..c828b2f4 100644 --- a/3rdparty/flic/flic.h +++ b/3rdparty/flic/flic.h @@ -6,31 +6,42 @@ // A basic FLIC header structure from the "EGI" documentation. Source: https://www.compuphase.com/flic.htm#FLICHEADER // This also goes over the FLIC structures: https://github.com/thinkbeforecoding/nomemalloc.handson/blob/master/flic.txt typedef struct { - DWORD size; /* Size of FLIC including this header */ - WORD type; /* File type 0xAF11, 0xAF12, 0xAF30, 0xAF44, ... */ - WORD frames; /* Number of frames in first segment */ - WORD width; /* FLIC width in pixels */ - WORD height; /* FLIC height in pixels */ - WORD depth; /* Bits per pixel (usually 8) */ - WORD flags; /* Set to zero or to three */ - DWORD speed; /* Delay between frames */ - WORD reserved1; /* Set to zero */ - DWORD created; /* Date of FLIC creation (FLC only) */ - DWORD creator; /* Serial number or compiler id (FLC only) */ - DWORD updated; /* Date of FLIC update (FLC only) */ - DWORD updater; /* Serial number (FLC only), see creator */ - WORD aspect_dx; /* Width of square rectangle (FLC only) */ - WORD aspect_dy; /* Height of square rectangle (FLC only) */ - WORD ext_flags; /* EGI: flags for specific EGI extensions */ - WORD keyframes; /* EGI: key-image frequency */ - WORD totalframes; /* EGI: total number of frames (segments) */ - DWORD req_memory; /* EGI: maximum chunk size (uncompressed) */ - WORD max_regions; /* EGI: max. number of regions in a CHK_REGION chunk */ - WORD transp_num; /* EGI: number of transparent levels */ - BYTE reserved2[24]; /* Set to zero */ - DWORD oframe1; /* Offset to frame 1 (FLC only) */ - DWORD oframe2; /* Offset to frame 2 (FLC only) */ - BYTE reserved3[40]; /* Set to zero */ + DWORD size; /* Size of FLIC including this header */ + WORD type; /* File type 0xAF11, 0xAF12, 0xAF30, 0xAF44, ... */ + WORD frames; /* Number of frames in first segment */ + WORD width; /* FLIC width in pixels */ + WORD height; /* FLIC height in pixels */ + WORD depth; /* Bits per pixel (usually 8) */ + WORD flags; /* Set to zero or to three */ + DWORD speed; /* Delay between frames */ + WORD reserved1; /* Set to zero */ + DWORD created; /* Date of FLIC creation (FLC only) */ + DWORD creator; /* Serial number or compiler id (FLC only) */ + DWORD updated; /* Date of FLIC update (FLC only) */ + DWORD updater; /* Serial number (FLC only), see creator */ + WORD aspect_dx; /* Width of square rectangle (FLC only) */ + WORD aspect_dy; /* Height of square rectangle (FLC only) */ + WORD ext_flags; /* EGI: flags for specific EGI extensions */ + WORD keyframes; /* EGI: key-image frequency */ + WORD totalframes; /* EGI: total number of frames (segments) */ + DWORD req_memory; /* EGI: maximum chunk size (uncompressed) */ + WORD max_regions; /* EGI: max. number of regions in a CHK_REGION chunk */ + WORD transp_num; /* EGI: number of transparent levels */ + BYTE reserved2[24]; /* Set to zero */ + DWORD oframe1; /* Offset to frame 1 (FLC only) */ + DWORD oframe2; /* Offset to frame 2 (FLC only) */ + BYTE reserved3[40]; /* Set to zero */ } FLIC_HEADER; -#endif FLIC_H // FLIC_H \ No newline at end of file +extern "C" +{ + void DecodeFLCFrame( + LPBITMAPINFOHEADER bitmapHeader, + void* pixelData, + FLIC_HEADER* flcHeader, + void* flcFrame, + unsigned char* decodedColorMap + ); +} + +#endif // FLIC_H diff --git a/3rdparty/flic/flic.lib b/3rdparty/flic/flic.lib new file mode 100644 index 00000000..8c276550 Binary files /dev/null and b/3rdparty/flic/flic.lib differ diff --git a/3rdparty/smack/RAD.H b/3rdparty/smacker/rad.h similarity index 99% rename from 3rdparty/smack/RAD.H rename to 3rdparty/smacker/rad.h index f041dc1c..610bd794 100644 --- a/3rdparty/smack/RAD.H +++ b/3rdparty/smacker/rad.h @@ -82,7 +82,7 @@ #endif #if !defined(__RADDOS__) && !defined(__RADWIN__) && !defined(__RADMAC__) - #error RAD.H didn'y detect your platform. Define __DOS__, __WINDOWS__, WIN32, macintosh, or powerc. + #error "RAD.H didn'y detect your platform. Define __DOS__, __WINDOWS__, WIN32, macintosh, or powerc." #endif #ifdef __RADMAC__ diff --git a/3rdparty/smack/SMACK.H b/3rdparty/smacker/smack.h similarity index 100% rename from 3rdparty/smack/SMACK.H rename to 3rdparty/smacker/smack.h diff --git a/3rdparty/smack/SMACK.LIB b/3rdparty/smacker/smack.lib similarity index 100% rename from 3rdparty/smack/SMACK.LIB rename to 3rdparty/smacker/smack.lib diff --git a/CMakeLists.txt b/CMakeLists.txt index 3650c718..eb509e5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,212 +2,93 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) project(isle CXX) -option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) -option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC}) -option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" ON) +include(CheckCXXSourceCompiles) +include(CMakeDependentOption) +include(CMakePushCheckState) -add_library(lego1 SHARED - LEGO1/act1state.cpp - LEGO1/act2brick.cpp - LEGO1/act2policestation.cpp - LEGO1/act3.cpp - LEGO1/act3shark.cpp - LEGO1/act3state.cpp - LEGO1/ambulance.cpp - LEGO1/ambulancemissionstate.cpp - LEGO1/animstate.cpp - LEGO1/beachhouseentity.cpp - LEGO1/bike.cpp - LEGO1/buildingentity.cpp - LEGO1/bumpbouy.cpp - LEGO1/carrace.cpp - LEGO1/define.cpp - LEGO1/dllmain.cpp - LEGO1/dunebuggy.cpp - LEGO1/elevatorbottom.cpp - LEGO1/gasstation.cpp - LEGO1/gasstationentity.cpp - LEGO1/gasstationstate.cpp - LEGO1/gifmanager.cpp - LEGO1/helicopter.cpp - LEGO1/helicopterstate.cpp - LEGO1/historybook.cpp - LEGO1/hospital.cpp - LEGO1/hospitalentity.cpp - LEGO1/hospitalstate.cpp - LEGO1/infocenter.cpp - LEGO1/infocenterdoor.cpp - LEGO1/infocenterentity.cpp - LEGO1/infocenterstate.cpp - LEGO1/isle.cpp - LEGO1/isleactor.cpp - LEGO1/islepathactor.cpp - LEGO1/jetski.cpp - LEGO1/jetskirace.cpp - LEGO1/jukebox.cpp - LEGO1/jukeboxentity.cpp - LEGO1/jukeboxstate.cpp - LEGO1/lego3dview.cpp - LEGO1/legoact2state.cpp - LEGO1/legoactioncontrolpresenter.cpp - LEGO1/legoactor.cpp - LEGO1/legoactor.cpp - LEGO1/legoanimactor.cpp - LEGO1/legoanimationmanager.cpp - LEGO1/legoanimmmpresenter.cpp - LEGO1/legoanimpresenter.cpp - LEGO1/legobackgroundcolor.cpp - LEGO1/legobackgroundcolor.cpp - LEGO1/legobuildingmanager.cpp - LEGO1/legocachesound.cpp - LEGO1/legocameracontroller.cpp - LEGO1/legocarbuild.cpp - LEGO1/legocarbuildanimpresenter.cpp - LEGO1/legocontrolmanager.cpp - LEGO1/legoentity.cpp - LEGO1/legoentitypresenter.cpp - LEGO1/legoeventnotificationparam.cpp - LEGO1/legoflctexturepresenter.cpp - LEGO1/legofullscreenmovie.cpp - LEGO1/legogamestate.cpp - LEGO1/legohideanimpresenter.cpp - LEGO1/legoinputmanager.cpp - LEGO1/legojetski.cpp - LEGO1/legoloadcachesoundpresenter.cpp - LEGO1/legolocomotionanimpresenter.cpp - LEGO1/legometerpresenter.cpp - LEGO1/legomodelpresenter.cpp - LEGO1/legonavcontroller.cpp - LEGO1/legoobjectfactory.cpp - LEGO1/legoomni.cpp - LEGO1/legopalettepresenter.cpp - LEGO1/legopartpresenter.cpp - LEGO1/legopathactor.cpp - LEGO1/legopathcontroller.cpp - LEGO1/legopathpresenter.cpp - LEGO1/legophonemepresenter.cpp - LEGO1/legoplantmanager.cpp - LEGO1/legorace.cpp - LEGO1/legoroi.cpp - LEGO1/legosoundmanager.cpp - LEGO1/legostate.cpp - LEGO1/legostream.cpp - LEGO1/legotexturepresenter.cpp - LEGO1/legoutil.cpp - LEGO1/legounksavedatawriter.cpp - LEGO1/legovehiclebuildstate.cpp - LEGO1/legovideomanager.cpp - LEGO1/legoworld.cpp - LEGO1/legoworldpresenter.cpp - LEGO1/motorcycle.cpp - LEGO1/mxactionnotificationparam.cpp - LEGO1/mxatomid.cpp - LEGO1/mxatomidcounter.cpp - LEGO1/mxaudiomanager.cpp - LEGO1/mxaudiopresenter.cpp - LEGO1/mxautolocker.cpp - LEGO1/mxbackgroundaudiomanager.cpp - LEGO1/mxbitmap.cpp - LEGO1/mxcompositemediapresenter.cpp - LEGO1/mxcompositepresenter.cpp - LEGO1/mxcontrolpresenter.cpp - LEGO1/mxcore.cpp - LEGO1/mxcriticalsection.cpp - LEGO1/mxdirect3d.cpp - LEGO1/mxdirectdraw.cpp - LEGO1/mxdiskstreamcontroller.cpp - LEGO1/mxdiskstreamprovider.cpp - LEGO1/mxdisplaysurface.cpp - LEGO1/mxdsaction.cpp - LEGO1/mxdsanim.cpp - LEGO1/mxdsbuffer.cpp - LEGO1/mxdschunk.cpp - LEGO1/mxdsevent.cpp - LEGO1/mxdsfile.cpp - LEGO1/mxdsmediaaction.cpp - LEGO1/mxdsmultiaction.cpp - LEGO1/mxdsobject.cpp - LEGO1/mxdsobjectaction.cpp - LEGO1/mxdsparallelaction.cpp - LEGO1/mxdsselectaction.cpp - LEGO1/mxdsserialaction.cpp - LEGO1/mxdssound.cpp - LEGO1/mxdssource.cpp - LEGO1/mxdsstill.cpp - LEGO1/mxdsstreamingaction.cpp - LEGO1/mxdssubscriber.cpp - LEGO1/mxentity.cpp - LEGO1/mxeventmanager.cpp - LEGO1/mxeventpresenter.cpp - LEGO1/mxflcpresenter.cpp - LEGO1/mxioinfo.cpp - LEGO1/mxloopingflcpresenter.cpp - LEGO1/mxloopingmidipresenter.cpp - LEGO1/mxloopingsmkpresenter.cpp - LEGO1/mxmediamanager.cpp - LEGO1/mxmediapresenter.cpp - LEGO1/mxmidipresenter.cpp - LEGO1/mxmusicmanager.cpp - LEGO1/mxmusicpresenter.cpp - LEGO1/mxnotificationmanager.cpp - LEGO1/mxnotificationparam.cpp - LEGO1/mxobjectfactory.cpp - LEGO1/mxomni.cpp - LEGO1/mxomnicreateflags.cpp - LEGO1/mxomnicreateparam.cpp - LEGO1/mxpalette.cpp - LEGO1/mxparam.cpp - LEGO1/mxpresenter.cpp - LEGO1/mxramstreamcontroller.cpp - LEGO1/mxramstreamprovider.cpp - LEGO1/mxregion.cpp - LEGO1/mxscheduler.cpp - LEGO1/mxsemaphore.cpp - LEGO1/mxsmack.cpp - LEGO1/mxsmkpresenter.cpp - LEGO1/mxsoundmanager.cpp - LEGO1/mxsoundpresenter.cpp - LEGO1/mxstillpresenter.cpp - LEGO1/mxstreamchunk.cpp - LEGO1/mxstreamcontroller.cpp - LEGO1/mxstreamer.cpp - LEGO1/mxstreamlist.cpp - LEGO1/mxstreamprovider.cpp - LEGO1/mxstring.cpp - LEGO1/mxthread.cpp - LEGO1/mxticklemanager.cpp - LEGO1/mxtimer.cpp - LEGO1/mxtransitionmanager.cpp - LEGO1/mxtype17notificationparam.cpp - LEGO1/mxunknown100dbdbc.cpp - LEGO1/mxvariable.cpp - LEGO1/mxvariabletable.cpp - LEGO1/mxvideomanager.cpp - LEGO1/mxvideoparam.cpp - LEGO1/mxvideoparamflags.cpp - LEGO1/mxvideopresenter.cpp - LEGO1/mxwavepresenter.cpp - LEGO1/pizza.cpp - LEGO1/pizzamissionstate.cpp - LEGO1/pizzeria.cpp - LEGO1/pizzeriastate.cpp - LEGO1/police.cpp - LEGO1/policeentity.cpp - LEGO1/policestate.cpp - LEGO1/racecar.cpp - LEGO1/racestandsentity.cpp - LEGO1/racestate.cpp - LEGO1/radio.cpp - LEGO1/radiostate.cpp - LEGO1/realtime/matrix.cpp - LEGO1/realtime/orientableroi.cpp - LEGO1/realtime/realtime.cpp - LEGO1/realtime/realtimeview.cpp - LEGO1/realtime/vector.cpp - LEGO1/registrationbook.cpp - LEGO1/score.cpp - LEGO1/scorestate.cpp - LEGO1/skateboard.cpp +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE) +option(ENABLE_CLANG_TIDY "Enable clang-tidy") +if (ENABLE_CLANG_TIDY) + find_program(CLANG_TIDY_BIN NAMES "clang-tidy") + set(CMAKE_C_CLANG_TIDY "${CLANG_TIDY_BIN}") + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_BIN}") +endif() + +math(EXPR bits "8 * ${CMAKE_SIZEOF_VOID_P}") +message(STATUS "Building ${bits}-bit LEGO Island") +if (NOT bits EQUAL 32) + 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() + +set(lego1_targets) +macro(register_lego1_target __target) + list(APPEND lego1_targets ${__target}) +endmacro() + +function(add_cxx_warning WARNING) + if(ISLE_WERROR) + set(compiler_option "-Werror=${WARNING}") + else() + set(compiler_option "-W${WARNING}") + endif() + string(MAKE_C_IDENTIFIER "COMPILER_SUPPORTS${compiler_option}" varname) + + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_FLAGS "${compiler_option} ") + if(MSVC) + string(APPEND CMAKE_REQUIRED_FLAGS "/WX") + else() + string(APPEND CMAKE_REQUIRED_FLAGS "-Werror") + endif() + check_cxx_source_compiles("int main() { return 0; }" ${varname}) + cmake_pop_check_state() + + if(${varname}) + add_compile_options(${compiler_option}) + endif() +endfunction() + +message(STATUS "MSVC for decompilation: ${MSVC_FOR_DECOMP}") + +option(ISLE_WERROR "Treat warnings as errors" OFF) +option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) +option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC_FOR_DECOMP}) +option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" ON) +cmake_dependent_option(ISLE_USE_DX5_LIBS "Build with internal DirectX 5 SDK Libraries" ON ISLE_USE_DX5 OFF) + +add_cxx_warning(parentheses) + +add_library(DirectX5::DirectX5 INTERFACE IMPORTED) +target_include_directories(DirectX5::DirectX5 INTERFACE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/inc") +if(ISLE_USE_DX5_LIBS) + target_link_directories(DirectX5::DirectX5 INTERFACE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/lib") +endif() + +add_library(Smacker::Smacker STATIC IMPORTED) +set_property(TARGET Smacker::Smacker PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/smacker/smack.lib") +set_property(TARGET Smacker::Smacker PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/smacker") + +add_library(FLIC::FLIC STATIC IMPORTED) +set_property(TARGET FLIC::FLIC PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/flic/flic.lib") +set_property(TARGET FLIC::FLIC PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/flic") + +add_library(Vec::Vec INTERFACE IMPORTED) +target_include_directories(Vec::Vec INTERFACE "${CMAKE_SOURCE_DIR}/3rdparty/vec") + +add_library(SmartHeap::SmartHeap STATIC IMPORTED) +set_property(TARGET SmartHeap::SmartHeap PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SHLW32MT.LIB") +set_property(TARGET SmartHeap::SmartHeap PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/smartheap") +set_property(TARGET SmartHeap::SmartHeap PROPERTY INTERFACE_COMPILE_OPTIONS "/FI${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SMRTHEAP.HPP") + +add_library(tglrl STATIC LEGO1/tgl/d3drm/camera.cpp LEGO1/tgl/d3drm/device.cpp LEGO1/tgl/d3drm/group.cpp @@ -217,44 +98,317 @@ add_library(lego1 SHARED LEGO1/tgl/d3drm/texture.cpp LEGO1/tgl/d3drm/unk.cpp LEGO1/tgl/d3drm/view.cpp - LEGO1/towtrack.cpp - LEGO1/towtrackmissionstate.cpp +) +register_lego1_target(tglrl) +set_property(TARGET tglrl PROPERTY ARCHIVE_OUTPUT_NAME "tglrl40$<$:d>") +target_include_directories(tglrl PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(tglrl PRIVATE d3drm) + +add_library(realtime STATIC + LEGO1/realtime/matrix.cpp + LEGO1/realtime/orientableroi.cpp + LEGO1/realtime/realtime.cpp + LEGO1/realtime/realtimeview.cpp + LEGO1/realtime/vector.cpp +) +register_lego1_target(realtime) +set_property(TARGET realtime PROPERTY ARCHIVE_OUTPUT_NAME "realtime$<$:d>") +target_include_directories(realtime PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(realtime PRIVATE Vec::Vec) + +add_library(viewmanager STATIC + LEGO1/viewmanager/viewlodlist.cpp LEGO1/viewmanager/viewmanager.cpp LEGO1/viewmanager/viewroi.cpp ) +register_lego1_target(viewmanager) +set_property(TARGET viewmanager PROPERTY ARCHIVE_OUTPUT_NAME "viewmanager$<$:d>") +target_include_directories(viewmanager PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(viewmanager PRIVATE Vec::Vec) + +add_library(mxdirectx STATIC + LEGO1/mxdirectx/mxdirect3d.cpp + LEGO1/mxdirectx/mxdirectdraw.cpp +) +register_lego1_target(mxdirectx) +set_property(TARGET mxdirectx PROPERTY ARCHIVE_OUTPUT_NAME "MxDirectX$<$:d>") +target_include_directories(mxdirectx PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(mxdirectx PRIVATE ddraw) + +add_library(roi STATIC + LEGO1/lego/sources/roi/legoroi.cpp +) +register_lego1_target(roi) +set_property(TARGET roi PROPERTY ARCHIVE_OUTPUT_NAME "roi$<$:d>") +target_include_directories(roi PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(roi PRIVATE) + +add_library(misc STATIC + LEGO1/lego/sources/misc/legoimage.cpp + LEGO1/lego/sources/misc/legostorage.cpp + LEGO1/lego/sources/misc/legotexture.cpp + LEGO1/lego/sources/misc/legotree.cpp +) +register_lego1_target(misc) +set_property(TARGET misc PROPERTY ARCHIVE_OUTPUT_NAME "misc$<$:d>") +target_include_directories(misc PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(misc PRIVATE) + +add_library(3dmanager STATIC + LEGO1/lego/sources/3dmanager/lego3dmanager.cpp + LEGO1/lego/sources/3dmanager/lego3dview.cpp + LEGO1/lego/sources/3dmanager/legoview1.cpp + LEGO1/lego/sources/3dmanager/tglsurface.cpp +) +register_lego1_target(3dmanager) +set_property(TARGET 3dmanager PROPERTY ARCHIVE_OUTPUT_NAME "3dmanager$<$:d>") +target_include_directories(3dmanager PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(3dmanager PRIVATE Vec::Vec) + +add_library(omni STATIC + LEGO1/omni/src/action/mxdsaction.cpp + LEGO1/omni/src/action/mxdsanim.cpp + LEGO1/omni/src/action/mxdsevent.cpp + LEGO1/omni/src/action/mxdsmediaaction.cpp + LEGO1/omni/src/action/mxdsmultiaction.cpp + LEGO1/omni/src/action/mxdsobjectaction.cpp + LEGO1/omni/src/action/mxdsobject.cpp + LEGO1/omni/src/action/mxdsparallelaction.cpp + LEGO1/omni/src/action/mxdsselectaction.cpp + LEGO1/omni/src/action/mxdsserialaction.cpp + LEGO1/omni/src/action/mxdssound.cpp + LEGO1/omni/src/action/mxdsstill.cpp + LEGO1/omni/src/action/mxdsstreamingaction.cpp + LEGO1/omni/src/audio/mxaudiomanager.cpp + LEGO1/omni/src/audio/mxaudiopresenter.cpp + LEGO1/omni/src/audio/mxloopingmidipresenter.cpp + LEGO1/omni/src/audio/mxmidipresenter.cpp + LEGO1/omni/src/audio/mxmusicmanager.cpp + LEGO1/omni/src/audio/mxmusicpresenter.cpp + LEGO1/omni/src/audio/mxsoundmanager.cpp + LEGO1/omni/src/audio/mxsoundpresenter.cpp + LEGO1/omni/src/audio/mxwavepresenter.cpp + LEGO1/omni/src/common/mxatomidcounter.cpp + LEGO1/omni/src/common/mxatomid.cpp + LEGO1/omni/src/common/mxcompositepresenter.cpp + LEGO1/omni/src/common/mxcore.cpp + LEGO1/omni/src/common/mxmediamanager.cpp + LEGO1/omni/src/common/mxmediapresenter.cpp + LEGO1/omni/src/common/mxobjectfactory.cpp + LEGO1/omni/src/common/mxpresenter.cpp + LEGO1/omni/src/common/mxstring.cpp + LEGO1/omni/src/common/mxticklemanager.cpp + LEGO1/omni/src/common/mxtimer.cpp + LEGO1/omni/src/common/mxutil.cpp + LEGO1/omni/src/common/mxvariable.cpp + LEGO1/omni/src/common/mxvariabletable.cpp + LEGO1/omni/src/entity/mxentity.cpp + LEGO1/omni/src/event/mxeventmanager.cpp + LEGO1/omni/src/event/mxeventpresenter.cpp + LEGO1/omni/src/main/mxomni.cpp + LEGO1/omni/src/main/mxomnicreateflags.cpp + LEGO1/omni/src/main/mxomnicreateparam.cpp + LEGO1/omni/src/notify/mxactionnotificationparam.cpp + LEGO1/omni/src/notify/mxnotificationmanager.cpp + LEGO1/omni/src/notify/mxnotificationparam.cpp + LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp + LEGO1/omni/src/stream/mxdiskstreamprovider.cpp + LEGO1/omni/src/stream/mxdsbuffer.cpp + LEGO1/omni/src/stream/mxdschunk.cpp + LEGO1/omni/src/stream/mxdsfile.cpp + LEGO1/omni/src/stream/mxdssource.cpp + LEGO1/omni/src/stream/mxdssubscriber.cpp + LEGO1/omni/src/stream/mxioinfo.cpp + LEGO1/omni/src/stream/mxramstreamcontroller.cpp + LEGO1/omni/src/stream/mxramstreamprovider.cpp + LEGO1/omni/src/stream/mxstreamchunk.cpp + LEGO1/omni/src/stream/mxstreamcontroller.cpp + LEGO1/omni/src/stream/mxstreamer.cpp + LEGO1/omni/src/stream/mxstreamlist.cpp + LEGO1/omni/src/stream/mxstreamprovider.cpp + LEGO1/omni/src/system/mxautolocker.cpp + LEGO1/omni/src/system/mxcriticalsection.cpp + LEGO1/omni/src/system/mxscheduler.cpp + LEGO1/omni/src/system/mxsemaphore.cpp + LEGO1/omni/src/system/mxthread.cpp + LEGO1/omni/src/video/mxbitmap.cpp + LEGO1/omni/src/video/mxdisplaysurface.cpp + LEGO1/omni/src/video/mxflcpresenter.cpp + LEGO1/omni/src/video/mxloopingflcpresenter.cpp + LEGO1/omni/src/video/mxloopingsmkpresenter.cpp + LEGO1/omni/src/video/mxpalette.cpp + LEGO1/omni/src/video/mxregion.cpp + LEGO1/omni/src/video/mxregioncursor.cpp + LEGO1/omni/src/video/mxsmack.cpp + LEGO1/omni/src/video/mxsmkpresenter.cpp + LEGO1/omni/src/video/mxstillpresenter.cpp + LEGO1/omni/src/video/mxvideomanager.cpp + LEGO1/omni/src/video/mxvideoparam.cpp + LEGO1/omni/src/video/mxvideoparamflags.cpp + LEGO1/omni/src/video/mxvideopresenter.cpp +) +register_lego1_target(omni) +set_property(TARGET omni PROPERTY ARCHIVE_OUTPUT_NAME "omni$<$:d>") +target_include_directories(omni PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include" "${CMAKE_SOURCE_DIR}/LEGO1" "${CMAKE_SOURCE_DIR}/util") +target_link_libraries(omni PRIVATE dsound winmm FLIC::FLIC Smacker::Smacker) + +add_library(lego1 SHARED + LEGO1/define.cpp + LEGO1/lego/legoomni/src/act1/act1state.cpp + LEGO1/lego/legoomni/src/act2/act2brick.cpp + LEGO1/lego/legoomni/src/act2/act2policestation.cpp + LEGO1/lego/legoomni/src/act2/legoact2.cpp + LEGO1/lego/legoomni/src/act2/legoact2state.cpp + LEGO1/lego/legoomni/src/act3/act3.cpp + LEGO1/lego/legoomni/src/act3/act3shark.cpp + LEGO1/lego/legoomni/src/act3/act3state.cpp + LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp + LEGO1/lego/legoomni/src/audio/legocachesound.cpp + LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp + LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp + LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp + LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp + LEGO1/lego/legoomni/src/build/buildingentity.cpp + LEGO1/lego/legoomni/src/build/dunebuggy.cpp + LEGO1/lego/legoomni/src/build/helicopter.cpp + LEGO1/lego/legoomni/src/build/helicopterstate.cpp + LEGO1/lego/legoomni/src/build/jetski.cpp + LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp + LEGO1/lego/legoomni/src/build/legocarbuild.cpp + LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp + LEGO1/lego/legoomni/src/build/racecar.cpp + LEGO1/lego/legoomni/src/common/animstate.cpp + LEGO1/lego/legoomni/src/common/gifmanager.cpp + LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp + LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp + LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp + LEGO1/lego/legoomni/src/common/legogamestate.cpp + LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp + LEGO1/lego/legoomni/src/common/legoplantmanager.cpp + LEGO1/lego/legoomni/src/common/legostate.cpp + LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp + 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/legocarraceactor.cpp + LEGO1/lego/legoomni/src/entity/legoentity.cpp + LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp + LEGO1/lego/legoomni/src/entity/legojetski.cpp + LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp + LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp + LEGO1/lego/legoomni/src/entity/legopathactor.cpp + LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp + LEGO1/lego/legoomni/src/entity/legorace.cpp + LEGO1/lego/legoomni/src/entity/legoraceactor.cpp + LEGO1/lego/legoomni/src/entity/legoracecar.cpp + LEGO1/lego/legoomni/src/entity/legoworld.cpp + LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp + LEGO1/lego/legoomni/src/gasstation/gasstation.cpp + LEGO1/lego/legoomni/src/gasstation/gasstationentity.cpp + LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp + LEGO1/lego/legoomni/src/hospital/ambulance.cpp + LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp + LEGO1/lego/legoomni/src/hospital/hospital.cpp + LEGO1/lego/legoomni/src/hospital/hospitalentity.cpp + LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp + LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp + LEGO1/lego/legoomni/src/infocenter/infocenter.cpp + LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp + LEGO1/lego/legoomni/src/infocenter/infocenterentity.cpp + LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp + LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp + LEGO1/lego/legoomni/src/infocenter/score.cpp + LEGO1/lego/legoomni/src/infocenter/scorestate.cpp + LEGO1/lego/legoomni/src/input/legoinputmanager.cpp + LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp + LEGO1/lego/legoomni/src/isle/bike.cpp + LEGO1/lego/legoomni/src/isle/bumpbouy.cpp + LEGO1/lego/legoomni/src/isle/doors.cpp + LEGO1/lego/legoomni/src/isle/historybook.cpp + LEGO1/lego/legoomni/src/isle/isleactor.cpp + LEGO1/lego/legoomni/src/isle/isle.cpp + LEGO1/lego/legoomni/src/isle/islepathactor.cpp + 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/motocycle.cpp + LEGO1/lego/legoomni/src/isle/radio.cpp + LEGO1/lego/legoomni/src/isle/radiostate.cpp + LEGO1/lego/legoomni/src/isle/skateboard.cpp + LEGO1/lego/legoomni/src/main/legoomni.cpp + LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp + LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp + LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp + LEGO1/lego/legoomni/src/pizzeria/pizza.cpp + LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp + LEGO1/lego/legoomni/src/pizzeria/pizzeria.cpp + LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp + LEGO1/lego/legoomni/src/police/police.cpp + LEGO1/lego/legoomni/src/police/policeentity.cpp + LEGO1/lego/legoomni/src/police/policestate.cpp + LEGO1/lego/legoomni/src/race/carrace.cpp + LEGO1/lego/legoomni/src/race/jetskirace.cpp + LEGO1/lego/legoomni/src/race/racestandsentity.cpp + LEGO1/lego/legoomni/src/race/racestate.cpp + LEGO1/lego/legoomni/src/towtrack/towtrack.cpp + LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp + LEGO1/lego/legoomni/src/unknown/legounknown100d7c88.cpp + LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp + LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp + LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp + LEGO1/lego/legoomni/src/video/legocarbuildanimpresenter.cpp + LEGO1/lego/legoomni/src/video/legoflctexturepresenter.cpp + LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp + LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp + LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp + LEGO1/lego/legoomni/src/video/legometerpresenter.cpp + LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp + LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp + LEGO1/lego/legoomni/src/video/legopartpresenter.cpp + LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp + LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp + LEGO1/lego/legoomni/src/video/legovideomanager.cpp + LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp + LEGO1/main.cpp +) +register_lego1_target(lego1) + if (MINGW) target_compile_definitions(lego1 PRIVATE DIRECTINPUT_VERSION=0x0500) endif() -# Additional include directories -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/util") -target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/3rdparty/vec") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/flic") -target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smack") - -if (ISLE_USE_SMARTHEAP) - add_library(SmartHeap::SmartHeap STATIC IMPORTED) - set_target_properties(SmartHeap::SmartHeap PROPERTIES - IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SHLW32MT.LIB" - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/3rdparty/smartheap" - INTERFACE_COMPILE_OPTIONS "/FI${CMAKE_SOURCE_DIR}/3rdparty/smartheap/SMRTHEAP.HPP") - - target_link_libraries(lego1 PRIVATE SmartHeap::SmartHeap) +if (MSVC) + target_sources(lego1 PRIVATE LEGO1/LegoOmni.def) +else() + target_sources(lego1 PRIVATE LEGO1/LegoOmni.mingw.def) endif() -# Use internal DirectX 5 if required -if (ISLE_USE_DX5) - target_include_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/inc") - target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/lib") -endif() - -target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smack") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/util") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1/omni/include") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1/lego/sources") +target_include_directories(lego1 PUBLIC "${CMAKE_SOURCE_DIR}/LEGO1/lego/legoomni/include") # Link libraries -target_link_libraries(lego1 PRIVATE ddraw dsound dxguid dinput winmm d3drm smack) +target_link_libraries(lego1 PRIVATE tglrl viewmanager realtime mxdirectx roi FLIC::FLIC Vec::Vec dinput dxguid misc 3dmanager omni) + +if (ISLE_USE_SMARTHEAP) + foreach(tgt IN LISTS lego1_targets) + target_link_libraries(${tgt} PRIVATE SmartHeap::SmartHeap) + endforeach() +endif() +foreach(tgt IN LISTS lego1_targets) + target_link_libraries(${tgt} PRIVATE $<$:DirectX5::DirectX5>) +endforeach() # Make sure filenames are ALL CAPS set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1) +set_property(TARGET lego1 PROPERTY PREFIX "") set_property(TARGET lego1 PROPERTY SUFFIX ".DLL") if (ISLE_BUILD_APP) @@ -264,16 +418,8 @@ if (ISLE_BUILD_APP) ISLE/define.cpp ) - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/util") - - # Include LEGO1 headers in ISLE - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1") - # Use internal DirectX 5 if required - if (ISLE_USE_DX5) - target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/inc") - target_link_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/dx5/lib") - endif() + target_link_libraries(isle PRIVATE $<$:DirectX5::DirectX5>) if (ISLE_USE_SMARTHEAP) target_link_libraries(isle PRIVATE SmartHeap::SmartHeap) @@ -288,13 +434,45 @@ if (ISLE_BUILD_APP) endif() if (MSVC) + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "15") + foreach(tgt IN LISTS lego1_targets) + target_compile_definitions(${tgt} PRIVATE _CRT_SECURE_NO_WARNINGS) + endforeach() + if (TARGET isle) + 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") + foreach(tgt IN LISTS lego1_targets) + target_compile_options(${tgt} PRIVATE "-Zc:__cplusplus") + endforeach() + if (TARGET isle) + target_compile_options(isle PRIVATE "-Zc:__cplusplus") + endif() + 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. if (ISLE_BUILD_APP) - target_compile_options(isle PRIVATE "/ML$<$:d>") + target_compile_options(isle PRIVATE "/MT$<$:d>") + target_link_options(isle PRIVATE "/OPT:REF") endif() + target_compile_options(lego1 PRIVATE "/MT$<$:d>") + foreach(tgt IN LISTS lego1_targets) + target_compile_options(${tgt} PRIVATE "/MT$<$:d>") + endforeach() set(CMAKE_CXX_FLAGS "/W3 /GX /D \"WIN32\" /D \"_WINDOWS\"") set(CMAKE_CXX_FLAGS_DEBUG "/Gm /Zi /Od /D \"_DEBUG\"") @@ -308,9 +486,50 @@ if (MSVC) set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "/incremental:no /debug") set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "/incremental:no") + set(CMAKE_STATIC_LINKER_FLAGS "/machine:I386") + set(CMAKE_SHARED_LINKER_FLAGS "/machine:I386") set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "/incremental:yes /debug") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "/incremental:no") set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "/incremental:no /debug") set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "/incremental:no") + + # Older MSVC versions don't support building in parallel. + # Force non-parallel builds of isle and lego1 by putting them in a pool with 1 available job. + if (CMAKE_CXX_COMPILER_ID VERSION_LESS 12) + foreach(tgt IN LISTS lego1_taregets) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_${tgt}=1;msvc_lego1=1") + set_property(TARGET ${tgt} PROPERTY JOB_POOL_COMPILE msvc_${tgt}) + set_property(TARGET ${tgt} PROPERTY JOB_POOL_LINK msvc_${tgt}) + endforeach() + if (TARGET isle) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS "msvc_isle=1") + set_property(TARGET isle PROPERTY JOB_POOL_COMPILE msvc_isle) + set_property(TARGET isle PROPERTY JOB_POOL_LINK msvc_isle) + endif() + endif() +endif() + +find_program(CLANGFORMAT_BIN NAMES clang-format) +if(EXISTS "${CLANGFORMAT_BIN}") + execute_process(COMMAND "${CLANGFORMAT_BIN}" --version + OUTPUT_VARIABLE "CLANGFORMAT_VERSION_OUTPUT" + RESULT_VARIABLE "CLANGFORMAT_RESULT" + ) + if(CLANGFORMAT_RESULT EQUAL 0 AND CLANGFORMAT_VERSION_OUTPUT MATCHES "version ([0-9\\.]+)") + set(CLANGFORMAT_VERSION "${CMAKE_MATCH_1}") + set(CLANGFORMAT_VERSION_REQUIRED "17.0") + message(DEBUG "Found clang-format version ${CLANGFORMAT_VERSION} (needs ${CLANGFORMAT_VERSION_REQUIRED}") + if(CLANGFORMAT_VERSION VERSION_GREATER_EQUAL "${CLANGFORMAT_VERSION_REQUIRED}") + file(GLOB_RECURSE isle_sources + "${PROJECT_SOURCE_DIR}/ISLE/*.cpp" + "${PROJECT_SOURCE_DIR}/ISLE/*.h" + "${PROJECT_SOURCE_DIR}/LEGO1/*.cpp" + "${PROJECT_SOURCE_DIR}/LEGO1/*.h" + ) + string(REPLACE ";" "\n" isle_sources_lines "${isle_sources}") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/isle_sources.txt" "${isle_sources_lines}\n") + add_custom_target(clang-format ${CLANGFORMAT_BIN} -i "--files=${CMAKE_CURRENT_BINARY_DIR}/isle_sources.txt") + endif() + endif() endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0d2c6894..23e25faf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,10 @@ # Contributing -## Learning Decompilation +## Important Note -Generally, decompilation is a fairly advanced skill. If you aren't already familiar with it, it will likely take you months, or even years, to learn the skills necessary to do it (depending on your current proficiency with C/C++ and x86 assembly). If you're still interested, [part 1 of the decompilation vlog](https://www.youtube.com/watch?v=MToTEqoVv3I) covers the overall process and should give you a starting point that you can dive in from. +While we're thrilled that there is so much interest in reverse engineering LEGO Island and are happy to accept contributions from anyone who would like to help progress us further to our goal of a complete codebase, proposed changes to this repository must adhere to a certain degree of engineering quality. While the established contributors here are more than happy to provide code reviews and constructive criticism, it is not their job to teach potential contributors C++ or decompilation fundamentals. As a project that is largely an artifact of the free time of its contributors, the more of that (often scarce) resource that can be dedicated to efficient work, the faster the decompilation will progress. Unfortunately, this results in well-intentioned but poorly constructed contributions actually hurting progress in the long-term. While we are greatly appreciative of the sentiment, if you aren't very confident in your decompilation abilities, it is generally in the project's best interest that you return when you have a better grasp over the process. + +Generally, decompilation is a fairly advanced skill. Depending on your current proficiency with C/C++ and x86 assembly, it could take you months or even years to learn the skills necessary to do it adequately. If you're still interested in learning, [part 1 of the decompilation vlog](https://www.youtube.com/watch?v=MToTEqoVv3I) covers the overall process and should give you a starting point that you can dive in from. Once again, please make yourself familiar with this process before attempting to contribute code to this project. ## Ghidra Server @@ -15,7 +17,7 @@ To access the Ghidra repository, use the following details: ## General Guidelines -If you have contributions, feel free to create a pull request! Someone will review and merge it (or provide feedback) as soon as possible. +If you feel fit to contribute, feel free to create a pull request! Someone will review and merge it (or provide feedback) as soon as possible. Please keep your pull requests small and understandable; you may be able to shoot ahead and make a lot of progress in a short amount of time, but this is a collaborative project, so you must allow others to catch up and follow along. Large pull requests become significantly more unwieldy to review, and as such make it exponentially more likely for a mistake or error to go undetected. They also make it harder to merge other pull requests because the more files you modify, the more likely it is for a merge conflict to occur. A general guideline is to keep submissions limited to one class at a time. Sometimes two or more classes may be too interlinked for this to be feasible, so this is not a hard rule, however if your PR is starting to modify more than 10 or so files, it's probably getting too big. diff --git a/ISLE/define.h b/ISLE/define.h index aac9f28d..3f92244b 100644 --- a/ISLE/define.h +++ b/ISLE/define.h @@ -8,9 +8,9 @@ class IsleApp; extern IsleApp* g_isle; extern int g_closed; -// GLOBAL: ISLE 0x4101c4 +// STRING: ISLE 0x4101c4 #define WNDCLASS_NAME "Lego Island MainNoM App" -// GLOBAL: ISLE 0x4101dc +// STRING: ISLE 0x4101dc #define WINDOW_TITLE "LEGO\xAE" extern unsigned char g_mousedown; extern unsigned char g_mousemoved; diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index ab0d2290..c4897a2b 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -8,11 +8,9 @@ #include "legomodelpresenter.h" #include "legoomni.h" #include "legopartpresenter.h" -#include "legoroi.h" #include "legovideomanager.h" #include "legoworldpresenter.h" #include "mxbackgroundaudiomanager.h" -#include "mxdirectdraw.h" #include "mxdsaction.h" #include "mxomnicreateflags.h" #include "mxomnicreateparam.h" @@ -21,6 +19,7 @@ #include "mxtimer.h" #include "mxtransitionmanager.h" #include "res/resource.h" +#include "viewmanager/viewmanager.h" #include @@ -53,7 +52,15 @@ IsleApp::IsleApp() m_frameDelta = 10; m_windowActive = 1; +#ifdef COMPAT_MODE + { + MxRect32 r(0, 0, 639, 479); + MxVideoParamFlags flags; + m_videoParam = MxVideoParam(r, NULL, 1, flags); + } +#else m_videoParam = MxVideoParam(MxRect32(0, 0, 639, 479), NULL, 1, MxVideoParamFlags()); +#endif m_videoParam.Flags().Set16Bit(MxDirectDraw::GetPrimaryBitDepth() == 16); m_windowHandle = NULL; @@ -132,9 +139,18 @@ BOOL IsleApp::SetupLegoOmni() char mediaPath[256]; GetProfileStringA("LEGO Island", "MediaPath", "", mediaPath, sizeof(mediaPath)); +#ifdef COMPAT_MODE + BOOL failure; + { + MxOmniCreateParam param(mediaPath, (struct HWND__*) m_windowHandle, m_videoParam, MxOmniCreateFlags()); + failure = Lego()->Create(param) == FAILURE; + } +#else BOOL failure = Lego()->Create(MxOmniCreateParam(mediaPath, (struct HWND__*) m_windowHandle, m_videoParam, MxOmniCreateFlags()) ) == FAILURE; +#endif + if (!failure) { VariableTable()->SetVariable("ACTOR_01", ""); TickleManager()->SetClientTickleInterval(VideoManager(), 10); @@ -388,7 +404,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) return DefWindowProcA(hWnd, uMsg, wParam, lParam); case WM_DISPLAYCHANGE: if (g_isle && VideoManager() && g_isle->m_fullScreen && VideoManager()->GetDirect3D()) { - if (VideoManager()->GetDirect3D()->GetDeviceModeFinder()) { + if (VideoManager()->GetDirect3D()->GetAssignedDevice()) { int targetDepth = wParam; int targetWidth = LOWORD(lParam); int targetHeight = HIWORD(lParam); @@ -606,8 +622,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) { @@ -754,12 +770,15 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) return; } - if (!Lego()) + if (!Lego()) { return; - if (!TickleManager()) + } + if (!TickleManager()) { return; - if (!Timer()) + } + if (!Timer()) { return; + } MxLong currentTime = Timer()->GetRealTime(); if (currentTime < g_lastFrameTime) { @@ -784,11 +803,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; } @@ -812,8 +831,9 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) this->m_gameStarted = 1; } } - else if (sleepIfNotNextFrame != 0) + else if (sleepIfNotNextFrame != 0) { Sleep(0); + } } // FUNCTION: ISLE 0x402e80 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/ISLE/res/resource.h b/ISLE/res/resource.h index 6148e89f..647c616e 100644 --- a/ISLE/res/resource.h +++ b/ISLE/res/resource.h @@ -1,5 +1,5 @@ -#define ISLE_ARROW 102 -#define ISLE_NO 103 -#define ISLE_BUSY 104 +#define ISLE_ARROW 102 +#define ISLE_NO 103 +#define ISLE_BUSY 104 -#define APP_ICON 105 +#define APP_ICON 105 diff --git a/LEGO1/LegoOmni.def b/LEGO1/LegoOmni.def new file mode 100644 index 00000000..a3bbfe66 --- /dev/null +++ b/LEGO1/LegoOmni.def @@ -0,0 +1,138 @@ +; LegoOmni.def : Declares the module paarameters for the LEGO1.DLL. + +DESCRIPTION "Lego OMNI Windows Dynamic Link Library" + +EXPORTS + +; EXPORTs really required only. + +??0LegoBackgroundColor@@QAE@PBD0@Z +??0LegoGameState@@QAE@XZ +??0LegoWorld@@QAE@XZ +??0MxAtomId@@QAE@PBDW4LookupMode@@@Z +??0MxBitmap@@QAE@XZ +??0MxCore@@QAE@XZ +??0MxCriticalSection@@QAE@XZ +??0MxDSAction@@QAE@XZ +??0MxDSFile@@QAE@PBDK@Z +??0MxOmniCreateFlags@@QAE@XZ +??0MxOmniCreateParam@@QAE@PBDPAUHWND__@@AAVMxVideoParam@@VMxOmniCreateFlags@@@Z +??0MxString@@QAE@ABV0@@Z +??0MxVideoParam@@QAE@AAV0@@Z +??0MxVideoParam@@QAE@AAVMxRect32@@PAVMxPalette@@KAAVMxVideoParamFlags@@@Z +??0MxVideoParam@@QAE@XZ +??0MxVideoParamFlags@@QAE@XZ +??1LegoEntity@@UAE@XZ +??1LegoGameState@@QAE@XZ +??1LegoWorld@@UAE@XZ +??1MXIOINFO@@QAE@XZ +??1MxAtomId@@QAE@XZ +??1MxBitmap@@UAE@XZ +??1MxCore@@UAE@XZ +??1MxCriticalSection@@QAE@XZ +??1MxDSAction@@UAE@XZ +??1MxDSFile@@UAE@XZ +??1MxPresenter@@UAE@XZ +??1MxString@@UAE@XZ +??1MxVideoParam@@QAE@XZ +??4MxAtomId@@QAEAAV0@ABV0@@Z +??4MxString@@QAEABV0@PBD@Z +??4MxVideoParam@@QAEAAV0@ABV0@@Z +??8MxPalette@@QAEEAAV0@@Z +?BackgroundAudioManager@@YAPAVMxBackgroundAudioManager@@XZ +?Close@MxDSFile@@UAEJXZ +?Close@MxStreamer@@QAEJPBD@Z +?CreateBackgroundAudio@LegoOmni@@QAEXXZ +?CreateInstance@LegoOmni@@SAXXZ +?CreatePalette@MxBitmap@@UAEPAVMxPalette@@XZ +?CreateStreamObject@@YAPAVMxDSObject@@PAVMxDSFile@@F@Z +?DestroyInstance@MxOmni@@SAXXZ +?Detach@MxPalette@@QAEXXZ +?DisableRMDevice@LegoVideoManager@@QAEHXZ +?DoneTickle@MxPresenter@@MAEXXZ +?Enable@MxBackgroundAudioManager@@QAEXE@Z +?Enable@MxPresenter@@UAEXE@Z +?EnableFullScreenMovie@LegoVideoManager@@QAEXEE@Z +?EnableRMDevice@LegoVideoManager@@QAEHXZ +?EndAction@MxPresenter@@UAEXXZ +?EventManager@@YAPAVMxEventManager@@XZ +?FlipToGDISurface@MxDirectDraw@@QAEHXZ +?GameState@@YAPAVLegoGameState@@XZ +?GetBufferSize@MxDSFile@@UAEKXZ +?GetCD@MxOmni@@SAPBDXZ +?GetCurrPathInfo@LegoOmni@@SAHPAPAVLegoPathBoundary@@AAH@Z +?GetDefaults@LegoNavController@@SAXPAHPAM11111111PAE@Z +?GetHD@MxOmni@@SAPBDXZ +?GetInstance@LegoOmni@@SAPAV1@XZ +?GetInstance@MxOmni@@SAPAV1@XZ +?GetInstance@MxScheduler@@SAPAV1@XZ +?GetNoCD_SourceName@@YAPBDXZ +?GetPartsThreshold@RealtimeView@@SAMXZ +?GetPrimaryBitDepth@MxDirectDraw@@SAHXZ +?GetRealTime@MxTimer@@QAEJXZ +?GetStreamBuffersNum@MxDSFile@@UAEKXZ +?GetUserMaxLOD@RealtimeView@@SAMXZ +?GetVariable@MxVariableTable@@QAEPBDPBD@Z +?Init@MxPresenter@@IAEXXZ +?InputManager@@YAPAVLegoInputManager@@XZ +?InvalidateRect@MxVideoManager@@QAEXAAVMxRect32@@@Z +?IsSound3D@MxOmni@@SAEXZ +?Lego@@YAPAVLegoOmni@@XZ +?Load@LegoGameState@@QAEJK@Z +?MSoundManager@@YAPAVMxSoundManager@@XZ +?MakeSourceName@@YAXPADPBD@Z +?MoveCursor@LegoVideoManager@@QAEXHH@Z +?MusicManager@@YAPAVMxMusicManager@@XZ +?NotificationManager@@YAPAVMxNotificationManager@@XZ +?Notify@MxCore@@UAEJAAVMxParam@@@Z +?Open@MxDSFile@@UAEJK@Z +?Open@MxStreamer@@QAEPAVMxStreamController@@PBDG@Z +?ParseExtra@MxPresenter@@MAEXXZ +?Pause@MxDirectDraw@@QAEHH@Z +?PickEntity@@YAPAVLegoEntity@@JJ@Z +?PickROI@@YAPAVLegoROI@@JJ@Z +?QueueEvent@LegoInputManager@@QAEXW4NotificationId@@EJJE@Z +?Read@MxBitmap@@UAEJPBD@Z +?Read@MxDSFile@@UAEJPAEK@Z +?RealizePalette@MxVideoManager@@UAEJPAVMxPalette@@@Z +?Register@LegoInputManager@@QAEXPAVMxCore@@@Z +?RemoveAll@ViewManager@@QAEXPAVViewROI@@@Z +?RemoveWorld@LegoOmni@@QAEXABVMxAtomId@@J@Z +?Save@LegoGameState@@QAEJK@Z +?Seek@MxDSFile@@UAEJJH@Z +?SerializePlayersInfo@LegoGameState@@QAEXF@Z +?SerializeScoreHistory@LegoGameState@@QAEXF@Z +?SetCD@MxOmni@@SAXPBD@Z +?SetDefaults@LegoNavController@@SAXHMMMMMMMMME@Z +?SetDeviceName@MxVideoParam@@QAEXPAD@Z +?SetDisplayBB@LegoROI@@QAEXH@Z +?SetDoMutex@MxCriticalSection@@SAXXZ +?SetHD@MxOmni@@SAXPBD@Z +?SetObjectName@MxDSObject@@QAEXPBD@Z +?SetOmniUserMessage@@YAXP6AXPBDH@Z@Z +?SetPartsThreshold@RealtimeView@@SAXM@Z +?SetSavePath@LegoGameState@@QAEXPAD@Z +?SetSound3D@MxOmni@@SAXE@Z +?SetUserMaxLOD@RealtimeView@@SAXM@Z +?SetVariable@MxVariableTable@@QAEXPAVMxVariable@@@Z +?SetVariable@MxVariableTable@@QAEXPBD0@Z +?SetWaitIndicator@MxTransitionManager@@QAEXPAVMxVideoPresenter@@@Z +?SoundManager@@YAPAVLegoSoundManager@@XZ +?Start@@YAJPAVMxDSAction@@@Z +?StartAction@MxPresenter@@UAEJPAVMxStreamController@@PAVMxDSAction@@@Z +?StartMultiTasking@MxScheduler@@QAEXK@Z +?Streamer@@YAPAVMxStreamer@@XZ +?Tickle@MxPresenter@@UAEJXZ +?TickleManager@@YAPAVMxTickleManager@@XZ +?Timer@@YAPAVMxTimer@@XZ +?TransitionManager@@YAPAVMxTransitionManager@@XZ +?UnRegister@LegoInputManager@@QAEXPAVMxCore@@@Z +?VariableTable@@YAPAVMxVariableTable@@XZ +?VideoManager@@YAPAVLegoVideoManager@@XZ +?configureLegoAnimationManager@LegoAnimationManager@@SAXH@Z +?configureLegoBuildingManager@LegoBuildingManager@@SAXH@Z +?configureLegoModelPresenter@LegoModelPresenter@@SAXH@Z +?configureLegoPartPresenter@LegoPartPresenter@@SAXHH@Z +?configureLegoROI@LegoROI@@SAXH@Z +?configureLegoWorldPresenter@LegoWorldPresenter@@SAXH@Z +_DllMain@12 diff --git a/LEGO1/LegoOmni.mingw.def b/LEGO1/LegoOmni.mingw.def new file mode 100644 index 00000000..e2c4ce5f --- /dev/null +++ b/LEGO1/LegoOmni.mingw.def @@ -0,0 +1,164 @@ +; LegoOmni.def : Declares the module paarameters for the LEGO1.DLL. + +; DESCRIPTION " Lego OMNI Windows Dynamic Link Library" + +EXPORTS + +; EXPORTs really required only. + +_ZN13LegoGameState11SetSavePathEPc +_ZN13LegoGameState20SerializePlayersInfoEs +_ZN13LegoGameState21SerializeScoreHistoryEs +_ZN13LegoGameState4SaveEj +_ZN13LegoGameStateC1Ev +_ZN13LegoGameStateC2Ev +_ZN13LegoGameStateD1Ev +_ZN13LegoGameStateD2Ev +_ZN9LegoWorldC1Ev +_ZN9LegoWorldC2Ev +_ZN9LegoWorldD0Ev +_ZN9LegoWorldD1Ev +_ZN9LegoWorldD2Ev +DllMain@12 +_Z10PickEntityii +_Z12EventManagerv +_Z12InputManagerv +_Z12MusicManagerv +_Z12SoundManagerv +_Z12VideoManagerv +_Z13MSoundManagerv +_Z13TickleManagerv +_Z13VariableTablev +_Z14MakeSourceNamePcPKc +_Z17TransitionManagerv +_Z18CreateStreamObjectP8MxDSFiles +_Z18GetNoCD_SourceNamev +_Z18SetOmniUserMessagePFvPKciE +_Z19NotificationManagerv +_Z22BackgroundAudioManagerv +_Z4Legov +_Z5StartP10MxDSAction +_Z5Timerv +_Z7PickROIii +_Z8Streamerv +_Z9GameStatev +_ZN10MxDSActionC1Ev +_ZN10MxDSActionC2Ev +_ZN10MxDSActionD0Ev +_ZN10MxDSActionD1Ev +_ZN10MxDSActionD2Ev +_ZN10MxDSObject13SetObjectNameEPKc +_ZN10MxStreamer4OpenEPKct +_ZN10MxStreamer5CloseEPKc +_ZN11MxPresenter10DoneTickleEv +_ZN11MxPresenter10ParseExtraEv +_ZN11MxPresenter11StartActionEP18MxStreamControllerP10MxDSAction +_ZN11MxPresenter4InitEv +_ZN11MxPresenter6EnableEh +_ZN11MxPresenter6TickleEv +_ZN11MxPresenter9EndActionEv +_ZN11MxScheduler11GetInstanceEv +_ZN11MxScheduler17StartMultiTaskingEj +_ZN11ViewManager9RemoveAllEP7ViewROI +_ZN12MxDirectDraw16FlipToGDISurfaceEv +_ZN12MxDirectDraw18GetPrimaryBitDepthEv +_ZN12MxDirectDraw5PauseEi +_ZN12MxVideoParam13SetDeviceNameEPc +_ZN12MxVideoParamC1ERS_ +_ZN12MxVideoParamC1Ev +_ZN12MxVideoParamC2ERS_ +_ZN12MxVideoParamC2Ev +_ZN12MxVideoParamD1Ev +_ZN12MxVideoParamD2Ev +_ZN12MxVideoParamaSERKS_ +_ZN12RealtimeView13GetUserMaxLODEv +_ZN12RealtimeView13SetUserMaxLODEf +_ZN12RealtimeView17GetPartsThresholdEv +_ZN12RealtimeView17SetPartsThresholdEf +_ZN14MxVideoManager14InvalidateRectER8MxRect32 +_ZN14MxVideoManager14RealizePaletteEP9MxPalette +_ZN15MxVariableTable11GetVariableEPKc +_ZN15MxVariableTable11SetVariableEP10MxVariable +_ZN15MxVariableTable11SetVariableEPKcS1_ = _ZN15MxVariableTable11SetVariableEPKcS1_ +;_ZN16LegoInputManager10QueueEventE14NotificationIdhiih +_ZN16LegoInputManager10QueueEventE14NotificationIdhiih +_ZN16LegoInputManager10UnRegisterEP6MxCore +_ZN16LegoInputManager8RegisterEP6MxCore +_ZN16LegoVideoManager10MoveCursorEii +_ZN16LegoVideoManager14EnableRMDeviceEv +_ZN16LegoVideoManager15DisableRMDeviceEv +_ZN16LegoVideoManager21EnableFullScreenMovieEhh +_ZN17LegoNavController11GetDefaultsEPiPfS1_S1_S1_S1_S1_S1_S1_S1_Ph +_ZN17LegoNavController11SetDefaultsEifffffffffh +_ZN17LegoPartPresenter26configureLegoPartPresenterEii +_ZN17MxCriticalSection10SetDoMutexEv +_ZN17MxCriticalSectionC1Ev +_ZN17MxCriticalSectionC2Ev +_ZN17MxCriticalSectionD1Ev +_ZN17MxCriticalSectionD2Ev +_ZN17MxOmniCreateFlagsC1Ev +_ZN17MxOmniCreateFlagsC2Ev +_ZN17MxOmniCreateParamC1EPKcP6HWND__R12MxVideoParam17MxOmniCreateFlags +_ZN17MxVideoParamFlagsC1Ev +_ZN17MxVideoParamFlagsC2Ev +_ZN18LegoModelPresenter27configureLegoModelPresenterEi +_ZN18LegoWorldPresenter27configureLegoWorldPresenterEi +_ZN19LegoBuildingManager28configureLegoBuildingManagerEi +_ZN19MxTransitionManager16SetWaitIndicatorEP16MxVideoPresenter +_ZN20LegoAnimationManager29configureLegoAnimationManagerEi +_ZN24MxBackgroundAudioManager6EnableEh +_ZN6MxCore6NotifyER7MxParam +_ZN6MxCoreC1Ev +_ZN6MxCoreC2Ev +_ZN6MxCoreD0Ev +_ZN6MxCoreD1Ev +_ZN6MxCoreD2Ev +_ZN6MxOmni10SetSound3DEh +_ZN6MxOmni11GetInstanceEv +_ZN6MxOmni15DestroyInstanceEv +_ZN6MxOmni5GetCDEv +_ZN6MxOmni5GetHDEv +_ZN6MxOmni5SetCDEPKc +_ZN6MxOmni5SetHDEPKc +_ZN6MxOmni9IsSound3DEv +_ZN7LegoROI12SetDisplayBBEi +_ZN7LegoROI16configureLegoROIEi +_ZN7MxTimer11GetRealTimeEv +_ZN8LegoOmni11GetInstanceEv +_ZN8LegoOmni11RemoveWorldERK8MxAtomIdi +_ZN8LegoOmni14CreateInstanceEv +_ZN8LegoOmni15GetCurrPathInfoEPP16LegoPathBoundaryRi +_ZN8LegoOmni21CreateBackgroundAudioEv +_ZN8MXIOINFOD1Ev +_ZN8MXIOINFOD2Ev +_ZN8MxAtomIdC1EPKc10LookupMode +_ZN8MxAtomIdC2EPKc10LookupMode +_ZN8MxAtomIdD1Ev +_ZN8MxAtomIdD2Ev +_ZN8MxAtomIdaSERKS_ +_ZN8MxBitmap13CreatePaletteEv +_ZN8MxBitmap4ReadEPKc +_ZN8MxBitmapC1Ev +_ZN8MxBitmapC2Ev +_ZN8MxBitmapD0Ev +_ZN8MxBitmapD1Ev +_ZN8MxBitmapD2Ev +_ZN8MxDSFile13GetBufferSizeEv +_ZN8MxDSFile19GetStreamBuffersNumEv +_ZN8MxDSFile4OpenEj +_ZN8MxDSFile4ReadEPhj +_ZN8MxDSFile4SeekEii +_ZN8MxDSFile5CloseEv +_ZN8MxDSFileC1EPKcj +_ZN8MxDSFileC2EPKcj +_ZN8MxDSFileD0Ev +_ZN8MxDSFileD1Ev +_ZN8MxDSFileD2Ev +_ZN8MxStringC1ERKS_ +_ZN8MxStringC2ERKS_ +_ZN8MxStringD0Ev +_ZN8MxStringD1Ev +_ZN8MxStringD2Ev +_ZN8MxStringaSEPKc +_ZN9MxPalette6DetachEv +_ZN9MxPaletteeqERS_ diff --git a/LEGO1/act1state.cpp b/LEGO1/act1state.cpp deleted file mode 100644 index c013b502..00000000 --- a/LEGO1/act1state.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "act1state.h" - -// STUB: LEGO1 0x100334b0 -Act1State::Act1State() -{ - // TODO -} diff --git a/LEGO1/act1state.h b/LEGO1/act1state.h deleted file mode 100644 index e2e8d3e1..00000000 --- a/LEGO1/act1state.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef ACT1STATE_H -#define ACT1STATE_H - -#include "legostate.h" - -// VTABLE: LEGO1 0x100d7028 -// SIZE 0x26c -class Act1State : public LegoState { -public: - Act1State(); - - // FUNCTION: LEGO1 0x100338a0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0154 - return "Act1State"; - }; - - // FUNCTION: LEGO1 0x100338b0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Act1State::ClassName()) || LegoState::IsA(p_name); - }; - - inline void SetUnknown18(MxU32 p_unk0x18) { m_unk0x18 = p_unk0x18; } - inline MxU32 GetUnknown18() { return m_unk0x18; } - -protected: - undefined m_unk0x8[0x10]; // 0x8 - MxU32 m_unk0x18; // 0x18 -}; - -#endif // ACT1STATE_H diff --git a/LEGO1/act2brick.h b/LEGO1/act2brick.h deleted file mode 100644 index de4f29b1..00000000 --- a/LEGO1/act2brick.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ACT2BRICK_H -#define ACT2BRICK_H - -#include "legopathactor.h" - -// VTABLE: LEGO1 0x100d9b60 -// SIZE 0x194 -class Act2Brick : public LegoPathActor { -public: - Act2Brick(); - virtual ~Act2Brick() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x08 - - // FUNCTION: LEGO1 0x1007a360 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0438 - return "Act2Brick"; - } - - // FUNCTION: LEGO1 0x1007a370 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Act2Brick::ClassName()) || LegoEntity::IsA(p_name); - } -}; - -#endif // ACT2BRICK_H diff --git a/LEGO1/act3.cpp b/LEGO1/act3.cpp deleted file mode 100644 index 149e19a7..00000000 --- a/LEGO1/act3.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "act3.h" - -DECOMP_SIZE_ASSERT(Act3, 0x4274) - -// STUB: LEGO1 0x10072270 -Act3::Act3() -{ - // TODO -} - -// STUB: LEGO1 0x100726a0 -Act3::~Act3() -{ - // TODO -} diff --git a/LEGO1/act3.h b/LEGO1/act3.h deleted file mode 100644 index cc4a2c3f..00000000 --- a/LEGO1/act3.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ACT3_H -#define ACT3_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d9628 -// SIZE 0x4274 -class Act3 : public LegoWorld { -public: - Act3(); - - virtual ~Act3() override; // vtable+00 - - // FUNCTION: LEGO1 0x10072510 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f013c - return "Act3"; - } - - // FUNCTION: LEGO1 0x10072520 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Act3::ClassName()) || LegoWorld::IsA(p_name); - } - - inline void SetUnkown420c(MxEntity* p_entity) { m_unk0x420c = p_entity; } - inline void SetUnkown4270(MxU32 p_unk0x4270) { m_unk0x4270 = p_unk0x4270; } - -protected: - undefined m_unk0xf8[0x4114]; // 0xf8 - MxEntity* m_unk0x420c; // 0x420c - undefined m_unk0x4210[0x60]; // 0x4210 - MxU32 m_unk0x4270; // 0x4270 -}; - -#endif // ACT3_H diff --git a/LEGO1/act3shark.cpp b/LEGO1/act3shark.cpp deleted file mode 100644 index 95e5a0e0..00000000 --- a/LEGO1/act3shark.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "act3shark.h" diff --git a/LEGO1/act3shark.h b/LEGO1/act3shark.h deleted file mode 100644 index 63a4e7a6..00000000 --- a/LEGO1/act3shark.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef ACT3SHARK_H -#define ACT3SHARK_H - -#include "legoanimactor.h" - -// VTABLE: LEGO1 0x100d7920 -class Act3Shark : public LegoAnimActor { -public: - // FUNCTION: LEGO1 0x100430c0 - inline virtual const char* ClassName() const override - { - // GLOBAL: LEGO1 0x100f03a0 - return "Act3Shark"; - } -}; - -#endif // ACT3SHARK_H diff --git a/LEGO1/ambulance.cpp b/LEGO1/ambulance.cpp deleted file mode 100644 index 1d9ca918..00000000 --- a/LEGO1/ambulance.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "ambulance.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(Ambulance, 0x184); - -// FUNCTION: LEGO1 0x10035ee0 -Ambulance::Ambulance() -{ - this->m_unk0x168 = 0; - this->m_unk0x16a = -1; - this->m_unk0x164 = 0; - this->m_unk0x16c = 0; - this->m_unk0x174 = -1; - this->m_unk0x16e = 0; - this->m_unk0x178 = -1; - this->m_unk0x170 = 0; - this->m_unk0x172 = 0; - this->m_unk0x13c = 40.0; - this->m_unk0x17c = 1.0; -} diff --git a/LEGO1/ambulance.h b/LEGO1/ambulance.h deleted file mode 100644 index eb46a1ed..00000000 --- a/LEGO1/ambulance.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef AMBULANCE_H -#define AMBULANCE_H - -#include "islepathactor.h" - -// VTABLE: LEGO1 0x100d71a8 -// SIZE 0x184 -class Ambulance : public IslePathActor { -public: - Ambulance(); - - // FUNCTION: LEGO1 0x10035fa0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f03c4 - return "Ambulance"; - } - - // FUNCTION: LEGO1 0x10035fb0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Ambulance::ClassName()) || IslePathActor::IsA(p_name); - } - -private: - // TODO: Ambulance fields - undefined m_unk0x160[4]; - MxS32 m_unk0x164; - MxS16 m_unk0x168; - MxS16 m_unk0x16a; - MxS16 m_unk0x16c; - MxS16 m_unk0x16e; - MxS16 m_unk0x170; - MxS16 m_unk0x172; - MxS32 m_unk0x174; - MxS32 m_unk0x178; - MxFloat m_unk0x17c; - undefined m_unk0x180[4]; -}; - -#endif // AMBULANCE_H diff --git a/LEGO1/animstate.h b/LEGO1/animstate.h deleted file mode 100644 index 5e8fa4e5..00000000 --- a/LEGO1/animstate.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ANIMSTATE_H -#define ANIMSTATE_H - -#include "legostate.h" - -// VTABLE: LEGO1 0x100d8d80 -// SIZE 0x1c -class AnimState : public LegoState { -public: - AnimState(); - virtual ~AnimState() override; // vtable+0x0 - - // FUNCTION: LEGO1 0x10065070 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0460 - return "AnimState"; - } - - // FUNCTION: LEGO1 0x10065080 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, AnimState::ClassName()) || LegoState::IsA(p_name); - } - - virtual MxBool SetFlag() override; // vtable+0x18 - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1C - -private: - undefined4 m_unk0x8; - undefined4 m_unk0xc; - void* m_unk0x10; - undefined4 m_unk0x14; - void* m_unk0x18; -}; - -#endif // ANIMSTATE_H diff --git a/LEGO1/beachhouseentity.cpp b/LEGO1/beachhouseentity.cpp deleted file mode 100644 index 66b07f60..00000000 --- a/LEGO1/beachhouseentity.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "beachhouseentity.h" - -// STUB: LEGO1 0x100150a0 -MxLong BeachHouseEntity::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/bike.cpp b/LEGO1/bike.cpp deleted file mode 100644 index 3c27ebc5..00000000 --- a/LEGO1/bike.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "bike.h" - -DECOMP_SIZE_ASSERT(Bike, 0x164); - -// FUNCTION: LEGO1 0x10076670 -Bike::Bike() -{ - this->m_unk0x13c = 20.0; - this->m_unk0x150 = 3.0; - this->m_unk0x148 = 1; -} diff --git a/LEGO1/bike.h b/LEGO1/bike.h deleted file mode 100644 index f3d5c90d..00000000 --- a/LEGO1/bike.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef BIKE_H -#define BIKE_H - -#include "decomp.h" -#include "islepathactor.h" - -// VTABLE: LEGO1 0x100d9808 -// SIZE 0x164 -class Bike : public IslePathActor { -public: - Bike(); - - // FUNCTION: LEGO1 0x100766f0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f03d0 - return "Bike"; - } - - // FUNCTION: LEGO1 0x10076700 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Bike::ClassName()) || IslePathActor::IsA(p_name); - } - -private: - // TODO: Bike fields - undefined m_unk0x160[4]; -}; - -#endif // BIKE_H diff --git a/LEGO1/bumpbouy.cpp b/LEGO1/bumpbouy.cpp deleted file mode 100644 index c4c8069d..00000000 --- a/LEGO1/bumpbouy.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "bumpbouy.h" diff --git a/LEGO1/bumpbouy.h b/LEGO1/bumpbouy.h deleted file mode 100644 index 8399c7ef..00000000 --- a/LEGO1/bumpbouy.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef BUMPBOUY_H -#define BUMPBOUY_H - -#include "legoanimactor.h" -#include "mxtypes.h" - -// VTABLE: LEGO1 0x100d6790 -class BumpBouy : public LegoAnimActor { -public: - // FUNCTION: LEGO1 0x100274e0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0394 - return "BumpBouy"; - } - - // FUNCTION: LEGO1 0x10027500 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, BumpBouy::ClassName()) || LegoAnimActor::IsA(p_name); - } -}; - -#endif // BUMPBOUY_H diff --git a/LEGO1/carrace.cpp b/LEGO1/carrace.cpp deleted file mode 100644 index 6da96168..00000000 --- a/LEGO1/carrace.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "carrace.h" - -// STUB: LEGO1 0x10016a90 -CarRace::CarRace() -{ - // TODO -} diff --git a/LEGO1/carrace.h b/LEGO1/carrace.h deleted file mode 100644 index b876fd4d..00000000 --- a/LEGO1/carrace.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef CARRACE_H -#define CARRACE_H - -#include "legorace.h" - -// VTABLE: LEGO1 0x100d5e50 -// SIZE 0x154 -class CarRace : public LegoRace { -public: - CarRace(); - - // FUNCTION: LEGO1 0x10016b20 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0528 - return "CarRace"; - } - - // FUNCTION: LEGO1 0x10016b30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, CarRace::ClassName()) || LegoRace::IsA(p_name); - } -}; - -#endif // CARRACE_H diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 31f1e521..1e403a50 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -1,7 +1,7 @@ #include "define.h" // GLOBAL: LEGO1 0x1010141c -MxU32 g_mxcoreCount[101] = {0, -6643, -5643, -5058, -4643, -4321, -4058, -3836, -3643, -3473, -3321, -3184, -3058, +MxS32 g_mxcoreCount[101] = {0, -6643, -5643, -5058, -4643, -4321, -4058, -3836, -3643, -3473, -3321, -3184, -3058, -2943, -2836, -2736, -2643, -2556, -2473, -2395, -2321, -2251, -2184, -2120, -2058, -2000, -1943, -1888, -1836, -1785, -1736, -1689, -1643, -1599, -1556, -1514, -1473, -1434, -1395, -1358, -1321, -1286, -1251, -1217, -1184, -1152, -1120, -1089, -1058, -1029, -1000, -971, @@ -10,17 +10,26 @@ MxU32 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 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/define.h b/LEGO1/define.h index 82e93375..d45d02c3 100644 --- a/LEGO1/define.h +++ b/LEGO1/define.h @@ -3,10 +3,11 @@ #include "mxtypes.h" -extern MxU32 g_mxcoreCount[101]; +extern MxS32 g_mxcoreCount[101]; extern const char* g_parseExtraTokens; extern const char* g_strWORLD; extern const char* g_strSOUND; +extern const char* g_strOBJECT; extern const char* g_strACTION; extern const char* g_strVISIBILITY; diff --git a/LEGO1/dllmain.cpp b/LEGO1/dllmain.cpp deleted file mode 100644 index f760aeae..00000000 --- a/LEGO1/dllmain.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -// FUNCTION: LEGO1 0x10091ee0 -__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - return TRUE; -} diff --git a/LEGO1/doors.h b/LEGO1/doors.h deleted file mode 100644 index a2c142a4..00000000 --- a/LEGO1/doors.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef DOORS_H -#define DOORS_H - -#include "legopathactor.h" - -// VTABLE: LEGO1 0x100d4788 -// SIZE 0x1f8 -class Doors : public LegoPathActor { -public: - // FUNCTION: LEGO1 0x1000e430 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f03e8 - return "Doors"; - } - - // FUNCTION: LEGO1 0x1000e440 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Doors::ClassName()) || LegoPathActor::IsA(p_name); - } -}; - -#endif // DOORS_H diff --git a/LEGO1/dunebuggy.cpp b/LEGO1/dunebuggy.cpp deleted file mode 100644 index a32b612d..00000000 --- a/LEGO1/dunebuggy.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "dunebuggy.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(DuneBuggy, 0x16c); - -// FUNCTION: LEGO1 0x10067bb0 -DuneBuggy::DuneBuggy() -{ - this->m_unk0x13c = 25.0; - this->m_unk0x164 = 1.0; -} diff --git a/LEGO1/dunebuggy.h b/LEGO1/dunebuggy.h deleted file mode 100644 index 1accaa05..00000000 --- a/LEGO1/dunebuggy.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DUNEBUGGY_H -#define DUNEBUGGY_H - -#include "decomp.h" -#include "islepathactor.h" - -// VTABLE: LEGO1 0x100d8f98 -// SIZE 0x16c -class DuneBuggy : public IslePathActor { -public: - DuneBuggy(); - - // FUNCTION: LEGO1 0x10067c30 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0410 - return "DuneBuggy"; - } - - // FUNCTION: LEGO1 0x10067c40 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, DuneBuggy::ClassName()) || IslePathActor::IsA(p_name); - } - -private: - // TODO: Double check DuneBuggy field types - undefined4 m_unk0x160; - MxFloat m_unk0x164; - undefined4 m_unk0x168; -}; - -#endif // DUNEBUGGY_H diff --git a/LEGO1/elevatorbottom.cpp b/LEGO1/elevatorbottom.cpp deleted file mode 100644 index 247defb0..00000000 --- a/LEGO1/elevatorbottom.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "elevatorbottom.h" - -// STUB: LEGO1 0x10017e90 -ElevatorBottom::ElevatorBottom() -{ - // TODO -} - -// STUB: LEGO1 0x10018060 -ElevatorBottom::~ElevatorBottom() -{ - // TODO -} - -// STUB: LEGO1 0x10018150 -MxLong ElevatorBottom::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/elevatorbottom.h b/LEGO1/elevatorbottom.h deleted file mode 100644 index 2a0f2570..00000000 --- a/LEGO1/elevatorbottom.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef ELEVATORBOTTOM_H -#define ELEVATORBOTTOM_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d5f20 -class ElevatorBottom : public LegoWorld { -public: - ElevatorBottom(); - virtual ~ElevatorBottom() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x10017f20 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f04ac - return "ElevatorBottom"; - } - - // FUNCTION: LEGO1 0x10017f30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ElevatorBottom::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // ELEVATORBOTTOM_H diff --git a/LEGO1/extra.h b/LEGO1/extra.h deleted file mode 100644 index e8aed106..00000000 --- a/LEGO1/extra.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef EXTRA_H -#define EXTRA_H - -// 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, -}; - -#endif // EXTRA_H diff --git a/LEGO1/gasstation.cpp b/LEGO1/gasstation.cpp deleted file mode 100644 index 24325511..00000000 --- a/LEGO1/gasstation.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "gasstation.h" - -// STUB: LEGO1 0x100046a0 -GasStation::GasStation() -{ - // TODO -} - -// STUB: LEGO1 0x100048c0 -GasStation::~GasStation() -{ - // TODO -} - -// STUB: LEGO1 0x10004a60 -MxLong GasStation::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} - -// STUB: LEGO1 0x10005c90 -MxResult GasStation::Tickle() -{ - // TODO - - return 0; -} diff --git a/LEGO1/gasstation.h b/LEGO1/gasstation.h deleted file mode 100644 index d6761980..00000000 --- a/LEGO1/gasstation.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef GASSTATION_H -#define GASSTATION_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d4650 -// SIZE 0x128 -// Radio variable at 0x46, in constructor -class GasStation : public LegoWorld { -public: - GasStation(); - virtual ~GasStation() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x10004780 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0168 - return "GasStation"; - } - - // FUNCTION: LEGO1 0x10004790 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, GasStation::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // GASSTATION_H diff --git a/LEGO1/gasstationstate.h b/LEGO1/gasstationstate.h deleted file mode 100644 index 2fb7e512..00000000 --- a/LEGO1/gasstationstate.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef GASSTATIONSTATE_H -#define GASSTATIONSTATE_H - -#include "legostate.h" - -// VTABLE: LEGO1 0x100d46e0 -// SIZE 0x24 -class GasStationState : public LegoState { -public: - GasStationState(); - - // FUNCTION: LEGO1 0x100061d0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0174 - return "GasStationState"; - } - - // FUNCTION: LEGO1 0x100061e0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, GasStationState::ClassName()) || LegoState::IsA(p_name); - } - -private: - undefined4 m_unk0x08[3]; - undefined4 m_unk0x14; - undefined2 m_unk0x18; - undefined2 m_unk0x1a; - undefined2 m_unk0x1c; - undefined2 m_unk0x1e; - undefined2 m_unk0x20; -}; - -#endif // GASSTATIONSTATE_H diff --git a/LEGO1/gifmanager.cpp b/LEGO1/gifmanager.cpp deleted file mode 100644 index 0fc25b96..00000000 --- a/LEGO1/gifmanager.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "gifmanager.h" - -DECOMP_SIZE_ASSERT(GifData, 0x14); -DECOMP_SIZE_ASSERT(GifMapEntry, 0x14); -DECOMP_SIZE_ASSERT(GifMap, 0x08); -DECOMP_SIZE_ASSERT(GifManagerBase, 0x14); -DECOMP_SIZE_ASSERT(GifManager, 0x30); - -GifMapEntry* g_unk0x100f0100; - -// FUNCTION: LEGO1 0x10001cc0 -GifMapEntry* GifMap::FindNode(const char*& p_string) -{ - GifMapEntry* ret = m_unk0x4; - GifMapEntry* current = ret->m_parent; - while (current != g_unk0x100f0100) { - if (strcmp(current->m_key, p_string) <= 0) { - ret = current; - current = current->m_right; - } - else - current = current->m_left; - } - return ret; -} diff --git a/LEGO1/gifmanager.h b/LEGO1/gifmanager.h deleted file mode 100644 index 3226b4b0..00000000 --- a/LEGO1/gifmanager.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef GIFMANAGER_H -#define GIFMANAGER_H - -#include "decomp.h" -#include "mxtypes.h" - -#include -#include - -struct GifData { -public: - const char* m_name; - LPDIRECTDRAWSURFACE m_surface; - LPDIRECTDRAWPALETTE m_palette; - LPDIRECT3DRMTEXTURE2 m_texture; - MxU8* m_data; -}; - -struct GifMapEntry { -public: - GifMapEntry* m_right; - GifMapEntry* m_parent; - GifMapEntry* m_left; - const char* m_key; - GifData* m_value; -}; - -class GifMap { -public: - GifMapEntry* FindNode(const char*& p_string); - - inline GifData* Get(const char* p_string) - { - GifData* ret = NULL; - GifMapEntry* entry = FindNode(p_string); - if (((m_unk0x4 == entry || strcmp(p_string, entry->m_key) > 0) ? m_unk0x4 : entry) != entry) - ret = entry->m_value; - return ret; - } - - undefined4 m_unk0x0; - GifMapEntry* m_unk0x4; -}; - -// VTABLE: LEGO1 0x100d86d4 -class GifManagerBase { -public: - // STUB: LEGO1 0x1005a310 - virtual ~GifManagerBase() {} // vtable+00 - - inline GifData* Get(const char* p_name) { return m_unk0x8.Get(p_name); } - -protected: - undefined4 m_unk0x0; - undefined4 m_unk0x4; - GifMap m_unk0x8; -}; - -// VTABLE: LEGO1 0x100d86fc -class GifManager : public GifManagerBase { -public: - // STUB: LEGO1 0x1005a580 - virtual ~GifManager() {} // vtable+00 - -protected: - undefined m_unk0x14[0x1c]; -}; - -#endif // GIFMANAGER_H diff --git a/LEGO1/helicopter.h b/LEGO1/helicopter.h deleted file mode 100644 index cc4f3b35..00000000 --- a/LEGO1/helicopter.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef HELICOPTER_H -#define HELICOPTER_H - -#include "helicopterstate.h" -#include "islepathactor.h" -#include "realtime/matrix.h" - -// SIZE 0x34 -class HelicopterSubclass { -public: - inline HelicopterSubclass() : m_unk0x30(0) {} - MxResult FUN_100040a0(Vector4Impl& p_v, float p_f); - -private: - Vector4Data m_unk0x0; // 0x0 - Vector4Data m_unk0x18; // 0x18 - undefined4 m_unk0x30; // 0x30 -}; - -// VTABLE: LEGO1 0x100d40f8 -// SIZE 0x230 -class Helicopter : public IslePathActor { -public: - Helicopter(); - virtual ~Helicopter() override; // vtable+0x0 - - // FUNCTION: LEGO1 0x10003070 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0130 - return "Helicopter"; - } - - // FUNCTION: LEGO1 0x10003080 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Helicopter::ClassName()) || IslePathActor::IsA(p_name); - } - - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 - void VTable0x70(float p_float) override; // vtable+0x70 - void VTable0x74(Matrix4Impl& p_transform) override; // vtable+0x74 - virtual MxU32 VTable0xcc() override; // vtable+0xcc - virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 - virtual MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 - virtual void VTable0xe4() override; // vtable+0xe4 - - // SYNTHETIC: LEGO1 0x10003210 - // Helicopter::`scalar deleting destructor' - -protected: - Matrix4Data m_unk0x160; // 0x160 - Matrix4Data m_unk0x1a8; // 0x1a8 - float m_unk0x1f0; // 0x1f0 - HelicopterSubclass m_unk0x1f4; // 0x1f4 - HelicopterState* m_state; // 0x228 - MxAtomId m_script; // 0x22c - -private: - void GetState(); -}; - -#endif // HELICOPTER_H diff --git a/LEGO1/helicopterstate.h b/LEGO1/helicopterstate.h deleted file mode 100644 index 1c43b04f..00000000 --- a/LEGO1/helicopterstate.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef HELICOPTERSTATE_H -#define HELICOPTERSTATE_H - -#include "decomp.h" -#include "legostate.h" - -// VTABLE: LEGO1 0x100d5418 -// SIZE 0xc -class HelicopterState : public LegoState { -public: - // FUNCTION: LEGO1 0x1000e0d0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0144 - return "HelicopterState"; - } - - // FUNCTION: LEGO1 0x1000e0e0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, HelicopterState::ClassName()) || LegoState::IsA(p_name); - } - - inline void SetUnknown8(MxU32 p_unk0x8) { m_unk0x8 = p_unk0x8; } - inline MxU32 GetUnkown8() { return m_unk0x8; } - -protected: - MxU32 m_unk0x8; // 0x8 -}; - -#endif // HELICOPTERSTATE_H diff --git a/LEGO1/historybook.cpp b/LEGO1/historybook.cpp deleted file mode 100644 index d00e8acd..00000000 --- a/LEGO1/historybook.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "historybook.h" - -// STUB: LEGO1 0x100822f0 -HistoryBook::HistoryBook() -{ - // TODO -} - -// STUB: LEGO1 0x100824d0 -HistoryBook::~HistoryBook() -{ - // TODO -} - -// STUB: LEGO1 0x10082680 -MxLong HistoryBook::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/historybook.h b/LEGO1/historybook.h deleted file mode 100644 index 18154c79..00000000 --- a/LEGO1/historybook.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef HISTORYBOOK_H -#define HISTORYBOOK_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100da328 -// SIZE 0x3e4 -class HistoryBook : public LegoWorld { -public: - HistoryBook(); - virtual ~HistoryBook() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x10082390 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f04bc - return "HistoryBook"; - } - - // FUNCTION: LEGO1 0x100823a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, HistoryBook::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // HISTORYBOOK_H diff --git a/LEGO1/hospital.cpp b/LEGO1/hospital.cpp deleted file mode 100644 index 3d8ff578..00000000 --- a/LEGO1/hospital.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "hospital.h" - -// STUB: LEGO1 0x100745e0 -Hospital::Hospital() -{ - // TODO -} - -// STUB: LEGO1 0x100747f0 -Hospital::~Hospital() -{ - // TODO -} - -// STUB: LEGO1 0x10074990 -MxLong Hospital::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/hospital.h b/LEGO1/hospital.h deleted file mode 100644 index 014c301d..00000000 --- a/LEGO1/hospital.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef HOSPITAL_H -#define HOSPITAL_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d9730 -// SIZE 0x12c -class Hospital : public LegoWorld { -public: - Hospital(); - virtual ~Hospital() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 - - // FUNCTION: LEGO1 0x100746b0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0490 - return "Hospital"; - } - - // FUNCTION: LEGO1 0x100746c0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Hospital::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // HOSPITAL_H diff --git a/LEGO1/hospitalstate.cpp b/LEGO1/hospitalstate.cpp deleted file mode 100644 index b1727b74..00000000 --- a/LEGO1/hospitalstate.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "hospitalstate.h" - -// STUB: LEGO1 0x10076370 -HospitalState::HospitalState() -{ - // TODO -} diff --git a/LEGO1/hospitalstate.h b/LEGO1/hospitalstate.h deleted file mode 100644 index 795342b0..00000000 --- a/LEGO1/hospitalstate.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef HOSPITALSTATE_H -#define HOSPITALSTATE_H - -#include "legostate.h" - -// VTABLE: LEGO1 0x100d97a0 -// SIZE 0x18 -class HospitalState : public LegoState { -public: - HospitalState(); - - // FUNCTION: LEGO1 0x10076400 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0480 - return "HospitalState"; - } - - // FUNCTION: LEGO1 0x10076410 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, HospitalState::ClassName()) || LegoState::IsA(p_name); - } -}; - -#endif // HOSPITALSTATE_H diff --git a/LEGO1/infocenter.cpp b/LEGO1/infocenter.cpp deleted file mode 100644 index f062f1e9..00000000 --- a/LEGO1/infocenter.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "infocenter.h" - -// STUB: LEGO1 0x1006ea20 -Infocenter::Infocenter() -{ - // TODO -} - -// STUB: LEGO1 0x1006ec90 -Infocenter::~Infocenter() -{ - // TODO -} - -// STUB: LEGO1 0x1006ef10 -MxLong Infocenter::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} - -// STUB: LEGO1 0x10070af0 -MxResult Infocenter::Tickle() -{ - // TODO - - return 0; -} diff --git a/LEGO1/infocenter.h b/LEGO1/infocenter.h deleted file mode 100644 index 3b4e7856..00000000 --- a/LEGO1/infocenter.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef INFOCENTER_H -#define INFOCENTER_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d9338 -// SIZE 0x1d8 -class Infocenter : public LegoWorld { -public: - Infocenter(); - virtual ~Infocenter() override; - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x1006eb40 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f04ec - return "Infocenter"; - } - - // FUNCTION: LEGO1 0x1006eb50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Infocenter::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // INFOCENTER_H diff --git a/LEGO1/infocenterdoor.cpp b/LEGO1/infocenterdoor.cpp deleted file mode 100644 index c6d85394..00000000 --- a/LEGO1/infocenterdoor.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "infocenterdoor.h" - -// STUB: LEGO1 0x10037730 -InfocenterDoor::InfocenterDoor() -{ - // TODO -} - -// STUB: LEGO1 0x100378f0 -InfocenterDoor::~InfocenterDoor() -{ - // TODO -} - -// STUB: LEGO1 0x100379e0 -MxLong InfocenterDoor::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/infocenterdoor.h b/LEGO1/infocenterdoor.h deleted file mode 100644 index 1586dbc8..00000000 --- a/LEGO1/infocenterdoor.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef INFOCENTERDOOR_H -#define INFOCENTERDOOR_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d72d8 -// SIZE 0xfc -class InfocenterDoor : public LegoWorld { -public: - InfocenterDoor(); - virtual ~InfocenterDoor(); // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x100377b0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f049c - return "InfocenterDoor"; - } - - // FUNCTION: LEGO1 0x100377c0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, InfocenterDoor::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // INFOCENTERDOOR_H diff --git a/LEGO1/infocenterstate.cpp b/LEGO1/infocenterstate.cpp deleted file mode 100644 index 47a31fbb..00000000 --- a/LEGO1/infocenterstate.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "infocenterstate.h" - -DECOMP_SIZE_ASSERT(InfocenterState, 0x94); - -// STUB: LEGO1 0x10071600 -InfocenterState::InfocenterState() -{ - // TODO -} - -// STUB: LEGO1 0x10071920 -InfocenterState::~InfocenterState() -{ - // TODO -} diff --git a/LEGO1/infocenterstate.h b/LEGO1/infocenterstate.h deleted file mode 100644 index 322e7bec..00000000 --- a/LEGO1/infocenterstate.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef INFOCENTERSTATE_H -#define INFOCENTERSTATE_H - -#include "decomp.h" -#include "legostate.h" - -// VTABLE: LEGO1 0x100d93a8 -// SIZE 0x94 -class InfocenterState : public LegoState { -public: - InfocenterState(); - virtual ~InfocenterState(); - - // FUNCTION: LEGO1 0x10071840 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f04dc - return "InfocenterState"; - } - - // FUNCTION: LEGO1 0x10071850 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, InfocenterState::ClassName()) || LegoState::IsA(p_name); - } - - inline MxU32 GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } - -private: - // Members should be renamed with their offsets before use - /* - struct UnkStruct - { - undefined4 unk1; - undefined2 unk2; - undefined2 unk3; - undefined2 unk4; - }; - - undefined2 unk1; - undefined2 unk2; - undefined4 unk3; - undefined4 padding1; - void *unk4; - undefined2 unk5; - undefined2 unk6; - undefined2 unk7; - undefined2 padding2; - void *unk8; - undefined2 unk9; - undefined2 unk10; - undefined2 unk11; - undefined2 padding3; - UnkStruct unk12[6]; - undefined4 unk13; - */ - - undefined m_pad[0x70]; - MxU32 m_buffer[7]; // 0x78 -}; - -#endif // INFOCENTERSTATE_H diff --git a/LEGO1/isleactor.cpp b/LEGO1/isleactor.cpp deleted file mode 100644 index a28afc6b..00000000 --- a/LEGO1/isleactor.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "isleactor.h" - -// NOTE: This is copied from base class LegoActor. IsleActor may in fact be larger but we don't know yet. -DECOMP_SIZE_ASSERT(IsleActor, 0x78) diff --git a/LEGO1/isleactor.h b/LEGO1/isleactor.h deleted file mode 100644 index aa205483..00000000 --- a/LEGO1/isleactor.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef ISLEACTOR_H -#define ISLEACTOR_H - -#include "legoactor.h" - -// VTABLE: LEGO1 0x100d5178 -class IsleActor : public LegoActor { -public: - // FUNCTION: LEGO1 0x1000e660 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f07dc - return "IsleActor"; - } - - // FUNCTION: LEGO1 0x1000e670 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, IsleActor::ClassName()) || LegoActor::IsA(p_name); - } -}; - -#endif // ISLEACTOR_H diff --git a/LEGO1/jetski.cpp b/LEGO1/jetski.cpp deleted file mode 100644 index 8bdf3fff..00000000 --- a/LEGO1/jetski.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "jetski.h" - -DECOMP_SIZE_ASSERT(Jetski, 0x164); - -// FUNCTION: LEGO1 0x1007e3b0 -Jetski::Jetski() -{ - this->m_unk0x13c = 25.0; - this->m_unk0x150 = 2.0; - this->m_unk0x148 = 1; -} diff --git a/LEGO1/jetski.h b/LEGO1/jetski.h deleted file mode 100644 index 8c669ca6..00000000 --- a/LEGO1/jetski.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef JETSKI_H -#define JETSKI_H - -#include "decomp.h" -#include "islepathactor.h" - -// VTABLE: LEGO1 0x100d9ec8 -// SIZE 0x164 -class Jetski : public IslePathActor { -public: - Jetski(); - - // FUNCTION: LEGO1 0x1007e430 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f03d8 - return "Jetski"; - } - - // FUNCTION: LEGO1 0x1007e440 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Jetski::ClassName()) || IslePathActor::IsA(p_name); - } - -private: - // TODO: Jetski fields - undefined m_unk0x160[4]; -}; - -#endif // JETSKI_H diff --git a/LEGO1/jukebox.cpp b/LEGO1/jukebox.cpp deleted file mode 100644 index d5ded948..00000000 --- a/LEGO1/jukebox.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "jukebox.h" - -#include "mxnotificationmanager.h" -#include "mxomni.h" - -DECOMP_SIZE_ASSERT(JukeBox, 0x104) - -// FUNCTION: LEGO1 0x1005d660 -JukeBox::JukeBox() -{ - m_unk0x100 = 0; - m_unk0xfc = 0; - NotificationManager()->Register(this); -} diff --git a/LEGO1/jukebox.h b/LEGO1/jukebox.h deleted file mode 100644 index 63b04520..00000000 --- a/LEGO1/jukebox.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef JUKEBOX_H -#define JUKEBOX_H - -#include "decomp.h" -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d8958 -// SIZE 0x104 -class JukeBox : public LegoWorld { -public: - JukeBox(); - - // FUNCTION: LEGO1 0x1005d6f0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f02cc - return "JukeBox"; - } - - // FUNCTION: LEGO1 0x1005d700 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name); - } - -private: - undefined m_unk0xf8[4]; // 0xf8 - undefined4 m_unk0xfc; // 0xfc - undefined2 m_unk0x100; // 0x100 -}; - -#endif // JUKEBOX_H diff --git a/LEGO1/lego/legoomni/include/act1state.h b/LEGO1/lego/legoomni/include/act1state.h new file mode 100644 index 00000000..1ad86c64 --- /dev/null +++ b/LEGO1/lego/legoomni/include/act1state.h @@ -0,0 +1,53 @@ +#ifndef ACT1STATE_H +#define ACT1STATE_H + +#include "legostate.h" + +// VTABLE: LEGO1 0x100d7028 +// SIZE 0x26c +class Act1State : public LegoState { +public: + Act1State(); + + // FUNCTION: LEGO1 0x100338a0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0154 + return "Act1State"; + } + + // FUNCTION: LEGO1 0x100338b0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Act1State::ClassName()) || LegoState::IsA(p_name); + } + + MxBool SetFlag() override; // vtable+0x18 + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + + inline void SetUnknown18(MxU32 p_unk0x18) { m_unk0x18 = p_unk0x18; } + inline MxU32 GetUnknown18() { return m_unk0x18; } + inline MxU32 GetUnknown1c() { return m_unk0x1c; } + inline MxS16 GetUnknown21() { return m_unk0x21; } + + inline void SetUnknown1c(MxU32 p_unk0x1c) { m_unk0x1c = p_unk0x1c; } + inline void SetUnknown21(MxS16 p_unk0x21) { m_unk0x21 = p_unk0x21; } + + void FUN_10034d00(); + + // SYNTHETIC: LEGO1 0x10033960 + // Act1State::`scalar deleting destructor' + +protected: + undefined m_unk0x08[0x10]; // 0x08 + 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/act2brick.h b/LEGO1/lego/legoomni/include/act2brick.h new file mode 100644 index 00000000..32856732 --- /dev/null +++ b/LEGO1/lego/legoomni/include/act2brick.h @@ -0,0 +1,35 @@ +#ifndef ACT2BRICK_H +#define ACT2BRICK_H + +#include "legopathactor.h" + +// VTABLE: LEGO1 0x100d9b60 +// SIZE 0x194 +class Act2Brick : public LegoPathActor { +public: + Act2Brick(); + ~Act2Brick() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1007a360 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0438 + return "Act2Brick"; + } + + // FUNCTION: LEGO1 0x1007a370 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Act2Brick::ClassName()) || LegoEntity::IsA(p_name); + } + + MxS32 VTable0x94() override; // vtable+0x94 + + // SYNTHETIC: LEGO1 0x1007a450 + // Act2Brick::`scalar deleting destructor' +}; + +#endif // ACT2BRICK_H diff --git a/LEGO1/act2policestation.h b/LEGO1/lego/legoomni/include/act2policestation.h similarity index 57% rename from LEGO1/act2policestation.h rename to LEGO1/lego/legoomni/include/act2policestation.h index 2ca1a4e8..02d95e5b 100644 --- a/LEGO1/act2policestation.h +++ b/LEGO1/lego/legoomni/include/act2policestation.h @@ -7,20 +7,23 @@ // SIZE 0x68 class Act2PoliceStation : public LegoEntity { public: - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x1000e200 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03fc + // STRING: LEGO1 0x100f03fc return "Act2PoliceStation"; } // FUNCTION: LEGO1 0x1000e210 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act2PoliceStation::ClassName()) || LegoEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f610 + // Act2PoliceStation::`scalar deleting destructor' }; #endif // ACT2POLICESTATION_H diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h new file mode 100644 index 00000000..46ae4e4f --- /dev/null +++ b/LEGO1/lego/legoomni/include/act3.h @@ -0,0 +1,56 @@ +#ifndef ACT3_H +#define ACT3_H + +#include "legoworld.h" + +// VTABLE: LEGO1 0x100d9628 +// SIZE 0x4274 +class Act3 : public LegoWorld { +public: + Act3(); + + ~Act3() override; // vtable+00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x10072510 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f013c + return "Act3"; + } + + // FUNCTION: LEGO1 0x10072520 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Act3::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + void VTable0x60() override; // vtable+0x60 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + inline void SetUnkown420c(MxEntity* p_entity) { m_unk0x420c = p_entity; } + inline void SetUnkown4270(MxU32 p_unk0x4270) { m_unk0x4270 = p_unk0x4270; } + + // SYNTHETIC: LEGO1 0x10072630 + // Act3::`scalar deleting destructor' + + MxBool FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); + MxBool FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); + void FUN_10073400(); + void FUN_10073430(); + +protected: + undefined m_unk0xf8[0x4114]; // 0xf8 + MxEntity* m_unk0x420c; // 0x420c + undefined m_unk0x4210[0x60]; // 0x4210 + MxU32 m_unk0x4270; // 0x4270 +}; + +#endif // ACT3_H diff --git a/LEGO1/act3actor.h b/LEGO1/lego/legoomni/include/act3actor.h similarity index 68% rename from LEGO1/act3actor.h rename to LEGO1/lego/legoomni/include/act3actor.h index ef756436..3d146cb7 100644 --- a/LEGO1/act3actor.h +++ b/LEGO1/lego/legoomni/include/act3actor.h @@ -1,14 +1,16 @@ #ifndef ACT3ACTOR_H #define ACT3ACTOR_H +#include "mxcore.h" + // FIXME: Uncertain location. There are three vtables which eventually call this // class' ClassName() function, but none of them call it directly. -class Act3Actor { +class Act3Actor : public MxCore { public: // FUNCTION: LEGO1 0x100431b0 - inline virtual const char* ClassName() override + inline const char* ClassName() const override { - // GLOBAL: LEGO1 0x100f03ac + // STRING: LEGO1 0x100f03ac return "Act3Actor"; } }; diff --git a/LEGO1/lego/legoomni/include/act3shark.h b/LEGO1/lego/legoomni/include/act3shark.h new file mode 100644 index 00000000..b0b26a48 --- /dev/null +++ b/LEGO1/lego/legoomni/include/act3shark.h @@ -0,0 +1,31 @@ +#ifndef ACT3SHARK_H +#define ACT3SHARK_H + +#include "legoanimactor.h" + +// VTABLE: LEGO1 0x100d7920 +class Act3Shark : public LegoAnimActor { +public: + // FUNCTION: LEGO1 0x100430c0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f03a0 + return "Act3Shark"; + } + + // FUNCTION: LEGO1 0x1001a130 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Act3Shark::ClassName()) || LegoAnimActor::IsA(p_name); + } + + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + + // SYNTHETIC: LEGO1 0x10043020 + // Act3Shark::`scalar deleting destructor' +}; + +#endif // ACT3SHARK_H diff --git a/LEGO1/act3state.h b/LEGO1/lego/legoomni/include/act3state.h similarity index 61% rename from LEGO1/act3state.h rename to LEGO1/lego/legoomni/include/act3state.h index 5da94fac..d1c83e48 100644 --- a/LEGO1/act3state.h +++ b/LEGO1/lego/legoomni/include/act3state.h @@ -4,25 +4,28 @@ #include "legostate.h" // VTABLE: LEGO1 0x100d4fc8 -// SIZE 0xc +// SIZE 0x0c class Act3State : public LegoState { public: inline Act3State() { m_unk0x08 = 0; } // FUNCTION: LEGO1 0x1000e300 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03f0 + // STRING: LEGO1 0x100f03f0 return "Act3State"; } // FUNCTION: LEGO1 0x1000e310 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Act3State::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool VTable0x14() override; + MxBool VTable0x14() override; + + // SYNTHETIC: LEGO1 0x1000e3c0 + // Act3State::`scalar deleting destructor' private: // FIXME: May be part of LegoState? Uncertain... diff --git a/LEGO1/lego/legoomni/include/ambulance.h b/LEGO1/lego/legoomni/include/ambulance.h new file mode 100644 index 00000000..17175b03 --- /dev/null +++ b/LEGO1/lego/legoomni/include/ambulance.h @@ -0,0 +1,55 @@ +#ifndef AMBULANCE_H +#define AMBULANCE_H + +#include "islepathactor.h" + +// VTABLE: LEGO1 0x100d71a8 +// SIZE 0x184 +class Ambulance : public IslePathActor { +public: + Ambulance(); + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x10035fa0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f03c4 + return "Ambulance"; + } + + // FUNCTION: LEGO1 0x10035fb0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Ambulance::ClassName()) || IslePathActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xdc(MxType19NotificationParam&) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x10036130 + // Ambulance::`scalar deleting destructor' + +private: + // TODO: Ambulance fields + undefined m_unk0x160[4]; + MxS32 m_unk0x164; + MxS16 m_unk0x168; + MxS16 m_unk0x16a; + MxS16 m_unk0x16c; + MxS16 m_unk0x16e; + MxS16 m_unk0x170; + MxS16 m_unk0x172; + MxS32 m_unk0x174; + MxS32 m_unk0x178; + MxFloat m_unk0x17c; + undefined m_unk0x180[4]; +}; + +#endif // AMBULANCE_H diff --git a/LEGO1/ambulancemissionstate.h b/LEGO1/lego/legoomni/include/ambulancemissionstate.h similarity index 50% rename from LEGO1/ambulancemissionstate.h rename to LEGO1/lego/legoomni/include/ambulancemissionstate.h index 05d09859..aca6120b 100644 --- a/LEGO1/ambulancemissionstate.h +++ b/LEGO1/lego/legoomni/include/ambulancemissionstate.h @@ -10,18 +10,20 @@ class AmbulanceMissionState : public LegoState { AmbulanceMissionState(); // FUNCTION: LEGO1 0x10037600 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00e8 + // STRING: LEGO1 0x100f00e8 return "AmbulanceMissionState"; } // FUNCTION: LEGO1 0x10037610 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, AmbulanceMissionState::ClassName()) || LegoState::IsA(p_name); } + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + inline MxU16 GetColor(MxU8 p_id) { switch (p_id) { @@ -40,19 +42,22 @@ class AmbulanceMissionState : public LegoState { } } + // SYNTHETIC: LEGO1 0x100376c0 + // AmbulanceMissionState::`scalar deleting destructor' + protected: - undefined4 m_unk0x8; // 0x08 - undefined4 m_unk0xc; // 0x0c - MxU16 m_unk0x10; // 0x10 - MxU16 m_unk0x12; // 0x12 - MxU16 m_unk0x14; // 0x14 - MxU16 m_unk0x16; // 0x16 - MxU16 m_unk0x18; // 0x18 - MxU16 m_color1; // 0x1a - MxU16 m_color2; // 0x1c - MxU16 m_color3; // 0x1e - MxU16 m_color4; // 0x20 - MxU16 m_color5; // 0x22 + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + MxU16 m_unk0x10; // 0x10 + MxU16 m_unk0x12; // 0x12 + MxU16 m_unk0x14; // 0x14 + MxU16 m_unk0x16; // 0x16 + MxU16 m_unk0x18; // 0x18 + MxU16 m_color1; // 0x1a + MxU16 m_color2; // 0x1c + MxU16 m_color3; // 0x1e + MxU16 m_color4; // 0x20 + MxU16 m_color5; // 0x22 }; #endif // AMBULANCEMISSIONSTATE_H diff --git a/LEGO1/lego/legoomni/include/animstate.h b/LEGO1/lego/legoomni/include/animstate.h new file mode 100644 index 00000000..63b884d8 --- /dev/null +++ b/LEGO1/lego/legoomni/include/animstate.h @@ -0,0 +1,40 @@ +#ifndef ANIMSTATE_H +#define ANIMSTATE_H + +#include "legostate.h" + +// VTABLE: LEGO1 0x100d8d80 +// SIZE 0x1c +class AnimState : public LegoState { +public: + AnimState(); + ~AnimState() override; // vtable+0x00 + + // FUNCTION: LEGO1 0x10065070 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0460 + return "AnimState"; + } + + // FUNCTION: LEGO1 0x10065080 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, AnimState::ClassName()) || LegoState::IsA(p_name); + } + + MxBool SetFlag() override; // vtable+0x18 + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1C + + // SYNTHETIC: LEGO1 0x10065130 + // AnimState::`scalar deleting destructor' + +private: + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + void* m_unk0x10; // 0x10 + undefined4 m_unk0x14; // 0x14 + void* m_unk0x18; // 0x18 +}; + +#endif // ANIMSTATE_H diff --git a/LEGO1/beachhouseentity.h b/LEGO1/lego/legoomni/include/beachhouseentity.h similarity index 62% rename from LEGO1/beachhouseentity.h rename to LEGO1/lego/legoomni/include/beachhouseentity.h index cf6a8909..0910f49e 100644 --- a/LEGO1/beachhouseentity.h +++ b/LEGO1/lego/legoomni/include/beachhouseentity.h @@ -7,20 +7,21 @@ // SIZE 0x68 class BeachHouseEntity : public BuildingEntity { public: - virtual MxLong Notify(MxParam& p_param) override; // vtable+04 - // FUNCTION: LEGO1 0x1000ee80 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0314 + // STRING: LEGO1 0x100f0314 return "BeachHouseEntity"; } // FUNCTION: LEGO1 0x1000ee90 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, BeachHouseEntity::ClassName()) || BuildingEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f970 + // BeachHouseEntity::`scalar deleting destructor' }; #endif // BEACHHOUSEENTITY_H diff --git a/LEGO1/lego/legoomni/include/bike.h b/LEGO1/lego/legoomni/include/bike.h new file mode 100644 index 00000000..bfc634b4 --- /dev/null +++ b/LEGO1/lego/legoomni/include/bike.h @@ -0,0 +1,39 @@ +#ifndef BIKE_H +#define BIKE_H + +#include "decomp.h" +#include "islepathactor.h" + +// VTABLE: LEGO1 0x100d9808 +// SIZE 0x164 +class Bike : public IslePathActor { +public: + Bike(); + + // FUNCTION: LEGO1 0x100766f0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f03d0 + return "Bike"; + } + + // FUNCTION: LEGO1 0x10076700 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Bike::ClassName()) || IslePathActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x10076880 + // Bike::`scalar deleting destructor' + +private: + // TODO: Bike fields + undefined m_unk0x160[4]; +}; + +#endif // BIKE_H diff --git a/LEGO1/buildingentity.h b/LEGO1/lego/legoomni/include/buildingentity.h similarity index 57% rename from LEGO1/buildingentity.h rename to LEGO1/lego/legoomni/include/buildingentity.h index f0ba4c3c..d07d9f5d 100644 --- a/LEGO1/buildingentity.h +++ b/LEGO1/lego/legoomni/include/buildingentity.h @@ -8,20 +8,25 @@ class BuildingEntity : public LegoEntity { public: BuildingEntity(); - virtual ~BuildingEntity() override; // vtable+0x0 + ~BuildingEntity() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10014f20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07e8 + // STRING: LEGO1 0x100f07e8 return "BuildingEntity"; } // FUNCTION: LEGO1 0x10014f30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, BuildingEntity::ClassName()) || LegoEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x10015010 + // BuildingEntity::`scalar deleting destructor' }; #endif // BUILDINGENTITY_H diff --git a/LEGO1/lego/legoomni/include/bumpbouy.h b/LEGO1/lego/legoomni/include/bumpbouy.h new file mode 100644 index 00000000..c6308d57 --- /dev/null +++ b/LEGO1/lego/legoomni/include/bumpbouy.h @@ -0,0 +1,34 @@ +#ifndef BUMPBOUY_H +#define BUMPBOUY_H + +#include "legoanimactor.h" +#include "mxtypes.h" + +// VTABLE: LEGO1 0x100d6790 +class BumpBouy : public LegoAnimActor { +public: + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x100274e0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0394 + return "BumpBouy"; + } + + // FUNCTION: LEGO1 0x10027500 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, BumpBouy::ClassName()) || LegoAnimActor::IsA(p_name); + } + + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + + // SYNTHETIC: LEGO1 0x10027490 + // BumpBouy::`scalar deleting destructor' +}; + +#endif // BUMPBOUY_H diff --git a/LEGO1/lego/legoomni/include/carrace.h b/LEGO1/lego/legoomni/include/carrace.h new file mode 100644 index 00000000..c5af66e8 --- /dev/null +++ b/LEGO1/lego/legoomni/include/carrace.h @@ -0,0 +1,42 @@ +#ifndef CARRACE_H +#define CARRACE_H + +#include "decomp.h" +#include "legorace.h" + +// VTABLE: LEGO1 0x100d5e50 +// SIZE 0x154 +class CarRace : public LegoRace { +public: + CarRace(); + + // FUNCTION: LEGO1 0x10016b20 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0528 + return "CarRace"; + } + + // FUNCTION: LEGO1 0x10016b30 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, CarRace::ClassName()) || LegoRace::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x64() override; // vtable+0x64 + undefined4 VTable0x6c(undefined4) override; // vtable+0x6c + undefined4 VTable0x70(undefined4) override; // vtable+0x70 + undefined4 VTable0x74(undefined4) override; // vtable+0x74 + undefined4 VTable0x78(undefined4) override; // vtable+0x78 + + // SYNTHETIC: LEGO1 0x10016c70 + // CarRace::`scalar deleting destructor' + +private: + undefined m_unk0x144[12]; // 0x144 + undefined4 m_unk0x150; // 0x150 +}; + +#endif // CARRACE_H diff --git a/LEGO1/carracestate.h b/LEGO1/lego/legoomni/include/carracestate.h similarity index 60% rename from LEGO1/carracestate.h rename to LEGO1/lego/legoomni/include/carracestate.h index c922354f..c7a1e376 100644 --- a/LEGO1/carracestate.h +++ b/LEGO1/lego/legoomni/include/carracestate.h @@ -8,17 +8,20 @@ class CarRaceState : public RaceState { public: // FUNCTION: LEGO1 0x1000dd30 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f009c + // STRING: LEGO1 0x100f009c return "CarRaceState"; } // FUNCTION: LEGO1 0x1000dd40 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, CarRaceState::ClassName()) || RaceState::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f740 + // CarRaceState::`scalar deleting destructor' }; #endif // CARRACESTATE_H diff --git a/LEGO1/lego/legoomni/include/doors.h b/LEGO1/lego/legoomni/include/doors.h new file mode 100644 index 00000000..35958455 --- /dev/null +++ b/LEGO1/lego/legoomni/include/doors.h @@ -0,0 +1,31 @@ +#ifndef DOORS_H +#define DOORS_H + +#include "legopathactor.h" + +// VTABLE: LEGO1 0x100d4788 +// SIZE 0x1f8 +class Doors : public LegoPathActor { +public: + // FUNCTION: LEGO1 0x1000e430 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f03e8 + return "Doors"; + } + + // FUNCTION: LEGO1 0x1000e440 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Doors::ClassName()) || LegoPathActor::IsA(p_name); + } + + void ParseAction(char*) override; // vtable+0x20 + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x94() override; // vtable+0x94 + + // SYNTHETIC: LEGO1 0x1000e580 + // Doors::`scalar deleting destructor' +}; + +#endif // DOORS_H diff --git a/LEGO1/lego/legoomni/include/dunebuggy.h b/LEGO1/lego/legoomni/include/dunebuggy.h new file mode 100644 index 00000000..27c0cdb5 --- /dev/null +++ b/LEGO1/lego/legoomni/include/dunebuggy.h @@ -0,0 +1,43 @@ +#ifndef DUNEBUGGY_H +#define DUNEBUGGY_H + +#include "decomp.h" +#include "islepathactor.h" + +// VTABLE: LEGO1 0x100d8f98 +// SIZE 0x16c +class DuneBuggy : public IslePathActor { +public: + DuneBuggy(); + + // FUNCTION: LEGO1 0x10067c30 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0410 + return "DuneBuggy"; + } + + // FUNCTION: LEGO1 0x10067c40 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, DuneBuggy::ClassName()) || IslePathActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xdc(MxType19NotificationParam& p_param) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x10067dc0 + // DuneBuggy::`scalar deleting destructor' + +private: + // TODO: Double check DuneBuggy field types + undefined4 m_unk0x160; + MxFloat m_unk0x164; + undefined4 m_unk0x168; +}; + +#endif // DUNEBUGGY_H diff --git a/LEGO1/lego/legoomni/include/elevatorbottom.h b/LEGO1/lego/legoomni/include/elevatorbottom.h new file mode 100644 index 00000000..8057b993 --- /dev/null +++ b/LEGO1/lego/legoomni/include/elevatorbottom.h @@ -0,0 +1,49 @@ +#ifndef ELEVATORBOTTOM_H +#define ELEVATORBOTTOM_H + +#include "decomp.h" +#include "legoworld.h" + +class LegoControlManagerEvent; + +// VTABLE: LEGO1 0x100d5f20 +// SIZE: 0xfc (from inlined ctor at 0x1000a8aa) +class ElevatorBottom : public LegoWorld { +public: + ElevatorBottom(); + ~ElevatorBottom() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x10017f20 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f04ac + return "ElevatorBottom"; + } + + // FUNCTION: LEGO1 0x10017f30 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ElevatorBottom::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + + // FUNCTION: LEGO1 0x10017f10 + MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x10018040 + // ElevatorBottom::`scalar deleting destructor' + +private: + undefined4 m_unk0xf8; // 0xf8 + + MxLong HandleClick(LegoControlManagerEvent& p_param); +}; + +#endif // ELEVATORBOTTOM_H diff --git a/LEGO1/lego/legoomni/include/extra.h b/LEGO1/lego/legoomni/include/extra.h new file mode 100644 index 00000000..35f08033 --- /dev/null +++ b/LEGO1/lego/legoomni/include/extra.h @@ -0,0 +1,23 @@ +#ifndef EXTRA_H +#define EXTRA_H + +// Items related to the Extra string of key-value pairs found in MxOb + +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 new file mode 100644 index 00000000..2d32bd81 --- /dev/null +++ b/LEGO1/lego/legoomni/include/gasstation.h @@ -0,0 +1,56 @@ +#ifndef GASSTATION_H +#define GASSTATION_H + +#include "decomp.h" +#include "legoworld.h" +#include "radio.h" + +// VTABLE: LEGO1 0x100d4650 +// SIZE 0x128 +// Radio variable at 0x46, in constructor +class GasStation : public LegoWorld { +public: + GasStation(); + ~GasStation() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x10004780 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0168 + return "GasStation"; + } + + // FUNCTION: LEGO1 0x10004790 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, GasStation::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x100048a0 + // GasStation::`scalar deleting destructor' + +private: + undefined2 m_unk0xf8; // 0xf8 + undefined2 m_unk0xfa; // 0xfa + undefined4 m_unk0xfc; // 0xfc + undefined4 m_unk0x100; // 0x100 + undefined2 m_unk0x104; // 0x104 + undefined2 m_unk0x106; // 0x106 + undefined4 m_unk0x108; // 0x108 + undefined4 m_unk0x10c; // 0x10c + undefined4 m_unk0x110; // 0x110 + undefined m_unk0x114; // 0x114 + undefined m_unk0x115; // 0x115 + Radio m_radio; // 0x118 +}; + +#endif // GASSTATION_H diff --git a/LEGO1/gasstationentity.h b/LEGO1/lego/legoomni/include/gasstationentity.h similarity index 62% rename from LEGO1/gasstationentity.h rename to LEGO1/lego/legoomni/include/gasstationentity.h index 17aa22cf..0b271d46 100644 --- a/LEGO1/gasstationentity.h +++ b/LEGO1/lego/legoomni/include/gasstationentity.h @@ -8,17 +8,20 @@ class GasStationEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000eb20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0348 + // STRING: LEGO1 0x100f0348 return "GasStationEntity"; } // FUNCTION: LEGO1 0x1000eb30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, GasStationEntity::ClassName()) || BuildingEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f890 + // GasStationEntity::`scalar deleting destructor' }; #endif // GASSTATIONENTITY_H diff --git a/LEGO1/lego/legoomni/include/gasstationstate.h b/LEGO1/lego/legoomni/include/gasstationstate.h new file mode 100644 index 00000000..e9bbd0df --- /dev/null +++ b/LEGO1/lego/legoomni/include/gasstationstate.h @@ -0,0 +1,40 @@ +#ifndef GASSTATIONSTATE_H +#define GASSTATIONSTATE_H + +#include "legostate.h" + +// VTABLE: LEGO1 0x100d46e0 +// SIZE 0x24 +class GasStationState : public LegoState { +public: + GasStationState(); + + // FUNCTION: LEGO1 0x100061d0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0174 + return "GasStationState"; + } + + // FUNCTION: LEGO1 0x100061e0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, GasStationState::ClassName()) || LegoState::IsA(p_name); + } + + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + + // SYNTHETIC: LEGO1 0x10006290 + // GasStationState::`scalar deleting destructor' + +private: + undefined4 m_unk0x08[3]; // 0x08 + undefined4 m_unk0x14; // 0x14 + undefined2 m_unk0x18; // 0x18 + undefined2 m_unk0x1a; // 0x1a + undefined2 m_unk0x1c; // 0x1c + undefined2 m_unk0x1e; // 0x1e + undefined2 m_unk0x20; // 0x20 +}; + +#endif // GASSTATIONSTATE_H diff --git a/LEGO1/lego/legoomni/include/gifmanager.h b/LEGO1/lego/legoomni/include/gifmanager.h new file mode 100644 index 00000000..ce600a62 --- /dev/null +++ b/LEGO1/lego/legoomni/include/gifmanager.h @@ -0,0 +1,141 @@ +#ifndef GIFMANAGER_H +#define GIFMANAGER_H + +#include "compat.h" +#include "decomp.h" +#include "mxstl/stlcompat.h" +#include "mxtypes.h" + +#include +#include + +#pragma warning(disable : 4237) + +// SIZE 0x14 +struct GifData { +public: + char* m_name; // 0x00 + LPDIRECTDRAWSURFACE m_surface; // 0x04 + LPDIRECTDRAWPALETTE m_palette; // 0x08 + LPDIRECT3DRMTEXTURE2 m_texture; // 0x0c + MxU8* m_data; // 0x10 + + ~GifData(); +}; + +struct GifMapComparator { + bool operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } +}; + +// SIZE 0x10 +class GifMap : public map { + // SYNTHETIC: LEGO1 0x1005a400 + // GifMap::~GifMap +}; + +typedef list GifList; + +// VTABLE: LEGO1 0x100d86d4 +// SIZE 0x18 +class GifManagerBase { +public: + // FUNCTION: LEGO1 0x1005b660 + virtual ~GifManagerBase() + { + GifMap::iterator it; + for (it = m_map.begin(); it != m_map.end(); it++) { + // DECOMP: Use of const_cast here matches ~ViewLODListManager from 96 source. + const char* const& key = (*it).first; + delete[] const_cast(key); + + if (m_ownership) { + delete (*it).second; // GifData* + } + } + } + + inline GifData* Get(const char* p_name) + { + GifMap::iterator it = m_map.find(p_name); + if (it != m_map.end()) { + return (*it).second; + } + + return NULL; + } + + // SYNTHETIC: LEGO1 0x1005a310 + // GifManagerBase::`scalar deleting destructor' + +protected: + MxBool m_ownership; // 0x04 + GifMap m_map; // 0x08 +}; + +// VTABLE: LEGO1 0x100d86fc +// SIZE 0x24 +class GifManager : public GifManagerBase { +public: + GifManager() { m_ownership = TRUE; } + ~GifManager() override; + + // SYNTHETIC: LEGO1 0x1005a580 + // GifManager::`scalar deleting destructor' + + void FUN_10099cc0(GifData* p_data); + +protected: + GifList m_list; // 0x18 +}; + +// TEMPLATE: LEGO1 0x10059c50 +// allocator::_Charalloc + +// clang-format off +// TEMPLATE: LEGO1 0x10001cc0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Lbound + +// TEMPLATE: LEGO1 0x1004f9b0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Insert + +// TEMPLATE: LEGO1 0x10059c70 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Color + +// TEMPLATE: LEGO1 0x10059c80 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Left + +// TEMPLATE: LEGO1 0x10059c90 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Parent + +// TEMPLATE: LEGO1 0x10059ca0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Right + +// TEMPLATE: LEGO1 0x10059cb0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::~_Tree,map >::_Kfn,GifMapComparator,allocator > + +// TEMPLATE: LEGO1 0x10059d80 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x10059dc0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::erase + +// TEMPLATE: LEGO1 0x1005a210 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Erase + +// TEMPLATE: LEGO1 0x1005a250 +// list >::~list > + +// TEMPLATE: LEGO1 0x1005a2c0 +// map >::~map > + +// TEMPLATE: LEGO1 0x1005a450 +// Map::~Map + +// TEMPLATE: LEGO1 0x1005a5a0 +// List::~List + +// GLOBAL: LEGO1 0x100f0100 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Nil +// clang-format on + +#endif // GIFMANAGER_H diff --git a/LEGO1/lego/legoomni/include/helicopter.h b/LEGO1/lego/legoomni/include/helicopter.h new file mode 100644 index 00000000..6c917aec --- /dev/null +++ b/LEGO1/lego/legoomni/include/helicopter.h @@ -0,0 +1,63 @@ +#ifndef HELICOPTER_H +#define HELICOPTER_H + +#include "helicopterstate.h" +#include "islepathactor.h" +#include "realtime/matrix.h" + +// SIZE 0x34 +class HelicopterSubclass { +public: + inline HelicopterSubclass() : m_unk0x30(0) {} + MxResult FUN_100040a0(Vector4& p_v, float p_f); + +private: + Mx4DPointFloat m_unk0x00; // 0x00 + Mx4DPointFloat m_unk0x18; // 0x18 + undefined4 m_unk0x30; // 0x30 +}; + +// VTABLE: LEGO1 0x100d40f8 +// SIZE 0x230 +class Helicopter : public IslePathActor { +public: + Helicopter(); + ~Helicopter() override; // vtable+0x00 + + // FUNCTION: LEGO1 0x10003070 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0130 + return "Helicopter"; + } + + // FUNCTION: LEGO1 0x10003080 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Helicopter::ClassName()) || IslePathActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x10003210 + // Helicopter::`scalar deleting destructor' + +protected: + MxMatrix m_unk0x160; // 0x160 + MxMatrix m_unk0x1a8; // 0x1a8 + float m_unk0x1f0; // 0x1f0 + HelicopterSubclass m_unk0x1f4; // 0x1f4 + HelicopterState* m_state; // 0x228 + MxAtomId m_script; // 0x22c + +private: + void GetState(); +}; + +#endif // HELICOPTER_H diff --git a/LEGO1/lego/legoomni/include/helicopterstate.h b/LEGO1/lego/legoomni/include/helicopterstate.h new file mode 100644 index 00000000..993b8f7c --- /dev/null +++ b/LEGO1/lego/legoomni/include/helicopterstate.h @@ -0,0 +1,44 @@ +#ifndef HELICOPTERSTATE_H +#define HELICOPTERSTATE_H + +#include "decomp.h" +#include "legostate.h" + +// VTABLE: LEGO1 0x100d5418 +// SIZE 0x0c +class HelicopterState : public LegoState { +public: + // FUNCTION: LEGO1 0x1000e0d0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0144 + return "HelicopterState"; + } + + // FUNCTION: LEGO1 0x1000e0e0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, HelicopterState::ClassName()) || LegoState::IsA(p_name); + } + + // FUNCTION: LEGO1 0x1000e0b0 + MxBool VTable0x14() override { return FALSE; } // vtable+0x14 + + // FUNCTION: LEGO1 0x1000e0c0 + MxBool SetFlag() override + { + m_unk0x08 = 0; + return TRUE; + } // vtable+0x18 + + inline void SetUnknown8(MxU32 p_unk0x08) { m_unk0x08 = p_unk0x08; } + inline MxU32 GetUnkown8() { return m_unk0x08; } + + // SYNTHETIC: LEGO1 0x1000e190 + // HelicopterState::`scalar deleting destructor' + +protected: + MxU32 m_unk0x08; // 0x08 +}; + +#endif // HELICOPTERSTATE_H diff --git a/LEGO1/lego/legoomni/include/historybook.h b/LEGO1/lego/legoomni/include/historybook.h new file mode 100644 index 00000000..862be059 --- /dev/null +++ b/LEGO1/lego/legoomni/include/historybook.h @@ -0,0 +1,36 @@ +#ifndef HISTORYBOOK_H +#define HISTORYBOOK_H + +#include "legoworld.h" + +// VTABLE: LEGO1 0x100da328 +// SIZE 0x3e4 +class HistoryBook : public LegoWorld { +public: + HistoryBook(); + ~HistoryBook() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x10082390 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f04bc + return "HistoryBook"; + } + + // FUNCTION: LEGO1 0x100823a0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, HistoryBook::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x64() override; // vtable+0x64 + + // SYNTHETIC: LEGO1 0x100824b0 + // HistoryBook::`scalar deleting destructor' +}; + +#endif // HISTORYBOOK_H diff --git a/LEGO1/lego/legoomni/include/hospital.h b/LEGO1/lego/legoomni/include/hospital.h new file mode 100644 index 00000000..809e64e2 --- /dev/null +++ b/LEGO1/lego/legoomni/include/hospital.h @@ -0,0 +1,55 @@ +#ifndef HOSPITAL_H +#define HOSPITAL_H + +#include "decomp.h" +#include "legoworld.h" + +// VTABLE: LEGO1 0x100d9730 +// SIZE 0x12c +class Hospital : public LegoWorld { +public: + Hospital(); + ~Hospital() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x100746b0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0490 + return "Hospital"; + } + + // FUNCTION: LEGO1 0x100746c0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Hospital::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x100747d0 + // Hospital::`scalar deleting destructor' + +private: + undefined2 m_unk0xf8; // 0xf8 + undefined4 m_unk0xfc; // 0xfc + undefined2 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 - VTable0x18 suggests this may be pointer to a LegoGameState + undefined2 m_unk0x108; // 0x108 + undefined4 m_unk0x10c; // 0x10c + undefined4 m_unk0x110; // 0x110 + undefined4 m_unk0x114; // 0x114 + undefined m_unk0x118; // 0x118 + undefined4 m_unk0x11c; // 0x11c + undefined4 m_unk0x120; // 0x120 + undefined m_unk0x124[4]; // 0x124 + undefined m_unk0x128; // 0x128 +}; + +#endif // HOSPITAL_H diff --git a/LEGO1/hospitalentity.h b/LEGO1/lego/legoomni/include/hospitalentity.h similarity index 61% rename from LEGO1/hospitalentity.h rename to LEGO1/lego/legoomni/include/hospitalentity.h index 9dc597f1..a837bd7b 100644 --- a/LEGO1/hospitalentity.h +++ b/LEGO1/lego/legoomni/include/hospitalentity.h @@ -8,17 +8,20 @@ class HospitalEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000ec40 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0338 + // STRING: LEGO1 0x100f0338 return "HospitalEntity"; } // FUNCTION: LEGO1 0x1000ec50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, HospitalEntity::ClassName()) || BuildingEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f820 + // HospitalEntity::`scalar deleting destructor' }; #endif // HOSPITALENTITY_H diff --git a/LEGO1/lego/legoomni/include/hospitalstate.h b/LEGO1/lego/legoomni/include/hospitalstate.h new file mode 100644 index 00000000..980007e3 --- /dev/null +++ b/LEGO1/lego/legoomni/include/hospitalstate.h @@ -0,0 +1,42 @@ +#ifndef HOSPITALSTATE_H +#define HOSPITALSTATE_H + +#include "decomp.h" +#include "legostate.h" + +// VTABLE: LEGO1 0x100d97a0 +// SIZE 0x18 +class HospitalState : public LegoState { +public: + HospitalState(); + ~HospitalState() override {} + + // FUNCTION: LEGO1 0x10076400 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0480 + return "HospitalState"; + } + + // FUNCTION: LEGO1 0x10076410 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, HospitalState::ClassName()) || LegoState::IsA(p_name); + } + + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + + // SYNTHETIC: LEGO1 0x100764c0 + // HospitalState::`scalar deleting destructor' + +private: + undefined m_unk0x08[4]; // 0x08 + undefined2 m_unk0x0c; // 0x0c + undefined2 m_unk0x0e; // 0x0e + undefined2 m_unk0x10; // 0x10 + undefined2 m_unk0x12; // 0x12 + undefined2 m_unk0x14; // 0x14 + undefined2 m_unk0x16; // 0x16 +}; + +#endif // HOSPITALSTATE_H diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h new file mode 100644 index 00000000..46e6b463 --- /dev/null +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -0,0 +1,239 @@ +#ifndef INFOCENTER_H +#define INFOCENTER_H + +#include "legoworld.h" +#include "mxrect32.h" +#include "radio.h" + +class InfocenterState; +class MxStillPresenter; +class LegoControlManagerEvent; + +// SIZE 0x18 +struct InfocenterMapEntry { + // FUNCTION: LEGO1 0x1006ec80 + InfocenterMapEntry() {} + + MxStillPresenter* m_presenter; // 0x00 + undefined4 m_unk0x04; // 0x04 + MxRect32 m_area; // 0x08 +}; + +// 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_leftArrowCtl = 1, + c_rightArrowCtl = 2, + c_infoCtl = 3, + c_doorCtl = 4, + c_boatCtl = 10, + c_raceCtl = 11, + c_pizzaCtl = 12, + c_gasCtl = 13, + c_medCtl = 14, + c_copCtl = 15, + c_bigInfoCtl = 16, + c_bookCtl = 17, + c_radioCtl = 18, + c_mamaCtl = 21, + c_papaCtl = 22, + c_pepperCtl = 23, + c_nickCtl = 24, + c_lauraCtl = 25, + + c_mamaSelected = 30, + c_papaSelected = 31, + c_pepperSelected = 32, + c_nickSelected = 33, + c_lauraSelected = 34, + + c_mamaMovie = 40, + c_papaMovie = 41, + c_pepperMovie = 42, + c_nickMovie = 43, + c_lauraMovie = 44, + + c_goToRegBook = 70, + c_goToRegBookRed = 71, + + c_unk499 = 499, + + c_welcomeDialogue = 500, + c_goodJobDialogue = 501, + + 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_gasCtlDescription = 555, + c_medCtlDescription = 556, + c_unk557 = 557, + c_boatCtlDescription = 558, + c_copCtlDescription = 559, + c_pizzaCtlDescription = 560, + c_raceCtlDescription = 561, + + c_leaveInfoCenterDialogue1 = 562, + c_leaveInfoCenterDialogue2 = 563, + c_leaveInfoCenterDialogue3 = 564, + c_leaveInfoCenterDialogue4 = 565, + + c_unk566 = 566, + c_unk567 = 567, + c_unk568 = 568, + + c_unk569 = 569, + c_unk570 = 570, + c_unk571 = 571, + c_unk572 = 572, + + c_registerToContinueDialogue = 573, + + c_bricksterDialogue = 574, + c_bricksterLaughs = 575, + }; + + enum SndAmimScript { + c_bookWig = 400 + }; + + Infocenter(); + ~Infocenter() override; + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1006eb40 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f04ec + return "Infocenter"; + } + + // FUNCTION: LEGO1 0x1006eb50 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Infocenter::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x1006ec60 + // Infocenter::`scalar deleting destructor' + +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 HandleClick(LegoControlManagerEvent& p_param); + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleNotification0(MxNotificationParam& p_param); + + void UpdateFrameHot(MxBool p_display); + void FUN_10070e90(); + + void PlayCutscene(Cutscene p_entityId, MxBool p_scale); + void StopCutscene(); + + void FUN_10070d10(MxS32 p_x, MxS32 p_y); + + void StartCredits(); + void StopCredits(); + + void PlayAction(InfomainScript p_objectId); + void StopCurrentAction(); + + void PlayBookAnimation(); + void StopBookAnimation(); + + InfomainScript m_currentInfomainScript; // 0xf8 + MxS16 m_unk0xfc; // 0xfc + InfocenterState* m_infocenterState; // 0x100 + undefined4 m_transitionDestination; // 0x104 + Cutscene m_currentCutscene; // 0x108 + Radio m_radio; // 0x10c + MxStillPresenter* m_unk0x11c; // 0x11c + InfocenterMapEntry m_mapAreas[7]; // 0x120 + MxS16 m_unk0x1c8; // 0x1c8 + MxStillPresenter* m_frameHotBitmap; // 0x1cc + MxS16 m_infoManDialogueTimer; // 0x1d0 + MxS16 m_bookAnimationTimer; // 0x1d2 + MxU16 m_unk0x1d4; // 0x1d4 + MxS16 m_unk0x1d6; // 0x1d6 +}; + +#endif // INFOCENTER_H diff --git a/LEGO1/lego/legoomni/include/infocenterdoor.h b/LEGO1/lego/legoomni/include/infocenterdoor.h new file mode 100644 index 00000000..84be246a --- /dev/null +++ b/LEGO1/lego/legoomni/include/infocenterdoor.h @@ -0,0 +1,48 @@ +#ifndef INFOCENTERDOOR_H +#define INFOCENTERDOOR_H + +#include "legoworld.h" + +class LegoControlManagerEvent; + +// VTABLE: LEGO1 0x100d72d8 +// SIZE 0xfc +class InfocenterDoor : public LegoWorld { +public: + InfocenterDoor(); + ~InfocenterDoor() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x100377b0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f049c + return "InfocenterDoor"; + } + + // FUNCTION: LEGO1 0x100377c0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, InfocenterDoor::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + + // FUNCTION: LEGO1 0x100377a0 + MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x100378d0 + // InfocenterDoor::`scalar deleting destructor' + +private: + MxS32 m_unk0xf8; // 0xf8 + + MxLong HandleClick(LegoControlManagerEvent& p_param); +}; + +#endif // INFOCENTERDOOR_H diff --git a/LEGO1/infocenterentity.h b/LEGO1/lego/legoomni/include/infocenterentity.h similarity index 62% rename from LEGO1/infocenterentity.h rename to LEGO1/lego/legoomni/include/infocenterentity.h index 44121ae2..85bcbce5 100644 --- a/LEGO1/infocenterentity.h +++ b/LEGO1/lego/legoomni/include/infocenterentity.h @@ -8,17 +8,20 @@ class InfoCenterEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000ea00 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f035c + // STRING: LEGO1 0x100f035c return "InfoCenterEntity"; } // FUNCTION: LEGO1 0x1000ea10 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, InfoCenterEntity::ClassName()) || BuildingEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f7b0 + // InfoCenterEntity::`scalar deleting destructor' }; #endif // INFOCENTERENTITY_H diff --git a/LEGO1/lego/legoomni/include/infocenterstate.h b/LEGO1/lego/legoomni/include/infocenterstate.h new file mode 100644 index 00000000..171e3c0b --- /dev/null +++ b/LEGO1/lego/legoomni/include/infocenterstate.h @@ -0,0 +1,54 @@ +#ifndef INFOCENTERSTATE_H +#define INFOCENTERSTATE_H + +#include "decomp.h" +#include "legostate.h" +#include "mxstillpresenter.h" + +// VTABLE: LEGO1 0x100d93a8 +// SIZE 0x94 +class InfocenterState : public LegoState { +public: + InfocenterState(); + ~InfocenterState() override; + + // FUNCTION: LEGO1 0x10071840 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f04dc + return "InfocenterState"; + } + + // FUNCTION: LEGO1 0x10071850 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, InfocenterState::ClassName()) || LegoState::IsA(p_name); + } + + // FUNCTION: LEGO1 0x10071830 + MxBool VTable0x14() override { return FALSE; } // vtable+0x14 + + inline MxS16 GetInfocenterBufferSize() { return sizeof(m_buffer) / sizeof(m_buffer[0]); } + inline MxStillPresenter* GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } + inline Playlist& GetUnknown0x08() { return m_unk0x08; } + inline Playlist& GetUnknown0x14() { return m_unk0x14; } + inline Playlist& GetUnknown0x68() { return m_unk0x68; } + inline MxU32 GetUnknown0x74() { return m_unk0x74; } + inline Playlist* GetUnknown0x44() { return m_unk0x44; } + + inline void SetUnknown0x74(MxU32 p_unk0x74) { m_unk0x74 = p_unk0x74; } + + // SYNTHETIC: LEGO1 0x10071900 + // InfocenterState::`scalar deleting destructor' + +private: + Playlist m_unk0x08; // 0x08 + Playlist m_unk0x14; // 0x14 + Playlist m_unk0x20[3]; // 0x20 + Playlist m_unk0x44[3]; // 0x44 + Playlist m_unk0x68; // 0x68 + MxU32 m_unk0x74; // 0x74 + MxStillPresenter* m_buffer[7]; // 0x78 +}; + +#endif // INFOCENTERSTATE_H diff --git a/LEGO1/isle.h b/LEGO1/lego/legoomni/include/isle.h similarity index 63% rename from LEGO1/isle.h rename to LEGO1/lego/legoomni/include/isle.h index 9f44eadd..f94e6832 100644 --- a/LEGO1/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; @@ -20,35 +20,34 @@ class Act1State; // VTABLE: LEGO1 0x100d6fb8 // SIZE 0x140 -// Radio at 0x12c class Isle : public LegoWorld { public: Isle(); - virtual ~Isle() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + ~Isle() override; + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10030910 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0458 + // STRING: LEGO1 0x100f0458 return "Isle"; } // FUNCTION: LEGO1 0x10030920 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Isle::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 - virtual void Stop() override; // vtable+50 - virtual void VTable0x58(MxCore* p_object) override; // vtable+58 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+50 + void Add(MxCore* p_object) override; // vtable+58 // FUNCTION: LEGO1 0x10030900 - virtual MxBool VTable0x5c() override { return TRUE; } // vtable+5c + MxBool VTable0x5c() override { return TRUE; } // vtable+5c // FUNCTION: LEGO1 0x10033170 - virtual void VTable0x60() override {} // vtable+60 - virtual MxBool VTable0x64() override; // vtable+64 - virtual void VTable0x68(MxBool p_add) override; // vtable+68 + void VTable0x60() override {} // vtable+60 + MxBool VTable0x64() override; // vtable+64 + void Enable(MxBool p_enable) override; // vtable+68 virtual void VTable0x6c(IslePathActor* p_actor); // vtable+6c inline void SetUnknown13c(MxU32 p_unk0x13c) { m_unk0x13c = p_unk0x13c; } @@ -57,6 +56,10 @@ class Isle : public LegoWorld { MxLong HandleType17Notification(MxParam& p_param); MxLong HandleType19Notification(MxParam& p_param); MxLong HandleTransitionEnd(); + void FUN_10032620(); + + // SYNTHETIC: LEGO1 0x10030a30 + // Isle::`scalar deleting destructor' protected: Act1State* m_act1state; // 0xf8 @@ -68,7 +71,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 new file mode 100644 index 00000000..c51946d3 --- /dev/null +++ b/LEGO1/lego/legoomni/include/isleactor.h @@ -0,0 +1,33 @@ +#ifndef ISLEACTOR_H +#define ISLEACTOR_H + +#include "legoactor.h" + +// VTABLE: LEGO1 0x100d5178 +class IsleActor : public LegoActor { +public: + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x1000e660 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f07dc + return "IsleActor"; + } + + // FUNCTION: LEGO1 0x1000e670 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, IsleActor::ClassName()) || LegoActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 +}; + +// SYNTHETIC: LEGO1 0x1000e940 +// IsleActor::~IsleActor + +// SYNTHETIC: LEGO1 0x1000e990 +// IsleActor::`scalar deleting destructor' + +#endif // ISLEACTOR_H diff --git a/LEGO1/islepathactor.h b/LEGO1/lego/legoomni/include/islepathactor.h similarity index 73% rename from LEGO1/islepathactor.h rename to LEGO1/lego/legoomni/include/islepathactor.h index 44f50475..a7fabbfa 100644 --- a/LEGO1/islepathactor.h +++ b/LEGO1/lego/legoomni/include/islepathactor.h @@ -1,9 +1,9 @@ #ifndef ISLEPATHACTOR_H #define ISLEPATHACTOR_H +#include "legocontrolmanager.h" #include "legopathactor.h" #include "legoworld.h" -#include "mxtype17notificationparam.h" #include "mxtype18notificationparam.h" #include "mxtype19notificationparam.h" #include "mxtypes.h" @@ -13,28 +13,33 @@ class IslePathActor : public LegoPathActor { public: IslePathActor(); - inline virtual ~IslePathActor() override { IslePathActor::Destroy(TRUE); } // vtable+0x0 + + // FUNCTION: LEGO1 0x10002e10 + inline ~IslePathActor() override { IslePathActor::Destroy(TRUE); } // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10002ea0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0104 + // STRING: LEGO1 0x100f0104 return "IslePathActor"; } // FUNCTION: LEGO1 0x10002eb0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, IslePathActor::ClassName()) || LegoPathActor::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c // FUNCTION: LEGO1 0x10002e70 virtual MxU32 VTable0xcc() { return 0; } // vtable+0xcc // FUNCTION: LEGO1 0x10002df0 virtual MxU32 VTable0xd0() { return 0; } // vtable+0xd0 // FUNCTION: LEGO1 0x10002e80 - virtual MxU32 VTable0xd4(MxType17NotificationParam&) { return 0; } // vtable+0xd4 + virtual MxU32 VTable0xd4(LegoControlManagerEvent&) { return 0; } // vtable+0xd4 // FUNCTION: LEGO1 0x10002e90 virtual MxU32 VTable0xd8(MxType18NotificationParam&) { return 0; } // vtable+0xd8 // FUNCTION: LEGO1 0x10002e00 diff --git a/LEGO1/lego/legoomni/include/jetski.h b/LEGO1/lego/legoomni/include/jetski.h new file mode 100644 index 00000000..b71e43cf --- /dev/null +++ b/LEGO1/lego/legoomni/include/jetski.h @@ -0,0 +1,41 @@ +#ifndef JETSKI_H +#define JETSKI_H + +#include "decomp.h" +#include "islepathactor.h" +#include "legocontrolmanager.h" + +// VTABLE: LEGO1 0x100d9ec8 +// SIZE 0x164 +class Jetski : public IslePathActor { +public: + Jetski(); + + // FUNCTION: LEGO1 0x1007e430 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f03d8 + return "Jetski"; + } + + // FUNCTION: LEGO1 0x1007e440 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Jetski::ClassName()) || IslePathActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent&) override; // vtable+0xd4 + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x1007e5c0 + // Jetski::`scalar deleting destructor' + +private: + // TODO: Jetski fields + undefined m_unk0x160[4]; +}; + +#endif // JETSKI_H diff --git a/LEGO1/jetskirace.h b/LEGO1/lego/legoomni/include/jetskirace.h similarity index 66% rename from LEGO1/jetskirace.h rename to LEGO1/lego/legoomni/include/jetskirace.h index 9488ed04..d926e871 100644 --- a/LEGO1/jetskirace.h +++ b/LEGO1/lego/legoomni/include/jetskirace.h @@ -8,14 +8,14 @@ class JetskiRace : public LegoRace { public: // FUNCTION: LEGO1 0x1000daf0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0530 + // STRING: LEGO1 0x100f0530 return "JetskiRace"; } // FUNCTION: LEGO1 0x1000db00 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JetskiRace::ClassName()) || LegoRace::IsA(p_name); } diff --git a/LEGO1/jetskiracestate.h b/LEGO1/lego/legoomni/include/jetskiracestate.h similarity index 61% rename from LEGO1/jetskiracestate.h rename to LEGO1/lego/legoomni/include/jetskiracestate.h index 9724e4a1..812a0a0f 100644 --- a/LEGO1/jetskiracestate.h +++ b/LEGO1/lego/legoomni/include/jetskiracestate.h @@ -8,17 +8,20 @@ class JetskiRaceState : public RaceState { public: // FUNCTION: LEGO1 0x1000dc40 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00ac + // STRING: LEGO1 0x100f00ac return "JetskiRaceState"; } // FUNCTION: LEGO1 0x1000dc50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JetskiRaceState::ClassName()) || RaceState::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f680 + // JetskiRaceState::`scalar deleting destructor' }; #endif // JETSKIRACESTATE_H diff --git a/LEGO1/lego/legoomni/include/jukebox.h b/LEGO1/lego/legoomni/include/jukebox.h new file mode 100644 index 00000000..94728ee2 --- /dev/null +++ b/LEGO1/lego/legoomni/include/jukebox.h @@ -0,0 +1,117 @@ +#ifndef JUKEBOX_H +#define JUKEBOX_H + +#include "decomp.h" +#include "legoworld.h" + +// VTABLE: LEGO1 0x100d8958 +// SIZE 0x104 +class JukeBox : public LegoWorld { +public: + JukeBox(); + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1005d6f0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f02cc + return "JukeBox"; + } + + // FUNCTION: LEGO1 0x1005d700 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x1005d810 + // JukeBox::`scalar deleting destructor' + + enum JukeBoxScript { + e_mamaPapaBrickolini, + e_jailUnused, + e_act2Cave, + e_bricksterChase, + e_brickHunt, + e_residentialArea, + e_beachBlvd, + e_cave, + e_centralRoads, + e_jail, + e_hospital, + e_informationCenter, + e_policeStation, + e_park, + e_centralNorthRoad, + e_garageArea, + e_raceTrack, + e_beach, + e_quietChirping, + e_jetskiRace, + e_act3Pursuit, + + e_legoRadioReminder1, + e_legoRadioJingle1, + e_legoRadioJingle2, + e_legoRadioJingle3, + e_legoRadioJingle4, + e_legoRadioReminder2, + + e_legoRadioRacingAd, + e_legoRadioNews1, + e_legoRadioNews2, + e_legoRadioPizzaAd1, + e_legoRadioBricksterPSA, + e_legoRadioSports1, + e_legoRadioIntermission1, + e_legoRadioIntermission2, + e_legoRadioPizzaAd2, + e_legoRadioWeatherReport, + e_legoRadioSports2, + e_legoRadioPizzaAd3, + e_legoRadioIntermission3, + e_legoRadioSuperStoreAd, + + e_legoRadioLuckyYou, + e_legoRadioJazzInterlude, + e_legoRadioPianoInterlude1, + e_legoRadioPoliceStation, + e_legoRadioPianoInterlude2, + e_legoRadioCredits, + + e_helicopterBuild, + e_padding1, + e_duneBuggyBuild, + e_padding2, + e_jetskiBuild, + e_padding3, + e_raceCarBuild, + e_padding4, + + e_jukeBoxMamaPapaBrickolini, + e_jukeBoxBrickByBrick, + e_jukeBoxTheBrickster, + e_jukeBoxBuildMeABridgeToday, + e_jukeBoxBaroqueInBrick, + e_jukeBoxMantaRay, + + e_observationDeck, + e_elevator, + e_pizzaMission, + }; + +private: + undefined m_unk0xf8[4]; // 0xf8 + undefined4 m_unk0xfc; // 0xfc + undefined2 m_unk0x100; // 0x100 +}; + +#endif // JUKEBOX_H diff --git a/LEGO1/jukeboxentity.h b/LEGO1/lego/legoomni/include/jukeboxentity.h similarity index 53% rename from LEGO1/jukeboxentity.h rename to LEGO1/lego/legoomni/include/jukeboxentity.h index 3e175568..8afee4b5 100644 --- a/LEGO1/jukeboxentity.h +++ b/LEGO1/lego/legoomni/include/jukeboxentity.h @@ -8,20 +8,25 @@ class JukeBoxEntity : public LegoEntity { public: JukeBoxEntity(); - virtual ~JukeBoxEntity() override; // vtable+0x0 + ~JukeBoxEntity() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10085cc0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02f0 + // STRING: LEGO1 0x100f02f0 return "JukeBoxEntity"; } // FUNCTION: LEGO1 0x10085cd0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JukeBoxEntity::ClassName()) || LegoEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x10085db0 + // JukeBoxEntity::`scalar deleting destructor' }; #endif // JUKEBOXENTITY_H diff --git a/LEGO1/jukeboxstate.h b/LEGO1/lego/legoomni/include/jukeboxstate.h similarity index 56% rename from LEGO1/jukeboxstate.h rename to LEGO1/lego/legoomni/include/jukeboxstate.h index 8a481437..7f157bd0 100644 --- a/LEGO1/jukeboxstate.h +++ b/LEGO1/lego/legoomni/include/jukeboxstate.h @@ -8,19 +8,22 @@ class JukeBoxState : public LegoState { public: // FUNCTION: LEGO1 0x1000f310 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02bc + // STRING: LEGO1 0x100f02bc return "JukeBoxState"; } // FUNCTION: LEGO1 0x1000f320 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JukeBoxState::ClassName()) || LegoState::IsA(p_name); } - virtual MxBool VTable0x14() override; // vtable+0x14 + MxBool VTable0x14() override; // vtable+0x14 + + // SYNTHETIC: LEGO1 0x1000f3d0 + // JukeBoxState::`scalar deleting destructor' }; #endif // JUKEBOXSTATE_H diff --git a/LEGO1/lego/legoomni/include/lego3dwavepresenter.h b/LEGO1/lego/legoomni/include/lego3dwavepresenter.h new file mode 100644 index 00000000..22b39156 --- /dev/null +++ b/LEGO1/lego/legoomni/include/lego3dwavepresenter.h @@ -0,0 +1,32 @@ +#ifndef LEGO3DWAVEPRESENTER_H +#define LEGO3DWAVEPRESENTER_H + +#include "mxwavepresenter.h" + +// VTABLE: LEGO1 0x100d52b0 +// SIZE 0xa0 +class Lego3DWavePresenter : public MxWavePresenter { +public: + // FUNCTION: LEGO1 0x1000d890 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f058c + return "Lego3DWavePresenter"; + } + + // FUNCTION: LEGO1 0x1000d8a0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Lego3DWavePresenter::ClassName()) || MxWavePresenter::IsA(p_name); + } + + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + + // SYNTHETIC: LEGO1 0x1000f4b0 + // Lego3DWavePresenter::`scalar deleting destructor' +}; + +#endif // LEGO3DWAVEPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoact2.h b/LEGO1/lego/legoomni/include/legoact2.h new file mode 100644 index 00000000..dfedc85d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoact2.h @@ -0,0 +1,25 @@ +#ifndef LEGOACT2_H +#define LEGOACT2_H + +#include "legocarraceactor.h" +#include "legopathactor.h" +#include "legoworld.h" + +// VTABLE: LEGO1 0x100d82e0 +// SIZE 0x1154 +class LegoAct2 : public LegoWorld { + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + void VTable0x60() override; // vtable+0x60 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x1004fe20 + // LegoAct2::`scalar deleting destructor' +}; + +#endif // LEGOACT2_H diff --git a/LEGO1/legoact2state.h b/LEGO1/lego/legoomni/include/legoact2state.h similarity index 53% rename from LEGO1/legoact2state.h rename to LEGO1/lego/legoomni/include/legoact2state.h index a26cdd7d..78101599 100644 --- a/LEGO1/legoact2state.h +++ b/LEGO1/lego/legoomni/include/legoact2state.h @@ -7,18 +7,25 @@ // SIZE 0x10 class LegoAct2State : public LegoState { public: + ~LegoAct2State() override {} + // FUNCTION: LEGO1 0x1000df80 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0428 + // STRING: LEGO1 0x100f0428 return "LegoAct2State"; } // FUNCTION: LEGO1 0x1000df90 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoAct2State::ClassName()) || LegoState::IsA(p_name); } + + MxBool VTable0x14() override; // vtable+0x14 + + // SYNTHETIC: LEGO1 0x1000e040 + // LegoAct2State::`scalar deleting destructor' }; #endif // LEGOACT2STATE_H diff --git a/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h b/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h new file mode 100644 index 00000000..3dcbfecb --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h @@ -0,0 +1,43 @@ +#ifndef LEGOACTIONCONTROLPRESENTER_H +#define LEGOACTIONCONTROLPRESENTER_H + +#include "decomp.h" +#include "legoutil.h" +#include "mxmediapresenter.h" + +// VTABLE: LEGO1 0x100d5118 +// SIZE 0x68 +class LegoActionControlPresenter : public MxMediaPresenter { +public: + inline LegoActionControlPresenter() { m_unk0x50 = Extra::ActionType::e_none; } + ~LegoActionControlPresenter() override { Destroy(TRUE); } // vtable+0x00 + + // FUNCTION: LEGO1 0x1000d0e0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f05bc + return "LegoActionControlPresenter"; + } + + // FUNCTION: LEGO1 0x1000d0f0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoActionControlPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + virtual void Destroy(MxBool p_fromDestructor); // vtable+0x5c + +private: + Extra::ActionType m_unk0x50; // 0x50 + MxString m_unk0x54; // 0x54 + undefined4 m_unk0x64; // 0x64 +}; + +// SYNTHETIC: LEGO1 0x1000d1d0 +// LegoActionControlPresenter::`scalar deleting destructor' + +#endif // LEGOACTIONCONTROLPRESENTER_H diff --git a/LEGO1/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h similarity index 72% rename from LEGO1/legoactor.h rename to LEGO1/lego/legoomni/include/legoactor.h index c8380177..0f048619 100644 --- a/LEGO1/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -9,20 +9,24 @@ class LegoActor : public LegoEntity { public: LegoActor(); + ~LegoActor() override; // FUNCTION: LEGO1 0x1002d210 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0124 + // STRING: LEGO1 0x100f0124 return "LegoActor"; } // FUNCTION: LEGO1 0x1002d220 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoActor::ClassName()) || LegoEntity::IsA(p_name); } + void ParseAction(char*) override; // vtable+0x20 + void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) override; // vtable+0x24 + // FUNCTION: LEGO1 0x10002cc0 virtual MxFloat VTable0x50() { return m_unk0x68; } // vtable+0x50 // FUNCTION: LEGO1 0x10002cd0 @@ -43,4 +47,7 @@ class LegoActor : public LegoEntity { MxU8 m_unk0x74; // 0x74 }; +// SYNTHETIC: LEGO1 0x1002d300 +// LegoActor::`scalar deleting destructor' + #endif // LEGOACTOR_H diff --git a/LEGO1/legoactorpresenter.h b/LEGO1/lego/legoomni/include/legoactorpresenter.h similarity index 50% rename from LEGO1/legoactorpresenter.h rename to LEGO1/lego/legoomni/include/legoactorpresenter.h index 359960dc..9c3b35bf 100644 --- a/LEGO1/legoactorpresenter.h +++ b/LEGO1/lego/legoomni/include/legoactorpresenter.h @@ -7,18 +7,27 @@ // SIZE 0x50 class LegoActorPresenter : public LegoEntityPresenter { public: + ~LegoActorPresenter() override{}; + // FUNCTION: LEGO1 0x1000cb10 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f06a4 + // STRING: LEGO1 0x100f06a4 return "LegoActorPresenter"; } // FUNCTION: LEGO1 0x1000cb20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoActorPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void ParseExtra() override; // vtable+0x30 }; +// SYNTHETIC: LEGO1 0x1000cc30 +// LegoActorPresenter::`scalar deleting destructor' + #endif // LEGOACTORPRESENTER_H diff --git a/LEGO1/legoanimactor.h b/LEGO1/lego/legoomni/include/legoanimactor.h similarity index 100% rename from LEGO1/legoanimactor.h rename to LEGO1/lego/legoomni/include/legoanimactor.h diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h new file mode 100644 index 00000000..94cb5b86 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -0,0 +1,47 @@ +#ifndef LEGOANIMATIONMANAGER_H +#define LEGOANIMATIONMANAGER_H + +#include "decomp.h" +#include "mxcore.h" + +// VTABLE: LEGO1 0x100d8c18 +// SIZE 0x500 +class LegoAnimationManager : public MxCore { +public: + LegoAnimationManager(); + ~LegoAnimationManager() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1005ec80 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f7508 + return "LegoAnimationManager"; + } + + // FUNCTION: LEGO1 0x1005ec90 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); + } + + void FUN_1005ee80(MxBool); + void FUN_1005ef10(); + void FUN_1005f0b0(); + void FUN_1005f6d0(MxBool); + void FUN_1005f720(undefined4); + void FUN_10061010(undefined4); + void FUN_10064670(MxBool); + + static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig); + + // SYNTHETIC: LEGO1 0x1005ed10 + // LegoAnimationManager::`scalar deleting destructor' + +private: + void Init(); +}; + +#endif // LEGOANIMATIONMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h new file mode 100644 index 00000000..c79c8043 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h @@ -0,0 +1,41 @@ +#ifndef LEGOANIMMMPRESENTER_H +#define LEGOANIMMMPRESENTER_H + +#include "mxcompositepresenter.h" + +// VTABLE: LEGO1 0x100d7de8 +// SIZE 0x74 +class LegoAnimMMPresenter : public MxCompositePresenter { +public: + LegoAnimMMPresenter(); + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x1004a950 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f046c + return "LegoAnimMMPresenter"; + } + + // FUNCTION: LEGO1 0x1004a960 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoAnimMMPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void DoneTickle() override; // vtable+0x2c + void ParseExtra() override; // vtable+0x30 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 + + // SYNTHETIC: LEGO1 0x1004aa40 + // LegoAnimMMPresenter::`scalar deleting destructor' +}; + +#endif // LEGOANIMMMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoanimpresenter.h b/LEGO1/lego/legoomni/include/legoanimpresenter.h new file mode 100644 index 00000000..221dfeb0 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -0,0 +1,102 @@ +#ifndef LEGOANIMPRESENTER_H +#define LEGOANIMPRESENTER_H + +#include "lego/sources/misc/legostorage.h" +#include "lego/sources/misc/legotree.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxvideopresenter.h" + +class LegoWorld; +class LegoAnimClass; + +// VTABLE: LEGO1 0x100d90c8 +// SIZE 0xc0 +class LegoAnimPresenter : public MxVideoPresenter { +public: + LegoAnimPresenter(); + ~LegoAnimPresenter() override; + + // FUNCTION: LEGO1 0x10068530 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f071c + return "LegoAnimPresenter"; + } + + // FUNCTION: LEGO1 0x10068540 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoAnimPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + virtual MxResult VTable0x88(MxStreamChunk* p_chunk); // vtable+0x88 + + inline LegoAnimClass* GetUnknown0x64() { return m_unk0x64; } + + const char* GetActionObjectName(); + +protected: + 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 0x100db8d8 +// SIZE 0x18 +class LegoAnimClass : public LegoTree { +public: + LegoAnimClass(); + ~LegoAnimClass() override; + + LegoResult Write(LegoStorage* p_storage) override; // vtable+0x08 + LegoTreeNodeData* CreateData() override; // vtable+0x0c + virtual MxResult VTable0x10(LegoMemory* p_stream, MxS32); // vtable+0x10 + + inline MxLong GetUnknown0x8() { return m_unk0x08; } + +private: + MxLong m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + undefined4 m_unk0x10; // 0x10 + undefined4 m_unk0x14; // 0x14 +}; + +// SYNTHETIC: LEGO1 0x100a0ba0 +// LegoAnimClass::`scalar deleting destructor' + +#endif // LEGOANIMPRESENTER_H diff --git a/LEGO1/legobackgroundcolor.h b/LEGO1/lego/legoomni/include/legobackgroundcolor.h similarity index 64% rename from LEGO1/legobackgroundcolor.h rename to LEGO1/lego/legoomni/include/legobackgroundcolor.h index c11508bc..672e39be 100644 --- a/LEGO1/legobackgroundcolor.h +++ b/LEGO1/lego/legoomni/include/legobackgroundcolor.h @@ -7,8 +7,8 @@ // SIZE 0x30 class LegoBackgroundColor : public MxVariable { public: - __declspec(dllexport) LegoBackgroundColor(const char* p_key, const char* p_value); - virtual void SetValue(const char* p_colorString) override; + LegoBackgroundColor(const char* p_key, const char* p_value); + void SetValue(const char* p_colorString) override; private: float m_h; diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h new file mode 100644 index 00000000..4559d41d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -0,0 +1,34 @@ +#ifndef LEGOBUILDINGMANAGER_H +#define LEGOBUILDINGMANAGER_H + +#include "mxcore.h" + +// VTABLE: LEGO1 0x100d6f50 +// SIZE 0x30 +class LegoBuildingManager : public MxCore { +public: + LegoBuildingManager(); + ~LegoBuildingManager() override; + + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1002f930 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f37d0 + return "LegoBuildingManager"; + } + + static void configureLegoBuildingManager(MxS32); + + void FUN_1002fa00(); + void FUN_1002fb30(); + + // SYNTHETIC: LEGO1 0x1002f940 + // LegoBuildingManager::`scalar deleting destructor' + +private: + void Init(); +}; + +#endif // LEGOBUILDINGMANAGER_H diff --git a/LEGO1/legocachesound.h b/LEGO1/lego/legoomni/include/legocachesound.h similarity index 54% rename from LEGO1/legocachesound.h rename to LEGO1/lego/legoomni/include/legocachesound.h index e045a719..2d7c932c 100644 --- a/LEGO1/legocachesound.h +++ b/LEGO1/lego/legoomni/include/legocachesound.h @@ -1,6 +1,7 @@ #ifndef LEGOCACHESOUND_H #define LEGOCACHESOUND_H +#include "decomp.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d4718 @@ -8,23 +9,28 @@ class LegoCacheSound : public MxCore { public: LegoCacheSound(); - virtual ~LegoCacheSound() override; // vtable+0x0 + ~LegoCacheSound() override; // vtable+0x00 // FUNCTION: LEGO1 0x10006580 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f01c4 + // STRING: LEGO1 0x100f01c4 return "LegoCacheSound"; } // FUNCTION: LEGO1 0x10006590 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoCacheSound::ClassName()) || MxCore::IsA(p_name); } + // SYNTHETIC: LEGO1 0x10006610 + // LegoCacheSound::`scalar deleting destructor' + private: void Init(); + + undefined m_padding0x08[0x80]; // 0x08 }; #endif // LEGOCACHESOUND_H diff --git a/LEGO1/lego/legoomni/include/legocachesoundlist.h b/LEGO1/lego/legoomni/include/legocachesoundlist.h new file mode 100644 index 00000000..25459911 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legocachesoundlist.h @@ -0,0 +1,104 @@ +#ifndef LEGOCACHESOUNDLIST_H +#define LEGOCACHESOUNDLIST_H + +#include "mxlist.h" +#include "mxtypes.h" + +class LegoCacheSound; + +// VTABLE: LEGO1 0x100d63b0 +// class MxCollection + +// VTABLE: LEGO1 0x100d63c8 +// class MxList + +// VTABLE: LEGO1 0x100d63e0 +// class MxPtrList + +// VTABLE: LEGO1 0x100d63f8 +// SIZE 0x18 +class LegoCacheSoundList : public MxPtrList { +public: + LegoCacheSoundList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} + + // FUNCTION: LEGO1 0x1001e650 + MxS8 Compare(LegoCacheSound* p_a, LegoCacheSound* p_b) override + { + return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; + } // vtable+0x14 +}; + +// VTABLE: LEGO1 0x100d64a0 +// class MxListCursor + +// VTABLE: LEGO1 0x100d6500 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d6518 +// SIZE 0x10 +class LegoCacheSoundListCursor : public MxPtrListCursor { +public: + LegoCacheSoundListCursor(LegoCacheSoundList* p_list) : MxPtrListCursor(p_list){}; +}; + +// TEMPLATE: LEGO1 0x1001e670 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1001e680 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1001e6d0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1001e6e0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x1001e770 +// MxPtrList::Destroy + +// SYNTHETIC: LEGO1 0x1001e780 +// LegoCacheSoundList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001e7f0 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x1001e840 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e8b0 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e960 +// MxPtrList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f350 +// LegoCacheSoundListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f3c0 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f410 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f480 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f4f0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001f540 +// LegoCacheSoundListCursor::~LegoCacheSoundListCursor + +// TEMPLATE: LEGO1 0x10020840 +// MxListCursor::MxListCursor + +// TEMPLATE: LEGO1 0x100224e0 +// MxList::InsertEntry + +// TEMPLATE: LEGO1 0x10022590 +// MxListCursor::Find + +// TEMPLATE: LEGO1 0x10022680 +// MxList::DeleteEntry + +#endif // LEGOCACHESOUNDLIST_H diff --git a/LEGO1/lego/legoomni/include/legocameracontroller.h b/LEGO1/lego/legoomni/include/legocameracontroller.h new file mode 100644 index 00000000..0032092b --- /dev/null +++ b/LEGO1/lego/legoomni/include/legocameracontroller.h @@ -0,0 +1,53 @@ +#ifndef LEGOCAMERACONTROLLER_H +#define LEGOCAMERACONTROLLER_H + +#include "legopointofviewcontroller.h" +#include "mxcore.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" +#include "mxpoint32.h" + +// VTABLE: LEGO1 0x100d57b0 +// SIZE 0xc8 +class LegoCameraController : public LegoPointOfViewController { +public: + LegoCameraController(); + ~LegoCameraController() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+04 + + // FUNCTION: LEGO1 0x10011ec0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0850 + return "LegoCameraController"; + } + + // FUNCTION: LEGO1 0x10011ed0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); + } + + 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(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: + MxMatrix m_matrix1; // 0x38 + MxMatrix m_matrix2; // 0x80 +}; + +// SYNTHETIC: LEGO1 0x10011f50 +// LegoCameraController::`scalar deleting destructor' + +#endif // LEGOCAMERACONTROLLER_H diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h new file mode 100644 index 00000000..03d0484d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -0,0 +1,39 @@ +#ifndef LEGOCARBUILD_H +#define LEGOCARBUILD_H + +#include "legoworld.h" + +// VTABLE: LEGO1 0x100d6658 +// SIZE 0x34c +class LegoCarBuild : public LegoWorld { +public: + LegoCarBuild(); + ~LegoCarBuild() override; + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x10022940 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0504 + return "LegoCarBuild"; + } + + // FUNCTION: LEGO1 0x10022950 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoCarBuild::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x10022a60 + // LegoCarBuild::`scalar deleting destructor' +}; + +#endif // LEGOCARBUILD_H diff --git a/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h new file mode 100644 index 00000000..fd5f8148 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h @@ -0,0 +1,36 @@ +#ifndef LEGOCARBUILDANIMPRESENTER_H +#define LEGOCARBUILDANIMPRESENTER_H + +#include "legoanimpresenter.h" + +// VTABLE: LEGO1 0x100d99e0 +// SIZE 0x150 +class LegoCarBuildAnimPresenter : public LegoAnimPresenter { +public: + LegoCarBuildAnimPresenter(); + ~LegoCarBuildAnimPresenter() override; // vtable+0x00 + + // FUNCTION: LEGO1 0x10078510 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f05ec + return "LegoCarBuildAnimPresenter"; + } + + // FUNCTION: LEGO1 0x10078520 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoCarBuildAnimPresenter::ClassName()) || LegoAnimPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + + // SYNTHETIC: LEGO1 0x10078660 + // LegoCarBuildAnimPresenter::`scalar deleting destructor' +}; + +#endif // LEGOCARBUILDANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legocarraceactor.h b/LEGO1/lego/legoomni/include/legocarraceactor.h new file mode 100644 index 00000000..3905be16 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legocarraceactor.h @@ -0,0 +1,34 @@ +#ifndef LEGOCARRACEACTOR_H +#define LEGOCARRACEACTOR_H + +#include "legoraceactor.h" + +// VTABLE: LEGO1 0x100da0d8 +class LegoCarRaceActor : public LegoRaceActor { +public: + // FUNCTION: LEGO1 0x10081650 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0568 + return "LegoCarRaceActor"; + } + + // FUNCTION: LEGO1 0x10081670 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name); + } + + void VTable0x68() override; // vtable+0x68 + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x90() override; // vtable+0x90 + MxS32 VTable0x94() override; // vtable+0x94 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c + + // SYNTHETIC: LEGO1 0x10081610 + // LegoCarRaceActor::`scalar deleting destructor' +}; + +#endif // LEGOCARRACEACTOR_H diff --git a/LEGO1/lego/legoomni/include/legocontrolmanager.h b/LEGO1/lego/legoomni/include/legocontrolmanager.h new file mode 100644 index 00000000..46719167 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legocontrolmanager.h @@ -0,0 +1,88 @@ +#ifndef LEGOCONTROLMANAGER_H +#define LEGOCONTROLMANAGER_H + +#include "legoeventnotificationparam.h" +#include "legoinputmanager.h" +#include "mxcore.h" +#include "mxpresenterlist.h" + +class MxControlPresenter; + +// VTABLE: LEGO1 0x100d6a98 +// SIZE 0x2c +class LegoControlManagerEvent : public LegoEventNotificationParam { +public: + inline LegoControlManagerEvent() : LegoEventNotificationParam() + { + m_clickedObjectId = -1; + m_clickedAtom = NULL; + } + + inline MxS32 GetClickedObjectId() const { return m_clickedObjectId; } + inline const char* GetClickedAtom() const { return m_clickedAtom; } + inline MxS16 GetUnknown0x28() const { return m_unk0x28; } + + inline void SetClickedObjectId(MxS32 p_clickedObjectId) { m_clickedObjectId = p_clickedObjectId; } + inline void SetClickedAtom(const char* p_clickedAtom) { m_clickedAtom = p_clickedAtom; } + inline void SetUnknown0x28(MxS16 p_unk0x28) { m_unk0x28 = p_unk0x28; } + +private: + MxS32 m_clickedObjectId; // 0x20 + const char* m_clickedAtom; // 0x24 + MxS16 m_unk0x28; // 0x28 +}; + +// SYNTHETIC: LEGO1 0x10028bf0 +// LegoControlManagerEvent::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10028c60 +// LegoControlManagerEvent::~LegoControlManagerEvent + +// VTABLE: LEGO1 0x100d6a80 +class LegoControlManager : public MxCore { +public: + LegoControlManager(); + ~LegoControlManager() override; // vtable+0x00 + + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x10028cb0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f31b8 + return "LegoControlManager"; + } + + // FUNCTION: LEGO1 0x10028cc0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + 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); + MxBool FUN_10029210(LegoEventNotificationParam& p_param, MxPresenter* p_presenter); + void FUN_100293c0(undefined4, const char*, undefined2); + MxControlPresenter* FUN_100294e0(MxS32 p_x, MxS32 p_y); + MxBool FUN_10029630(); + MxBool FUN_10029750(); + void FUN_100292e0(); + + inline undefined4 GetUnknown0x0c() { return m_unk0x0c; } + inline undefined GetUnknown0x10() { return m_unk0x10; } + + // SYNTHETIC: LEGO1 0x10028d40 + // LegoControlManager::`scalar deleting destructor' + +private: + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + MxBool m_unk0x10; // 0x10 + MxPresenter* m_unk0x14; // 0x14 + LegoControlManagerEvent m_event; // 0x18 + MxPresenterList* m_presenterList; // 0x44 + LegoNotifyList m_notifyList; // 0x48 +}; + +#endif // LEGOCONTROLMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h new file mode 100644 index 00000000..e132a113 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -0,0 +1,87 @@ +#ifndef LEGOENTITY_H +#define LEGOENTITY_H + +#include "decomp.h" +#include "extra.h" +#include "mxdsaction.h" +#include "mxentity.h" +#include "realtime/vector.h" +#include "roi/legoroi.h" + +// VTABLE: LEGO1 0x100d4858 +// SIZE 0x68 +class LegoEntity : public MxEntity { +public: + enum { + c_bit1 = 0x01, + c_bit2 = 0x02 + }; + + inline LegoEntity() { Init(); } + + // FUNCTION: LEGO1 0x1000c290 + ~LegoEntity() override { Destroy(TRUE); } + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x1000c2f0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0064 + return "LegoEntity"; + } + + // FUNCTION: LEGO1 0x1000c300 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoEntity::ClassName()) || MxEntity::IsA(p_name); + } + + virtual MxResult Create(MxDSAction& p_dsAction); // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c + virtual void ParseAction(char*); // vtable+0x20 + virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 + virtual void SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, const Vector3& p_up); // vtable+0x28 + virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c + + // FUNCTION: LEGO1 0x10001090 + virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 + + virtual void VTable0x34(); // vtable+0x34 + virtual void VTable0x38(); // vtable+0x38 + virtual void VTable0x3c(); // vtable+0x3c + virtual void VTable0x40(); // vtable+0x40 + virtual void VTable0x44(); // vtable+0x44 + virtual void VTable0x48(); // vtable+0x48 + virtual void VTable0x4c(); // vtable+0x4c + + void FUN_10010c30(); + void SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool); + + inline LegoROI* GetROI() { return m_roi; } + inline MxU8 GetFlags() { return m_flags; } + +protected: + void Init(); + void SetWorld(); + + 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" + 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..938c85d4 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoentitylist.h @@ -0,0 +1,101 @@ +#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 + 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' + +// TEMPLATE: LEGO1 0x1001f180 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f1d0 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f240 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f2b0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001f300 +// LegoEntityListCursor::~LegoEntityListCursor + +// TEMPLATE: LEGO1 0x100207d0 +// MxListCursor::MxListCursor + +// TEMPLATE: LEGO1 0x10022430 +// MxList::InsertEntry + +// TEMPLATE: LEGO1 0x10022630 +// MxList::DeleteEntry + +#endif // LEGOENTITYLIST_H diff --git a/LEGO1/lego/legoomni/include/legoentitypresenter.h b/LEGO1/lego/legoomni/include/legoentitypresenter.h new file mode 100644 index 00000000..565e7878 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoentitypresenter.h @@ -0,0 +1,48 @@ +#ifndef LEGOENTITYPRESENTER_H +#define LEGOENTITYPRESENTER_H + +#include "mxcompositepresenter.h" + +class LegoEntity; + +// VTABLE: LEGO1 0x100d8398 +// SIZE 0x50 +class LegoEntityPresenter : public MxCompositePresenter { +public: + LegoEntityPresenter(); + ~LegoEntityPresenter() override; // vtable+0x00 + + // FUNCTION: LEGO1 0x100534b0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f06b8 + return "LegoEntityPresenter"; + } + + // FUNCTION: LEGO1 0x100534c0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoEntityPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + void Destroy() override; // vtable+0x38 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + virtual void Init(); // vtable+0x68 + virtual undefined4 SetEntity(LegoEntity* p_entity); // vtable+0x6c + + void SetEntityLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up); + + // SYNTHETIC: LEGO1 0x100535a0 + // LegoEntityPresenter::`scalar deleting destructor' + +private: + void Destroy(MxBool p_fromDestructor); + +protected: + LegoEntity* m_entity; // 0x4c +}; + +#endif // LEGOENTITYPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h new file mode 100644 index 00000000..a9c13632 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h @@ -0,0 +1,61 @@ +#ifndef LEGOEVENTNOTIFICATIONPARAM_H +#define LEGOEVENTNOTIFICATIONPARAM_H + +#include "mxnotificationparam.h" +#include "mxtypes.h" +#include "roi/legoroi.h" + +#include + +// VTABLE: LEGO1 0x100d6aa0 +// SIZE 0x20 +class LegoEventNotificationParam : public MxNotificationParam { +public: + // FUNCTION: LEGO1 0x10028690 + MxNotificationParam* Clone() override + { + LegoEventNotificationParam* clone = + new LegoEventNotificationParam(m_type, m_sender, m_modifier, m_x, m_y, m_key); + clone->m_roi = m_roi; + return clone; + } // vtable+0x04 + + inline LegoEventNotificationParam() : MxNotificationParam(c_notificationType0, NULL) {} + inline LegoEventNotificationParam( + NotificationId p_type, + MxCore* p_sender, + MxU8 p_modifier, + MxS32 p_x, + MxS32 p_y, + MxU8 p_key + ) + : MxNotificationParam(p_type, p_sender), m_modifier(p_modifier), m_x(p_x), m_y(p_y), m_key(p_key), m_roi(NULL) + { + } + + inline MxU8 GetModifier() { return m_modifier; } + inline MxU8 GetKey() const { return m_key; } + inline MxS32 GetX() const { return m_x; } + inline MxS32 GetY() const { return m_y; } + + inline void SetROI(LegoROI* p_roi) { m_roi = p_roi; } + inline void SetModifier(MxU8 p_modifier) { m_modifier = p_modifier; } + inline void SetKey(MxU8 p_key) { m_key = p_key; } + inline void SetX(MxS32 p_x) { m_x = p_x; } + inline void SetY(MxS32 p_y) { m_y = p_y; } + +protected: + MxU8 m_modifier; // 0x0c + MxS32 m_x; // 0x10 + MxS32 m_y; // 0x14 + MxU8 m_key; // 0x18 + LegoROI* m_roi; // 0x1c +}; + +// SYNTHETIC: LEGO1 0x10028770 +// LegoEventNotificationParam::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100287e0 +// LegoEventNotificationParam::~LegoEventNotificationParam + +#endif // LEGOEVENTNOTIFICATIONPARAM_H diff --git a/LEGO1/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h similarity index 82% rename from LEGO1/legoextraactor.h rename to LEGO1/lego/legoomni/include/legoextraactor.h index 6b8a9198..87a0ab21 100644 --- a/LEGO1/legoextraactor.h +++ b/LEGO1/lego/legoomni/include/legoextraactor.h @@ -7,9 +7,9 @@ class LegoExtraActor : public LegoAnimActor { public: // FUNCTION: LEGO1 0x1002b7a0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f3204 + // STRING: LEGO1 0x100f3204 return "LegoExtraActor"; } diff --git a/LEGO1/lego/legoomni/include/legoflctexturepresenter.h b/LEGO1/lego/legoomni/include/legoflctexturepresenter.h new file mode 100644 index 00000000..70f8a309 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoflctexturepresenter.h @@ -0,0 +1,34 @@ +#ifndef LEGOFLCTEXTUREPRESENTER_H +#define LEGOFLCTEXTUREPRESENTER_H + +#include "decomp.h" +#include "mxflcpresenter.h" + +// VTABLE: LEGO1 0x100d89e0 +// SIZE 0x70 +class LegoFlcTexturePresenter : public MxFlcPresenter { +public: + LegoFlcTexturePresenter(); + + // FUNCTION: LEGO1 0x1005def0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0634 + return "LegoFlcTexturePresenter"; + } + + void StartingTickle() override; // vtable+0x1c + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void PutFrame() override; // vtable+0x6c + + // SYNTHETIC: LEGO1 0x1005df00 + // LegoFlcTexturePresenter::`scalar deleting destructor' + +private: + void Init(); + + undefined4 m_unk0x68; // 0x68 + undefined4 m_unk0x6c; // 0x6c +}; + +#endif // LEGOFLCTEXTUREPRESENTER_H diff --git a/LEGO1/legofullscreenmovie.h b/LEGO1/lego/legoomni/include/legofullscreenmovie.h similarity index 83% rename from LEGO1/legofullscreenmovie.h rename to LEGO1/lego/legoomni/include/legofullscreenmovie.h index f2cdaae4..2f2f7614 100644 --- a/LEGO1/legofullscreenmovie.h +++ b/LEGO1/lego/legoomni/include/legofullscreenmovie.h @@ -8,7 +8,7 @@ class LegoFullScreenMovie : public MxVariable { public: LegoFullScreenMovie(const char* p_key, const char* p_value); - virtual void SetValue(const char* p_option) override; + void SetValue(const char* p_option) override; }; #endif // LEGOFULLSCREENMOVIE_H diff --git a/LEGO1/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h similarity index 50% rename from LEGO1/legogamestate.h rename to LEGO1/lego/legoomni/include/legogamestate.h index 656b990c..0b45f11c 100644 --- a/LEGO1/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -2,10 +2,11 @@ #define LEGOGAMESTATE_H #include "decomp.h" +#include "lego/sources/misc/legostorage.h" #include "legobackgroundcolor.h" #include "legofullscreenmovie.h" -#include "legostream.h" #include "mxtypes.h" +#include "mxvariabletable.h" class LegoState; class MxVariable; @@ -19,34 +20,41 @@ struct ColorStringStruct { // SIZE 0x430 class LegoGameState { public: - __declspec(dllexport) LegoGameState(); - __declspec(dllexport) ~LegoGameState(); - __declspec(dllexport) MxResult Load(MxULong); - __declspec(dllexport) MxResult Save(MxULong); - __declspec(dllexport) void SerializePlayersInfo(MxS16); - __declspec(dllexport) void SerializeScoreHistory(MxS16 p_flags); - __declspec(dllexport) void SetSavePath(char*); + LegoGameState(); + ~LegoGameState(); + MxResult Load(MxULong); + MxResult Save(MxULong); + void SerializePlayersInfo(MxS16); + void SerializeScoreHistory(MxS16 p_flags); + void SetSavePath(char*); - LegoState* GetState(COMPAT_CONST char* p_stateName); - LegoState* CreateState(COMPAT_CONST char* p_stateName); + LegoState* GetState(const char* p_stateName); + LegoState* CreateState(const char* p_stateName); void GetFileSavePath(MxString* p_outPath, MxULong p_slotn); - void FUN_1003a720(MxU32); - void HandleAction(MxU32); + void StopArea(MxU32 p_area = 0); + void SwitchArea(MxU32 p_area); - inline MxU8 GetUnknownC() { return m_unk0xc; } + inline MxU8 GetUnknownC() { return m_unk0x0c; } inline MxU32 GetUnknown10() { return m_unk0x10; } inline MxS32 GetCurrentAct() { return m_currentAct; } - inline undefined4 GetUnknown424() { return m_unk0x424; } + inline MxU32 GetCurrentArea() { return m_currentArea; } + inline MxU32 GetPreviousArea() { return m_previousArea; } + inline MxU32 GetUnknown0x42c() { return m_unk0x42c; } + inline void SetDirty(MxBool p_dirty) { m_isDirty = p_dirty; } - inline void SetUnknown424(undefined4 p_unk0x424) { m_unk0x424 = p_unk0x424; } + inline void SetCurrentArea(MxU32 p_currentArea) { m_currentArea = p_currentArea; } + inline void SetPreviousArea(MxU32 p_previousArea) { m_previousArea = p_previousArea; } + inline void SetUnknown0x0c(MxU8 p_unk0x0c) { m_unk0x0c = p_unk0x0c; } void SetSomeEnumState(undefined4 p_state); void FUN_1003ceb0(); + void FUN_10039780(MxU8); + void FUN_10039940(); struct ScoreStruct { void WriteScoreHistory(); - void FUN_1003ccf0(LegoFileStream&); + void FUN_1003ccf0(LegoFile&); MxU16 m_unk0x00; undefined m_unk0x02[0x2c][20]; @@ -54,13 +62,15 @@ class LegoGameState { private: void RegisterState(LegoState* p_state); - MxResult WriteEndOfVariables(LegoStream* p_stream); + MxResult WriteVariable(LegoStorage* p_stream, MxVariableTable* p_from, const char* p_variableName); + MxResult WriteEndOfVariables(LegoStorage* p_stream); + MxS32 ReadVariable(LegoStorage* p_stream, MxVariableTable* p_to); void SetROIHandlerFunction(); - char* m_savePath; // 0x0 - MxS16 m_stateCount; // 0x4 - LegoState** m_stateArray; // 0x8 - MxU8 m_unk0xc; // 0xc + char* m_savePath; // 0x00 + MxS16 m_stateCount; // 0x04 + LegoState** m_stateArray; // 0x08 + MxU8 m_unk0x0c; // 0x0c MxU32 m_unk0x10; // 0x10 MxS32 m_currentAct; // 0x14 LegoBackgroundColor* m_backgroundColor; // 0x18 @@ -71,8 +81,8 @@ class LegoGameState { ScoreStruct m_unk0xa6; // 0xa6 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 + MxU32 m_currentArea; // 0x424 + MxU32 m_previousArea; // 0x428 undefined4 m_unk0x42c; // 0x42c }; diff --git a/LEGO1/lego/legoomni/include/legohideanimpresenter.h b/LEGO1/lego/legoomni/include/legohideanimpresenter.h new file mode 100644 index 00000000..37b8c475 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legohideanimpresenter.h @@ -0,0 +1,44 @@ +#ifndef LEGOHIDEANIMPRESENTER_H +#define LEGOHIDEANIMPRESENTER_H + +#include "decomp.h" +#include "legoloopinganimpresenter.h" + +// VTABLE: LEGO1 0x100d9278 +// SIZE 0xc4 +class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { +public: + LegoHideAnimPresenter(); + ~LegoHideAnimPresenter() override; + + // FUNCTION: LEGO1 0x1006d880 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f06cc + return "LegoHideAnimPresenter"; + } + + // FUNCTION: LEGO1 0x1006d890 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x18 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + +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 new file mode 100644 index 00000000..69a9dc64 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -0,0 +1,228 @@ +#ifndef LEGOINPUTMANAGER_H +#define LEGOINPUTMANAGER_H + +#include "decomp.h" +#include "legoeventnotificationparam.h" +#include "legoworld.h" +#include "mxlist.h" +#include "mxpresenter.h" +#include "mxqueue.h" + +#include + +class LegoControlManager; + +extern MxS32 g_unk0x100f31b0; +extern const char* g_unk0x100f31b4; + +// VTABLE: LEGO1 0x100d87b8 +// class MxCollection + +// VTABLE: LEGO1 0x100d87d0 +// class MxList + +// VTABLE: LEGO1 0x100d87e8 +// class MxQueue + +// VTABLE: LEGO1 0x100d8800 +// SIZE 0x18 +class LegoEventQueue : public MxQueue {}; + +// VTABLE: LEGO1 0x100d6a20 +// class MxCollection + +// VTABLE: LEGO1 0x100d6a38 +// class MxList + +// VTABLE: LEGO1 0x100d6a50 +// class MxPtrList + +// VTABLE: LEGO1 0x100d6a68 +// SIZE 0x18 +class LegoNotifyList : public MxPtrList { +protected: + // FUNCTION: LEGO1 0x10028830 + MxS8 Compare(MxCore* p_element1, MxCore* p_element2) override + { + return p_element1 == p_element2 ? 0 : p_element1 < p_element2 ? -1 : 1; + } // vtable+0x14 + +public: + LegoNotifyList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} +}; + +// VTABLE: LEGO1 0x100d6ac0 +// class MxListCursor + +// VTABLE: LEGO1 0x100d6ad8 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d6aa8 +// SIZE 0x10 +class LegoNotifyListCursor : public MxPtrListCursor { +public: + LegoNotifyListCursor(LegoNotifyList* p_list) : MxPtrListCursor(p_list) {} +}; + +// VTABLE: LEGO1 0x100d8760 +// SIZE 0x338 +class LegoInputManager : public MxPresenter { +public: + LegoInputManager(); + ~LegoInputManager() override; + + void QueueEvent(NotificationId p_id, MxU8 p_modifier, MxLong p_x, MxLong p_y, MxU8 p_key); + void Register(MxCore*); + void UnRegister(MxCore*); + + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1005b8c0 + MxResult PutData() override { return SUCCESS; } // vtable+0x4c + + MxResult Create(HWND p_hwnd); + void Destroy() override; + void CreateAndAcquireKeyboard(HWND p_hwnd); + void ReleaseDX(); + MxResult GetJoystickId(); + MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, DWORD* p_buttonsState, MxU32* p_povPosition); + void StartAutoDragTimer(); + void StopAutoDragTimer(); + void EnableInputProcessing(); + void SetCamera(LegoCameraController* p_camera); + void ClearCamera(); + void SetWorld(LegoWorld* p_world); + 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 DisableInputProcessing() + { + m_unk0x88 = TRUE; + m_unk0x336 = FALSE; + } + + inline LegoControlManager* GetControlManager() { return m_controlManager; } + inline LegoWorld* GetWorld() { return m_world; } + inline LegoCameraController* GetCamera() { return m_camera; } + + void ProcessEvents(); + MxBool ProcessOneEvent(LegoEventNotificationParam& p_param); + MxBool FUN_1005cdf0(LegoEventNotificationParam& p_param); + + // SYNTHETIC: LEGO1 0x1005b8d0 + // LegoInputManager::`scalar deleting destructor' + +private: + MxCriticalSection m_criticalSection; // 0x58 + LegoNotifyList* m_keyboardNotifyList; // 0x5c + LegoCameraController* m_camera; // 0x60 + LegoWorld* m_world; // 0x64 + LegoEventQueue* m_eventQueue; // 0x68 + undefined4 m_unk0x6c; // 0x6c + undefined4 m_unk0x70; // 0x70 + undefined4 m_unk0x74; // 0x74 + UINT m_autoDragTimerID; // 0x78 + UINT m_autoDragTime; // 0x7c + undefined m_unk0x80; // 0x80 + undefined m_unk0x81; // 0x81 + LegoControlManager* m_controlManager; // 0x84 + MxBool m_unk0x88; // 0x88 + IDirectInput* m_directInput; // 0x8c + IDirectInputDevice* m_directInputDevice; // 0x90 + undefined m_unk0x94; // 0x94 + undefined4 m_unk0x98; // 0x98 + undefined m_unk0x9c[0xf8]; // 0x9c + undefined m_unk0x194; // 0x194 + MxBool m_unk0x195; // 0x195 + MxS32 m_joyid; // 0x198 + MxS32 m_joystickIndex; // 0x19c + JOYCAPS m_joyCaps; // 0x200 + MxBool m_useJoystick; // 0x334 + MxBool m_unk0x335; // 0x335 + MxBool m_unk0x336; // 0x336 +}; + +// TEMPLATE: LEGO1 0x10028850 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x10028860 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x100288b0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x100288c0 +// MxList::~MxList + +// SYNTHETIC: LEGO1 0x10028950 +// LegoNotifyList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x100289c0 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x10028a10 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10028a80 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10028b30 +// MxPtrList::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x10028ba0 +// LegoNotifyList::~LegoNotifyList + +// SYNTHETIC: LEGO1 0x10028fd0 +// LegoNotifyListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x10029040 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x10029090 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x10029100 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x10029170 +// MxListCursor::~MxListCursor + +// TEMPLATE: LEGO1 0x100291c0 +// LegoNotifyListCursor::~LegoNotifyListCursor + +// TEMPLATE: LEGO1 0x1005bb80 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1005bbe0 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1005bc30 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1005bc80 +// MxList::~MxList + +// SYNTHETIC: LEGO1 0x1005bd50 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1005bdc0 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1005beb0 +// LegoEventQueue::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1005bf20 +// MxQueue::~MxQueue + +// SYNTHETIC: LEGO1 0x1005bf70 +// MxQueue::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1005d010 +// MxListEntry::GetValue + +#endif // LEGOINPUTMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legojetski.h b/LEGO1/lego/legoomni/include/legojetski.h new file mode 100644 index 00000000..1ec0b9bb --- /dev/null +++ b/LEGO1/lego/legoomni/include/legojetski.h @@ -0,0 +1,36 @@ +#ifndef LEGOJETSKI_H +#define LEGOJETSKI_H + +#include "legojetskiraceactor.h" + +// VTABLE: LEGO1 0x100d5a40 +class LegoJetski : public LegoJetskiRaceActor { +public: + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x10013e80 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f053c + return "LegoJetski"; + } + + // FUNCTION: LEGO1 0x10013ea0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoJetski::ClassName()) || LegoJetskiRaceActor::IsA(p_name); + } + + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x94() override; // vtable+0x94 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c + + // SYNTHETIC: LEGO1 0x10013e20 + // LegoJetski::`scalar deleting destructor' +}; + +#endif // LEGOJETSKI_H diff --git a/LEGO1/legojetskiraceactor.h b/LEGO1/lego/legoomni/include/legojetskiraceactor.h similarity index 54% rename from LEGO1/legojetskiraceactor.h rename to LEGO1/lego/legoomni/include/legojetskiraceactor.h index d2ab88d8..fd7d88bb 100644 --- a/LEGO1/legojetskiraceactor.h +++ b/LEGO1/lego/legoomni/include/legojetskiraceactor.h @@ -7,9 +7,9 @@ class LegoJetskiRaceActor : public LegoCarRaceActor { public: // FUNCTION: LEGO1 0x10081d80 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0554 + // STRING: LEGO1 0x100f0554 return "LegoJetskiRaceActor"; } @@ -18,6 +18,14 @@ class LegoJetskiRaceActor : public LegoCarRaceActor { { return !strcmp(p_name, LegoJetskiRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); } + + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c + + // SYNTHETIC: LEGO1 0x10081d40 + // LegoJetskiRaceActor::`scalar deleting destructor' }; #endif // LEGOJETSKIRACEACTOR_H diff --git a/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h b/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h new file mode 100644 index 00000000..cb6ad80a --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoloadcachesoundpresenter.h @@ -0,0 +1,43 @@ +#ifndef LEGOLOADCACHESOUNDPRESENTER_H +#define LEGOLOADCACHESOUNDPRESENTER_H + +#include "decomp.h" +#include "mxwavepresenter.h" + +class LegoCacheSound; + +// VTABLE: LEGO1 0x100d5fa8 +// SIZE 0x90 +class LegoLoadCacheSoundPresenter : public MxWavePresenter { +public: + LegoLoadCacheSoundPresenter(); + ~LegoLoadCacheSoundPresenter() override; + + // FUNCTION: LEGO1 0x10018450 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f05a0 + return "LegoLoadCacheSoundPresenter"; + } + + void ReadyTickle() override; // vtable+0x18 + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + MxResult PutData() override; // vtable+0x4c + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + + LegoCacheSound* m_cacheSound; // 0x6c + undefined* m_unk0x70; // 0x70 + undefined* m_unk0x74; // 0x74 + undefined4 m_unk0x78; // 0x78 + undefined m_unk0x7c; // 0x7c + PCMWAVEFORMAT m_pcmWaveFormat; // 0x7d +}; + +// SYNTHETIC: LEGO1 0x10018460 +// LegoLoadCacheSoundPresenter::`scalar deleting destructor' + +#endif // LEGOLOADCACHESOUNDPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h new file mode 100644 index 00000000..2a78176d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h @@ -0,0 +1,59 @@ +#ifndef LEGOLOCOMOTIONANIMPRESENTER_H +#define LEGOLOCOMOTIONANIMPRESENTER_H + +#include "legoloopinganimpresenter.h" + +// VTABLE: LEGO1 0x100d9170 +// SIZE 0xd8 +class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { +public: + LegoLocomotionAnimPresenter(); + ~LegoLocomotionAnimPresenter() override; + + // FUNCTION: LEGO1 0x1006ce50 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f06e4 + return "LegoLocomotionAnimPresenter"; + } + + // FUNCTION: LEGO1 0x1006ce60 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || LegoLoopingAnimPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + void PutFrame() override; // vtable+0x6c + MxResult VTable0x88(MxStreamChunk* p_chunk) override; // vtable+0x88 + + // SYNTHETIC: LEGO1 0x1006cfe0 + // LegoLocomotionAnimPresenter::`scalar deleting destructor' + + inline void DecrementUnknown0xd4() + { + if (m_unk0xd4) { + --m_unk0xd4; + } + } + + inline undefined2 GetUnknown0xd4() { return m_unk0xd4; } + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + + undefined4 m_unk0xc0; // 0xc0 + undefined4* m_unk0xc4; // 0xc4 + MxCore* m_unk0xc8; // 0xc8 + MxS32 m_unk0xcc; // 0xcc + MxS32 m_unk0xd0; // 0xd0 + undefined2 m_unk0xd4; // 0xd4 +}; + +#endif // LEGOLOCOMOTIONANIMPRESENTER_H diff --git a/LEGO1/legoloopinganimpresenter.h b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h similarity index 60% rename from LEGO1/legoloopinganimpresenter.h rename to LEGO1/lego/legoomni/include/legoloopinganimpresenter.h index 7f033a98..50815015 100644 --- a/LEGO1/legoloopinganimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h @@ -8,9 +8,9 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { public: // FUNCTION: LEGO1 0x1000c9a0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0700 + // STRING: LEGO1 0x100f0700 return "LegoLoopingAnimPresenter"; } @@ -19,6 +19,15 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { { return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); } + + void StreamingTickle() override; // vtable+0x20 + void PutFrame() override; // vtable+0x6c }; +// SYNTHETIC: LEGO1 0x1006d000 +// LegoLoopingAnimPresenter::~LegoLoopingAnimPresenter + +// SYNTHETIC: LEGO1 0x1000f440 +// LegoLoopingAnimPresenter::`scalar deleting destructor' + #endif // LEGOLOOPINGANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legometerpresenter.h b/LEGO1/lego/legoomni/include/legometerpresenter.h new file mode 100644 index 00000000..378c0574 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legometerpresenter.h @@ -0,0 +1,36 @@ +#ifndef LEGOMETERPRESENTER_H +#define LEGOMETERPRESENTER_H + +#include "mxstillpresenter.h" + +// VTABLE: LEGO1 0x100d7ac8 +// SIZE 0x94 (from 0x1000a163) +class LegoMeterPresenter : public MxStillPresenter { +public: + LegoMeterPresenter(); + ~LegoMeterPresenter() override; + + // MxStillPresenter's `::ClassName` and `::IsA` are used. + + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + 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 new file mode 100644 index 00000000..c94be713 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legomodelpresenter.h @@ -0,0 +1,42 @@ +#ifndef LEGOMODELPRESENTER_H +#define LEGOMODELPRESENTER_H + +#include "mxvideopresenter.h" + +class AutoROI; + +// VTABLE: LEGO1 0x100d4e50 +// SIZE 0x6c (discovered through inline constructor at 0x10009ae6) +class LegoModelPresenter : public MxVideoPresenter { +public: + static void configureLegoModelPresenter(MxS32 p_modelPresenterConfig); + + // FUNCTION: LEGO1 0x1000ccb0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f067c + return "LegoModelPresenter"; + } + + // FUNCTION: LEGO1 0x1000ccc0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void ParseExtra() override; // vtable+0x30 + void Destroy() override; // vtable+0x38 + + // SYNTHETIC: LEGO1 0x1000cdd0 + // LegoModelPresenter::`scalar deleting destructor' + +protected: + void Destroy(MxBool p_fromDestructor); + +private: + AutoROI* m_unk0x64; // 0x64 + MxBool m_addedToView; // 0x68 +}; + +#endif // LEGOMODELPRESENTER_H diff --git a/LEGO1/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h similarity index 82% rename from LEGO1/legonavcontroller.h rename to LEGO1/lego/legoomni/include/legonavcontroller.h index ffaf99cb..58ace217 100644 --- a/LEGO1/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -9,7 +9,7 @@ // SIZE 0x70 class LegoNavController : public MxCore { public: - __declspec(dllexport) static void GetDefaults( + static void GetDefaults( int* p_mouseDeadzone, float* p_movementMaxSpeed, float* p_turnMaxSpeed, @@ -22,7 +22,7 @@ class LegoNavController : public MxCore { float* p_rotationSensitivity, MxBool* p_turnUseVelocity ); - __declspec(dllexport) static void SetDefaults( + static void SetDefaults( int p_mouseDeadzone, float p_movementMaxSpeed, float p_turnMaxSpeed, @@ -37,12 +37,13 @@ class LegoNavController : public MxCore { ); LegoNavController(); - virtual ~LegoNavController() override; // vtable+0x0 + ~LegoNavController() override; // vtable+0x00 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x10054b80 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f66d8 + // STRING: LEGO1 0x100f66d8 return "LegoNavController"; } @@ -59,6 +60,11 @@ class LegoNavController : public MxCore { float CalculateNewAccel(int p_pos, int p_center, float p_maxAccel, int p_minAccel); float CalculateNewVel(float p_targetVel, float p_currentVel, float p_accel, float p_time); + inline void SetTrackDefaultParams(MxBool p_trackDefault) { m_trackDefault = p_trackDefault; } + + // SYNTHETIC: LEGO1 0x10054c10 + // LegoNavController::`scalar deleting destructor' + private: int m_hMax; int m_vMax; diff --git a/LEGO1/lego/legoomni/include/legonotify.h b/LEGO1/lego/legoomni/include/legonotify.h new file mode 100644 index 00000000..ed4218b2 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legonotify.h @@ -0,0 +1,11 @@ +#ifndef LEGONOTIFY_H +#define LEGONOTIFY_H + +enum LegoEventNotificationParamType { + c_lButtonState = 1, + c_rButtonState = 2, + c_modKey1 = 4, + c_modKey2 = 8, +}; + +#endif // LEGONOTIFY_H diff --git a/LEGO1/lego/legoomni/include/legoobjectfactory.h b/LEGO1/lego/legoomni/include/legoobjectfactory.h new file mode 100644 index 00000000..66006588 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoobjectfactory.h @@ -0,0 +1,120 @@ +#ifndef LEGOOBJECTFACTORY_H +#define LEGOOBJECTFACTORY_H + +#include "mxobjectfactory.h" + +#define FOR_LEGOOBJECTFACTORY_OBJECTS(X) \ + X(LegoModelPresenter) \ + X(LegoTexturePresenter) \ + X(LegoPhonemePresenter) \ + X(LegoFlcTexturePresenter) \ + X(LegoEntityPresenter) \ + X(LegoActorPresenter) \ + X(LegoWorldPresenter) \ + X(LegoWorld) \ + X(LegoPalettePresenter) \ + X(LegoPathPresenter) \ + X(LegoAnimPresenter) \ + X(LegoLoopingAnimPresenter) \ + X(LegoLocomotionAnimPresenter) \ + X(LegoHideAnimPresenter) \ + X(LegoPartPresenter) \ + X(LegoCarBuildAnimPresenter) \ + X(LegoActionControlPresenter) \ + X(MxVideoPresenter) \ + X(LegoLoadCacheSoundPresenter) \ + X(Lego3DWavePresenter) \ + X(LegoActor) \ + X(LegoPathActor) \ + X(LegoRaceCar) \ + X(LegoJetski) \ + /*X(JetskiRace) \*/ \ + X(LegoEntity) \ + X(LegoCarRaceActor) \ + X(LegoJetskiRaceActor) \ + X(LegoCarBuild) \ + X(Infocenter) \ + X(LegoAnimActor) \ + X(MxControlPresenter) \ + X(RegistrationBook) \ + X(HistoryBook) \ + X(ElevatorBottom) \ + X(InfocenterDoor) \ + X(Score) \ + X(ScoreState) \ + X(Hospital) \ + X(Isle) \ + X(Police) \ + X(GasStation) \ + X(LegoAct2) \ + X(LegoAct2State) \ + /*X(CarRace)*/ \ + X(HospitalState) \ + X(InfocenterState) \ + X(PoliceState) \ + X(GasStationState) \ + X(SkateBoard) \ + X(Helicopter) \ + X(HelicopterState) \ + X(DuneBuggy) \ + X(Pizza) \ + X(PizzaMissionState) \ + /*X(Act2Actor)*/ \ + /*X(Act2Brick)*/ \ + /*X(Act2GenActor)*/ \ + X(Act2PoliceStation) \ + X(Act3) \ + X(Act3State) \ + X(Doors) \ + X(LegoAnimMMPresenter) \ + X(RaceCar) \ + X(Jetski) \ + X(Bike) \ + X(Motocycle) \ + X(Ambulance) \ + X(AmbulanceMissionState) \ + X(TowTrack) \ + X(TowTrackMissionState) \ + /*X(Act3Cop)*/ \ + /*X(Act3Brickster)*/ \ + X(Act3Shark) \ + X(BumpBouy) \ + X(Act3Actor) \ + X(JetskiRaceState) \ + X(CarRaceState) \ + X(Act1State) \ + X(Pizzeria) \ + X(PizzeriaState) \ + X(InfoCenterEntity) \ + X(HospitalEntity) \ + X(GasStationEntity) \ + X(PoliceEntity) \ + X(BeachHouseEntity) \ + X(RaceStandsEntity) \ + X(JukeBoxEntity) \ + X(RadioState) \ + /*X(CaveEntity)*/ \ + /*X(JailEntity)*/ \ + X(MxCompositeMediaPresenter) \ + X(JukeBox) \ + X(JukeBoxState) \ + /*X(RaceSkel)*/ \ + X(AnimState) + +// VTABLE: LEGO1 0x100d4768 +class LegoObjectFactory : public MxObjectFactory { +public: + LegoObjectFactory(); + MxCore* Create(const char* p_name) override; // vtable 0x14 + void Destroy(MxCore* p_object) override; // vtable 0x18 + + // SYNTHETIC: LEGO1 0x10009000 + // LegoObjectFactory::`scalar deleting destructor' + +private: +#define X(V) MxAtomId m_id##V; + FOR_LEGOOBJECTFACTORY_OBJECTS(X) +#undef X +}; + +#endif // LEGOOBJECTFACTORY_H diff --git a/LEGO1/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h similarity index 54% rename from LEGO1/legoomni.h rename to LEGO1/lego/legoomni/include/legoomni.h index 69f6964a..ff973f95 100644 --- a/LEGO1/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -27,7 +27,8 @@ class MxAtomId; class MxBackgroundAudioManager; class MxDSFile; class MxTransitionManager; -class MxUnknown100dbdbc; +class ViewLODListManager; +class ViewManager; extern MxAtomId* g_copterScript; extern MxAtomId* g_dunecarScript; @@ -59,52 +60,60 @@ extern MxAtomId* g_creditsScript; extern MxAtomId* g_nocdSourceName; // VTABLE: LEGO1 0x100d8638 -// SIZE: 0x140 +// SIZE 0x140 class LegoOmni : public MxOmni { public: - __declspec(dllexport) void CreateBackgroundAudio(); - __declspec(dllexport) void RemoveWorld(const MxAtomId&, MxLong); - __declspec(dllexport) static int GetCurrPathInfo(LegoPathBoundary**, MxS32&); - __declspec(dllexport) static void CreateInstance(); - __declspec(dllexport) static LegoOmni* GetInstance(); + enum { + c_disableInput = 0x01, + c_disable3d = 0x02, + c_clearScreen = 0x04 + }; + + void CreateBackgroundAudio(); + void RemoveWorld(const MxAtomId&, MxLong); + static int GetCurrPathInfo(LegoPathBoundary**, MxS32&); + static void CreateInstance(); + static LegoOmni* GetInstance(); LegoOmni(); - virtual ~LegoOmni(); // vtable+00 + ~LegoOmni() override; // vtable+00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+04 + MxLong Notify(MxParam& p_param) override; // vtable+04 // FUNCTION: LEGO1 0x10058aa0 - inline virtual const char* ClassName() const override // vtable+0c + inline const char* ClassName() const override // vtable+0c { - // GLOBAL: LEGO1 0x100f671c + // STRING: LEGO1 0x100f671c return "LegoOmni"; } // FUNCTION: LEGO1 0x10058ab0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+10 + inline MxBool IsA(const char* p_name) const override // vtable+10 { return !strcmp(p_name, LegoOmni::ClassName()) || MxOmni::IsA(p_name); } - virtual void Init() override; // vtable+14 - virtual MxResult Create(MxOmniCreateParam& p_param) override; // vtable+18 - virtual void Destroy() override; // vtable+1c - virtual MxResult Start(MxDSAction* p_dsAction) override; // vtable+20 - virtual void DeleteObject(MxDSAction& p_dsAction) override; // vtable+24 - virtual MxBool DoesEntityExist(MxDSAction& p_dsAction) override; // vtable+28 - virtual MxEntity* FindWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) override; // vtable+30 - virtual void NotifyCurrentEntity(MxNotificationParam* p_param) override; // vtable+34 - virtual void StartTimer() override; // vtable+38 - virtual void StopTimer() override; // vtable+3c + void Init() override; // vtable+14 + MxResult Create(MxOmniCreateParam& p_param) override; // vtable+18 + void Destroy() override; // vtable+1c + MxResult Start(MxDSAction* p_dsAction) override; // vtable+20 + void DeleteObject(MxDSAction& p_dsAction) override; // vtable+24 + MxBool DoesEntityExist(MxDSAction& p_dsAction) override; // vtable+28 + MxEntity* AddToWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) override; // vtable+30 + void NotifyCurrentEntity(MxNotificationParam* p_param) override; // vtable+34 + void StartTimer() override; // vtable+38 + void StopTimer() override; // vtable+3c - LegoEntity* FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid); + LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid); + void AddWorld(LegoWorld* p_world); + void DeleteWorld(LegoWorld* p_world); + void FUN_1005b4f0(MxBool p_disable, MxU16 p_flags); LegoVideoManager* GetVideoManager() { return (LegoVideoManager*) m_videoManager; } LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } - LegoInputManager* GetInputManager() { return m_inputMgr; } GifManager* GetGifManager() { return m_gifManager; } - LegoWorld* GetCurrentOmniWorld() { return m_currentWorld; } + LegoWorld* GetCurrentWorld() { return m_currentWorld; } LegoNavController* GetNavController() { return m_navController; } IslePathActor* GetCurrentVehicle() { return m_currentVehicle; } LegoPlantManager* GetLegoPlantManager() { return m_plantManager; } @@ -114,15 +123,25 @@ 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 SetCurrentWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } + inline void SetExit(MxBool p_exit) { m_exit = p_exit; } + + inline void CloseMainWindow() { PostMessageA(m_windowHandle, WM_CLOSE, 0, 0); } + + // SYNTHETIC: LEGO1 0x10058b30 + // LegoOmni::`scalar deleting destructor' private: undefined4* m_unk0x68; // 0x68 - MxUnknown100dbdbc* m_renderMgr; // 0x6c + ViewLODListManager* m_viewLODListManager; // 0x6c LegoInputManager* m_inputMgr; // 0x70 GifManager* m_gifManager; // 0x74 LegoWorldList* m_worldList; // 0x78 LegoWorld* m_currentWorld; // 0x7c - MxBool m_unk0x80; // 0x80 + MxBool m_exit; // 0x80 LegoNavController* m_navController; // 0x84 IslePathActor* m_currentVehicle; // 0x88 LegoUnkSaveDataWriter* m_saveDataWriter; // 0x8c @@ -136,36 +155,36 @@ class LegoOmni : public MxOmni { MxBool m_unk0x13c; // 0x13c }; -__declspec(dllexport) MxBackgroundAudioManager* BackgroundAudioManager(); -__declspec(dllexport) MxDSObject* CreateStreamObject(MxDSFile*, MxS16); -__declspec(dllexport) LegoGameState* GameState(); -__declspec(dllexport) const char* GetNoCD_SourceName(); -__declspec(dllexport) LegoInputManager* InputManager(); -__declspec(dllexport) LegoOmni* Lego(); -__declspec(dllexport) void MakeSourceName(char*, const char*); -__declspec(dllexport) LegoEntity* PickEntity(MxLong, MxLong); -__declspec(dllexport) LegoROI* PickROI(MxLong, MxLong); -__declspec(dllexport) void SetOmniUserMessage(void (*)(const char*, int)); -__declspec(dllexport) LegoSoundManager* SoundManager(); -__declspec(dllexport) MxResult Start(MxDSAction*); -__declspec(dllexport) MxTransitionManager* TransitionManager(); -__declspec(dllexport) LegoVideoManager* VideoManager(); - +MxBackgroundAudioManager* BackgroundAudioManager(); +LegoGameState* GameState(); +const char* GetNoCD_SourceName(); +LegoInputManager* InputManager(); +LegoOmni* Lego(); +LegoEntity* PickEntity(MxLong, MxLong); +LegoROI* PickROI(MxLong, MxLong); +LegoSoundManager* SoundManager(); +MxTransitionManager* TransitionManager(); +LegoVideoManager* VideoManager(); LegoAnimationManager* AnimationManager(); +LegoNavController* NavController(); LegoBuildingManager* BuildingManager(); LegoControlManager* ControlManager(); -IslePathActor* GetCurrentVehicle(); +IslePathActor* CurrentVehicle(); +ViewManager* GetViewManager(); LegoPlantManager* PlantManager(); -MxBool KeyValueStringParse(char*, const char*, const char*); -LegoWorld* GetCurrentWorld(); +LegoWorld* CurrentWorld(); +LegoUnkSaveDataWriter* UnkSaveDataWriter(); GifManager* GetGifManager(); -void FUN_10015820(MxU32, MxU32); -LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid); +void FUN_10015820(MxBool p_disable, MxU16 p_flags); +void FUN_10015860(const char*, MxU8); +LegoWorld* FindWorld(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/legopalettepresenter.h b/LEGO1/lego/legoomni/include/legopalettepresenter.h similarity index 60% rename from LEGO1/legopalettepresenter.h rename to LEGO1/lego/legoomni/include/legopalettepresenter.h index e29b5391..c9e7fb81 100644 --- a/LEGO1/legopalettepresenter.h +++ b/LEGO1/lego/legoomni/include/legopalettepresenter.h @@ -10,12 +10,12 @@ class LegoPalettePresenter : public MxVideoPresenter { public: LegoPalettePresenter(); - virtual ~LegoPalettePresenter() override; // vtable+0x0 + ~LegoPalettePresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x10079f30 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f061c + // STRING: LEGO1 0x100f061c return "LegoPalettePresenter"; } @@ -25,13 +25,19 @@ class LegoPalettePresenter : public MxVideoPresenter { return !strcmp(p_name, ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void Destroy() override; // vtable+0x38 + void ReadyTickle() override; // vtable+0x18 + void Destroy() override; // vtable+0x38 + + MxResult ParsePalette(MxStreamChunk* p_chunk); + + // SYNTHETIC: LEGO1 0x1007a050 + // LegoPalettePresenter::`scalar deleting destructor' private: void Init(); void Destroy(MxBool p_fromDestructor); - MxPalette* m_palette; + MxPalette* m_palette; // 0x64 }; #endif // LEGOPALETTEPRESENTER_H diff --git a/LEGO1/legopartpresenter.h b/LEGO1/lego/legoomni/include/legopartpresenter.h similarity index 58% rename from LEGO1/legopartpresenter.h rename to LEGO1/lego/legoomni/include/legopartpresenter.h index 936d4876..ab27b0e9 100644 --- a/LEGO1/legopartpresenter.h +++ b/LEGO1/lego/legoomni/include/legopartpresenter.h @@ -8,9 +8,9 @@ class LegoPartPresenter : public MxMediaPresenter { public: // FUNCTION: LEGO1 0x1000cf70 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f05d8 + // STRING: LEGO1 0x100f05d8 return "LegoPartPresenter"; } @@ -20,7 +20,14 @@ class LegoPartPresenter : public MxMediaPresenter { return !strcmp(p_name, LegoPartPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - __declspec(dllexport) static void configureLegoPartPresenter(MxS32, MxS32); + void ReadyTickle() override; // vtable+0x18 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + + static void configureLegoPartPresenter(MxS32, MxS32); + + // SYNTHETIC: LEGO1 0x1000d060 + // LegoPartPresenter::`scalar deleting destructor' }; #endif // LEGOPARTPRESENTER_H diff --git a/LEGO1/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h similarity index 84% rename from LEGO1/legopathactor.h rename to LEGO1/lego/legoomni/include/legopathactor.h index f331e8ce..c2a2026c 100644 --- a/LEGO1/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -10,12 +10,12 @@ class LegoPathActor : public LegoActor { public: LegoPathActor(); - virtual ~LegoPathActor() override; + ~LegoPathActor() override; // FUNCTION: LEGO1 0x1000c430 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0114 + // STRING: LEGO1 0x100f0114 return "LegoPathActor"; } @@ -25,10 +25,11 @@ 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 + void ParseAction(char*) override; // vtable+0x20 + 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 @@ -66,6 +67,9 @@ class LegoPathActor : public LegoActor { inline void SetUnknownDC(MxU32 p_unk0xdc) { m_unk0xdc = p_unk0xdc; } + // SYNTHETIC: LEGO1 0x1002d800 + // LegoPathActor::`scalar deleting destructor' + protected: undefined m_unk0x78[0x64]; // 0x78 MxU32 m_unk0xdc; // 0xdc diff --git a/LEGO1/legopathboundary.h b/LEGO1/lego/legoomni/include/legopathboundary.h similarity index 100% rename from LEGO1/legopathboundary.h rename to LEGO1/lego/legoomni/include/legopathboundary.h diff --git a/LEGO1/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h similarity index 55% rename from LEGO1/legopathcontroller.h rename to LEGO1/lego/legoomni/include/legopathcontroller.h index 7bb6d30d..4ad0b03f 100644 --- a/LEGO1/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -8,14 +8,14 @@ class LegoPathController : public MxCore { public: LegoPathController(); - virtual ~LegoPathController() override; + ~LegoPathController() override { Destroy(); } - virtual MxResult Tickle() override; // vtable+08 + MxResult Tickle() override; // vtable+08 // FUNCTION: LEGO1 0x10045110 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f11b8 + // STRING: LEGO1 0x100f11b8 return "LegoPathController"; } @@ -24,6 +24,14 @@ class LegoPathController : public MxCore { { return !strcmp(p_name, LegoPathController::ClassName()) || MxCore::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x10045740 + // LegoPathController::`scalar deleting destructor' + + virtual void VTable0x14(); // vtable+0x14 + virtual void Destroy(); // vtable+0x18 + + void Enable(MxBool p_enable); }; #endif // LEGOPATHCONTROLLER_H diff --git a/LEGO1/legopathcontrollerlist.h b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h similarity index 53% rename from LEGO1/legopathcontrollerlist.h rename to LEGO1/lego/legoomni/include/legopathcontrollerlist.h index db31c2c4..af2642a2 100644 --- a/LEGO1/legopathcontrollerlist.h +++ b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h @@ -5,6 +5,12 @@ #include "mxlist.h" #include "mxtypes.h" +// VTABLE: LEGO1 0x100d6380 +// class MxCollection + +// VTABLE: LEGO1 0x100d6398 +// class MxList + // VTABLE: LEGO1 0x100d6320 // class MxPtrList @@ -15,17 +21,24 @@ class LegoPathControllerList : public MxPtrList { LegoPathControllerList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x1001d210 - virtual MxS8 Compare(LegoPathController* p_a, LegoPathController* p_b) override + MxS8 Compare(LegoPathController* p_a, LegoPathController* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 }; -// VTABLE: LEGO1 0x100d6380 -// class MxCollection +// VTABLE: LEGO1 0x100d6578 +// class MxListCursor -// VTABLE: LEGO1 0x100d6398 -// class MxList +// VTABLE: LEGO1 0x100d6548 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d6560 +// SIZE 0x10 +class LegoPathControllerListCursor : public MxPtrListCursor { +public: + LegoPathControllerListCursor(LegoPathControllerList* p_list) : MxPtrListCursor(p_list){}; +}; // TEMPLATE: LEGO1 0x1001d230 // MxCollection::Compare @@ -45,6 +58,12 @@ class LegoPathControllerList : public MxPtrList { // TEMPLATE: LEGO1 0x1001d3c0 // MxPtrList::Destroy +// SYNTHETIC: LEGO1 0x1001d3d0 +// LegoPathControllerList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001d440 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x1001d490 // MxCollection::`scalar deleting destructor' @@ -54,4 +73,25 @@ class LegoPathControllerList : public MxPtrList { // SYNTHETIC: LEGO1 0x1001d5b0 // MxPtrList::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x1001d620 +// LegoPathControllerList::~LegoPathControllerList + +// SYNTHETIC: LEGO1 0x1001f830 +// LegoPathControllerListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f8a0 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f8f0 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f960 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f9d0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001fa20 +// LegoPathControllerListCursor::~LegoPathControllerListCursor + #endif // LEGOPATHCONTROLLERLIST_H diff --git a/LEGO1/legopathpresenter.h b/LEGO1/lego/legoomni/include/legopathpresenter.h similarity index 54% rename from LEGO1/legopathpresenter.h rename to LEGO1/lego/legoomni/include/legopathpresenter.h index 8fe2d5ee..e6c5da14 100644 --- a/LEGO1/legopathpresenter.h +++ b/LEGO1/lego/legoomni/include/legopathpresenter.h @@ -8,11 +8,12 @@ class LegoPathPresenter : public MxMediaPresenter { public: LegoPathPresenter(); + ~LegoPathPresenter() override; // FUNCTION: LEGO1 0x100449a0 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0690 + // STRING: LEGO1 0x100f0690 return "LegoPathPresenter"; } @@ -22,10 +23,15 @@ class LegoPathPresenter : public MxMediaPresenter { return !strcmp(p_name, LegoPathPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + void ReadyTickle() override; // vtable+0x18 + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + + // SYNTHETIC: LEGO1 0x10044a90 + // LegoPathPresenter::`scalar deleting destructor' private: void Init(); diff --git a/LEGO1/legophonemepresenter.h b/LEGO1/lego/legoomni/include/legophonemepresenter.h similarity index 51% rename from LEGO1/legophonemepresenter.h rename to LEGO1/lego/legoomni/include/legophonemepresenter.h index 7b620723..db86a1e5 100644 --- a/LEGO1/legophonemepresenter.h +++ b/LEGO1/lego/legoomni/include/legophonemepresenter.h @@ -11,15 +11,23 @@ class LegoPhonemePresenter : public MxFlcPresenter { public: LegoPhonemePresenter(); - virtual ~LegoPhonemePresenter() override; // vtable+0x0 + ~LegoPhonemePresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x1004e310 - inline const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f064c + // STRING: LEGO1 0x100f064c return "LegoPhonemePresenter"; } + void StartingTickle() override; // vtable+0x1c + void EndAction() override; // vtable+0x40 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void PutFrame() override; // vtable+0x6c + + // SYNTHETIC: LEGO1 0x1004e320 + // LegoPhonemePresenter::`scalar deleting destructor' + private: void Init(); int m_unk0x68; diff --git a/LEGO1/lego/legoomni/include/legoplantmanager.h b/LEGO1/lego/legoomni/include/legoplantmanager.h new file mode 100644 index 00000000..bc96de5a --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -0,0 +1,33 @@ +#ifndef LEGOPLANTMANAGER_H +#define LEGOPLANTMANAGER_H + +#include "decomp.h" +#include "mxcore.h" + +// VTABLE: LEGO1 0x100d6758 +// SIZE 0x2c +class LegoPlantManager : public MxCore { +public: + LegoPlantManager(); + ~LegoPlantManager() override; // vtable+0x00 + + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x10026290 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f318c + return "LegoPlantManager"; + } + + void FUN_10026360(undefined4 p_world); + void FUN_100263a0(undefined4 p_und); + + // SYNTHETIC: LEGO1 0x100262a0 + // LegoPlantManager::`scalar deleting destructor' + +private: + void Init(); +}; + +#endif // LEGOPLANTMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legopointofviewcontroller.h b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h new file mode 100644 index 00000000..b6db3014 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h @@ -0,0 +1,103 @@ +#ifndef LEGOPOINTOFVIEWCONTROLLER_H +#define LEGOPOINTOFVIEWCONTROLLER_H + +#include "decomp.h" +#include "mxcore.h" +#include "mxpoint32.h" + +#include + +class Lego3DView; +class LegoEntity; +class LegoNavController; + +////////////////////////////////////////////////////////////////////////////// +// +// LegoMouseController + +// VTABLE: LEGO1 0x100d8dd8 +// SIZE 0x20 +class LegoMouseController : public MxCore { +public: + LegoMouseController(); + ~LegoMouseController() override; + + virtual void LeftDown(int, int); // vtable+0x14 + virtual void LeftDrag(int, int); // vtable+0x18 + virtual void LeftUp(int, int); // vtable+0x1c + virtual void RightDown(int, int); // vtable+0x20 + virtual void RightDrag(int, int); // vtable+0x24 + virtual void RightUp(int, int); // vtable+0x28 + +private: + BOOL m_isButtonDown; // 0x08 + undefined4 m_unk0x0c; // 0x0c + MxDouble m_buttonX; // 0x10 + MxDouble m_buttonY; // 0x18 +}; + +// SYNTHETIC: LEGO1 0x100655b0 +// LegoMouseController::`scalar deleting destructor' + +// VTABLE: LEGO1 0x100d8e08 +// SIZE 0x38 +class LegoPointOfViewController : public LegoMouseController { +public: + LegoPointOfViewController(); + ~LegoPointOfViewController() override; + + MxResult Tickle() override; // vtable+0x08 + void LeftDown(int p_x, int p_y) override; // vtable+0x0c + void LeftDrag(int p_x, int p_y) override; // vtable+0x10 + + // FUNCTION: LEGO1 0x10011e40 + void LeftUp(int p_x, int p_y) override + { + LegoMouseController::LeftUp(p_x, p_y); + AffectPointOfView(); + } + // vtable+0x14 + + // FUNCTION: LEGO1 0x10011e60 + void RightDown(int p_x, int p_y) override + { + LegoMouseController::RightDown(p_x, p_y); + AffectPointOfView(); + } + // vtable+0x20 + + // FUNCTION: LEGO1 0x10011e80 + void RightDrag(int p_x, int p_y) override + { + LegoMouseController::RightDrag(p_x, p_y); + AffectPointOfView(); + } + // vtable+0x24 + + // FUNCTION: LEGO1 0x10011ea0 + void RightUp(int p_x, int p_y) override + { + LegoMouseController::RightUp(p_x, p_y); + AffectPointOfView(); + } // vtable+0x28 + 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; } + inline LegoNavController* GetNavController() { return m_nav; } + +protected: + void AffectPointOfView(); + + Lego3DView* m_lego3DView; // 0x20 + LegoEntity* m_entity; // 0x24 + MxDouble m_entityOffsetUp; // 0x28 + LegoNavController* m_nav; // 0x30 +}; + +// SYNTHETIC: LEGO1 0x10065750 +// LegoPointOfViewController::`scalar deleting destructor' + +#endif /* LEGOPOINTOFVIEWCONTROLLER_H */ diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h new file mode 100644 index 00000000..c8b02f2e --- /dev/null +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -0,0 +1,67 @@ +#ifndef LEGORACE_H +#define LEGORACE_H + +#include "decomp.h" +#include "legoworld.h" +#include "mxrect32.h" +#include "mxtypes.h" + +// VTABLE: LEGO1 0x100d5db0 +// SIZE 0x144 +class LegoRace : public LegoWorld { +public: + LegoRace(); + ~LegoRace() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x10015ba0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f07c4 + return "LegoRace"; + } + + // FUNCTION: LEGO1 0x10015bb0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoRace::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + virtual undefined4 VTable0x6c(undefined4) = 0; // vtable+0x6c + virtual undefined4 VTable0x70(undefined4); // vtable+0x70 + virtual undefined4 VTable0x74(undefined4); // vtable+0x74 + virtual undefined4 VTable0x78(undefined4); // vtable+0x78 + virtual void VTable0x7c(undefined4, undefined4); // vtable+0x7c + + // SYNTHETIC: LEGO1 0x10015cc0 + // LegoRace::`scalar deleting destructor' + +private: + undefined4 m_unk0xf8; // 0xf8 + undefined4 m_unk0xfc; // 0xfc + undefined4 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 + undefined4 m_unk0x108; // 0x108 + undefined4 m_unk0x10c; // 0x10c + undefined4 m_unk0x110; // 0x110 + undefined4 m_unk0x114; // 0x114 + undefined4 m_unk0x118; // 0x118 + undefined4 m_unk0x11c; // 0x11c + undefined4 m_unk0x120; // 0x120 + undefined4 m_unk0x124; // 0x124 + undefined4 m_unk0x128; // 0x128 + undefined4 m_unk0x12c; // 0x12c + +protected: + MxRect32 m_unk0x130; // 0x130 + +private: + undefined4 m_unk0x140; // 0x140 +}; + +#endif // LEGORACE_H diff --git a/LEGO1/lego/legoomni/include/legoraceactor.h b/LEGO1/lego/legoomni/include/legoraceactor.h new file mode 100644 index 00000000..48f66b26 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoraceactor.h @@ -0,0 +1,35 @@ +#ifndef LEGORACEACTOR_H +#define LEGORACEACTOR_H + +#include "legoanimactor.h" +#include "realtime/matrix.h" + +// VTABLE: LEGO1 0x100d5b88 +class LegoRaceActor : public LegoAnimActor { +public: + // FUNCTION: LEGO1 0x10014af0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0bf4 + return "LegoRaceActor"; + } + + // FUNCTION: LEGO1 0x10014b10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoRaceActor::ClassName()) || LegoAnimActor::IsA(p_name); + } + + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x68() override; // vtable+0x68 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + MxS32 VTable0x90() override; // vtable+0x90 + MxS32 VTable0x94() override; // vtable+0x94 + + // SYNTHETIC: LEGO1 0x10014ab0 + // LegoRaceActor::`scalar deleting destructor' +}; + +#endif // LEGORACEACTOR_H diff --git a/LEGO1/lego/legoomni/include/legoracecar.h b/LEGO1/lego/legoomni/include/legoracecar.h new file mode 100644 index 00000000..f90c4cad --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoracecar.h @@ -0,0 +1,38 @@ +#ifndef LEGOCARRACE_H +#define LEGOCARRACE_H + +#include "legocarraceactor.h" +#include "legopathactor.h" + +// VTABLE: LEGO1 0x100d58b8 +// SIZE 0x200 +class LegoRaceCar : public LegoCarRaceActor { +public: + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x10014290 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0548 + return "LegoRaceCar"; + } + + // FUNCTION: LEGO1 0x100142b0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); + } + + void ParseAction(char*) override; // vtable+0x20 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void VTable0x6c() override; // vtable+0x6c + void VTable0x70(float p_float) override; // vtable+0x70 + MxS32 VTable0x94() override; // vtable+0x94 + void VTable0x98() override; // vtable+0x98 + void VTable0x9c() override; // vtable+0x9c + + // SYNTHETIC: LEGO1 0x10014230 + // LegoRaceCar::`scalar deleting destructor' +}; + +#endif // LEGOCARRACE_H diff --git a/LEGO1/lego/legoomni/include/legosoundmanager.h b/LEGO1/lego/legoomni/include/legosoundmanager.h new file mode 100644 index 00000000..83a4ea7d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legosoundmanager.h @@ -0,0 +1,31 @@ +#ifndef LEGOSOUNDMANAGER_H +#define LEGOSOUNDMANAGER_H + +#include "legounknown100d6b4c.h" +#include "mxsoundmanager.h" + +// VTABLE: LEGO1 0x100d6b10 +// SIZE 0x44 +class LegoSoundManager : public MxSoundManager { +public: + LegoSoundManager(); + ~LegoSoundManager() override; + + MxResult Tickle() override; // vtable+08 + void Destroy() override; // vtable+18 + MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x30 + + // SYNTHETIC: LEGO1 0x10029920 + // LegoSoundManager::`scalar deleting destructor' + + inline LegoUnknown100d6b4c* GetUnknown0x40() { return m_unk0x40; } + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + + undefined4 m_unk0x3c; // 0x3c + LegoUnknown100d6b4c* m_unk0x40; // 0x40 +}; + +#endif // LEGOSOUNDMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h new file mode 100644 index 00000000..2ed94a3e --- /dev/null +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -0,0 +1,97 @@ +#ifndef LEGOSTATE_H +#define LEGOSTATE_H + +#include "decomp.h" +#include "lego/sources/misc/legostorage.h" +#include "mxcore.h" +#include "mxstring.h" + +// VTABLE: LEGO1 0x100d46c0 +// SIZE 0x08 +class LegoState : public MxCore { +public: + // FUNCTION: LEGO1 0x10005f40 + ~LegoState() override {} + + // FUNCTION: LEGO1 0x100060d0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f01b8 + return "LegoState"; + } + + // FUNCTION: LEGO1 0x100060e0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoState::ClassName()) || MxCore::IsA(p_name); + } + + // FUNCTION: LEGO1 0x10005f90 + virtual MxBool VTable0x14() { return TRUE; } // vtable+0x14 + + // FUNCTION: LEGO1 0x10005fa0 + virtual MxBool SetFlag() { return FALSE; } // vtable+0x18 + + // FUNCTION: LEGO1 0x10005fb0 + virtual MxResult VTable0x1c(LegoFile* p_legoFile) + { + if (p_legoFile->IsWriteMode()) { + p_legoFile->FUN_10006030(this->ClassName()); + } + return SUCCESS; + } // vtable+0x1c + + // SYNTHETIC: LEGO1 0x10006160 + // LegoState::`scalar deleting destructor' + + // SIZE 0x0c + class Playlist { + public: + enum Mode { + e_loop, + e_once, + e_random, + e_loopSkipFirst + }; + + // FUNCTION: LEGO1 0x10017c00 + Playlist() + { + m_objectIds = NULL; + m_length = 0; + m_mode = e_loop; + m_nextIndex = 0; + } + + Playlist(MxU32* p_objectIds, MxS16 p_length) + { + m_objectIds = p_objectIds; + m_length = p_length; + m_mode = e_loop; + m_nextIndex = 0; + } + + // FUNCTION: LEGO1 0x10071800 + Playlist& operator=(const Playlist& p_shuffle) + { + m_objectIds = p_shuffle.m_objectIds; + m_length = p_shuffle.m_length; + m_nextIndex = p_shuffle.m_nextIndex; + m_mode = p_shuffle.m_mode; + return *this; + } + + MxU32 Next(); + MxBool Contains(MxU32 p_objectId); + + inline void SetUnknown0x08(MxS16 p_unk0x08) { m_nextIndex = p_unk0x08; } + + private: + MxU32* m_objectIds; // 0x00 + MxS16 m_length; // 0x04 + MxS16 m_mode; // 0x06 + MxS16 m_nextIndex; // 0x08 + }; +}; + +#endif // LEGOSTATE_H diff --git a/LEGO1/legotexturepresenter.h b/LEGO1/lego/legoomni/include/legotexturepresenter.h similarity index 52% rename from LEGO1/legotexturepresenter.h rename to LEGO1/lego/legoomni/include/legotexturepresenter.h index 22a23500..472c5828 100644 --- a/LEGO1/legotexturepresenter.h +++ b/LEGO1/lego/legoomni/include/legotexturepresenter.h @@ -7,22 +7,27 @@ // SIZE 0x54 (from inlined construction at 0x10009bb5) class LegoTexturePresenter : public MxMediaPresenter { public: - virtual ~LegoTexturePresenter() override; + ~LegoTexturePresenter() override; // FUNCTION: LEGO1 0x1000ce50 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0664 + // STRING: LEGO1 0x100f0664 return "LegoTexturePresenter"; } // FUNCTION: LEGO1 0x1000ce60 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoTexturePresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual MxResult AddToManager() override; // vtable+0x34 + void DoneTickle() override; // vtable+0x2c + MxResult AddToManager() override; // vtable+0x34 + MxResult PutData() override; // vtable+0x4c + + // SYNTHETIC: LEGO1 0x1000cf40 + // LegoTexturePresenter::`scalar deleting destructor' }; #endif // LEGOTEXTUREPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legounknown100d6b4c.h b/LEGO1/lego/legoomni/include/legounknown100d6b4c.h new file mode 100644 index 00000000..9b10bd50 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legounknown100d6b4c.h @@ -0,0 +1,15 @@ +#ifndef LEGOUNKNOWN100D6B4C_H +#define LEGOUNKNOWN100D6B4C_H + +#include "decomp.h" + +class LegoCacheSound; + +// VTABLE: LEGO1 0x100d6b4c +// SIZE 0x20 +class LegoUnknown100d6b4c { +public: + void FUN_1003dc40(LegoCacheSound** p_und); +}; + +#endif // LEGOUNKNOWN100D6B4C_H diff --git a/LEGO1/lego/legoomni/include/legounknown100d7c88.h b/LEGO1/lego/legoomni/include/legounknown100d7c88.h new file mode 100644 index 00000000..2fa960c8 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legounknown100d7c88.h @@ -0,0 +1,20 @@ +#ifndef LEGOUNKNOWN100D7C88_H +#define LEGOUNKNOWN100D7C88_H + +#include "decomp.h" +#include "mxstring.h" + +// VTABLE: LEGO1 0x100d7c88 +class LegoUnknown100d7c88 { +public: + ~LegoUnknown100d7c88(); + + virtual undefined4 VTable0x00(); // vtable+0x00 + // More virtual functions + +private: + MxString m_unk0x04; // 0x04 + undefined4 m_unk0x14; // 0x14 +}; + +#endif // LEGOUNKNOWN100D7C88_H diff --git a/LEGO1/lego/legoomni/include/legounknown100d9d00.h b/LEGO1/lego/legoomni/include/legounknown100d9d00.h new file mode 100644 index 00000000..0c567b17 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legounknown100d9d00.h @@ -0,0 +1,48 @@ +#ifndef LEGOUNKNOWN100D9D00_H +#define LEGOUNKNOWN100D9D00_H + +#include "decomp.h" +#include "legounknown100d7c88.h" +#include "mxlist.h" + +// VTABLE: LEGO1 0x100d9cd0 +// class MxCollection + +// VTABLE: LEGO1 0x100d9ce8 +// class MxList + +// VTABLE: LEGO1 0x100d9d00 +// SIZE 0x18 +class LegoUnknown100d9d00 : public MxList { +public: + LegoUnknown100d9d00() { SetDestroy(Destroy); } + + // STUB: LEGO1 0x1007b210 + MxS8 Compare(LegoUnknown100d7c88* p_a, LegoUnknown100d7c88* p_b) override { return -1; } // vtable+0x14 + + // FUNCTION: LEGO1 0x1007b2e0 + static void Destroy(LegoUnknown100d7c88* p_element) { delete p_element; } +}; + +// 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' + +// SYNTHETIC: LEGO1 0x1007b470 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1007b4e0 +// MxList::`scalar deleting destructor' + +#endif // LEGOUNKNOWN100D9D00_H diff --git a/LEGO1/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h similarity index 77% rename from LEGO1/legounksavedatawriter.h rename to LEGO1/lego/legoomni/include/legounksavedatawriter.h index 039058e6..d33cfc56 100644 --- a/LEGO1/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -2,9 +2,11 @@ #define LEGOUNKSAVEDATAWRITER_H #include "decomp.h" +#include "lego/sources/misc/legostorage.h" #include "mxtypes.h" -class LegoStream; +class AutoROI; +class LegoROI; struct LegoSaveDataEntry3 { char* m_name; @@ -32,7 +34,10 @@ struct LegoSaveDataEntry3 { }; class LegoUnkSaveDataWriter { - MxResult WriteSaveData3(LegoStream* p_stream); +public: + MxResult WriteSaveData3(LegoStorage* p_stream); + AutoROI* FUN_10083500(undefined4, undefined4); + 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 new file mode 100644 index 00000000..922a2c60 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoutil.h @@ -0,0 +1,24 @@ +#ifndef LEGOUTIL_H +#define LEGOUTIL_H + +#include "extra.h" +#include "mxtypes.h" +#include "mxutil.h" + +#include + +class MxAtomId; +class LegoEntity; +class LegoAnimPresenter; + +void FUN_1003e050(LegoAnimPresenter* p_presenter); +Extra::ActionType MatchActionString(const char*); +void InvokeAction(Extra::ActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender); +void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut); +MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); +void FUN_1003ef00(MxBool); +void SetAppCursor(WPARAM p_wparam); +MxBool FUN_1003ef60(); +MxBool RemoveFromWorld(MxAtomId& p_atomId1, MxS32 p_id1, MxAtomId& p_atomId2, MxS32 p_id2); + +#endif // LEGOUTIL_H diff --git a/LEGO1/legovehiclebuildstate.h b/LEGO1/lego/legoomni/include/legovehiclebuildstate.h similarity index 73% rename from LEGO1/legovehiclebuildstate.h rename to LEGO1/lego/legoomni/include/legovehiclebuildstate.h index a39740bb..229fdcfb 100644 --- a/LEGO1/legovehiclebuildstate.h +++ b/LEGO1/lego/legoomni/include/legovehiclebuildstate.h @@ -6,35 +6,30 @@ #include "mxstring.h" // VTABLE: LEGO1 0x100d66e0 -// SIZE 0x50 (from 1000acd7) +// SIZE 0x50 class LegoVehicleBuildState : public LegoState { public: LegoVehicleBuildState(char* p_classType); // FUNCTION: LEGO1 0x10025ff0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { return this->m_className.GetData(); } // FUNCTION: LEGO1 0x10026000 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, this->m_className.GetData()) || LegoState::IsA(p_name); } -public: - struct UnkStruct { - undefined4 m_unk0x00; - undefined2 m_unk0x04; - undefined2 m_unk0x06; - undefined2 m_unk0x08; + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c - UnkStruct(); - }; + // SYNTHETIC: LEGO1 0x100260a0 + // LegoVehicleBuildState::`scalar deleting destructor' private: - UnkStruct m_unk0x08[4]; // 0x08 + Playlist m_unk0x08[4]; // 0x08 // This can be one of the following: // * LegoRaceCarBuildState diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h new file mode 100644 index 00000000..bb43c05c --- /dev/null +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -0,0 +1,91 @@ +#ifndef LEGOVIDEOMANAGER_H +#define LEGOVIDEOMANAGER_H + +#include "3dmanager/lego3dmanager.h" +#include "decomp.h" +#include "legounknown100d9d00.h" +#include "mxdirectx/mxdirect3d.h" +#include "mxdirectx/mxstopwatch.h" +#include "mxvideomanager.h" + +#include + +class LegoROI; + +// VTABLE: LEGO1 0x100d9c88 +// SIZE 0x590 +class LegoVideoManager : public MxVideoManager { +public: + LegoVideoManager(); + ~LegoVideoManager() override; + + int EnableRMDevice(); + int DisableRMDevice(); + void EnableFullScreenMovie(MxBool p_enable); + void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); + void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY); + + MxResult Tickle() override; // vtable+0x08 + void Destroy() override; // vtable+0x18 + MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x2c + MxResult RealizePalette(MxPalette*) override; // vtable+0x30 + void UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) override; // vtable+0x34 + virtual MxPresenter* GetPresenterAt(MxS32 p_x, MxS32 p_y); // vtable+0x38 + + // FUNCTION: LEGO1 0x1007ab10 + virtual LegoUnknown100d9d00* VTable0x3c() { return m_unk0x100d9d00; } // vtable+0x3c + + void SetSkyColor(float p_red, float p_green, float p_blue); + void OverrideSkyColor(MxBool p_shouldOverride); + + inline Lego3DManager* Get3DManager() { return this->m_3dManager; } + inline MxDirect3D* GetDirect3D() { return this->m_direct3d; } + inline void SetRender3D(MxBool p_render3d) { this->m_render3d = p_render3d; } + inline void SetUnk0x554(MxBool p_unk0x554) { this->m_unk0x554 = p_unk0x554; } + +private: + MxResult CreateDirect3D(); + MxResult ConfigureD3DRM(); + void DrawFPS(); + + inline void DrawCursor(); + + Tgl::Renderer* m_renderer; // 0x64 + Lego3DManager* m_3dManager; // 0x68 + LegoROI* m_viewROI; // 0x6c + undefined4 m_unk0x70; // 0x70 + MxDirect3D* m_direct3d; // 0x74 + undefined4 m_unk0x78[27]; // 0x78 + MxBool m_render3d; // 0xe4 + MxBool m_unk0xe5; // 0xe5 + MxBool m_unk0xe6; // 0xe6 + PALETTEENTRY m_paletteEntries[256]; // 0xe7 + undefined m_padding0x4e7; // 0x4e7 + LegoUnknown100d9d00* m_unk0x100d9d00; // 0x4e8 + MxBool m_isFullscreenMovie; // 0x4ec + MxPalette* m_palette; // 0x4f0 + MxStopWatch* m_stopWatch; // 0x4f4 + double m_elapsedSeconds; // 0x4f8 + MxBool m_fullScreenMovie; // 0x500 + MxBool m_drawCursor; // 0x501 + MxS32 m_cursorXCopy; // 0x504 + MxS32 m_cursorYCopy; // 0x508 + MxS32 m_cursorX; // 0x50c + MxS32 m_cursorY; // 0x510 + LPDIRECTDRAWSURFACE m_cursorSurface; // 0x514 + RECT m_cursorRect; // 0x518 + undefined4 m_unk0x528; // 0x528 + MxBool m_drawFPS; // 0x52c + RECT m_fpsRect; // 0x530 + HFONT m_arialFont; // 0x540 + SIZE m_fpsSize; // 0x544 + undefined m_pad0x54c[8]; // 0x54c + MxBool m_unk0x554; // 0x554 + MxBool m_paused; // 0x555 + undefined m_pad0x556[0x39]; // 0x556 +}; + +// SYNTHETIC: LEGO1 0x1007ab20 +// LegoVideoManager::`scalar deleting destructor' + +#endif // LEGOVIDEOMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h new file mode 100644 index 00000000..98dbbd5c --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -0,0 +1,162 @@ +#ifndef LEGOWORLD_H +#define LEGOWORLD_H + +#include "legocachesound.h" +#include "legocachesoundlist.h" +#include "legocameracontroller.h" +#include "legoentity.h" +#include "legoentitylist.h" +#include "legopathcontrollerlist.h" +#include "mxpresenter.h" +#include "mxpresenterlist.h" + +class IslePathActor; +class LegoPathBoundary; +class LegoHideAnimPresenter; + +struct CoreSetCompare { + MxS32 operator()(MxCore* const& p_a, MxCore* const& p_b) const { return (MxS32) p_a < (MxS32) p_b; } +}; + +typedef set MxCoreSet; + +// VTABLE: LEGO1 0x100d6280 +// SIZE 0xf8 +class LegoWorld : public LegoEntity { +public: + enum StartupTicks { + e_start = 0, + e_one, + e_two, + e_three, + e_four + }; + + LegoWorld(); + ~LegoWorld() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1001d690 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0058 + return "LegoWorld"; + } + + // FUNCTION: LEGO1 0x1001d6a0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoWorld::ClassName()) || LegoEntity::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + virtual void ReadyWorld(); // vtable+0x50 + virtual LegoCameraController* VTable0x54(); // vtable+0x54 + virtual void Add(MxCore* p_object); // vtable+0x58 + virtual MxBool VTable0x5c(); // vtable+0x5c + + // FUNCTION: LEGO1 0x100010a0 + virtual void VTable0x60() {} // vtable+0x60 + + virtual MxBool VTable0x64(); // vtable+0x64 + virtual void Enable(MxBool p_enable); // vtable+0x68 + + inline LegoCameraController* GetCamera() { return m_cameraController; } + inline undefined4 GetUnknown0xec() { return m_unk0xec; } + + MxBool PresentersPending(); + void Remove(MxCore* p_object); + void FUN_1001fc80(IslePathActor* p_actor); + MxS32 GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); + MxCore* Find(const char* p_class, const char* p_name); + MxCore* Find(const MxAtomId& p_atom, MxS32 p_entityId); + + // SYNTHETIC: LEGO1 0x1001dee0 + // LegoWorld::`scalar deleting destructor' + +protected: + LegoPathControllerList m_list0x68; // 0x68 + MxPresenterList m_animPresenters; // 0x80 + LegoCameraController* m_cameraController; // 0x98 + LegoEntityList* m_entityList; // 0x9c + LegoCacheSoundList* m_cacheSoundList; // 0xa0 + MxBool m_destroyed; // 0xa4 + MxCoreSet m_set0xa8; // 0xa8 + MxPresenterList m_controlPresenters; // 0xb8 + MxCoreSet m_set0xd0; // 0xd0 + list m_list0xe0; // 0xe0 + undefined4 m_unk0xec; // 0xec + LegoHideAnimPresenter* m_hideAnimPresenter; // 0xf0 + MxS16 m_startupTicks; // 0xf4 + MxBool m_worldStarted; // 0xf6 + undefined m_unk0xf7; // 0xf7 +}; + +// clang-format off +// TEMPLATE: LEGO1 0x1001d780 +// _Tree >::_Kfn,CoreSetCompare,allocator >::~_Tree >::_Kfn,CoreSetCompare,allocator > + +// TEMPLATE: LEGO1 0x1001d850 +// _Tree >::_Kfn,CoreSetCompare,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x1001d890 +// _Tree >::_Kfn,CoreSetCompare,allocator >::erase + +// TEMPLATE: LEGO1 0x1001dcf0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Erase + +// TEMPLATE: LEGO1 0x1001dd30 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Init + +// TEMPLATE: LEGO1 0x1001ddf0 +// list >::~list > + +// TEMPLATE: LEGO1 0x1001df50 +// List::~List + +// TEMPLATE: LEGO1 0x1001de60 +// list >::_Buynode + +// TEMPLATE: LEGO1 0x1001de90 +// set >::~set > + +// TEMPLATE: LEGO1 0x1001df00 +// Set::~Set + +// TEMPLATE: LEGO1 0x1001f590 +// list >::erase + +// TEMPLATE: LEGO1 0x100208b0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::insert + +// TEMPLATE: LEGO1 0x10020b20 +// _Tree >::_Kfn,CoreSetCompare,allocator >::iterator::_Dec + +// XTEMPLATE LEGO1 0x10020b70 + +// TEMPLATE: LEGO1 0x10020bb0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Buynode + +// TEMPLATE: LEGO1 0x10020bd0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Insert + +// TEMPLATE: LEGO1 0x10020e50 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Lrotate + +// TEMPLATE: LEGO1 0x10020eb0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Rrotate + +// TEMPLATE: LEGO1 0x10021340 +// _Tree >::_Kfn,CoreSetCompare,allocator >::find + +// TEMPLATE: LEGO1 0x10022360 +// _Construct + +// GLOBAL: LEGO1 0x100f11a0 +// _Tree >::_Kfn,CoreSetCompare,allocator >::_Nil +// clang-format on + +#endif // LEGOWORLD_H diff --git a/LEGO1/legoworldlist.h b/LEGO1/lego/legoomni/include/legoworldlist.h similarity index 50% rename from LEGO1/legoworldlist.h rename to LEGO1/lego/legoomni/include/legoworldlist.h index 22cf5838..bd8197bc 100644 --- a/LEGO1/legoworldlist.h +++ b/LEGO1/lego/legoomni/include/legoworldlist.h @@ -22,12 +22,43 @@ class LegoWorldList : public MxPtrList { LegoWorldList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x100598d0 - virtual MxS8 Compare(LegoWorld* p_a, LegoWorld* p_b) override - { - return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; - }; // vtable+0x14 + MxS8 Compare(LegoWorld* p_a, LegoWorld* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 + + // SYNTHETIC: LEGO1 0x10059a00 + // LegoWorldList::`scalar deleting destructor' }; +// 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 + +// SYNTHETIC: LEGO1 0x1003e930 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1003e9a0 +// MxPtrListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1003ea10 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1003ea60 +// LegoWorldListCursor::~LegoWorldListCursor + // TEMPLATE: LEGO1 0x100598f0 // MxCollection::Compare @@ -52,4 +83,7 @@ class LegoWorldList : public MxPtrList { // SYNTHETIC: LEGO1 0x10059be0 // MxPtrList::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x1005b740 +// MxList::DeleteEntry + #endif // LEGOWORLDLIST_H diff --git a/LEGO1/lego/legoomni/include/legoworldpresenter.h b/LEGO1/lego/legoomni/include/legoworldpresenter.h new file mode 100644 index 00000000..a9a7f324 --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoworldpresenter.h @@ -0,0 +1,41 @@ +#ifndef LEGOWORLDPRESENTER_H +#define LEGOWORLDPRESENTER_H + +#include "legoentitypresenter.h" + +// VTABLE: LEGO1 0x100d8ee0 +// SIZE 0x54 +class LegoWorldPresenter : public LegoEntityPresenter { +public: + LegoWorldPresenter(); + ~LegoWorldPresenter() override; // vtable+0x00 + + static void configureLegoWorldPresenter(MxS32 p_legoWorldPresenterQuality); + + // FUNCTION: LEGO1 0x10066630 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0608 + return "LegoWorldPresenter"; + } + + // FUNCTION: LEGO1 0x10066640 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoWorldPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void ParseExtra() override; // vtable+0x30 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 + + // SYNTHETIC: LEGO1 0x10066750 + // LegoWorldPresenter::`scalar deleting destructor' + +private: + undefined4 m_unk0x50; +}; + +#endif // LEGOWORLDPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/motocycle.h b/LEGO1/lego/legoomni/include/motocycle.h new file mode 100644 index 00000000..cf3f376f --- /dev/null +++ b/LEGO1/lego/legoomni/include/motocycle.h @@ -0,0 +1,42 @@ +#ifndef MOTOCYCLE_H +#define MOTOCYCLE_H + +#include "decomp.h" +#include "islepathactor.h" + +// VTABLE: LEGO1 0x100d7090 +// SIZE 0x16c +class Motocycle : public IslePathActor { +public: + Motocycle(); + + // FUNCTION: LEGO1 0x10035840 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f38e8 + return "Motorcycle"; + } + + // FUNCTION: LEGO1 0x10035850 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Motocycle::ClassName()) || IslePathActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xdc(MxType19NotificationParam&) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x100359d0 + // Motocycle::`scalar deleting destructor' + +private: + undefined m_unk0x160[4]; + MxFloat m_unk0x164; + undefined m_unk0x168[4]; +}; + +#endif // MOTOCYCLE_H diff --git a/LEGO1/mxbackgroundaudiomanager.h b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h similarity index 53% rename from LEGO1/mxbackgroundaudiomanager.h rename to LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h index cb03624c..3e7793f6 100644 --- a/LEGO1/mxbackgroundaudiomanager.h +++ b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h @@ -13,24 +13,26 @@ class MxBackgroundAudioManager : public MxCore { public: MxBackgroundAudioManager(); - virtual ~MxBackgroundAudioManager() override; + ~MxBackgroundAudioManager() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 - virtual MxResult Tickle() override; // vtable+0x08 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1007eb70 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7ac4 + // STRING: LEGO1 0x100f7ac4 return "MxBackgroundAudioManager"; } // FUNCTION: LEGO1 0x1007eb80 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxBackgroundAudioManager::ClassName()) || MxCore::IsA(p_name); } + inline MxBool GetMusicEnabled() { return m_musicEnabled; } + void StartAction(MxParam& p_param); void StopAction(MxParam& p_param); MxResult PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, undefined4 p_unk0x13c); @@ -39,28 +41,31 @@ class MxBackgroundAudioManager : public MxCore { void FUN_1007ef40(); void FadeInOrFadeOut(); - __declspec(dllexport) void Enable(MxBool p_enable); + void Enable(MxBool p_enable); virtual MxResult Create(MxAtomId& p_script, MxU32 p_frequencyMS); void Stop(); void LowerVolume(); void RaiseVolume(); + // SYNTHETIC: LEGO1 0x1007ec00 + // MxBackgroundAudioManager::`scalar deleting destructor' + private: void Init(); MxResult OpenMusic(MxAtomId& p_script); void DestroyMusic(); - MxBool m_musicEnabled; // 0x8 - MxDSAction m_action1; // 0xc - MxAudioPresenter* m_unk0xa0; - MxDSAction m_action2; // 0xa4 - MxAudioPresenter* m_unk0x138; - MxS32 m_unk0x13c; - MxS32 m_unk0x140; - MxS32 m_targetVolume; - MxS16 m_unk0x148; - MxAtomId m_script; + MxBool m_musicEnabled; // 0x08 + MxDSAction m_action1; // 0x0c + MxAudioPresenter* m_unk0xa0; // 0xa0 + MxDSAction m_action2; // 0xa4 + MxAudioPresenter* m_unk0x138; // 0x138 + MxS32 m_unk0x13c; // 0x13c + MxS32 m_unk0x140; // 0x140 + MxS32 m_targetVolume; // 0x144 + MxS16 m_unk0x148; // 0x148 + MxAtomId m_script; // 0x14c }; #endif // MXBACKGROUNDAUDIOMANAGER_H diff --git a/LEGO1/mxcompositemediapresenter.h b/LEGO1/lego/legoomni/include/mxcompositemediapresenter.h similarity index 53% rename from LEGO1/mxcompositemediapresenter.h rename to LEGO1/lego/legoomni/include/mxcompositemediapresenter.h index 4f0efc76..efba804f 100644 --- a/LEGO1/mxcompositemediapresenter.h +++ b/LEGO1/lego/legoomni/include/mxcompositemediapresenter.h @@ -8,26 +8,26 @@ class MxCompositeMediaPresenter : public MxCompositePresenter { public: MxCompositeMediaPresenter(); - virtual ~MxCompositeMediaPresenter() override; + ~MxCompositeMediaPresenter() override; - virtual MxResult Tickle() override; // vtable+0x08 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10073f10 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f02d4 + // STRING: LEGO1 0x100f02d4 return "MxCompositeMediaPresenter"; } // FUNCTION: LEGO1 0x10073f20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxCompositeMediaPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } - virtual void StartingTickle() override; // vtable+0x1c - virtual MxResult StartAction(MxStreamController*, MxDSAction* p_action) override; // vtable+0x3c - virtual MxResult PutData() override; // vtable+0x4c + void StartingTickle() override; // vtable+0x1c + MxResult StartAction(MxStreamController*, MxDSAction* p_action) override; // vtable+0x3c + MxResult PutData() override; // vtable+0x4c private: MxS16 m_unk0x4c; // 0x4c diff --git a/LEGO1/lego/legoomni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h new file mode 100644 index 00000000..e12c1a25 --- /dev/null +++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h @@ -0,0 +1,58 @@ +#ifndef MXCONTROLPRESENTER_H +#define MXCONTROLPRESENTER_H + +#include "decomp.h" +#include "mxcompositepresenter.h" + +class LegoControlManagerEvent; +class MxVideoPresenter; + +// VTABLE: LEGO1 0x100d7b88 +// SIZE 0x5c +class MxControlPresenter : public MxCompositePresenter { +public: + MxControlPresenter(); + ~MxControlPresenter() override; + + // FUNCTION: LEGO1 0x10044000 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0514 + return "MxControlPresenter"; + } + + // FUNCTION: LEGO1 0x10044010 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxControlPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 + void Enable(MxBool p_enable) override; // vtable+0x54 + MxBool VTable0x64(undefined4 p_undefined) override; // vtable+0x64 + virtual void VTable0x68(MxBool p_unk0x50); // vtable+0x68 + virtual void VTable0x6c(MxS16); // vtable+0x6c + + MxBool FUN_10044480(LegoControlManagerEvent* p_event, MxPresenter* p_presenter); + MxBool FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter); + +private: + undefined2 m_unk0x4c; // 0x4c + MxS16 m_unk0x4e; // 0x4e + MxBool m_unk0x50; // 0x50 + undefined2 m_unk0x52; // 0x52 + undefined2 m_unk0x54; // 0x54 + undefined2 m_unk0x56; // 0x56 + MxS16* m_unk0x58; // 0x58 +}; + +// SYNTHETIC: LEGO1 0x100440f0 +// MxControlPresenter::`scalar deleting destructor' + +#endif // MXCONTROLPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h new file mode 100644 index 00000000..89f0d73b --- /dev/null +++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h @@ -0,0 +1,78 @@ +#ifndef MXTRANSITIONMANAGER_H +#define MXTRANSITIONMANAGER_H + +#include "legoomni.h" +#include "mxcore.h" +#include "mxvideopresenter.h" + +#include + +// VTABLE: LEGO1 0x100d7ea0 +class MxTransitionManager : public MxCore { +public: + MxTransitionManager(); + ~MxTransitionManager() override; // vtable+0x00 + + void SetWaitIndicator(MxVideoPresenter* p_waitIndicator); + + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1004b950 + inline const char* ClassName() const override // vtable+0x0c + { + return "MxTransitionManager"; + } + + // FUNCTION: LEGO1 0x1004b960 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxTransitionManager::ClassName()) || MxCore::IsA(p_name); + } + + virtual MxResult GetDDrawSurfaceFromVideoManager(); // vtable+0x14 + + enum TransitionType { + 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); + + inline TransitionType GetTransitionType() { return m_transitionType; } + + // SYNTHETIC: LEGO1 0x1004b9e0 + // MxTransitionManager::`scalar deleting destructor' + +private: + void EndTransition(MxBool p_notifyWorld); + void TransitionNone(); + void TransitionDissolve(); + void TransitionPixelation(); + void TransitionWipe(); + void TransitionWindows(); + void TransitionBroken(); + + void SubmitCopyRect(LPDDSURFACEDESC p_ddsc); + void SetupCopyRect(LPDDSURFACEDESC p_ddsc); + + MxVideoPresenter* m_waitIndicator; // 0x08 + RECT m_copyRect; // 0x0c + MxU8* m_copyBuffer; // 0x1c + FlagBitfield m_copyFlags; // 0x20 + undefined4 m_unk0x24; // 0x24 + FlagBitfield m_unk0x28; // 0x28 + TransitionType m_transitionType; // 0x2c + LPDIRECTDRAWSURFACE m_ddSurface; // 0x30 + MxU16 m_animationTimer; // 0x34 + MxU16 m_columnOrder[640]; // 0x36 + MxU16 m_randomShift[480]; // 0x536 + MxULong m_systemTime; // 0x8f8 + MxS32 m_animationSpeed; // 0x8fc +}; + +#endif // MXTRANSITIONMANAGER_H diff --git a/LEGO1/pizza.h b/LEGO1/lego/legoomni/include/pizza.h similarity index 70% rename from LEGO1/pizza.h rename to LEGO1/lego/legoomni/include/pizza.h index f1ac9f45..5ba1da94 100644 --- a/LEGO1/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -13,23 +13,28 @@ class Pizza : public IsleActor { public: Pizza(); - virtual ~Pizza() override; + ~Pizza() override; - virtual MxResult Tickle() override; // vtable+08 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x10037f90 - inline const char* ClassName() const // vtable+0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f038c + // STRING: LEGO1 0x100f038c return "Pizza"; } // FUNCTION: LEGO1 0x10037fa0 - inline MxBool IsA(const char* p_name) const override // vtable+10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, Pizza::ClassName()) || IsleActor::IsA(p_name); } + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + + // SYNTHETIC: LEGO1 0x100380e0 + // Pizza::`scalar deleting destructor' + private: undefined4 m_unk0x78; undefined4 m_unk0x7c; diff --git a/LEGO1/pizzamissionstate.h b/LEGO1/lego/legoomni/include/pizzamissionstate.h similarity index 54% rename from LEGO1/pizzamissionstate.h rename to LEGO1/lego/legoomni/include/pizzamissionstate.h index a9231c81..1b111c43 100644 --- a/LEGO1/pizzamissionstate.h +++ b/LEGO1/lego/legoomni/include/pizzamissionstate.h @@ -3,40 +3,47 @@ #include "legostate.h" +// SIZE 0x20 struct PizzaMissionStateEntry { public: - undefined2 m_unk0x0; + undefined2 m_unk0x00; MxU8 m_id; - undefined m_unk0x3[0x15]; + undefined m_unk0x03[0x15]; MxU16 m_color; undefined m_unk0x18[6]; }; // VTABLE: LEGO1 0x100d7408 +// SIZE 0xb0 class PizzaMissionState : public LegoState { public: // FUNCTION: LEGO1 0x10039290 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f00d4 + // STRING: LEGO1 0x100f00d4 return "PizzaMissionState"; } // FUNCTION: LEGO1 0x100392a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, PizzaMissionState::ClassName()) || LegoState::IsA(p_name); } + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + inline MxU16 GetColor(MxU8 p_id) { return GetState(p_id)->m_color; } + // SYNTHETIC: LEGO1 0x10039350 + // PizzaMissionState::`scalar deleting destructor' + private: PizzaMissionStateEntry* GetState(MxU8 p_id); protected: - undefined4 m_unk0x8; - undefined4 m_unk0xc; - PizzaMissionStateEntry m_state[5]; + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + PizzaMissionStateEntry m_state[5]; // 0x10 }; #endif // PIZZAMISSIONSTATE_H diff --git a/LEGO1/lego/legoomni/include/pizzeria.h b/LEGO1/lego/legoomni/include/pizzeria.h new file mode 100644 index 00000000..49c4960a --- /dev/null +++ b/LEGO1/lego/legoomni/include/pizzeria.h @@ -0,0 +1,29 @@ +#ifndef PIZZERIA_H +#define PIZZERIA_H + +#include "isleactor.h" + +// VTABLE: LEGO1 0x100d5520 +// SIZE 0x84 +class Pizzeria : public IsleActor { +public: + // FUNCTION: LEGO1 0x1000e780 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0380 + return "Pizzeria"; + } + + // FUNCTION: LEGO1 0x1000e790 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Pizzeria::ClassName()) || IsleActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + + // SYNTHETIC: LEGO1 0x1000e8d0 + // Pizzeria::`scalar deleting destructor' +}; + +#endif // PIZZERIA_H diff --git a/LEGO1/pizzeriastate.h b/LEGO1/lego/legoomni/include/pizzeriastate.h similarity index 55% rename from LEGO1/pizzeriastate.h rename to LEGO1/lego/legoomni/include/pizzeriastate.h index 53f4ddd5..b4d6b0fe 100644 --- a/LEGO1/pizzeriastate.h +++ b/LEGO1/lego/legoomni/include/pizzeriastate.h @@ -10,17 +10,22 @@ class PizzeriaState : public LegoState { PizzeriaState(); // FUNCTION: LEGO1 0x10017c20 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0370 + // STRING: LEGO1 0x100f0370 return "PizzeriaState"; } // FUNCTION: LEGO1 0x10017c30 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, PizzeriaState::ClassName()) || LegoState::IsA(p_name); } + + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + + // SYNTHETIC: LEGO1 0x10017ce0 + // PizzeriaState::`scalar deleting destructor' }; #endif // PIZZERIASTATE_H diff --git a/LEGO1/lego/legoomni/include/police.h b/LEGO1/lego/legoomni/include/police.h new file mode 100644 index 00000000..595f5ede --- /dev/null +++ b/LEGO1/lego/legoomni/include/police.h @@ -0,0 +1,48 @@ +#ifndef POLICE_H +#define POLICE_H + +#include "decomp.h" +#include "legoworld.h" +#include "mxdsaction.h" +#include "policestate.h" +#include "radio.h" + +// VTABLE: LEGO1 0x100d8a80 +// SIZE 0x110 +// Radio at 0xf8 +class Police : public LegoWorld { +public: + Police(); + ~Police() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x1005e1e0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0450 + return "Police"; + } + + // FUNCTION: LEGO1 0x1005e1f0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Police::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x5c() override; // vtable+0x5c + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x1005e300 + // Police::`scalar deleting destructor' + +private: + Radio m_radio; // 0xf8 + PoliceState* m_policeState; // 0x108 + undefined4 m_unk0x10c; // 0x10c +}; + +#endif // POLICE_H diff --git a/LEGO1/policeentity.h b/LEGO1/lego/legoomni/include/policeentity.h similarity index 61% rename from LEGO1/policeentity.h rename to LEGO1/lego/legoomni/include/policeentity.h index e2314dd3..acf0937b 100644 --- a/LEGO1/policeentity.h +++ b/LEGO1/lego/legoomni/include/policeentity.h @@ -8,17 +8,20 @@ class PoliceEntity : public BuildingEntity { public: // FUNCTION: LEGO1 0x1000ed60 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0328 + // STRING: LEGO1 0x100f0328 return "PoliceEntity"; } // FUNCTION: LEGO1 0x1000ed70 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, PoliceEntity::ClassName()) || BuildingEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000f900 + // PoliceEntity::`scalar deleting destructor' }; #endif // POLICEENTITY_H diff --git a/LEGO1/lego/legoomni/include/policestate.h b/LEGO1/lego/legoomni/include/policestate.h new file mode 100644 index 00000000..551d83c4 --- /dev/null +++ b/LEGO1/lego/legoomni/include/policestate.h @@ -0,0 +1,37 @@ +#ifndef POLICESTATE_H +#define POLICESTATE_H + +#include "decomp.h" +#include "legostate.h" + +// VTABLE: LEGO1 0x100d8af0 +// SIZE 0x10 +class PoliceState : public LegoState { +public: + PoliceState(); + ~PoliceState() override {} + + // FUNCTION: LEGO1 0x1005e860 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0444 + return "PoliceState"; + } + + // FUNCTION: LEGO1 0x1005e870 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, PoliceState::ClassName()) || LegoState::IsA(p_name); + } + + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + + // SYNTHETIC: LEGO1 0x1005e920 + // PoliceState::`scalar deleting destructor' + +private: + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c +}; + +#endif // POLICESTATE_H diff --git a/LEGO1/racecar.h b/LEGO1/lego/legoomni/include/racecar.h similarity index 52% rename from LEGO1/racecar.h rename to LEGO1/lego/legoomni/include/racecar.h index b0db77c5..462c2dbe 100644 --- a/LEGO1/racecar.h +++ b/LEGO1/lego/legoomni/include/racecar.h @@ -9,21 +9,27 @@ class RaceCar : public IslePathActor { public: RaceCar(); - virtual ~RaceCar() override; // vtable+0x0 + ~RaceCar() override; // vtable+0x00 // FUNCTION: LEGO1 0x10028270 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f03e0 + // STRING: LEGO1 0x100f03e0 return "RaceCar"; } // FUNCTION: LEGO1 0x10028280 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RaceCar::ClassName()) || IslePathActor::IsA(p_name); } + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxU32 VTable0xcc() override; // vtable+0xcc + + // SYNTHETIC: LEGO1 0x10028400 + // RaceCar::`scalar deleting destructor' + private: // TODO: RaceCar fields undefined m_unk0x160[4]; diff --git a/LEGO1/lego/legoomni/include/racestandsentity.h b/LEGO1/lego/legoomni/include/racestandsentity.h new file mode 100644 index 00000000..5b5b83e5 --- /dev/null +++ b/LEGO1/lego/legoomni/include/racestandsentity.h @@ -0,0 +1,26 @@ +#ifndef RACESTANDSENTITY_H +#define RACESTANDSENTITY_H + +#include "buildingentity.h" + +// VTABLE: LEGO1 0x100d48a8 +// SIZE 0x68 +class RaceStandsEntity : public BuildingEntity { + // FUNCTION: LEGO1 0x1000efa0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0300 + return "RaceStandsEntity"; + } + + // FUNCTION: LEGO1 0x1000efb0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, RaceStandsEntity::ClassName()) || BuildingEntity::IsA(p_name); + } + + // SYNTHETIC: LEGO1 0x1000f9e0 + // RaceStandsEntity::`scalar deleting destructor' +}; + +#endif // RACESTANDSENTITY_H diff --git a/LEGO1/racestate.h b/LEGO1/lego/legoomni/include/racestate.h similarity index 55% rename from LEGO1/racestate.h rename to LEGO1/lego/legoomni/include/racestate.h index 63a775d4..987d3a69 100644 --- a/LEGO1/racestate.h +++ b/LEGO1/lego/legoomni/include/racestate.h @@ -6,8 +6,8 @@ struct RaceStateEntry { public: MxU8 m_id; - undefined m_unk0x1[1]; - MxU16 m_unk0x2; + undefined m_unk0x01[1]; + MxU16 m_unk0x02; MxU16 m_color; }; @@ -18,27 +18,32 @@ class RaceState : public LegoState { RaceState(); // FUNCTION: LEGO1 0x10016010 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07d0 + // STRING: LEGO1 0x100f07d0 return "RaceState"; } // FUNCTION: LEGO1 0x10016020 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RaceState::ClassName()) || LegoState::IsA(p_name); } + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1c + inline MxU16 GetColor(MxU8 p_id) { return GetState(p_id)->m_color; } + // SYNTHETIC: LEGO1 0x100160d0 + // RaceState::`scalar deleting destructor' + private: RaceStateEntry* GetState(MxU8 p_id); protected: - RaceStateEntry m_state[5]; - undefined2 m_unk0x26[2]; - undefined4 m_unk0x28; + RaceStateEntry m_state[5]; // 0x08 + undefined2 m_unk0x26[2]; // 0x26 + undefined4 m_unk0x28; // 0x28 }; #endif // RACESTATE_H diff --git a/LEGO1/lego/legoomni/include/radio.h b/LEGO1/lego/legoomni/include/radio.h new file mode 100644 index 00000000..23ddb276 --- /dev/null +++ b/LEGO1/lego/legoomni/include/radio.h @@ -0,0 +1,51 @@ +#ifndef RADIO_H +#define RADIO_H + +#include "legocontrolmanager.h" +#include "mxactionnotificationparam.h" +#include "mxcore.h" +#include "radiostate.h" + +// VTABLE: LEGO1 0x100d6d10 +// SIZE 0x10 +class Radio : public MxCore { +public: + Radio(); + ~Radio() override; + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x1002c8e0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f328c + return "Radio"; + } + + // FUNCTION: LEGO1 0x1002c8f0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Radio::ClassName()) || MxCore::IsA(p_name); + } + + void Initialize(MxBool p_und); + void Play(); + void Stop(); + + inline RadioState* GetState() { return m_state; } + + // SYNTHETIC: LEGO1 0x1002c970 + // Radio::`scalar deleting destructor' + +private: + void CreateRadioState(); + + RadioState* m_state; // 0x08 + MxBool m_unk0x0c; // 0x0c + MxBool m_bgAudioPreviouslyEnabled; // 0x0d + + MxLong HandleEndAction(MxEndActionNotificationParam& p_param); + MxLong HandleClick(LegoControlManagerEvent& p_param); +}; + +#endif // RADIO_H diff --git a/LEGO1/lego/legoomni/include/radiostate.h b/LEGO1/lego/legoomni/include/radiostate.h new file mode 100644 index 00000000..6dcdafd9 --- /dev/null +++ b/LEGO1/lego/legoomni/include/radiostate.h @@ -0,0 +1,44 @@ +#ifndef RADIOSTATE_H +#define RADIOSTATE_H + +#include "legostate.h" +#include "mxdsaction.h" + +// VTABLE: LEGO1 0x100d6d28 +// SIZE 0x30 +class RadioState : public LegoState { +public: + RadioState(); + + // FUNCTION: LEGO1 0x1002cf60 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f04f8 + return "RadioState"; + } + + // FUNCTION: LEGO1 0x1002cf70 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, RadioState::ClassName()) || LegoState::IsA(p_name); + } + + MxBool VTable0x14() override; // vtable+0x14 + + // SYNTHETIC: LEGO1 0x1002d020 + // RadioState::`scalar deleting destructor' + + inline MxBool IsActive() { return m_active; } + + inline void SetActive(MxBool p_active) { m_active = p_active; } + + undefined4 FUN_1002d090(); + MxBool FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId); + +private: + Playlist m_unk0x08[3]; // 0x08 + MxS16 m_unk0x2c; // 0x2c + MxBool m_active; // 0x2e +}; + +#endif // RADIOSTATE_H diff --git a/LEGO1/lego/legoomni/include/registrationbook.h b/LEGO1/lego/legoomni/include/registrationbook.h new file mode 100644 index 00000000..4a7f3ee8 --- /dev/null +++ b/LEGO1/lego/legoomni/include/registrationbook.h @@ -0,0 +1,38 @@ +#ifndef REGISTRATIONBOOK_H +#define REGISTRATIONBOOK_H + +#include "legoworld.h" + +// VTABLE: LEGO1 0x100d9928 +// SIZE 0x2d0 +class RegistrationBook : public LegoWorld { +public: + RegistrationBook(); + ~RegistrationBook() override; // vtable+0x00 + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x10076e10 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f04c8 + return "RegistrationBook"; + } + + // FUNCTION: LEGO1 0x10076e20 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, RegistrationBook::ClassName()) || LegoWorld::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool VTable0x64() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x10076f30 + // RegistrationBook::`scalar deleting destructor' +}; + +#endif // REGISTRATIONBOOK_H diff --git a/LEGO1/lego/legoomni/include/score.h b/LEGO1/lego/legoomni/include/score.h new file mode 100644 index 00000000..2f03abe5 --- /dev/null +++ b/LEGO1/lego/legoomni/include/score.h @@ -0,0 +1,54 @@ +#ifndef SCORE_H +#define SCORE_H + +#include "legocontrolmanager.h" +#include "legoeventnotificationparam.h" +#include "legoworld.h" +#include "mxactionnotificationparam.h" +#include "scorestate.h" + +// VTABLE: LEGO1 0x100d4018 +// SIZE 0x104 +class Score : public LegoWorld { +public: + Score(); + ~Score() override; // vtable+0x00 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + + // FUNCTION: LEGO1 0x100010c0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0050 + return "Score"; + } + + // FUNCTION: LEGO1 0x100010d0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, Score::ClassName()) || LegoWorld::IsA(p_name); + } + + // SYNTHETIC: LEGO1 0x100011e0 + // Score::`scalar deleting destructor' + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+18 + void ReadyWorld() override; // vtable+50 + MxBool VTable0x5c() override; // vtable+5c + MxBool VTable0x64() override; // vtable+64 + void Enable(MxBool p_enable) override; // vtable+68 + + void Paint(); + MxLong FUN_10001510(MxEndActionNotificationParam& p_param); + MxLong FUN_100016d0(LegoControlManagerEvent& p_param); + void FillArea(MxU32 p_x, MxU32 p_y, MxS16 p_color); + +protected: + undefined4 m_unk0xf8; + ScoreState* m_state; + MxU8* m_surface; + +private: + void DeleteScript(); +}; + +#endif // SCORE_H diff --git a/LEGO1/scorestate.h b/LEGO1/lego/legoomni/include/scorestate.h similarity index 57% rename from LEGO1/scorestate.h rename to LEGO1/lego/legoomni/include/scorestate.h index 2797ad34..78609c02 100644 --- a/LEGO1/scorestate.h +++ b/LEGO1/lego/legoomni/include/scorestate.h @@ -4,30 +4,33 @@ #include "legostate.h" // VTABLE: LEGO1 0x100d53f8 -// SIZE 0xc +// SIZE 0x0c class ScoreState : public LegoState { public: // FUNCTION: LEGO1 0x1000de40 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0084 + // STRING: LEGO1 0x100f0084 return "ScoreState"; - }; + } // FUNCTION: LEGO1 0x1000de50 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, ScoreState::ClassName()) || LegoState::IsA(p_name); - }; + } - virtual MxBool VTable0x14() override; // vtable+0x14 - virtual MxBool SetFlag() override; // vtable+0x18 + MxBool VTable0x14() override; // vtable+0x14 + MxBool SetFlag() override; // vtable+0x18 inline MxBool GetTutorialFlag() { return m_playCubeTutorial; } inline void SetTutorialFlag(MxBool p_playCubeTutorial) { m_playCubeTutorial = p_playCubeTutorial; } + // SYNTHETIC: LEGO1 0x1000df00 + // ScoreState::`scalar deleting destructor' + private: - MxBool m_playCubeTutorial; + MxBool m_playCubeTutorial; // 0x08 }; #endif // SCORESTATE_H diff --git a/LEGO1/lego/legoomni/include/skateboard.h b/LEGO1/lego/legoomni/include/skateboard.h new file mode 100644 index 00000000..628e26f5 --- /dev/null +++ b/LEGO1/lego/legoomni/include/skateboard.h @@ -0,0 +1,41 @@ +#ifndef SKATEBOARD_H +#define SKATEBOARD_H + +#include "decomp.h" +#include "islepathactor.h" + +// VTABLE: LEGO1 0x100d55f0 +// SIZE 0x168 +class SkateBoard : public IslePathActor { +public: + SkateBoard(); + + // FUNCTION: LEGO1 0x1000fdd0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f041c + return "SkateBoard"; + } + + // FUNCTION: LEGO1 0x1000fde0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, SkateBoard::ClassName()) || IslePathActor::IsA(p_name); + } + + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd0() override; // vtable+0xd0 + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x1000ff60 + // SkateBoard::`scalar deleting destructor' + +private: + // TODO: SkateBoard types + undefined m_unk0x160; + undefined m_unk0x161[0x7]; +}; + +#endif // SKATEBOARD_H diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h new file mode 100644 index 00000000..85e54e6b --- /dev/null +++ b/LEGO1/lego/legoomni/include/towtrack.h @@ -0,0 +1,52 @@ +#ifndef TOWTRACK_H +#define TOWTRACK_H + +#include "decomp.h" +#include "islepathactor.h" + +// VTABLE: LEGO1 0x100d7ee0 +// SIZE 0x180 +class TowTrack : public IslePathActor { +public: + TowTrack(); + + // FUNCTION: LEGO1 0x1004c7c0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f03b8 + return "TowTrack"; + } + + // FUNCTION: LEGO1 0x1004c7d0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, TowTrack::ClassName()) || IslePathActor::IsA(p_name); + } + + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void VTable0x70(float p_float) override; // vtable+0x70 + MxU32 VTable0xcc() override; // vtable+0xcc + MxU32 VTable0xd4(LegoControlManagerEvent& p_param) override; // vtable+0xd4 + MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 + MxU32 VTable0xdc(MxType19NotificationParam& p_param) override; // vtable+0xdc + void VTable0xe4() override; // vtable+0xe4 + + // SYNTHETIC: LEGO1 0x1004c950 + // TowTrack::`scalar deleting destructor' + +private: + // TODO: TowTrack field types + undefined m_unk0x154[4]; + MxS32 m_unk0x164; + MxS16 m_unk0x168; + MxS16 m_unk0x16a; + MxS16 m_unk0x16c; + MxS16 m_unk0x16e; + MxS32 m_unk0x170; + MxS32 m_unk0x174; + MxFloat m_unk0x178; + undefined4 m_unk0x17c; +}; + +#endif // TOWTRACK_H diff --git a/LEGO1/lego/legoomni/include/towtrackmissionstate.h b/LEGO1/lego/legoomni/include/towtrackmissionstate.h new file mode 100644 index 00000000..e96e87be --- /dev/null +++ b/LEGO1/lego/legoomni/include/towtrackmissionstate.h @@ -0,0 +1,65 @@ +#ifndef TOWTRACKMISSIONSTATE_H +#define TOWTRACKMISSIONSTATE_H + +#include "legostate.h" + +// VTABLE: LEGO1 0x100d7fd8 +// SIZE 0x28 +class TowTrackMissionState : public LegoState { +public: + TowTrackMissionState(); + + // FUNCTION: LEGO1 0x1004dfa0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f00bc + return "TowTrackMissionState"; + } + + // FUNCTION: LEGO1 0x1004dfb0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, TowTrackMissionState::ClassName()) || LegoState::IsA(p_name); + } + + MxResult VTable0x1c(LegoFile* p_legoFile) override; // vtable+0x1C + + inline MxU16 GetColor(MxU8 p_id) + { + switch (p_id) { + case 1: + return m_color1; + case 2: + return m_color2; + case 3: + return m_color3; + case 4: + return m_color4; + case 5: + return m_color5; + default: + return 0; + } + } + + // SYNTHETIC: LEGO1 0x1004e060 + // TowTrackMissionState::`scalar deleting destructor' + +protected: + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + MxU8 m_unk0x10; // 0x10 + MxU16 m_unk0x12; // 0x12 + MxU16 m_unk0x14; // 0x14 + MxU16 m_unk0x16; // 0x16 + MxU16 m_unk0x18; // 0x18 + MxU16 m_unk0x1a; // 0x1a + MxU16 m_unk0x1c; // 0x1c + MxU16 m_color1; // 0x1e + MxU16 m_color2; // 0x20 + MxU16 m_color3; // 0x22 + MxU16 m_color4; // 0x24 + MxU16 m_color5; // 0x26 +}; + +#endif // TOWTRACKMISSIONSTATE_H diff --git a/LEGO1/lego/legoomni/src/act1/act1state.cpp b/LEGO1/lego/legoomni/src/act1/act1state.cpp new file mode 100644 index 00000000..cd39f1e2 --- /dev/null +++ b/LEGO1/lego/legoomni/src/act1/act1state.cpp @@ -0,0 +1,34 @@ +#include "act1state.h" + +// 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 0x10033ac0 +MxResult Act1State::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x100346d0 +MxBool Act1State::SetFlag() +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x10034d00 +void Act1State::FUN_10034d00() +{ + // TODO +} diff --git a/LEGO1/act2brick.cpp b/LEGO1/lego/legoomni/src/act2/act2brick.cpp similarity index 80% rename from LEGO1/act2brick.cpp rename to LEGO1/lego/legoomni/src/act2/act2brick.cpp index 77e46622..338d2ae9 100644 --- a/LEGO1/act2brick.cpp +++ b/LEGO1/lego/legoomni/src/act2/act2brick.cpp @@ -12,6 +12,13 @@ Act2Brick::~Act2Brick() // TODO } +// STUB: LEGO1 0x1007a750 +MxS32 Act2Brick::VTable0x94() +{ + // TODO + return 0; +} + // STUB: LEGO1 0x1007a7f0 MxResult Act2Brick::Tickle() { diff --git a/LEGO1/act2policestation.cpp b/LEGO1/lego/legoomni/src/act2/act2policestation.cpp similarity index 100% rename from LEGO1/act2policestation.cpp rename to LEGO1/lego/legoomni/src/act2/act2policestation.cpp diff --git a/LEGO1/lego/legoomni/src/act2/legoact2.cpp b/LEGO1/lego/legoomni/src/act2/legoact2.cpp new file mode 100644 index 00000000..c32f407c --- /dev/null +++ b/LEGO1/lego/legoomni/src/act2/legoact2.cpp @@ -0,0 +1,54 @@ +#include "legoact2.h" + +// STUB: LEGO1 0x1004fe10 +MxBool LegoAct2::VTable0x5c() +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x1004ff20 +MxResult LegoAct2::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10050040 +MxResult LegoAct2::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10050380 +MxLong LegoAct2::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10050a80 +void LegoAct2::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x10050cf0 +void LegoAct2::Enable(MxBool p_enable) +{ + // TODO +} + +// STUB: LEGO1 0x100519c0 +void LegoAct2::VTable0x60() +{ + // TODO +} + +// STUB: LEGO1 0x100519d0 +MxBool LegoAct2::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/act2/legoact2state.cpp b/LEGO1/lego/legoomni/src/act2/legoact2state.cpp new file mode 100644 index 00000000..46b09a93 --- /dev/null +++ b/LEGO1/lego/legoomni/src/act2/legoact2state.cpp @@ -0,0 +1,8 @@ +#include "legoact2state.h" + +// STUB: LEGO1 0x1000df70 +MxBool LegoAct2State::VTable0x14() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/act3/act3.cpp b/LEGO1/lego/legoomni/src/act3/act3.cpp new file mode 100644 index 00000000..b0971ec4 --- /dev/null +++ b/LEGO1/lego/legoomni/src/act3/act3.cpp @@ -0,0 +1,96 @@ +#include "act3.h" + +DECOMP_SIZE_ASSERT(Act3, 0x4274) + +// STUB: LEGO1 0x10072270 +Act3::Act3() +{ + // TODO +} + +// STUB: LEGO1 0x10072500 +MxBool Act3::VTable0x5c() +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x100726a0 +Act3::~Act3() +{ + // TODO +} + +// STUB: LEGO1 0x100727e0 +MxBool Act3::FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) +{ + return FALSE; +} + +// STUB: LEGO1 0x10072980 +MxBool Act3::FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) +{ + return FALSE; +} + +// STUB: LEGO1 0x10072c30 +MxResult Act3::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10072d50 +void Act3::Destroy(MxBool p_fromDestructor) +{ + // TODO +} + +// STUB: LEGO1 0x10072de0 +MxLong Act3::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10073270 +void Act3::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x10073300 +MxResult Act3::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10073400 +void Act3::FUN_10073400() +{ +} + +// STUB: LEGO1 0x10073430 +void Act3::FUN_10073430() +{ +} + +// STUB: LEGO1 0x10073a90 +void Act3::Enable(MxBool p_enable) +{ + // TODO +} + +// STUB: LEGO1 0x10073e40 +void Act3::VTable0x60() +{ + // TODO +} + +// STUB: LEGO1 0x10073e50 +MxBool Act3::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/act3/act3shark.cpp b/LEGO1/lego/legoomni/src/act3/act3shark.cpp new file mode 100644 index 00000000..f695234d --- /dev/null +++ b/LEGO1/lego/legoomni/src/act3/act3shark.cpp @@ -0,0 +1,25 @@ +#include "act3shark.h" + +// STUB: LEGO1 0x1001a1c0 +void Act3Shark::VTable0x74(Matrix4& p_transform) +{ + // TODO +} + +// STUB: LEGO1 0x100430e0 +void Act3Shark::ParseAction(char*) +{ + // TODO +} + +// STUB: LEGO1 0x100430f0 +void Act3Shark::SetWorldSpeed(MxFloat p_worldSpeed) +{ + // TODO +} + +// STUB: LEGO1 0x10043100 +void Act3Shark::VTable0x70(float p_float) +{ + // TODO +} diff --git a/LEGO1/act3state.cpp b/LEGO1/lego/legoomni/src/act3/act3state.cpp similarity index 100% rename from LEGO1/act3state.cpp rename to LEGO1/lego/legoomni/src/act3/act3state.cpp diff --git a/LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp b/LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp new file mode 100644 index 00000000..580f3405 --- /dev/null +++ b/LEGO1/lego/legoomni/src/audio/lego3dwavepresenter.cpp @@ -0,0 +1,26 @@ +#include "lego3dwavepresenter.h" + +// STUB: LEGO1 0x1004a7c0 +MxResult Lego3DWavePresenter::AddToManager() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1004a7f0 +void Lego3DWavePresenter::Destroy() +{ + // TODO +} + +// STUB: LEGO1 0x1004a810 +void Lego3DWavePresenter::StartingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1004a8b0 +void Lego3DWavePresenter::StreamingTickle() +{ + // TODO +} diff --git a/LEGO1/legocachesound.cpp b/LEGO1/lego/legoomni/src/audio/legocachesound.cpp similarity index 85% rename from LEGO1/legocachesound.cpp rename to LEGO1/lego/legoomni/src/audio/legocachesound.cpp index eb58278c..a3855e88 100644 --- a/LEGO1/legocachesound.cpp +++ b/LEGO1/lego/legoomni/src/audio/legocachesound.cpp @@ -1,5 +1,7 @@ #include "legocachesound.h" +DECOMP_SIZE_ASSERT(LegoCacheSound, 0x88) + // FUNCTION: LEGO1 0x100064d0 LegoCacheSound::LegoCacheSound() { diff --git a/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp new file mode 100644 index 00000000..e9dec128 --- /dev/null +++ b/LEGO1/lego/legoomni/src/audio/legoloadcachesoundpresenter.cpp @@ -0,0 +1,77 @@ +#include "legoloadcachesoundpresenter.h" + +#include "legocachesound.h" +#include "mxstreamchunk.h" +#include "mxwavepresenter.h" + +DECOMP_SIZE_ASSERT(LegoLoadCacheSoundPresenter, 0x90) + +// FUNCTION: LEGO1 0x10018340 +LegoLoadCacheSoundPresenter::LegoLoadCacheSoundPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x10018480 +LegoLoadCacheSoundPresenter::~LegoLoadCacheSoundPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x100184e0 +void LegoLoadCacheSoundPresenter::Init() +{ + this->m_unk0x70 = NULL; + this->m_unk0x78 = 0; + this->m_unk0x7c = 0; +} + +// FUNCTION: LEGO1 0x100184f0 +void LegoLoadCacheSoundPresenter::Destroy(MxBool p_fromDestructor) +{ + delete[] this->m_unk0x70; + MxWavePresenter::Destroy(p_fromDestructor); +} + +// FUNCTION: LEGO1 0x10018510 +void LegoLoadCacheSoundPresenter::ReadyTickle() +{ + MxStreamChunk* chunk = NextChunk(); + + if (chunk) { + WaveFormat* header = (WaveFormat*) chunk->GetData(); + m_unk0x78 = 0; + + MxU8* data = new MxU8[header->m_dataSize]; + m_unk0x70 = data; + m_unk0x74 = data; + + m_cacheSound = new LegoCacheSound; + memcpy(&m_pcmWaveFormat, &header->m_pcmWaveFormat, sizeof(m_pcmWaveFormat)); + + m_subscriber->DestroyChunk(chunk); + ProgressTickleState(e_streaming); + } +} + +// STUB: LEGO1 0x100185f0 +void LegoLoadCacheSoundPresenter::StreamingTickle() +{ + // TODO + EndAction(); +} + +// FUNCTION: LEGO1 0x100186f0 +void LegoLoadCacheSoundPresenter::DoneTickle() +{ + if (m_unk0x7c != 0) { + EndAction(); + } +} + +// STUB: LEGO1 0x10018700 +MxResult LegoLoadCacheSoundPresenter::PutData() +{ + // TODO + return SUCCESS; +} diff --git a/LEGO1/legosoundmanager.cpp b/LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp similarity index 100% rename from LEGO1/legosoundmanager.cpp rename to LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp diff --git a/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp b/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp new file mode 100644 index 00000000..2ed5f178 --- /dev/null +++ b/LEGO1/lego/legoomni/src/audio/legounknown100d6b4c.cpp @@ -0,0 +1,7 @@ +#include "legounknown100d6b4c.h" + +// STUB: LEGO1 0x1003dc40 +void LegoUnknown100d6b4c::FUN_1003dc40(LegoCacheSound** p_und) +{ + // TODO +} diff --git a/LEGO1/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp similarity index 91% rename from LEGO1/mxbackgroundaudiomanager.cpp rename to LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index c4b8b6bd..581d97c5 100644 --- a/LEGO1/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -47,8 +47,9 @@ MxResult MxBackgroundAudioManager::Create(MxAtomId& p_script, MxU32 p_frequencyM // FUNCTION: LEGO1 0x1007ed20 MxResult MxBackgroundAudioManager::OpenMusic(MxAtomId& p_script) { - if (m_script.GetInternal()) + if (m_script.GetInternal()) { DestroyMusic(); + } MxResult result = FAILURE; @@ -77,18 +78,17 @@ void MxBackgroundAudioManager::DestroyMusic() MxResult MxBackgroundAudioManager::Tickle() { switch (m_unk0x13c) { - case MxPresenter::TickleState_Starting: + case MxPresenter::e_starting: FadeInOrFadeOut(); - return SUCCESS; - case MxPresenter::TickleState_Streaming: + break; + case MxPresenter::e_streaming: FUN_1007ee70(); - return SUCCESS; - case MxPresenter::TickleState_Repeating: + break; + case MxPresenter::e_repeating: FUN_1007ef40(); - return SUCCESS; - default: - return SUCCESS; } + + return SUCCESS; } // FUNCTION: LEGO1 0x1007ee70 @@ -104,26 +104,30 @@ void MxBackgroundAudioManager::FUN_1007ee70() m_unk0x138 = NULL; m_action2.SetObjectId(-1); m_action2.SetAtomId(MxAtomId()); - m_unk0x13c = NULL; + m_unk0x13c = 0; } } // FUNCTION: LEGO1 0x1007ef40 void MxBackgroundAudioManager::FUN_1007ef40() { - MxU32 compare; - MxU32 volume; + MxS32 compare, volume; + if (m_unk0xa0 == NULL) { if (m_unk0x138) { - compare = 30; - if (m_unk0x148 == 0) { - compare = m_unk0x148; + if (m_unk0x148 != 0) { + compare = 30; } + else { + compare = m_targetVolume; + } + volume = m_unk0x138->GetVolume(); if (volume < compare) { if (m_unk0x140 + m_unk0x138->GetVolume() <= compare) { - compare = m_unk0x140 + compare; + compare = m_unk0x140 + m_unk0x138->GetVolume(); } + m_unk0x138->SetVolume(compare); } else { @@ -133,7 +137,7 @@ void MxBackgroundAudioManager::FUN_1007ef40() m_unk0x138 = NULL; m_action2.SetObjectId(-1); m_action2.SetAtomId(MxAtomId()); - m_unk0x13c = NULL; + m_unk0x13c = 0; } } } @@ -142,12 +146,14 @@ void MxBackgroundAudioManager::FUN_1007ef40() DeleteObject(*m_unk0xa0->GetAction()); } else { - compare = m_unk0xa0->GetVolume(); - volume = 0; - if (compare != m_unk0x140 && -1 < compare - m_unk0x140) { + if (m_unk0xa0->GetVolume() - m_unk0x140 > 0) { volume = m_unk0xa0->GetVolume() - m_unk0x140; } - m_unk0x138->SetVolume(volume); + else { + volume = 0; + } + + m_unk0xa0->SetVolume(volume); } } } @@ -264,15 +270,17 @@ MxResult MxBackgroundAudioManager::PlayMusic(MxDSAction& p_action, undefined4 p_ // FUNCTION: LEGO1 0x1007f470 void MxBackgroundAudioManager::Stop() { - if (m_action2.GetObjectId() != -1) + if (m_action2.GetObjectId() != -1) { DeleteObject(m_action2); + } m_unk0x138 = 0; m_action2.SetAtomId(MxAtomId()); m_action2.SetObjectId(-1); - if (m_action1.GetObjectId() != -1) + if (m_action1.GetObjectId() != -1) { DeleteObject(m_action1); + } m_unk0xa0 = 0; m_action1.SetAtomId(MxAtomId()); diff --git a/LEGO1/buildingentity.cpp b/LEGO1/lego/legoomni/src/build/buildingentity.cpp similarity index 63% rename from LEGO1/buildingentity.cpp rename to LEGO1/lego/legoomni/src/build/buildingentity.cpp index 37a09f2f..37b0a8d9 100644 --- a/LEGO1/buildingentity.cpp +++ b/LEGO1/lego/legoomni/src/build/buildingentity.cpp @@ -11,3 +11,11 @@ BuildingEntity::~BuildingEntity() { // TODO } + +// STUB: LEGO1 0x100150a0 +MxLong BuildingEntity::Notify(MxParam& p_param) +{ + // TODO + + return 0; +} diff --git a/LEGO1/lego/legoomni/src/build/dunebuggy.cpp b/LEGO1/lego/legoomni/src/build/dunebuggy.cpp new file mode 100644 index 00000000..66fa23d2 --- /dev/null +++ b/LEGO1/lego/legoomni/src/build/dunebuggy.cpp @@ -0,0 +1,52 @@ +#include "dunebuggy.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(DuneBuggy, 0x16c); + +// FUNCTION: LEGO1 0x10067bb0 +DuneBuggy::DuneBuggy() +{ + this->m_unk0x13c = 25.0; + this->m_unk0x164 = 1.0; +} + +// STUB: LEGO1 0x10067e30 +MxResult DuneBuggy::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10067ec0 +void DuneBuggy::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x10067fa0 +void DuneBuggy::VTable0xe4() +{ + // TODO +} + +// STUB: LEGO1 0x10068060 +MxU32 DuneBuggy::VTable0xcc() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x100681b0 +MxU32 DuneBuggy::VTable0xd4(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10068270 +MxU32 DuneBuggy::VTable0xdc(MxType19NotificationParam& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/helicopter.cpp b/LEGO1/lego/legoomni/src/build/helicopter.cpp similarity index 60% rename from LEGO1/helicopter.cpp rename to LEGO1/lego/legoomni/src/build/helicopter.cpp index 87ee1dcb..7e836fcf 100644 --- a/LEGO1/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/build/helicopter.cpp @@ -3,6 +3,7 @@ #include "act1state.h" #include "act3.h" #include "isle.h" +#include "jukebox.h" #include "legoanimationmanager.h" #include "legocontrolmanager.h" #include "legogamestate.h" @@ -12,6 +13,9 @@ #include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(Helicopter, 0x230) +DECOMP_SIZE_ASSERT(Mx3DPointFloat, 0x14) +DECOMP_SIZE_ASSERT(Mx4DPointFloat, 0x18) +DECOMP_SIZE_ASSERT(MxMatrix, 0x48) // FUNCTION: LEGO1 0x10001e60 Helicopter::Helicopter() @@ -27,17 +31,18 @@ Helicopter::~Helicopter() } // FUNCTION: LEGO1 0x100032c0 -MxResult Helicopter::Create(MxDSObject& p_dsObject) +MxResult Helicopter::Create(MxDSAction& p_dsAction) { - MxResult result = IslePathActor::Create(p_dsObject); - LegoWorld* world = GetCurrentWorld(); + MxResult result = IslePathActor::Create(p_dsAction); + LegoWorld* world = CurrentWorld(); SetWorld(world); if (world->IsA("Act3")) { ((Act3*) GetWorld())->SetUnkown420c(this); } world = GetWorld(); - if (world) - world->VTable0x58(this); + if (world) { + world->Add(this); + } GetState(); return result; } @@ -46,8 +51,9 @@ MxResult Helicopter::Create(MxDSObject& p_dsObject) void Helicopter::GetState() { m_state = (HelicopterState*) GameState()->GetState("HelicopterState"); - if (!m_state) + if (!m_state) { m_state = (HelicopterState*) GameState()->CreateState("HelicopterState"); + } } // FUNCTION: LEGO1 0x10003360 @@ -58,10 +64,10 @@ void Helicopter::VTable0xe4() } IslePathActor::VTable0xe4(); if (!GameState()->GetUnknown10()) { - GameState()->SetUnknown424(0x3c); - if (GetCurrentVehicle()) { - if (GetCurrentVehicle()->IsA("IslePathActor")) { - ((IslePathActor*) GetCurrentVehicle())->VTable0xe8(0x37, TRUE, 7); + GameState()->SetCurrentArea(0x3c); + if (CurrentVehicle()) { + if (CurrentVehicle()->IsA("IslePathActor")) { + ((IslePathActor*) CurrentVehicle())->VTable0xe8(0x37, TRUE, 7); } } } @@ -83,14 +89,16 @@ void Helicopter::VTable0xe4() // FUNCTION: LEGO1 0x10003480 MxU32 Helicopter::VTable0xcc() { - if (!FUN_1003ef60()) + if (!FUN_1003ef60()) { return 1; - if (!m_world) - m_world = GetCurrentWorld(); + } + if (!m_world) { + m_world = CurrentWorld(); + } AnimationManager()->FUN_1005f6d0(FALSE); - if (GetCurrentVehicle()) { - if (GetCurrentVehicle()->VTable0x60() != GameState()->GetUnknownC()) { - GetCurrentVehicle()->VTable0xe4(); + if (CurrentVehicle()) { + if (CurrentVehicle()->VTable0x60() != GameState()->GetUnknownC()) { + CurrentVehicle()->VTable0xe4(); } } switch (GameState()->GetUnknown10()) { @@ -98,11 +106,11 @@ MxU32 Helicopter::VTable0xcc() m_script = *g_isleScript; AnimationManager()->FUN_10064670(FALSE); VTable0xe8(0x29, TRUE, 7); - ((Isle*) GetCurrentWorld())->SetUnknown13c(0x3c); - FUN_10015820(1, 0); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, TRUE); + ((Isle*) CurrentWorld())->SetUnknown13c(0x3c); + FUN_10015820(TRUE, 0); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, TRUE); SetUnknownDC(4); - PlayMusic(9); + PlayMusic(JukeBox::e_jail); break; case 1: m_script = *g_act2mainScript; @@ -112,14 +120,14 @@ 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; } // FUNCTION: LEGO1 0x100035e0 -MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) +MxU32 Helicopter::VTable0xd4(LegoControlManagerEvent& p_param) { MxU32 ret = 0; MxAtomId script; @@ -134,76 +142,84 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) script = *g_act3Script; break; } - if (p_param.GetUnknown28() == 1) { - switch (p_param.GetUnknown20()) { + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { case 0x17: if (*g_act3Script == script) { - ((Act3*) GetCurrentWorld())->SetUnkown4270(2); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, FALSE); + ((Act3*) CurrentWorld())->SetUnkown4270(2); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); } - else if (m_state->GetUnkown8() != 0) + else if (m_state->GetUnkown8() != 0) { break; + } VTable0xe4(); - GameState()->SetUnknown424(0x42); + GameState()->SetCurrentArea(0x42); ret = 1; break; case 0x18: { - if (*g_act3Script == script) + if (*g_act3Script == script) { break; + } Act1State* state = (Act1State*) GameState()->GetState("Act1State"); if (m_state->GetUnkown8() == 0) { state->SetUnknown18(4); 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; break; } case 0x19: - if (*g_act3Script == script) + if (*g_act3Script == script) { break; + } if (m_state->GetUnkown8() == 2) { m_state->SetUnknown8(3); m_world->FUN_1001fc80(this); - InvokeAction(ExtraActionType_start, script, 0x21, NULL); + InvokeAction(Extra::ActionType::e_start, script, 0x21, NULL); SetUnknownDC(4); } ret = 1; break; case 0x1a: - if (*g_act3Script != script) + if (*g_act3Script != script) { break; + } ret = 1; /* fall through */ case 0x1b: - if (*g_act3Script != script) + if (*g_act3Script != script) { break; + } if (m_world && m_world->GetCamera()) { - 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) - if (m_world->FUN_100727e0(m_unk0x138, loc, dir, v7c)) + if (ret) { + if (((Act3*) m_world)->FUN_100727e0(m_unk0x138, loc, dir, v7c)) { break; - else if (m_world->FUN_10072980(m_unk0x138, loc, dir, v7c)) + } + else if (((Act3*) m_world)->FUN_10072980(m_unk0x138, loc, dir, v7c)) { break; + } + } } ret = 1; break; case 0x1c: if (GameState()->GetUnknown10() == 0) { - ((Isle*) GetCurrentWorld())->SetUnknown13c(2); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, FALSE); + ((Isle*) CurrentWorld())->SetUnknown13c(2); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); VTable0xe4(); } ret = 1; @@ -219,52 +235,66 @@ 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) { ((Act1State*) GameState()->GetState("Act1State"))->SetUnknown18(4); VTable0xe8(0x2a, TRUE, 7); } - else + 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]); - m_world->GetCamera()->LookAt(at, dir, up); + + 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()->LookAt(at, dir, up); + m_world->GetCamera()->SetWorldTransform(at, dir, up); + if (GameState()->GetUnknown10() == 0) { ((Act1State*) GameState()->GetState("Act1State"))->SetUnknown18(0); VTable0xe8(0x29, TRUE, 7); } - else + 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); @@ -273,8 +303,9 @@ void Helicopter::VTable0x74(Matrix4Impl& p_transform) else { m_roi->FUN_100a58f0(p_transform); m_roi->VTable0x14(); - if (m_cameraFlag) + if (m_cameraFlag) { FUN_10010c30(); + } } } @@ -291,17 +322,19 @@ void Helicopter::VTable0x70(float p_float) float f = m_unk0x1f0 - p_float + 3000; if (f >= 0) { float f2 = f / 3000 + 1; - if (f2 < 0) + if (f2 < 0) { f2 = 0; - if (1.0f < f2) + } + if (1.0f < f2) { f2 = 1.0f; - 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); } @@ -312,32 +345,33 @@ void Helicopter::VTable0x70(float p_float) m_world->GetCamera()->FUN_100123e0(mat, 0); } else { - if (state == 4) - m_world->FUN_10073400(); - else - m_world->FUN_10073430(); + if (state == 4) { + ((Act3*) m_world)->FUN_10073400(); + } + else { + ((Act3*) m_world)->FUN_10073430(); + } m_unk0xdc = 4; } } } // 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_unk0x00.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) { - double d1 = p_v.Dot(&m_unk0x0, &m_unk0x18), d2; + double d1 = p_v.Dot(&m_unk0x00, &m_unk0x18), d2; if (d1 + 1 > 0.00001) { if (1 - d1 > 0.00001) { double d = acos(d1); @@ -350,21 +384,22 @@ MxResult HelicopterSubclass::FUN_100040a0(Vector4Impl& p_v, float p_f) d2 = p_f; } for (MxS32 i = 0; i < 4; i++) { - p_v[i] = m_unk0x18[i] * d2 + m_unk0x0[i] * d1; + p_v[i] = m_unk0x18[i] * d2 + m_unk0x00[i] * d1; } return SUCCESS; } - p_v[0] = -m_unk0x0[1]; - p_v[1] = m_unk0x0[1]; - p_v[2] = -m_unk0x0[3]; - p_v[3] = m_unk0x0[2]; + p_v[0] = -m_unk0x00[1]; + p_v[1] = m_unk0x00[1]; + p_v[2] = -m_unk0x00[3]; + p_v[3] = m_unk0x00[2]; d1 = sin((1 - p_f) * 1.570796326794895); d2 = sin(p_f * 1.570796326794895); for (MxS32 i = 0; i < 3; i++) { - p_v[i] = m_unk0x0[i] * d1 + p_v[i] * d2; + p_v[i] = m_unk0x00[i] * d1 + p_v[i] * d2; } return SUCCESS; } - else + else { return FAILURE; + } } diff --git a/LEGO1/helicopterstate.cpp b/LEGO1/lego/legoomni/src/build/helicopterstate.cpp similarity index 100% rename from LEGO1/helicopterstate.cpp rename to LEGO1/lego/legoomni/src/build/helicopterstate.cpp diff --git a/LEGO1/lego/legoomni/src/build/jetski.cpp b/LEGO1/lego/legoomni/src/build/jetski.cpp new file mode 100644 index 00000000..7a5a3dcd --- /dev/null +++ b/LEGO1/lego/legoomni/src/build/jetski.cpp @@ -0,0 +1,44 @@ +#include "jetski.h" + +DECOMP_SIZE_ASSERT(Jetski, 0x164); + +// FUNCTION: LEGO1 0x1007e3b0 +Jetski::Jetski() +{ + this->m_unk0x13c = 25.0; + this->m_unk0x150 = 2.0; + this->m_unk0x148 = 1; +} + +// STUB: LEGO1 0x1007e630 +MxResult Jetski::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1007e680 +void Jetski::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x1007e6f0 +void Jetski::VTable0xe4() +{ + // TODO +} + +// STUB: LEGO1 0x1007e750 +MxU32 Jetski::VTable0xcc() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1007e8e0 +MxU32 Jetski::VTable0xd4(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp similarity index 66% rename from LEGO1/legobuildingmanager.cpp rename to LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index 34652509..cb5fad99 100644 --- a/LEGO1/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -26,3 +26,22 @@ void LegoBuildingManager::Init() { // TODO } + +// STUB: LEGO1 0x1002fa00 +void LegoBuildingManager::FUN_1002fa00() +{ + // TODO +} + +// STUB: LEGO1 0x1002fb30 +void LegoBuildingManager::FUN_1002fb30() +{ + // TODO +} + +// STUB: LEGO1 0x10030220 +MxResult LegoBuildingManager::Tickle() +{ + // TODO + return SUCCESS; +} diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp new file mode 100644 index 00000000..09651ba2 --- /dev/null +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -0,0 +1,62 @@ +#include "legocarbuild.h" + +// STUB: LEGO1 0x100226d0 +LegoCarBuild::LegoCarBuild() +{ + // TODO +} + +// STUB: LEGO1 0x10022930 +MxBool LegoCarBuild::VTable0x5c() +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x10022a80 +LegoCarBuild::~LegoCarBuild() +{ + // TODO +} + +// STUB: LEGO1 0x10022b70 +MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x100238b0 +MxResult LegoCarBuild::Tickle() +{ + // TODO + + return 0; +} + +// STUB: LEGO1 0x10024050 +MxLong LegoCarBuild::Notify(MxParam& p_param) +{ + // TODO + + return 0; +} + +// STUB: LEGO1 0x100242c0 +void LegoCarBuild::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x100256c0 +void LegoCarBuild::Enable(MxBool p_enable) +{ + // TODO +} + +// STUB: LEGO1 0x10025e70 +MxBool LegoCarBuild::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/legovehiclebuildstate.cpp b/LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp similarity index 52% rename from LEGO1/legovehiclebuildstate.cpp rename to LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp index b0dccde2..8cf60edd 100644 --- a/LEGO1/legovehiclebuildstate.cpp +++ b/LEGO1/lego/legoomni/src/build/legovehiclebuildstate.cpp @@ -2,17 +2,7 @@ #include "decomp.h" -DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50); // 1000acd7 -DECOMP_SIZE_ASSERT(LegoVehicleBuildState::UnkStruct, 0xc); - -// FUNCTION: LEGO1 0x10017c00 -LegoVehicleBuildState::UnkStruct::UnkStruct() -{ - m_unk0x04 = 0; - m_unk0x00 = 0; - m_unk0x06 = 0; - m_unk0x08 = 0; -} +DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) // FUNCTION: LEGO1 0x10025f30 LegoVehicleBuildState::LegoVehicleBuildState(char* p_classType) @@ -23,3 +13,10 @@ LegoVehicleBuildState::LegoVehicleBuildState(char* p_classType) this->m_unk0x4e = 0; this->m_placedPartCount = 0; } + +// STUB: LEGO1 0x10026120 +MxResult LegoVehicleBuildState::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return SUCCESS; +} diff --git a/LEGO1/lego/legoomni/src/build/racecar.cpp b/LEGO1/lego/legoomni/src/build/racecar.cpp new file mode 100644 index 00000000..a057b8a4 --- /dev/null +++ b/LEGO1/lego/legoomni/src/build/racecar.cpp @@ -0,0 +1,33 @@ +#include "racecar.h" + +#include "legocontrolmanager.h" +#include "legoomni.h" + +DECOMP_SIZE_ASSERT(RaceCar, 0x164); + +// FUNCTION: LEGO1 0x10028200 +RaceCar::RaceCar() +{ + m_unk0x13c = 40.0; +} + +// FUNCTION: LEGO1 0x10028420 +RaceCar::~RaceCar() +{ + ControlManager()->Unregister(this); + VTable0xe4(); +} + +// STUB: LEGO1 0x10028490 +MxResult RaceCar::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x100284d0 +MxU32 RaceCar::VTable0xcc() +{ + // TODO + return 0; +} diff --git a/LEGO1/animstate.cpp b/LEGO1/lego/legoomni/src/common/animstate.cpp similarity index 82% rename from LEGO1/animstate.cpp rename to LEGO1/lego/legoomni/src/common/animstate.cpp index 1a08890b..c7665237 100644 --- a/LEGO1/animstate.cpp +++ b/LEGO1/lego/legoomni/src/common/animstate.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(AnimState, 0x1c); // FUNCTION: LEGO1 0x10064ff0 AnimState::AnimState() { - m_unk0xc = 0; + m_unk0x0c = 0; m_unk0x10 = NULL; m_unk0x14 = 0; m_unk0x18 = NULL; @@ -18,7 +18,7 @@ AnimState::~AnimState() } // STUB: LEGO1 0x100652d0 -MxResult AnimState::VTable0x1c(LegoFileStream* p_legoFileStream) +MxResult AnimState::VTable0x1c(LegoFile* p_legoFile) { // TODO return FAILURE; diff --git a/LEGO1/lego/legoomni/src/common/gifmanager.cpp b/LEGO1/lego/legoomni/src/common/gifmanager.cpp new file mode 100644 index 00000000..09e25c5e --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/gifmanager.cpp @@ -0,0 +1,62 @@ +#include "gifmanager.h" + +DECOMP_SIZE_ASSERT(GifData, 0x14); +DECOMP_SIZE_ASSERT(GifMap, 0x10); +DECOMP_SIZE_ASSERT(GifManagerBase, 0x18); +DECOMP_SIZE_ASSERT(GifManager, 0x24); + +// FUNCTION: LEGO1 0x10065c00 +GifData::~GifData() +{ + if (m_name) { + delete[] m_name; + m_name = NULL; + } + + if (m_palette) { + m_palette->Release(); + m_palette = NULL; + } + + if (m_surface) { + m_surface->Release(); + m_surface = NULL; + } + + if (m_texture) { + m_texture->Release(); + m_texture = NULL; + } +} + +// FUNCTION: LEGO1 0x10099870 +GifManager::~GifManager() +{ +} + +// FUNCTION: LEGO1 0x10099cc0 +void GifManager::FUN_10099cc0(GifData* p_data) +{ + if (p_data == NULL) { + return; + } + +#ifdef COMPAT_MODE + GifList::iterator it; + for (it = m_list.begin(); it != m_list.end(); it++) { +#else + for (GifList::iterator it = m_list.begin(); it != m_list.end(); it++) { +#endif + if (*it == p_data) { + // TODO: This is wrong, but what is at +0x0c on the iterator? + *it = NULL; + + if (p_data->m_texture->Release() == TRUE) { + delete p_data; + m_list.erase(it); + } + + return; + } + } +} diff --git a/LEGO1/legoactioncontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp similarity index 61% rename from LEGO1/legoactioncontrolpresenter.cpp rename to LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp index 88c3143f..370b54c7 100644 --- a/LEGO1/legoactioncontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp @@ -4,22 +4,50 @@ #include "extra.h" #include "legoomni.h" #include "legoutil.h" +#include "mxcompositepresenter.h" #include "mxmediapresenter.h" #include "mxomni.h" +#include "mxstreamchunk.h" #include "mxticklemanager.h" DECOMP_SIZE_ASSERT(LegoActionControlPresenter, 0x68) -// STUB: LEGO1 0x10043ce0 +// FUNCTION: LEGO1 0x10043ce0 void LegoActionControlPresenter::ReadyTickle() { - // TODO + MxStreamChunk* chunk = NextChunk(); + + if (chunk) { + ParseExtra(); + ProgressTickleState(e_starting); + + m_subscriber->DestroyChunk(chunk); + if (m_compositePresenter) { + if (m_action->GetDuration() == -1 || m_action->GetFlags() & 1) { + m_compositePresenter->VTable0x60(this); + } + } + } } -// STUB: LEGO1 0x10043d40 +// FUNCTION: LEGO1 0x10043d40 void LegoActionControlPresenter::RepeatingTickle() { - // TODO + if (IsEnabled()) { + if (m_unk0x50 == 0) { + ParseExtra(); + } + +#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); + } } // FUNCTION: LEGO1 0x10043df0 @@ -52,8 +80,9 @@ void LegoActionControlPresenter::ParseExtra() { MxU32 len = m_action->GetExtraLength(); - if (len == 0) + if (len == 0) { return; + } len &= MAXWORD; @@ -64,11 +93,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/legobackgroundcolor.cpp b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp similarity index 81% rename from LEGO1/legobackgroundcolor.cpp rename to LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp index e682356b..461e84db 100644 --- a/LEGO1/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 @@ -26,8 +34,9 @@ void LegoBackgroundColor::SetValue(const char* p_colorString) m_value.ToLowerCase(); LegoVideoManager* videomanager = VideoManager(); - if (!videomanager || !p_colorString) + if (!videomanager || !p_colorString) { return; + } float convertedR, convertedG, convertedB; char* colorStringCopy = strcpy(new char[strlen(p_colorString) + 1], p_colorString); @@ -35,14 +44,17 @@ void LegoBackgroundColor::SetValue(const char* p_colorString) if (!strcmp(colorStringSplit, g_set)) { colorStringSplit = strtok(0, g_delimiter); - if (colorStringSplit) + if (colorStringSplit) { m_h = (float) (atoi(colorStringSplit) * 0.01); + } colorStringSplit = strtok(0, g_delimiter); - if (colorStringSplit) + if (colorStringSplit) { m_s = (float) (atoi(colorStringSplit) * 0.01); + } colorStringSplit = strtok(0, g_delimiter); - if (colorStringSplit) + if (colorStringSplit) { m_v = (float) (atoi(colorStringSplit) * 0.01); + } ConvertHSVToRGB(m_h, m_s, m_v, &convertedR, &convertedG, &convertedB); videomanager->SetSkyColor(convertedR, convertedG, convertedB); diff --git a/LEGO1/legofullscreenmovie.cpp b/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp similarity index 88% rename from LEGO1/legofullscreenmovie.cpp rename to LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp index 110a88d0..b10b285f 100644 --- a/LEGO1/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 new file mode 100644 index 00000000..864bb258 --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -0,0 +1,626 @@ +#include "legogamestate.h" + +#include "infocenterstate.h" +#include "legoanimationmanager.h" +#include "legoomni.h" +#include "legostate.h" +#include "legoutil.h" +#include "legovideomanager.h" +#include "legoworld.h" +#include "mxbackgroundaudiomanager.h" +#include "mxobjectfactory.h" +#include "mxstring.h" +#include "mxvariabletable.h" +#include "roi/legoroi.h" + +#include + +// Based on the highest dword offset (0x42c) referenced in the constructor. +// There may be other members that come after. +DECOMP_SIZE_ASSERT(LegoGameState, 0x430) + +// GLOBAL: LEGO1 0x100f3e40 +// STRING: LEGO1 0x100f3e3c +const char* g_fileExtensionGS = ".GS"; + +// GLOBAL: LEGO1 0x100f3e44 +// STRING: LEGO1 0x100f3e30 +const char* g_playersGSI = "Players.gsi"; + +// GLOBAL: LEGO1 0x100f3e48 +// STRING: LEGO1 0x100f3e24 +const char* g_historyGSI = "History.gsi"; + +// This is a pointer to the end of the global variable name table, which has +// the text "END_OF_VARIABLES" in it. +// TODO: make g_endOfVariables reference the actual end of the variable array. +// GLOBAL: LEGO1 0x100f3e50 +// STRING: LEGO1 0x100f3e00 +const char* g_endOfVariables = "END_OF_VARIABLES"; + +// GLOBAL: LEGO1 0x100f3e58 +ColorStringStruct g_colorSaveData[43] = { + {"c_dbbkfny0", "lego red"}, {"c_dbbkxly0", "lego white"}, {"c_chbasey0", "lego black"}, + {"c_chbacky0", "lego black"}, {"c_chdishy0", "lego white"}, {"c_chhorny0", "lego black"}, + {"c_chljety1", "lego black"}, {"c_chrjety1", "lego black"}, {"c_chmidly0", "lego black"}, + {"c_chmotry0", "lego blue"}, {"c_chsidly0", "lego black"}, {"c_chsidry0", "lego black"}, + {"c_chstuty0", "lego black"}, {"c_chtaily0", "lego black"}, {"c_chwindy1", "lego black"}, + {"c_dbfbrdy0", "lego red"}, {"c_dbflagy0", "lego yellow"}, {"c_dbfrfny4", "lego red"}, + {"c_dbfrxly0", "lego white"}, {"c_dbhndly0", "lego white"}, {"c_dbltbry0", "lego white"}, + {"c_jsdashy0", "lego white"}, {"c_jsexhy0", "lego black"}, {"c_jsfrnty5", "lego black"}, + {"c_jshndly0", "lego red"}, {"c_jslsidy0", "lego black"}, {"c_jsrsidy0", "lego black"}, + {"c_jsskiby0", "lego red"}, {"c_jswnshy5", "lego white"}, {"c_rcbacky6", "lego green"}, + {"c_rcedgey0", "lego green"}, {"c_rcfrmey0", "lego red"}, {"c_rcfrnty6", "lego green"}, + {"c_rcmotry0", "lego white"}, {"c_rcsidey0", "lego green"}, {"c_rcstery0", "lego white"}, + {"c_rcstrpy0", "lego yellow"}, {"c_rctailya", "lego white"}, {"c_rcwhl1y0", "lego white"}, + {"c_rcwhl2y0", "lego white"}, {"c_jsbasey0", "lego white"}, {"c_chblady0", "lego black"}, + {"c_chseaty0", "lego white"}, +}; + +// NOTE: This offset = the end of the variables table, the last entry +// in that table is a special entry, the string "END_OF_VARIABLES" +extern const char* g_endOfVariables; + +// FUNCTION: LEGO1 0x10039550 +LegoGameState::LegoGameState() +{ + // TODO + SetROIHandlerFunction(); + + this->m_stateCount = 0; + this->m_unk0x0c = 0; + this->m_savePath = NULL; + this->m_currentArea = 0; + this->m_previousArea = 0; + this->m_unk0x42c = 0; + this->m_isDirty = FALSE; + this->m_currentAct = -1; + + m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68"); + VariableTable()->SetVariable(m_backgroundColor); + + m_tempBackgroundColor = new LegoBackgroundColor("tempBackgroundcolor", "set 56 54 68"); + VariableTable()->SetVariable(m_tempBackgroundColor); + + m_fullScreenMovie = new LegoFullScreenMovie("fsmovie", "disable"); + VariableTable()->SetVariable(m_fullScreenMovie); + + VariableTable()->SetVariable("lightposition", "2"); + SerializeScoreHistory(1); +} + +// FUNCTION: LEGO1 0x10039720 +LegoGameState::~LegoGameState() +{ + LegoROI::SetSomeHandlerFunction(NULL); + + if (m_stateCount) { + for (MxS16 i = 0; i < m_stateCount; i++) { + LegoState* state = m_stateArray[i]; + if (state) { + delete state; + } + } + + delete[] m_stateArray; + } + + delete[] m_savePath; +} + +// STUB: LEGO1 0x10039780 +void LegoGameState::FUN_10039780(MxU8) +{ + // TODO +} + +// STUB: LEGO1 0x10039940 +void LegoGameState::FUN_10039940() +{ + // TODO +} + +// FUNCTION: LEGO1 0x10039980 +MxResult LegoGameState::Save(MxULong p_slot) +{ + MxResult result; + InfocenterState* infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); + + if (!infocenterState || infocenterState->GetInfocenterBufferElement(0) == NULL) { + result = SUCCESS; + } + else { + result = FAILURE; + MxVariableTable* variableTable = VariableTable(); + MxString savePath; + GetFileSavePath(&savePath, p_slot); + LegoFile fileStream; + if (fileStream.Open(savePath.GetData(), LegoFile::c_write) != FAILURE) { + MxU32 maybeVersion = 0x1000C; + fileStream.Write(&maybeVersion, 4); + fileStream.Write(&m_unk0x24, 2); + fileStream.Write(&m_unk0x10, 2); + fileStream.Write(&m_unk0x0c, 1); + + for (MxS32 i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) { + if (WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) { + return result; + } + } + + if (WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) { + if (WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) { + WriteEndOfVariables(&fileStream); + + // TODO: Calls down to more aggregate writing functions + return SUCCESS; + } + } + } + } + return result; +} + +// STUB: LEGO1 0x10039c60 +MxResult LegoGameState::Load(MxULong) +{ + // TODO + return 0; +} + +// FUNCTION: LEGO1 0x10039f00 +void LegoGameState::SetSavePath(char* p_savePath) +{ + if (m_savePath != NULL) { + delete[] m_savePath; + } + + if (p_savePath) { + m_savePath = new char[strlen(p_savePath) + 1]; + strcpy(m_savePath, p_savePath); + } + else { + m_savePath = NULL; + } +} + +// FUNCTION: LEGO1 0x10039f70 +MxResult LegoGameState::WriteVariable(LegoStorage* p_stream, MxVariableTable* p_from, const char* p_variableName) +{ + MxResult result = FAILURE; + const char* variableValue = p_from->GetVariable(p_variableName); + + if (variableValue) { + MxU8 length = strlen(p_variableName); + if (p_stream->Write((char*) &length, 1) == SUCCESS) { + if (p_stream->Write(p_variableName, length) == SUCCESS) { + length = strlen(variableValue); + if (p_stream->Write((char*) &length, 1) == SUCCESS) { + result = p_stream->Write((char*) variableValue, length); + } + } + } + } + return result; +} + +// FUNCTION: LEGO1 0x1003a020 +MxResult LegoGameState::WriteEndOfVariables(LegoStorage* p_stream) +{ + MxU8 len = strlen(g_endOfVariables); + if (p_stream->Write(&len, 1) == SUCCESS) { + return p_stream->Write(g_endOfVariables, len); + } + return FAILURE; +} + +// 95% match, just some instruction ordering differences on the call to +// MxVariableTable::SetVariable at the end. +// FUNCTION: LEGO1 0x1003a080 +MxS32 LegoGameState::ReadVariable(LegoStorage* p_stream, MxVariableTable* p_to) +{ + MxS32 result = 1; + MxU8 length; + + if (p_stream->Read((char*) &length, 1) == SUCCESS) { + char nameBuffer[256]; + if (p_stream->Read(nameBuffer, length) == SUCCESS) { + nameBuffer[length] = '\0'; + if (strcmp(nameBuffer, g_endOfVariables) == 0) { + // 2 -> "This was the last entry, done reading." + result = 2; + } + else { + if (p_stream->Read((char*) &length, 1) == SUCCESS) { + char valueBuffer[256]; + if (p_stream->Read(valueBuffer, length) == SUCCESS) { + result = 0; + valueBuffer[length] = '\0'; + p_to->SetVariable(nameBuffer, valueBuffer); + } + } + } + } + } + return result; +} + +// FUNCTION: LEGO1 0x1003a170 +void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) +{ + char baseForSlot[2] = "0"; + char path[1024] = ""; + + // Save path base + if (m_savePath != NULL) { + strcpy(path, m_savePath); + } + + // Slot: "G0", "G1", ... + strcat(path, "\\G"); + baseForSlot[0] += p_slotn; + strcat(path, baseForSlot); + + // Extension: ".GS" + strcat(path, g_fileExtensionGS); + *p_outPath = MxString(path); +} + +// STUB: LEGO1 0x1003a2e0 +void LegoGameState::SerializePlayersInfo(MxS16) +{ + // TODO +} + +// FUNCTION: LEGO1 0x1003a720 +void LegoGameState::StopArea(MxU32 p_area) +{ + if (p_area == 0) { + p_area = m_previousArea; + } + + switch (p_area) { + case 1: + InvokeAction(Extra::e_stop, *g_isleScript, 0, NULL); + InvokeAction(Extra::e_close, *g_isleScript, 0, NULL); + InvokeAction(Extra::e_close, *g_sndAnimScript, 0, NULL); + break; + case 2: + InvokeAction(Extra::e_stop, *g_infomainScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infomainScript, 0, NULL); + break; + case 3: + InvokeAction(Extra::e_stop, *g_infodoorScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infodoorScript, 0, NULL); + break; + case 5: + InvokeAction(Extra::e_stop, *g_elevbottScript, 0, NULL); + InvokeAction(Extra::e_close, *g_elevbottScript, 0, NULL); + break; + case 6: + case 7: + RemoveFromWorld(*g_isleScript, 0x41b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 1052, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x41d, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x41e, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x420, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x422, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x424, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x426, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x428, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x42a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x42b, *g_isleScript, 0); + break; + case 8: + RemoveFromWorld(*g_isleScript, 0x45b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x45c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x45d, *g_isleScript, 0); + break; + case 9: + RemoveFromWorld(*g_isleScript, 0x475, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x476, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x477, *g_isleScript, 0); + break; + case 10: + RemoveFromWorld(*g_isleScript, 0x45f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x460, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x461, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x462, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x463, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x464, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x465, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x466, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x467, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x469, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x468, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46d, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46e, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x471, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x472, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x12, *g_isleScript, 0); + break; + case 0xb: + RemoveFromWorld(*g_isleScript, 0x47a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47d, *g_isleScript, 0); + break; + case 0xc: + InvokeAction(Extra::e_stop, *g_regbookScript, 0, NULL); + InvokeAction(Extra::e_close, *g_regbookScript, 0, NULL); + break; + case 0xd: + InvokeAction(Extra::e_stop, *g_infoscorScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infoscorScript, 0, NULL); + break; + case 0xe: + InvokeAction(Extra::e_stop, *g_jetraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetracerScript, 0, NULL); + break; + case 0x12: + InvokeAction(Extra::e_stop, *g_carraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_carraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_carracerScript, 0, NULL); + break; + case 0x1a: + Lego()->RemoveWorld(*g_garageScript, 0); + InvokeAction(Extra::e_stop, *g_garageScript, 0, NULL); + InvokeAction(Extra::e_close, *g_garageScript, 0, NULL); + break; + case 0x1b: + RemoveFromWorld(*g_isleScript, 0x489, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48c, *g_isleScript, 0); + break; + case 0x1e: + InvokeAction(Extra::e_stop, *g_hospitalScript, 0, NULL); + InvokeAction(Extra::e_close, *g_hospitalScript, 0, NULL); + break; + case 0x22: + InvokeAction(Extra::e_stop, *g_policeScript, 0, NULL); + InvokeAction(Extra::e_close, *g_policeScript, 0, NULL); + break; + case 0x23: + RemoveFromWorld(*g_isleScript, 0x47f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x480, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x481, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x482, *g_isleScript, 0); + break; + case 0x24: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x2f, NULL); + InvokeAction(Extra::e_stop, *g_copterScript, 0, NULL); + InvokeAction(Extra::e_close, *g_copterScript, 0, NULL); + break; + case 0x25: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x31, NULL); + InvokeAction(Extra::e_stop, *g_dunecarScript, 0, NULL); + InvokeAction(Extra::e_close, *g_dunecarScript, 0, NULL); + break; + case 0x26: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x33, NULL); + InvokeAction(Extra::e_stop, *g_jetskiScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetskiScript, 0, NULL); + break; + case 0x27: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x35, NULL); + InvokeAction(Extra::e_stop, *g_racecarScript, 0, NULL); + InvokeAction(Extra::e_close, *g_racecarScript, 0, NULL); + break; + case 0x2e: + if (m_currentArea != 2) { + InvokeAction(Extra::e_stop, *g_act2mainScript, 0, NULL); + InvokeAction(Extra::e_close, *g_act2mainScript, 0, NULL); + } + break; + case 0x2f: + if (m_currentArea != 2) { + InvokeAction(Extra::e_stop, *g_act3Script, 0, NULL); + InvokeAction(Extra::e_close, *g_act3Script, 0, NULL); + } + break; + case 0x35: + InvokeAction(Extra::e_stop, *g_jukeboxwScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jukeboxwScript, 0, NULL); + break; + case 0x38: + InvokeAction(Extra::e_disable, *g_histbookScript, 0, NULL); + InvokeAction(Extra::e_stop, *g_histbookScript, 0, NULL); + InvokeAction(Extra::e_close, *g_histbookScript, 0, NULL); + break; + } +} + +// STUB: LEGO1 0x1003b060 +void LegoGameState::SwitchArea(MxU32 p_area) +{ + m_previousArea = m_currentArea; + m_currentArea = p_area; + + BackgroundAudioManager()->Stop(); + AnimationManager()->FUN_1005ef10(); + VideoManager()->SetUnk0x554(FALSE); + + MxAtomId* script = g_isleScript; + LegoWorld* world; + + switch (p_area) { + case 1: + break; + case 2: + VideoManager()->SetUnk0x554(TRUE); + script = g_infomainScript; + break; + case 3: + VideoManager()->SetUnk0x554(TRUE); + script = g_infodoorScript; + break; + // TODO + case 5: + script = g_elevbottScript; + break; + case 6: + case 7: + world = FindWorld(*g_isleScript, 0); + + if (world == NULL) { + InvokeAction(Extra::ActionType::e_opendisk, *g_isleScript, 0, NULL); + } + else { +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType20, NULL); + NotificationManager()->Send(world, ¶m); + } +#else + NotificationManager()->Send(world, &MxNotificationParam(c_notificationType20, NULL)); +#endif + } + break; + case 12: + VideoManager()->SetUnk0x554(TRUE); + script = g_regbookScript; + break; + case 13: + VideoManager()->SetUnk0x554(TRUE); + script = g_infoscorScript; + break; + + // TODO: implement other cases + } + + InvokeAction(Extra::ActionType::e_opendisk, *script, 0, NULL); +} + +// FUNCTION: LEGO1 0x1003bac0 +void LegoGameState::SetROIHandlerFunction() +{ + LegoROI::SetSomeHandlerFunction(&ROIHandlerFunction); +} + +// FUNCTION: LEGO1 0x1003bad0 +MxBool ROIHandlerFunction(char* p_input, char* p_output, MxU32 p_copyLen) +{ + if (p_output != NULL && p_copyLen != 0 && + (strnicmp(p_input, "INDIR-F-", strlen("INDIR-F-")) == 0 || + strnicmp(p_input, "INDIR-G-", strlen("INDIR-F-")) == 0)) { + + char buf[256]; + sprintf(buf, "c_%s", &p_input[strlen("INDIR-F-")]); + + const char* value = VariableTable()->GetVariable(buf); + if (value != NULL) { + strncpy(p_output, value, p_copyLen); + p_output[p_copyLen - 1] = '\0'; + return TRUE; + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x1003bbb0 +LegoState* LegoGameState::GetState(const char* p_stateName) +{ + for (MxS32 i = 0; i < m_stateCount; ++i) { + if (m_stateArray[i]->IsA(p_stateName)) { + return m_stateArray[i]; + } + } + return NULL; +} + +// FUNCTION: LEGO1 0x1003bc00 +LegoState* LegoGameState::CreateState(const char* p_stateName) +{ + LegoState* newState = (LegoState*) ObjectFactory()->Create(p_stateName); + RegisterState(newState); + + return newState; +} + +// FUNCTION: LEGO1 0x1003bc30 +void LegoGameState::RegisterState(LegoState* p_state) +{ + MxS32 targetIndex; + for (targetIndex = 0; targetIndex < m_stateCount; ++targetIndex) { + if (m_stateArray[targetIndex]->IsA(p_state->ClassName())) { + break; + } + } + + if (targetIndex == m_stateCount) { + LegoState** newBuffer = new LegoState*[m_stateCount + 1]; + + if (m_stateCount != 0) { + memcpy(newBuffer, m_stateArray, m_stateCount * sizeof(LegoState*)); + delete[] m_stateArray; + } + + newBuffer[m_stateCount++] = p_state; + m_stateArray = newBuffer; + return; + } + + if (m_stateArray[targetIndex]) { + delete m_stateArray[targetIndex]; + } + m_stateArray[targetIndex] = p_state; +} + +// STUB: LEGO1 0x1003c870 +void LegoGameState::ScoreStruct::WriteScoreHistory() +{ + // TODO +} + +// STUB: LEGO1 0x1003ccf0 +void LegoGameState::ScoreStruct::FUN_1003ccf0(LegoFile&) +{ + // TODO +} + +// FUNCTION: LEGO1 0x1003cdd0 +void LegoGameState::SerializeScoreHistory(MxS16 p_flags) +{ + LegoFile stream; + MxString savePath(m_savePath); + savePath += "\\"; + savePath += g_historyGSI; + + if (p_flags == LegoFile::c_write) { + m_unk0xa6.WriteScoreHistory(); + } + + if (stream.Open(savePath.GetData(), p_flags) == SUCCESS) { + m_unk0xa6.FUN_1003ccf0(stream); + } +} + +// FUNCTION: LEGO1 0x1003cea0 +void LegoGameState::SetSomeEnumState(undefined4 p_state) +{ + m_unk0x10 = p_state; +} + +// FUNCTION: LEGO1 0x1003ceb0 +void LegoGameState::FUN_1003ceb0() +{ + if (FindWorld(*g_isleScript, 0)) { + m_currentAct = 0; + } + else if (FindWorld(*g_act2mainScript, 0)) { + m_currentAct = 1; + } + else if (FindWorld(*g_act3Script, 0)) { + m_currentAct = 2; + } + else { + m_currentAct = -1; + } +} diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp new file mode 100644 index 00000000..8e3d7526 --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -0,0 +1,135 @@ +#include "legoobjectfactory.h" + +#include "carrace.h" +#include "decomp.h" +#include "dunebuggy.h" +#include "elevatorbottom.h" +#include "gasstation.h" +#include "gasstationstate.h" +#include "helicopter.h" +#include "helicopterstate.h" +#include "historybook.h" +#include "hospital.h" +#include "hospitalstate.h" +#include "infocenter.h" +#include "infocenterdoor.h" +#include "infocenterstate.h" +#include "isle.h" +#include "jetskirace.h" +#include "lego3dwavepresenter.h" +#include "legoact2.h" +#include "legoact2state.h" +#include "legoactioncontrolpresenter.h" +#include "legoactor.h" +#include "legoactorpresenter.h" +#include "legoanimactor.h" +#include "legoanimpresenter.h" +#include "legocarbuild.h" +#include "legocarbuildanimpresenter.h" +#include "legocarraceactor.h" +#include "legoentity.h" +#include "legoentitypresenter.h" +#include "legoflctexturepresenter.h" +#include "legohideanimpresenter.h" +#include "legojetski.h" +#include "legojetskiraceactor.h" +#include "legoloadcachesoundpresenter.h" +#include "legolocomotionanimpresenter.h" +#include "legoloopinganimpresenter.h" +#include "legomodelpresenter.h" +#include "legopalettepresenter.h" +#include "legopartpresenter.h" +#include "legopathactor.h" +#include "legopathpresenter.h" +#include "legophonemepresenter.h" +#include "legoracecar.h" +#include "legotexturepresenter.h" +#include "legoworld.h" +#include "legoworldpresenter.h" +#include "mxcontrolpresenter.h" +#include "mxvideopresenter.h" +#include "pizza.h" +#include "pizzamissionstate.h" +#include "police.h" +#include "policestate.h" +#include "registrationbook.h" +#include "score.h" +#include "scorestate.h" +#include "skateboard.h" +// #include "act2actor.h" +#include "act2brick.h" +// #include "act2genactor.h" +#include "act2policestation.h" +#include "act3.h" +#include "act3state.h" +#include "ambulance.h" +#include "ambulancemissionstate.h" +#include "bike.h" +#include "doors.h" +#include "jetski.h" +#include "legoanimmmpresenter.h" +#include "motocycle.h" +#include "racecar.h" +#include "towtrack.h" +#include "towtrackmissionstate.h" +// #include "act3cop.h" +// #include "act3brickster.h" +#include "act1state.h" +#include "act3actor.h" +#include "act3shark.h" +#include "beachhouseentity.h" +#include "bumpbouy.h" +#include "carracestate.h" +#include "gasstationentity.h" +#include "hospitalentity.h" +#include "infocenterentity.h" +#include "jetskiracestate.h" +#include "jukeboxentity.h" +#include "pizzeria.h" +#include "pizzeriastate.h" +#include "policeentity.h" +#include "racestandsentity.h" +#include "radiostate.h" +// #include "caveentity.h" +// #include "jailentity.h" +#include "jukebox.h" +#include "jukeboxstate.h" +#include "mxcompositemediapresenter.h" +// #include "raceskel.h" +#include "animstate.h" + +// TODO: Before HospitalState, add all of the different LegoVehicleBuildState's + +// TODO: Uncomment once we have all the relevant types ready +// DECOMP_SIZE_ASSERT(LegoObjectFactory, 0x1c8); + +// FUNCTION: LEGO1 0x10006e40 +LegoObjectFactory::LegoObjectFactory() +{ +#define X(V) this->m_id##V = MxAtomId(#V, e_exact); + FOR_LEGOOBJECTFACTORY_OBJECTS(X) +#undef X +} + +// FUNCTION: LEGO1 0x10009a90 +MxCore* LegoObjectFactory::Create(const char* p_name) +{ + MxAtomId atom(p_name, e_exact); + +#define X(V) \ + if (this->m_id##V == atom) { \ + return new V; \ + } \ + else + FOR_LEGOOBJECTFACTORY_OBJECTS(X) +#undef X + { + return MxObjectFactory::Create(p_name); + } +} + +// FUNCTION: LEGO1 0x1000fb30 +void LegoObjectFactory::Destroy(MxCore* p_object) +{ + delete p_object; +} diff --git a/LEGO1/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp similarity index 64% rename from LEGO1/legoplantmanager.cpp rename to LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 4b93d8d7..ec04cf6a 100644 --- a/LEGO1/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -18,6 +18,18 @@ void LegoPlantManager::Init() // TODO } +// STUB: LEGO1 0x10026360 +void LegoPlantManager::FUN_10026360(undefined4 p_world) +{ + // TODO +} + +// STUB: LEGO1 0x100263a0 +void LegoPlantManager::FUN_100263a0(undefined4 p_und) +{ + // TODO +} + // STUB: LEGO1 0x10026e00 MxResult LegoPlantManager::Tickle() { diff --git a/LEGO1/lego/legoomni/src/common/legostate.cpp b/LEGO1/lego/legoomni/src/common/legostate.cpp new file mode 100644 index 00000000..a8c2cc6b --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/legostate.cpp @@ -0,0 +1,59 @@ +#include "legostate.h" + +#include + +DECOMP_SIZE_ASSERT(LegoState, 0x08) +DECOMP_SIZE_ASSERT(LegoState::Playlist, 0x0c) + +// FUNCTION: LEGO1 0x10014d00 +MxU32 LegoState::Playlist::Next() +{ + MxU32 objectId; + + switch (m_mode) { + case e_loop: + objectId = m_objectIds[m_nextIndex]; + if (m_nextIndex - m_length == -1) { + m_nextIndex = 0; + } + else { + m_nextIndex++; + } + break; + + case e_once: + objectId = m_objectIds[m_nextIndex]; + if (m_length > m_nextIndex + 1) { + m_nextIndex++; + } + break; + + case e_random: + m_nextIndex = rand() % m_length; + objectId = m_objectIds[m_nextIndex]; + break; + + case e_loopSkipFirst: + objectId = m_objectIds[m_nextIndex]; + if (m_nextIndex - m_length == -1) { + m_nextIndex = 1; + } + else { + m_nextIndex++; + } + } + + return objectId; +} + +// FUNCTION: LEGO1 0x10014de0 +MxBool LegoState::Playlist::Contains(MxU32 p_objectId) +{ + for (MxS16 i = 0; i < m_length; i++) { + if (m_objectIds[i] == p_objectId) { + return TRUE; + } + } + + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp new file mode 100644 index 00000000..c7154155 --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -0,0 +1,72 @@ +#include "legounksavedatawriter.h" + +#include "legogamestate.h" +#include "roi/legoroi.h" + +DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108); + +// GLOBAL: LEGO1 0x10104f20 +LegoSaveDataEntry3 g_saveData3[66]; + +// FUNCTION: LEGO1 0x10083310 +MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStorage* p_stream) +{ + MxResult result = FAILURE; + + // This should probably be a for loop but I can't figure out how to + // make it match as a for loop. + LegoSaveDataEntry3* entry = g_saveData3; + const LegoSaveDataEntry3* end = &g_saveData3[66]; + + while (TRUE) { + if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS) { + break; + } + if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS) { + break; + } + if (++entry >= end) { + result = SUCCESS; + break; + } + } + return result; +} + +// STUB: LEGO1 0x10083500 +AutoROI* LegoUnkSaveDataWriter::FUN_10083500(undefined4, undefined4) +{ + // TODO + // involves an STL map with a _Nil node at 0x100fc508 + return NULL; +} + +// 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 new file mode 100644 index 00000000..51cf4342 --- /dev/null +++ b/LEGO1/lego/legoomni/src/common/legoutil.cpp @@ -0,0 +1,255 @@ +#include "legoutil.h" + +#include "legoomni.h" +#include "legoworld.h" +#include "mxdsaction.h" +#include "mxomni.h" +#include "mxstreamer.h" +#include "mxtypes.h" + +#include +#include + +// STUB: LEGO1 0x1003e050 +void FUN_1003e050(LegoAnimPresenter* p_presenter) +{ + // TODO +} + +// FUNCTION: LEGO1 0x1003e300 +Extra::ActionType MatchActionString(const char* p_str) +{ + Extra::ActionType result = Extra::ActionType::e_unknown; + + if (!strcmpi("openram", p_str)) { + result = Extra::ActionType::e_openram; + } + else if (!strcmpi("opendisk", p_str)) { + result = Extra::ActionType::e_opendisk; + } + else if (!strcmpi("close", p_str)) { + result = Extra::ActionType::e_close; + } + else if (!strcmpi("start", p_str)) { + result = Extra::ActionType::e_start; + } + else if (!strcmpi("stop", p_str)) { + result = Extra::ActionType::e_stop; + } + else if (!strcmpi("run", p_str)) { + result = Extra::ActionType::e_run; + } + else if (!strcmpi("exit", p_str)) { + result = Extra::ActionType::e_exit; + } + else if (!strcmpi("enable", p_str)) { + result = Extra::ActionType::e_enable; + } + else if (!strcmpi("disable", p_str)) { + result = Extra::ActionType::e_disable; + } + else if (!strcmpi("notify", p_str)) { + result = Extra::ActionType::e_notify; + } + + return result; +} + +MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId); +void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender); + +// FUNCTION: LEGO1 0x1003e430 +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 Extra::ActionType::e_opendisk: + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_diskStream); + Start(&action); + } + break; + 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 Extra::ActionType::e_close: + action.SetUnknown24(-2); + DeleteObject(action); + Streamer()->Close(p_pAtom.GetInternal()); + break; + case Extra::ActionType::e_start: + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + Start(&action); + } + break; + case Extra::ActionType::e_stop: + action.SetUnknown24(-2); + if (!FUN_1003ee00(p_pAtom, p_targetEntityId)) { + DeleteObject(action); + } + break; + case Extra::ActionType::e_run: + _spawnl(0, "\\lego\\sources\\main\\main.exe", "\\lego\\sources\\main\\main.exe", "/script", &p_pAtom, 0); + break; + case Extra::ActionType::e_exit: + Lego()->SetExit(TRUE); + break; + case Extra::ActionType::e_enable: + CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId); + break; + case Extra::ActionType::e_disable: + CheckIfEntityExists(FALSE, p_pAtom.GetInternal(), p_targetEntityId); + break; + case Extra::ActionType::e_notify: + NotifyEntity(p_pAtom.GetInternal(), p_targetEntityId, p_sender); + break; + } +} + +// FUNCTION: LEGO1 0x1003e670 +MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId) +{ + LegoWorld* world = FindWorld(MxAtomId(p_filename, e_lowerCase2), p_entityId); + + if (world) { + world->Enable(p_enable); + return TRUE; + } + else { + return FALSE; + } +} + +// STUB: LEGO1 0x1003e700 +void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender) +{ +} + +// FUNCTION: LEGO1 0x1003eae0 +void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut) +{ + double calc; + double p; + MxLong hueIndex; + double v9; + double v12; + double v13; + + double sDbl = p_s; + + if (p_s > 0.5f) { + calc = (1.0f - p_v) * p_s + p_v; + } + else { + calc = (p_v + 1.0) * sDbl; + } + if (calc <= 0.0) { + *p_gOut = 0.0f; + *p_bOut = 0.0f; + *p_rOut = 0.0f; + return; + } + p = p_s * 2.0f - calc; + hueIndex = p_h * 6.0; + v9 = (p_h * 6.0 - (float) hueIndex) * ((calc - p) / calc) * calc; + v12 = p + v9; + v13 = calc - v9; + switch (hueIndex) { + case 0: + *p_rOut = calc; + *p_bOut = v12; + *p_gOut = p; + break; + case 1: + *p_rOut = v13; + *p_bOut = calc; + *p_gOut = p; + break; + case 2: + *p_rOut = p; + *p_bOut = calc; + *p_gOut = v12; + break; + case 3: + *p_rOut = p; + *p_bOut = v13; + *p_gOut = calc; + break; + case 4: + *p_rOut = v12; + *p_bOut = p; + *p_gOut = calc; + break; + case 5: + *p_rOut = calc; + *p_bOut = p; + *p_gOut = v13; + break; + case 6: + *p_rOut = calc; + *p_bOut = p; + *p_gOut = v13; + break; + default: + return; + } +} + +// STUB: LEGO1 0x1003ee00 +MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id) +{ + return TRUE; +} + +// FUNCTION: LEGO1 0x1003ee80 +MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_worldAtom, MxS32 p_worldEntityId) +{ + LegoWorld* world = FindWorld(p_worldAtom, p_worldEntityId); + + if (world) { + MxCore* object = world->Find(p_entityAtom, p_entityId); + + if (object) { + world->Remove(object); + + if (!object->IsA("MxPresenter")) { + delete object; + } + else { + if (((MxPresenter*) object)->GetAction()) { + FUN_100b7220(((MxPresenter*) object)->GetAction(), MxDSAction::c_world, FALSE); + } + + ((MxPresenter*) object)->EndAction(); + } + + return TRUE; + } + } + + return FALSE; +} + +// STUB: LEGO1 0x1003ef00 +void FUN_1003ef00(MxBool) +{ + // TODO (something related to animation manager) +} + +// FUNCTION: LEGO1 0x1003ef40 +void SetAppCursor(WPARAM p_wparam) +{ + PostMessageA(MxOmni::GetInstance()->GetWindowHandle(), 0x5400, p_wparam, 0); +} + +// STUB: LEGO1 0x1003ef60 +MxBool FUN_1003ef60() +{ + return TRUE; +} diff --git a/LEGO1/mxcompositemediapresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp similarity index 73% rename from LEGO1/mxcompositemediapresenter.cpp rename to LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp index 0547c815..fe1543a2 100644 --- a/LEGO1/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,14 @@ 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); - else if (presenter->IsA("MxAudioPresenter")) - SoundManager()->RemovePresenter(*presenter); + if (presenter->IsA("MxVideoPresenter")) { + VideoManager()->UnregisterPresenter(*presenter); + } + else if (presenter->IsA("MxAudioPresenter")) { + SoundManager()->UnregisterPresenter(*presenter); + } success = TRUE; } @@ -70,12 +72,13 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller action->SetOrigin(this); m_list.push_back(presenter); } - else if (presenter) + else if (presenter) { delete presenter; + } } if (!m_compositePresenter) { - SetTickleState(TickleState_Ready); + SetTickleState(e_ready); MxLong time = Timer()->GetTime(); m_action->SetUnknown90(time); } @@ -93,12 +96,13 @@ 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 || - ((*it)->GetAction() && (*it)->GetAction()->GetStartTime())) + if ((*it)->GetCurrentTickleState() == e_streaming || + ((*it)->GetAction() && (*it)->GetAction()->GetStartTime())) { m_unk0x4c++; + } } } @@ -107,24 +111,24 @@ void MxCompositeMediaPresenter::StartingTickle() m_unk0x4c = 0; for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { - if (!(*it)->GetAction()->GetStartTime()) + if (!(*it)->GetAction()->GetStartTime()) { m_unk0x4c++; + } } } } else { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { - if (!(*it)->GetAction()->GetStartTime() && ((MxMediaPresenter*) *it)->FUN_100b5650() && - !((*it)->GetAction()->GetFlags() & MxDSAction::Flag_Bit9)) { + if (!(*it)->GetAction()->GetStartTime() && ((MxMediaPresenter*) *it)->CurrentChunk() && + !((*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,18 +141,18 @@ 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: { - for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) + 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; } default: @@ -163,9 +167,10 @@ MxResult MxCompositeMediaPresenter::PutData() { MxAutoLocker lock(&m_criticalSection); - if (m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_Done) { - for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) + if (m_currentTickleState >= e_streaming && m_currentTickleState <= e_done) { + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { (*it)->PutData(); + } } return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp new file mode 100644 index 00000000..01d5bb3a --- /dev/null +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -0,0 +1,205 @@ +#include "legocontrolmanager.h" + +#include "legoeventnotificationparam.h" +#include "legoomni.h" +#include "legovideomanager.h" +#include "mxcontrolpresenter.h" +#include "mxpresenter.h" +#include "mxticklemanager.h" + +DECOMP_SIZE_ASSERT(LegoControlManager, 0x60) +DECOMP_SIZE_ASSERT(LegoControlManagerEvent, 0x2c) + +// FUNCTION: LEGO1 0x10028520 +LegoControlManager::LegoControlManager() +{ + m_presenterList = NULL; + m_unk0x08 = 0; + m_unk0x0c = 0; + m_unk0x10 = FALSE; + m_unk0x14 = NULL; + TickleManager()->RegisterClient(this, 10); +} + +// FUNCTION: LEGO1 0x10028d60 +LegoControlManager::~LegoControlManager() +{ + TickleManager()->UnregisterClient(this); +} + +// FUNCTION: LEGO1 0x10028df0 +void LegoControlManager::FUN_10028df0(MxPresenterList* p_presenterList) +{ + m_presenterList = p_presenterList; + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; +} + +// FUNCTION: LEGO1 0x10028e10 +void LegoControlManager::Register(MxCore* p_listener) +{ + m_notifyList.Append(p_listener); +} + +// FUNCTION: LEGO1 0x10028ea0 +void LegoControlManager::Unregister(MxCore* p_listener) +{ + LegoNotifyListCursor cursor(&m_notifyList); + if (cursor.Find(p_listener)) { + cursor.Detach(); + } +} + +// FUNCTION: LEGO1 0x10029210 +MxBool LegoControlManager::FUN_10029210(LegoEventNotificationParam& p_param, MxPresenter* p_presenter) +{ + if (m_presenterList != NULL && m_presenterList->GetCount() != 0) { + m_unk0x14 = p_presenter; + + if (p_param.GetType() == c_notificationButtonUp || p_param.GetType() == c_notificationButtonDown) { + m_event.SetType(p_param.GetType()); + m_event.SetSender(p_param.GetSender()); + m_event.SetModifier(p_param.GetModifier()); + m_event.SetX(p_param.GetX()); + m_event.SetY(p_param.GetY()); + m_event.SetKey(p_param.GetKey()); + + if (p_param.GetType() == c_notificationButtonUp) { + if (m_unk0x10 == TRUE) { + m_unk0x10 = FALSE; + return TRUE; + } + + if (g_unk0x100f31b0 != -1 && g_unk0x100f31b4 != NULL) { + if (m_unk0x08 == 2) { + return FUN_10029750(); + } + else { + m_unk0x0c = 1; + return TRUE; + } + } + } + else if (p_param.GetType() == c_notificationButtonDown) { + if (m_unk0x0c == 1) { + m_unk0x10 = TRUE; + return TRUE; + } + else { + return FUN_10029630(); + } + } + } + + return FALSE; + } + else { + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; + + return FALSE; + } +} + +// FUNCTION: LEGO1 0x100292e0 +void LegoControlManager::FUN_100292e0() +{ + LegoNotifyListCursor cursor(&m_notifyList); + MxCore* target; + + // The usual cursor.Next() loop doesn't match here, even though + // the logic is the same. It does match when "deconstructed" into + // the following Head(), Current() and NextFragment() calls, + // but this seems unlikely to be the original code. + cursor.Head(); + while (cursor.Current(target)) { + cursor.NextFragment(); + target->Notify(m_event); + } +} + +// STUB: LEGO1 0x100293c0 +void LegoControlManager::FUN_100293c0(undefined4, const char*, undefined2) +{ +} + +// FUNCTION: LEGO1 0x100294e0 +MxControlPresenter* LegoControlManager::FUN_100294e0(MxS32 p_x, MxS32 p_y) +{ + if (m_presenterList) { + MxPresenterListCursor cursor(m_presenterList); + MxPresenter* control; + MxVideoPresenter* presenter = (MxVideoPresenter*) VideoManager()->GetPresenterAt(p_x, p_y); + + if (presenter) { + while (cursor.Next(control)) { + if (((MxControlPresenter*) control)->FUN_10044270(p_x, p_y, presenter)) { + return (MxControlPresenter*) control; + } + } + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10029600 +MxResult LegoControlManager::Tickle() +{ + if (m_unk0x08 == 2 && m_unk0x0c == 1) { + m_event.SetType(c_notificationButtonUp); + FUN_10029750(); + return 0; + } + else if (m_unk0x08 == 1) { + m_unk0x08 = 2; + } + return 0; +} + +// FUNCTION: LEGO1 0x10029630 +MxBool LegoControlManager::FUN_10029630() +{ + MxPresenterListCursor cursor(m_presenterList); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + if (((MxControlPresenter*) presenter)->FUN_10044480(&m_event, m_unk0x14)) { + g_unk0x100f31b0 = m_event.GetClickedObjectId(); + g_unk0x100f31b4 = m_event.GetClickedAtom(); + FUN_100292e0(); + m_unk0x08 = 1; + return TRUE; + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x10029750 +MxBool LegoControlManager::FUN_10029750() +{ + MxPresenterListCursor cursor(m_presenterList); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + if (presenter->GetAction() && presenter->GetAction()->GetObjectId() == g_unk0x100f31b0 && + presenter->GetAction()->GetAtomId().GetInternal() == g_unk0x100f31b4) { + if (((MxControlPresenter*) presenter)->FUN_10044480(&m_event, m_unk0x14)) { + FUN_100292e0(); + } + + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; + + m_unk0x08 = 0; + m_unk0x0c = 0; + + return TRUE; + } + } + + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp new file mode 100644 index 00000000..ae131445 --- /dev/null +++ b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp @@ -0,0 +1,331 @@ +#include "mxcontrolpresenter.h" + +#include "define.h" +#include "legocontrolmanager.h" +#include "mxdsmultiaction.h" +#include "mxticklemanager.h" +#include "mxtimer.h" +#include "mxutil.h" +#include "mxvideopresenter.h" + +DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) + +// GLOBAL: LEGO1 0x10102064 +// STRING: LEGO1 0x10101fec +const char* g_style = "STYLE"; + +// GLOBAL: LEGO1 0x10102068 +// STRING: LEGO1 0x10101fe4 +const char* g_grid = "GRID"; + +// GLOBAL: LEGO1 0x1010206c +// STRING: LEGO1 0x10101fe0 +const char* g_map = "MAP"; + +// GLOBAL: LEGO1 0x10102074 +// STRING: LEGO1 0x10101fd0 +const char* g_toggle = "TOGGLE"; + +// FUNCTION: LEGO1 0x10043f50 +MxControlPresenter::MxControlPresenter() +{ + this->m_unk0x4c = 0; + this->m_unk0x4e = -1; + this->m_unk0x50 = FALSE; + this->m_unk0x52 = 0; + this->m_unk0x58 = 0; + this->m_unk0x54 = 0; +} + +// FUNCTION: LEGO1 0x10043fd0 +void MxControlPresenter::RepeatingTickle() +{ + // empty +} + +// FUNCTION: LEGO1 0x10043fe0 +MxBool MxControlPresenter::VTable0x64(undefined4 p_undefined) +{ + return m_unk0x50; +} + +// FUNCTION: LEGO1 0x10043ff0 +void MxControlPresenter::VTable0x68(MxBool p_unk0x50) +{ + m_unk0x50 = p_unk0x50; +} + +// FUNCTION: LEGO1 0x10044110 +MxControlPresenter::~MxControlPresenter() +{ + if (m_unk0x58) { + delete m_unk0x58; + } +} + +// FUNCTION: LEGO1 0x10044180 +MxResult MxControlPresenter::AddToManager() +{ + m_unk0x4e = 0; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10044190 +MxResult MxControlPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + 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 +void MxControlPresenter::EndAction() +{ + if (m_action) { + m_unk0x50 = TRUE; + MxCompositePresenter::EndAction(); + } +} + +// FUNCTION: LEGO1 0x10044270 +MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* p_presenter) +{ + if (m_unk0x4c == 3) { + MxVideoPresenter* frontPresenter = (MxVideoPresenter*) m_list.front(); + + if (p_presenter == frontPresenter || frontPresenter->GetDisplayZ() < p_presenter->GetDisplayZ()) { + if (p_presenter->VTable0x7c()) { + MxS32 height = frontPresenter->GetHeight(); + MxS32 width = frontPresenter->GetWidth(); + + if (frontPresenter->GetLocation().GetX() <= p_x && + p_x < width - 1 + frontPresenter->GetLocation().GetX() && + frontPresenter->GetLocation().GetY() <= p_y && + p_y < height - 1 + frontPresenter->GetLocation().GetY()) { + MxU8* start; + + if (frontPresenter->GetAlphaMask() == NULL) { + start = frontPresenter->GetBitmap()->GetStart( + p_x - frontPresenter->GetLocation().GetX(), + p_y - frontPresenter->GetLocation().GetY() + ); + } + else { + start = NULL; + } + + m_unk0x56 = 0; + if (m_unk0x58 == NULL) { + if (*start != 0) { + m_unk0x56 = 1; + } + } + else { + for (MxS16 i = 1; i <= *m_unk0x58; i++) { + if (m_unk0x58[i] == *start) { + m_unk0x56 = i; + break; + } + } + } + + if (m_unk0x56) { + return TRUE; + } + } + } + } + } + else { + if (ContainsPresenter(m_list, p_presenter)) { + if (m_unk0x4c == 2) { + MxS32 width = p_presenter->GetWidth(); + MxS32 height = p_presenter->GetHeight(); + + if (m_unk0x52 == 2 && m_unk0x54 == 2) { + MxS16 val; + if (p_x < p_presenter->GetLocation().GetX() + width / 2) { + val = 3; + if (p_y < p_presenter->GetLocation().GetY() + height / 2) { + val = 1; + } + m_unk0x56 = val; + return TRUE; + } + + val = 4; + if (p_y < p_presenter->GetLocation().GetY() + height / 2) { + val = 2; + } + + m_unk0x56 = val; + return TRUE; + } + } + else { + m_unk0x56 = -1; + } + + return TRUE; + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x10044480 +MxBool MxControlPresenter::FUN_10044480(LegoControlManagerEvent* p_event, MxPresenter* p_presenter) +{ + if (IsEnabled()) { + switch (p_event->GetType()) { + case c_notificationButtonUp: + if (m_unk0x4c == 0 || m_unk0x4c == 2 || m_unk0x4c == 3) { + p_event->SetClickedObjectId(m_action->GetObjectId()); + p_event->SetClickedAtom(m_action->GetAtomId().GetInternal()); + VTable0x6c(0); + p_event->SetType(c_notificationClick); + p_event->SetUnknown0x28(m_unk0x4e); + return TRUE; + } + break; + case c_notificationButtonDown: + if (FUN_10044270(p_event->GetX(), p_event->GetY(), (MxVideoPresenter*) p_presenter)) { + p_event->SetClickedObjectId(m_action->GetObjectId()); + p_event->SetClickedAtom(m_action->GetAtomId().GetInternal()); + VTable0x6c(m_unk0x56); + p_event->SetType(c_notificationClick); + p_event->SetUnknown0x28(m_unk0x4e); + return TRUE; + } + break; + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x10044540 +void MxControlPresenter::VTable0x6c(MxS16 p_val) +{ + if (p_val == -1) { + if ((MxS16) ((MxDSMultiAction*) m_action)->GetActionList()->GetCount() - m_unk0x4e == 1) { + m_unk0x4e = 0; + } + else { + m_unk0x4e++; + } + } + else { + m_unk0x4e = p_val; + } + + m_action->SetUnknown90(Timer()->GetTime()); + + MxS16 i = 0; + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + (*it)->Enable(((m_unk0x4c == 3 && m_unk0x4e == 0) || !IsEnabled()) ? FALSE : m_unk0x4e == i); + i++; + } +} + +// FUNCTION: LEGO1 0x10044610 +void MxControlPresenter::ReadyTickle() +{ + MxPresenter::ParseExtra(); + TickleManager()->UnregisterClient(this); + ProgressTickleState(e_repeating); +} + +// FUNCTION: LEGO1 0x10044640 +void MxControlPresenter::ParseExtra() +{ + char result[256]; + MxU16 len = m_action->GetExtraLength(); + if (len) { + char buffer[256]; + memcpy(buffer, m_action->GetExtraData(), m_action->GetExtraLength()); + buffer[len] = 0; + + if (KeyValueStringParse(result, g_style, buffer)) { + char* str = strtok(result, g_parseExtraTokens); + if (!strcmpi(str, g_toggle)) { + m_unk0x4c = 1; + } + else if (!strcmpi(str, g_grid)) { + m_unk0x4c = 2; + m_unk0x52 = atoi(strtok(NULL, g_parseExtraTokens)); + m_unk0x54 = atoi(strtok(NULL, g_parseExtraTokens)); + } + else if (!strcmpi(str, g_map)) { + m_unk0x4c = 3; + str = strtok(NULL, g_parseExtraTokens); + if (str) { + MxS16 count = atoi(str); + m_unk0x58 = new MxS16[count + 1]; + *m_unk0x58 = count; + for (MxS16 i = 1; i <= count; i++) { + m_unk0x58[i] = atoi(strtok(NULL, g_parseExtraTokens)); + } + } + } + else { + m_unk0x4c = 0; + } + } + + if (KeyValueStringParse(result, g_strVISIBILITY, buffer)) { + if (!strcmpi(result, "FALSE")) { + Enable(FALSE); + } + } + } +} + +// FUNCTION: LEGO1 0x10044820 +void MxControlPresenter::Enable(MxBool p_enable) +{ + 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; + } + } +} + +// FUNCTION: LEGO1 0x100448a0 +MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState) +{ + 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 new file mode 100644 index 00000000..5c18b9d3 --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -0,0 +1,31 @@ +#include "legoactor.h" + +DECOMP_SIZE_ASSERT(LegoActor, 0x78) + +// FUNCTION: LEGO1 0x1002d110 +LegoActor::LegoActor() +{ + m_unk0x68 = 0.0f; + m_unk0x6c = 0; + m_unk0x70 = 0.0f; + m_unk0x10 = 0; + m_unk0x74 = 0; +} + +// STUB: LEGO1 0x1002d320 +LegoActor::~LegoActor() +{ + // TODO +} + +// STUB: LEGO1 0x1002d390 +void LegoActor::ParseAction(char*) +{ + // TODO +} + +// STUB: LEGO1 0x1002d670 +void LegoActor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) +{ + // 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..076333a6 --- /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 (CurrentWorld()) { + 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/legoanimactor.cpp b/LEGO1/lego/legoomni/src/entity/legoanimactor.cpp similarity index 100% rename from LEGO1/legoanimactor.cpp rename to LEGO1/lego/legoomni/src/entity/legoanimactor.cpp diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp new file mode 100644 index 00000000..b68d0a01 --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -0,0 +1,124 @@ +#include "legocameracontroller.h" + +#include "legoinputmanager.h" +#include "legonotify.h" +#include "legoomni.h" +#include "legovideomanager.h" + +DECOMP_SIZE_ASSERT(LegoCameraController, 0xc8); + +// FUNCTION: LEGO1 0x10011d50 +LegoCameraController::LegoCameraController() +{ + SetWorldTransform(Mx3DPointFloat(0, 0, 0), Mx3DPointFloat(0, 0, 1), Mx3DPointFloat(0, 1, 0)); +} + +// FUNCTION: LEGO1 0x10011f70 +LegoCameraController::~LegoCameraController() +{ + if (InputManager()) { + if (InputManager()->GetCamera() == this) { + InputManager()->ClearCamera(); + } + } +} + +// FUNCTION: LEGO1 0x10011ff0 +MxResult LegoCameraController::Create() +{ + InputManager()->SetCamera(this); + return LegoPointOfViewController::Create(VideoManager()->Get3DManager()->GetLego3DView()); +} + +// STUB: LEGO1 0x10012020 +MxLong LegoCameraController::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// FUNCTION: LEGO1 0x100121b0 +void LegoCameraController::OnLButtonDown(MxPoint32 p_point) +{ + LeftDown(p_point.GetX(), p_point.GetY()); +} + +// FUNCTION: LEGO1 0x100121d0 +void LegoCameraController::OnLButtonUp(MxPoint32 p_point) +{ + LeftUp(p_point.GetX(), p_point.GetY()); +} + +// FUNCTION: LEGO1 0x100121f0 +void LegoCameraController::OnRButtonDown(MxPoint32 p_point) +{ + RightDown(p_point.GetX(), p_point.GetY()); +} + +// FUNCTION: LEGO1 0x10012210 +void LegoCameraController::OnRButtonUp(MxPoint32 p_point) +{ + RightUp(p_point.GetX(), p_point.GetY()); +} + +// FUNCTION: LEGO1 0x10012230 +void LegoCameraController::OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) +{ + if (p_modifier & c_lButtonState) { + LeftDrag(p_point.GetX(), p_point.GetY()); + } + else if (p_modifier & c_rButtonState) { + RightDrag(p_point.GetX(), p_point.GetY()); + } +} + +// FUNCTION: LEGO1 0x10012260 +void LegoCameraController::SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up) +{ + CalcLocalTransform(p_at, p_dir, p_up, m_matrix1); + m_matrix2 = m_matrix1; +} + +// STUB: LEGO1 0x100123e0 +void LegoCameraController::FUN_100123e0(const MxMatrix& p_transform, MxU32) +{ +} + +// FUNCTION: LEGO1 0x10012740 +Mx3DPointFloat LegoCameraController::GetWorldUp() +{ + 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); + } +} + +// FUNCTION: LEGO1 0x100127f0 +Mx3DPointFloat LegoCameraController::GetWorldLocation() +{ + 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); + } +} + +// FUNCTION: LEGO1 0x100128a0 +Mx3DPointFloat LegoCameraController::GetWorldDirection() +{ + 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/legocarraceactor.cpp b/LEGO1/lego/legoomni/src/entity/legocarraceactor.cpp new file mode 100644 index 00000000..6e967472 --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legocarraceactor.cpp @@ -0,0 +1,45 @@ +#include "legocarraceactor.h" + +// STUB: LEGO1 0x10014130 +void LegoCarRaceActor::VTable0x68() +{ + // TODO +} + +// STUB: LEGO1 0x100141a0 +MxS32 LegoCarRaceActor::VTable0x90() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1005d650 +MxS32 LegoCarRaceActor::VTable0x94() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10081830 +void LegoCarRaceActor::VTable0x6c() +{ + // TODO +} + +// STUB: LEGO1 0x10081d10 +void LegoCarRaceActor::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x10081d20 +void LegoCarRaceActor::VTable0x98() +{ + // TODO +} + +// STUB: LEGO1 0x10081d30 +void LegoCarRaceActor::VTable0x9c() +{ + // TODO +} diff --git a/LEGO1/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp similarity index 63% rename from LEGO1/legoentity.cpp rename to LEGO1/lego/legoomni/src/entity/legoentity.cpp index 26f9daab..86ccf923 100644 --- a/LEGO1/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,35 @@ 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); + } + + UnkSaveDataWriter()->FUN_10083db0(m_roi); + } + else { + VideoManager()->Get3DManager()->GetLego3DView()->Remove(*m_roi); + delete m_roi; + } } delete[] m_actionArgString; @@ -64,9 +70,9 @@ void LegoEntity::Destroy(MxBool p_fromDestructor) // FUNCTION: LEGO1 0x10010880 void LegoEntity::SetWorld() { - LegoWorld* world = GetCurrentWorld(); + LegoWorld* world = CurrentWorld(); if (world != NULL && world != (LegoWorld*) this) { - world->VTable0x58(this); + world->Add(this); } } @@ -76,9 +82,20 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) // TODO } -// STUB: LEGO1 0x10010c30 +// STUB: LEGO1 0x100109b0 +void LegoEntity::SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool) +{ + // TODO +} + +// FUNCTION: LEGO1 0x10010c30 void LegoEntity::FUN_10010c30() { + LegoWorld* world = CurrentWorld(); + + if (m_cameraFlag && world && world->GetCamera() && m_roi) { + world->GetCamera()->FUN_100123e0(m_roi->GetLocal2World(), 1); + } } // FUNCTION: LEGO1 0x10010e10 @@ -91,13 +108,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 new file mode 100644 index 00000000..f43f1aa9 --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp @@ -0,0 +1,108 @@ +#include "legoentitypresenter.h" + +#include "islepathactor.h" +#include "legoomni.h" +#include "legovideomanager.h" + +DECOMP_SIZE_ASSERT(LegoEntityPresenter, 0x50); + +// FUNCTION: LEGO1 0x10053440 +LegoEntityPresenter::LegoEntityPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x100535c0 +void LegoEntityPresenter::Init() +{ + m_entity = NULL; +} + +// FUNCTION: LEGO1 0x100535d0 +LegoEntityPresenter::~LegoEntityPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x10053630 +undefined4 LegoEntityPresenter::SetEntity(LegoEntity* p_entity) +{ + m_entity = p_entity; + return 0; +} + +// FUNCTION: LEGO1 0x10053640 +void LegoEntityPresenter::Destroy(MxBool p_fromDestructor) +{ + if (VideoManager()) { + VideoManager()->UnregisterPresenter(*this); + } + + Init(); +} + +// FUNCTION: LEGO1 0x10053670 +void LegoEntityPresenter::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x10053680 +MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + MxResult result = MxCompositePresenter::StartAction(p_controller, p_action); + + if (VideoManager()) { + VideoManager()->RegisterPresenter(*this); + } + + return result; +} + +// FUNCTION: LEGO1 0x100536c0 +void LegoEntityPresenter::ReadyTickle() +{ + if (CurrentWorld()) { + 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(); + } + ProgressTickleState(e_starting); + } +} + +// FUNCTION: LEGO1 0x10053720 +void LegoEntityPresenter::RepeatingTickle() +{ + if (m_list.empty()) { + EndAction(); + } +} + +// FUNCTION: LEGO1 0x10053730 +void LegoEntityPresenter::SetEntityLocation( + Mx3DPointFloat& p_location, + Mx3DPointFloat& p_direction, + Mx3DPointFloat& p_up +) +{ + if (m_entity) { + m_entity->SetLocation(p_location, p_direction, p_up, TRUE); + } +} + +// FUNCTION: LEGO1 0x10053750 +void LegoEntityPresenter::ParseExtra() +{ + char data[512]; + MxU16 len = m_action->GetExtraLength(); + if (len) { + memcpy(data, m_action->GetExtraData(), len); + data[len] = 0; + + len &= MAXWORD; + m_entity->ParseAction(data); + } +} diff --git a/LEGO1/lego/legoomni/src/entity/legojetski.cpp b/LEGO1/lego/legoomni/src/entity/legojetski.cpp new file mode 100644 index 00000000..828b4f5b --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legojetski.cpp @@ -0,0 +1,51 @@ +#include "legojetski.h" + +// STUB: LEGO1 0x10013e70 +MxLong LegoJetski::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10014110 +void LegoJetski::ParseAction(char*) +{ + // TODO +} + +// STUB: LEGO1 0x10014120 +void LegoJetski::SetWorldSpeed(MxFloat p_worldSpeed) +{ + // TODO +} + +// STUB: LEGO1 0x10014140 +void LegoJetski::VTable0x6c() +{ + // TODO +} + +// STUB: LEGO1 0x10014180 +void LegoJetski::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x100141b0 +MxS32 LegoJetski::VTable0x94() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x100141c0 +void LegoJetski::VTable0x98() +{ + // TODO +} + +// STUB: LEGO1 0x10014200 +void LegoJetski::VTable0x9c() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp b/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp new file mode 100644 index 00000000..e8c7801f --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legojetskiraceactor.cpp @@ -0,0 +1,25 @@ +#include "legojetskiraceactor.h" + +// STUB: LEGO1 0x10081fc0 +void LegoJetskiRaceActor::VTable0x6c() +{ + // TODO +} + +// STUB: LEGO1 0x100822c0 +void LegoJetskiRaceActor::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x100822d0 +void LegoJetskiRaceActor::VTable0x98() +{ + // TODO +} + +// STUB: LEGO1 0x100822e0 +void LegoJetskiRaceActor::VTable0x9c() +{ + // TODO +} diff --git a/LEGO1/legonavcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp similarity index 95% rename from LEGO1/legonavcontroller.cpp rename to LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp index a806edd0..8a9ec812 100644 --- a/LEGO1/legonavcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legonavcontroller.cpp @@ -148,8 +148,9 @@ void LegoNavController::SetDefaults( // FUNCTION: LEGO1 0x10054e40 void LegoNavController::SetTargets(int p_hPos, int p_vPos, MxBool p_accel) { - if (this->m_trackDefault != FALSE) + if (this->m_trackDefault != FALSE) { ResetToDefault(); + } if (p_accel != FALSE) { this->m_targetTurnSpeed = CalculateNewTargetSpeed(p_hPos, this->m_hMax / 2, this->m_turnMaxSpeed); @@ -178,12 +179,15 @@ float LegoNavController::CalculateNewTargetSpeed(int p_pos, int p_center, float float result; int diff = p_pos - p_center; - if (diff > this->m_mouseDeadzone) + if (diff > this->m_mouseDeadzone) { result = (diff - m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone); - else if (diff < -m_mouseDeadzone) + } + else if (diff < -m_mouseDeadzone) { result = (diff + m_mouseDeadzone) * p_maxSpeed / (p_center - m_mouseDeadzone); - else + } + else { result = 0.0f; + } return result; } @@ -196,8 +200,9 @@ float LegoNavController::CalculateNewAccel(int p_pos, int p_center, float p_maxA result = Abs(diff) * p_maxAccel / p_center; - if (result < p_minAccel) + if (result < p_minAccel) { result = (float) p_minAccel; + } return result; } @@ -214,11 +219,20 @@ float LegoNavController::CalculateNewVel(float p_targetVel, float p_currentVel, float deltaVel = p_accel * p_time; newVel = p_currentVel + (deltaVel * vSign); - if (vSign > 0) + if (vSign > 0) { newVel = Min(newVel, p_targetVel); - else + } + else { newVel = Max(newVel, p_targetVel); + } } return newVel; } + +// STUB: LEGO1 0x10055a60 +MxLong LegoNavController::Notify(MxParam& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/legopathactor.cpp b/LEGO1/lego/legoomni/src/entity/legopathactor.cpp similarity index 88% rename from LEGO1/legopathactor.cpp rename to LEGO1/lego/legoomni/src/entity/legopathactor.cpp index f6d0a10d..b3174f83 100644 --- a/LEGO1/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 } @@ -68,6 +68,12 @@ void LegoPathActor::VTable0x68() // TODO } +// STUB: LEGO1 0x1002f020 +void LegoPathActor::ParseAction(char*) +{ + // TODO +} + // STUB: LEGO1 0x1002f1b0 void LegoPathActor::VTable0x9c() { diff --git a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp new file mode 100644 index 00000000..f656022d --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp @@ -0,0 +1,140 @@ +#include "legonavcontroller.h" +#include "legoomni.h" +#include "legopointofviewcontroller.h" +#include "mxticklemanager.h" + +DECOMP_SIZE_ASSERT(LegoMouseController, 0x20); +DECOMP_SIZE_ASSERT(LegoPointOfViewController, 0x38); + +////////////////////////////////////////////////////////////////////// + +// FUNCTION: LEGO1 0x10065550 +LegoMouseController::LegoMouseController() +{ + m_isButtonDown = FALSE; +} + +// FUNCTION: LEGO1 0x100655d0 +LegoMouseController::~LegoMouseController() +{ +} + +// FUNCTION: LEGO1 0x10065620 +void LegoMouseController::LeftDown(int p_x, int p_y) +{ + m_isButtonDown = TRUE; + m_buttonX = p_x; + m_buttonY = p_y; +} + +// FUNCTION: LEGO1 0x10065640 +void LegoMouseController::LeftUp(int p_x, int p_y) +{ + m_isButtonDown = FALSE; + m_buttonX = p_x; + m_buttonY = p_y; +} + +// FUNCTION: LEGO1 0x10065660 +void LegoMouseController::LeftDrag(int p_x, int p_y) +{ + m_buttonX = p_x; + m_buttonY = p_y; +} + +// FUNCTION: LEGO1 0x10065680 +void LegoMouseController::RightDown(int p_x, int p_y) +{ + m_isButtonDown = TRUE; + m_buttonX = p_x; + m_buttonY = p_y; +} + +// FUNCTION: LEGO1 0x100656a0 +void LegoMouseController::RightUp(int p_x, int p_y) +{ + m_isButtonDown = FALSE; + m_buttonX = p_x; + m_buttonY = p_y; +} + +// FUNCTION: LEGO1 0x100656c0 +void LegoMouseController::RightDrag(int p_x, int p_y) +{ + m_buttonX = p_x; + m_buttonY = p_y; +} + +////////////////////////////////////////////////////////////////////// + +// FUNCTION: LEGO1 0x100656e0 +LegoPointOfViewController::LegoPointOfViewController() +{ + m_lego3DView = NULL; + m_entity = NULL; + m_nav = NULL; + // m_entityOffsetUp is a temporary kludge. It should be replaced + // by 3D camera offset and position stored in the entity since each + // entity may have a different best viewpoint. + m_entityOffsetUp = 0.0; +} + +// FUNCTION: LEGO1 0x10065770 +LegoPointOfViewController::~LegoPointOfViewController() +{ + TickleManager()->UnregisterClient(this); + if (m_nav) { + delete m_nav; + m_nav = NULL; + } +} + +// FUNCTION: LEGO1 0x100657f0 +MxResult LegoPointOfViewController::Create(Lego3DView* p_lego3DView) +{ + m_lego3DView = p_lego3DView; + m_nav = new LegoNavController(); + LegoOmni::GetInstance()->SetNavController(m_nav); + m_nav->SetTrackDefaultParams(TRUE); + TickleManager()->RegisterClient(this, 10); + 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) +{ + LegoMouseController::LeftDown(p_x, p_y); + AffectPointOfView(); +} + +// FUNCTION: LEGO1 0x100658e0 +void LegoPointOfViewController::LeftDrag(int p_x, int p_y) +{ + LegoMouseController::LeftDrag(p_x, p_y); + AffectPointOfView(); +} + +// STUB: LEGO1 0x10065900 +void LegoPointOfViewController::AffectPointOfView() +{ + // TODO +} + +// STUB: LEGO1 0x10065930 +MxResult LegoPointOfViewController::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10065ae0 +void LegoPointOfViewController::SetEntity(LegoEntity* p_entity) +{ + // TODO +} diff --git a/LEGO1/legorace.cpp b/LEGO1/lego/legoomni/src/entity/legorace.cpp similarity index 93% rename from LEGO1/legorace.cpp rename to LEGO1/lego/legoomni/src/entity/legorace.cpp index d5eefbd5..7c65c4da 100644 --- a/LEGO1/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; @@ -82,7 +82,7 @@ MxLong LegoRace::Notify(MxParam& p_param) } // STUB: LEGO1 0x10015ed0 -void LegoRace::VTable0x68(MxBool p_add) +void LegoRace::Enable(MxBool p_enable) { // TODO } diff --git a/LEGO1/lego/legoomni/src/entity/legoraceactor.cpp b/LEGO1/lego/legoomni/src/entity/legoraceactor.cpp new file mode 100644 index 00000000..84022005 --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoraceactor.cpp @@ -0,0 +1,45 @@ +#include "legoraceactor.h" + +// STUB: LEGO1 0x10014190 +void LegoRaceActor::VTable0x74(Matrix4& p_transform) +{ + // TODO +} + +// STUB: LEGO1 0x10014ca0 +void LegoRaceActor::ParseAction(char*) +{ + // TODO +} + +// STUB: LEGO1 0x10014cb0 +void LegoRaceActor::SetWorldSpeed(MxFloat p_worldSpeed) +{ + // TODO +} + +// STUB: LEGO1 0x10014cc0 +void LegoRaceActor::VTable0x68() +{ + // TODO +} + +// STUB: LEGO1 0x10014cd0 +void LegoRaceActor::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x10014ce0 +MxS32 LegoRaceActor::VTable0x90() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10014cf0 +MxS32 LegoRaceActor::VTable0x94() +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/entity/legoracecar.cpp b/LEGO1/lego/legoomni/src/entity/legoracecar.cpp new file mode 100644 index 00000000..8728783a --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoracecar.cpp @@ -0,0 +1,51 @@ +#include "legoracecar.h" + +// STUB: LEGO1 0x10014280 +MxLong LegoRaceCar::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x100144d0 +void LegoRaceCar::ParseAction(char*) +{ + // TODO +} + +// STUB: LEGO1 0x100144e0 +void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed) +{ + // TODO +} + +// STUB: LEGO1 0x100144f0 +void LegoRaceCar::VTable0x6c() +{ + // TODO +} + +// STUB: LEGO1 0x10014530 +void LegoRaceCar::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x10014540 +MxS32 LegoRaceCar::VTable0x94() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10014550 +void LegoRaceCar::VTable0x98() +{ + // TODO +} + +// STUB: LEGO1 0x10014580 +void LegoRaceCar::VTable0x9c() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp new file mode 100644 index 00000000..f9c0b63c --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -0,0 +1,702 @@ +#include "legoworld.h" + +#include "legoanimationmanager.h" +#include "legoanimpresenter.h" +#include "legobuildingmanager.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legolocomotionanimpresenter.h" +#include "legonavcontroller.h" +#include "legoomni.h" +#include "legoplantmanager.h" +#include "legosoundmanager.h" +#include "legoutil.h" +#include "legovideomanager.h" +#include "mxactionnotificationparam.h" +#include "mxcontrolpresenter.h" +#include "mxnotificationmanager.h" +#include "mxnotificationparam.h" +#include "mxomni.h" +#include "mxticklemanager.h" + +DECOMP_SIZE_ASSERT(LegoWorld, 0xf8) +DECOMP_SIZE_ASSERT(LegoEntityList, 0x18) +DECOMP_SIZE_ASSERT(LegoEntityListCursor, 0x10) +DECOMP_SIZE_ASSERT(LegoCacheSoundList, 0x18) +DECOMP_SIZE_ASSERT(LegoCacheSoundListCursor, 0x10) + +// FUNCTION: LEGO1 0x1001ca40 +LegoWorld::LegoWorld() : m_list0x68(TRUE) +{ + m_startupTicks = e_four; + m_cameraController = NULL; + m_entityList = NULL; + m_cacheSoundList = NULL; + m_destroyed = FALSE; + m_hideAnimPresenter = NULL; + m_worldStarted = FALSE; + + NotificationManager()->Register(this); +} + +// FUNCTION: LEGO1 0x1001d670 +MxBool LegoWorld::VTable0x5c() +{ + return FALSE; +} + +// FUNCTION: LEGO1 0x1001d680 +MxBool LegoWorld::VTable0x64() +{ + return FALSE; +} + +// FUNCTION: LEGO1 0x1001dfa0 +LegoWorld::~LegoWorld() +{ + Destroy(TRUE); + + TickleManager()->UnregisterClient(this); + NotificationManager()->Unregister(this); +} + +// FUNCTION: LEGO1 0x1001e0b0 +MxResult LegoWorld::Create(MxDSAction& p_dsAction) +{ + MxEntity::Create(p_dsAction); + + m_entityList = new LegoEntityList(TRUE); + + if (!m_entityList) { + return FAILURE; + } + + m_cacheSoundList = new LegoCacheSoundList(TRUE); + + if (!m_cacheSoundList) { + return FAILURE; + } + + if (!VTable0x54()) { + return FAILURE; + } + + if (p_dsAction.GetFlags() & MxDSAction::c_enabled) { + if (CurrentWorld()) { + CurrentWorld()->Enable(0); + } + + SetCurrentWorld(this); + ControlManager()->FUN_10028df0(&m_controlPresenters); + } + + SetIsWorldActive(TRUE); + m_unk0xec = -1; + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1001e9d0 +void LegoWorld::Destroy(MxBool p_fromDestructor) +{ + m_destroyed = TRUE; + + if (CurrentWorld() == this) { + ControlManager()->FUN_10028df0(NULL); + SetCurrentWorld(NULL); + } + + m_list0x68.DeleteAll(); + + if (m_cameraController) { + delete m_cameraController; + m_cameraController = NULL; + } + + MxPresenterListCursor animPresenterCursor(&m_animPresenters); + MxPresenter* presenter; + + while (animPresenterCursor.First(presenter)) { + animPresenterCursor.Detach(); + + MxDSAction* action = presenter->GetAction(); + if (action) { + if (presenter->IsA("LegoLocomotionAnimPresenter")) { + LegoLocomotionAnimPresenter* animPresenter = (LegoLocomotionAnimPresenter*) presenter; + + animPresenter->DecrementUnknown0xd4(); + if (animPresenter->GetUnknown0xd4() == 0) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + else { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + } + + while (!m_set0xa8.empty()) { + MxCoreSet::iterator it = m_set0xa8.begin(); + MxCore* object = *it; + m_set0xa8.erase(it); + + if (object->IsA("MxPresenter")) { + MxPresenter* presenter = (MxPresenter*) object; + MxDSAction* action = presenter->GetAction(); + + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + else { + delete object; + } + } + + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + + while (controlPresenterCursor.First(presenter)) { + controlPresenterCursor.Detach(); + + MxDSAction* action = presenter->GetAction(); + if (action) { + FUN_100b7220(action, MxDSAction::c_world, FALSE); + presenter->EndAction(); + } + } + + if (m_unk0xec != -1 && m_set0xd0.empty()) { + PlantManager()->FUN_100263a0(m_unk0xec); + BuildingManager()->FUN_1002fb30(); + } + + if (m_entityList) { + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.First(entity)) { + cursor.Detach(); + + if (!(entity->GetFlags() & LegoEntity::c_bit2)) { + delete entity; + } + } + + delete m_entityList; + m_entityList = NULL; + } + + if (m_cacheSoundList) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); + LegoCacheSound* sound; + + while (cursor.First(sound)) { + cursor.Detach(); + SoundManager()->GetUnknown0x40()->FUN_1003dc40(&sound); + } + + delete m_cacheSoundList; + m_cacheSoundList = NULL; + } + + while (!m_list0xe0.empty()) { + AutoROI* roi = m_list0xe0.front(); + m_list0xe0.pop_front(); + delete roi; + } + + if (!p_fromDestructor) { + LegoEntity::Destroy(FALSE); + } +} + +// FUNCTION: LEGO1 0x1001f5e0 +MxLong LegoWorld::Notify(MxParam& p_param) +{ + MxLong ret = 0; + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationEndAction: { + MxPresenter* presenter = (MxPresenter*) ((MxEndActionNotificationParam&) p_param).GetSender(); + Remove(presenter); + ret = 1; + break; + } + case c_notificationNewPresenter: + TickleManager()->RegisterClient(this, 100); + break; + } + return ret; +} + +// FUNCTION: LEGO1 0x1001f630 +LegoCameraController* LegoWorld::VTable0x54() +{ + 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 +void LegoWorld::FUN_1001fc80(IslePathActor* p_actor) +{ +} + +// STUB: LEGO1 0x10020120 +MxS32 LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) +{ + // TODO + return 0; +} + +// FUNCTION: LEGO1 0x10020220 +void LegoWorld::Add(MxCore* p_object) +{ + if (p_object && !p_object->IsA("LegoWorld") && !p_object->IsA("LegoWorldPresenter")) { + if (p_object->IsA("LegoAnimPresenter")) { + LegoAnimPresenter* animPresenter = (LegoAnimPresenter*) p_object; + + if (!strcmpi(animPresenter->GetAction()->GetObjectName(), "ConfigAnimation")) { + FUN_1003e050(animPresenter); + animPresenter->GetAction()->SetDuration(animPresenter->GetUnknown0x64()->GetUnknown0x8()); + } + } + + if (p_object->IsA("MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + + if (cursor.Find((MxPresenter*) p_object)) { + return; + } + + m_controlPresenters.Append((MxPresenter*) p_object); + } + else if (p_object->IsA("MxEntity")) { + LegoEntityListCursor cursor(m_entityList); + + if (cursor.Find((LegoEntity*) p_object)) { + return; + } + + m_entityList->Append((LegoEntity*) p_object); + } + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); + + if (cursor.Find((MxPresenter*) p_object)) { + return; + } + + ((MxPresenter*) p_object)->SendToCompositePresenter(Lego()); + m_animPresenters.Append(((MxPresenter*) p_object)); + + if (p_object->IsA("LegoHideAnimPresenter")) { + m_hideAnimPresenter = (LegoHideAnimPresenter*) p_object; + } + } + else if (p_object->IsA("LegoCacheSound")) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); + + if (cursor.Find((LegoCacheSound*) p_object)) { + return; + } + + m_cacheSoundList->Append((LegoCacheSound*) p_object); + } + else { + if (m_set0xa8.find(p_object) == m_set0xa8.end()) { + m_set0xa8.insert(p_object); + } + } + + if (!m_set0xd0.empty() && p_object->IsA("MxPresenter")) { + if (((MxPresenter*) p_object)->IsEnabled()) { + ((MxPresenter*) p_object)->Enable(FALSE); + m_set0xd0.insert(p_object); + } + } + } +} + +// FUNCTION: LEGO1 0x10020f10 +void LegoWorld::Remove(MxCore* p_object) +{ + if (p_object) { + MxCoreSet::iterator it; + + if (p_object->IsA("MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + + if (cursor.Find((MxControlPresenter*) p_object)) { + cursor.Detach(); + ((MxControlPresenter*) p_object)->GetAction()->SetOrigin(Lego()); + ((MxControlPresenter*) p_object)->VTable0x68(TRUE); + } + } + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); + + if (cursor.Find((MxPresenter*) p_object)) { + cursor.Detach(); + } + + if (p_object->IsA("LegoHideAnimPresenter")) { + m_hideAnimPresenter = NULL; + } + } + else if (p_object->IsA("MxEntity")) { + if (p_object->IsA("LegoPathActor")) { + FUN_1001fc80((IslePathActor*) p_object); + } + + if (m_entityList) { + LegoEntityListCursor cursor(m_entityList); + + if (cursor.Find((LegoEntity*) p_object)) { + cursor.Detach(); + } + } + } + else if (p_object->IsA("LegoCacheSound")) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); + + if (cursor.Find((LegoCacheSound*) p_object)) { + cursor.Detach(); + } + } + else { + it = m_set0xa8.find(p_object); + if (it != m_set0xa8.end()) { + m_set0xa8.erase(it); + } + } + + it = m_set0xd0.find(p_object); + if (it != m_set0xd0.end()) { + m_set0xd0.erase(it); + } + } +} + +// FUNCTION: LEGO1 0x100213a0 +MxCore* LegoWorld::Find(const char* p_class, const char* p_name) +{ + if (!strcmp(p_class, "MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + MxDSAction* action = presenter->GetAction(); + if (!strcmp(action->GetObjectName(), p_name)) { + return presenter; + } + } + + return NULL; + } + else if (!strcmp(p_class, "MxEntity")) { + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.Next(entity)) { + if (!p_name) { + return entity; + } + + LegoROI* roi = entity->GetROI(); + if (roi && !strcmpi(roi->GetUnknown0xe4(), p_name)) { + return entity; + } + } + + return NULL; + } + else if (!strcmp(p_class, "LegoAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); + MxPresenter* presenter; + + while (cursor.Next(presenter)) { + if (!strcmpi(((LegoAnimPresenter*) presenter)->GetActionObjectName(), p_name)) { + return presenter; + } + } + + return NULL; + } + else { + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + if ((*it)->IsA(p_class) && (*it)->IsA("MxPresenter")) { + MxPresenter* presenter = (MxPresenter*) *it; + MxDSAction* action = presenter->GetAction(); + + if (!strcmp(action->GetObjectName(), p_name)) { + return *it; + } + } + } + + return NULL; + } +} + +// FUNCTION: LEGO1 0x10021790 +MxCore* LegoWorld::Find(const MxAtomId& p_atom, MxS32 p_entityId) +{ + LegoEntityListCursor entityCursor(m_entityList); + LegoEntity* entity; + + while (entityCursor.Next(entity)) { + if (entity->GetAtom() == p_atom && entity->GetEntityId() == p_entityId) { + return entity; + } + } + + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + MxPresenter* presenter; + + while (controlPresenterCursor.Next(presenter)) { + MxDSAction* action = presenter->GetAction(); + + if (action->GetAtomId() == p_atom && action->GetObjectId() == p_entityId) { + return presenter; + } + } + + MxPresenterListCursor animPresenterCursor(&m_animPresenters); + + while (animPresenterCursor.Next(presenter)) { + MxDSAction* action = presenter->GetAction(); + + if (action && action->GetAtomId() == p_atom && action->GetObjectId() == p_entityId) { + return presenter; + } + } + + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + MxCore* core = *it; + + if (core->IsA("MxPresenter")) { + MxPresenter* presenter = (MxPresenter*) *it; + MxDSAction* action = presenter->GetAction(); + + if (action->GetAtomId() == p_atom && action->GetObjectId() == p_entityId) { + return *it; + } + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10021a70 +void LegoWorld::Enable(MxBool p_enable) +{ + if (p_enable && !m_set0xd0.empty()) { + if (CurrentWorld() != this) { + if (CurrentWorld()) { + AnimationManager()->FUN_10061010(0); + CurrentWorld()->Enable(FALSE); + + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.Next(entity)) { + if (entity->GetROI()) { + entity->GetROI()->SetUnknown0x104(entity); + GetViewManager()->AddToUnknown0x08(entity->GetROI()); + } + } + } + + while (!m_set0xd0.empty()) { + MxCoreSet::iterator it = m_set0xd0.begin(); + + if ((*it)->IsA("MxPresenter")) { + ((MxPresenter*) *it)->Enable(TRUE); + } + else if ((*it)->IsA("LegoPathController")) { + ((LegoPathController*) *it)->Enable(TRUE); + } + + m_set0xd0.erase(it); + } + + SetCurrentWorld(this); + ControlManager()->FUN_10028df0(&m_controlPresenters); + InputManager()->SetCamera(m_cameraController); + + if (m_cameraController) { + InputManager()->Register(m_cameraController->GetNavController()); + Lego()->SetNavController(m_cameraController->GetNavController()); + } + + if (m_unk0xec != -1) { + PlantManager()->FUN_10026360(m_unk0xec); + AnimationManager()->FUN_1005f720(m_unk0xec); + BuildingManager()->FUN_1002fa00(); + AnimationManager()->FUN_1005f0b0(); + } + + GameState()->FUN_10039940(); + SetIsWorldActive(TRUE); + } + } + else if (!p_enable && m_set0xd0.empty()) { + MxPresenter* presenter; + LegoPathController* controller; + IslePathActor* vehicle = CurrentVehicle(); + + if (vehicle) { + FUN_1001fc80(vehicle); + } + + AnimationManager()->FUN_1005ee80(FALSE); + m_set0xd0.insert(this); + + if (m_unk0xec != -1) { + PlantManager()->FUN_100263a0(m_unk0xec); + BuildingManager()->FUN_1002fb30(); + } + + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + + while (controlPresenterCursor.Next(presenter)) { + if (presenter->IsEnabled()) { + m_set0xd0.insert(presenter); + presenter->Enable(FALSE); + } + } + + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + if ((*it)->IsA("LegoActionControlPresenter") || + ((*it)->IsA("MxPresenter") && ((MxPresenter*) *it)->IsEnabled())) { + m_set0xd0.insert(*it); + ((MxPresenter*) *it)->Enable(FALSE); + } + } + + if (CurrentWorld() && CurrentWorld() == this) { + ControlManager()->FUN_10028df0(NULL); + Lego()->SetCurrentWorld(NULL); + } + + if (InputManager()->GetCamera() == m_cameraController) { + InputManager()->ClearCamera(); + } + + if (m_cameraController) { + InputManager()->UnRegister(m_cameraController->GetNavController()); + + if (NavController() == m_cameraController->GetNavController()) { + Lego()->SetNavController(NULL); + } + } + + LegoPathControllerListCursor pathControllerCursor(&m_list0x68); + + while (pathControllerCursor.Next(controller)) { + controller->Enable(FALSE); + m_set0xd0.insert(controller); + } + + GetViewManager()->RemoveAll(NULL); + } +} + +// FUNCTION: LEGO1 0x10022080 +MxResult LegoWorld::Tickle() +{ + if (!m_worldStarted) { + switch (m_startupTicks) { + case e_start: + m_worldStarted = TRUE; + SetAppCursor(0); + ReadyWorld(); + return TRUE; + case e_two: + if (PresentersPending()) { + break; + } + default: + m_startupTicks--; + } + } + + return TRUE; +} + +// FUNCTION: LEGO1 0x100220e0 +MxBool LegoWorld::PresentersPending() +{ + MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); + MxPresenter* presenter; + + while (controlPresenterCursor.Next(presenter)) { + if (presenter->IsEnabled() && !presenter->HasTickleStatePassed(MxPresenter::e_starting)) { + return TRUE; + } + } + + MxPresenterListCursor animPresenterCursor(&m_animPresenters); + + while (animPresenterCursor.Next(presenter)) { + if (presenter->IsEnabled()) { + if (presenter->IsA("LegoLocomotionAnimPresenter")) { + if (!presenter->HasTickleStatePassed(MxPresenter::e_ready)) { + return TRUE; + } + } + else { + if (!presenter->HasTickleStatePassed(MxPresenter::e_starting)) { + return TRUE; + } + } + } + } + + for (MxCoreSet::iterator it = m_set0xa8.begin(); it != m_set0xa8.end(); it++) { + if ((*it)->IsA("MxPresenter")) { + presenter = (MxPresenter*) *it; + + if (presenter->IsEnabled() && !presenter->HasTickleStatePassed(MxPresenter::e_starting)) { + return TRUE; + } + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x10022340 +void LegoWorld::ReadyWorld() +{ + TickleManager()->UnregisterClient(this); +} diff --git a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp new file mode 100644 index 00000000..d4e002de --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp @@ -0,0 +1,176 @@ +#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" + +// GLOBAL: LEGO1 0x100f75d4 +undefined4 g_legoWorldPresenterQuality = 1; + +// FUNCTION: LEGO1 0x100665b0 +void LegoWorldPresenter::configureLegoWorldPresenter(MxS32 p_legoWorldPresenterQuality) +{ + g_legoWorldPresenterQuality = p_legoWorldPresenterQuality; +} + +// FUNCTION: LEGO1 0x100665c0 +LegoWorldPresenter::LegoWorldPresenter() +{ + m_unk0x50 = 50000; +} + +// FUNCTION: LEGO1 0x10066770 +LegoWorldPresenter::~LegoWorldPresenter() +{ + 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(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + } + + 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 +MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + MxAutoLocker lock(&m_criticalSection); + + MxResult result = FAILURE; + MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); + MxObjectFactory* factory = ObjectFactory(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) { + // The usual cursor.Next() loop doesn't match here, even though + // the logic is the same. It does match when "deconstructed" into + // the following Head(), Current() and NextFragment() calls, + // but this seems unlikely to be the original code. + // The alpha debug build also uses Next(). + cursor.Head(); + while (cursor.Current(action)) { + cursor.NextFragment(); + + MxBool success = FALSE; + + action->CopyFlags(m_action->GetFlags()); + + const char* presenterName = PresenterNameDispatch(*action); + MxPresenter* presenter = (MxPresenter*) factory->Create(presenterName); + + if (presenter && presenter->AddToManager() == SUCCESS) { + presenter->SetCompositePresenter(this); + if (presenter->StartAction(p_controller, action) == SUCCESS) { + presenter->SetTickleState(e_idle); + success = TRUE; + } + } + + if (success) { + action->SetOrigin(this); + m_list.push_back(presenter); + } + else if (presenter) { + delete presenter; + } + } + + VideoManager()->RegisterPresenter(*this); + + result = SUCCESS; + } + + return result; +} + +// FUNCTION: LEGO1 0x10066a50 +void LegoWorldPresenter::ReadyTickle() +{ + 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(); + ProgressTickleState(e_starting); +} + +// FUNCTION: LEGO1 0x10066ac0 +void LegoWorldPresenter::StartingTickle() +{ + if (m_action->IsA("MxDSSerialAction")) { + MxPresenter* presenter = *m_list.begin(); + 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() == e_idle) { + (*it)->SetTickleState(e_ready); + } + } + } + + ProgressTickleState(e_streaming); +} + +// 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)->Add(p_presenter); + } +} + +// STUB: LEGO1 0x10067b00 +void LegoWorldPresenter::ParseExtra() +{ +} diff --git a/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp new file mode 100644 index 00000000..37ff261e --- /dev/null +++ b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp @@ -0,0 +1,75 @@ +#include "gasstation.h" + +#include "mxnotificationmanager.h" + +// FUNCTION: LEGO1 0x100046a0 +GasStation::GasStation() +{ + this->m_unk0xf8 = 0; + this->m_unk0x100 = 0; + this->m_unk0xfc = 0; + this->m_unk0x108 = 0; + this->m_unk0x104 = 0; + this->m_unk0x114 = 0; + this->m_unk0x106 = 0; + this->m_unk0x10c = 0; + this->m_unk0x115 = 0; + this->m_unk0x110 = 0; + + NotificationManager()->Register(this); +} + +// STUB: LEGO1 0x10004770 +MxBool GasStation::VTable0x5c() +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x100048c0 +GasStation::~GasStation() +{ + // TODO +} + +// STUB: LEGO1 0x10004990 +MxResult GasStation::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10004a60 +MxLong GasStation::Notify(MxParam& p_param) +{ + // TODO + + return 0; +} + +// STUB: LEGO1 0x10004b30 +void GasStation::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x10005c40 +void GasStation::Enable(MxBool p_enable) +{ + // TODO +} + +// STUB: LEGO1 0x10005c90 +MxResult GasStation::Tickle() +{ + // TODO + + return 0; +} + +// STUB: LEGO1 0x10005e70 +MxBool GasStation::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/gasstationentity.cpp b/LEGO1/lego/legoomni/src/gasstation/gasstationentity.cpp similarity index 100% rename from LEGO1/gasstationentity.cpp rename to LEGO1/lego/legoomni/src/gasstation/gasstationentity.cpp diff --git a/LEGO1/gasstationstate.cpp b/LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp similarity index 72% rename from LEGO1/gasstationstate.cpp rename to LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp index b4ec4dfd..b4b242ac 100644 --- a/LEGO1/gasstationstate.cpp +++ b/LEGO1/lego/legoomni/src/gasstation/gasstationstate.cpp @@ -16,3 +16,10 @@ GasStationState::GasStationState() unk0x08[1] = -1; unk0x08[2] = -1; } + +// STUB: LEGO1 0x10006300 +MxResult GasStationState::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return SUCCESS; +} diff --git a/LEGO1/lego/legoomni/src/hospital/ambulance.cpp b/LEGO1/lego/legoomni/src/hospital/ambulance.cpp new file mode 100644 index 00000000..aad42ca4 --- /dev/null +++ b/LEGO1/lego/legoomni/src/hospital/ambulance.cpp @@ -0,0 +1,81 @@ +#include "ambulance.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(Ambulance, 0x184); + +// FUNCTION: LEGO1 0x10035ee0 +Ambulance::Ambulance() +{ + this->m_unk0x168 = 0; + this->m_unk0x16a = -1; + this->m_unk0x164 = 0; + this->m_unk0x16c = 0; + this->m_unk0x174 = -1; + this->m_unk0x16e = 0; + this->m_unk0x178 = -1; + this->m_unk0x170 = 0; + this->m_unk0x172 = 0; + this->m_unk0x13c = 40.0; + this->m_unk0x17c = 1.0; +} + +// STUB: LEGO1 0x10035f90 +void Ambulance::Destroy(MxBool p_fromDestructor) +{ + // TODO +} + +// STUB: LEGO1 0x100361d0 +MxResult Ambulance::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10036300 +void Ambulance::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x10036420 +MxLong Ambulance::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10036860 +MxU32 Ambulance::VTable0xdc(MxType19NotificationParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10036ce0 +MxU32 Ambulance::VTable0xcc() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10036e90 +void Ambulance::VTable0xe4() +{ + // TODO +} + +// STUB: LEGO1 0x10036f90 +MxU32 Ambulance::VTable0xd4(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10037160 +MxResult Ambulance::Tickle() +{ + // TODO + return SUCCESS; +} diff --git a/LEGO1/ambulancemissionstate.cpp b/LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp similarity index 68% rename from LEGO1/ambulancemissionstate.cpp rename to LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp index 4213a587..e99c3229 100644 --- a/LEGO1/ambulancemissionstate.cpp +++ b/LEGO1/lego/legoomni/src/hospital/ambulancemissionstate.cpp @@ -8,9 +8,9 @@ AmbulanceMissionState::AmbulanceMissionState() m_unk0x10 = 0; m_unk0x12 = 0; m_unk0x14 = 0; - m_unk0x8 = 0; + m_unk0x08 = 0; m_unk0x16 = 0; - m_unk0xc = 0; + m_unk0x0c = 0; m_unk0x18 = 0; m_color1 = 0; m_color2 = 0; @@ -18,3 +18,10 @@ AmbulanceMissionState::AmbulanceMissionState() m_color4 = 0; m_color5 = 0; } + +// STUB: LEGO1 0x10037440 +MxResult AmbulanceMissionState::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/hospital/hospital.cpp b/LEGO1/lego/legoomni/src/hospital/hospital.cpp new file mode 100644 index 00000000..8412cee5 --- /dev/null +++ b/LEGO1/lego/legoomni/src/hospital/hospital.cpp @@ -0,0 +1,78 @@ +#include "hospital.h" + +#include "mxnotificationmanager.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(Hospital, 0x12c) + +// FUNCTION: LEGO1 0x100745e0 +Hospital::Hospital() +{ + this->m_unk0xf8 = 0; + this->m_unk0x100 = 0; + this->m_unk0x104 = 0; + this->m_unk0x108 = 0; + this->m_unk0xfc = 0; + this->m_unk0x10c = 0; + this->m_unk0x110 = 0; + this->m_unk0x114 = 0; + this->m_unk0x118 = 0; + this->m_unk0x11c = 0; + this->m_unk0x120 = 0; + this->m_unk0x128 = 0; + NotificationManager()->Register(this); +} + +// STUB: LEGO1 0x100746a0 +MxBool Hospital::VTable0x5c() +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x100747f0 +Hospital::~Hospital() +{ + // TODO +} + +// STUB: LEGO1 0x100748c0 +MxResult Hospital::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10074990 +MxLong Hospital::Notify(MxParam& p_param) +{ + // TODO + + return 0; +} + +// STUB: LEGO1 0x10074a60 +void Hospital::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x10076220 +void Hospital::Enable(MxBool p_enable) +{ + // TODO +} + +// STUB: LEGO1 0x10076270 +MxResult Hospital::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10076330 +MxBool Hospital::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/hospitalentity.cpp b/LEGO1/lego/legoomni/src/hospital/hospitalentity.cpp similarity index 100% rename from LEGO1/hospitalentity.cpp rename to LEGO1/lego/legoomni/src/hospital/hospitalentity.cpp diff --git a/LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp b/LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp new file mode 100644 index 00000000..326415d1 --- /dev/null +++ b/LEGO1/lego/legoomni/src/hospital/hospitalstate.cpp @@ -0,0 +1,21 @@ +#include "hospitalstate.h" + +DECOMP_SIZE_ASSERT(HospitalState, 0x18) + +// FUNCTION: LEGO1 0x10076370 +HospitalState::HospitalState() +{ + this->m_unk0x0c = 0; + this->m_unk0x0e = 0; + this->m_unk0x10 = 0; + this->m_unk0x12 = 0; + this->m_unk0x14 = 0; + this->m_unk0x16 = 0; +} + +// STUB: LEGO1 0x10076530 +MxResult HospitalState::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp new file mode 100644 index 00000000..98e7d1b9 --- /dev/null +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -0,0 +1,140 @@ +#include "elevatorbottom.h" + +#include "act1state.h" +#include "jukebox.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "mxnotificationmanager.h" +#include "mxomni.h" +#include "mxtransitionmanager.h" + +DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) + +// STRING: LEGO1 0x100f0d34 +// GLOBAL: LEGO1 0x100f3a44 +char* g_cameraLoc = "CAMERA_LOCATION"; + +// FUNCTION: LEGO1 0x10017e90 +ElevatorBottom::ElevatorBottom() +{ + NotificationManager()->Register(this); + this->m_unk0xf8 = 0; +} + +// FUNCTION: LEGO1 0x10018060 +ElevatorBottom::~ElevatorBottom() +{ + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); +} + +// FUNCTION: LEGO1 0x100180f0 +MxResult ElevatorBottom::Create(MxDSAction& p_dsAction) +{ + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + SetIsWorldActive(FALSE); + + GameState()->SetCurrentArea(5); + GameState()->StopArea(); + + return result; +} + +// FUNCTION: LEGO1 0x10018150 +MxLong ElevatorBottom::Notify(MxParam& p_param) +{ + MxLong ret = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationClick: + ret = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_unk0xf8); + break; + } + } + + return ret; +} + +// FUNCTION: LEGO1 0x100181b0 +void ElevatorBottom::ReadyWorld() +{ + LegoWorld::ReadyWorld(); + PlayMusic(JukeBox::e_informationCenter); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); +} + +// FUNCTION: LEGO1 0x100181d0 +MxLong ElevatorBottom::HandleClick(LegoControlManagerEvent& p_param) +{ + MxLong result = 0; + + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { + case 1: + m_unk0xf8 = 3; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 2: + m_unk0xf8 = 2; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 3: + LegoGameState* gs = GameState(); + Act1State* state = (Act1State*) gs->GetState("Act1State"); + + if (state == NULL) { + state = (Act1State*) gs->CreateState("Act1State"); + } + + state->SetUnknown1c(1); + m_unk0xf8 = 6; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + VariableTable()->SetVariable(g_cameraLoc, "LCAMZI1,90"); + result = 1; + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x100182c0 +void ElevatorBottom::Enable(MxBool p_enable) +{ + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } +} + +// FUNCTION: LEGO1 0x10018310 +MxBool ElevatorBottom::VTable0x64() +{ + DeleteObjects(&m_atom, 500, 999); + m_unk0xf8 = 2; + return TRUE; +} diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp new file mode 100644 index 00000000..38af048d --- /dev/null +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -0,0 +1,1189 @@ +#include "infocenter.h" + +#include "infocenterstate.h" +#include "jukebox.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 "mxcontrolpresenter.h" +#include "mxnotificationmanager.h" +#include "mxstillpresenter.h" +#include "mxticklemanager.h" +#include "mxtransitionmanager.h" + +DECOMP_SIZE_ASSERT(Infocenter, 0x1d8) +DECOMP_SIZE_ASSERT(InfocenterMapEntry, 0x18) + +// GLOBAL: LEGO1 0x100f76a0 +const char* g_object2x4red = "2x4red"; + +// GLOBAL: LEGO1 0x100f76a4 +const char* g_object2x4grn = "2x4grn"; + +// FUNCTION: LEGO1 0x1006ea20 +Infocenter::Infocenter() +{ + m_unk0xfc = 0; + m_unk0x11c = NULL; + m_infocenterState = NULL; + m_frameHotBitmap = NULL; + m_transitionDestination = 0; + m_currentInfomainScript = c_noInfomain; + m_currentCutscene = e_noIntro; + + memset(&m_mapAreas, 0, sizeof(m_mapAreas)); + + m_unk0x1c8 = -1; + SetAppCursor(1); + NotificationManager()->Register(this); + + m_infoManDialogueTimer = 0; + m_bookAnimationTimer = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; +} + +// FUNCTION: LEGO1 0x1006ec90 +Infocenter::~Infocenter() +{ + BackgroundAudioManager()->Stop(); + + MxS16 i = 0; + do { + if (m_infocenterState->GetInfocenterBufferElement(i) != NULL) { + m_infocenterState->GetInfocenterBufferElement(i)->Enable(FALSE); + } + i++; + } while (i < m_infocenterState->GetInfocenterBufferSize()); + + ControlManager()->Unregister(this); + + InputManager()->UnRegister(this); + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + NotificationManager()->Unregister(this); + + TickleManager()->UnregisterClient(this); +} + +// FUNCTION: LEGO1 0x1006ed90 +MxResult Infocenter::Create(MxDSAction& p_dsAction) +{ + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + m_infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); + if (!m_infocenterState) { + m_infocenterState = (InfocenterState*) GameState()->CreateState("InfocenterState"); + m_infocenterState->SetUnknown0x74(3); + } + else { + if (m_infocenterState->GetUnknown0x74() != 8 && m_infocenterState->GetUnknown0x74() != 4 && + m_infocenterState->GetUnknown0x74() != 15) { + m_infocenterState->SetUnknown0x74(2); + } + + MxS16 count, i; + for (count = 0; count < m_infocenterState->GetInfocenterBufferSize(); count++) { + if (m_infocenterState->GetInfocenterBufferElement(count) == NULL) { + break; + } + } + + for (i = 0; i < count; i++) { + if (m_infocenterState->GetInfocenterBufferElement(i)) { + m_infocenterState->GetInfocenterBufferElement(i)->Enable(TRUE); + m_infocenterState->GetInfocenterBufferElement(i)->SetTickleState(MxPresenter::e_repeating); + m_infocenterState->GetInfocenterBufferElement(i)->VTable0x88(((7 - count) / 2 + i) * 29 + 223, 45); + } + } + } + + GameState()->SetCurrentArea(2); + GameState()->StopArea(0); + + if (m_infocenterState->GetUnknown0x74() == 4) { + LegoGameState* state = GameState(); + state->SetPreviousArea(GameState()->GetUnknown0x42c()); + } + + InputManager()->Register(this); + SetIsWorldActive(FALSE); + + return result; +} + +// FUNCTION: LEGO1 0x1006ef10 +MxLong Infocenter::Notify(MxParam& p_param) +{ + MxLong result = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationType0: + result = HandleNotification0((MxNotificationParam&) p_param); + break; + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) 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_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + StopBookAnimation(); + m_bookAnimationTimer = 0; + + if (m_infocenterState->GetUnknown0x74() == 0x0c) { + StartCredits(); + m_infocenterState->SetUnknown0x74(0xd); + } + else if (m_transitionDestination != 0) { + BackgroundAudioManager()->RaiseVolume(); + GameState()->SwitchArea(m_transitionDestination); + m_transitionDestination = 0; + } + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x1006f080 +MxLong Infocenter::HandleEndAction(MxEndActionNotificationParam& p_param) +{ + MxDSAction* action = p_param.GetAction(); + if (action->GetAtomId() == *g_creditsScript && action->GetObjectId() == c_unk499) { + Lego()->CloseMainWindow(); + return 1; + } + + if (action->GetAtomId() == m_atom && + (action->GetObjectId() == c_mamaMovie || action->GetObjectId() == c_papaMovie || + action->GetObjectId() == c_pepperMovie || action->GetObjectId() == c_nickMovie || + action->GetObjectId() == c_lauraMovie)) { + if (m_unk0x1d4) { + m_unk0x1d4--; + } + + if (!m_unk0x1d4) { + PlayMusic(JukeBox::e_informationCenter); + GameState()->FUN_10039780(m_unk0xfc); + + switch (m_unk0xfc) { + case 1: + PlayAction(c_pepperCharacterSelect); + break; + case 2: + PlayAction(c_mamaCharacterSelect); + break; + case 3: + PlayAction(c_papaCharacterSelect); + break; + case 4: + PlayAction(c_nickCharacterSelect); + break; + case 5: + PlayAction(c_lauraCharacterSelect); + break; + default: + break; + } + + UpdateFrameHot(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().GetInternal(), 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); + PlayAction(c_badEndingDialogue); + m_currentCutscene = e_noIntro; + return 1; + case e_goodEndMovie: + StopCutscene(); + m_infocenterState->SetUnknown0x74(11); + PlayAction(c_goodEndingDialogue); + m_currentCutscene = e_noIntro; + return 1; + } + + // default / 2nd case probably? + StopCutscene(); + m_infocenterState->SetUnknown0x74(11); + PlayAction(c_welcomeDialogue); + m_currentCutscene = e_noIntro; + + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_bookAnimationTimer = 1; + return 1; + } + break; + case 1: + m_infocenterState->SetUnknown0x74(11); + + switch (m_currentCutscene) { + case e_badEndMovie: + PlayAction(c_badEndingDialogue); + break; + case e_goodEndMovie: + PlayAction(c_goodEndingDialogue); + break; + default: + PlayAction(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() == c_goToRegBook || action->GetObjectId() == c_goToRegBookRed) { + 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_infoManDialogueTimer = 1; + PlayMusic(JukeBox::e_informationCenter); + } + + 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::ReadyWorld() +{ + m_infoManDialogueTimer = 0; + m_bookAnimationTimer = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; + + MxStillPresenter* bg = (MxStillPresenter*) Find("MxStillPresenter", "Background_Bitmap"); + MxStillPresenter* bgRed = (MxStillPresenter*) Find("MxStillPresenter", "BackgroundRed_Bitmap"); + + switch (GameState()->GetUnknown10()) { + case 0: + bg->Enable(1); + 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_bookAnimationTimer = 1; + } + + PlayAction(c_letsGetStartedDialogue); + PlayMusic(JukeBox::e_informationCenter); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + return; + default: + PlayMusic(JukeBox::e_informationCenter); + // TODO + break; + case 8: + PlayMusic(JukeBox::e_informationCenter); + PlayAction(c_exitConfirmationDialogue); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + return; + case 0xf: + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_bookAnimationTimer = 1; + } + + PlayAction(c_clickOnInfomanDialogue); + PlayMusic(JukeBox::e_informationCenter); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + return; + } + break; + case 1: + // TODO + break; + case 2: + // TODO + break; + default: + m_infocenterState->SetUnknown0x74(11); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + return; + } +} + +// FUNCTION: LEGO1 0x1006f9a0 +void Infocenter::InitializeBitmaps() +{ + m_radio.Initialize(TRUE); + + ((MxPresenter*) Find(m_atom, c_leftArrowCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_rightArrowCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_infoCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_boatCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_raceCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_pizzaCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_gasCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_medCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_copCtl))->Enable(TRUE); + + ((MxPresenter*) Find(m_atom, c_mamaCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_papaCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_pepperCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_nickCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_lauraCtl))->Enable(TRUE); + ((MxPresenter*) Find(m_atom, c_radioCtl))->Enable(TRUE); + + m_mapAreas[0].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Info_A_Bitmap"); + m_mapAreas[0].m_area.SetLeft(391); + m_mapAreas[0].m_area.SetTop(182); + m_mapAreas[0].m_area.SetRight(427); + m_mapAreas[0].m_area.SetBottom(230); + m_mapAreas[0].m_unk0x04 = 3; + + m_mapAreas[1].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Boat_A_Bitmap"); + m_mapAreas[1].m_area.SetLeft(304); + m_mapAreas[1].m_area.SetTop(225); + m_mapAreas[1].m_area.SetRight(350); + m_mapAreas[1].m_area.SetBottom(268); + m_mapAreas[1].m_unk0x04 = 10; + + m_mapAreas[2].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Race_A_Bitmap"); + m_mapAreas[2].m_area.SetLeft(301); + m_mapAreas[2].m_area.SetTop(133); + m_mapAreas[2].m_area.SetRight(347); + m_mapAreas[2].m_area.SetBottom(181); + m_mapAreas[2].m_unk0x04 = 11; + + m_mapAreas[3].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Pizza_A_Bitmap"); + m_mapAreas[3].m_area.SetLeft(289); + m_mapAreas[3].m_area.SetTop(182); + m_mapAreas[3].m_area.SetRight(335); + m_mapAreas[3].m_area.SetBottom(225); + m_mapAreas[3].m_unk0x04 = 12; + + m_mapAreas[4].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Gas_A_Bitmap"); + m_mapAreas[4].m_area.SetLeft(350); + m_mapAreas[4].m_area.SetTop(161); + m_mapAreas[4].m_area.SetRight(391); + m_mapAreas[4].m_area.SetBottom(209); + m_mapAreas[4].m_unk0x04 = 13; + + m_mapAreas[5].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Med_A_Bitmap"); + m_mapAreas[5].m_area.SetLeft(392); + m_mapAreas[5].m_area.SetTop(130); + m_mapAreas[5].m_area.SetRight(438); + m_mapAreas[5].m_area.SetBottom(176); + m_mapAreas[5].m_unk0x04 = 14; + + m_mapAreas[6].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Cop_A_Bitmap"); + m_mapAreas[6].m_area.SetLeft(396); + m_mapAreas[6].m_area.SetTop(229); + m_mapAreas[6].m_area.SetRight(442); + m_mapAreas[6].m_area.SetBottom(272); + m_mapAreas[6].m_unk0x04 = 15; + + m_frameHotBitmap = (MxStillPresenter*) Find("MxStillPresenter", "FrameHot_Bitmap"); + + UpdateFrameHot(TRUE); +} + +// FUNCTION: LEGO1 0x1006fd00 +MxU8 Infocenter::HandleMouseMove(MxS32 p_x, MxS32 p_y) +{ + if (m_unk0x11c) { + if (!m_unk0x11c->IsEnabled()) { + MxS32 oldDisplayZ = m_unk0x11c->GetDisplayZ(); + + m_unk0x11c->SetDisplayZ(1000); + VideoManager()->SortPresenterList(); + m_unk0x11c->Enable(TRUE); + m_unk0x11c->VTable0x88(p_x, p_y); + + m_unk0x11c->SetDisplayZ(oldDisplayZ); + } + else { + m_unk0x11c->VTable0x88(p_x, p_y); + } + + FUN_10070d10(p_x, p_y); + return 1; + } + + return 0; +} + +// 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_bookAnimationTimer = 1; + return 1; + } + break; + case 1: + case 4: + break; + default: { + InfomainScript script = m_currentInfomainScript; + StopCurrentAction(); + + 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; +} + +// FUNCTION: LEGO1 0x1006feb0 +MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) +{ + if (m_unk0x11c) { + MxControlPresenter* control = InputManager()->GetControlManager()->FUN_100294e0(p_x - 1, p_y - 1); + + switch (m_unk0x11c->GetAction()->GetObjectId()) { + case c_mamaSelected: + m_unk0xfc = 2; + break; + case c_papaSelected: + m_unk0xfc = 3; + break; + case c_pepperSelected: + m_unk0xfc = 1; + break; + case c_nickSelected: + m_unk0xfc = 4; + break; + case c_lauraSelected: + m_unk0xfc = 5; + break; + } + + if (control != NULL) { + m_infoManDialogueTimer = 0; + + switch (control->GetAction()->GetObjectId()) { + case c_mamaCtl: + if (m_unk0xfc == 2) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_mamaMovie); + m_unk0x1d4++; + } + break; + case c_papaCtl: + if (m_unk0xfc == 3) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_papaMovie); + m_unk0x1d4++; + } + break; + case c_pepperCtl: + if (m_unk0xfc == 1) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_pepperMovie); + m_unk0x1d4++; + } + break; + case c_nickCtl: + if (m_unk0xfc == 4) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_nickMovie); + m_unk0x1d4++; + } + break; + case c_lauraCtl: + if (m_unk0xfc == 5) { + m_radio.Stop(); + BackgroundAudioManager()->Stop(); + PlayAction(c_lauraMovie); + m_unk0x1d4++; + } + break; + } + } + else { + if (m_unk0x1c8 != -1) { + m_infoManDialogueTimer = 0; + + switch (m_mapAreas[m_unk0x1c8].m_unk0x04) { + case 3: + GameState()->FUN_10039780(m_unk0xfc); + + switch (m_unk0xfc) { + case 1: + PlayAction(c_pepperCharacterSelect); + break; + case 2: + PlayAction(c_mamaCharacterSelect); + break; + case 3: + PlayAction(c_papaCharacterSelect); + break; + case 4: + PlayAction(c_nickCharacterSelect); + break; + case 5: + PlayAction(c_lauraCharacterSelect); + break; + } + break; + case 10: + if (m_unk0xfc) { + m_transitionDestination = 16; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 11: + if (m_unk0xfc) { + m_transitionDestination = 19; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 12: + if (m_unk0xfc) { + m_transitionDestination = 22; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 13: + if (m_unk0xfc) { + m_transitionDestination = 25; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 14: + if (m_unk0xfc) { + m_transitionDestination = 29; + m_infocenterState->SetUnknown0x74(5); + } + break; + case 15: + if (m_unk0xfc) { + m_transitionDestination = 32; + m_infocenterState->SetUnknown0x74(5); + } + break; + } + } + } + + m_unk0x11c->Enable(FALSE); + m_unk0x11c = NULL; + + if (m_infocenterState->GetUnknown0x74() == 5) { + InfomainScript dialogueToPlay; + + if (GameState()->GetUnknown10() == 0) { + if (m_infocenterState->GetInfocenterBufferElement(0) == NULL) { + m_infocenterState->SetUnknown0x74(2); + m_transitionDestination = 0; + dialogueToPlay = c_registerToContinueDialogue; + } + else { + switch (m_unk0xfc) { + case 1: + dialogueToPlay = c_pepperCharacterSelect; + break; + case 2: + dialogueToPlay = c_mamaCharacterSelect; + break; + case 3: + dialogueToPlay = c_papaCharacterSelect; + break; + case 4: + dialogueToPlay = c_nickCharacterSelect; + break; + case 5: + dialogueToPlay = c_lauraCharacterSelect; + GameState()->SetUnknown0x0c(m_unk0xfc); + break; + default: + dialogueToPlay = + (InfomainScript) m_infocenterState->GetUnknown0x44()[GameState()->GetUnknown10()].Next(); + break; + } + + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + } + } + else { + dialogueToPlay = + (InfomainScript) m_infocenterState->GetUnknown0x44()[GameState()->GetUnknown10()].Next(); + } + + PlayAction(dialogueToPlay); + } + + UpdateFrameHot(TRUE); + FUN_10070d10(0, 0); + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x10070370 +MxU8 Infocenter::HandleClick(LegoControlManagerEvent& p_param) +{ + if (p_param.GetUnknown0x28() == 1) { + m_infoManDialogueTimer = 0; + + InfomainScript actionToPlay = c_noInfomain; + StopCurrentAction(); + InfomainScript characterBitmap = c_noInfomain; + + GameState(); + + switch (p_param.GetClickedObjectId()) { + case c_leftArrowCtl: + m_infocenterState->SetUnknown0x74(14); + StopCurrentAction(); + + if (GameState()->GetUnknown10() == 0) { + m_radio.Stop(); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_transitionDestination = 5; + } + else { + MxU32 objectId = m_infocenterState->GetUnknown0x68().Next(); + PlayAction((InfomainScript) objectId); + } + + break; + case c_rightArrowCtl: + m_infocenterState->SetUnknown0x74(14); + StopCurrentAction(); + + if (GameState()->GetUnknown10() == 0) { + m_radio.Stop(); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_transitionDestination = 13; + } + else { + MxU32 objectId = m_infocenterState->GetUnknown0x68().Next(); + PlayAction((InfomainScript) objectId); + } + + break; + case c_infoCtl: + m_radio.Stop(); + break; + case c_doorCtl: + if (m_infocenterState->GetUnknown0x74() != 8) { + actionToPlay = c_exitConfirmationDialogue; + m_radio.Stop(); + m_infocenterState->SetUnknown0x74(8); + } + + break; + case c_boatCtl: + actionToPlay = c_boatCtlDescription; + m_radio.Stop(); + break; + case c_raceCtl: + actionToPlay = c_raceCtlDescription; + m_radio.Stop(); + break; + case c_pizzaCtl: + actionToPlay = c_pizzaCtlDescription; + m_radio.Stop(); + break; + case c_gasCtl: + actionToPlay = c_gasCtlDescription; + m_radio.Stop(); + break; + case c_medCtl: + actionToPlay = c_medCtlDescription; + m_radio.Stop(); + break; + case c_copCtlDescription: + actionToPlay = c_copCtlDescription; + m_radio.Stop(); + break; + case c_bigInfoCtl: + // TODO + break; + case c_bookCtl: + m_transitionDestination = 12; + m_infocenterState->SetUnknown0x74(4); + actionToPlay = GameState()->GetUnknown10() ? c_goToRegBookRed : c_goToRegBook; + m_radio.Stop(); + GameState()->SetCurrentArea(GameState()->GetPreviousArea()); + InputManager()->DisableInputProcessing(); + break; + case c_mamaCtl: + characterBitmap = c_mamaSelected; + UpdateFrameHot(FALSE); + break; + case c_papaCtl: + characterBitmap = c_papaSelected; + UpdateFrameHot(FALSE); + break; + case c_pepperCtl: + characterBitmap = c_pepperSelected; + UpdateFrameHot(FALSE); + break; + case c_nickCtl: + characterBitmap = c_nickSelected; + UpdateFrameHot(FALSE); + break; + case c_lauraCtl: + characterBitmap = c_lauraSelected; + UpdateFrameHot(FALSE); + break; + } + + if (actionToPlay != c_noInfomain) { + PlayAction(actionToPlay); + } + + if (characterBitmap != c_noInfomain) { + m_unk0x11c = (MxStillPresenter*) Find(m_atom, characterBitmap); + } + } + + return 1; +} + +// FUNCTION: LEGO1 0x10070870 +MxLong Infocenter::HandleNotification0(MxNotificationParam& p_param) +{ + // MxLong result + MxCore* sender = p_param.GetSender(); + + if (sender == NULL) { + if (m_infocenterState->GetUnknown0x74() == 8) { + m_infoManDialogueTimer = 0; + StopCutscene(); + PlayAction(c_exitConfirmationDialogue); + } + } + else if (sender->IsA("MxEntity") && m_infocenterState->GetUnknown0x74() != 5 && m_infocenterState->GetUnknown0x74() != 12) { + switch (((MxEntity*) sender)->GetEntityId()) { + case 5: { + m_infoManDialogueTimer = 0; + + InfomainScript objectId; + if (GameState()->GetUnknown10()) { + objectId = (InfomainScript) m_infocenterState->GetUnknown0x14().Next(); + } + else { + objectId = (InfomainScript) m_infocenterState->GetUnknown0x08().Next(); + } + + PlayAction(objectId); + FUN_10015860(g_object2x4red, 0); + FUN_10015860(g_object2x4grn, 0); + return 1; + } + case 6: + if (m_infocenterState->GetUnknown0x74() == 8) { + StopCurrentAction(); + FUN_10015860(g_object2x4red, 0); + FUN_10015860(g_object2x4grn, 0); + m_infocenterState->SetUnknown0x74(2); + PlayAction(c_infomanSneeze); + return 1; + } + case 7: + if (m_infocenterState->GetUnknown0x74() == 8) { + if (m_infocenterState->GetInfocenterBufferElement(0)) { + GameState()->Save(0); + } + + m_infocenterState->SetUnknown0x74(12); + PlayAction(c_exitGameDialogue); + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + return 1; + } + } + } + else { + if (sender->IsA("Radio") && m_radio.GetState()->IsActive()) { + if (m_currentInfomainScript == c_mamaMovie || m_currentInfomainScript == c_papaMovie || + m_currentInfomainScript == c_pepperMovie || m_currentInfomainScript == c_nickMovie || + m_currentInfomainScript == c_lauraMovie || m_currentInfomainScript == c_unk557 || + m_currentInfomainScript == c_boatCtlDescription || m_currentInfomainScript == c_raceCtlDescription || + m_currentInfomainScript == c_pizzaCtlDescription || m_currentInfomainScript == c_gasCtlDescription || + m_currentInfomainScript == c_medCtlDescription || m_currentInfomainScript == c_copCtlDescription) { + StopCurrentAction(); + } + } + } + + return 1; +} + +// FUNCTION: LEGO1 0x10070aa0 +void Infocenter::Enable(MxBool p_enable) +{ + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } +} + +// FUNCTION: LEGO1 0x10070af0 +MxResult Infocenter::Tickle() +{ + if (m_worldStarted == FALSE) { + LegoWorld::Tickle(); + return SUCCESS; + } + + if (m_infoManDialogueTimer != 0 && (m_infoManDialogueTimer += 100) > 25000) { + PlayAction(c_clickOnInfomanDialogue); + m_infoManDialogueTimer = 0; + } + + if (m_bookAnimationTimer != 0 && (m_bookAnimationTimer += 100) > 3000) { + PlayBookAnimation(); + m_bookAnimationTimer = 1; + } + + if (m_unk0x1d6 != 0) { + m_unk0x1d6 += 100; + + if (m_unk0x1d6 > 3400 && m_unk0x1d6 < 3650) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 1); + } + else if (m_unk0x1d6 > 3650 && m_unk0x1d6 < 3900) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 0); + } + else if (m_unk0x1d6 > 3900 && m_unk0x1d6 < 4150) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 1); + } + else if (m_unk0x1d6 > 4400) { + ControlManager()->FUN_100293c0(0x10, m_atom.GetInternal(), 0); + m_unk0x1d6 = 0; + } + } + + return SUCCESS; +} + +// 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(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); +} + +// FUNCTION: LEGO1 0x10070d00 +MxBool Infocenter::VTable0x5c() +{ + return TRUE; +} + +// FUNCTION: LEGO1 0x10070d10 +void Infocenter::FUN_10070d10(MxS32 p_x, MxS32 p_y) +{ + MxS16 i; + for (i = 0; i < (MxS32) (sizeof(m_mapAreas) / sizeof(m_mapAreas[0])); i++) { + MxS32 right = m_mapAreas[i].m_area.GetRight(); + MxS32 bottom = m_mapAreas[i].m_area.GetBottom(); + MxS32 left = m_mapAreas[i].m_area.GetLeft(); + MxS32 top = m_mapAreas[i].m_area.GetTop(); + + if (left <= p_x && p_x <= right && top <= p_y && p_y <= bottom) { + break; + } + } + + if (i == 7) { + i = -1; + } + + if (i != m_unk0x1c8) { + if (m_unk0x1c8 != -1) { + m_mapAreas[m_unk0x1c8].m_presenter->Enable(FALSE); + } + + m_unk0x1c8 = i; + if (i != -1) { + m_mapAreas[i].m_presenter->Enable(TRUE); + } + } +} + +// FUNCTION: LEGO1 0x10070dc0 +void Infocenter::UpdateFrameHot(MxBool p_display) +{ + if (p_display) { + MxS32 x, y; + + switch (GameState()->GetUnknownC()) { + case 1: + x = 302; + y = 81; + break; + case 2: + x = 204; + y = 81; + break; + case 3: + x = 253; + y = 81; + break; + case 4: + x = 353; + y = 81; + break; + case 5: + x = 399; + y = 81; + break; + default: + return; + } + + MxS32 originalDisplayZ = m_frameHotBitmap->GetDisplayZ(); + + m_frameHotBitmap->SetDisplayZ(1000); + VideoManager()->SortPresenterList(); + + m_frameHotBitmap->Enable(TRUE); + m_frameHotBitmap->VTable0x88(x, y); + m_frameHotBitmap->SetDisplayZ(originalDisplayZ); + } + else { + if (m_frameHotBitmap) { + m_frameHotBitmap->Enable(FALSE); + } + } +} + +// STUB: LEGO1 0x10070e90 +void Infocenter::FUN_10070e90() +{ +} + +// FUNCTION: LEGO1 0x10070f60 +MxBool Infocenter::VTable0x64() +{ + if (m_infocenterState != NULL) { + MxU32 val = m_infocenterState->GetUnknown0x74(); + + if (val == 0) { + StopCutscene(); + m_infocenterState->SetUnknown0x74(1); + } + else if (val == 13) { + StopCredits(); + } + else if (val != 8) { + m_infocenterState->SetUnknown0x74(8); + +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType0, NULL); + Notify(param); + } +#else + Notify(MxNotificationParam(c_notificationType0, NULL)); +#endif + } + } + + return FALSE; +} + +// STUB: LEGO1 0x10071030 +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::PlayAction(InfomainScript p_objectId) +{ + MxDSAction action; + action.SetObjectId(p_objectId); + action.SetAtomId(*g_infomainScript); + StopCurrentAction(); + + m_currentInfomainScript = p_objectId; + BackgroundAudioManager()->LowerVolume(); + Start(&action); +} + +// FUNCTION: LEGO1 0x100713d0 +void Infocenter::StopCurrentAction() +{ + 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/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp new file mode 100644 index 00000000..325b5eb0 --- /dev/null +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp @@ -0,0 +1,168 @@ +#include "infocenterdoor.h" + +#include "infocenterstate.h" +#include "jukebox.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "mxactionnotificationparam.h" +#include "mxbackgroundaudiomanager.h" +#include "mxnotificationmanager.h" +#include "mxtransitionmanager.h" + +DECOMP_SIZE_ASSERT(InfocenterDoor, 0xfc) + +// FUNCTION: LEGO1 0x10037730 +InfocenterDoor::InfocenterDoor() +{ + m_unk0xf8 = 0; + + NotificationManager()->Register(this); +} + +// FUNCTION: LEGO1 0x100378f0 +InfocenterDoor::~InfocenterDoor() +{ + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); +} + +// FUNCTION: LEGO1 0x10037980 +MxResult InfocenterDoor::Create(MxDSAction& p_dsAction) +{ + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + SetIsWorldActive(FALSE); + + GameState()->SetCurrentArea(3); + GameState()->StopArea(); + + return result; +} + +// FUNCTION: LEGO1 0x100379e0 +MxLong InfocenterDoor::Notify(MxParam& p_param) +{ + MxLong result = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationEndAction: + if (((MxEndActionNotificationParam&) p_param).GetAction()->GetAtomId() == m_atom) { + BackgroundAudioManager()->RaiseVolume(); + result = 1; + } + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_unk0xf8); + result = 1; + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x10037a70 +void InfocenterDoor::ReadyWorld() +{ + LegoWorld::ReadyWorld(); + PlayMusic(JukeBox::e_informationCenter); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); +} + +// FUNCTION: LEGO1 0x10037a90 +MxLong InfocenterDoor::HandleClick(LegoControlManagerEvent& p_param) +{ + MxLong result = 0; + + if (p_param.GetUnknown0x28() == 1) { + DeleteObjects(&m_atom, 500, 510); + + switch (p_param.GetClickedObjectId()) { + case 1: + m_unk0xf8 = 13; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 2: + m_unk0xf8 = 5; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 3: + m_unk0xf8 = 2; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 4: + if (GameState()->GetUnknownC()) { + InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState"); + if (state->GetInfocenterBufferElement(0) != NULL) { + m_unk0xf8 = 4; + } + else { + MxDSAction action; + action.SetObjectId(503); + action.SetAtomId(*g_infodoorScript); + BackgroundAudioManager()->LowerVolume(); + Start(&action); + goto done; + } + } + else { + MxDSAction action; + action.SetObjectId(500); + action.SetAtomId(*g_infodoorScript); + BackgroundAudioManager()->LowerVolume(); + Start(&action); + goto done; + } + + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + + done: + result = 1; + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x10037c80 +void InfocenterDoor::Enable(MxBool p_enable) +{ + LegoWorld::Enable(p_enable); + + if (p_enable) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } +} + +// FUNCTION: LEGO1 0x10037cd0 +MxBool InfocenterDoor::VTable0x64() +{ + DeleteObjects(&m_atom, 500, 510); + m_unk0xf8 = 2; + return TRUE; +} diff --git a/LEGO1/infocenterentity.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterentity.cpp similarity index 100% rename from LEGO1/infocenterentity.cpp rename to LEGO1/lego/legoomni/src/infocenter/infocenterentity.cpp diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp new file mode 100644 index 00000000..55f4f4d8 --- /dev/null +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp @@ -0,0 +1,122 @@ +#include "infocenterstate.h" + +#include "infocenter.h" + +DECOMP_SIZE_ASSERT(InfocenterState, 0x94); + +// GLOBAL: LEGO1 0x100f76a8 +Infocenter::InfomainScript g_unk0x100f76a8[14] = { + Infocenter::c_clickOnObjectsGuidanceDialogue, + Infocenter::c_arrowNavigationGuidanceDialogue, + Infocenter::c_elevatorGuidanceDialogue, + Infocenter::c_radioGuidanceDialogue, + Infocenter::c_exitGuidanceDialogue1, + Infocenter::c_goOutsideGuidanceDialogue, + Infocenter::c_experimentGuidanceDialogue, + Infocenter::c_returnBackGuidanceDialogue1, + Infocenter::c_bricksterWarningDialogue, + Infocenter::c_infomanHiccup, + Infocenter::c_infomanSneeze, + Infocenter::c_infomanLaughs, + Infocenter::c_newGameGuidanceDialogue, + Infocenter::c_returnBackGuidanceDialogue3 +}; + +// GLOBAL: LEGO1 0x100f76e0 +Infocenter::InfomainScript g_unk0x100f76e0[6] = { + Infocenter::c_bricksterWarningDialogue, + Infocenter::c_newGameGuidanceDialogue, + Infocenter::c_bricksterEscapedDialogue1, + Infocenter::c_bricksterEscapedDialogue5, + Infocenter::c_exitGuidanceDialogue2 + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f76f8 +Infocenter::InfomainScript g_unk0x100f76f8[6] = { + Infocenter::c_returnBackGuidanceDialogue2, + Infocenter::c_reenterInfoCenterDialogue1, + Infocenter::c_reenterInfoCenterDialogue2, + Infocenter::c_reenterInfoCenterDialogue3, + Infocenter::c_reenterInfoCenterDialogue4 + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f7710 +Infocenter::InfomainScript g_unk0x100f7710[4] = { + Infocenter::c_bricksterEscapedDialogue1, + Infocenter::c_bricksterEscapedDialogue2, + Infocenter::c_bricksterEscapedDialogue3, + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f7720 +Infocenter::InfomainScript g_unk0x100f7720[4] = { + Infocenter::c_bricksterEscapedDialogue4, + Infocenter::c_bricksterEscapedDialogue5, + Infocenter::c_bricksterEscapedDialogue6, + Infocenter::c_bricksterEscapedDialogue7 +}; + +// GLOBAL: LEGO1 0x100f7730 +Infocenter::InfomainScript g_unk0x100f7730[4] = { + Infocenter::c_leaveInfoCenterDialogue1, + Infocenter::c_leaveInfoCenterDialogue2, + Infocenter::c_leaveInfoCenterDialogue3, + Infocenter::c_leaveInfoCenterDialogue4 +}; + +// GLOBAL: LEGO1 0x100f7740 +Infocenter::InfomainScript g_unk0x100f7740[4] = + {Infocenter::c_unk569, Infocenter::c_unk570, Infocenter::c_unk571, Infocenter::c_unk572}; + +// GLOBAL: LEGO1 0x100f7750 +Infocenter::InfomainScript g_unk0x100f7750[4] = { + Infocenter::c_unk566, + Infocenter::c_unk567, + Infocenter::c_unk568, + // Zero-terminated +}; + +// GLOBAL: LEGO1 0x100f7760 +Infocenter::InfomainScript g_unk0x100f7760[2] = {Infocenter::c_bricksterDialogue, Infocenter::c_bricksterLaughs}; + +// FUNCTION: LEGO1 0x10071600 +InfocenterState::InfocenterState() +{ + m_unk0x08 = LegoState::Playlist((MxU32*) g_unk0x100f76a8, sizeof(g_unk0x100f76a8) / sizeof(g_unk0x100f76a8[0])); + + m_unk0x14 = LegoState::Playlist((MxU32*) g_unk0x100f76e0, sizeof(g_unk0x100f76e0) / sizeof(g_unk0x100f76e0[0]) - 1); + + m_unk0x20[0] = + LegoState::Playlist((MxU32*) g_unk0x100f76f8, sizeof(g_unk0x100f76f8) / sizeof(g_unk0x100f76f8[0]) - 1); + + m_unk0x20[1] = + LegoState::Playlist((MxU32*) g_unk0x100f7710, sizeof(g_unk0x100f7710) / sizeof(g_unk0x100f7710[0]) - 1); + + m_unk0x20[2] = LegoState::Playlist((MxU32*) g_unk0x100f7720, sizeof(g_unk0x100f7720) / sizeof(g_unk0x100f7720[0])); + + m_unk0x44[0] = LegoState::Playlist((MxU32*) g_unk0x100f7730, sizeof(g_unk0x100f7730) / sizeof(g_unk0x100f7730[0])); + + m_unk0x44[1] = LegoState::Playlist((MxU32*) g_unk0x100f7740, sizeof(g_unk0x100f7740) / sizeof(g_unk0x100f7740[0])); + + m_unk0x44[2] = + LegoState::Playlist((MxU32*) g_unk0x100f7750, sizeof(g_unk0x100f7750) / sizeof(g_unk0x100f7750[0]) - 1); + + m_unk0x68 = LegoState::Playlist((MxU32*) g_unk0x100f7760, sizeof(g_unk0x100f7760) / sizeof(g_unk0x100f7760[0])); + + memset(m_buffer, 0, sizeof(m_buffer)); +} + +// FUNCTION: LEGO1 0x10071920 +InfocenterState::~InfocenterState() +{ + MxS16 i = 0; + do { + if (GetInfocenterBufferElement(i) != NULL) { + delete GetInfocenterBufferElement(i)->GetAction(); + delete GetInfocenterBufferElement(i); + } + i++; + } while (i < GetInfocenterBufferSize()); +} diff --git a/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp b/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp new file mode 100644 index 00000000..5d5c6d94 --- /dev/null +++ b/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp @@ -0,0 +1,55 @@ +#include "registrationbook.h" + +#include "legoomni.h" + +// STUB: LEGO1 0x10076d20 +RegistrationBook::RegistrationBook() +{ + // TODO +} + +// STUB: LEGO1 0x10076f50 +RegistrationBook::~RegistrationBook() +{ + // TODO +} + +// STUB: LEGO1 0x10077060 +MxResult RegistrationBook::Create(MxDSAction& p_dsAction) +{ + return SUCCESS; +} + +// STUB: LEGO1 0x100770e0 +MxLong RegistrationBook::Notify(MxParam& p_param) +{ + // TODO + + return 0; +} + +// STUB: LEGO1 0x10077cc0 +void RegistrationBook::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x10077fd0 +MxResult RegistrationBook::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10078180 +void RegistrationBook::Enable(MxBool p_enable) +{ + // TODO +} + +// FUNCTION: LEGO1 0x100783e0 +MxBool RegistrationBook::VTable0x64() +{ + DeleteObjects(&m_atom, 500, 506); + return TRUE; +} diff --git a/LEGO1/score.cpp b/LEGO1/lego/legoomni/src/infocenter/score.cpp similarity index 79% rename from LEGO1/score.cpp rename to LEGO1/lego/legoomni/src/infocenter/score.cpp index dcc39f02..74744fbf 100644 --- a/LEGO1/score.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/score.cpp @@ -2,6 +2,7 @@ #include "ambulancemissionstate.h" #include "gifmanager.h" +#include "jukebox.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" @@ -31,17 +32,18 @@ MxBool Score::VTable0x5c() // FUNCTION: LEGO1 0x10001200 Score::~Score() { - if (InputManager()->GetWorld() == this) + if (InputManager()->GetWorld() == this) { InputManager()->ClearWorld(); + } InputManager()->UnRegister(this); ControlManager()->Unregister(this); NotificationManager()->Unregister(this); } // 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); @@ -51,8 +53,8 @@ MxResult Score::Create(MxDSObject& p_dsObject) LegoGameState* gs = GameState(); ScoreState* state = (ScoreState*) gs->GetState("ScoreState"); m_state = state ? state : (ScoreState*) gs->CreateState("ScoreState"); - GameState()->SetUnknown424(0xd); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(0xd); + GameState()->StopArea(); } return result; @@ -76,7 +78,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; @@ -86,17 +88,19 @@ MxLong Score::Notify(MxParam& p_param) ret = FUN_10001510((MxEndActionNotificationParam&) p_param); break; case c_notificationKeyPress: - if (((LegoEventNotificationParam&) p_param).GetKey() == 0x20) + if (((LegoEventNotificationParam&) p_param).GetKey() == 0x20) { DeleteScript(); // Shutting down + } ret = 1; break; - case TYPE17: - ret = FUN_100016d0((MxType17NotificationParam&) p_param); + case c_notificationClick: + ret = FUN_100016d0((LegoControlManagerEvent&) p_param); break; - case MXTRANSITIONMANAGER_TRANSITIONENDED: + case c_notificationTransitioned: DeleteObjects(g_infoscorScript, 7, 9); - if (m_unk0xf8) - GameState()->HandleAction(m_unk0xf8); + if (m_unk0xf8) { + GameState()->SwitchArea(m_unk0xf8); + } ret = 1; break; default: @@ -116,10 +120,10 @@ 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); + PlayMusic(JukeBox::e_informationCenter); m_state->SetTutorialFlag(FALSE); } } @@ -128,9 +132,9 @@ MxLong Score::FUN_10001510(MxEndActionNotificationParam& p_param) } // FUNCTION: LEGO1 0x10001580 -void Score::Stop() +void Score::ReadyWorld() { - LegoWorld::Stop(); + LegoWorld::ReadyWorld(); MxDSAction action; action.SetObjectId(0x1f4); @@ -144,28 +148,29 @@ void Score::Stop() action.SetAtomId(*g_infoscorScript); Start(&action); } - else - PlayMusic(11); + else { + PlayMusic(JukeBox::e_informationCenter); + } - FUN_10015820(0, 7); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x100016d0 -MxLong Score::FUN_100016d0(MxType17NotificationParam& p_param) +MxLong Score::FUN_100016d0(LegoControlManagerEvent& p_param) { - MxS16 l = p_param.GetUnknown28(); + MxS16 l = p_param.GetUnknown0x28(); - if (l == 1 || p_param.GetUnknown20() == 4) { - switch (p_param.GetUnknown20()) { + if (l == 1 || p_param.GetClickedObjectId() == 4) { + switch (p_param.GetClickedObjectId()) { case 1: m_unk0xf8 = 2; 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(); @@ -212,23 +217,23 @@ MxLong Score::FUN_100016d0(MxType17NotificationParam& p_param) } // FUNCTION: LEGO1 0x10001980 -void Score::VTable0x68(MxBool p_add) +void Score::Enable(MxBool p_enable) { - LegoWorld::VTable0x68(p_add); + LegoWorld::Enable(p_enable); - if (p_add) { + if (p_enable) { InputManager()->SetWorld(this); SetIsWorldActive(FALSE); } - else if (InputManager()->GetWorld() == this) + else if (InputManager()->GetWorld() == this) { InputManager()->ClearWorld(); + } } // FUNCTION: LEGO1 0x100019d0 void Score::Paint() { - GifManager* gm = GetGifManager(); - GifData* gd = gm->Get("bigcube.gif"); + GifData* gd = GetGifManager()->Get("bigcube.gif"); if (gd) { RaceState* l78 = (RaceState*) GameState()->GetState("JetskiRaceState"); @@ -249,25 +254,30 @@ void Score::Paint() for (MxU8 id = 1; id <= 5; id++) { m_surface = (MxU8*) desc.lpSurface; MxU16 color = 0; - if (l70) + if (l70) { color = l70->GetColor(id); + } MxU32 row = id - 1; FillArea(0, row, color); color = 0; - if (l78) + if (l78) { color = l78->GetColor(id); + } FillArea(1, row, color); color = 0; - if (l74) + if (l74) { color = l74->GetColor(id); + } FillArea(2, row, color); color = 0; - if (lesi) + if (lesi) { color = lesi->GetColor(id); + } FillArea(3, row, color); color = 0; - if (lebp) + if (lebp) { color = lebp->GetColor(id); + } FillArea(4, row, color); } @@ -303,12 +313,12 @@ void Score::FillArea(MxU32 p_x, MxU32 p_y, MxS16 p_color) data[0] = 0x11; data[17] = 0x28; data[18] = 0x28; - data[1] = 0xf; + data[1] = 0x0f; MxU32 size = data[p_x + 14]; MxU8* ptr = data[p_x + 4] + data[p_y + 9] + m_surface; MxS32 count = data[p_y + 19]; - data[2] = 0x8; - data[3] = 0x5; + data[2] = 0x08; + data[3] = 0x05; MxU32 value = data[p_color]; for (; count > 0; count--) { memset(ptr++, value, size); diff --git a/LEGO1/scorestate.cpp b/LEGO1/lego/legoomni/src/infocenter/scorestate.cpp similarity index 100% rename from LEGO1/scorestate.cpp rename to LEGO1/lego/legoomni/src/infocenter/scorestate.cpp diff --git a/LEGO1/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp similarity index 52% rename from LEGO1/legoinputmanager.cpp rename to LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index cdfd4bb3..45801476 100644 --- a/LEGO1/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -2,20 +2,30 @@ #include "legocontrolmanager.h" #include "legoomni.h" +#include "legovideomanager.h" #include "mxautolocker.h" +#include "roi/legoroi.h" -DECOMP_SIZE_ASSERT(LegoInputManager, 0x338); -DECOMP_SIZE_ASSERT(LegoEventQueue, 0x18); +DECOMP_SIZE_ASSERT(LegoInputManager, 0x338) +DECOMP_SIZE_ASSERT(LegoNotifyList, 0x18) +DECOMP_SIZE_ASSERT(LegoNotifyListCursor, 0x10) +DECOMP_SIZE_ASSERT(LegoEventQueue, 0x18) + +// GLOBAL: LEGO1 0x100f31b0 +MxS32 g_unk0x100f31b0 = -1; + +// GLOBAL: LEGO1 0x100f31b4 +const char* g_unk0x100f31b4 = NULL; // FUNCTION: LEGO1 0x1005b790 LegoInputManager::LegoInputManager() { - m_unk0x5c = NULL; + m_keyboardNotifyList = NULL; m_world = NULL; m_camera = NULL; m_eventQueue = NULL; m_unk0x80 = 0; - m_timer = 0; + m_autoDragTimerID = 0; m_unk0x6c = 0; m_unk0x70 = 0; m_controlManager = NULL; @@ -31,10 +41,10 @@ LegoInputManager::LegoInputManager() m_unk0x335 = FALSE; m_unk0x336 = FALSE; m_unk0x74 = 0x19; - m_timeout = 1000; + m_autoDragTime = 1000; } -// STUB: LEGO1 0x1005b8b0 +// FUNCTION: LEGO1 0x1005b8b0 MxResult LegoInputManager::Tickle() { ProcessEvents(); @@ -50,10 +60,27 @@ LegoInputManager::~LegoInputManager() // FUNCTION: LEGO1 0x1005b960 MxResult LegoInputManager::Create(HWND p_hwnd) { - // TODO - if (m_eventQueue == NULL) - m_eventQueue = new LegoEventQueue(); - return SUCCESS; + MxResult result = SUCCESS; + + m_controlManager = new LegoControlManager; + + if (!m_keyboardNotifyList) { + m_keyboardNotifyList = new LegoNotifyList; + } + + if (!m_eventQueue) { + m_eventQueue = new LegoEventQueue; + } + + CreateAndAcquireKeyboard(p_hwnd); + GetJoystickId(); + + if (!m_keyboardNotifyList || !m_eventQueue || !m_directInputDevice) { + Destroy(); + result = FAILURE; + } + + return result; } // FUNCTION: LEGO1 0x1005bfe0 @@ -61,16 +88,19 @@ void LegoInputManager::Destroy() { ReleaseDX(); - if (m_unk0x5c) - delete m_unk0x5c; - m_unk0x5c = NULL; + if (m_keyboardNotifyList) { + delete m_keyboardNotifyList; + } + m_keyboardNotifyList = NULL; - if (m_eventQueue) + if (m_eventQueue) { delete m_eventQueue; + } m_eventQueue = NULL; - if (m_controlManager) + if (m_controlManager) { delete m_controlManager; + } } // FUNCTION: LEGO1 0x1005c030 @@ -158,8 +188,9 @@ MxResult LegoInputManager::GetJoystickState( if ((capabilities & JOYCAPS_HASPOV) != 0) { joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS; - if ((capabilities & JOYCAPS_POVCTS) != 0) + if ((capabilities & JOYCAPS_POVCTS) != 0) { joyinfoex.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNPOV | JOY_RETURNBUTTONS | JOY_RETURNPOVCTS; + } } MMRESULT mmresult = joyGetPosEx(m_joyid, &joyinfoex); @@ -189,16 +220,26 @@ MxResult LegoInputManager::GetJoystickState( return FAILURE; } -// STUB: LEGO1 0x1005c470 -void LegoInputManager::Register(MxCore*) +// FUNCTION: LEGO1 0x1005c470 +void LegoInputManager::Register(MxCore* p_notify) { - // TODO + MxAutoLocker lock(&m_criticalSection); + + LegoNotifyListCursor cursor(m_keyboardNotifyList); + if (!cursor.Find(p_notify)) { + m_keyboardNotifyList->Append(p_notify); + } } -// STUB: LEGO1 0x1005c5c0 -void LegoInputManager::UnRegister(MxCore*) +// FUNCTION: LEGO1 0x1005c5c0 +void LegoInputManager::UnRegister(MxCore* p_notify) { - // TODO + MxAutoLocker lock(&m_criticalSection); + + LegoNotifyListCursor cursor(m_keyboardNotifyList); + if (cursor.Find(p_notify)) { + cursor.Detach(); + } } // FUNCTION: LEGO1 0x1005c700 @@ -243,31 +284,156 @@ void LegoInputManager::ProcessEvents() LegoEventNotificationParam event; while (m_eventQueue->Dequeue(event)) { - if (ProcessOneEvent(event)) + if (ProcessOneEvent(event)) { break; + } } } -// STUB: LEGO1 0x1005c9c0 +// FUNCTION: LEGO1 0x1005c9c0 MxBool LegoInputManager::ProcessOneEvent(LegoEventNotificationParam& p_param) +{ + MxBool processRoi; + + if (p_param.GetType() == c_notificationKeyPress) { + if (!Lego()->IsTimerRunning() || p_param.GetKey() == 0x13) { + if (p_param.GetKey() == 0x10) { + if (m_unk0x195) { + m_unk0x80 = 0; + p_param.SetType(c_notificationDrag); + + if (m_camera) { + m_camera->Notify(p_param); + } + } + + m_unk0x195 = !m_unk0x195; + return TRUE; + } + + LegoNotifyListCursor cursor(m_keyboardNotifyList); + MxCore* target; + + while (cursor.Next(target)) { + if (target->Notify(p_param) != 0) { + return TRUE; + } + } + } + } + else { + if (!Lego()->IsTimerRunning()) { + processRoi = TRUE; + + if (m_unk0x335 != 0) { + if (p_param.GetType() == c_notificationButtonDown) { + LegoEventNotificationParam notification(c_notificationKeyPress, NULL, 0, 0, 0, ' '); + LegoNotifyListCursor cursor(m_keyboardNotifyList); + MxCore* target; + + while (cursor.Next(target)) { + if (target->Notify(notification) != 0) { + return TRUE; + } + } + } + + return TRUE; + } + + if (m_unk0x195 && p_param.GetType() == c_notificationButtonDown) { + m_unk0x195 = 0; + return TRUE; + } + + if (m_world != NULL && m_world->Notify(p_param) != 0) { + return TRUE; + } + + if (p_param.GetType() == c_notificationButtonDown) { + MxPresenter* presenter = VideoManager()->GetPresenterAt(p_param.GetX(), p_param.GetY()); + + if (presenter) { + if (presenter->GetDisplayZ() < 0) { + processRoi = FALSE; + + if (m_controlManager->FUN_10029210(p_param, presenter)) { + return TRUE; + } + } + else { + LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY()); + + if (roi == NULL && m_controlManager->FUN_10029210(p_param, presenter)) { + return TRUE; + } + } + } + } + else if (p_param.GetType() == c_notificationButtonUp) { + if (g_unk0x100f31b0 != -1 || m_controlManager->GetUnknown0x10() || + m_controlManager->GetUnknown0x0c() == 1) { + MxBool result = m_controlManager->FUN_10029210(p_param, NULL); + StopAutoDragTimer(); + + m_unk0x80 = 0; + m_unk0x81 = 0; + return result; + } + } + + if (FUN_1005cdf0(p_param)) { + if (processRoi && p_param.GetType() == c_notificationType11) { + LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY()); + p_param.SetROI(roi); + + if (roi && roi->GetUnk0x0c() == 1) { + for (OrientableROI* oroi = roi->GetUnknown0xd4(); oroi; oroi = oroi->GetUnknown0xd4()) { + roi = (LegoROI*) oroi; + } + + LegoEntity* entity = roi->GetUnknown0x104(); + if (entity && entity->Notify(p_param) != 0) { + return TRUE; + } + } + } + + if (m_camera && m_camera->Notify(p_param) != 0) { + return TRUE; + } + } + } + } + + return FALSE; +} + +// STUB: LEGO1 0x1005cdf0 +MxBool LegoInputManager::FUN_1005cdf0(LegoEventNotificationParam& p_param) { // TODO return FALSE; } // FUNCTION: LEGO1 0x1005cfb0 -void LegoInputManager::SetTimer() +void LegoInputManager::StartAutoDragTimer() { - LegoOmni* omni = LegoOmni::GetInstance(); - UINT timer = ::SetTimer(omni->GetWindowHandle(), 1, m_timeout, NULL); - m_timer = timer; + m_autoDragTimerID = ::SetTimer(LegoOmni::GetInstance()->GetWindowHandle(), 1, m_autoDragTime, NULL); } // FUNCTION: LEGO1 0x1005cfd0 -void LegoInputManager::KillTimer() +void LegoInputManager::StopAutoDragTimer() { - if (m_timer != 0) { - LegoOmni* omni = LegoOmni::GetInstance(); - ::KillTimer(omni->GetWindowHandle(), m_timer); + if (m_autoDragTimerID) { + ::KillTimer(LegoOmni::GetInstance()->GetWindowHandle(), m_autoDragTimerID); } } + +// FUNCTION: LEGO1 0x1005cff0 +void LegoInputManager::EnableInputProcessing() +{ + m_unk0x88 = FALSE; + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = NULL; +} diff --git a/LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp b/LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp new file mode 100644 index 00000000..f243b92a --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp @@ -0,0 +1 @@ +#include "beachhouseentity.h" diff --git a/LEGO1/lego/legoomni/src/isle/bike.cpp b/LEGO1/lego/legoomni/src/isle/bike.cpp new file mode 100644 index 00000000..219208ea --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/bike.cpp @@ -0,0 +1,38 @@ +#include "bike.h" + +DECOMP_SIZE_ASSERT(Bike, 0x164); + +// FUNCTION: LEGO1 0x10076670 +Bike::Bike() +{ + this->m_unk0x13c = 20.0; + this->m_unk0x150 = 3.0; + this->m_unk0x148 = 1; +} + +// STUB: LEGO1 0x100768f0 +MxResult Bike::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10076920 +void Bike::VTable0xe4() +{ + // TODO +} + +// STUB: LEGO1 0x100769a0 +MxU32 Bike::VTable0xcc() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10076aa0 +MxU32 Bike::VTable0xd4(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/isle/bumpbouy.cpp b/LEGO1/lego/legoomni/src/isle/bumpbouy.cpp new file mode 100644 index 00000000..6ae105ff --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/bumpbouy.cpp @@ -0,0 +1,32 @@ +#include "bumpbouy.h" + +// STUB: LEGO1 0x1000fd00 +void BumpBouy::ParseAction(char*) +{ + // TODO +} + +// STUB: LEGO1 0x1000fd10 +void BumpBouy::SetWorldSpeed(MxFloat p_worldSpeed) +{ + // TODO +} + +// STUB: LEGO1 0x1000fd20 +void BumpBouy::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x1000fd30 +void BumpBouy::VTable0x74(Matrix4& p_transform) +{ + // TODO +} + +// STUB: LEGO1 0x100274d0 +MxLong BumpBouy::Notify(MxParam& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/isle/doors.cpp b/LEGO1/lego/legoomni/src/isle/doors.cpp new file mode 100644 index 00000000..aa7e2031 --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/doors.cpp @@ -0,0 +1,20 @@ +#include "doors.h" + +// STUB: LEGO1 0x10066100 +MxS32 Doors::VTable0x94() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10066250 +void Doors::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x100664e0 +void Doors::ParseAction(char*) +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/isle/historybook.cpp b/LEGO1/lego/legoomni/src/isle/historybook.cpp new file mode 100644 index 00000000..4681ce1c --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/historybook.cpp @@ -0,0 +1,41 @@ +#include "historybook.h" + +// STUB: LEGO1 0x100822f0 +HistoryBook::HistoryBook() +{ + // TODO +} + +// STUB: LEGO1 0x100824d0 +HistoryBook::~HistoryBook() +{ + // TODO +} + +// STUB: LEGO1 0x10082610 +MxResult HistoryBook::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10082680 +MxLong HistoryBook::Notify(MxParam& p_param) +{ + // TODO + + return 0; +} + +// STUB: LEGO1 0x100826f0 +void HistoryBook::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x10082a10 +MxBool HistoryBook::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/isle.cpp b/LEGO1/lego/legoomni/src/isle/isle.cpp similarity index 74% rename from LEGO1/isle.cpp rename to LEGO1/lego/legoomni/src/isle/isle.cpp index 2d1d856a..c5c9ae1f 100644 --- a/LEGO1/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; @@ -46,37 +46,37 @@ Isle::~Isle() InputManager()->ClearWorld(); } - if (GetCurrentVehicle() != NULL) { - VTable0x6c(GetCurrentVehicle()); + if (CurrentVehicle() != NULL) { + VTable0x6c(CurrentVehicle()); } NotificationManager()->Unregister(this); } // 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); - GameState()->FUN_1003a720(0); + GameState()->StopArea(); switch (GameState()->GetCurrentAct()) { case 1: - GameState()->FUN_1003a720(0x2e); + GameState()->StopArea(0x2e); break; case 2: - GameState()->FUN_1003a720(0x2e); + GameState()->StopArea(0x2e); break; case -1: m_unk0x13c = 2; } - if (GameState()->GetUnknown424() == 1) { - GameState()->SetUnknown424(0); + if (GameState()->GetCurrentArea() == 1) { + GameState()->SetCurrentArea(0); } LegoGameState* gameState = GameState(); @@ -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,13 +115,13 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case TYPE17: + case c_notificationClick: result = HandleType17Notification(p_param); break; - case TYPE18: + case c_notificationType18: switch (m_act1state->GetUnknown18()) { case 4: - result = GetCurrentVehicle()->Notify(p_param); + result = CurrentVehicle()->Notify(p_param); break; case 8: result = m_towtrack->Notify(p_param); @@ -131,13 +131,13 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case TYPE19: + case c_notificationType19: result = HandleType19Notification(p_param); break; - case TYPE20: - VTable0x68(TRUE); + case c_notificationType20: + Enable(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::ReadyWorld() { - // TODO + LegoWorld::ReadyWorld(); + + if (m_act1state->GetUnknown21()) { + GameState()->SwitchArea(2); + m_act1state->SetUnknown18(0); + m_act1state->SetUnknown21(0); + } + else if (GameState()->GetCurrentAct()) { + FUN_1003ef00(TRUE); + FUN_10032620(); + m_act1state->FUN_10034d00(); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + } } // STUB: LGEO1 0x10031030 @@ -171,7 +183,27 @@ MxLong Isle::HandleType19Notification(MxParam& p_param) } // STUB: LEGO1 0x10031820 -void Isle::VTable0x68(MxBool p_add) +void Isle::Enable(MxBool p_enable) +{ + if (m_set0xd0.empty() == p_enable) { + return; + } + + LegoWorld::Enable(p_enable); + m_radio.Initialize(p_enable); + + if (p_enable) { + // TODO + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } +} + +// STUB: LEGO1 0x10032620 +void Isle::FUN_10032620() { // TODO } @@ -183,9 +215,9 @@ MxLong Isle::HandleTransitionEnd() } // FUNCTION: LEGO1 0x10032f10 -void Isle::VTable0x58(MxCore* p_object) +void Isle::Add(MxCore* p_object) { - LegoWorld::VTable0x58(p_object); + LegoWorld::Add(p_object); if (p_object->IsA("Pizza")) { m_pizza = (Pizza*) p_object; @@ -212,7 +244,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; @@ -228,7 +260,7 @@ void Isle::VTable0x58(MxCore* p_object) // FUNCTION: LEGO1 0x10033050 void Isle::VTable0x6c(IslePathActor* p_actor) { - LegoWorld::EndAction(p_actor); + LegoWorld::Remove(p_actor); if (p_actor->IsA("Helicopter")) { m_helicopter = NULL; diff --git a/LEGO1/lego/legoomni/src/isle/isleactor.cpp b/LEGO1/lego/legoomni/src/isle/isleactor.cpp new file mode 100644 index 00000000..b6ac3556 --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/isleactor.cpp @@ -0,0 +1,18 @@ +#include "isleactor.h" + +// NOTE: This is copied from base class LegoActor. IsleActor may in fact be larger but we don't know yet. +DECOMP_SIZE_ASSERT(IsleActor, 0x78) + +// STUB: LEGO1 0x1002c780 +MxResult IsleActor::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1002c7b0 +MxLong IsleActor::Notify(MxParam& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/islepathactor.cpp b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp similarity index 62% rename from LEGO1/islepathactor.cpp rename to LEGO1/lego/legoomni/src/isle/islepathactor.cpp index 528bbde8..55ef5b71 100644 --- a/LEGO1/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp @@ -12,9 +12,24 @@ 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 0x1001a2c0 +MxLong IslePathActor::Notify(MxParam& p_param) +{ + // TODO + return 0; } // STUB: LEGO1 0x1001a350 diff --git a/LEGO1/lego/legoomni/src/isle/jukebox.cpp b/LEGO1/lego/legoomni/src/isle/jukebox.cpp new file mode 100644 index 00000000..ed937aeb --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/jukebox.cpp @@ -0,0 +1,61 @@ +#include "jukebox.h" + +#include "mxnotificationmanager.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(JukeBox, 0x104) + +// FUNCTION: LEGO1 0x1005d660 +JukeBox::JukeBox() +{ + m_unk0x100 = 0; + m_unk0xfc = 0; + NotificationManager()->Register(this); +} + +// STUB: LEGO1 0x1005d6e0 +MxBool JukeBox::VTable0x5c() +{ + // TODO + return FALSE; +} + +// STUB: LEGO1 0x1005d8d0 +MxResult JukeBox::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1005d980 +MxLong JukeBox::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1005d9f0 +void JukeBox::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x1005dde0 +void JukeBox::Enable(MxBool p_enable) +{ + // TODO +} + +// STUB: LEGO1 0x1005de30 +MxResult JukeBox::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1005de70 +MxBool JukeBox::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/jukeboxentity.cpp b/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp similarity index 63% rename from LEGO1/jukeboxentity.cpp rename to LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp index 73071896..026772c0 100644 --- a/LEGO1/jukeboxentity.cpp +++ b/LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp @@ -11,3 +11,10 @@ JukeBoxEntity::~JukeBoxEntity() { // TODO } + +// STUB: LEGO1 0x10085e40 +MxLong JukeBoxEntity::Notify(MxParam& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/jukeboxstate.cpp b/LEGO1/lego/legoomni/src/isle/jukeboxstate.cpp similarity index 100% rename from LEGO1/jukeboxstate.cpp rename to LEGO1/lego/legoomni/src/isle/jukeboxstate.cpp diff --git a/LEGO1/lego/legoomni/src/isle/motocycle.cpp b/LEGO1/lego/legoomni/src/isle/motocycle.cpp new file mode 100644 index 00000000..0f4424f9 --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/motocycle.cpp @@ -0,0 +1,52 @@ +#include "motocycle.h" + +DECOMP_SIZE_ASSERT(Motocycle, 0x16c); + +// FUNCTION: LEGO1 0x100357b0 +Motocycle::Motocycle() +{ + this->m_unk0x13c = 40.0; + this->m_unk0x150 = 1.75; + this->m_unk0x148 = 1; + this->m_unk0x164 = 1.0; +} + +// STUB: LEGO1 0x10035a40 +MxResult Motocycle::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10035ad0 +void Motocycle::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x10035bc0 +void Motocycle::VTable0xe4() +{ + // TODO +} + +// STUB: LEGO1 0x10035c50 +MxU32 Motocycle::VTable0xcc() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10035d70 +MxU32 Motocycle::VTable0xd4(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10035df0 +MxU32 Motocycle::VTable0xdc(MxType19NotificationParam& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/isle/radio.cpp b/LEGO1/lego/legoomni/src/isle/radio.cpp new file mode 100644 index 00000000..52bda8f2 --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/radio.cpp @@ -0,0 +1,158 @@ +#include "radio.h" + +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoomni.h" +#include "mxbackgroundaudiomanager.h" +#include "mxcontrolpresenter.h" +#include "mxnotificationmanager.h" + +DECOMP_SIZE_ASSERT(Radio, 0x10); + +// FUNCTION: LEGO1 0x1002c850 +Radio::Radio() +{ + NotificationManager()->Register(this); + ControlManager()->Register(this); + + m_unk0x0c = TRUE; + CreateRadioState(); +} + +// FUNCTION: LEGO1 0x1002c990 +Radio::~Radio() +{ + if (m_state->IsActive()) { + BackgroundAudioManager()->Stop(); + m_state->SetActive(FALSE); + } + + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); +} + +// FUNCTION: LEGO1 0x1002ca30 +MxLong Radio::Notify(MxParam& p_param) +{ + MxLong result = 0; + + if (m_unk0x0c) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) p_param); + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x1002ca70 +void Radio::Play() +{ + if (!m_state->IsActive()) { + CurrentWorld(); + + MxDSAction action; + action.SetObjectId(m_state->FUN_1002d090()); + action.SetAtomId(*g_jukeboxScript); + action.SetLoopCount(1); + + m_bgAudioPreviouslyEnabled = BackgroundAudioManager()->GetMusicEnabled(); + if (!m_bgAudioPreviouslyEnabled) { + BackgroundAudioManager()->Enable(TRUE); + } + + BackgroundAudioManager()->PlayMusic(action, 3, 4); + m_state->SetActive(TRUE); + } +} + +// FUNCTION: LEGO1 0x1002cb70 +void Radio::Stop() +{ + if (m_state->IsActive()) { + LegoWorld* world = CurrentWorld(); + + MxControlPresenter* presenter = (MxControlPresenter*) world->Find(world->GetAtom(), 18); + + if (presenter) { + presenter->VTable0x6c(0); + } + + BackgroundAudioManager()->Stop(); + BackgroundAudioManager()->Enable(m_bgAudioPreviouslyEnabled); + m_state->SetActive(FALSE); + } +} + +// FUNCTION: LEGO1 0x1002cbc0 +MxLong Radio::HandleClick(LegoControlManagerEvent& p_param) +{ + MxDSAction action; // Unused + MxS32 objectId = p_param.GetClickedObjectId(); + + if (objectId == 18) { + if (m_state->IsActive()) { + Stop(); + } + else { + Play(); + } + + if (CurrentWorld()) { +#ifdef COMPAT_MODE + MxNotificationParam param(c_notificationEndAction, this); + CurrentWorld()->Notify(param); +#else + CurrentWorld()->Notify(MxNotificationParam(c_notificationType0, this)); +#endif + } + + return 1; + } + + return 0; +} + +// FUNCTION: LEGO1 0x1002ccc0 +MxLong Radio::HandleEndAction(MxEndActionNotificationParam& p_param) +{ + if (m_state->IsActive() && + m_state->FUN_1002d0c0(p_param.GetAction()->GetAtomId(), p_param.GetAction()->GetObjectId())) { + + MxDSAction action; + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(m_state->FUN_1002d090()); + action.SetLoopCount(1); + + BackgroundAudioManager()->PlayMusic(action, 3, 4); + return 1; + } + + return 0; +} + +// FUNCTION: LEGO1 0x1002cdc0 +void Radio::Initialize(MxBool p_und) +{ + if (m_unk0x0c != p_und) { + m_unk0x0c = p_und; + CreateRadioState(); + } +} + +// FUNCTION: LEGO1 0x1002cde0 +void Radio::CreateRadioState() +{ + LegoGameState* gameState = GameState(); + RadioState* state = (RadioState*) gameState->GetState("RadioState"); + if (state == NULL) { + state = (RadioState*) gameState->CreateState("RadioState"); + } + + m_state = state; +} diff --git a/LEGO1/lego/legoomni/src/isle/radiostate.cpp b/LEGO1/lego/legoomni/src/isle/radiostate.cpp new file mode 100644 index 00000000..077864a7 --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/radiostate.cpp @@ -0,0 +1,99 @@ +#include "radiostate.h" + +#include "jukebox.h" +#include "legoomni.h" +#include "mxtimer.h" + +// GLOBAL: LEGO1 0x100f3218 +JukeBox::JukeBoxScript g_unk0x100f3218[6] = { + JukeBox::e_legoRadioReminder1, + JukeBox::e_legoRadioJingle1, + JukeBox::e_legoRadioJingle2, + JukeBox::e_legoRadioJingle3, + JukeBox::e_legoRadioJingle4, + JukeBox::e_legoRadioReminder2 +}; + +// GLOBAL: LEGO1 0x100f3230 +JukeBox::JukeBoxScript g_unk0x100f3230[14] = { + JukeBox::e_legoRadioRacingAd, + JukeBox::e_legoRadioNews1, + JukeBox::e_legoRadioNews2, + JukeBox::e_legoRadioPizzaAd1, + JukeBox::e_legoRadioBricksterPSA, + JukeBox::e_legoRadioSports1, + JukeBox::e_legoRadioIntermission1, + JukeBox::e_legoRadioIntermission2, + JukeBox::e_legoRadioPizzaAd2, + JukeBox::e_legoRadioWeatherReport, + JukeBox::e_legoRadioSports2, + JukeBox::e_legoRadioPizzaAd3, + JukeBox::e_legoRadioIntermission3, + JukeBox::e_legoRadioSuperStoreAd, +}; + +// GLOBAL: LEGO1 0x100f3268 +JukeBox::JukeBoxScript g_unk0x100f3268[9] = { + JukeBox::e_centralRoads, + JukeBox::e_beachBlvd, + JukeBox::e_residentialArea, + JukeBox::e_legoRadioLuckyYou, + JukeBox::e_legoRadioJazzInterlude, + JukeBox::e_legoRadioPianoInterlude1, + JukeBox::e_legoRadioPoliceStation, + JukeBox::e_legoRadioPianoInterlude2, + JukeBox::e_legoRadioCredits, +}; + +// FUNCTION: LEGO1 0x1002ce10 +RadioState::RadioState() +{ + srand(Timer()->GetTime()); + + MxS32 random = rand(); + m_unk0x2c = random % 3; + + m_unk0x08[0] = LegoState::Playlist((MxU32*) g_unk0x100f3218, sizeof(g_unk0x100f3218) / sizeof(g_unk0x100f3218[0])); + m_unk0x08[0].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3218) / sizeof(g_unk0x100f3218[0]))); + + m_unk0x08[1] = LegoState::Playlist((MxU32*) g_unk0x100f3230, sizeof(g_unk0x100f3230) / sizeof(g_unk0x100f3230[0])); + m_unk0x08[1].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3230) / sizeof(g_unk0x100f3230[0]))); + + m_unk0x08[2] = LegoState::Playlist((MxU32*) g_unk0x100f3268, sizeof(g_unk0x100f3268) / sizeof(g_unk0x100f3268[0])); + m_unk0x08[2].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3268) / sizeof(g_unk0x100f3268[0]))); + + m_active = FALSE; +} + +// FUNCTION: LEGO1 0x1002cf50 +MxBool RadioState::VTable0x14() +{ + return FALSE; +} + +// FUNCTION: LEGO1 0x1002d090 +MxU32 RadioState::FUN_1002d090() +{ + if (m_unk0x2c == 2) { + m_unk0x2c = 0; + } + else { + m_unk0x2c++; + } + + return m_unk0x08[m_unk0x2c].Next(); +} + +// FUNCTION: LEGO1 0x1002d0c0 +MxBool RadioState::FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId) +{ + if (*g_jukeboxScript == p_atom) { + for (MxS16 i = 0; i < 3; i++) { + if (m_unk0x08[i].Contains(p_objectId)) { + return TRUE; + } + } + } + + return FALSE; +} diff --git a/LEGO1/lego/legoomni/src/isle/skateboard.cpp b/LEGO1/lego/legoomni/src/isle/skateboard.cpp new file mode 100644 index 00000000..22998f85 --- /dev/null +++ b/LEGO1/lego/legoomni/src/isle/skateboard.cpp @@ -0,0 +1,52 @@ +#include "skateboard.h" + +#include "decomp.h" +#include "mxnotificationmanager.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(SkateBoard, 0x168); + +// FUNCTION: LEGO1 0x1000fd40 +SkateBoard::SkateBoard() +{ + this->m_unk0x160 = 0; + this->m_unk0x13c = 15.0; + this->m_unk0x150 = 3.5; + this->m_unk0x148 = 1; + + NotificationManager()->Register(this); +} + +// STUB: LEGO1 0x10010000 +MxResult SkateBoard::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10010050 +void SkateBoard::VTable0xe4() +{ + // TODO +} + +// STUB: LEGO1 0x100100e0 +MxU32 SkateBoard::VTable0xcc() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10010230 +MxU32 SkateBoard::VTable0xd4(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x100104f0 +MxU32 SkateBoard::VTable0xd0() +{ + // TODO + return 0; +} diff --git a/LEGO1/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp similarity index 69% rename from LEGO1/legoomni.cpp rename to LEGO1/lego/legoomni/src/main/legoomni.cpp index cd3438a7..7384da72 100644 --- a/LEGO1/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -19,11 +19,13 @@ #include "mxdsfile.h" #include "mxomnicreateflags.h" #include "mxomnicreateparam.h" +#include "mxstreamer.h" #include "mxticklemanager.h" #include "mxtransitionmanager.h" -#include "mxunknown100dbdbc.h" +#include "viewmanager/viewmanager.h" DECOMP_SIZE_ASSERT(LegoWorldList, 0x18); +DECOMP_SIZE_ASSERT(LegoWorldListCursor, 0x10); // GLOBAL: LEGO1 0x100f451c MxAtomId* g_copterScript = NULL; @@ -100,7 +102,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 @@ -110,18 +112,16 @@ MxAtomId* g_creditsScript = NULL; MxAtomId* g_nocdSourceName = NULL; // GLOBAL: LEGO1 0x100f6718 +// STRING: LEGO1 0x100f6710 const char* g_current = "current"; -// GLOBAL: LEGO1 0x101020e8 -void (*g_omniUserMessage)(const char*, int); - // GLOBAL: LEGO1 0x100f4c58 MxBool g_isWorldActive = TRUE; // FUNCTION: LEGO1 0x10015700 LegoOmni* Lego() { - return (LegoOmni*) MxOmni::GetInstance(); + return LegoOmni::GetInstance(); } // FUNCTION: LEGO1 0x10015710 @@ -173,15 +173,27 @@ LegoNavController* NavController() } // FUNCTION: LEGO1 0x10015790 -IslePathActor* GetCurrentVehicle() +IslePathActor* CurrentVehicle() { return LegoOmni::GetInstance()->GetCurrentVehicle(); } // FUNCTION: LEGO1 0x100157a0 -LegoWorld* GetCurrentWorld() +LegoWorld* CurrentWorld() { - return LegoOmni::GetInstance()->GetCurrentOmniWorld(); + return LegoOmni::GetInstance()->GetCurrentWorld(); +} + +// FUNCTION: LEGO1 0x100157b0 +LegoUnkSaveDataWriter* UnkSaveDataWriter() +{ + return LegoOmni::GetInstance()->GetUnkSaveDataWriter(); +} + +// FUNCTION: LEGO1 0x100157c0 +ViewManager* GetViewManager() +{ + return VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager(); } // FUNCTION: LEGO1 0x100157e0 @@ -202,16 +214,22 @@ GifManager* GetGifManager() return LegoOmni::GetInstance()->GetGifManager(); } -// STUB: LEGO1 0x10015820 -void FUN_10015820(MxU32, MxU32) +// FUNCTION: LEGO1 0x10015820 +void FUN_10015820(MxBool p_disable, MxU16 p_flags) +{ + LegoOmni::GetInstance()->FUN_1005b4f0(p_disable, p_flags); +} + +// STUB: LEGO1 0x10015860 +void FUN_10015860(const char*, MxU8) { // TODO } // FUNCTION: LEGO1 0x100158c0 -LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid) +LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) { - return LegoOmni::GetInstance()->FindByEntityIdOrAtomId(p_atom, p_entityid); + return LegoOmni::GetInstance()->FindWorld(p_atom, p_entityid); } // FUNCTION: LEGO1 0x100158e0 @@ -220,6 +238,12 @@ MxDSAction& GetCurrentAction() return LegoOmni::GetInstance()->GetCurrentAction(); } +// FUNCTION: LEGO1 0x100158f0 +void SetCurrentWorld(LegoWorld* p_world) +{ + LegoOmni::GetInstance()->SetCurrentWorld(p_world); +} + // FUNCTION: LEGO1 0x10015900 MxTransitionManager* TransitionManager() { @@ -240,11 +264,26 @@ void PlayMusic(MxU32 p_index) // FUNCTION: LEGO1 0x100159c0 void SetIsWorldActive(MxBool p_isWorldActive) { - if (!p_isWorldActive) + if (!p_isWorldActive) { LegoOmni::GetInstance()->GetInputManager()->SetCamera(NULL); + } g_isWorldActive = p_isWorldActive; } +// 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() { @@ -256,7 +295,7 @@ void FUN_1001a700() // FUNCTION: LEGO1 0x1003dd70 LegoROI* PickROI(MxLong p_a, MxLong p_b) { - return VideoManager()->Get3DManager()->GetLego3DView()->PickROI(p_a, p_b); + return (LegoROI*) VideoManager()->Get3DManager()->GetLego3DView()->Pick(p_a, p_b); } // STUB: LEGO1 0x1003ddc0 @@ -269,34 +308,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 @@ -386,11 +425,11 @@ void LegoOmni::Init() MxOmni::Init(); m_unk0x68 = 0; m_inputMgr = NULL; - m_renderMgr = NULL; + m_viewLODListManager = NULL; m_gifManager = NULL; m_worldList = NULL; m_currentWorld = NULL; - m_unk0x80 = FALSE; + m_exit = FALSE; m_currentVehicle = NULL; m_saveDataWriter = NULL; m_plantManager = NULL; @@ -444,9 +483,9 @@ void LegoOmni::Destroy() m_gifManager = NULL; } - if (m_renderMgr) { - delete m_renderMgr; - m_renderMgr = NULL; + if (m_viewLODListManager) { + delete m_viewLODListManager; + m_viewLODListManager = NULL; } if (m_inputMgr) { @@ -492,17 +531,20 @@ MxResult LegoOmni::Create(MxOmniCreateParam& p_param) p_param.CreateFlags().CreateSoundManager(FALSE); p_param.CreateFlags().CreateTickleManager(FALSE); - if (!(m_tickleManager = new MxTickleManager())) + if (!(m_tickleManager = new MxTickleManager())) { return FAILURE; + } - if (MxOmni::Create(p_param) != SUCCESS) + if (MxOmni::Create(p_param) != SUCCESS) { return FAILURE; + } m_objectFactory = new LegoObjectFactory(); - if (m_objectFactory == NULL) + if (m_objectFactory == NULL) { return FAILURE; + } - if (m_soundManager = new LegoSoundManager()) { + if ((m_soundManager = new LegoSoundManager())) { if (m_soundManager->Create(10, 0) != SUCCESS) { delete m_soundManager; m_soundManager = NULL; @@ -510,21 +552,21 @@ MxResult LegoOmni::Create(MxOmniCreateParam& p_param) } } - if (m_videoManager = new LegoVideoManager()) { + if ((m_videoManager = new LegoVideoManager())) { if (m_videoManager->Create(p_param.GetVideoParam(), 100, 0) != SUCCESS) { delete m_videoManager; m_videoManager = NULL; } } - if (m_inputMgr = new LegoInputManager()) { + if ((m_inputMgr = new LegoInputManager())) { if (m_inputMgr->Create(p_param.GetWindowHandle()) != SUCCESS) { delete m_inputMgr; m_inputMgr = NULL; } } - m_renderMgr = new MxUnknown100dbdbc(); + m_viewLODListManager = new ViewLODListManager(); m_gifManager = new GifManager(); // TODO: there is another class here m_plantManager = new LegoPlantManager(); @@ -533,7 +575,8 @@ MxResult LegoOmni::Create(MxOmniCreateParam& p_param) m_gameState = new LegoGameState(); m_worldList = new LegoWorldList(TRUE); - if (m_renderMgr && m_gifManager && m_worldList && m_plantManager && m_animationManager && m_buildingManager) { + if (m_viewLODListManager && m_gifManager && m_worldList && m_plantManager && m_animationManager && + m_buildingManager) { // TODO: initialize a bunch of MxVariables RegisterScripts(); FUN_1001a700(); @@ -568,55 +611,133 @@ LegoOmni* LegoOmni::GetInstance() return (LegoOmni*) MxOmni::GetInstance(); } -// STUB: LEGO1 0x1005af10 -void LegoOmni::RemoveWorld(const MxAtomId&, MxLong) +// FUNCTION: LEGO1 0x1005ad20 +void LegoOmni::AddWorld(LegoWorld* p_world) { - // TODO + m_worldList->Append(p_world); } -// STUB: LEGO1 0x1005b0c0 -LegoEntity* LegoOmni::FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid) +// FUNCTION: LEGO1 0x1005adb0 +void LegoOmni::DeleteWorld(LegoWorld* p_world) { - // TODO + if (m_worldList) { + LegoWorldListCursor cursor(m_worldList); + + if (cursor.Find(p_world)) { + cursor.Detach(); + + if (m_currentWorld == p_world) { + m_currentWorld = NULL; + } + + delete p_world; + } + } +} + +// FUNCTION: LEGO1 0x1005af10 +void LegoOmni::RemoveWorld(const MxAtomId& p_atom, MxLong p_objectId) +{ + if (m_worldList) { + LegoWorldListCursor a(m_worldList); + LegoWorldListCursor b(m_worldList); + LegoWorld* world; + + a.Head(); + while (a.Current(world)) { + b = a; + b.Next(); + + if ((p_objectId == -1 || world->GetEntityId() == p_objectId) && + (!p_atom.GetInternal() || world->GetAtom() == p_atom)) { + a.Detach(); + delete world; + } + + a = b; + } + } +} + +// FUNCTION: LEGO1 0x1005b0c0 +LegoWorld* LegoOmni::FindWorld(const MxAtomId& p_atom, MxS32 p_entityid) +{ + if (m_worldList) { + LegoWorldListCursor cursor(m_worldList); + LegoWorld* world; + + while (cursor.Next(world)) { + if ((p_entityid == -1 || world->GetEntityId() == p_entityid) && + (!p_atom.GetInternal() || world->GetAtom() == p_atom)) { + return world; + } + } + } + return NULL; } -// STUB: LEGO1 0x1005b1d0 +// FUNCTION: LEGO1 0x1005b1d0 void LegoOmni::DeleteObject(MxDSAction& p_dsAction) { - // TODO + if (p_dsAction.GetAtomId().GetInternal() != NULL) { + LegoWorld* world = FindWorld(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()); + if (world) { + DeleteWorld(world); + return; + } + + if (m_currentWorld != NULL) { + MxCore* entity = m_currentWorld->Find(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()); + if (entity) { + m_currentWorld->Remove(entity); + + if (entity->IsA("MxPresenter")) { + Streamer()->FUN_100b98f0(((MxPresenter*) entity)->GetAction()); + ((MxPresenter*) entity)->EndAction(); + } + else { + delete entity; + } + return; + } + } + } + MxOmni::DeleteObject(p_dsAction); } // FUNCTION: LEGO1 0x1005b2f0 -MxEntity* LegoOmni::FindWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) +MxEntity* LegoOmni::AddToWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p_presenter) { - LegoWorld* foundEntity = NULL; + LegoWorld* world = NULL; + if (strcmpi(p_id, g_current)) { - foundEntity = (LegoWorld*) FindByEntityIdOrAtomId(MxAtomId(p_id, LookupMode_LowerCase2), p_entityId); + world = FindWorld(MxAtomId(p_id, e_lowerCase2), p_entityId); } else { - foundEntity = this->m_currentWorld; + world = this->m_currentWorld; } - if (foundEntity != NULL) { - foundEntity->VTable0x58(p_presenter); + if (world != NULL) { + world->Add(p_presenter); } - return foundEntity; + return world; } // FUNCTION: LEGO1 0x1005b3a0 void LegoOmni::NotifyCurrentEntity(MxNotificationParam* p_param) { - if (m_currentWorld) + if (m_currentWorld) { NotificationManager()->Send(m_currentWorld, p_param); + } } // FUNCTION: LEGO1 0x1005b3c0 MxBool LegoOmni::DoesEntityExist(MxDSAction& p_dsAction) { if (MxOmni::DoesEntityExist(p_dsAction)) { - if (FindByEntityIdOrAtomId(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()) == NULL) { + if (FindWorld(p_dsAction.GetAtomId(), p_dsAction.GetObjectId()) == NULL) { return TRUE; } } @@ -626,18 +747,42 @@ MxBool LegoOmni::DoesEntityExist(MxDSAction& p_dsAction) // FUNCTION: LEGO1 0x1005b400 MxS32 LegoOmni::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) { - if (GetCurrentWorld() == NULL) { + if (::CurrentWorld() == NULL) { return -1; } - return GetCurrentWorld()->GetCurrPathInfo(p_path, p_value); + return ::CurrentWorld()->GetCurrPathInfo(p_path, p_value); +} + +// FUNCTION: LEGO1 0x1005b4f0 +void LegoOmni::FUN_1005b4f0(MxBool p_disable, MxU16 p_flags) +{ + if (p_disable) { + if (p_flags & c_disableInput) { + m_inputMgr->DisableInputProcessing(); + } + + if (p_flags & c_disable3d) { + ((LegoVideoManager*) m_videoManager)->SetRender3D(FALSE); + } + + if (p_flags & c_clearScreen) { + m_videoManager->GetDisplaySurface()->ClearScreen(); + } + } + else { + m_inputMgr->EnableInputProcessing(); + ((LegoVideoManager*) m_videoManager)->SetRender3D(TRUE); + ((LegoVideoManager*) m_videoManager)->UpdateView(0, 0, 0, 0); + } } // FUNCTION: LEGO1 0x1005b560 void LegoOmni::CreateBackgroundAudio() { - if (m_bkgAudioManager) + if (m_bkgAudioManager) { m_bkgAudioManager->Create(*g_jukeboxScript, 100); + } } // FUNCTION: LEGO1 0x1005b580 @@ -663,7 +808,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; @@ -682,104 +827,3 @@ void LegoOmni::StopTimer() MxOmni::StopTimer(); SetAppCursor(0); } - -// FUNCTION: LEGO1 0x100acf50 -MxResult Start(MxDSAction* p_dsAction) -{ - return MxOmni::GetInstance()->Start(p_dsAction); -} - -// FUNCTION: LEGO1 0x100b6ff0 -void MakeSourceName(char* p_output, const char* p_input) -{ - const char* cln = strchr(p_input, ':'); - if (cln) { - p_input = cln + 1; - } - - strcpy(p_output, p_input); - - strlwr(p_output); - - char* extLoc = strstr(p_output, ".si"); - if (extLoc) { - *extLoc = 0; - } -} - -// FUNCTION: LEGO1 0x100b7050 -MxBool KeyValueStringParse(char* p_outputValue, const char* p_key, const char* p_source) -{ - MxBool didMatch = FALSE; - - MxS16 len = strlen(p_source); - char* temp = new char[len + 1]; - strcpy(temp, p_source); - - char* token = strtok(temp, ", \t\r\n:"); - while (token) { - len -= (strlen(token) + 1); - - if (strcmpi(token, p_key) == 0) { - if (p_outputValue && len > 0) { - char* cur = &token[strlen(p_key)]; - cur++; - while (*cur != ',') { - if (*cur == ' ' || *cur == '\0' || *cur == '\t' || *cur == '\n' || *cur == '\r') - break; - *p_outputValue++ = *cur++; - } - *p_outputValue = '\0'; - } - - didMatch = TRUE; - break; - } - - token = strtok(NULL, ", \t\r\n:"); - } - - delete[] temp; - return didMatch; -} - -// FUNCTION: LEGO1 0x100b7210 -void SetOmniUserMessage(void (*p_userMsg)(const char*, int)) -{ - g_omniUserMessage = p_userMsg; -} - -// FUNCTION: LEGO1 0x100c0280 -MxDSObject* CreateStreamObject(MxDSFile* p_file, MxS16 p_ofs) -{ - MxU8* buf; - _MMCKINFO tmpChunk; - - if (p_file->Seek(((MxLong*) p_file->GetBuffer())[p_ofs], 0)) { - return NULL; - } - - if (p_file->Read((MxU8*) &tmpChunk.ckid, 8) == 0 && tmpChunk.ckid == FOURCC('M', 'x', 'S', 't')) { - if (p_file->Read((MxU8*) &tmpChunk.ckid, 8) == 0 && tmpChunk.ckid == FOURCC('M', 'x', 'O', 'b')) { - - buf = new MxU8[tmpChunk.cksize]; - if (!buf) { - return NULL; - } - - if (p_file->Read(buf, tmpChunk.cksize) != 0) { - return NULL; - } - - // Save a copy so we can clean up properly, because - // this function will alter the pointer value. - MxU8* copy = buf; - MxDSObject* obj = DeserializeDSObjectDispatch(&buf, -1); - delete[] copy; - return obj; - } - return NULL; - } - - return NULL; -} diff --git a/LEGO1/legoeventnotificationparam.cpp b/LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp similarity index 100% rename from LEGO1/legoeventnotificationparam.cpp rename to LEGO1/lego/legoomni/src/notify/legoeventnotificationparam.cpp diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp new file mode 100644 index 00000000..f2b4d0bb --- /dev/null +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -0,0 +1,32 @@ +#include "legopathcontroller.h" + +// STUB: LEGO1 0x10044f40 +LegoPathController::LegoPathController() +{ + // TODO +} + +// STUB: LEGO1 0x10045880 +void LegoPathController::VTable0x14() +{ + // TODO +} + +// STUB: LEGO1 0x10045b20 +void LegoPathController::Destroy() +{ + // TODO +} + +// STUB: LEGO1 0x10045c10 +MxResult LegoPathController::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10046be0 +void LegoPathController::Enable(MxBool p_enable) +{ + // TODO +} diff --git a/LEGO1/legopathpresenter.cpp b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp similarity index 56% rename from LEGO1/legopathpresenter.cpp rename to LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp index b8ab8faf..f0ff859f 100644 --- a/LEGO1/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; } @@ -33,16 +39,18 @@ MxResult LegoPathPresenter::AddToManager() // FUNCTION: LEGO1 0x10044b70 void LegoPathPresenter::Destroy(MxBool p_fromDestructor) { - if (VideoManager()) - VideoManager()->RemovePresenter(*this); + if (VideoManager()) { + VideoManager()->UnregisterPresenter(*this); + } { MxAutoLocker lock(&this->m_criticalSection); Init(); } - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x10044c10 @@ -51,11 +59,33 @@ 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() { - if (this->m_action->GetDuration() == -1) + if (this->m_action->GetDuration() == -1) { return; + } EndAction(); } diff --git a/LEGO1/pizza.cpp b/LEGO1/lego/legoomni/src/pizzeria/pizza.cpp similarity index 80% rename from LEGO1/pizza.cpp rename to LEGO1/lego/legoomni/src/pizzeria/pizza.cpp index 3b0201f6..8b7efe78 100644 --- a/LEGO1/pizza.cpp +++ b/LEGO1/lego/legoomni/src/pizzeria/pizza.cpp @@ -20,6 +20,13 @@ Pizza::~Pizza() TickleManager()->UnregisterClient(this); } +// STUB: LEGO1 0x10038170 +MxResult Pizza::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + // STUB: LEGO1 0x100388a0 MxResult Pizza::Tickle() { diff --git a/LEGO1/pizzamissionstate.cpp b/LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp similarity index 57% rename from LEGO1/pizzamissionstate.cpp rename to LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp index a7aa59b4..c1804a4f 100644 --- a/LEGO1/pizzamissionstate.cpp +++ b/LEGO1/lego/legoomni/src/pizzeria/pizzamissionstate.cpp @@ -3,11 +3,20 @@ DECOMP_SIZE_ASSERT(PizzaMissionStateEntry, 0x20) DECOMP_SIZE_ASSERT(PizzaMissionState, 0xb0) +// STUB: LEGO1 0x100393c0 +MxResult PizzaMissionState::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return SUCCESS; +} + // FUNCTION: LEGO1 0x10039510 PizzaMissionStateEntry* PizzaMissionState::GetState(MxU8 p_id) { - for (MxS16 i = 0; i < 5; i++) - if (m_state[i].m_id == p_id) + for (MxS16 i = 0; i < 5; i++) { + if (m_state[i].m_id == p_id) { return m_state + i; + } + } return NULL; } diff --git a/LEGO1/lego/legoomni/src/pizzeria/pizzeria.cpp b/LEGO1/lego/legoomni/src/pizzeria/pizzeria.cpp new file mode 100644 index 00000000..84404f01 --- /dev/null +++ b/LEGO1/lego/legoomni/src/pizzeria/pizzeria.cpp @@ -0,0 +1,8 @@ +#include "pizzeria.h" + +// STUB: LEGO1 0x100179c0 +MxResult Pizzeria::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} diff --git a/LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp b/LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp new file mode 100644 index 00000000..6694e4d8 --- /dev/null +++ b/LEGO1/lego/legoomni/src/pizzeria/pizzeriastate.cpp @@ -0,0 +1,14 @@ +#include "pizzeriastate.h" + +// STUB: LEGO1 0x10017af0 +PizzeriaState::PizzeriaState() +{ + // TODO +} + +// STUB: LEGO1 0x10017da0 +MxResult PizzeriaState::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return SUCCESS; +} diff --git a/LEGO1/lego/legoomni/src/police/police.cpp b/LEGO1/lego/legoomni/src/police/police.cpp new file mode 100644 index 00000000..c14c482b --- /dev/null +++ b/LEGO1/lego/legoomni/src/police/police.cpp @@ -0,0 +1,90 @@ +#include "police.h" + +#include "jukebox.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "mxnotificationmanager.h" + +DECOMP_SIZE_ASSERT(Police, 0x110) + +// FUNCTION: LEGO1 0x1005e130 +Police::Police() +{ + m_policeState = NULL; + m_unk0x10c = 0; + NotificationManager()->Register(this); +} + +// STUB: LEGO1 0x1005e1d0 +MxBool Police::VTable0x5c() +{ + // TODO + return FALSE; +} + +// FUNCTION: LEGO1 0x1005e320 +Police::~Police() +{ + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + ControlManager()->Unregister(this); + InputManager()->UnRegister(this); + NotificationManager()->Unregister(this); +} + +// FUNCTION: LEGO1 0x1005e3e0 +MxResult Police::Create(MxDSAction& p_dsAction) +{ + MxResult ret = LegoWorld::Create(p_dsAction); + if (ret == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + SetIsWorldActive(FALSE); + InputManager()->Register(this); + + LegoGameState* gameState = GameState(); + PoliceState* policeState = (PoliceState*) gameState->GetState("PoliceState"); + if (!policeState) { + policeState = (PoliceState*) gameState->CreateState("PoliceState"); + } + + m_policeState = policeState; + GameState()->SetCurrentArea(0x22); + GameState()->StopArea(); + return ret; +} + +// STUB: LEGO1 0x1005e480 +MxLong Police::Notify(MxParam& p_param) +{ + // TODO + + return 0; +} + +// FUNCTION: LEGO1 0x1005e530 +void Police::ReadyWorld() +{ + LegoWorld::ReadyWorld(); + PlayMusic(JukeBox::e_policeStation); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); +} + +// STUB: LEGO1 0x1005e740 +void Police::Enable(MxBool p_enable) +{ + // TODO +} + +// STUB: LEGO1 0x1005e790 +MxBool Police::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/policeentity.cpp b/LEGO1/lego/legoomni/src/police/policeentity.cpp similarity index 100% rename from LEGO1/policeentity.cpp rename to LEGO1/lego/legoomni/src/police/policeentity.cpp diff --git a/LEGO1/lego/legoomni/src/police/policestate.cpp b/LEGO1/lego/legoomni/src/police/policestate.cpp new file mode 100644 index 00000000..87ce9ff8 --- /dev/null +++ b/LEGO1/lego/legoomni/src/police/policestate.cpp @@ -0,0 +1,30 @@ +#include "policestate.h" + +#include + +DECOMP_SIZE_ASSERT(PoliceState, 0x10) + +// FUNCTION: LEGO1 0x1005e7c0 +PoliceState::PoliceState() +{ + m_unk0x0c = 0; + m_unk0x08 = (rand() % 2 == 0) ? 501 : 500; +} + +// FUNCTION: LEGO1 0x1005e990 +MxResult PoliceState::VTable0x1c(LegoFile* p_legoFile) +{ + if (p_legoFile->IsWriteMode()) { + p_legoFile->FUN_10006030(ClassName()); + } + + if (p_legoFile->IsReadMode()) { + p_legoFile->Read(&m_unk0x08, sizeof(m_unk0x08)); + } + else { + undefined4 unk0x08 = m_unk0x08; + p_legoFile->Write(&unk0x08, sizeof(m_unk0x08)); + } + + return SUCCESS; +} diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp new file mode 100644 index 00000000..6230ed78 --- /dev/null +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -0,0 +1,58 @@ +#include "carrace.h" + +DECOMP_SIZE_ASSERT(CarRace, 0x154); + +// FUNCTION: LEGO1 0x10016a90 +CarRace::CarRace() +{ + this->m_unk0x150 = 0; + this->m_unk0x130 = MxRect32(0x16c, 0x154, 0x1ec, 0x15e); +} + +// STUB: LEGO1 0x10016ce0 +MxResult CarRace::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10016dd0 +void CarRace::ReadyWorld() +{ + // TODO +} + +// STUB: LEGO1 0x10016f60 +undefined4 CarRace::VTable0x74(undefined4) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x100170e0 +undefined4 CarRace::VTable0x70(undefined4) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10017650 +undefined4 CarRace::VTable0x6c(undefined4) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x100177e0 +undefined4 CarRace::VTable0x78(undefined4) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x10017900 +MxBool CarRace::VTable0x64() +{ + // TODO + return FALSE; +} diff --git a/LEGO1/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp similarity index 100% rename from LEGO1/jetskirace.cpp rename to LEGO1/lego/legoomni/src/race/jetskirace.cpp diff --git a/LEGO1/racestandsentity.cpp b/LEGO1/lego/legoomni/src/race/racestandsentity.cpp similarity index 100% rename from LEGO1/racestandsentity.cpp rename to LEGO1/lego/legoomni/src/race/racestandsentity.cpp diff --git a/LEGO1/racestate.cpp b/LEGO1/lego/legoomni/src/race/racestate.cpp similarity index 69% rename from LEGO1/racestate.cpp rename to LEGO1/lego/legoomni/src/race/racestate.cpp index 4776f97c..39e6c51c 100644 --- a/LEGO1/racestate.cpp +++ b/LEGO1/lego/legoomni/src/race/racestate.cpp @@ -11,13 +11,22 @@ RaceState::RaceState() // TODO } +// STUB: LEGO1 0x10016140 +MxResult RaceState::VTable0x1c(LegoFile* p_legoFile) +{ + // TODO + return SUCCESS; +} + // FUNCTION: LEGO1 0x10016280 RaceStateEntry* RaceState::GetState(MxU8 p_id) { for (MxS16 i = 0;; i++) { - if (i >= 5) + if (i >= 5) { return NULL; - if (m_state[i].m_id == p_id) + } + if (m_state[i].m_id == p_id) { return m_state + i; + } } } diff --git a/LEGO1/lego/legoomni/src/towtrack/towtrack.cpp b/LEGO1/lego/legoomni/src/towtrack/towtrack.cpp new file mode 100644 index 00000000..ebfd3ee7 --- /dev/null +++ b/LEGO1/lego/legoomni/src/towtrack/towtrack.cpp @@ -0,0 +1,71 @@ +#include "towtrack.h" + +DECOMP_SIZE_ASSERT(TowTrack, 0x180); + +// FUNCTION: LEGO1 0x1004c720 +TowTrack::TowTrack() +{ + this->m_unk0x168 = 0; + this->m_unk0x16a = -1; + this->m_unk0x164 = 0; + this->m_unk0x16c = 0; + this->m_unk0x170 = -1; + this->m_unk0x16e = 0; + this->m_unk0x174 = -1; + this->m_unk0x13c = 40.0; + this->m_unk0x178 = 1.0; +} + +// STUB: LEGO1 0x1004c9e0 +MxResult TowTrack::Create(MxDSAction& p_dsAction) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1004cb10 +void TowTrack::VTable0x70(float p_float) +{ + // TODO +} + +// STUB: LEGO1 0x1004cc80 +MxLong TowTrack::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1004cd30 +MxU32 TowTrack::VTable0xd8(MxType18NotificationParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1004d330 +MxU32 TowTrack::VTable0xdc(MxType19NotificationParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1004d690 +MxU32 TowTrack::VTable0xcc() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1004d8f0 +void TowTrack::VTable0xe4() +{ + // TODO +} + +// STUB: LEGO1 0x1004d9e0 +MxU32 TowTrack::VTable0xd4(LegoControlManagerEvent& p_param) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp b/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp new file mode 100644 index 00000000..9a85e0b6 --- /dev/null +++ b/LEGO1/lego/legoomni/src/towtrack/towtrackmissionstate.cpp @@ -0,0 +1,75 @@ +#include "towtrackmissionstate.h" + +DECOMP_SIZE_ASSERT(TowTrackMissionState, 0x28) + +// FUNCTION: LEGO1 0x1004dd30 +TowTrackMissionState::TowTrackMissionState() +{ + m_unk0x12 = 0; + m_unk0x14 = 0; + m_unk0x16 = 0; + m_unk0x08 = 0; + m_unk0x18 = 0; + m_unk0x0c = 0; + m_unk0x1a = 0; + m_unk0x10 = 0; + m_unk0x1c = 0; + m_color1 = 0; + m_color2 = 0; + m_color3 = 0; + m_color4 = 0; +} + +// FUNCTION: LEGO1 0x1004dde0 +MxResult TowTrackMissionState::VTable0x1c(LegoFile* p_legoFile) +{ + if (p_legoFile->IsWriteMode()) { + p_legoFile->FUN_10006030(this->ClassName()); + } + + if (p_legoFile->IsReadMode()) { + p_legoFile->Read(&m_unk0x12, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x14, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x16, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x18, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x1a, sizeof(MxU16)); + p_legoFile->Read(&m_unk0x1c, sizeof(MxU16)); + p_legoFile->Read(&m_color1, sizeof(MxU16)); + p_legoFile->Read(&m_color2, sizeof(MxU16)); + p_legoFile->Read(&m_color3, sizeof(MxU16)); + p_legoFile->Read(&m_color4, sizeof(MxU16)); + } + else if (p_legoFile->IsWriteMode()) { + MxU16 write = m_unk0x12; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_unk0x14; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_unk0x16; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_unk0x18; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_unk0x1a; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_unk0x1c; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_color1; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_color2; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_color3; + p_legoFile->Write(&write, sizeof(MxU16)); + + write = m_color4; + p_legoFile->Write(&write, sizeof(MxU16)); + } + + return SUCCESS; +} diff --git a/LEGO1/lego/legoomni/src/unknown/legounknown100d7c88.cpp b/LEGO1/lego/legoomni/src/unknown/legounknown100d7c88.cpp new file mode 100644 index 00000000..b3f386e3 --- /dev/null +++ b/LEGO1/lego/legoomni/src/unknown/legounknown100d7c88.cpp @@ -0,0 +1,12 @@ +#include "legounknown100d7c88.h" + +// FUNCTION: LEGO1 0x10044e50 +LegoUnknown100d7c88::~LegoUnknown100d7c88() +{ +} + +// FUNCTION: LEGO1 0x10044eb0 +MxU32 LegoUnknown100d7c88::VTable0x00() +{ + return m_unk0x14; +} diff --git a/LEGO1/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp similarity index 67% rename from LEGO1/legoanimationmanager.cpp rename to LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp index 444eeccf..0b10ed24 100644 --- a/LEGO1/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp @@ -21,6 +21,24 @@ LegoAnimationManager::~LegoAnimationManager() // TODO } +// STUB: LEGO1 0x1005ee80 +void LegoAnimationManager::FUN_1005ee80(MxBool) +{ + // TODO +} + +// STUB: LEGO1 0x1005ef10 +void LegoAnimationManager::FUN_1005ef10() +{ + // TODO +} + +// STUB: LEGO1 0x1005f0b0 +void LegoAnimationManager::FUN_1005f0b0() +{ + // TODO +} + // STUB: LEGO1 0x1005f130 void LegoAnimationManager::Init() { @@ -33,6 +51,18 @@ void LegoAnimationManager::FUN_1005f6d0(MxBool) // TODO } +// STUB: LEGO1 0x1005f720 +void LegoAnimationManager::FUN_1005f720(undefined4) +{ + // TODO +} + +// STUB: LEGO1 0x10061010 +void LegoAnimationManager::FUN_10061010(undefined4) +{ + // TODO +} + // STUB: LEGO1 0x100619f0 MxLong LegoAnimationManager::Notify(MxParam& p_param) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp new file mode 100644 index 00000000..6b5a6040 --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legoanimmmpresenter.cpp @@ -0,0 +1,69 @@ +#include "legoanimmmpresenter.h" + +// STUB: LEGO1 0x1004a8d0 +LegoAnimMMPresenter::LegoAnimMMPresenter() +{ + // TODO +} + +// STUB: LEGO1 0x1004aaf0 +MxResult LegoAnimMMPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1004aec0 +void LegoAnimMMPresenter::EndAction() +{ + // TODO +} + +// STUB: LEGO1 0x1004b140 +void LegoAnimMMPresenter::ReadyTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1004b1c0 +void LegoAnimMMPresenter::StartingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1004b220 +void LegoAnimMMPresenter::StreamingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1004b250 +void LegoAnimMMPresenter::RepeatingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1004b2c0 +void LegoAnimMMPresenter::DoneTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1004b2d0 +MxLong LegoAnimMMPresenter::Notify(MxParam& p_param) +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1004b360 +void LegoAnimMMPresenter::VTable0x60(MxPresenter* p_presenter) +{ + // TODO +} + +// STUB: LEGO1 0x1004b390 +void LegoAnimMMPresenter::ParseExtra() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp new file mode 100644 index 00000000..68c664de --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -0,0 +1,235 @@ +#include "legoanimpresenter.h" + +#include "legoomni.h" +#include "legoworld.h" +#include "mxcompositepresenter.h" +#include "mxdsanim.h" +#include "mxstreamchunk.h" +#include "mxvideomanager.h" + +DECOMP_SIZE_ASSERT(LegoAnimPresenter, 0xc0) +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; + LegoMemory 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 +} + +// FUNCTION: LEGO1 0x1006b550 +void LegoAnimPresenter::ReadyTickle() +{ + m_currentWorld = CurrentWorld(); + + 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) { + ProgressTickleState(e_done); + if (m_compositePresenter) { + if (m_compositePresenter->IsA("LegoAnimMMPresenter")) { + m_compositePresenter->VTable0x60(this); + } + } + } + else { + if (m_action->GetElapsedTime() > m_unk0x64->GetUnknown0x8() + m_action->GetStartTime()) { + m_unk0x95 = 1; + } + } +} + +// STUB: LEGO1 0x1006b8c0 +void LegoAnimPresenter::DoneTickle() +{ + // TODO +} + +// FUNCTION: LEGO1 0x1006b8d0 +MxResult LegoAnimPresenter::AddToManager() +{ + return MxVideoPresenter::AddToManager(); +} + +// FUNCTION: LEGO1 0x1006b8e0 +void LegoAnimPresenter::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x1006b8f0 +const char* LegoAnimPresenter::GetActionObjectName() +{ + return m_action->GetObjectName(); +} + +// 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 0x100a0b30 +LegoAnimClass::LegoAnimClass() +{ + m_unk0x08 = 0; + m_unk0x0c = 0; + m_unk0x10 = 0; + m_unk0x14 = 0; +} + +// STUB: LEGO1 0x100a0bc0 +LegoAnimClass::~LegoAnimClass() +{ + // TODO +} + +// STUB: LEGO1 0x100a0c70 +MxResult LegoAnimClass::VTable0x10(LegoMemory* p_stream, MxS32) +{ + return SUCCESS; +} + +// STUB: LEGO1 0x100a0e30 +LegoResult LegoAnimClass::Write(LegoStorage* p_storage) +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x100a1040 +LegoTreeNodeData* LegoAnimClass::CreateData() +{ + // TODO + return NULL; +} diff --git a/LEGO1/lego/legoomni/src/video/legocarbuildanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legocarbuildanimpresenter.cpp new file mode 100644 index 00000000..24bb175b --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legocarbuildanimpresenter.cpp @@ -0,0 +1,43 @@ +#include "legocarbuildanimpresenter.h" + +// STUB: LEGO1 0x10078400 +LegoCarBuildAnimPresenter::LegoCarBuildAnimPresenter() +{ + // TODO +} + +// STUB: LEGO1 0x10078500 +void LegoCarBuildAnimPresenter::RepeatingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x10078680 +LegoCarBuildAnimPresenter::~LegoCarBuildAnimPresenter() +{ + // TODO +} + +// STUB: LEGO1 0x10078790 +void LegoCarBuildAnimPresenter::PutFrame() +{ + // TODO +} + +// STUB: LEGO1 0x100788c0 +void LegoCarBuildAnimPresenter::ReadyTickle() +{ + // TODO +} + +// STUB: LEGO1 0x100789e0 +void LegoCarBuildAnimPresenter::StreamingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x10078db0 +void LegoCarBuildAnimPresenter::EndAction() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legoflctexturepresenter.cpp b/LEGO1/lego/legoomni/src/video/legoflctexturepresenter.cpp new file mode 100644 index 00000000..8d77a1eb --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legoflctexturepresenter.cpp @@ -0,0 +1,34 @@ +#include "legoflctexturepresenter.h" + +DECOMP_SIZE_ASSERT(LegoFlcTexturePresenter, 0x70) + +// FUNCTION: LEGO1 0x1005de80 +LegoFlcTexturePresenter::LegoFlcTexturePresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x1005df70 +void LegoFlcTexturePresenter::Init() +{ + this->m_unk0x68 = 0; + this->m_unk0x6c = 0; +} + +// STUB: LEGO1 0x1005df80 +void LegoFlcTexturePresenter::StartingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1005e0c0 +void LegoFlcTexturePresenter::LoadFrame(MxStreamChunk* p_chunk) +{ + // TODO +} + +// STUB: LEGO1 0x1005e100 +void LegoFlcTexturePresenter::PutFrame() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp new file mode 100644 index 00000000..81a854f8 --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp @@ -0,0 +1,76 @@ +#include "legohideanimpresenter.h" + +DECOMP_SIZE_ASSERT(LegoHideAnimPresenter, 0xc4) + +// FUNCTION: LEGO1 0x1006d7e0 +LegoHideAnimPresenter::LegoHideAnimPresenter() +{ + Init(); +} + +// 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(); + } +} + +// STUB: LEGO1 0x1006dab0 +MxResult LegoHideAnimPresenter::AddToManager() +{ + // TODO + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1006dac0 +void LegoHideAnimPresenter::Destroy() +{ + Destroy(FALSE); +} + +// STUB: LEGO1 0x1006dad0 +void LegoHideAnimPresenter::PutFrame() +{ + // TODO +} + +// STUB: LEGO1 0x1006dae0 +void LegoHideAnimPresenter::ReadyTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1006db20 +void LegoHideAnimPresenter::StartingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1006e9e0 +void LegoHideAnimPresenter::EndAction() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp new file mode 100644 index 00000000..45098aac --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legolocomotionanimpresenter.cpp @@ -0,0 +1,115 @@ +#include "legolocomotionanimpresenter.h" + +#include "legoomni.h" +#include "legoworld.h" + +DECOMP_SIZE_ASSERT(LegoLocomotionAnimPresenter, 0xd8) + +// FUNCTION: LEGO1 0x1006cdd0 +LegoLocomotionAnimPresenter::LegoLocomotionAnimPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x1006d050 +LegoLocomotionAnimPresenter::~LegoLocomotionAnimPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x1006d0b0 +void LegoLocomotionAnimPresenter::Init() +{ + m_unk0xc0 = 0; + m_unk0xc4 = 0; + m_unk0xcc = -1; + m_unk0xd0 = -1; + m_unk0xc8 = 0; + m_unk0xd4 = 0; +} + +// FUNCTION: LEGO1 0x1006d0e0 +void LegoLocomotionAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + m_criticalSection.Enter(); + + if (m_unk0xc4) { + delete[] m_unk0xc4; + } + + if (m_unk0xc8) { + delete m_unk0xc8; + } + + m_unk0x68 = 0; + Init(); + + m_criticalSection.Leave(); + + if (!p_fromDestructor) { + LegoAnimPresenter::Destroy(); + } +} + +// FUNCTION: LEGO1 0x1006d140 +MxResult LegoLocomotionAnimPresenter::VTable0x88(MxStreamChunk* p_chunk) +{ + MxResult result = LegoAnimPresenter::VTable0x88(p_chunk); + return result == SUCCESS ? SUCCESS : result; +} + +// STUB: LEGO1 0x1006d160 +MxResult LegoLocomotionAnimPresenter::AddToManager() +{ + return MxVideoPresenter::AddToManager(); +} + +// FUNCTION: LEGO1 0x1006d5b0 +void LegoLocomotionAnimPresenter::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x1006d5c0 +void LegoLocomotionAnimPresenter::PutFrame() +{ + // Empty +} + +// FUNCTION: LEGO1 0x1006d5d0 +void LegoLocomotionAnimPresenter::ReadyTickle() +{ + LegoAnimPresenter::ReadyTickle(); + + if (m_currentWorld != NULL && m_currentTickleState == e_starting) { + m_currentWorld->Add(this); + if (m_compositePresenter != NULL) { + SendToCompositePresenter(Lego()); + } + + m_unk0xd4++; + } +} + +// STUB: LEGO1 0x1006d610 +void LegoLocomotionAnimPresenter::StartingTickle() +{ + // TODO + EndAction(); +} + +// FUNCTION: LEGO1 0x1006d660 +void LegoLocomotionAnimPresenter::StreamingTickle() +{ + if (m_unk0xd4 == 0) { + EndAction(); + } +} + +// FUNCTION: LEGO1 0x1006d670 +void LegoLocomotionAnimPresenter::EndAction() +{ + if (m_action) { + MxVideoPresenter::EndAction(); + } +} diff --git a/LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp new file mode 100644 index 00000000..8cfb3499 --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legoloopinganimpresenter.cpp @@ -0,0 +1,13 @@ +#include "legoloopinganimpresenter.h" + +// STUB: LEGO1 0x1006caa0 +void LegoLoopingAnimPresenter::StreamingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1006cb40 +void LegoLoopingAnimPresenter::PutFrame() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp new file mode 100644 index 00000000..4ea26beb --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp @@ -0,0 +1,126 @@ +#include "legometerpresenter.h" + +#include "decomp.h" +#include "mxbitmap.h" +#include "mxutil.h" + +DECOMP_SIZE_ASSERT(LegoMeterPresenter, 0x94) + +// GLOBAL: LEGO1 0x1010207c +// STRING: LEGO1 0x10101fb4 +const char* g_filterIndex = "FILLER_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; + SetBit1(FALSE); +} + +// 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 new file mode 100644 index 00000000..4f835212 --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -0,0 +1,41 @@ +#include "legomodelpresenter.h" + +// GLOBAL: LEGO1 0x100f7ae0 +int g_modelPresenterConfig = 1; + +// FUNCTION: LEGO1 0x1000cca0 +void LegoModelPresenter::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x1007f660 +void LegoModelPresenter::configureLegoModelPresenter(MxS32 p_modelPresenterConfig) +{ + g_modelPresenterConfig = p_modelPresenterConfig; +} + +// FUNCTION: LEGO1 0x1007f670 +void LegoModelPresenter::Destroy(MxBool p_fromDestructor) +{ + 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 +void LegoModelPresenter::ParseExtra() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp new file mode 100644 index 00000000..7fff790f --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp @@ -0,0 +1,92 @@ +#include "legopalettepresenter.h" + +#include "lego/sources/misc/legostorage.h" +#include "legoomni.h" +#include "legovideomanager.h" +#include "mxstreamchunk.h" + +DECOMP_SIZE_ASSERT(LegoPalettePresenter, 0x68) + +// FUNCTION: LEGO1 0x10079e50 +LegoPalettePresenter::LegoPalettePresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x1007a070 +LegoPalettePresenter::~LegoPalettePresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x1007a0d0 +void LegoPalettePresenter::Init() +{ + m_palette = NULL; +} + +// FUNCTION: LEGO1 0x1007a0e0 +void LegoPalettePresenter::Destroy(MxBool p_fromDestructor) +{ + m_criticalSection.Enter(); + if (m_palette) { + delete m_palette; + } + Init(); + m_criticalSection.Leave(); + if (!p_fromDestructor) { + MxVideoPresenter::Destroy(FALSE); + } +} + +// FUNCTION: LEGO1 0x1007a120 +void LegoPalettePresenter::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x1007a130 +MxResult LegoPalettePresenter::ParsePalette(MxStreamChunk* p_chunk) +{ + MxU8 buffer[40]; + RGBQUAD palette[256]; + MxResult result = FAILURE; + + LegoMemory stream((char*) p_chunk->GetData()); + if (stream.Read(buffer, sizeof(buffer)) == SUCCESS) { + if (stream.Read(palette, sizeof(palette)) == SUCCESS) { + m_palette = new MxPalette(palette); + if (m_palette) { + result = SUCCESS; + } + } + } + + if (result != SUCCESS && m_palette) { + delete m_palette; + m_palette = NULL; + } + + return result; +} + +// FUNCTION: LEGO1 0x1007a230 +void LegoPalettePresenter::ReadyTickle() +{ + MxStreamChunk* chunk = m_subscriber->CurrentChunk(); + if (chunk) { + if (chunk->GetTime() <= m_action->GetElapsedTime()) { + ParseExtra(); + ProgressTickleState(e_starting); + + chunk = m_subscriber->NextChunk(); + MxResult result = ParsePalette(chunk); + m_subscriber->DestroyChunk(chunk); + + if (result == SUCCESS) { + VideoManager()->RealizePalette(m_palette); + } + EndAction(); + } + } +} diff --git a/LEGO1/legopartpresenter.cpp b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp similarity index 61% rename from LEGO1/legopartpresenter.cpp rename to LEGO1/lego/legoomni/src/video/legopartpresenter.cpp index 1ae834f9..545d2f65 100644 --- a/LEGO1/legopartpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopartpresenter.cpp @@ -6,9 +6,28 @@ int g_partPresenterConfig1 = 1; // GLOBAL: LEGO1 0x100f7aa4 int g_partPresenterConfig2 = 100; +// STUB: LEGO1 0x1000cf60 +void LegoPartPresenter::Destroy() +{ + // TODO +} + // FUNCTION: LEGO1 0x1007c990 void LegoPartPresenter::configureLegoPartPresenter(MxS32 p_partPresenterConfig1, MxS32 p_partPresenterConfig2) { g_partPresenterConfig1 = p_partPresenterConfig1; g_partPresenterConfig2 = p_partPresenterConfig2; } + +// STUB: LEGO1 0x1007c9b0 +MxResult LegoPartPresenter::AddToManager() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x1007deb0 +void LegoPartPresenter::ReadyTickle() +{ + // TODO +} diff --git a/LEGO1/legophonemepresenter.cpp b/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp similarity index 53% rename from LEGO1/legophonemepresenter.cpp rename to LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp index 31948367..4d128531 100644 --- a/LEGO1/legophonemepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legophonemepresenter.cpp @@ -21,3 +21,27 @@ void LegoPhonemePresenter::Init() m_unk0x70 = 0; m_unk0x84 = 0; } + +// STUB: LEGO1 0x1004e3d0 +void LegoPhonemePresenter::StartingTickle() +{ + // TODO +} + +// STUB: LEGO1 0x1004e800 +void LegoPhonemePresenter::LoadFrame(MxStreamChunk* p_chunk) +{ + // TODO +} + +// STUB: LEGO1 0x1004e840 +void LegoPhonemePresenter::PutFrame() +{ + // TODO +} + +// STUB: LEGO1 0x1004e870 +void LegoPhonemePresenter::EndAction() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp new file mode 100644 index 00000000..e376966f --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp @@ -0,0 +1,36 @@ +#include "legotexturepresenter.h" + +#include "legoomni.h" +#include "legovideomanager.h" +#include "mxcompositepresenter.h" + +// FUNCTION: LEGO1 0x1004eb40 +LegoTexturePresenter::~LegoTexturePresenter() +{ + VideoManager()->UnregisterPresenter(*this); +} + +// FUNCTION: LEGO1 0x1004ebb0 +MxResult LegoTexturePresenter::AddToManager() +{ + VideoManager()->RegisterPresenter(*this); + return SUCCESS; +} + +// STUB: LEGO1 0x1004fc60 +MxResult LegoTexturePresenter::PutData() +{ + // TODO + return FAILURE; +} + +// FUNCTION: LEGO1 0x1004fcb0 +void LegoTexturePresenter::DoneTickle() +{ + if (this->m_compositePresenter && !this->m_compositePresenter->VTable0x64(2)) { + SetTickleState(e_idle); + return; + } + + MxMediaPresenter::DoneTickle(); +} diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp new file mode 100644 index 00000000..e80b7eed --- /dev/null +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -0,0 +1,513 @@ +#include "legovideomanager.h" + +#include "legoomni.h" +#include "mxtimer.h" +#include "mxtransitionmanager.h" +#include "realtime/matrix.h" +#include "roi/legoroi.h" +#include "tgl/d3drm/impl.h" +#include "viewmanager/viewroi.h" + +DECOMP_SIZE_ASSERT(LegoVideoManager, 0x590); +DECOMP_SIZE_ASSERT(MxStopWatch, 0x18); +DECOMP_SIZE_ASSERT(MxFrequencyMeter, 0x20); + +// FUNCTION: LEGO1 0x1007aa20 +LegoVideoManager::LegoVideoManager() +{ + m_renderer = NULL; + m_3dManager = NULL; + m_viewROI = NULL; + m_direct3d = NULL; + m_unk0xe6 = FALSE; + memset(m_unk0x78, 0, sizeof(m_unk0x78)); + m_unk0x78[0] = 0x6c; + m_unk0x100d9d00 = NULL; + m_isFullscreenMovie = FALSE; + m_palette = NULL; + m_stopWatch = NULL; + m_drawCursor = FALSE; + m_cursorX = m_cursorY; + m_cursorYCopy = m_cursorY; + m_cursorXCopy = m_cursorY; + m_cursorSurface = NULL; + m_fullScreenMovie = FALSE; + m_drawFPS = FALSE; + m_unk0x528 = 0; + m_arialFont = NULL; + m_unk0xe5 = FALSE; + m_unk0x554 = FALSE; + m_paused = FALSE; +} + +// FUNCTION: LEGO1 0x1007ab40 +LegoVideoManager::~LegoVideoManager() +{ + Destroy(); + delete m_palette; +} + +// FUNCTION: LEGO1 0x1007abb0 +MxResult LegoVideoManager::CreateDirect3D() +{ + if (!m_direct3d) { + m_direct3d = new MxDirect3D; + } + + return m_direct3d ? SUCCESS : FAILURE; +} + +// FUNCTION: LEGO1 0x1007ac40 +MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) +{ + MxBool paletteCreated = FALSE; + MxDriver* driver = NULL; + MxDevice* device = NULL; + MxResult result = FAILURE; + + MxDeviceEnumerate100d9cc8 deviceEnumerate; + 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; + + if (!p_videoParam.GetPalette()) { + MxPalette* palette = new MxPalette; + p_videoParam.SetPalette(palette); + + if (!palette) { + goto done; + } + paletteCreated = TRUE; + } + + PALETTEENTRY paletteEntries[256]; + p_videoParam.GetPalette()->GetEntries(paletteEntries); + + if (CreateDirect3D() != SUCCESS) { + goto done; + } + + if (deviceEnumerate.DoEnumerate() != SUCCESS) { + goto done; + } + + if (p_videoParam.GetDeviceName()) { + deviceNum = deviceEnumerate.ParseDeviceName(p_videoParam.GetDeviceName()); + if (deviceNum >= 0) { + if ((deviceNum = deviceEnumerate.GetDevice(deviceNum, driver, device)) != SUCCESS) { + deviceNum = -1; + } + } + } + + if (deviceNum < 0) { + deviceEnumerate.FUN_1009d210(); + deviceNum = deviceEnumerate.FUN_1009d0d0(); + deviceEnumerate.GetDevice(deviceNum, driver, device); + } + + m_direct3d->SetDevice(deviceEnumerate, driver, device); + + if (!driver->m_ddCaps.dwCaps2 && driver->m_ddCaps.dwSVBRops[7] != 2) { + p_videoParam.Flags().SetF2bit0(TRUE); + } + else { + p_videoParam.Flags().SetF2bit0(FALSE); + } + + ViewROI::SetUnk101013d8(p_videoParam.Flags().GetF2bit0() == FALSE); + + if (!m_direct3d->Create( + hwnd, + p_videoParam.Flags().GetFullScreen(), + p_videoParam.Flags().GetFlipSurfaces(), + p_videoParam.Flags().GetBackBuffers() == FALSE, + p_videoParam.GetRect().GetWidth(), + p_videoParam.GetRect().GetHeight(), + bits, + paletteEntries, + sizeof(paletteEntries) / sizeof(paletteEntries[0]) + )) { + goto done; + } + + if (MxVideoManager::VTable0x28( + p_videoParam, + m_direct3d->GetDirectDraw(), + m_direct3d->GetDirect3D(), + m_direct3d->GetFrontBuffer(), + m_direct3d->GetBackBuffer(), + m_direct3d->GetClipper(), + p_frequencyMS, + p_createThread + ) != SUCCESS) { + goto done; + } + + m_renderer = Tgl::CreateRenderer(); + + if (!m_renderer) { + goto done; + } + + m_3dManager = new Lego3DManager; + + if (!m_3dManager) { + goto done; + } + + Lego3DManager::CreateStruct createStruct; + memset(&createStruct, 0, sizeof(createStruct)); + createStruct.m_hWnd = LegoOmni::GetInstance()->GetWindowHandle(); + createStruct.m_pDirectDraw = m_pDirectDraw; + createStruct.m_pFrontBuffer = m_displaySurface->GetDirectDrawSurface1(); + createStruct.m_pBackBuffer = m_displaySurface->GetDirectDrawSurface2(); + createStruct.m_pPalette = m_videoParam.GetPalette()->CreateNativePalette(); + createStruct.m_isFullScreen = FALSE; + createStruct.m_isWideViewAngle = m_videoParam.Flags().GetWideViewAngle(); + createStruct.m_direct3d = m_direct3d->GetDirect3D(); + createStruct.m_d3dDevice = m_direct3d->GetDirect3DDevice(); + + if (!m_3dManager->Create(createStruct)) { + goto done; + } + + ViewLODList* pLODList; + + if (ConfigureD3DRM() != SUCCESS) { + goto done; + } + + pLODList = m_3dManager->GetViewLODListManager()->Create("CameraROI", 1); + m_viewROI = new LegoROI(m_renderer, pLODList, Timer()->GetTime()); + pLODList->Release(); + + CalcLocalTransform(posVec, dirVec, upVec, outMatrix); + m_viewROI->WrappedSetLocalTransform(outMatrix); + + m_3dManager->Add(*m_viewROI); + m_3dManager->SetPointOfView(*m_viewROI); + + m_unk0x100d9d00 = new LegoUnknown100d9d00; + m_render3d = FALSE; + m_stopWatch = new MxStopWatch; + m_stopWatch->Start(); + + result = SUCCESS; + +done: + if (paletteCreated) { + delete p_videoParam.GetPalette(); + p_videoParam.SetPalette(NULL); + } + + return result; +} + +// FUNCTION: LEGO1 0x1007b5e0 +void LegoVideoManager::Destroy() +{ + // todo: delete m_unk0x512 + // todo: delete m_unk0x258 + if (m_arialFont != NULL) { + DeleteObject(m_arialFont); + m_arialFont = NULL; + } + + // delete m_unk0x64; //TODO: delete d3drm + + delete m_3dManager; + MxVideoManager::Destroy(); + delete m_stopWatch; +} + +// FUNCTION: LEGO1 0x1007b6a0 +void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) +{ + m_cursorX = p_cursorX; + m_cursorY = p_cursorY; + m_drawCursor = TRUE; + + if (623 < p_cursorX) { + m_cursorX = 623; + } + + if (463 < p_cursorY) { + m_cursorY = 463; + } +} + +// FUNCTION: LEGO1 0x1007b770 +MxResult LegoVideoManager::Tickle() +{ + if (m_unk0x554 && !m_videoParam.Flags().GetFlipSurfaces() && + TransitionManager()->GetTransitionType() == MxTransitionManager::e_notTransitioning) { + Sleep(30); + } + + m_stopWatch->Stop(); + m_elapsedSeconds = m_stopWatch->ElapsedSeconds(); + m_stopWatch->Reset(); + m_stopWatch->Start(); + + m_direct3d->RestoreSurfaces(); + + SortPresenterList(); + + MxPresenter* presenter; + MxPresenterListCursor cursor(m_presenters); + + while (cursor.Next(presenter)) { + presenter->Tickle(); + } + + 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_paused && (m_render3d || m_unk0xe5)) { + cursor.Reset(); + + while (cursor.Next(presenter) && presenter->GetDisplayZ() >= 0) { + presenter->PutData(); + } + + if (!m_unk0xe5) { + m_3dManager->Render(0.0); + m_3dManager->GetLego3DView()->GetDevice()->Update(); + } + + cursor.Prev(); + + while (cursor.Next(presenter)) { + presenter->PutData(); + } + + if (m_drawCursor) { + DrawCursor(); + } + + if (m_drawFPS) { + DrawFPS(); + } + } + else if (m_fullScreenMovie) { + MxPresenter* presenter; + MxPresenterListCursor cursor(m_presenters); + + if (cursor.Last(presenter)) { + presenter->PutData(); + } + } + + 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()); + } + + UpdateRegion(); + } + + m_region->Reset(); + return SUCCESS; +} + +inline void LegoVideoManager::DrawCursor() +{ + if (m_cursorX != m_cursorXCopy || m_cursorY != m_cursorYCopy) { + if (m_cursorX >= 0 && m_cursorY >= 0) { + m_cursorXCopy = m_cursorX; + m_cursorYCopy = m_cursorY; + } + } + + LPDIRECTDRAWSURFACE ddSurface2 = m_displaySurface->GetDirectDrawSurface2(); + + if (!m_cursorSurface) { + m_cursorRect.top = 0; + m_cursorRect.left = 0; + m_cursorRect.bottom = 16; + m_cursorRect.right = 16; + m_cursorSurface = MxDisplaySurface::CreateCursorSurface(); + + if (!m_cursorSurface) { + m_drawCursor = FALSE; + } + } + + ddSurface2 + ->BltFast(m_cursorXCopy, m_cursorYCopy, m_cursorSurface, &m_cursorRect, DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY); +} + +// STUB: LEGO1 0x1007bbc0 +void LegoVideoManager::DrawFPS() +{ + // TODO +} + +// FUNCTION: LEGO1 0x1007c080 +MxPresenter* LegoVideoManager::GetPresenterAt(MxS32 p_x, MxS32 p_y) +{ + MxPresenterListCursor cursor(m_presenters); + MxPresenter* presenter; + + while (cursor.Prev(presenter)) { + if (presenter->IsHit(p_x, p_y)) { + return presenter; + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x1007c290 +MxResult LegoVideoManager::RealizePalette(MxPalette* p_pallete) +{ + if (p_pallete && m_videoParam.GetPalette()) { + p_pallete->GetEntries(m_paletteEntries); + m_videoParam.GetPalette()->SetEntries(m_paletteEntries); + m_displaySurface->SetPalette(m_videoParam.GetPalette()); + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1007c300 +void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable) +{ + EnableFullScreenMovie(p_enable, TRUE); +} + +// FUNCTION: LEGO1 0x1007c310 +void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) +{ + if (m_isFullscreenMovie != p_enable) { + m_isFullscreenMovie = p_enable; + + if (p_enable) { + m_palette = m_videoParam.GetPalette()->Clone(); + OverrideSkyColor(FALSE); + + m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); + + m_render3d = FALSE; + m_fullScreenMovie = TRUE; + } + else { + m_displaySurface->ClearScreen(); + m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); + + // restore previous pallete + RealizePalette(m_palette); + delete m_palette; + m_palette = NULL; + + // update region where video used to be + MxRect32 rect( + 0, + 0, + m_videoParam.GetRect().GetRight() - m_videoParam.GetRect().GetLeft(), + m_videoParam.GetRect().GetBottom() - m_videoParam.GetRect().GetTop() + ); + + InvalidateRect(rect); + UpdateRegion(); + OverrideSkyColor(TRUE); + + m_render3d = TRUE; + m_fullScreenMovie = FALSE; + } + } + + if (p_enable) { + m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); + } + else { + m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); + } +} + +// FUNCTION: LEGO1 0x1007c440 +void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue) +{ + PALETTEENTRY colorStrucure; + + colorStrucure.peRed = (p_red * 255.0f); + colorStrucure.peGreen = (p_green * 255.0f); + colorStrucure.peBlue = (p_blue * 255.0f); + colorStrucure.peFlags = -124; + m_videoParam.GetPalette()->SetSkyColor(&colorStrucure); + m_videoParam.GetPalette()->SetOverrideSkyColor(TRUE); + m_3dManager->GetLego3DView()->GetView()->SetBackgroundColor(p_red, p_green, p_blue); +} + +// FUNCTION: LEGO1 0x1007c4c0 +void LegoVideoManager::OverrideSkyColor(MxBool p_shouldOverride) +{ + this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride); +} + +// FUNCTION: LEGO1 0x1007c4d0 +void LegoVideoManager::UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) +{ + if (p_width == 0) { + p_width = m_videoParam.GetRect().GetWidth(); + } + if (p_height == 0) { + p_height = m_videoParam.GetRect().GetHeight(); + } + + if (!m_paused) { + m_3dManager->GetLego3DView()->GetView()->ForceUpdate(p_x, p_y, p_width, p_height); + } +} + +// STUB: LEGO1 0x1007c560 +int LegoVideoManager::EnableRMDevice() +{ + // TODO + return 0; +} + +// STUB: LEGO1 0x1007c740 +int LegoVideoManager::DisableRMDevice() +{ + // TODO + return 0; +} + +// FUNCTION: LEGO1 0x1007c930 +MxResult LegoVideoManager::ConfigureD3DRM() +{ + IDirect3DRMDevice2* d3drm = + ((TglImpl::DeviceImpl*) m_3dManager->GetLego3DView()->GetDevice())->ImplementationData(); + + if (!d3drm) { + return FAILURE; + } + + MxAssignedDevice* assignedDevice = m_direct3d->GetAssignedDevice(); + + if (assignedDevice && assignedDevice->GetFlags() & MxAssignedDevice::c_hardwareMode) { + if (assignedDevice->GetDesc().dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) { + d3drm->SetTextureQuality(D3DRMTEXTURE_LINEAR); + } + + d3drm->SetDither(TRUE); + + if (assignedDevice->GetDesc().dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_ALPHAFLATBLEND) { + d3drm->SetRenderMode(D3DRMRENDERMODE_BLENDEDTRANSPARENCY); + } + } + + return SUCCESS; +} diff --git a/LEGO1/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp similarity index 82% rename from LEGO1/mxtransitionmanager.cpp rename to LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp index b10ac7c1..8672cdaa 100644 --- a/LEGO1/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,18 +129,25 @@ 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; TickleManager()->UnregisterClient(this); if (p_notifyWorld) { - LegoWorld* world = GetCurrentWorld(); + LegoWorld* world = CurrentWorld(); if (world) { - world->Notify(MxNotificationParam(MXTRANSITIONMANAGER_TRANSITIONENDED, this)); +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationTransitioned, this); + world->Notify(param); + } +#else + world->Notify(MxNotificationParam(c_notificationTransitioned, this)); +#endif } } } @@ -150,7 +157,7 @@ void MxTransitionManager::EndTransition(MxBool p_notifyWorld) void MxTransitionManager::TransitionNone() { LegoVideoManager* videoManager = VideoManager(); - videoManager->GetDisplaySurface()->FUN_100ba640(); + videoManager->GetDisplaySurface()->ClearScreen(); EndTransition(TRUE); } @@ -202,11 +209,13 @@ void MxTransitionManager::TransitionDissolve() for (MxS32 col = 0; col < 640; col++) { // Select 16 columns on each tick - if (m_animationTimer * 16 > m_columnOrder[col]) + if (m_animationTimer * 16 > m_columnOrder[col]) { continue; + } - if (m_animationTimer * 16 + 15 < m_columnOrder[col]) + if (m_animationTimer * 16 + 15 < m_columnOrder[col]) { continue; + } for (MxS32 row = 0; row < 480; row++) { // Shift the chosen column a different amount at each scanline. @@ -216,10 +225,12 @@ void MxTransitionManager::TransitionDissolve() // Set the chosen pixel to black if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) { - ((MxU8*) ddsd.lpSurface)[row * ddsd.lPitch + xShift] = 0; + MxU8* surf = (MxU8*) ddsd.lpSurface + ddsd.lPitch * row + xShift; + *surf = 0; } else { - ((MxU16*) ddsd.lpSurface)[row * ddsd.lPitch + xShift] = 0; + MxU8* surf = (MxU8*) ddsd.lpSurface + ddsd.lPitch * row + xShift * 2; + *(MxU16*) surf = 0; } } } @@ -229,7 +240,7 @@ void MxTransitionManager::TransitionDissolve() if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) { LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1(); - surf->BltFast(NULL, NULL, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT); + surf->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT); } m_animationTimer++; @@ -282,60 +293,47 @@ void MxTransitionManager::TransitionPixelation() for (MxS32 col = 0; col < 64; col++) { // Select 4 columns on each tick - if (m_animationTimer * 4 > m_columnOrder[col]) + if (m_animationTimer * 4 > m_columnOrder[col]) { continue; + } - if (m_animationTimer * 4 + 3 < m_columnOrder[col]) + if (m_animationTimer * 4 + 3 < m_columnOrder[col]) { continue; + } for (MxS32 row = 0; row < 48; row++) { - MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64); - // To do the pixelation, we subdivide the 640x480 surface into // 10x10 pixel blocks. At the chosen block, we sample the top-leftmost // color and set the other 99 pixels to that value. - // Find the pixel to sample - MxS32 sampleOfs = 10 * row * ddsd.lPitch + xShift; + // First, get the offset of the 10x10 block that we will sample for this row. + MxS32 xShift = 10 * ((m_randomShift[row] + col) % 64); + + // Combine xShift with this value to target the correct location in the buffer. MxS32 bytesPerPixel = ddsd.ddpfPixelFormat.dwRGBBitCount / 8; - // Save this cast from void* to save time. - // Seems to help accuracy doing it this way. - MxU8* surface = (MxU8*) ddsd.lpSurface; - MxU8* source = surface + sampleOfs * bytesPerPixel; + // Seek to the sample position. + MxU8* source = (MxU8*) ddsd.lpSurface + 10 * row * ddsd.lPitch + bytesPerPixel * xShift; + // Sample byte or word depending on display mode. MxU32 sample = bytesPerPixel == 1 ? *source : *(MxU16*) source; + // For each of the 10 rows in the 10x10 square: for (MxS32 k = 10 * row; k < 10 * row + 10; k++) { if (ddsd.ddpfPixelFormat.dwRGBBitCount == 8) { - // TODO: This block and the next don't match, but they are - // hopefully correct in principle. - MxU16 colorWord = MAKEWORD(LOBYTE(sample), LOBYTE(sample)); - MxU32 newColor = MAKELONG(colorWord, colorWord); + MxU8* pos = (MxU8*) ddsd.lpSurface + k * ddsd.lPitch + xShift; - MxU8* pos = surface + k * ddsd.lPitch + xShift; - MxU32* dest = (MxU32*) pos; - - // Sets 10 pixels (10 bytes) - dest[0] = newColor; - dest[1] = newColor; - MxU16* half = (MxU16*) (dest + 2); - *half = newColor; + for (MxS32 tt = 0; tt < 10; tt++) { + pos[tt] = sample; + } } else { - MxU32 newColor = MAKELONG(sample, sample); + // Need to double xShift because it measures pixels not bytes + MxU16* pos = (MxU16*) ((MxU8*) ddsd.lpSurface + k * ddsd.lPitch + 2 * xShift); - // You might expect a cast to MxU16* instead, but lPitch is - // bytes/scanline, not pixels/scanline. Therefore, we just - // need to double the xShift to get to the right spot. - MxU8* pos = surface + k * ddsd.lPitch + 2 * xShift; - MxU32* dest = (MxU32*) pos; - // Sets 10 pixels (20 bytes) - dest[0] = newColor; - dest[1] = newColor; - dest[2] = newColor; - dest[3] = newColor; - dest[4] = newColor; + for (MxS32 tt = 0; tt < 10; tt++) { + pos[tt] = sample; + } } } } @@ -346,7 +344,7 @@ void MxTransitionManager::TransitionPixelation() if (VideoManager()->GetVideoParam().Flags().GetFlipSurfaces()) { LPDIRECTDRAWSURFACE surf = VideoManager()->GetDisplaySurface()->GetDirectDrawSurface1(); - surf->BltFast(NULL, NULL, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT); + surf->BltFast(0, 0, m_ddSurface, &g_fullScreenRect, DDBLTFAST_WAIT); } m_animationTimer++; @@ -468,7 +466,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; } @@ -479,9 +477,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(); } } @@ -535,7 +533,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 @@ -555,8 +553,9 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) (const MxU8*) p_ddsc->lpSurface + m_copyRect.top * p_ddsc->lPitch + bytesPerPixel * m_copyRect.left; m_copyBuffer = new MxU8[bytesPerPixel * width * height]; - if (!m_copyBuffer) + if (!m_copyBuffer) { return; + } // Copy into the copy buffer MxU8* dst = m_copyBuffer; @@ -569,7 +568,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.cpp b/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp new file mode 100644 index 00000000..4fa43a3c --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.cpp @@ -0,0 +1,96 @@ +// Lego3DManager.cpp : implementation file +// +#include "lego3dmanager.h" + +#include "decomp.h" +#include "viewmanager/viewlodlist.h" + +DECOMP_SIZE_ASSERT(Lego3DManager, 0x10); + +////////////////////////////////////////////////////////////////////////////// + +// FUNCTION: LEGO1 0x100ab2d0 +BOOL InitializeCreateStruct( + TglSurface::CreateStruct& rTglSurfaceCreateStruct, + const Lego3DManager::CreateStruct& rCreateStruct +) +{ + // initializes a TglSurface::CreateStruct from a Lego3DManager::CreateStruct + rTglSurfaceCreateStruct.m_pDriverGUID = rCreateStruct.m_pDriverGUID; + rTglSurfaceCreateStruct.m_hWnd = rCreateStruct.m_hWnd; + rTglSurfaceCreateStruct.m_pDirectDraw = rCreateStruct.m_pDirectDraw; + rTglSurfaceCreateStruct.m_pFrontBuffer = rCreateStruct.m_pFrontBuffer; + rTglSurfaceCreateStruct.m_pBackBuffer = rCreateStruct.m_pBackBuffer; + rTglSurfaceCreateStruct.m_pPalette = rCreateStruct.m_pPalette; + rTglSurfaceCreateStruct.m_isFullScreen = rCreateStruct.m_isFullScreen; + rTglSurfaceCreateStruct.m_isWideViewAngle = rCreateStruct.m_isWideViewAngle; + rTglSurfaceCreateStruct.m_direct3d = rCreateStruct.m_direct3d; + rTglSurfaceCreateStruct.m_d3dDevice = rCreateStruct.m_d3dDevice; + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// + +// FUNCTION: LEGO1 0x100ab320 +Lego3DManager::Lego3DManager() +{ + // Tgl things + m_pRenderer = 0; + + m_pLego3DView = 0; + m_pViewLODListManager = 0; +} + +// FUNCTION: LEGO1 0x100ab360 +Lego3DManager::~Lego3DManager() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x100ab370 +BOOL Lego3DManager::Create(CreateStruct& rCreateStruct) +{ + TglSurface::CreateStruct tglSurfaceCreateStruct; + BOOL result; + + assert(!m_pViewLODListManager); + assert(!m_pRenderer); + assert(!m_pLego3DView); + + m_pViewLODListManager = new ViewLODListManager; + assert(m_pViewLODListManager); + + m_pRenderer = Tgl::CreateRenderer(); + assert(m_pRenderer); + + m_pLego3DView = new Lego3DView; + + result = InitializeCreateStruct(tglSurfaceCreateStruct, rCreateStruct); + assert(result); + + result = m_pLego3DView->Create(tglSurfaceCreateStruct, m_pRenderer); + assert(result); + + return result; +} + +// FUNCTION: LEGO1 0x100ab460 +void Lego3DManager::Destroy() +{ + delete m_pLego3DView; + m_pLego3DView = 0; + + delete m_pRenderer; + m_pRenderer = 0; + + delete m_pViewLODListManager; + m_pViewLODListManager = 0; +} + +// FUNCTION: LEGO1 0x100ab4b0 +double Lego3DManager::Render(double p_und) +{ + assert(m_pLego3DView); + + return m_pLego3DView->Render(p_und); +} diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.h b/LEGO1/lego/sources/3dmanager/lego3dmanager.h new file mode 100644 index 00000000..9d993f26 --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.h @@ -0,0 +1,124 @@ +#ifndef _Lego3DManager_h +#define _Lego3DManager_h + +#include "assert.h" +#include "lego3dview.h" + +namespace Tgl +{ +class Renderer; +class Group; +} // namespace Tgl + +class ViewROI; + +// ??? for now +class ViewLODListManager; + +///////////////////////////////////////////////////////////////////////////// +// +// Lego3DManager + +// VTABLE: LEGO1 0x100dbfa4 +// SIZE 0x10 +class Lego3DManager { +public: + // SIZE 0x28 + struct CreateStruct { + const GUID* m_pDriverGUID; // 0x00 + HWND m_hWnd; // 0x04 + IDirectDraw* m_pDirectDraw; // 0x08 + IDirectDrawSurface* m_pFrontBuffer; // 0x0c + IDirectDrawSurface* m_pBackBuffer; // 0x10 + IDirectDrawPalette* m_pPalette; // 0x14 + BOOL m_isFullScreen; // 0x18 + BOOL m_isWideViewAngle; // 0x1c + IDirect3D2* m_direct3d; // 0x20 + IDirect3DDevice2* m_d3dDevice; // 0x24 + }; + +public: + Lego3DManager(); + virtual ~Lego3DManager(); + + BOOL Create(CreateStruct&); + void Destroy(); + + BOOL Add(ViewROI&); + BOOL Remove(ViewROI&); + BOOL Moved(ViewROI&); + BOOL SetPointOfView(ViewROI&); + + double Render(double p_und); + + Tgl::Renderer* GetRenderer(); + Tgl::Group* GetScene(); + Lego3DView* GetLego3DView(); + // ??? for now + ViewLODListManager* GetViewLODListManager(); + + // SYNTHETIC: LEGO1 0x100ab340 + // Lego3DManager::`scalar deleting destructor' + +private: + Tgl::Renderer* m_pRenderer; // 0x04 + + Lego3DView* m_pLego3DView; // 0x08 + ViewLODListManager* m_pViewLODListManager; // 0x0c +}; + +///////////////////////////////////////////////////////////////////////////// +// +// Lego3DManager implementaion + +inline BOOL Lego3DManager::Add(ViewROI& rROI) +{ + assert(m_pLego3DView); + + return m_pLego3DView->Add(rROI); +} + +inline BOOL Lego3DManager::Remove(ViewROI& rROI) +{ + assert(m_pLego3DView); + + return m_pLego3DView->Remove(rROI); +} + +inline BOOL Lego3DManager::SetPointOfView(ViewROI& rROI) +{ + assert(m_pLego3DView); + + return m_pLego3DView->SetPointOfView(rROI); +} + +inline BOOL Lego3DManager::Moved(ViewROI& rROI) +{ + assert(m_pLego3DView); + + return m_pLego3DView->Moved(rROI); +} + +inline Tgl::Renderer* Lego3DManager::GetRenderer() +{ + return m_pRenderer; +} + +inline Tgl::Group* Lego3DManager::GetScene() +{ + assert(m_pLego3DView); + + return m_pLego3DView->GetScene(); +} + +inline Lego3DView* Lego3DManager::GetLego3DView() +{ + return m_pLego3DView; +} + +inline ViewLODListManager* Lego3DManager::GetViewLODListManager() +{ + return m_pViewLODListManager; +} + +#endif /* _Lego3DManager_h */ diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.cpp b/LEGO1/lego/sources/3dmanager/lego3dview.cpp new file mode 100644 index 00000000..34f699d8 --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/lego3dview.cpp @@ -0,0 +1,224 @@ +// Lego3DView.cpp : implementation file +// + +#include "lego3dview.h" + +#include "viewmanager/viewmanager.h" + +DECOMP_SIZE_ASSERT(Lego3DView, 0xa8) + +///////////////////////////////////////////////////////////////////////////// +// Lego3DView + +// FUNCTION: LEGO1 0x100aae90 +Lego3DView::Lego3DView() +{ + m_pViewManager = 0; + m_previousRenderTime = 0; + m_unk0x98 = 0; + m_pPointOfView = 0; +} + +// FUNCTION: LEGO1 0x100aaf30 +Lego3DView::~Lego3DView() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x100aaf90 +BOOL Lego3DView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) +{ + double viewAngle = 45; + 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(GetScene()); + assert(!m_pViewManager); + + 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 + // // accompanied by calling ViewManager::SetFrustrum() + + return TRUE; +} + +// FUNCTION: LEGO1 0x100ab0b0 +void Lego3DView::Destroy() +{ + if (m_pPointOfView) { + m_pPointOfView = 0; + m_pViewManager->SetPOVSource(0); + } + + delete m_pViewManager; + m_pViewManager = 0; + + LegoView1::Destroy(); +} + +// STUB: LEGO1 0x100ab100 +BOOL Lego3DView::Add(ViewROI& rROI) +{ + // assert(m_pViewManager); + + // m_pViewManager->Add(rROI); + + return TRUE; +} + +// STUB: LEGO1 0x100ab170 +BOOL Lego3DView::Remove(ViewROI& rROI) +{ + // assert(m_pViewManager); + + // m_pViewManager->Remove(rROI); + + // if (m_pPointOfView == &rROI) { + // m_pPointOfView = 0; + // m_pViewManager->SetPOVSource(0); + // } + + return TRUE; +} + +// STUB: LEGO1 0x100ab1b0 +BOOL Lego3DView::SetPointOfView(ViewROI& rROI) +{ + // Tgl::DoubleMatrix4 transformation; + // Tgl::Result result; + + // m_pPointOfView = &rROI; + + // assert(m_pViewManager); + // m_pViewManager->SetPOVSource(m_pPointOfView); + + // assert(GetCamera()); + // SETMAT4(transformation, rROI.GetLocalTransform()); + // result = GetCamera()->SetTransformation(transformation); + // assert(Tgl::Succeeded(result)); + + return TRUE; +} + +// STUB: LEGO1 0x100ab210 +BOOL Lego3DView::Moved(ViewROI& rROI) +{ + // assert(m_pViewManager); + + // m_pViewManager->Moved(rROI); + + // if (m_pPointOfView == &rROI) { + // // move the camera + // Tgl::DoubleMatrix4 transformation; + // Tgl::Result result; + + // assert(GetCamera()); + + // SETMAT4(transformation, rROI.GetLocalTransform()); + // result = GetCamera()->SetTransformation(transformation); + // assert(Tgl::Succeeded(result)); + // } + + return TRUE; +} + +// FUNCTION: LEGO1 0x100ab270 +double Lego3DView::Render(double p_und) +{ + assert(m_pViewManager); + m_pViewManager->Update(m_previousRenderTime, p_und); + m_previousRenderTime = TglSurface::Render(); + return m_previousRenderTime; +} + +/* +virtual Tgl::Result Tgl::View::Pick(unsigned long x, + unsigned long y, + const Tgl::Group** ppGroupsToPickFrom, + int groupsToPickFromCount, + const Tgl::Group**& rppPickedGroups, + int& rPickedGroupCount) = 0; +*/ + +// typedef std::map> Group2ROI; + +// STUB: LEGO1 0x100ab2b0 +ViewROI* Lego3DView::Pick(unsigned long x, unsigned long y) +{ + // const ROIList& visible_rois = m_pViewManager->GetVisibleROIs(); + // int n_in = 0, n_out; + // const Tgl::Group** groups_in = new const Tgl::Group*[visible_rois.size()]; + // const Tgl::Group** groups_out = NULL; + // Group2ROI roi_map; + // ViewROI* viewROI = NULL; + + // // generate the list of groups to pick from which is all the geometry + // // groups of all the currently visible ROIs in the view manager. + // // Also, construct a mapping from each group back to it's ROI since that's + // // what we need to return. + // // + // WALK_STL_OBJECT(visible_rois, ROIList, vi) + // { + // ViewROI* vroi = (ViewROI*) (*vi); + // Tgl::Group* g = vroi->GetGeometry(); + // assert(g); + // groups_in[n_in++] = g; + // roi_map[g] = *vi; + // } + + // // perform the pick on our TglView passing the visible groups + // // + // Tgl::View* tglview = GetView(); + // assert(tglview); + // tglview->Pick(x, y, groups_in, n_in, groups_out, n_out); + + // // search the returned group hierarchy from the bottom for the + // // first group which was in groups_in. + // // + // for (int i = n_out - 1; i >= 0; i--) { + // const Tgl::Group* g = (const Tgl::Group*) (groups_out[i]); + // if (!g) // null entries means group node wasn't in groups_in + // continue; + // Group2ROI::iterator gi = roi_map.find(g); + // if (gi != roi_map.end()) { + // viewROI = (ViewROI*) ((*gi).second); + // break; + // } + // } + + // // delete the heap allocated arrays. + // // + // delete[] groups_in; + // if (groups_out) + // delete[] groups_out; + + return NULL; +} + +// double Lego3DView::GetTargetRenderingRate() const +// { +// double secondsAllowed; + +// assert(m_pViewManager); + +// secondsAllowed = m_pViewManager->GetSecondsAllowed(); + +// return (secondsAllowed ? (1 / secondsAllowed) : HUGE_VAL); +// } diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.h b/LEGO1/lego/sources/3dmanager/lego3dview.h new file mode 100644 index 00000000..cbbde4a8 --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/lego3dview.h @@ -0,0 +1,58 @@ +#ifndef _Lego3DView_h +#define _Lego3DView_h + +#include "decomp.h" +#include "legoview1.h" +#include "viewmanager/viewmanager.h" + +///////////////////////////////////////////////////////////////////////////// +// Lego3DView + +// VTABLE: LEGO1 0x100dbf78 +// SIZE 0xa8 +class Lego3DView : public LegoView1 { +public: + Lego3DView(); + ~Lego3DView() override; + + BOOL Create(const CreateStruct&, Tgl::Renderer*); + void Destroy() override; // vtable+0x08 + + BOOL Add(ViewROI&); + BOOL Remove(ViewROI&); + BOOL Moved(ViewROI&); + BOOL SetPointOfView(ViewROI&); + + double Render(double p_und); + + ViewROI* Pick(unsigned long x, unsigned long y); + + ViewROI* GetPointOfView(); + ViewManager* GetViewManager(); + // double GetTargetRenderingRate() const; + +private: + ViewManager* m_pViewManager; // 0x88 + double m_previousRenderTime; // 0x90 + double m_unk0x98; // 0x98 + ViewROI* m_pPointOfView; // 0xa0 +}; + +// SYNTHETIC: LEGO1 0x100aaf10 +// Lego3DView::`scalar deleting destructor' + +///////////////////////////////////////////////////////////////////////////// +// +// Lego3DView implementation + +inline ViewManager* Lego3DView::GetViewManager() +{ + return m_pViewManager; +} + +inline ViewROI* Lego3DView::GetPointOfView() +{ + return m_pPointOfView; +} + +#endif /* _Lego3DView_h */ diff --git a/LEGO1/lego/sources/3dmanager/legoview1.cpp b/LEGO1/lego/sources/3dmanager/legoview1.cpp new file mode 100644 index 00000000..28ffb911 --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/legoview1.cpp @@ -0,0 +1,184 @@ +// LegoView1.cpp : implementation file +// + +#include "legoview1.h" + +#include "decomp.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" +#include "realtime/realtime.h" + +#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 + +// FUNCTION: LEGO1 0x100ab510 +LegoView::LegoView() +{ + m_pScene = 0; + m_pCamera = 0; +} + +// FUNCTION: LEGO1 0x100ab5a0 +LegoView::~LegoView() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x100ab600 +BOOL LegoView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) +{ + float viewAngle = 45; + if (rCreateStruct.m_isWideViewAngle) { + viewAngle = 90; + } + + float frontClippingDistance = 0.1; + float backClippingDistance = 500; + + assert(!m_pScene); + assert(!m_pCamera); + assert(pRenderer); + + m_pScene = pRenderer->CreateGroup(); + assert(m_pScene); + // TglSurface::Create() calls CreateView(), and we need the camera in + // CreateView(), so create camera before calling TglSurface::Create() + m_pCamera = pRenderer->CreateCamera(); + assert(m_pCamera); + + if (!TglSurface::Create(rCreateStruct, pRenderer, m_pScene)) { + delete m_pScene; + m_pScene = 0; + + delete m_pCamera; + m_pCamera = 0; + + return FALSE; + } + + assert(GetView()); + GetView()->SetFrustrum(frontClippingDistance, backClippingDistance, viewAngle); + GetView()->SetBackgroundColor(.223, .639, .851); + + return TRUE; +} + +// FUNCTION: LEGO1 0x100ab6c0 +Tgl::View* LegoView::CreateView(Tgl::Renderer* pRenderer, Tgl::Device* pDevice) +{ + assert(pRenderer); + assert(pDevice); + + return pRenderer->CreateView(pDevice, m_pCamera, 0, 0, GetWidth(), GetHeight()); +} + +// FUNCTION: LEGO1 0x100ab6f0 +void LegoView::Destroy() +{ + delete m_pScene; + m_pScene = 0; + + delete m_pCamera; + m_pCamera = 0; + + TglSurface::Destroy(); +} + +///////////////////////////////////////////////////////////////////////////// +// LegoView1 + +// FUNCTION: LEGO1 0x100ab730 +LegoView1::LegoView1() +{ + m_pSunLight = 0; + m_pDirectionalLight = 0; + m_pAmbientLight = 0; +} + +// FUNCTION: LEGO1 0x100ab7c0 +LegoView1::~LegoView1() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x100ab820 +BOOL LegoView1::AddLightsToViewport() +{ + GetView()->Add(m_pSunLight); + GetView()->Add(m_pDirectionalLight); + GetView()->Add(m_pAmbientLight); + return TRUE; +} + +// FUNCTION: LEGO1 0x100ab860 +BOOL LegoView1::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) +{ + if (!LegoView::Create(rCreateStruct, pRenderer)) { + return FALSE; + } + + // lights + 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); + + Mx3DPointFloat direction(0.0, -1.0, 0.0); + Mx3DPointFloat position(0.0, 0.0, 0.0); + Mx3DPointFloat up(1.0, 0.0, 0.0); + + Tgl::FloatMatrix4 matrix; + Matrix4 in(matrix); + MxMatrix transform; + + 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()); + + return AddLightsToViewport(); +} + +// FUNCTION: LEGO1 0x100abad0 +void LegoView1::Destroy() +{ + if (m_pSunLight) { + GetView()->Remove(m_pSunLight); + delete m_pSunLight; + m_pSunLight = 0; + } + + if (m_pDirectionalLight) { + GetView()->Remove(m_pDirectionalLight); + delete m_pDirectionalLight; + m_pDirectionalLight = 0; + } + + if (m_pAmbientLight) { + GetView()->Remove(m_pAmbientLight); + delete m_pAmbientLight; + m_pAmbientLight = 0; + } + + LegoView::Destroy(); +} diff --git a/LEGO1/lego/sources/3dmanager/legoview1.h b/LEGO1/lego/sources/3dmanager/legoview1.h new file mode 100644 index 00000000..34b8f026 --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/legoview1.h @@ -0,0 +1,76 @@ +#ifndef _LegoView1_h +#define _LegoView1_h + +#include "compat.h" +#include "decomp.h" +#include "tglsurface.h" + +namespace Tgl +{ +class Camera; +} + +///////////////////////////////////////////////////////////////////////////// +// LegoView + +// VTABLE: LEGO1 0x100dc000 +// SIZE 0x78 +class LegoView : public TglSurface { +public: + LegoView(); + ~LegoView() override; + + BOOL Create(const CreateStruct&, Tgl::Renderer*); + void Destroy() override; // vtable+0x08 + + Tgl::Group* GetScene() const; + Tgl::Camera* GetCamera() const; + +protected: + Tgl::View* CreateView(Tgl::Renderer*, Tgl::Device*) override; // vtable+0x10 + +private: + Tgl::Group* m_pScene; // 0x70 + Tgl::Camera* m_pCamera; // 0x74 +}; + +///////////////////////////////////////////////////////////////////////////// +// LegoView implementation + +inline Tgl::Group* LegoView::GetScene() const +{ + return m_pScene; +} + +inline Tgl::Camera* LegoView::GetCamera() const +{ + return m_pCamera; +} + +// SYNTHETIC: LEGO1 0x100ab580 +// LegoView::`scalar deleting destructor' + +///////////////////////////////////////////////////////////////////////////// +// LegoView1 + +// VTABLE: LEGO1 0x100dc018 +// SIZE 0x88 +class LegoView1 : public LegoView { +public: + LegoView1(); + ~LegoView1() override; + + BOOL AddLightsToViewport(); + BOOL Create(const TglSurface::CreateStruct&, Tgl::Renderer*); + void Destroy() override; // vtable+0x08 + +private: + Tgl::Light* m_pSunLight; // 0x78 + Tgl::Light* m_pDirectionalLight; // 0x7c + Tgl::Light* m_pAmbientLight; // 0x80 +}; + +// SYNTHETIC: LEGO1 0x100ab7a0 +// LegoView1::`scalar deleting destructor' + +#endif /* _LegoView1_h */ diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.cpp b/LEGO1/lego/sources/3dmanager/tglsurface.cpp new file mode 100644 index 00000000..394e03e5 --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/tglsurface.cpp @@ -0,0 +1,229 @@ +// TglSurface.cpp : implementation file + +#include "tglsurface.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(TglSurface, 0x70); + +using namespace Tgl; + +///////////////////////////////////////////////////////////////////////////// +// TglSurface + +// FUNCTION: LEGO1 0x100abbf0 +TglSurface::TglSurface() +{ + m_pRenderer = 0; + m_pDevice = 0; + m_pView = 0; + m_pScene = 0; + + m_width = 0; + m_height = 0; + + m_stopRendering = FALSE; + m_isInitialized = FALSE; + + // statistics + m_frameCount = 0; +#ifdef _DEBUG + m_triangleCount = 0; +#endif +} + +// FUNCTION: LEGO1 0x100abd60 +TglSurface::~TglSurface() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x100abde0 +void TglSurface::Destroy() +{ + DestroyView(); + + delete m_pDevice; + m_pDevice = 0; + + m_pRenderer = 0; + m_pScene = 0; +} + +// ??? +// FUNCTION: LEGO1 0x100abe10 +int GetBitsPerPixel(IDirectDrawSurface* pSurface) +{ + DDPIXELFORMAT pixelFormat; + HRESULT result; + + memset(&pixelFormat, 0, sizeof(pixelFormat)); + pixelFormat.dwSize = sizeof(pixelFormat); + + result = pSurface->GetPixelFormat(&pixelFormat); + assert(result == DD_OK); + assert(pixelFormat.dwFlags & DDPF_RGB); + + return pixelFormat.dwRGBBitCount; +} + +// FUNCTION: LEGO1 0x100abe50 +BOOL TglSurface::Create(const CreateStruct& rCreateStruct, Renderer* pRenderer, Group* pScene) +{ + DeviceDirect3DCreateData createData = {rCreateStruct.m_direct3d, rCreateStruct.m_d3dDevice}; + int bitsPerPixel = GetBitsPerPixel(rCreateStruct.m_pFrontBuffer); + + ColorModel colorModel = Ramp; + ShadingModel shadingModel = Gouraud; + int shadeCount = 32; + BOOL dither = TRUE; + int textureShadeCount = -1; + int textureColorCount = -1; + Result result; + + m_pRenderer = pRenderer; + m_pScene = pScene; + m_pDevice = m_pRenderer->CreateDevice(createData); + + if (!m_pDevice) { + assert(0); + m_pRenderer = 0; + m_pScene = 0; + return FALSE; + } + + if (bitsPerPixel == 1) { + shadeCount = 4; + textureShadeCount = 4; + } + else if (bitsPerPixel == 8) { + shadeCount = 16; + dither = FALSE; + textureShadeCount = 16; + textureColorCount = 256; + } + else if (bitsPerPixel == 16) { + shadeCount = 32; + dither = FALSE; + textureShadeCount = 32; + textureColorCount = 256; + } + else if (bitsPerPixel >= 24) { + shadeCount = 256; + dither = FALSE; + textureShadeCount = 256; + textureColorCount = 64; + } + else { + dither = FALSE; + } + + if (textureShadeCount != -1) { + result = pRenderer->SetTextureDefaultShadeCount(textureShadeCount); + assert(Succeeded(result)); + } + if (textureColorCount != -1) { + result = pRenderer->SetTextureDefaultColorCount(textureColorCount); + assert(Succeeded(result)); + } + + result = m_pDevice->SetColorModel(colorModel); + assert(Succeeded(result)); + result = m_pDevice->SetShadingModel(shadingModel); + assert(Succeeded(result)); + result = m_pDevice->SetShadeCount(shadeCount); + assert(Succeeded(result)); + result = m_pDevice->SetDither(dither); + assert(Succeeded(result)); + + m_width = m_pDevice->GetWidth(); + m_height = m_pDevice->GetHeight(); + + m_pView = CreateView(m_pRenderer, m_pDevice); + if (!m_pView) { + delete m_pDevice; + m_pDevice = 0; + m_pRenderer = 0; + m_pScene = 0; + return FALSE; + } + + m_frameRateMeter.Reset(); + m_renderingRateMeter.Reset(); +#ifdef _DEBUG + m_triangleRateMeter.Reset(); +#endif + m_frameRateMeter.StartOperation(); + + m_isInitialized = TRUE; + + return TRUE; +} + +// FUNCTION: LEGO1 0x100ac030 +void TglSurface::DestroyView() +{ + delete m_pView; + m_pView = 0; +} + +// FUNCTION: LEGO1 0x100ac050 +double TglSurface::Render() +{ + MxStopWatch renderTimer; + + if (m_isInitialized && !m_stopRendering) { + Result result; + +#ifdef _DEBUG + m_triangleRateMeter.StartOperation(); +#endif + m_renderingRateMeter.StartOperation(); + renderTimer.Start(); + + // TODO: Wrong interface + result = m_pView->Render((Tgl::Light*) m_pScene); + + renderTimer.Stop(); + assert(Succeeded(result)); + m_renderingRateMeter.EndOperation(); +#ifdef _DEBUG + m_triangleRateMeter.EndOperation(); +#endif + m_frameRateMeter.EndOperation(); + m_frameCount++; + +#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; + } +#endif + +#if 0 + // reset rate meters every 20 frames + if ((++m_frameCount % 20) == 0) +#else + // reset rate meters every 4 seconds + if (m_frameRateMeter.ElapsedSeconds() > 4.0) +#endif + { + m_frameRateMeter.Reset(); + m_renderingRateMeter.Reset(); +#ifdef _DEBUG + m_triangleRateMeter.Reset(); +#endif + } + + m_frameRateMeter.StartOperation(); + } + + return renderTimer.ElapsedSeconds(); +} diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.h b/LEGO1/lego/sources/3dmanager/tglsurface.h new file mode 100644 index 00000000..2b97db50 --- /dev/null +++ b/LEGO1/lego/sources/3dmanager/tglsurface.h @@ -0,0 +1,90 @@ +#ifndef _TglSurface_h +#define _TglSurface_h + +#include "mxdirectx/mxstopwatch.h" +#include "tgl/tgl.h" + +namespace Tgl +{ +class Renderer; +class Device; +class View; +class Group; +} // namespace Tgl + +///////////////////////////////////////////////////////////////////////////// +// TglSurface + +// VTABLE: LEGO1 0x100dc060 +// SIZE 0x70 +class TglSurface { +public: + // SIZE 0x28 + struct CreateStruct { + const GUID* m_pDriverGUID; // 0x00 + HWND m_hWnd; // 0x04 + IDirectDraw* m_pDirectDraw; // 0x08 + IDirectDrawSurface* m_pFrontBuffer; // 0x0c + IDirectDrawSurface* m_pBackBuffer; // 0x10 + IDirectDrawPalette* m_pPalette; // 0x14 + BOOL m_isFullScreen; // 0x18 + BOOL m_isWideViewAngle; // 0x1c + IDirect3D2* m_direct3d; // 0x20 + IDirect3DDevice2* m_d3dDevice; // 0x24 + }; + +public: + TglSurface(); + virtual ~TglSurface(); + + virtual BOOL Create(const CreateStruct&, Tgl::Renderer*, Tgl::Group* pScene); // vtable+0x04 + virtual void Destroy(); // vtable+0x08 + virtual double Render(); // render time in seconds // vtable+0x0c + + Tgl::Renderer* GetRenderer() const { return m_pRenderer; } + Tgl::Device* GetDevice() const { return m_pDevice; } + Tgl::View* GetView() const { return m_pView; } + Tgl::Group* GetScene() const { return m_pScene; } + + unsigned long GetWidth() const { return m_width; } + unsigned long GetHeight() const { return m_height; } + + double GetRenderingRate() const { return m_renderingRateMeter.Frequency(); } + double GetFrameRate() const { return m_frameRateMeter.Frequency(); } + unsigned long GetFrameCount() const { return m_frameCount; } +#ifdef _DEBUG + double GetTriangleRate() const { return m_triangleRateMeter.Frequency(); } +#endif + +protected: + virtual Tgl::View* CreateView(Tgl::Renderer*, Tgl::Device*) = 0; // vtable+0x10 + virtual void DestroyView(); // vtable+0x14 + +private: + Tgl::Renderer* m_pRenderer; // 0x08 + Tgl::Device* m_pDevice; // 0x0c + Tgl::View* m_pView; // 0x10 + Tgl::Group* m_pScene; // 0x14 + + unsigned long m_width; // 0x18 + unsigned long m_height; // 0x1c + + BOOL m_isInitialized; // 0x20 + BOOL m_stopRendering; // 0x24 + + // statistics + MxFrequencyMeter m_renderingRateMeter; // 0x28 + MxFrequencyMeter m_frameRateMeter; // 0x48 + unsigned long m_frameCount; // 0x68 +#ifdef _DEBUG + MxFrequencyMeter m_triangleRateMeter; + unsigned long m_triangleCount; +#endif +}; + +///////////////////////////////////////////////////////////////////////////// + +// SYNTHETIC: LEGO1 0x100abcf0 +// TglSurface::`scalar deleting destructor' + +#endif /* _TglSurface_h */ diff --git a/LEGO1/lego/sources/misc/legoimage.cpp b/LEGO1/lego/sources/misc/legoimage.cpp new file mode 100644 index 00000000..da3f04a0 --- /dev/null +++ b/LEGO1/lego/sources/misc/legoimage.cpp @@ -0,0 +1,176 @@ +#include "legoimage.h" + +#include "decomp.h" +#include "legostorage.h" +#include "memory.h" + +DECOMP_SIZE_ASSERT(LegoPaletteEntry, 0x03); +DECOMP_SIZE_ASSERT(LegoImage, 0x310); + +// FUNCTION: LEGO1 0x100994c0 +LegoPaletteEntry::LegoPaletteEntry() +{ + m_red = 0; + m_green = 0; + m_blue = 0; +} + +// FUNCTION: LEGO1 0x100994d0 +LegoResult LegoPaletteEntry::Read(LegoStorage* p_storage) +{ + LegoResult result; + if ((result = p_storage->Read(&m_red, sizeof(m_red))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_green, sizeof(m_green))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_blue, sizeof(m_blue))) != SUCCESS) { + return result; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099520 +LegoResult LegoPaletteEntry::Write(LegoStorage* p_storage) +{ + LegoResult result; + if ((result = p_storage->Write(&m_red, sizeof(m_red))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_green, sizeof(m_green))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_blue, sizeof(m_blue))) != SUCCESS) { + return result; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099570 +LegoImage::LegoImage() +{ + m_width = 0; + m_height = 0; + m_count = 0; + m_bits = NULL; +} + +// FUNCTION: LEGO1 0x100995a0 +LegoImage::LegoImage(LegoU32 p_width, LegoU32 p_height) +{ + m_width = p_width; + m_height = p_height; + m_count = 0; + m_bits = new LegoU8[m_width * m_height]; +} + +// FUNCTION: LEGO1 0x100995f0 +LegoImage::~LegoImage() +{ + if (m_bits) { + delete[] m_bits; + } +} + +// FUNCTION: LEGO1 0x10099610 +LegoResult LegoImage::Read(LegoStorage* p_storage, LegoU32 p_square) +{ + LegoResult result; + if ((result = p_storage->Read(&m_width, sizeof(m_width))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_height, sizeof(m_height))) != SUCCESS) { + return result; + } + if ((result = p_storage->Read(&m_count, sizeof(m_height))) != SUCCESS) { + return result; + } + for (LegoU32 i = 0; i < m_count; i++) { + if ((result = m_palette[i].Read(p_storage)) != SUCCESS) { + return result; + } + } + if (m_bits) { + delete[] m_bits; + } + m_bits = new LegoU8[m_width * m_height]; + if ((result = p_storage->Read(m_bits, m_width * m_height)) != SUCCESS) { + return result; + } + + if (p_square && m_width != m_height) { + LegoU8* newBits; + + if (m_height < m_width) { + LegoU32 aspect = m_width / m_height; + newBits = new LegoU8[m_width * m_width]; + LegoU8* src = m_bits; + LegoU8* dst = newBits; + + for (LegoU32 row = 0; row < m_height; row++) { + if (aspect) { + for (LegoU32 dup = aspect; dup; dup--) { + memcpy(dst, src, m_width); + dst += m_width; + } + } + src += m_width; + } + + m_height = m_width; + } + else { + LegoU32 aspect = m_height / m_width; + newBits = new LegoU8[m_height * m_height]; + LegoU8* src = m_bits; + LegoU8* dst = newBits; + + for (LegoU32 row = 0; row < m_height; row++) { + for (LegoU32 col = 0; col < m_width; col++) { + if (aspect) { + for (LegoU32 dup = aspect; dup; dup--) { + *dst = *src; + dst++; + } + } + + src++; + } + } + + m_width = m_height; + } + + delete[] m_bits; + m_bits = newBits; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100997e0 +LegoResult LegoImage::Write(LegoStorage* p_storage) +{ + LegoResult result; + if ((result = p_storage->Write(&m_width, sizeof(m_width))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_height, sizeof(m_height))) != SUCCESS) { + return result; + } + if ((result = p_storage->Write(&m_count, sizeof(m_height))) != SUCCESS) { + return result; + } + for (LegoU32 i = 0; i < m_count; i++) { + if ((result = m_palette[i].Write(p_storage)) != SUCCESS) { + return result; + } + } + if (m_bits) { + if ((result = p_storage->Write(m_bits, m_width * m_height)) != SUCCESS) { + return result; + } + } + return SUCCESS; +} diff --git a/LEGO1/lego/sources/misc/legoimage.h b/LEGO1/lego/sources/misc/legoimage.h new file mode 100644 index 00000000..d77a1439 --- /dev/null +++ b/LEGO1/lego/sources/misc/legoimage.h @@ -0,0 +1,54 @@ +#ifndef __LEGOIMAGE_H +#define __LEGOIMAGE_H + +#include "legotypes.h" + +class LegoStorage; + +// SIZE 0x03 +class LegoPaletteEntry { +public: + LegoPaletteEntry(); + // LegoPaletteEntry(LegoU8 p_red, LegoU8 p_green, LegoU8 p_blue); + LegoU8 GetRed() { return m_red; } + void SetRed(LegoU8 p_red) { m_red = p_red; } + LegoU8 GetGreen() { return m_green; } + void SetGreen(LegoU8 p_green) { m_green = p_green; } + LegoU8 GetBlue() { return m_blue; } + void SetBlue(LegoU8 p_blue) { m_blue = p_blue; } + LegoResult Read(LegoStorage* p_storage); + LegoResult Write(LegoStorage* p_storage); + +protected: + LegoU8 m_red; // 0x00 + LegoU8 m_green; // 0x01 + LegoU8 m_blue; // 0x02 +}; + +// 0x310 +class LegoImage { +public: + LegoImage(); + LegoImage(LegoU32 p_width, LegoU32 p_height); + ~LegoImage(); + LegoU32 GetWidth() { return m_width; } + void SetWidth(LegoU32 p_width) { m_width = p_width; } + LegoU32 GetHeight() { return m_height; } + void SetHeight(LegoU32 p_height) { m_height = p_height; } + LegoPaletteEntry* GetPalette() { return m_palette; } + LegoPaletteEntry& GetPaletteEntry(LegoU32 p_i) { return m_palette[p_i]; } + void SetPaletteEntry(LegoU32 p_i, LegoPaletteEntry& p_paletteEntry) { m_palette[p_i] = p_paletteEntry; } + LegoU8* GetBits() { return m_bits; } + void SetBits(LegoU8* p_bits) { m_bits = p_bits; } + LegoResult Read(LegoStorage* p_storage, LegoU32 p_square); + LegoResult Write(LegoStorage* p_storage); + +protected: + LegoU32 m_width; // 0x00 + LegoU32 m_height; // 0x04 + LegoU32 m_count; // 0x08 + LegoPaletteEntry m_palette[256]; // 0x0c + LegoU8* m_bits; // 0x30c +}; + +#endif // __LEGOIMAGE_H diff --git a/LEGO1/lego/sources/misc/legostorage.cpp b/LEGO1/lego/sources/misc/legostorage.cpp new file mode 100644 index 00000000..8fa71553 --- /dev/null +++ b/LEGO1/lego/sources/misc/legostorage.cpp @@ -0,0 +1,142 @@ +#include "legostorage.h" + +#include "decomp.h" + +#include +#include + +DECOMP_SIZE_ASSERT(LegoStorage, 0x08); +DECOMP_SIZE_ASSERT(LegoMemory, 0x10); +DECOMP_SIZE_ASSERT(LegoFile, 0x0c); + +// FUNCTION: LEGO1 0x10099080 +LegoMemory::LegoMemory(void* p_buffer) : LegoStorage() +{ + m_buffer = (LegoU8*) p_buffer; + m_position = 0; +} + +// FUNCTION: LEGO1 0x10099160 +LegoResult LegoMemory::Read(void* p_buffer, LegoU32 p_size) +{ + memcpy(p_buffer, m_buffer + m_position, p_size); + m_position += p_size; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099190 +LegoResult LegoMemory::Write(const void* p_buffer, LegoU32 p_size) +{ + memcpy(m_buffer + m_position, p_buffer, p_size); + m_position += p_size; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100991c0 +LegoFile::LegoFile() +{ + m_file = NULL; +} + +// FUNCTION: LEGO1 0x10099250 +LegoFile::~LegoFile() +{ + if (m_file) { + fclose(m_file); + } +} + +// FUNCTION: LEGO1 0x100992c0 +LegoResult LegoFile::Read(void* p_buffer, LegoU32 p_size) +{ + if (!m_file) { + return FAILURE; + } + if (fread(p_buffer, 1, p_size, m_file) != p_size) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099300 +LegoResult LegoFile::Write(const void* p_buffer, LegoU32 p_size) +{ + if (!m_file) { + return FAILURE; + } + if (fwrite(p_buffer, 1, p_size, m_file) != p_size) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099340 +LegoResult LegoFile::GetPosition(LegoU32& p_position) +{ + if (!m_file) { + return FAILURE; + } + LegoU32 position = ftell(m_file); + if (position == -1) { + return FAILURE; + } + p_position = position; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10099370 +LegoResult LegoFile::SetPosition(LegoU32 p_position) +{ + if (!m_file) { + return FAILURE; + } + if (fseek(m_file, p_position, SEEK_SET) != 0) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100993a0 +LegoResult LegoFile::Open(const char* p_name, LegoU32 p_mode) +{ + if (m_file) { + fclose(m_file); + } + char mode[4]; + mode[0] = '\0'; + if (p_mode & c_read) { + m_mode = c_read; + strcat(mode, "r"); + } + if (p_mode & c_write) { + if (m_mode != c_read) { + m_mode = c_write; + } + strcat(mode, "w"); + } + if ((p_mode & c_text) != 0) { + strcat(mode, "t"); + } + else { + strcat(mode, "b"); + } + + if (!(m_file = fopen(p_name, mode))) { + return FAILURE; + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100994a0 +LegoResult LegoMemory::GetPosition(LegoU32& p_position) +{ + p_position = m_position; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100994b0 +LegoResult LegoMemory::SetPosition(LegoU32 p_position) +{ + m_position = p_position; + return SUCCESS; +} diff --git a/LEGO1/lego/sources/misc/legostorage.h b/LEGO1/lego/sources/misc/legostorage.h new file mode 100644 index 00000000..97dcc538 --- /dev/null +++ b/LEGO1/lego/sources/misc/legostorage.h @@ -0,0 +1,95 @@ +#ifndef __LEGOSTORAGE_H +#define __LEGOSTORAGE_H + +#include "legotypes.h" +#include "mxstring.h" + +#include + +// VTABLE: LEGO1 0x100d7d80 +// SIZE 0x08 +class LegoStorage { +public: + enum OpenFlags { + c_read = 1, + c_write = 2, + c_text = 4 + }; + + LegoStorage() : m_mode(0) {} + + // FUNCTION: LEGO1 0x10045ad0 + virtual ~LegoStorage(){}; + + virtual LegoResult Read(void* p_buffer, LegoU32 p_size) = 0; + virtual LegoResult Write(const void* p_buffer, LegoU32 p_size) = 0; + virtual LegoResult GetPosition(LegoU32& p_position) = 0; + virtual LegoResult SetPosition(LegoU32 p_position) = 0; + + // FUNCTION: LEGO1 0x10045ae0 + virtual LegoBool IsWriteMode() { return m_mode == c_write; } + + // FUNCTION: LEGO1 0x10045af0 + virtual LegoBool IsReadMode() { return m_mode == c_read; } + + // SYNTHETIC: LEGO1 0x10045b00 + // LegoStorage::`scalar deleting destructor' + +protected: + LegoU8 m_mode; // 0x04 +}; + +// VTABLE: LEGO1 0x100db710 +// SIZE 0x10 +class LegoMemory : public LegoStorage { +public: + LegoMemory(void* p_buffer); + LegoResult Read(void* p_buffer, LegoU32 p_size) override; + LegoResult Write(const void* p_buffer, LegoU32 p_size) override; + LegoResult GetPosition(LegoU32& p_position) override; + LegoResult SetPosition(LegoU32 p_position) override; + + // SYNTHETIC: LEGO1 0x10045a80 + // LegoMemory::~LegoMemory + + // SYNTHETIC: LEGO1 0x100990f0 + // LegoMemory::`scalar deleting destructor' + +protected: + LegoU8* m_buffer; // 0x04 + LegoU32 m_position; // 0x08 +}; + +// VTABLE: LEGO1 0x100db730 +// SIZE 0x0c +class LegoFile : public LegoStorage { +public: + LegoFile(); + ~LegoFile() override; + LegoResult Read(void* p_buffer, LegoU32 p_size) override; + LegoResult Write(const void* p_buffer, LegoU32 p_size) override; + LegoResult GetPosition(LegoU32& p_position) override; + LegoResult SetPosition(LegoU32 p_position) override; + LegoResult Open(const char* p_name, LegoU32 p_mode); + + // FUNCTION: LEGO1 0x10006030 + LegoStorage* FUN_10006030(MxString p_str) + { + const char* data = p_str.GetData(); + LegoU32 fullLength = strlen(data); + + LegoU16 limitedLength = fullLength; + Write(&limitedLength, sizeof(limitedLength)); + Write((char*) data, (LegoS16) fullLength); + + return this; + } + + // SYNTHETIC: LEGO1 0x10099230 + // LegoFile::`scalar deleting destructor' + +protected: + FILE* m_file; // 0x08 +}; + +#endif // __LEGOSTORAGE_H diff --git a/LEGO1/lego/sources/misc/legotexture.cpp b/LEGO1/lego/sources/misc/legotexture.cpp new file mode 100644 index 00000000..1f8844ff --- /dev/null +++ b/LEGO1/lego/sources/misc/legotexture.cpp @@ -0,0 +1,31 @@ +#include "legotexture.h" + +#include "decomp.h" +#include "legoimage.h" +#include "legostorage.h" + +DECOMP_SIZE_ASSERT(LegoTexture, 0x04); + +// FUNCTION: LEGO1 0x10098fb0 +LegoTexture::LegoTexture() +{ + m_image = new LegoImage(); +} + +// FUNCTION: LEGO1 0x10099030 +LegoTexture::~LegoTexture() +{ + delete m_image; +} + +// FUNCTION: LEGO1 0x10099050 +LegoResult LegoTexture::Read(LegoStorage* p_storage, LegoU32 p_square) +{ + return m_image->Read(p_storage, p_square); +} + +// FUNCTION: LEGO1 0x10099070 +LegoResult LegoTexture::Write(LegoStorage* p_storage) +{ + return m_image->Write(p_storage); +} diff --git a/LEGO1/lego/sources/misc/legotexture.h b/LEGO1/lego/sources/misc/legotexture.h new file mode 100644 index 00000000..1e279660 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotexture.h @@ -0,0 +1,23 @@ +#ifndef __LEGOTEXTURE_H +#define __LEGOTEXTURE_H + +#include "legotypes.h" + +class LegoImage; +class LegoStorage; + +// SIZE 0x04 +class LegoTexture { +public: + LegoTexture(); + ~LegoTexture(); + LegoImage* GetImage() { return m_image; } + void SetImage(LegoImage* p_image) { m_image = p_image; } + LegoResult Read(LegoStorage* p_storage, LegoU32 p_square); + LegoResult Write(LegoStorage* p_storage); + +protected: + LegoImage* m_image; // 0x00 +}; + +#endif // __LEGOTEXTURE_H diff --git a/LEGO1/lego/sources/misc/legotree.cpp b/LEGO1/lego/sources/misc/legotree.cpp new file mode 100644 index 00000000..e7f24513 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotree.cpp @@ -0,0 +1,110 @@ +#include "legotree.h" + +#include "decomp.h" +#include "legostorage.h" + +DECOMP_SIZE_ASSERT(LegoTreeNodeData, 0x04) +DECOMP_SIZE_ASSERT(LegoTreeNode, 0x010) +DECOMP_SIZE_ASSERT(LegoTree, 0x08) + +// FUNCTION: LEGO1 0x10099d60 +LegoTreeNode::LegoTreeNode() +{ + m_data = NULL; + m_numChildren = 0; + m_children = NULL; +} + +// FUNCTION: LEGO1 0x10099da0 +LegoTreeNode::~LegoTreeNode() +{ + if (m_data) { + delete m_data; + } + if (m_children) { + delete[] m_children; + } +} + +// FUNCTION: LEGO1 0x10099dd0 +LegoTree::LegoTree() +{ + m_root = NULL; +} + +// FUNCTION: LEGO1 0x10099e00 +LegoTree::~LegoTree() +{ + if (m_root) { + Delete(m_root); + } +} + +// FUNCTION: LEGO1 0x10099e20 +LegoResult LegoTree::Read(LegoStorage* p_storage) +{ + return Read(p_storage, m_root); +} + +// FUNCTION: LEGO1 0x10099e40 +LegoResult LegoTree::Write(LegoStorage* p_storage) +{ + return Write(p_storage, m_root); +} + +// FUNCTION: LEGO1 0x10099e60 +LegoResult LegoTree::Read(LegoStorage* p_storage, LegoTreeNode*& p_node) +{ + LegoResult result; + p_node = new LegoTreeNode(); + p_node->SetData(CreateData()); + if ((result = p_node->GetData()->Read(p_storage)) != SUCCESS) { + return result; + } + LegoU32 numChildren; + if ((result = p_storage->Read(&numChildren, sizeof(numChildren))) != SUCCESS) { + return result; + } + if (numChildren) { + p_node->SetChildren(new LegoTreeNode*[numChildren]); + for (LegoU32 i = 0; i < numChildren; i++) { + LegoTreeNode* node; + if ((result = Read(p_storage, node)) != SUCCESS) { + return result; + } + p_node->SetNumChildren(p_node->GetNumChildren() + 1); + p_node->SetChild(i, node); + } + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009a020 +LegoResult LegoTree::Write(LegoStorage* p_storage, LegoTreeNode* p_node) +{ + LegoResult result; + if (p_node->GetData()) { + if ((result = p_node->GetData()->Write(p_storage)) != SUCCESS) { + return result; + } + } + LegoU32 numChildren = p_node->GetNumChildren(); + if ((result = p_storage->Write(&numChildren, sizeof(numChildren))) != SUCCESS) { + return result; + } + for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { + if ((result = Write(p_storage, p_node->GetChild(i))) != SUCCESS) { + return result; + } + } + return SUCCESS; +} + +// FUNCTION: LEGO1 0x1009a0a0 +void LegoTree::Delete(LegoTreeNode* p_node) +{ + for (LegoU32 i = 0; i < p_node->GetNumChildren(); i++) { + Delete(p_node->GetChild(i)); + } + delete p_node; +} diff --git a/LEGO1/lego/sources/misc/legotree.h b/LEGO1/lego/sources/misc/legotree.h new file mode 100644 index 00000000..3ee3d4e5 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotree.h @@ -0,0 +1,77 @@ +#ifndef __LEGOTREE_H +#define __LEGOTREE_H + +#ifdef _DEBUG +#include +#endif +#include "legotypes.h" + +class LegoStorage; + +// VTABLE: LEGO1 0x100db778 +// SIZE 0x04 +class LegoTreeNodeData { +public: + LegoTreeNodeData() {} + virtual ~LegoTreeNodeData() {} + + // FUNCTION: LEGO1 0x10099fe0 + virtual LegoResult Read(LegoStorage* p_storage) { return SUCCESS; } // vtable+0x04 + + // FUNCTION: LEGO1 0x10099ff0 + virtual LegoResult Write(LegoStorage* p_storage) { return SUCCESS; } // vtable+0x08 + + // SYNTHETIC: LEGO1 0x1009a000 + // LegoTreeNodeData::`scalar deleting destructor' +}; + +// VTABLE: LEGO1 0x100db764 +// SIZE 0x10 +class LegoTreeNode { +public: + LegoTreeNode(); + virtual ~LegoTreeNode(); + LegoTreeNodeData* GetData() { return m_data; } + void SetData(LegoTreeNodeData* p_data) { m_data = p_data; } + LegoU32 GetNumChildren() { return m_numChildren; } + void SetNumChildren(LegoU32 p_numChildren) { m_numChildren = p_numChildren; } + LegoTreeNode* GetChild(LegoU32 p_i) { return m_children[p_i]; } + void SetChild(LegoU32 p_i, LegoTreeNode* p_child) { m_children[p_i] = p_child; } + LegoTreeNode** GetChildren() { return m_children; } + void SetChildren(LegoTreeNode** p_children) { m_children = p_children; } + + // SYNTHETIC: LEGO1 0x10099d80 + // LegoTreeNode::`scalar deleting destructor' + +protected: + LegoTreeNodeData* m_data; // 0x04 + LegoU32 m_numChildren; // 0x08 + LegoTreeNode** m_children; // 0x0c +}; + +// VTABLE: LEGO1 0x100db768 +// SIZE 0x08 +class LegoTree { +public: + LegoTree(); + virtual ~LegoTree(); + LegoTreeNode* GetRoot() { return m_root; } + void SetRoot(LegoTreeNode* p_root) { m_root = p_root; } + virtual LegoResult Read(LegoStorage* p_storage); // vtable+0x04 + virtual LegoResult Write(LegoStorage* p_storage); // vtable+0x08 + + // SYNTHETIC: LEGO1 0x10099de0 + // LegoTree::`scalar deleting destructor' + +protected: + LegoResult Read(LegoStorage* p_storage, LegoTreeNode*& p_node); + LegoResult Write(LegoStorage* p_storage, LegoTreeNode* p_node); + void Delete(LegoTreeNode* p_node); + + // FUNCTION: LEGO1 0x10099f70 + virtual LegoTreeNodeData* CreateData() { return new LegoTreeNodeData(); } // vtable+0x0c + + LegoTreeNode* m_root; // 0x04 +}; + +#endif // __LEGOTREE_H diff --git a/LEGO1/lego/sources/misc/legotypes.h b/LEGO1/lego/sources/misc/legotypes.h new file mode 100644 index 00000000..7ba6ada1 --- /dev/null +++ b/LEGO1/lego/sources/misc/legotypes.h @@ -0,0 +1,44 @@ +/* + This unpublished source code contains trade secrets and + copyrighted materials which are the property of Mindscape, Inc. + Unauthorized use, copying or distribution is a violation of U.S. + and international laws and is strictly prohibited. +*/ + +#ifndef __LEGOTYPES_H +#define __LEGOTYPES_H + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef SUCCESS +#define SUCCESS 0 +#endif + +#ifndef FAILURE +#define FAILURE -1 +#endif + +typedef char LegoS8; +typedef unsigned char LegoU8; +typedef short LegoS16; +typedef unsigned short LegoU16; +typedef long LegoS32; +typedef unsigned long LegoU32; +typedef float LegoFloat; +typedef char LegoChar; + +typedef LegoU8 LegoBool; +typedef LegoS32 LegoTime; +typedef LegoS32 LegoResult; + +#endif // __LEGOTYPES_H diff --git a/LEGO1/lego/sources/misc/legoutil.h b/LEGO1/lego/sources/misc/legoutil.h new file mode 100644 index 00000000..92bb84c2 --- /dev/null +++ b/LEGO1/lego/sources/misc/legoutil.h @@ -0,0 +1,54 @@ +#ifndef __LEGOUTIL_H +#define __LEGOUTIL_H + +template +inline T Min(T p_t1, T p_t2) +{ + return p_t1 < p_t2 ? p_t1 : p_t2; +} + +template +inline T Min(T p_t1, T p_t2, T p_t3) +{ + return Min(p_t1, Min(p_t2, p_t3)); +} + +template +inline T Max(T p_t1, T p_t2) +{ + return p_t1 > p_t2 ? p_t1 : p_t2; +} + +template +inline T Max(T p_t1, T p_t2, T p_t3) +{ + return Max(p_t1, Max(p_t2, p_t3)); +} + +template +inline T Abs(T p_t) +{ + return p_t < 0 ? -p_t : p_t; +} + +template +inline void Swap(T& p_t1, T& p_t2) +{ + T t = p_t1; + p_t1 = p_t2; + p_t2 = t; +} + +template +inline T DToR(T p_d) +{ + return p_d * 3.1416F / 180.0F; +} + +template +inline T RToD(T p_r) +{ + return p_r * 180.0F / 3.1416F; +} + +#endif // __LEGOUTIL_H diff --git a/LEGO1/lego/sources/misc/version.h b/LEGO1/lego/sources/misc/version.h new file mode 100644 index 00000000..1eaa84af --- /dev/null +++ b/LEGO1/lego/sources/misc/version.h @@ -0,0 +1,6 @@ +#ifndef __VERSION_H +#define __VERSION_H + +#define MODEL_VERSION 3 + +#endif // __VERSION_H diff --git a/LEGO1/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp similarity index 66% rename from LEGO1/legoroi.cpp rename to LEGO1/lego/sources/roi/legoroi.cpp index f23901ad..e54696a8 100644 --- a/LEGO1/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -2,13 +2,15 @@ #include +DECOMP_SIZE_ASSERT(LegoROI, 0x10c); + // SIZE 0x14 typedef struct { const char* m_name; - MxS32 m_red; - MxS32 m_green; - MxS32 m_blue; - MxS32 m_unk0x10; + int m_red; + int m_green; + int m_blue; + int m_unk0x10; } ROIColorAlias; // GLOBAL: LEGO1 0x100dbe28 @@ -30,55 +32,69 @@ ROIColorAlias g_roiColorAliases[22] = { }; // GLOBAL: LEGO1 0x10101368 -MxS32 g_roiConfig = 100; +int g_roiConfig = 100; // GLOBAL: LEGO1 0x101013ac ROIHandler g_someHandlerFunction = NULL; +// FUNCTION: LEGO1 0x100a46a0 +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) { } // FUNCTION: LEGO1 0x100a81c0 -void LegoROI::configureLegoROI(MxS32 p_roiConfig) +void LegoROI::configureLegoROI(int p_roiConfig) { g_roiConfig = p_roiConfig; } +// STUB: LEGO1 0x100a9a50 +LegoROI::LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, int p_time) : ViewROI(p_renderer, p_lodList) +{ + m_time = p_time; +} + // FUNCTION: LEGO1 0x100a9bf0 -MxBool LegoROI::CallTheHandlerFunction( +unsigned char LegoROI::CallTheHandlerFunction( char* p_param, - MxFloat& p_red, - MxFloat& p_green, - MxFloat& p_blue, - MxFloat& p_other + float& p_red, + float& p_green, + float& p_blue, + float& p_other ) { // TODO - if (p_param == NULL) + if (p_param == NULL) { return FALSE; + } if (g_someHandlerFunction) { char buf[32]; - if (g_someHandlerFunction(p_param, buf, 32)) + if (g_someHandlerFunction(p_param, buf, 32)) { p_param = buf; + } } return ColorAliasLookup(p_param, p_red, p_green, p_blue, p_other); } // FUNCTION: LEGO1 0x100a9c50 -MxBool LegoROI::ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green, MxFloat& p_blue, MxFloat& p_other) +unsigned char LegoROI::ColorAliasLookup(char* p_param, float& p_red, float& p_green, float& p_blue, float& p_other) { // TODO: this seems awfully hacky for these devs. is there a dynamic way // to represent `the end of this array` that would improve this? - MxU32 i = 0; + unsigned int i = 0; do { if (strcmpi(g_roiColorAliases[i].m_name, p_param) == 0) { p_red = g_roiColorAliases[i].m_red * g_normalizeByteToFloat; @@ -88,7 +104,7 @@ MxBool LegoROI::ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green return TRUE; } i++; - } while ((MxS32*) &g_roiColorAliases[i] < &g_roiConfig); + } while ((int*) &g_roiColorAliases[i] < &g_roiConfig); return FALSE; } @@ -100,7 +116,20 @@ void LegoROI::SetSomeHandlerFunction(ROIHandler p_func) } // FUNCTION: LEGO1 0x100a9e10 -void LegoROI::SetDisplayBB(MxS32 p_displayBB) +void LegoROI::SetDisplayBB(int p_displayBB) { // Intentionally empty function } + +// FUNCTION: LEGO1 0x100aa340 +float LegoROI::IntrinsicImportance() const +{ + return .5; +} + +// Note: Actually part of parent class (doesn't exist yet) +// STUB: LEGO1 0x100aa350 +void LegoROI::UpdateWorldBoundingVolumes() +{ + // TODO +} diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h new file mode 100644 index 00000000..cfaa21c0 --- /dev/null +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -0,0 +1,59 @@ +#ifndef LEGOROI_H +#define LEGOROI_H + +#include "viewmanager/viewroi.h" + +typedef unsigned char (*ROIHandler)(char*, char*, unsigned int); + +class LegoEntity; + +// Note: There is an extra class between LegoROI and ViewROI, +// maybe called "AutoROI". VTABLE 0x100dbe38 + +// TODO: Set as superclass of LegoROI +class AutoROI : public ViewROI {}; + +// VTABLE: LEGO1 0x100dbea8 +// SIZE 0x10c +class LegoROI : public ViewROI { +public: + LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, int p_time); + + float IntrinsicImportance() const override; // vtable+0x04 + // Note: Actually part of parent class (doesn't exist yet) + void UpdateWorldBoundingVolumes() override; // vtable+0x18 + + void SetDisplayBB(int p_displayBB); + static void configureLegoROI(int p_roi); + + static void SetSomeHandlerFunction(ROIHandler p_func); + static unsigned char CallTheHandlerFunction( + char* p_param, + float& p_red, + float& p_green, + float& p_blue, + float& p_other + ); + static unsigned char ColorAliasLookup(char* p_param, float& p_red, float& p_green, float& p_blue, float& p_other); + + void WrappedSetLocalTransform(Matrix4& p_transform); + void FUN_100a46b0(Matrix4& p_transform); + void FUN_100a58f0(Matrix4& p_transform); + + inline const char* GetUnknown0xe4() { return m_unk0xe4; } + inline LegoEntity* GetUnknown0x104() { return m_unk0x104; } + + inline void SetUnknown0x104(LegoEntity* p_unk0x104) { m_unk0x104 = p_unk0x104; } + + // SYNTHETIC: LEGO1 0x100a9ad0 + // LegoROI::`scalar deleting destructor' + +private: + undefined4 m_unk0xe0; // 0xe0 + const char* m_unk0xe4; // 0xe4 + undefined m_unk0xe8[0x1c]; // 0xe8 + LegoEntity* m_unk0x104; // 0x104 + int m_time; // 0x108 +}; + +#endif // LEGOROI_H diff --git a/LEGO1/lego3dmanager.h b/LEGO1/lego3dmanager.h deleted file mode 100644 index 3e1cf202..00000000 --- a/LEGO1/lego3dmanager.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef LEGO3DMANAGER_H -#define LEGO3DMANAGER_H - -#include "lego3dview.h" - -class Lego3DManager { -public: - inline Lego3DView* GetLego3DView() { return this->m_3dView; } - -private: - undefined4 m_unk0x00; // 0x00 - undefined4 m_unk0x04; // 0x04 - Lego3DView* m_3dView; // 0x08 -}; - -#endif // LEGO3DMANAGER_H diff --git a/LEGO1/lego3dview.cpp b/LEGO1/lego3dview.cpp deleted file mode 100644 index 0bb384e8..00000000 --- a/LEGO1/lego3dview.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "lego3dview.h" - -#include "legoroi.h" - -// STUB: LEGO1 0x100ab2b0 -LegoROI* Lego3DView::PickROI(MxLong p_a, MxLong p_b) -{ - // TODO - return NULL; -} diff --git a/LEGO1/lego3dview.h b/LEGO1/lego3dview.h deleted file mode 100644 index cafca31a..00000000 --- a/LEGO1/lego3dview.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LEGO3DVIEW_H -#define LEGO3DVIEW_H - -#include "mxtypes.h" -#include "viewmanager/viewmanager.h" - -class LegoROI; - -class Lego3DView { -public: - inline ViewManager* GetViewManager() { return this->m_viewManager; } - LegoROI* PickROI(MxLong p_a, MxLong p_b); - -private: - char m_pad[0x88]; - ViewManager* m_viewManager; -}; - -#endif // LEGO3DVIEW_H diff --git a/LEGO1/lego3dwavepresenter.h b/LEGO1/lego3dwavepresenter.h deleted file mode 100644 index a2363518..00000000 --- a/LEGO1/lego3dwavepresenter.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef LEGO3DWAVEPRESENTER_H -#define LEGO3DWAVEPRESENTER_H - -#include "legowavepresenter.h" - -// VTABLE: LEGO1 0x100d52b0 -// SIZE 0xa0 -class Lego3DWavePresenter : public LegoWavePresenter { -public: - // FUNCTION: LEGO1 0x1000d890 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f058c - return "Lego3DWavePresenter"; - } - - // FUNCTION: LEGO1 0x1000d8a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Lego3DWavePresenter::ClassName()) || MxWavePresenter::IsA(p_name); - } -}; - -#endif // LEGO3DWAVEPRESENTER_H diff --git a/LEGO1/legoact2state.cpp b/LEGO1/legoact2state.cpp deleted file mode 100644 index 1ca6a144..00000000 --- a/LEGO1/legoact2state.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "legoact2state.h" diff --git a/LEGO1/legoactioncontrolpresenter.h b/LEGO1/legoactioncontrolpresenter.h deleted file mode 100644 index 98815348..00000000 --- a/LEGO1/legoactioncontrolpresenter.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef LEGOACTIONCONTROLPRESENTER_H -#define LEGOACTIONCONTROLPRESENTER_H - -#include "decomp.h" -#include "legoutil.h" -#include "mxmediapresenter.h" - -// VTABLE: LEGO1 0x100d5118 -// SIZE 0x68 -class LegoActionControlPresenter : public MxMediaPresenter { -public: - inline LegoActionControlPresenter() { m_unk0x50 = ExtraActionType_none; } - virtual ~LegoActionControlPresenter() override { Destroy(TRUE); }; // vtable+0x00 - - // FUNCTION: LEGO1 0x1000d0e0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f05bc - return "LegoActionControlPresenter"; - } - - // FUNCTION: LEGO1 0x1000d0f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoActionControlPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); - } - - virtual void ReadyTickle() override; // vtable+0x18 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy(MxBool p_fromDestructor); // vtable+0x5c - -private: - ExtraActionType m_unk0x50; // 0x50 - MxString m_unk0x54; // 0x54 - undefined4 m_unk0x64; // 0x64 -}; - -// SYNTHETIC: LEGO1 0x1000d1d0 -// LegoActionControlPresenter::`scalar deleting destructor' - -#endif // LEGOACTIONCONTROLPRESENTER_H diff --git a/LEGO1/legoactor.cpp b/LEGO1/legoactor.cpp deleted file mode 100644 index 46f59a77..00000000 --- a/LEGO1/legoactor.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "legoactor.h" - -DECOMP_SIZE_ASSERT(LegoActor, 0x78) - -// FUNCTION: LEGO1 0x1002d110 -LegoActor::LegoActor() -{ - m_unk0x68 = 0.0f; - m_unk0x6c = 0; - m_unk0x70 = 0.0f; - m_unk0x10 = 0; - m_unk0x74 = 0; -} diff --git a/LEGO1/legoanimationmanager.h b/LEGO1/legoanimationmanager.h deleted file mode 100644 index 0a647e8f..00000000 --- a/LEGO1/legoanimationmanager.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef LEGOANIMATIONMANAGER_H -#define LEGOANIMATIONMANAGER_H - -#include "mxcore.h" - -// VTABLE: LEGO1 0x100d8c18 -// SIZE 0x500 -class LegoAnimationManager : public MxCore { -public: - LegoAnimationManager(); - virtual ~LegoAnimationManager() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x1005ec80 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f7508 - return "LegoAnimationManager"; - } - - // FUNCTION: LEGO1 0x1005ec90 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); - } - - void FUN_1005f6d0(MxBool); - void FUN_10064670(MxBool); - - __declspec(dllexport) static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig); - -private: - void Init(); -}; - -#endif // LEGOANIMATIONMANAGER_H diff --git a/LEGO1/legoanimmmpresenter.cpp b/LEGO1/legoanimmmpresenter.cpp deleted file mode 100644 index a6e20919..00000000 --- a/LEGO1/legoanimmmpresenter.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "legoanimmmpresenter.h" - -// STUB: LEGO1 0x1004a8d0 -LegoAnimMMPresenter::LegoAnimMMPresenter() -{ - // TODO -} diff --git a/LEGO1/legoanimmmpresenter.h b/LEGO1/legoanimmmpresenter.h deleted file mode 100644 index 9fc9d19f..00000000 --- a/LEGO1/legoanimmmpresenter.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef LEGOANIMMMPRESENTER_H -#define LEGOANIMMMPRESENTER_H - -#include "mxcompositepresenter.h" - -// VTABLE: LEGO1 0x100d7de8 -// SIZE 0x74 -class LegoAnimMMPresenter : public MxCompositePresenter { -public: - LegoAnimMMPresenter(); - - // FUNCTION: LEGO1 0x1004a950 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f046c - return "LegoAnimMMPresenter"; - } - - // FUNCTION: LEGO1 0x1004a960 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoAnimMMPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); - } -}; - -#endif // LEGOANIMMMPRESENTER_H diff --git a/LEGO1/legoanimpresenter.cpp b/LEGO1/legoanimpresenter.cpp deleted file mode 100644 index 2bdd7475..00000000 --- a/LEGO1/legoanimpresenter.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "legoanimpresenter.h" - -// STUB: LEGO1 0x10068420 -LegoAnimPresenter::LegoAnimPresenter() -{ - // TODO -} - -// STUB: LEGO1 0x100686f0 -void LegoAnimPresenter::Init() -{ - // TODO -} diff --git a/LEGO1/legoanimpresenter.h b/LEGO1/legoanimpresenter.h deleted file mode 100644 index 5961f74a..00000000 --- a/LEGO1/legoanimpresenter.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef LEGOANIMPRESENTER_H -#define LEGOANIMPRESENTER_H - -#include "mxvideopresenter.h" - -// VTABLE: LEGO1 0x100d90c8 -class LegoAnimPresenter : public MxVideoPresenter { -public: - LegoAnimPresenter(); - - // FUNCTION: LEGO1 0x10068530 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f071c - return "LegoAnimPresenter"; - } - - // FUNCTION: LEGO1 0x10068540 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoAnimPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); - } - -private: - void Init(); -}; - -#endif // LEGOANIMPRESENTER_H diff --git a/LEGO1/legobuildingmanager.h b/LEGO1/legobuildingmanager.h deleted file mode 100644 index 38c9cd57..00000000 --- a/LEGO1/legobuildingmanager.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef LEGOBUILDINGMANAGER_H -#define LEGOBUILDINGMANAGER_H - -#include "mxcore.h" - -// VTABLE: LEGO1 0x100d6f50 -// SIZE 0x30 -class LegoBuildingManager : public MxCore { -public: - LegoBuildingManager(); - virtual ~LegoBuildingManager() override; - - // FUNCTION: LEGO1 0x1002f930 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f37d0 - return "LegoBuildingManager"; - } - - __declspec(dllexport) static void configureLegoBuildingManager(MxS32); - -private: - void Init(); -}; - -#endif // LEGOBUILDINGMANAGER_H diff --git a/LEGO1/legocameracontroller.cpp b/LEGO1/legocameracontroller.cpp deleted file mode 100644 index a182d025..00000000 --- a/LEGO1/legocameracontroller.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "legocameracontroller.h" - -// STUB: LEGO1 0x10011d50 -LegoCameraController::LegoCameraController() -{ - // TODO -} - -// STUB: LEGO1 0x10011f70 -LegoCameraController::~LegoCameraController() -{ - // TODO -} - -// STUB: LEGO1 0x10012260 -void LegoCameraController::LookAt(Vector3Impl& p_at, Vector3Impl& p_dir, Vector3Impl& p_up) -{ -} - -// STUB: LEGO1 0x100123e0 -void LegoCameraController::FUN_100123e0(Matrix4Data& p_transform, MxU32) -{ -} - -// STUB: LEGO1 0x10012740 -Vector3Data& LegoCameraController::FUN_10012740() -{ - return Vector3Data(); -} - -// STUB: LEGO1 0x100127f0 -Vector3Data& LegoCameraController::FUN_100127f0() -{ - return Vector3Data(); -} - -// STUB: LEGO1 0x100128a0 -Vector3Data& LegoCameraController::FUN_100128a0() -{ - return Vector3Data(); -} diff --git a/LEGO1/legocameracontroller.h b/LEGO1/legocameracontroller.h deleted file mode 100644 index 7fa9552d..00000000 --- a/LEGO1/legocameracontroller.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef LEGOCAMERACONTROLLER_H -#define LEGOCAMERACONTROLLER_H - -#include "mxcore.h" -#include "realtime/matrix.h" -#include "realtime/vector.h" - -// VTABLE: LEGO1 0x100d57b0 -// SIZE 0xc8 -class LegoCameraController : public MxCore { -public: - LegoCameraController(); - virtual ~LegoCameraController() override; // vtable+0x0 - - // FUNCTION: LEGO1 0x10011ec0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0850 - return "LegoCameraController"; - } - - // FUNCTION: LEGO1 0x10011ed0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); - } - - void LookAt(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(); -}; - -#endif // LEGOCAMERACONTROLLER_H diff --git a/LEGO1/legocarbuild.cpp b/LEGO1/legocarbuild.cpp deleted file mode 100644 index f75e4653..00000000 --- a/LEGO1/legocarbuild.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "legocarbuild.h" - -// STUB: LEGO1 0x100226d0 -LegoCarBuild::LegoCarBuild() -{ - // TODO -} - -// STUB: LEGO1 0x10022a80 -LegoCarBuild::~LegoCarBuild() -{ - // TODO -} - -// STUB: LEGO1 0x100238b0 -MxResult LegoCarBuild::Tickle() -{ - // TODO - - return 0; -} - -// STUB: LEGO1 0x10024050 -MxLong LegoCarBuild::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/legocarbuild.h b/LEGO1/legocarbuild.h deleted file mode 100644 index b4a93e7c..00000000 --- a/LEGO1/legocarbuild.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef LEGOCARBUILD_H -#define LEGOCARBUILD_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d6658 -// SIZE 0x34c -class LegoCarBuild : public LegoWorld { -public: - LegoCarBuild(); - virtual ~LegoCarBuild() override; - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x10022940 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0504 - return "LegoCarBuild"; - } - - // FUNCTION: LEGO1 0x10022950 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoCarBuild::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // LEGOCARBUILD_H diff --git a/LEGO1/legocarbuildanimpresenter.cpp b/LEGO1/legocarbuildanimpresenter.cpp deleted file mode 100644 index 0b5ba549..00000000 --- a/LEGO1/legocarbuildanimpresenter.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "legocarbuildanimpresenter.h" - -// STUB: LEGO1 0x10078400 -LegoCarBuildAnimPresenter::LegoCarBuildAnimPresenter() -{ - // TODO -} - -// STUB: LEGO1 0x10078680 -LegoCarBuildAnimPresenter::~LegoCarBuildAnimPresenter() -{ - // TODO -} diff --git a/LEGO1/legocarbuildanimpresenter.h b/LEGO1/legocarbuildanimpresenter.h deleted file mode 100644 index 8be926f7..00000000 --- a/LEGO1/legocarbuildanimpresenter.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef LEGOCARBUILDANIMPRESENTER_H -#define LEGOCARBUILDANIMPRESENTER_H - -#include "legoanimpresenter.h" - -// VTABLE: LEGO1 0x100d99e0 -// SIZE 0x150 -class LegoCarBuildAnimPresenter : public LegoAnimPresenter { -public: - LegoCarBuildAnimPresenter(); - virtual ~LegoCarBuildAnimPresenter() override; // vtable+0x0 - - // FUNCTION: LEGO1 0x10078510 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f05ec - return "LegoCarBuildAnimPresenter"; - } - - // FUNCTION: LEGO1 0x10078520 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoCarBuildAnimPresenter::ClassName()) || LegoAnimPresenter::IsA(p_name); - } -}; - -#endif // LEGOCARBUILDANIMPRESENTER_H diff --git a/LEGO1/legocarraceactor.h b/LEGO1/legocarraceactor.h deleted file mode 100644 index d03b20eb..00000000 --- a/LEGO1/legocarraceactor.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LEGOCARRACEACTOR_H -#define LEGOCARRACEACTOR_H - -#include "legoraceactor.h" - -// VTABLE: LEGO1 0x100da0d8 -class LegoCarRaceActor : public LegoRaceActor { -public: - // FUNCTION: LEGO1 0x10081650 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0568 - return "LegoCarRaceActor"; - } - - // FUNCTION: LEGO1 0x10081670 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name); - } -}; - -#endif // LEGOCARRACEACTOR_H diff --git a/LEGO1/legocontrolmanager.cpp b/LEGO1/legocontrolmanager.cpp deleted file mode 100644 index f3c70c50..00000000 --- a/LEGO1/legocontrolmanager.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "legocontrolmanager.h" - -// STUB: LEGO1 0x10028520 -LegoControlManager::LegoControlManager() -{ - // TODO -} - -// STUB: LEGO1 0x10028d60 -LegoControlManager::~LegoControlManager() -{ - // TODO -} - -// STUB: LEGO1 0x10028e10 -void LegoControlManager::Register(MxCore* p_listener) -{ - // TODO -} - -// STUB: LEGO1 0x10028ea0 -void LegoControlManager::Unregister(MxCore* p_listener) -{ - // TODO -} - -// STUB: LEGO1 0x10029600 -MxResult LegoControlManager::Tickle() -{ - // TODO - - return 0; -} diff --git a/LEGO1/legocontrolmanager.h b/LEGO1/legocontrolmanager.h deleted file mode 100644 index 591effb6..00000000 --- a/LEGO1/legocontrolmanager.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LEGOCONTROLMANAGER_H -#define LEGOCONTROLMANAGER_H - -#include "mxcore.h" - -// VTABLE: LEGO1 0x100d6a80 -class LegoControlManager : public MxCore { -public: - LegoControlManager(); - virtual ~LegoControlManager() override; // vtable+0x0 - - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x10028cb0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f31b8 - return "LegoControlManager"; - } - - // FUNCTION: LEGO1 0x10028cc0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoControlManager::ClassName()) || MxCore::IsA(p_name); - } - - void Register(MxCore* p_listener); - void Unregister(MxCore* p_listener); -}; - -#endif // LEGOCONTROLMANAGER_H diff --git a/LEGO1/legoentity.h b/LEGO1/legoentity.h deleted file mode 100644 index cdee29c3..00000000 --- a/LEGO1/legoentity.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef LEGOENTITY_H -#define LEGOENTITY_H - -#include "decomp.h" -#include "extra.h" -#include "legoroi.h" -#include "mxdsobject.h" -#include "mxentity.h" -#include "realtime/vector.h" - -// VTABLE: LEGO1 0x100d4858 -// SIZE 0x68 (probably) -class LegoEntity : public MxEntity { -public: - // Inlined at 0x100853f7 - inline LegoEntity() { Init(); } - - __declspec(dllexport) virtual ~LegoEntity() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x1000c2f0 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f0064 - return "LegoEntity"; - } - - // FUNCTION: LEGO1 0x1000c300 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - 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 - // FUNCTION: LEGO1 0x10001090 - virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 - virtual void VTable0x34(); // vtable+0x34 - virtual void VTable0x38(); // vtable+0x38 - virtual void VTable0x3c(); // vtable+0x3c - virtual void VTable0x40(); // vtable+0x40 - virtual void VTable0x44(); // vtable+0x44 - virtual void VTable0x48(); // vtable+0x48 - virtual void VTable0x4c(); // vtable+0x4c - - void FUN_10010c30(); - -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; - // 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 -}; - -#endif // LEGOENTITY_H diff --git a/LEGO1/legoentitypresenter.cpp b/LEGO1/legoentitypresenter.cpp deleted file mode 100644 index dc1a44eb..00000000 --- a/LEGO1/legoentitypresenter.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "legoentitypresenter.h" - -#include "legoomni.h" -#include "legovideomanager.h" - -DECOMP_SIZE_ASSERT(LegoEntityPresenter, 0x50); - -// FUNCTION: LEGO1 0x10053440 -LegoEntityPresenter::LegoEntityPresenter() -{ - Init(); -} - -// FUNCTION: LEGO1 0x100535c0 -void LegoEntityPresenter::Init() -{ - m_unk0x4c = 0; -} - -// FUNCTION: LEGO1 0x100535d0 -LegoEntityPresenter::~LegoEntityPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x10053630 -undefined4 LegoEntityPresenter::VTable0x6c(undefined4 p_unk0x4c) -{ - m_unk0x4c = p_unk0x4c; - return 0; -} - -// FUNCTION: LEGO1 0x10053640 -void LegoEntityPresenter::Destroy(MxBool p_fromDestructor) -{ - if (VideoManager()) { - VideoManager()->RemovePresenter(*this); - } - - Init(); -} - -// FUNCTION: LEGO1 0x10053670 -void LegoEntityPresenter::Destroy() -{ - Destroy(FALSE); -} diff --git a/LEGO1/legoentitypresenter.h b/LEGO1/legoentitypresenter.h deleted file mode 100644 index 9e072498..00000000 --- a/LEGO1/legoentitypresenter.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef LEGOENTITYPRESENTER_H -#define LEGOENTITYPRESENTER_H - -#include "mxcompositepresenter.h" - -// VTABLE: LEGO1 0x100d8398 -// SIZE 0x50 -class LegoEntityPresenter : public MxCompositePresenter { -public: - LegoEntityPresenter(); - virtual ~LegoEntityPresenter() override; // vtable+0x0 - - // FUNCTION: LEGO1 0x100534b0 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f06b8 - return "LegoEntityPresenter"; - } - - // FUNCTION: LEGO1 0x100534c0 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoEntityPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); - } - - virtual void Destroy() override; // vtable+0x38 - virtual void Init(); // vtable+0x68 - virtual undefined4 VTable0x6c(undefined4 p_unk0x4c); // vtable+0x6c - -private: - void Destroy(MxBool p_fromDestructor); - - undefined4 m_unk0x4c; -}; - -#endif // LEGOENTITYPRESENTER_H diff --git a/LEGO1/legoeventnotificationparam.h b/LEGO1/legoeventnotificationparam.h deleted file mode 100644 index 5f0195ec..00000000 --- a/LEGO1/legoeventnotificationparam.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef LEGOEVENTNOTIFICATIONPARAM_H -#define LEGOEVENTNOTIFICATIONPARAM_H - -#include "mxnotificationparam.h" -#include "mxtypes.h" - -// VTABLE: LEGO1 0x100d6aa0 -class LegoEventNotificationParam : public MxNotificationParam { -public: - inline LegoEventNotificationParam() : MxNotificationParam(PARAM_NONE, NULL) {} - inline LegoEventNotificationParam( - NotificationId p_type, - MxCore* p_sender, - MxU8 p_modifier, - MxS32 p_x, - MxS32 p_y, - MxU8 p_key - ) - : MxNotificationParam(p_type, p_sender), m_modifier(p_modifier), m_x(p_x), m_y(p_y), m_key(p_key), m_unk0x1c(0) - { - } - - virtual ~LegoEventNotificationParam() override {} // vtable+0x0 (scalar deleting destructor) - inline MxU8 GetKey() const { return m_key; } - -protected: - MxU8 m_modifier; // 0x0c - MxS32 m_x; // 0x10 - MxS32 m_y; // 0x14 - MxU8 m_key; // 0x18 - MxU32 m_unk0x1c; // 0x1c -}; - -#endif // LEGOEVENTNOTIFICATIONPARAM_H diff --git a/LEGO1/legoflctexturepresenter.cpp b/LEGO1/legoflctexturepresenter.cpp deleted file mode 100644 index 29a49814..00000000 --- a/LEGO1/legoflctexturepresenter.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "legoflctexturepresenter.h" - -// STUB: LEGO1 0x1005de80 -LegoFlcTexturePresenter::LegoFlcTexturePresenter() -{ - // TODO -} diff --git a/LEGO1/legoflctexturepresenter.h b/LEGO1/legoflctexturepresenter.h deleted file mode 100644 index c68d045d..00000000 --- a/LEGO1/legoflctexturepresenter.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LEGOFLCTEXTUREPRESENTER_H -#define LEGOFLCTEXTUREPRESENTER_H - -#include "mxflcpresenter.h" - -// VTABLE: LEGO1 0x100d89e0 -// SIZE 0x70 -class LegoFlcTexturePresenter : public MxFlcPresenter { -public: - LegoFlcTexturePresenter(); - - // FUNCTION: LEGO1 0x1005def0 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f0634 - return "LegoFlcTexturePresenter"; - } -}; - -#endif // LEGOFLCTEXTUREPRESENTER_H diff --git a/LEGO1/legogamestate.cpp b/LEGO1/legogamestate.cpp deleted file mode 100644 index 62a30db4..00000000 --- a/LEGO1/legogamestate.cpp +++ /dev/null @@ -1,313 +0,0 @@ -#include "legogamestate.h" - -#include "infocenterstate.h" -#include "legoomni.h" -#include "legoroi.h" -#include "legostate.h" -#include "legostream.h" -#include "mxobjectfactory.h" -#include "mxstring.h" -#include "mxvariabletable.h" - -// Based on the highest dword offset (0x42c) referenced in the constructor. -// There may be other members that come after. -DECOMP_SIZE_ASSERT(LegoGameState, 0x430) - -// GLOBAL: LEGO1 0x100f3e24 -const char* g_historyGSI = "History.gsi"; - -// GLOBAL: LEGO1 0x100f3e30 -const char* g_playersGSI = "Players.gsi"; - -// GLOBAL: LEGO1 0x100f3e40 -const char* g_fileExtensionGS = ".GS"; - -// GLOBAL: LEGO1 0x100f3e58 -ColorStringStruct g_colorSaveData[43] = { - {"c_dbbkfny0", "lego red"}, {"c_dbbkxly0", "lego white"}, {"c_chbasey0", "lego black"}, - {"c_chbacky0", "lego black"}, {"c_chdishy0", "lego white"}, {"c_chhorny0", "lego black"}, - {"c_chljety1", "lego black"}, {"c_chrjety1", "lego black"}, {"c_chmidly0", "lego black"}, - {"c_chmotry0", "lego blue"}, {"c_chsidly0", "lego black"}, {"c_chsidry0", "lego black"}, - {"c_chstuty0", "lego black"}, {"c_chtaily0", "lego black"}, {"c_chwindy1", "lego black"}, - {"c_dbfbrdy0", "lego red"}, {"c_dbflagy0", "lego yellow"}, {"c_dbfrfny4", "lego red"}, - {"c_dbfrxly0", "lego white"}, {"c_dbhndly0", "lego white"}, {"c_dbltbry0", "lego white"}, - {"c_jsdashy0", "lego white"}, {"c_jsexhy0", "lego black"}, {"c_jsfrnty5", "lego black"}, - {"c_jshndly0", "lego red"}, {"c_jslsidy0", "lego black"}, {"c_jsrsidy0", "lego black"}, - {"c_jsskiby0", "lego red"}, {"c_jswnshy5", "lego white"}, {"c_rcbacky6", "lego green"}, - {"c_rcedgey0", "lego green"}, {"c_rcfrmey0", "lego red"}, {"c_rcfrnty6", "lego green"}, - {"c_rcmotry0", "lego white"}, {"c_rcsidey0", "lego green"}, {"c_rcstery0", "lego white"}, - {"c_rcstrpy0", "lego yellow"}, {"c_rctailya", "lego white"}, {"c_rcwhl1y0", "lego white"}, - {"c_rcwhl2y0", "lego white"}, {"c_jsbasey0", "lego white"}, {"c_chblady0", "lego black"}, - {"c_chseaty0", "lego white"}, -}; - -// NOTE: This offset = the end of the variables table, the last entry -// in that table is a special entry, the string "END_OF_VARIABLES" -extern const char* g_endOfVariables; - -// FUNCTION: LEGO1 0x10039550 -LegoGameState::LegoGameState() -{ - // TODO - SetROIHandlerFunction(); - - m_stateCount = 0; - m_backgroundColor = new LegoBackgroundColor("backgroundcolor", "set 56 54 68"); - VariableTable()->SetVariable(m_backgroundColor); - - m_tempBackgroundColor = new LegoBackgroundColor("tempBackgroundcolor", "set 56 54 68"); - VariableTable()->SetVariable(m_tempBackgroundColor); - - m_fullScreenMovie = new LegoFullScreenMovie("fsmovie", "disable"); - VariableTable()->SetVariable(m_fullScreenMovie); - - VariableTable()->SetVariable("lightposition", "2"); - SerializeScoreHistory(1); -} - -// FUNCTION: LEGO1 0x10039720 -LegoGameState::~LegoGameState() -{ - LegoROI::SetSomeHandlerFunction(NULL); - - if (m_stateCount) { - for (MxS16 i = 0; i < m_stateCount; i++) { - LegoState* state = m_stateArray[i]; - if (state) - delete state; - } - - delete[] m_stateArray; - } - - delete[] m_savePath; -} - -// 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 { - result = FAILURE; - MxVariableTable* variableTable = VariableTable(); - MxString savePath; - GetFileSavePath(&savePath, p_slot); - LegoFileStream fileStream; - if (fileStream.Open(savePath.GetData(), LegoStream::WriteBit) != FAILURE) { - MxU32 maybeVersion = 0x1000C; - fileStream.Write(&maybeVersion, 4); - fileStream.Write(&m_unk0x24, 2); - fileStream.Write(&m_unk0x10, 2); - fileStream.Write(&m_unk0xc, 1); - - for (MxS32 i = 0; i < sizeof(g_colorSaveData) / sizeof(g_colorSaveData[0]); ++i) { - if (LegoStream::WriteVariable(&fileStream, variableTable, g_colorSaveData[i].m_targetName) == FAILURE) - return result; - } - - if (LegoStream::WriteVariable(&fileStream, variableTable, "backgroundcolor") != FAILURE) { - if (LegoStream::WriteVariable(&fileStream, variableTable, "lightposition") != FAILURE) { - WriteEndOfVariables(&fileStream); - - // TODO: Calls down to more aggregate writing functions - return SUCCESS; - } - } - } - } - return result; -} - -// STUB: LEGO1 0x10039c60 -MxResult LegoGameState::Load(MxULong) -{ - // TODO - return 0; -} - -// FUNCTION: LEGO1 0x10039f00 -void LegoGameState::SetSavePath(char* p_savePath) -{ - if (m_savePath != NULL) - delete[] m_savePath; - - if (p_savePath) { - m_savePath = new char[strlen(p_savePath) + 1]; - strcpy(m_savePath, p_savePath); - } - else - m_savePath = NULL; -} - -// FUNCTION: LEGO1 0x1003a020 -MxResult LegoGameState::WriteEndOfVariables(LegoStream* p_stream) -{ - MxU8 len = strlen(g_endOfVariables); - if (p_stream->Write(&len, 1) == SUCCESS) - return p_stream->Write(g_endOfVariables, len); - return FAILURE; -} - -// FUNCTION: LEGO1 0x1003a170 -void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) -{ - char baseForSlot[2] = "0"; - char path[1024] = ""; - - // Save path base - if (m_savePath != NULL) - strcpy(path, m_savePath); - - // Slot: "G0", "G1", ... - strcat(path, "G"); - baseForSlot[0] += p_slotn; - strcat(path, baseForSlot); - - // Extension: ".GS" - strcat(path, g_fileExtensionGS); - *p_outPath = MxString(path); -} - -// STUB: LEGO1 0x1003a2e0 -void LegoGameState::SerializePlayersInfo(MxS16) -{ - // TODO -} - -// STUB: LEGO1 0x1003a720 -void LegoGameState::FUN_1003a720(MxU32) -{ - // TODO -} - -// STUB: LEGO1 0x1003b060 -void LegoGameState::HandleAction(MxU32) -{ - // TODO -} - -// FUNCTION: LEGO1 0x1003bac0 -void LegoGameState::SetROIHandlerFunction() -{ - LegoROI::SetSomeHandlerFunction(&ROIHandlerFunction); -} - -// FUNCTION: LEGO1 0x1003bad0 -MxBool ROIHandlerFunction(char* p_input, char* p_output, MxU32 p_copyLen) -{ - if (p_output != NULL && p_copyLen != 0 && - (strnicmp(p_input, "INDIR-F-", strlen("INDIR-F-")) == 0 || - strnicmp(p_input, "INDIR-G-", strlen("INDIR-F-")) == 0)) { - - char buf[256]; - sprintf(buf, "c_%s", &p_input[strlen("INDIR-F-")]); - - const char* value = VariableTable()->GetVariable(buf); - if (value != NULL) { - strncpy(p_output, value, p_copyLen); - p_output[p_copyLen - 1] = '\0'; - return TRUE; - } - } - - return FALSE; -} - -// FUNCTION: LEGO1 0x1003bbb0 -LegoState* LegoGameState::GetState(COMPAT_CONST char* p_stateName) -{ - for (MxS32 i = 0; i < m_stateCount; ++i) - if (m_stateArray[i]->IsA(p_stateName)) - return m_stateArray[i]; - return NULL; -} - -// FUNCTION: LEGO1 0x1003bc00 -LegoState* LegoGameState::CreateState(COMPAT_CONST char* p_stateName) -{ - LegoState* newState = (LegoState*) ObjectFactory()->Create(p_stateName); - RegisterState(newState); - - return newState; -} - -// FUNCTION: LEGO1 0x1003bc30 -void LegoGameState::RegisterState(LegoState* p_state) -{ - MxS32 targetIndex; - for (targetIndex = 0; targetIndex < m_stateCount; ++targetIndex) - if (m_stateArray[targetIndex]->IsA(p_state->ClassName())) - break; - - if (targetIndex == m_stateCount) { - LegoState** newBuffer = new LegoState*[m_stateCount + 1]; - - if (m_stateCount != 0) { - memcpy(newBuffer, m_stateArray, m_stateCount * sizeof(LegoState*)); - delete[] m_stateArray; - } - - newBuffer[m_stateCount++] = p_state; - m_stateArray = newBuffer; - return; - } - - if (m_stateArray[targetIndex]) - delete m_stateArray[targetIndex]; - m_stateArray[targetIndex] = p_state; -} - -// STUB: LEGO1 0x1003c870 -void LegoGameState::ScoreStruct::WriteScoreHistory() -{ - // TODO -} - -// STUB: LEGO1 0x1003ccf0 -void LegoGameState::ScoreStruct::FUN_1003ccf0(LegoFileStream&) -{ - // TODO -} - -// FUNCTION: LEGO1 0x1003cdd0 -void LegoGameState::SerializeScoreHistory(MxS16 p_flags) -{ - LegoFileStream stream; - MxString savePath(m_savePath); - savePath += "\\"; - savePath += g_historyGSI; - - if (p_flags == LegoStream::WriteBit) { - m_unk0xa6.WriteScoreHistory(); - } - - if (stream.Open(savePath.GetData(), (LegoStream::OpenFlags) p_flags) == SUCCESS) { - m_unk0xa6.FUN_1003ccf0(stream); - } -} - -// FUNCTION: LEGO1 0x1003cea0 -void LegoGameState::SetSomeEnumState(undefined4 p_state) -{ - m_unk0x10 = p_state; -} - -// FUNCTION: LEGO1 0x1003ceb0 -void LegoGameState::FUN_1003ceb0() -{ - if (FindEntityByAtomIdOrEntityId(*g_isleScript, 0)) { - m_currentAct = 0; - } - else if (FindEntityByAtomIdOrEntityId(*g_act2mainScript, 0)) { - m_currentAct = 1; - } - else if (FindEntityByAtomIdOrEntityId(*g_act3Script, 0)) { - m_currentAct = 2; - } - else { - m_currentAct = -1; - } -} diff --git a/LEGO1/legohideanimpresenter.cpp b/LEGO1/legohideanimpresenter.cpp deleted file mode 100644 index f13165cc..00000000 --- a/LEGO1/legohideanimpresenter.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "legohideanimpresenter.h" - -// FUNCTION: LEGO1 0x1006d7e0 -LegoHideAnimPresenter::LegoHideAnimPresenter() -{ - Init(); -} - -// STUB: LEGO1 0x1006da50 -void LegoHideAnimPresenter::Init() -{ -} diff --git a/LEGO1/legohideanimpresenter.h b/LEGO1/legohideanimpresenter.h deleted file mode 100644 index aca44424..00000000 --- a/LEGO1/legohideanimpresenter.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef LEGOHIDEANIMPRESENTER_H -#define LEGOHIDEANIMPRESENTER_H - -#include "legoloopinganimpresenter.h" - -// VTABLE: LEGO1 0x100d9278 -// SIZE 0xc4 -class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { -public: - LegoHideAnimPresenter(); - - // FUNCTION: LEGO1 0x1006d880 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f06cc - return "LegoHideAnimPresenter"; - } - - // FUNCTION: LEGO1 0x1006d890 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); - } - -private: - void Init(); -}; - -#endif // LEGOHIDEANIMPRESENTER_H diff --git a/LEGO1/legoinputmanager.h b/LEGO1/legoinputmanager.h deleted file mode 100644 index fcb9b560..00000000 --- a/LEGO1/legoinputmanager.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef LEGOINPUTMANAGER_H -#define LEGOINPUTMANAGER_H - -#include "decomp.h" -#include "legoeventnotificationparam.h" -#include "legoworld.h" -#include "mxlist.h" -#include "mxpresenter.h" -#include "mxqueue.h" - -#include - -class LegoControlManager; - -// VTABLE: LEGO1 0x100d87b8 -// class MxCollection - -// VTABLE: LEGO1 0x100d87d0 -// class MxList - -// VTABLE: LEGO1 0x100d87e8 -// class MxQueue - -// VTABLE: LEGO1 0x100d8800 -// SIZE 0x18 -class LegoEventQueue : public MxQueue {}; - -// VTABLE: LEGO1 0x100d8760 -// SIZE 0x338 -class LegoInputManager : public MxPresenter { -public: - LegoInputManager(); - virtual ~LegoInputManager() override; - - __declspec(dllexport) void QueueEvent(NotificationId p_id, MxU8 p_modifier, MxLong p_x, MxLong p_y, MxU8 p_key); - __declspec(dllexport) void Register(MxCore*); - __declspec(dllexport) void UnRegister(MxCore*); - - virtual MxResult Tickle() override; // vtable+0x8 - - MxResult Create(HWND p_hwnd); - void Destroy(); - void CreateAndAcquireKeyboard(HWND p_hwnd); - void ReleaseDX(); - MxResult GetJoystickId(); - MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, DWORD* p_buttonsState, MxU32* p_povPosition); - void SetTimer(); - void KillTimer(); - void SetCamera(LegoCameraController* p_camera); - void ClearCamera(); - void SetWorld(LegoWorld* p_world); - void ClearWorld(); - - inline void SetUnknown88(MxBool p_unk0x88) { m_unk0x88 = p_unk0x88; } - inline void SetUnknown336(MxBool p_unk0x336) { m_unk0x336 = p_unk0x336; } - - inline LegoControlManager* GetControlManager() { return m_controlManager; } - inline LegoWorld* GetWorld() { return m_world; } - - void ProcessEvents(); - MxBool ProcessOneEvent(LegoEventNotificationParam& p_param); - - // private: - MxCriticalSection m_criticalSection; - MxList* m_unk0x5c; // list or hash table - LegoCameraController* m_camera; - LegoWorld* m_world; - LegoEventQueue* m_eventQueue; // +0x68 - undefined4 m_unk0x6c; - undefined4 m_unk0x70; - undefined4 m_unk0x74; - UINT m_timer; - UINT m_timeout; - undefined m_unk0x80; - undefined m_unk0x81; - LegoControlManager* m_controlManager; - MxBool m_unk0x88; - IDirectInput* m_directInput; - IDirectInputDevice* m_directInputDevice; - undefined m_unk0x94; - undefined4 m_unk0x98; - undefined m_unk0x9c[0xF8]; - undefined m_unk0x194; - MxBool m_unk0x195; - MxS32 m_joyid; - MxS32 m_joystickIndex; - JOYCAPS m_joyCaps; - MxBool m_useJoystick; - MxBool m_unk0x335; - MxBool m_unk0x336; -}; - -// TEMPLATE: LEGO1 0x1005bb80 -// MxCollection::Compare - -// TEMPLATE: LEGO1 0x1005bc30 -// MxCollection::Destroy - -// TEMPLATE: LEGO1 0x1005bc80 -// MxList::~MxList - -// SYNTHETIC: LEGO1 0x1005bd50 -// MxCollection::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1005bdc0 -// MxList::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1005beb0 -// LegoEventQueue::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1005bf70 -// MxQueue::`scalar deleting destructor' - -// TEMPLATE: LEGO1 0x1005d010 -// MxListEntry::GetValue - -#endif // LEGOINPUTMANAGER_H diff --git a/LEGO1/legojetski.cpp b/LEGO1/legojetski.cpp deleted file mode 100644 index d0fffd85..00000000 --- a/LEGO1/legojetski.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "legojetski.h" diff --git a/LEGO1/legojetski.h b/LEGO1/legojetski.h deleted file mode 100644 index b7909a46..00000000 --- a/LEGO1/legojetski.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LEGOJETSKI_H -#define LEGOJETSKI_H - -#include "legojetskiraceactor.h" - -// VTABLE: LEGO1 0x100d5a40 -class LegoJetski : public LegoJetskiRaceActor { -public: - // FUNCTION: LEGO1 0x10013e80 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f053c - return "LegoJetski"; - } - - // FUNCTION: LEGO1 0x10013ea0 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoJetski::ClassName()) || LegoJetskiRaceActor::IsA(p_name); - } -}; - -#endif // LEGOJETSKI_H diff --git a/LEGO1/legoloadcachesoundpresenter.cpp b/LEGO1/legoloadcachesoundpresenter.cpp deleted file mode 100644 index 4bc2cbd6..00000000 --- a/LEGO1/legoloadcachesoundpresenter.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "legoloadcachesoundpresenter.h" - -// FUNCTION: LEGO1 0x10018340 -LegoLoadCacheSoundPresenter::LegoLoadCacheSoundPresenter() -{ - Init(); -} - -// STUB: LEGO1 0x10018480 -LegoLoadCacheSoundPresenter::~LegoLoadCacheSoundPresenter() -{ - // TODO -} - -// STUB: LEGO1 0x100184e0 -void LegoLoadCacheSoundPresenter::Init() -{ - // TODO -} diff --git a/LEGO1/legoloadcachesoundpresenter.h b/LEGO1/legoloadcachesoundpresenter.h deleted file mode 100644 index 6f9f473b..00000000 --- a/LEGO1/legoloadcachesoundpresenter.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef LEGOLOADCACHESOUNDPRESENTER_H -#define LEGOLOADCACHESOUNDPRESENTER_H - -#include "mxwavepresenter.h" - -// VTABLE: LEGO1 0x100d5fa8 -// SIZE 0x90 -class LegoLoadCacheSoundPresenter : public MxWavePresenter { -public: - LegoLoadCacheSoundPresenter(); - virtual ~LegoLoadCacheSoundPresenter() override; - - // FUNCTION: LEGO1 0x10018450 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f05a0 - return "LegoLoadCacheSoundPresenter"; - } - -private: - void Init(); -}; - -#endif // LEGOLOADCACHESOUNDPRESENTER_H diff --git a/LEGO1/legolocomotionanimpresenter.cpp b/LEGO1/legolocomotionanimpresenter.cpp deleted file mode 100644 index 27d6e421..00000000 --- a/LEGO1/legolocomotionanimpresenter.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "legolocomotionanimpresenter.h" - -// FUNCTION: LEGO1 0x1006cdd0 -LegoLocomotionAnimPresenter::LegoLocomotionAnimPresenter() -{ - Init(); -} - -// STUB: LEGO1 0x1006d0b0 -void LegoLocomotionAnimPresenter::Init() -{ - // TODO -} diff --git a/LEGO1/legolocomotionanimpresenter.h b/LEGO1/legolocomotionanimpresenter.h deleted file mode 100644 index e7d7af25..00000000 --- a/LEGO1/legolocomotionanimpresenter.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef LEGOLOCOMOTIONANIMPRESENTER_H -#define LEGOLOCOMOTIONANIMPRESENTER_H - -#include "legoloopinganimpresenter.h" - -// VTABLE: LEGO1 0x100d9170 -class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { -public: - LegoLocomotionAnimPresenter(); - - // FUNCTION: LEGO1 0x1006ce50 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f06e4 - return "LegoLocomotionAnimPresenter"; - } - - // FUNCTION: LEGO1 0x1006ce60 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, ClassName()) || LegoLoopingAnimPresenter::IsA(p_name); - } - -private: - void Init(); -}; - -#endif // LEGOLOCOMOTIONANIMPRESENTER_H diff --git a/LEGO1/legometerpresenter.cpp b/LEGO1/legometerpresenter.cpp deleted file mode 100644 index 6314a4fd..00000000 --- a/LEGO1/legometerpresenter.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "legometerpresenter.h" - -#include "decomp.h" - -// Uncomment when member class variables are fleshed out. -// DECOMP_SIZE_ASSERT(LegoMeterPresenter, 0x94); // 0x1000a163 diff --git a/LEGO1/legometerpresenter.h b/LEGO1/legometerpresenter.h deleted file mode 100644 index 023a7bfa..00000000 --- a/LEGO1/legometerpresenter.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef LEGOMETERPRESENTER_H -#define LEGOMETERPRESENTER_H - -#include "mxstillpresenter.h" - -// VTABLE: LEGO1 0x100d7ac8 -// SIZE 0x94 (from 0x1000a163) -class LegoMeterPresenter : public MxStillPresenter { -public: - // MxStillPresenter's `::ClassName` and `::IsA` are used. -}; - -#endif // LEGOMETERPRESENTER_H diff --git a/LEGO1/legomodelpresenter.cpp b/LEGO1/legomodelpresenter.cpp deleted file mode 100644 index 75ed1750..00000000 --- a/LEGO1/legomodelpresenter.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "legomodelpresenter.h" - -// GLOBAL: LEGO1 0x100f7ae0 -int g_modelPresenterConfig = 1; - -// FUNCTION: LEGO1 0x1007f660 -void LegoModelPresenter::configureLegoModelPresenter(MxS32 p_modelPresenterConfig) -{ - g_modelPresenterConfig = p_modelPresenterConfig; -} diff --git a/LEGO1/legomodelpresenter.h b/LEGO1/legomodelpresenter.h deleted file mode 100644 index b529fede..00000000 --- a/LEGO1/legomodelpresenter.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef LEGOMODELPRESENTER_H -#define LEGOMODELPRESENTER_H - -#include "mxvideopresenter.h" - -// VTABLE: LEGO1 0x100d4e50 -// SIZE 0x6c (discovered through inline constructor at 0x10009ae6) -class LegoModelPresenter : public MxVideoPresenter { -public: - __declspec(dllexport) static void configureLegoModelPresenter(MxS32 p_modelPresenterConfig); - - // FUNCTION: LEGO1 0x1000ccb0 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f067c - return "LegoModelPresenter"; - } - - // FUNCTION: LEGO1 0x1000ccc0 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoModelPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); - } -}; - -#endif // LEGOMODELPRESENTER_H diff --git a/LEGO1/legoobjectfactory.cpp b/LEGO1/legoobjectfactory.cpp deleted file mode 100644 index 2c77c7a9..00000000 --- a/LEGO1/legoobjectfactory.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "legoobjectfactory.h" - -#include "decomp.h" -#include "infocenterstate.h" - -// TODO: Uncomment once we have all the relevant types ready -// DECOMP_SIZE_ASSERT(LegoObjectFactory, 0x1c8); - -// FUNCTION: LEGO1 0x10006e40 -LegoObjectFactory::LegoObjectFactory() -{ -#define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact); - FOR_LEGOOBJECTFACTORY_OBJECTS(X) -#undef X -} - -// FUNCTION: LEGO1 0x10009a90 -MxCore* LegoObjectFactory::Create(const char* p_name) -{ - MxAtomId atom(p_name, LookupMode_Exact); - -#define X(V) \ - if (this->m_id##V == atom) { \ - return new V; \ - } \ - else - FOR_LEGOOBJECTFACTORY_OBJECTS(X) -#undef X - { - return MxObjectFactory::Create(p_name); - } -} - -// FUNCTION: LEGO1 0x1000fb30 -void LegoObjectFactory::Destroy(MxCore* p_object) -{ - delete p_object; -} diff --git a/LEGO1/legoobjectfactory.h b/LEGO1/legoobjectfactory.h deleted file mode 100644 index 82117d34..00000000 --- a/LEGO1/legoobjectfactory.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef LEGOOBJECTFACTORY_H -#define LEGOOBJECTFACTORY_H - -#include "mxobjectfactory.h" - -#define FOR_LEGOOBJECTFACTORY_OBJECTS(X) X(InfocenterState) - -// VTABLE: LEGO1 0x100d4768 -class LegoObjectFactory : public MxObjectFactory { -public: - LegoObjectFactory(); - virtual MxCore* Create(const char* p_name) override; // vtable 0x14 - virtual void Destroy(MxCore* p_object) override; // vtable 0x18 - -private: -#define X(V) MxAtomId m_id##V; - FOR_LEGOOBJECTFACTORY_OBJECTS(X) -#undef X -}; - -#endif // LEGOOBJECTFACTORY_H diff --git a/LEGO1/legopalettepresenter.cpp b/LEGO1/legopalettepresenter.cpp deleted file mode 100644 index 5ee9279f..00000000 --- a/LEGO1/legopalettepresenter.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "legopalettepresenter.h" - -DECOMP_SIZE_ASSERT(LegoPalettePresenter, 0x68) - -// FUNCTION: LEGO1 0x10079e50 -LegoPalettePresenter::LegoPalettePresenter() -{ - Init(); -} - -// FUNCTION: LEGO1 0x1007a070 -LegoPalettePresenter::~LegoPalettePresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1007a0d0 -void LegoPalettePresenter::Init() -{ - m_palette = NULL; -} - -// FUNCTION: LEGO1 0x1007a0e0 -void LegoPalettePresenter::Destroy(MxBool p_fromDestructor) -{ - m_criticalSection.Enter(); - if (m_palette) { - delete m_palette; - } - Init(); - m_criticalSection.Leave(); - if (!p_fromDestructor) { - MxVideoPresenter::Destroy(FALSE); - } -} - -// FUNCTION: LEGO1 0x1007a120 -void LegoPalettePresenter::Destroy() -{ - Destroy(FALSE); -} diff --git a/LEGO1/legopathcontroller.cpp b/LEGO1/legopathcontroller.cpp deleted file mode 100644 index a636253a..00000000 --- a/LEGO1/legopathcontroller.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "legopathcontroller.h" - -// STUB: LEGO1 0x10044f40 -LegoPathController::LegoPathController() -{ - // TODO -} - -// STUB: LEGO1 0x10045740 -LegoPathController::~LegoPathController() -{ - // TODO -} - -// STUB: LEGO1 0x10045c10 -MxResult LegoPathController::Tickle() -{ - // TODO - return SUCCESS; -} diff --git a/LEGO1/legoplantmanager.h b/LEGO1/legoplantmanager.h deleted file mode 100644 index 87a6ec79..00000000 --- a/LEGO1/legoplantmanager.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef LEGOPLANTMANAGER_H -#define LEGOPLANTMANAGER_H - -#include "mxcore.h" - -// VTABLE: LEGO1 0x100d6758 -// SIZE 0x2c -class LegoPlantManager : public MxCore { -public: - LegoPlantManager(); - virtual ~LegoPlantManager() override; // vtable+0x0 - - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x10026290 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f318c - return "LegoPlantManager"; - } - -private: - void Init(); -}; - -#endif // LEGOPLANTMANAGER_H diff --git a/LEGO1/legorace.h b/LEGO1/legorace.h deleted file mode 100644 index 8ae52d8e..00000000 --- a/LEGO1/legorace.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef LEGORACE_H -#define LEGORACE_H - -#include "decomp.h" -#include "legoworld.h" -#include "mxtypes.h" - -// VTABLE: LEGO1 0x100d5db0 -// SIZE 0x144 -class LegoRace : public LegoWorld { -public: - LegoRace(); - virtual ~LegoRace() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x10015ba0 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f07c4 - return "LegoRace"; - } - - // FUNCTION: LEGO1 0x10015bb0 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoRace::ClassName()) || LegoWorld::IsA(p_name); - } - - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 - virtual MxBool VTable0x5c() override; // vtable+0x5c - virtual MxBool VTable0x64() override; // vtable+0x64 - virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 - virtual undefined4 VTable0x6c(undefined4) = 0; // vtable+0x6c - virtual undefined4 VTable0x70(undefined4); // vtable+0x70 - virtual undefined4 VTable0x74(undefined4); // vtable+0x74 - virtual undefined4 VTable0x78(undefined4); // vtable+0x78 - virtual void VTable0x7c(undefined4, undefined4); // vtable+0x7c - -private: - undefined4 m_unk0xf8; // 0xf8 - undefined4 m_unk0xfc; // 0xfc - undefined4 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 - undefined4 m_unk0x108; // 0x108 - undefined4 m_unk0x10c; // 0x10c - undefined4 m_unk0x110; // 0x110 - undefined4 m_unk0x114; // 0x114 - undefined4 m_unk0x118; // 0x118 - undefined4 m_unk0x11c; // 0x11c - undefined4 m_unk0x120; // 0x120 - this may be the current vehcle (function at 0x10015880) - undefined4 m_unk0x124; // 0x124 - something game state - undefined4 m_unk0x128; // 0x128 - undefined4 m_unk0x12c; // 0x12c - undefined4 m_unk0x130[4]; // unconfirmed bytes, ghidra claims these are integers - undefined4 m_unk0x140; -}; - -#endif // LEGORACE_H diff --git a/LEGO1/legoraceactor.h b/LEGO1/legoraceactor.h deleted file mode 100644 index 9a4e34ec..00000000 --- a/LEGO1/legoraceactor.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LEGORACEACTOR_H -#define LEGORACEACTOR_H - -#include "legoanimactor.h" - -// VTABLE: LEGO1 0x100d5b88 -class LegoRaceActor : public LegoAnimActor { -public: - // FUNCTION: LEGO1 0x10014af0 - inline const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f0bf4 - return "LegoRaceActor"; - } - - // FUNCTION: LEGO1 0x10014b10 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoRaceActor::ClassName()) || LegoAnimActor::IsA(p_name); - } -}; - -#endif // LEGORACEACTOR_H diff --git a/LEGO1/legoroi.h b/LEGO1/legoroi.h deleted file mode 100644 index 74024ce6..00000000 --- a/LEGO1/legoroi.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef LEGOROI_H -#define LEGOROI_H - -#include "mxtypes.h" -#include "viewmanager/viewroi.h" - -typedef MxBool (*ROIHandler)(char*, char*, MxU32); - -class LegoROI : public ViewROI { -public: - __declspec(dllexport) void SetDisplayBB(MxS32 p_displayBB); - __declspec(dllexport) static void configureLegoROI(MxS32 p_roi); - - static void SetSomeHandlerFunction(ROIHandler p_func); - static MxBool CallTheHandlerFunction( - char* p_param, - MxFloat& p_red, - MxFloat& p_green, - MxFloat& p_blue, - MxFloat& p_other - ); - static MxBool ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green, MxFloat& p_blue, MxFloat& p_other); - void FUN_100a46b0(Matrix4Impl& p_transform); - void FUN_100a58f0(Matrix4Impl& p_transform); -}; - -#endif // LEGOROI_H diff --git a/LEGO1/legostate.cpp b/LEGO1/legostate.cpp deleted file mode 100644 index c99fb708..00000000 --- a/LEGO1/legostate.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "legostate.h" - -DECOMP_SIZE_ASSERT(LegoState, 0x08); - -// FUNCTION: LEGO1 0x10005f40 -LegoState::~LegoState() -{ -} - -// FUNCTION: LEGO1 0x10005f90 -MxBool LegoState::VTable0x14() -{ - return TRUE; -} - -// FUNCTION: LEGO1 0x10005fa0 -MxBool LegoState::SetFlag() -{ - return FALSE; -} - -// FUNCTION: LEGO1 0x10005fb0 -MxResult LegoState::VTable0x1c(LegoFileStream* p_legoFileStream) -{ - if (p_legoFileStream->IsWriteMode()) { - p_legoFileStream->FUN_10006030(this->ClassName()); - } - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10006030 -LegoFileStream* LegoFileStream::FUN_10006030(MxString p_str) -{ - const char* data = p_str.GetData(); - MxU32 fullLength = strlen(data); - - MxU16 limitedLength = fullLength; - Write(&limitedLength, sizeof(limitedLength)); - Write(data, (MxS16) fullLength); - - return this; -} diff --git a/LEGO1/legostate.h b/LEGO1/legostate.h deleted file mode 100644 index 55f0a1af..00000000 --- a/LEGO1/legostate.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef LEGOSTATE_H -#define LEGOSTATE_H - -#include "decomp.h" -#include "legostream.h" -#include "mxcore.h" -#include "mxstring.h" - -// VTABLE: LEGO1 0x100d46c0 -class LegoState : public MxCore { -public: - virtual ~LegoState() override; // vtable+0x00 - - // FUNCTION: LEGO1 0x100060d0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f01b8 - return "LegoState"; - } - - // FUNCTION: LEGO1 0x100060e0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoState::ClassName()) || MxCore::IsA(p_name); - } - - virtual MxBool VTable0x14(); // vtable+0x14 - virtual MxBool SetFlag(); // vtable+0x18 - virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream); // vtable+0x1C -}; - -#endif // LEGOSTATE_H diff --git a/LEGO1/legostream.cpp b/LEGO1/legostream.cpp deleted file mode 100644 index 0cfe0a51..00000000 --- a/LEGO1/legostream.cpp +++ /dev/null @@ -1,200 +0,0 @@ - -#include "legostream.h" - -#include "mxvariabletable.h" - -#include -#include - -// This is a pointer to the end of the global variable name table, which has -// the text "END_OF_VARIABLES" in it. -// TODO: make g_endOfVariables reference the actual end of the variable array. -// GLOBAL: LEGO1 0x100f3e50 -const char* g_endOfVariables = "END_OF_VARIABLES"; - -// Very likely but not certain sizes. -// The classes are only used on the stack in functions we have not 100% matched -// yet, we can confirm the size once we have. -DECOMP_SIZE_ASSERT(LegoStream, 0x8); -DECOMP_SIZE_ASSERT(LegoFileStream, 0xC); -DECOMP_SIZE_ASSERT(LegoMemoryStream, 0x10); - -// FUNCTION: LEGO1 0x10039f70 -MxResult LegoStream::WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName) -{ - MxResult result = FAILURE; - const char* variableValue = p_from->GetVariable(p_variableName); - - if (variableValue) { - MxU8 length = strlen(p_variableName); - if (p_stream->Write((char*) &length, 1) == SUCCESS) { - if (p_stream->Write(p_variableName, length) == SUCCESS) { - length = strlen(variableValue); - if (p_stream->Write((char*) &length, 1) == SUCCESS) - result = p_stream->Write((char*) variableValue, length); - } - } - } - return result; -} - -// 95% match, just some instruction ordering differences on the call to -// MxVariableTable::SetVariable at the end. -// FUNCTION: LEGO1 0x1003a080 -MxS32 LegoStream::ReadVariable(LegoStream* p_stream, MxVariableTable* p_to) -{ - MxS32 result = 1; - MxU8 length; - - if (p_stream->Read((char*) &length, 1) == SUCCESS) { - char nameBuffer[256]; - if (p_stream->Read(nameBuffer, length) == SUCCESS) { - nameBuffer[length] = '\0'; - if (strcmp(nameBuffer, g_endOfVariables) == 0) - // 2 -> "This was the last entry, done reading." - result = 2; - else { - if (p_stream->Read((char*) &length, 1) == SUCCESS) { - char valueBuffer[256]; - if (p_stream->Read(valueBuffer, length) == SUCCESS) { - result = 0; - valueBuffer[length] = '\0'; - p_to->SetVariable(nameBuffer, valueBuffer); - } - } - } - } - } - return result; -} - -// FUNCTION: LEGO1 0x10045ae0 -MxBool LegoStream::IsWriteMode() -{ - return m_mode == LEGOSTREAM_MODE_WRITE; -} - -// FUNCTION: LEGO1 0x10045af0 -MxBool LegoStream::IsReadMode() -{ - return m_mode == LEGOSTREAM_MODE_READ; -} - -// FUNCTION: LEGO1 0x10099080 -LegoMemoryStream::LegoMemoryStream(char* p_buffer) : LegoStream() -{ - m_buffer = p_buffer; - m_offset = 0; -} - -// FUNCTION: LEGO1 0x10099160 -MxResult LegoMemoryStream::Read(void* p_buffer, MxU32 p_size) -{ - memcpy(p_buffer, m_buffer + m_offset, p_size); - m_offset += p_size; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10099190 -MxResult LegoMemoryStream::Write(const void* p_buffer, MxU32 p_size) -{ - memcpy(m_buffer + m_offset, p_buffer, p_size); - m_offset += p_size; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100991c0 -LegoFileStream::LegoFileStream() : LegoStream() -{ - m_hFile = NULL; -} - -// FUNCTION: LEGO1 0x10099250 -LegoFileStream::~LegoFileStream() -{ - if (m_hFile != NULL) - fclose(m_hFile); -} - -// FUNCTION: LEGO1 0x100992c0 -MxResult LegoFileStream::Read(void* p_buffer, MxU32 p_size) -{ - if (m_hFile == NULL) - return FAILURE; - - return (fread(p_buffer, 1, p_size, m_hFile) == p_size) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x10099300 -MxResult LegoFileStream::Write(const void* p_buffer, MxU32 p_size) -{ - if (m_hFile == NULL) - return FAILURE; - - return (fwrite(p_buffer, 1, p_size, m_hFile) == p_size) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x10099340 -MxResult LegoFileStream::Tell(MxU32* p_offset) -{ - if (m_hFile == NULL) - return FAILURE; - - int got = ftell(m_hFile); - if (got == -1) - return FAILURE; - - *p_offset = got; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10099370 -MxResult LegoFileStream::Seek(MxU32 p_offset) -{ - if (m_hFile == NULL) - return FAILURE; - - return (fseek(m_hFile, p_offset, 0) == 0) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x100993a0 -MxResult LegoFileStream::Open(const char* p_filename, OpenFlags p_mode) -{ - char modeString[4]; - - if (m_hFile != NULL) - fclose(m_hFile); - - modeString[0] = '\0'; - if (p_mode & ReadBit) { - m_mode = LEGOSTREAM_MODE_READ; - strcat(modeString, "r"); - } - - if (p_mode & WriteBit) { - if (m_mode != LEGOSTREAM_MODE_READ) - m_mode = LEGOSTREAM_MODE_WRITE; - strcat(modeString, "w"); - } - - if ((p_mode & 4) != 0) - strcat(modeString, "b"); - else - strcat(modeString, "t"); - - return (m_hFile = fopen(p_filename, modeString)) ? SUCCESS : FAILURE; -} - -// FUNCTION: LEGO1 0x100994a0 -MxResult LegoMemoryStream::Tell(MxU32* p_offset) -{ - *p_offset = m_offset; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100994b0 -MxResult LegoMemoryStream::Seek(MxU32 p_offset) -{ - m_offset = p_offset; - return SUCCESS; -} diff --git a/LEGO1/legostream.h b/LEGO1/legostream.h deleted file mode 100644 index 8b0a57c1..00000000 --- a/LEGO1/legostream.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef LEGOSTREAM_H -#define LEGOSTREAM_H - -#include "compat.h" -#include "decomp.h" -#include "mxstring.h" -#include "mxtypes.h" - -#pragma warning(disable : 4237) -#include - -#define LEGOSTREAM_MODE_READ 1 -#define LEGOSTREAM_MODE_WRITE 2 - -class MxVariableTable; - -// VTABLE: LEGO1 0x100d7d80 -class LegoStream { -public: - LegoStream() : m_mode(0) {} - inline virtual ~LegoStream(){}; - - virtual MxResult Read(void* p_buffer, MxU32 p_size) = 0; - virtual MxResult Write(const void* p_buffer, MxU32 p_size) = 0; - virtual MxResult Tell(MxU32* p_offset) = 0; - virtual MxResult Seek(MxU32 p_offset) = 0; - - virtual MxBool IsWriteMode(); - virtual MxBool IsReadMode(); - - enum OpenFlags { - ReadBit = 1, - WriteBit = 2, - BinaryBit = 4, - }; - - static MxResult __stdcall WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName); - static MxS32 __stdcall ReadVariable(LegoStream* p_stream, MxVariableTable* p_to); - -protected: - MxU8 m_mode; -}; - -// VTABLE: LEGO1 0x100db730 -class LegoFileStream : public LegoStream { -public: - LegoFileStream(); - virtual ~LegoFileStream(); - - MxResult Read(void* p_buffer, MxU32 p_size) override; - MxResult Write(const void* p_buffer, MxU32 p_size) override; - MxResult Tell(MxU32* p_offset) override; - MxResult Seek(MxU32 p_offset) override; - - MxResult Open(const char* p_filename, OpenFlags p_mode); - - LegoFileStream* FUN_10006030(MxString p_str); - -private: - FILE* m_hFile; -}; - -// 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; - MxResult Tell(MxU32* p_offset) override; - MxResult Seek(MxU32 p_offset) override; - -private: - char* m_buffer; - MxU32 m_offset; -}; - -#endif // LEGOSTREAM_H diff --git a/LEGO1/legotexturepresenter.cpp b/LEGO1/legotexturepresenter.cpp deleted file mode 100644 index 36a7e243..00000000 --- a/LEGO1/legotexturepresenter.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "legotexturepresenter.h" - -#include "legoomni.h" -#include "legovideomanager.h" - -// FUNCTION: LEGO1 0x1004eb40 -LegoTexturePresenter::~LegoTexturePresenter() -{ - VideoManager()->RemovePresenter(*this); -} - -// FUNCTION: LEGO1 0x1004ebb0 -MxResult LegoTexturePresenter::AddToManager() -{ - VideoManager()->AddPresenter(*this); - return SUCCESS; -} diff --git a/LEGO1/legounksavedatawriter.cpp b/LEGO1/legounksavedatawriter.cpp deleted file mode 100644 index 2e4d1804..00000000 --- a/LEGO1/legounksavedatawriter.cpp +++ /dev/null @@ -1,49 +0,0 @@ - -#include "legounksavedatawriter.h" - -#include "legogamestate.h" -#include "legostream.h" - -DECOMP_SIZE_ASSERT(LegoSaveDataEntry3, 0x108); - -// GLOBAL: LEGO1 0x10104f20 -LegoSaveDataEntry3 g_saveData3[66]; - -// FUNCTION: LEGO1 0x10083310 -MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream* p_stream) -{ - MxResult result = FAILURE; - - // This should probably be a for loop but I can't figure out how to - // make it match as a for loop. - LegoSaveDataEntry3* entry = g_saveData3; - const LegoSaveDataEntry3* end = &g_saveData3[66]; - - while (TRUE) { - if (p_stream->Write(&entry->m_savePart1, 4) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart2, 4) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart3, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_currentFrame, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart5, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart6, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart7, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart8, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart9, 1) != SUCCESS) - break; - if (p_stream->Write(&entry->m_savePart10, 1) != SUCCESS) - break; - if (++entry >= end) { - result = SUCCESS; - break; - } - } - return result; -} diff --git a/LEGO1/legoutil.cpp b/LEGO1/legoutil.cpp deleted file mode 100644 index 42d14dac..00000000 --- a/LEGO1/legoutil.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "legoutil.h" - -#include "mxomni.h" -#include "mxtypes.h" - -#include - -// FUNCTION: LEGO1 0x1003e300 -ExtraActionType MatchActionString(const char* p_str) -{ - ExtraActionType result = ExtraActionType_unknown; - - if (!strcmpi("openram", p_str)) - result = ExtraActionType_openram; - else if (!strcmpi("opendisk", p_str)) - result = ExtraActionType_opendisk; - else if (!strcmpi("close", p_str)) - result = ExtraActionType_close; - else if (!strcmpi("start", p_str)) - result = ExtraActionType_start; - else if (!strcmpi("stop", p_str)) - result = ExtraActionType_stop; - else if (!strcmpi("run", p_str)) - result = ExtraActionType_run; - else if (!strcmpi("exit", p_str)) - result = ExtraActionType_exit; - else if (!strcmpi("enable", p_str)) - result = ExtraActionType_enable; - else if (!strcmpi("disable", p_str)) - result = ExtraActionType_disable; - else if (!strcmpi("notify", p_str)) - result = ExtraActionType_notify; - - return result; -} - -// STUB: LEGO1 0x1003e430 -void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender) -{ -} - -// FUNCTION: LEGO1 0x1003eae0 -void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut) -{ - double calc; - double p; - MxLong hueIndex; - double v9; - double v12; - double v13; - - double sDbl = p_s; - - if (p_s > 0.5f) - calc = (1.0f - p_v) * p_s + p_v; - else - calc = (p_v + 1.0) * sDbl; - if (calc <= 0.0) { - *p_gOut = 0.0f; - *p_bOut = 0.0f; - *p_rOut = 0.0f; - return; - } - p = p_s * 2.0f - calc; - hueIndex = p_h * 6.0; - v9 = (p_h * 6.0 - (float) hueIndex) * ((calc - p) / calc) * calc; - v12 = p + v9; - v13 = calc - v9; - switch (hueIndex) { - case 0: - *p_rOut = calc; - *p_bOut = v12; - *p_gOut = p; - break; - case 1: - *p_rOut = v13; - *p_bOut = calc; - *p_gOut = p; - break; - case 2: - *p_rOut = p; - *p_bOut = calc; - *p_gOut = v12; - break; - case 3: - *p_rOut = p; - *p_bOut = v13; - *p_gOut = calc; - break; - case 4: - *p_rOut = v12; - *p_bOut = p; - *p_gOut = calc; - break; - case 5: - *p_rOut = calc; - *p_bOut = p; - *p_gOut = v13; - break; - case 6: - *p_rOut = calc; - *p_bOut = p; - *p_gOut = v13; - break; - default: - return; - } -} - -// STUB: LEGO1 0x1003ee00 -void FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id) -{ -} - -// STUB: LEGO1 0x1003ef00 -void FUN_1003ef00(MxBool) -{ - // TODO (something related to animation manager) -} - -// FUNCTION: LEGO1 0x1003ef40 -void SetAppCursor(WPARAM p_wparam) -{ - PostMessageA(MxOmni::GetInstance()->GetWindowHandle(), 0x5400, p_wparam, 0); -} - -// STUB: LEGO1 0x1003ef60 -MxBool FUN_1003ef60() -{ - return TRUE; -} diff --git a/LEGO1/legoutil.h b/LEGO1/legoutil.h deleted file mode 100644 index a6351395..00000000 --- a/LEGO1/legoutil.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef LEGOUTIL_H -#define LEGOUTIL_H - -#include "extra.h" -#include "legoentity.h" -#include "mxatomid.h" -#include "mxtypes.h" - -#include - -template -inline T Abs(T p_t) -{ - return p_t < 0 ? -p_t : p_t; -} - -template -inline T Min(T p_t1, T p_t2) -{ - return p_t1 < p_t2 ? p_t1 : p_t2; -} - -template -inline T Max(T p_t1, T p_t2) -{ - return p_t1 > p_t2 ? p_t1 : p_t2; -} - -template -inline void GetScalar(MxU8** p_source, T& p_dest) -{ - p_dest = *(T*) *p_source; - *p_source += sizeof(T); -} - -template -inline T GetScalar(T** p_source) -{ - T val = **p_source; - *p_source += 1; - return val; -} - -template -inline void GetDouble(MxU8** p_source, T& p_dest) -{ - p_dest = *(double*) *p_source; - *p_source += sizeof(double); -} - -template -inline void GetString(MxU8** p_source, const char* p_dest, T* p_obj, void (T::*p_setter)(const char*)) -{ - (p_obj->*p_setter)((char*) *p_source); - *p_source += strlen(p_dest) + 1; -} - -ExtraActionType MatchActionString(const char*); -void InvokeAction(ExtraActionType 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); -void FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); -void FUN_1003ef00(MxBool); -void SetAppCursor(WPARAM p_wparam); -MxBool FUN_1003ef60(); - -#endif // LEGOUTIL_H diff --git a/LEGO1/legovideomanager.cpp b/LEGO1/legovideomanager.cpp deleted file mode 100644 index 167b81a3..00000000 --- a/LEGO1/legovideomanager.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "legovideomanager.h" - -DECOMP_SIZE_ASSERT(LegoVideoManager, 0x590); - -// FUNCTION: LEGO1 0x1007aa20 -LegoVideoManager::LegoVideoManager() -{ - m_unk0x64 = 0; - m_3dManager = NULL; - m_unk0x6c = 0; - m_direct3d = 0; - m_unk0xe6 = FALSE; - memset(m_unk0x78, 0, sizeof(m_unk0x78)); - m_unk0x78[0] = 0x6c; - m_unk0x4e8 = 0; - m_isFullscreenMovie = FALSE; - m_palette = NULL; - m_prefCounter = NULL; - m_cursorMoved = FALSE; - m_cursorX = m_cursorY; - m_cursorYCopy = m_cursorY; - m_cursorXCopy = m_cursorY; - m_unk0x514 = 0; - m_unk0x500 = FALSE; - m_drawFPS = FALSE; - m_unk0x528 = 0; - m_arialFont = NULL; - m_unk0xe5 = FALSE; - m_unk0x554 = 0; - m_initialized = FALSE; -} - -// FUNCTION: LEGO1 0x1007ab40 -LegoVideoManager::~LegoVideoManager() -{ - Destroy(); - delete m_palette; -} - -// FUNCTION: LEGO1 0x1007b5e0 -void LegoVideoManager::Destroy() -{ - // todo: delete m_unk0x512 - // todo: delete m_unk0x258 - if (m_arialFont != NULL) { - DeleteObject(m_arialFont); - m_arialFont = NULL; - } - - // delete m_unk0x64; //TODO: delete d3drm - - delete m_3dManager; - MxVideoManager::Destroy(); - // todo: delete m_unk0x4e8 - delete[] m_prefCounter; -} - -// FUNCTION: LEGO1 0x1007b6a0 -void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) -{ - m_cursorX = p_cursorX; - m_cursorY = p_cursorY; - m_cursorMoved = TRUE; - - if (623 < p_cursorX) - m_cursorX = 623; - - if (463 < p_cursorY) - m_cursorY = 463; -} - -// FUNCTION: LEGO1 0x1007c300 -void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable) -{ - EnableFullScreenMovie(p_enable, TRUE); -} - -// FUNCTION: LEGO1 0x1007c310 -void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) -{ - if (m_isFullscreenMovie != p_enable) { - m_isFullscreenMovie = p_enable; - - if (p_enable) { - m_palette = m_videoParam.GetPalette()->Clone(); - OverrideSkyColor(FALSE); - - m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); - - m_unk0xe4 = FALSE; - m_unk0x500 = TRUE; - } - else { - m_displaySurface->FUN_100ba640(); - m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); - - // restore previous pallete - RealizePalette(m_palette); - delete m_palette; - m_palette = NULL; - - // update region where video used to be - MxRect32 rect( - 0, - 0, - m_videoParam.GetRect().GetRight() - m_videoParam.GetRect().GetLeft(), - m_videoParam.GetRect().GetBottom() - m_videoParam.GetRect().GetTop() - ); - - InvalidateRect(rect); - UpdateRegion(); - OverrideSkyColor(TRUE); - - m_unk0xe4 = TRUE; - m_unk0x500 = FALSE; - } - } - - if (p_enable) { - m_displaySurface->GetVideoParam().Flags().SetF1bit3(p_scale); - } - else { - m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); - } -} - -// FUNCTION: LEGO1 0x1007c440 -void LegoVideoManager::SetSkyColor(float p_red, float p_green, float p_blue) -{ - PALETTEENTRY colorStrucure; - - colorStrucure.peRed = (p_red * 255.0f); - colorStrucure.peGreen = (p_green * 255.0f); - colorStrucure.peBlue = (p_blue * 255.0f); - colorStrucure.peFlags = -124; - m_videoParam.GetPalette()->SetSkyColor(&colorStrucure); - m_videoParam.GetPalette()->SetOverrideSkyColor(TRUE); - - // TODO 3d manager - // m_3dManager->m_pViewport->VTable0x1c(red, green, blue) -} - -// FUNCTION: LEGO1 0x1007c4c0 -void LegoVideoManager::OverrideSkyColor(MxBool p_shouldOverride) -{ - this->m_videoParam.GetPalette()->SetOverrideSkyColor(p_shouldOverride); -} - -// STUB: LEGO1 0x1007c560 -int LegoVideoManager::EnableRMDevice() -{ - // TODO - return 0; -} - -// STUB: LEGO1 0x1007c740 -int LegoVideoManager::DisableRMDevice() -{ - // TODO - return 0; -} diff --git a/LEGO1/legovideomanager.h b/LEGO1/legovideomanager.h deleted file mode 100644 index 11501e2d..00000000 --- a/LEGO1/legovideomanager.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef LEGOVIDEOMANAGER_H -#define LEGOVIDEOMANAGER_H - -#include "decomp.h" -#include "lego3dmanager.h" -#include "mxdirect3d.h" -#include "mxvideomanager.h" - -#include - -// VTABLE: LEGO1 0x100d9c88 -// SIZE 0x590 -class LegoVideoManager : public MxVideoManager { -public: - LegoVideoManager(); - virtual ~LegoVideoManager() override; - - __declspec(dllexport) int EnableRMDevice(); - __declspec(dllexport) int DisableRMDevice(); - void EnableFullScreenMovie(MxBool p_enable); - __declspec(dllexport) void EnableFullScreenMovie(MxBool p_enable, MxBool p_scale); - __declspec(dllexport) void MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY); - - virtual void Destroy() override; // vtable+0x18 - - void SetSkyColor(float p_red, float p_green, float p_blue); - void OverrideSkyColor(MxBool p_shouldOverride); - - 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; } - -private: - undefined4 m_unk0x64; - Lego3DManager* m_3dManager; // 0x68 - undefined4 m_unk0x6c; - undefined4 m_unk0x70; - MxDirect3D* m_direct3d; // 0x74 - undefined4 m_unk0x78[27]; - MxBool m_unk0xe4; - MxBool m_unk0xe5; - MxBool m_unk0xe6; - PALETTEENTRY m_paletteEntries[256]; // 0xe7 - undefined m_padding0x4e7; - undefined4 m_unk0x4e8; - MxBool m_isFullscreenMovie; // 0x4ec - MxPalette* m_palette; // 0x4f0 - LARGE_INTEGER* m_prefCounter; // 0x4f4 - undefined m_padding0x4f4[8]; - MxBool m_unk0x500; - MxBool m_cursorMoved; // 0x501 - MxS32 m_cursorXCopy; // 0x504 - MxS32 m_cursorYCopy; // 0x508 - MxS32 m_cursorX; // 0x50c - MxS32 m_cursorY; // 0x510 - undefined4 m_unk0x514; - undefined m_pad0x518[0x10]; - undefined4 m_unk0x528; - MxBool m_drawFPS; // 0x52c - RECT m_fpsRect; // 0x530 - HFONT m_arialFont; // 0x540 - SIZE m_fpsSize; // 0x544 - undefined m_pad0x54c[8]; - undefined m_unk0x554; - MxBool m_initialized; // 0x555 - undefined m_pad0x556[0x39]; -}; - -#endif // LEGOVIDEOMANAGER_H diff --git a/LEGO1/legoworld.cpp b/LEGO1/legoworld.cpp deleted file mode 100644 index 03139566..00000000 --- a/LEGO1/legoworld.cpp +++ /dev/null @@ -1,128 +0,0 @@ -#include "legoworld.h" - -#include "legoinputmanager.h" -#include "legoomni.h" -#include "mxactionnotificationparam.h" -#include "mxnotificationparam.h" -#include "mxomni.h" -#include "mxticklemanager.h" - -DECOMP_SIZE_ASSERT(LegoWorld, 0xf8); - -// STUB: LEGO1 0x1001ca40 -LegoWorld::LegoWorld() : m_list0x68(TRUE) -{ - // TODO -} - -// FUNCTION: LEGO1 0x1001d670 -MxBool LegoWorld::VTable0x5c() -{ - return FALSE; -} - -// FUNCTION: LEGO1 0x1001d680 -MxBool LegoWorld::VTable0x64() -{ - return FALSE; -} - -// STUB: LEGO1 0x1001dfa0 -LegoWorld::~LegoWorld() -{ - // TODO -} - -// STUB: LEGO1 0x1001e0b0 -MxResult LegoWorld::SetAsCurrentWorld(MxDSObject& p_dsObject) -{ - // TODO - return SUCCESS; -} - -// FUNCTION: LEGO1 0x1001f5e0 -MxLong LegoWorld::Notify(MxParam& p_param) -{ - MxLong ret = 0; - switch (((MxNotificationParam&) p_param).GetNotification()) { - case c_notificationEndAction: { - MxPresenter* presenter = (MxPresenter*) ((MxEndActionNotificationParam&) p_param).GetSender(); - EndAction(presenter); - ret = 1; - break; - } - case c_notificationNewPresenter: - TickleManager()->RegisterClient(this, 100); - break; - } - return ret; -} - -// STUB: LEGO1 0x1001f630 -void LegoWorld::VTable0x54() -{ - // TODO -} - -// STUB: LEGO1 0x1001fc80 -void LegoWorld::FUN_1001fc80(IslePathActor* p_actor) -{ -} - -// STUB: LEGO1 0x10020120 -MxS32 LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) -{ - // TODO - return 0; -} - -// STUB: LEGO1 0x10020220 -void LegoWorld::VTable0x58(MxCore* p_object) -{ - // TODO -} - -// STUB: LEGO1 0x10020f10 -void LegoWorld::EndAction(MxCore* p_object) -{ -} - -// STUB: LEGO1 0x10021a70 -void LegoWorld::VTable0x68(MxBool p_add) -{ - // TODO -} - -// STUB: LEGO1 0x10022080 -MxResult LegoWorld::Tickle() -{ - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10022340 -void LegoWorld::Stop() -{ - TickleManager()->UnregisterClient(this); -} - -// STUB: LEGO1 0x100727e0 -MxBool LegoWorld::FUN_100727e0(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) -{ - return FALSE; -} - -// STUB: LEGO1 0x10072980 -MxBool LegoWorld::FUN_10072980(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) -{ - return FALSE; -} - -// STUB: LEGO1 0x10073400 -void LegoWorld::FUN_10073400() -{ -} - -// STUB: LEGO1 0x10073430 -void LegoWorld::FUN_10073430() -{ -} diff --git a/LEGO1/legoworld.h b/LEGO1/legoworld.h deleted file mode 100644 index fadeea5c..00000000 --- a/LEGO1/legoworld.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef LEGOWORLD_H -#define LEGOWORLD_H - -#include "legocameracontroller.h" -#include "legoentity.h" -#include "legopathcontrollerlist.h" -#include "mxpresenter.h" -#include "mxpresenterlist.h" - -class IslePathActor; -class LegoPathBoundary; - -// VTABLE: LEGO1 0x100d6280 -// SIZE 0xf8 -class LegoWorld : public LegoEntity { -public: - __declspec(dllexport) LegoWorld(); - __declspec(dllexport) virtual ~LegoWorld(); // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x1001d690 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0058 - return "LegoWorld"; - } - - // FUNCTION: LEGO1 0x1001d6a0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - 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 - - inline LegoCameraController* GetCamera() { return m_camera; } - - 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); - void FUN_10073400(); - void FUN_10073430(); - MxS32 GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); - -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[0x26]; // 0xd0 - undefined m_unk0xf6; // 0xf6 - undefined m_unk0xf7; // 0xf7 -}; - -// SYNTHETIC: LEGO1 0x1001eed0 -// MxPresenterListCursor::`scalar deleting destructor' - -// TEMPLATE: LEGO1 0x1001ef40 -// MxPtrListCursor::~MxPtrListCursor - -// SYNTHETIC: LEGO1 0x1001ef90 -// MxListCursor::`scalar deleting destructor' - -// SYNTHETIC: LEGO1 0x1001f000 -// MxPtrListCursor::`scalar deleting destructor' - -// TEMPLATE: LEGO1 0x1001f070 -// MxListCursor::~MxListCursor - -// FUNCTION: LEGO1 0x1001f0c0 -// MxPresenterListCursor::~MxPresenterListCursor - -#endif // LEGOWORLD_H diff --git a/LEGO1/legoworldpresenter.cpp b/LEGO1/legoworldpresenter.cpp deleted file mode 100644 index 9cd12880..00000000 --- a/LEGO1/legoworldpresenter.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "legoworldpresenter.h" - -// GLOBAL: LEGO1 0x100f75d4 -undefined4 g_legoWorldPresenterQuality = 1; - -// FUNCTION: LEGO1 0x100665b0 -void LegoWorldPresenter::configureLegoWorldPresenter(MxS32 p_legoWorldPresenterQuality) -{ - g_legoWorldPresenterQuality = p_legoWorldPresenterQuality; -} - -// FUNCTION: LEGO1 0x100665c0 -LegoWorldPresenter::LegoWorldPresenter() -{ - m_unk0x50 = 50000; -} - -// STUB: LEGO1 0x10066770 -LegoWorldPresenter::~LegoWorldPresenter() -{ - // TODO -} diff --git a/LEGO1/legoworldpresenter.h b/LEGO1/legoworldpresenter.h deleted file mode 100644 index bcae2f5e..00000000 --- a/LEGO1/legoworldpresenter.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef LEGOWORLDPRESENTER_H -#define LEGOWORLDPRESENTER_H - -#include "legoentitypresenter.h" - -// VTABLE: LEGO1 0x100d8ee0 -// SIZE 0x54 -class LegoWorldPresenter : public LegoEntityPresenter { -public: - LegoWorldPresenter(); - virtual ~LegoWorldPresenter() override; // vtable+0x0 - - __declspec(dllexport) static void configureLegoWorldPresenter(MxS32 p_legoWorldPresenterQuality); - - // FUNCTION: LEGO1 0x10066630 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0608 - return "LegoWorldPresenter"; - } - - // FUNCTION: LEGO1 0x10066640 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoWorldPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); - } - -private: - undefined4 m_unk0x50; -}; - -#endif // LEGOWORLDPRESENTER_H diff --git a/LEGO1/library_flic.h b/LEGO1/library_flic.h new file mode 100644 index 00000000..ece2d6f9 --- /dev/null +++ b/LEGO1/library_flic.h @@ -0,0 +1,51 @@ +#ifdef 0 + +// LIBRARY: LEGO1 0x100bd530 +// _FUN_100bd530 + +// LIBRARY: LEGO1 0x100bd580 +// _FUN_100bd580 + +// LIBRARY: LEGO1 0x100bd600 +// _FUN_100bd600 + +// LIBRARY: LEGO1 0x100bd680 +// _FUN_100bd680 + +// LIBRARY: LEGO1 0x100bd6e0 +// _FUN_100bd6e0 + +// LIBRARY: LEGO1 0x100bd760 +// _FUN_100bd760 + +// LIBRARY: LEGO1 0x100bd880 +// _FUN_100bd880 + +// LIBRARY: LEGO1 0x100bd8a0 +// _FUN_100bd8a0 + +// LIBRARY: LEGO1 0x100bd8f0 +// _FUN_100bd8f0 + +// LIBRARY: LEGO1 0x100bd940 +// _FUN_100bd940 + +// LIBRARY: LEGO1 0x100bd960 +// _FUN_100bd960 + +// LIBRARY: LEGO1 0x100bda10 +// _FUN_100bda10 + +// LIBRARY: LEGO1 0x100bdac0 +// _FUN_100bdac0 + +// LIBRARY: LEGO1 0x100bdc00 +// _FUN_100bdc00 + +// LIBRARY: LEGO1 0x100bdc90 +// _FUN_100bdc90 + +// LIBRARY: LEGO1 0x100bdce0 +// _DecodeFLCFrame + +#endif diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h new file mode 100644 index 00000000..259ed919 --- /dev/null +++ b/LEGO1/library_msvc.h @@ -0,0 +1,111 @@ +#ifdef 0 +// For LEGO1 symbols only + +// aka `operator new` +// LIBRARY: LEGO1 0x10086240 +// ??2@YAPAXI@Z + +// aka `operator delete` +// LIBRARY: LEGO1 0x10086260 +// ??3@YAXPAX@Z + +// LIBRARY: LEGO1 0x1008a090 +// _malloc + +// LIBRARY: LEGO1 0x1008a1c0 +// _free + +// LIBRARY: LEGO1 0x1008b020 +// ___CxxFrameHandler + +// LIBRARY: LEGO1 0x1008b400 +// _atol + +// LIBRARY: LEGO1 0x1008b4b0 +// _atoi + +// LIBRARY: LEGO1 0x1008b4c0 +// _strtok + +// LIBRARY: LEGO1 0x1008b5a0 +// _sprintf + +// LIBRARY: LEGO1 0x1008b608 +// __ftol + +// LIBRARY: LEGO1 0x1008b630 +// _srand + +// LIBRARY: LEGO1 0x1008b640 +// _rand + +// LIBRARY: LEGO1 0x1008b680 +// _strncmp + +// LIBRARY: LEGO1 0x1008b730 +// _fprintf + +// LIBRARY: LEGO1 0x1008b670 +// __purecall + +// 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/library_smack.h b/LEGO1/library_smack.h new file mode 100644 index 00000000..2909ebd3 --- /dev/null +++ b/LEGO1/library_smack.h @@ -0,0 +1,18 @@ +#ifdef 0 + +// LIBRARY: LEGO1 0x100cd782 +// _SmackGetSizeTables + +// LIBRARY: LEGO1 0x100cd7e8 +// _SmackDoTables + +// LIBRARY: LEGO1 0x100cda83 +// _SmackDoFrameToBuffer + +// LIBRARY: LEGO1 0x100d052c +// _SmackGetSizeDeltas + +// LIBRARY: LEGO1 0x100d0543 +// _SmackGetRect + +#endif diff --git a/LEGO1/main.cpp b/LEGO1/main.cpp new file mode 100644 index 00000000..260afb24 --- /dev/null +++ b/LEGO1/main.cpp @@ -0,0 +1,7 @@ +#include + +// FUNCTION: LEGO1 0x10091ee0 +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return TRUE; +} diff --git a/LEGO1/motorcycle.cpp b/LEGO1/motorcycle.cpp deleted file mode 100644 index 18fabd8a..00000000 --- a/LEGO1/motorcycle.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "motorcycle.h" - -DECOMP_SIZE_ASSERT(Motorcycle, 0x16c); - -// FUNCTION: LEGO1 0x100357b0 -Motorcycle::Motorcycle() -{ - this->m_unk0x13c = 40.0; - this->m_unk0x150 = 1.75; - this->m_unk0x148 = 1; - this->m_unk0x164 = 1.0; -} diff --git a/LEGO1/motorcycle.h b/LEGO1/motorcycle.h deleted file mode 100644 index a698fcd8..00000000 --- a/LEGO1/motorcycle.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef MOTORCYCLE_H -#define MOTORCYCLE_H - -#include "decomp.h" -#include "islepathactor.h" - -// VTABLE: LEGO1 0x100d7090 -// SIZE 0x16c -class Motorcycle : public IslePathActor { -public: - Motorcycle(); - - // FUNCTION: LEGO1 0x10035840 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f38e8 - return "Motorcycle"; - } - - // 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); - } - -private: - undefined m_unk0x160[4]; - MxFloat m_unk0x164; - undefined m_unk0x168[4]; -}; - -#endif // MOTORCYCLE_H diff --git a/LEGO1/mxactionnotificationparam.cpp b/LEGO1/mxactionnotificationparam.cpp deleted file mode 100644 index b5d84832..00000000 --- a/LEGO1/mxactionnotificationparam.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "mxactionnotificationparam.h" - -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() -{ - return new MxEndActionNotificationParam(c_notificationStartAction, this->m_sender, this->m_action, this->m_realloc); -} - -// FUNCTION: LEGO1 0x100b04f0 -MxNotificationParam* MxType4NotificationParam::Clone() -{ - return new MxType4NotificationParam(this->m_sender, this->m_action, this->m_unk0x14); -} diff --git a/LEGO1/mxatomidcounter.h b/LEGO1/mxatomidcounter.h deleted file mode 100644 index 8fb5ae97..00000000 --- a/LEGO1/mxatomidcounter.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef MXATOMIDCOUNTER_H -#define MXATOMIDCOUNTER_H - -#include "mxstl/stlcompat.h" -#include "mxstring.h" - -// Counts the number of existing MxAtomId objects based -// on the matching char* string. A seems fit for purpose here: -// We have an MxString as a key and MxU16 as the value. -// And yet a is the best match. The malloc in MxOmni::Create -// for the _Nil node asks for more bytes than a regular node if a -// is used, but all nodes are 20 bytes wide with a . -// Also: the increment/decrement methods suggest a custom type was used -// for the combined key_value_pair, which doesn't seem possible with . - -// SIZE: 0x14 (including padding) -class MxAtomIdCounter { -public: - // always inlined - MxAtomIdCounter(const char* p_str) - { - m_key = p_str; - m_value = 0; - } - - void Inc(); - void Dec(); - inline MxString* GetKey() { return &m_key; }; - inline MxU16 GetValue() { return m_value; }; - -private: - MxString m_key; - MxU16 m_value; -}; - -struct MxAtomIdCounterCompare { - // FUNCTION: LEGO1 0x100ad120 - int operator()(MxAtomIdCounter* const& p_val0, MxAtomIdCounter* const& p_val1) const - { - return strcmp(p_val0->GetKey()->GetData(), p_val1->GetKey()->GetData()) > 0; - } -}; - -class MxAtomIdCounterSet : public set {}; - -#endif // MXATOMIDCOUNTER_H diff --git a/LEGO1/mxaudiomanager.h b/LEGO1/mxaudiomanager.h deleted file mode 100644 index c910a493..00000000 --- a/LEGO1/mxaudiomanager.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MXAUDIOMANAGER_H -#define MXAUDIOMANAGER_H - -#include "decomp.h" -#include "mxmediamanager.h" - -// VTABLE: LEGO1 0x100dc6e0 -class MxAudioManager : public MxMediaManager { -public: - MxAudioManager(); - virtual ~MxAudioManager() override; - - 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 - -private: - void Destroy(MxBool p_fromDestructor); - - static MxS32 g_count; - -protected: - void Init(); - - MxS32 m_volume; // 0x2c -}; - -#endif // MXAUDIOMANAGER_H diff --git a/LEGO1/mxaudiopresenter.cpp b/LEGO1/mxaudiopresenter.cpp deleted file mode 100644 index 1ef74dea..00000000 --- a/LEGO1/mxaudiopresenter.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "mxaudiopresenter.h" - -#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/mxaudiopresenter.h b/LEGO1/mxaudiopresenter.h deleted file mode 100644 index f1d207e1..00000000 --- a/LEGO1/mxaudiopresenter.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MXAUDIOPRESENTER_H -#define MXAUDIOPRESENTER_H - -#include "decomp.h" -#include "mxmediapresenter.h" - -// VTABLE: LEGO1 0x100d4c70 -// SIZE 0x54 -class MxAudioPresenter : public MxMediaPresenter { -public: - MxAudioPresenter() { m_volume = 100; } - - // FUNCTION: LEGO1 0x1000d280 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f078c - return "MxAudioPresenter"; - } - - // FUNCTION: LEGO1 0x1000d290 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxAudioPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); - } - - virtual MxS32 GetVolume(); // vtable+0x5c - virtual void SetVolume(MxS32 p_volume); // vtable+0x60 - -protected: - MxS32 m_volume; -}; - -#endif // MXAUDIOPRESENTER_H diff --git a/LEGO1/mxbitmap.h b/LEGO1/mxbitmap.h deleted file mode 100644 index b87bcdcf..00000000 --- a/LEGO1/mxbitmap.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef MXBITMAP_H -#define MXBITMAP_H - -#include "mxcore.h" -#include "mxpalette.h" -#include "mxtypes.h" - -#include - -// The stock BITMAPINFO struct from wingdi.h only makes room for one color -// in the palette. It seems like the expectation (if you use the struct) -// is to malloc as much as you actually need, and then index into the array -// anyway even though its stated size is [1]. -// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfo -// In our case, the size 0x428 is used frequently, which matches -// a 40-byte header plus 256 colors, so just use that as our template. - -// SIZE 0x428 -struct MxBITMAPINFO { - BITMAPINFOHEADER m_bmiHeader; - RGBQUAD m_bmiColors[256]; -}; - -// Non-standard value for biCompression in the BITMAPINFOHEADER struct. -// By default, uncompressed bitmaps (BI_RGB) are stored in bottom-up order. -// You can specify that the bitmap has top-down order instead by providing -// a negative number for biHeight. It could be that Mindscape decided on a -// belt & suspenders approach here. -#define BI_RGB_TOPDOWN 0x10 - -// SIZE 0x20 -// VTABLE: LEGO1 0x100dc7b0 -class MxBitmap : public MxCore { -public: - __declspec(dllexport) MxBitmap(); - __declspec(dllexport) virtual ~MxBitmap(); // vtable+00 - - virtual MxResult ImportBitmap(MxBitmap* p_bitmap); // vtable+14 - virtual MxResult ImportBitmapInfo(MxBITMAPINFO* p_info); // vtable+18 - virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool); // vtable+1c - virtual MxResult LoadFile(HANDLE p_handle); // vtable+20 - __declspec(dllexport) virtual MxLong Read(const char* p_filename); // vtable+24 - virtual int VTable0x28(int); - 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 - virtual void ImportPalette(MxPalette* p_palette); // vtable+38 - virtual MxResult SetBitDepth(MxBool); // vtable+3c - virtual MxResult StretchBits( - HDC p_hdc, - MxS32 p_xSrc, - MxS32 p_ySrc, - MxS32 p_xDest, - MxS32 p_yDest, - MxS32 p_destWidth, - MxS32 p_destHeight - ); // vtable+40 - - inline BITMAPINFOHEADER* GetBmiHeader() const { return m_bmiHeader; } - inline MxLong GetBmiWidth() const { return m_bmiHeader->biWidth; } - inline MxLong GetBmiStride() const { return ((m_bmiHeader->biWidth + 3) & -4); } - inline MxLong GetBmiHeight() const { return m_bmiHeader->biHeight; } - inline MxLong GetBmiHeightAbs() const - { - return m_bmiHeader->biHeight > 0 ? m_bmiHeader->biHeight : -m_bmiHeader->biHeight; - } - inline MxU8* GetBitmapData() const { return m_data; } - inline MxBITMAPINFO* GetBitmapInfo() const { return m_info; } - -private: - MxResult ImportColorsToPalette(RGBQUAD*, MxPalette*); - - MxBITMAPINFO* m_info; // 0x8 - BITMAPINFOHEADER* m_bmiHeader; // 0xc - RGBQUAD* m_paletteData; // 0x10 - MxU8* m_data; // 0x14 - MxBool m_isHighColor; // 0x18 - MxPalette* m_palette; // 0x1c -}; - -#endif // MXBITMAP_H diff --git a/LEGO1/mxcontrolpresenter.cpp b/LEGO1/mxcontrolpresenter.cpp deleted file mode 100644 index 47e8a720..00000000 --- a/LEGO1/mxcontrolpresenter.cpp +++ /dev/null @@ -1,114 +0,0 @@ -#include "mxcontrolpresenter.h" - -#include "legoomni.h" -#include "mxticklemanager.h" - -DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) - -// FUNCTION: LEGO1 0x10043f50 -MxControlPresenter::MxControlPresenter() -{ - this->m_unk0x4c = 0; - this->m_unk0x4e = -1; - this->m_unk0x50 = FALSE; - this->m_unk0x52 = 0; - this->m_unk0x58 = 0; - this->m_unk0x54 = 0; -} - -// FUNCTION: LEGO1 0x10043fd0 -void MxControlPresenter::RepeatingTickle() -{ - // empty -} - -// FUNCTION: LEGO1 0x10043fe0 -MxBool MxControlPresenter::VTable0x64(undefined4 p_undefined) -{ - return m_unk0x50; -} - -// FUNCTION: LEGO1 0x10043ff0 -void MxControlPresenter::VTable0x68(MxBool p_undefined) -{ - m_unk0x50 = p_undefined; -} - -// FUNCTION: LEGO1 0x10044110 -MxControlPresenter::~MxControlPresenter() -{ - if (m_unk0x58) - delete m_unk0x58; -} - -// FUNCTION: LEGO1 0x10044180 -MxResult MxControlPresenter::AddToManager() -{ - m_unk0x4e = 0; - return SUCCESS; -} - -// STUB: LEGO1 0x10044190 -MxResult MxControlPresenter::StartAction(MxStreamController*, MxDSAction*) -{ - // TODO - return SUCCESS; -} - -// FUNCTION: LEGO1 0x10044260 -void MxControlPresenter::EndAction() -{ - if (m_action) { - m_unk0x50 = TRUE; - MxCompositePresenter::EndAction(); - } -} - -// STUB: LEGO1 0x10044270 -MxBool MxControlPresenter::FUN_10044270(undefined4, undefined4, undefined4*) -{ - // TODO - return TRUE; -} - -// STUB: LEGO1 0x10044480 -MxBool MxControlPresenter::FUN_10044480(undefined4, undefined4*) -{ - // TODO - return TRUE; -} - -// STUB: LEGO1 0x10044540 -void MxControlPresenter::FUN_10044540(undefined2) -{ - // TODO -} - -// FUNCTION: LEGO1 0x10044610 -void MxControlPresenter::ReadyTickle() -{ - MxPresenter::ParseExtra(); - TickleManager()->UnregisterClient(this); - - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; -} - -// STUB: LEGO1 0x10044640 -void MxControlPresenter::ParseExtra() -{ - // TODO -} - -// STUB: LEGO1 0x10044820 -void MxControlPresenter::Enable(MxBool p_enable) -{ - // TODO -} - -// STUB: LEGO1 0x100448a0 -MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState) -{ - // TODO - return TRUE; -} diff --git a/LEGO1/mxcontrolpresenter.h b/LEGO1/mxcontrolpresenter.h deleted file mode 100644 index 515af808..00000000 --- a/LEGO1/mxcontrolpresenter.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef MXCONTROLPRESENTER_H -#define MXCONTROLPRESENTER_H - -#include "decomp.h" -#include "mxcompositepresenter.h" - -// VTABLE: LEGO1 0x100d7b88 -// SIZE 0x5c -class MxControlPresenter : public MxCompositePresenter { -public: - MxControlPresenter(); - virtual ~MxControlPresenter() override; - - // FUNCTION: LEGO1 0x10044000 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0514 - return "MxControlPresenter"; - } - - // FUNCTION: LEGO1 0x10044010 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxControlPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); - } - - virtual void ReadyTickle() override; // vtable+0x18 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual MxBool VTable0x64(undefined4 p_undefined) override; // vtable+0x64 - virtual void VTable0x68(MxBool p_undefined); // vtable+0x68 - -private: - MxBool FUN_10044270(undefined4, undefined4, undefined4*); - MxBool FUN_10044480(undefined4, undefined4*); - void FUN_10044540(undefined2); - - undefined2 m_unk0x4c; // 0x4c - MxS16 m_unk0x4e; // 0x4e - MxBool m_unk0x50; // 0x50 - undefined2 m_unk0x52; // 0x52 - undefined2 m_unk0x54; // 0x54 - undefined4* m_unk0x58; // 0x58 -}; - -// SYNTHETIC: LEGO1 0x100440f0 -// MxControlPresenter::`scalar deleting destructor' - -#endif // MXCONTROLPRESENTER_H diff --git a/LEGO1/mxdirect3d.cpp b/LEGO1/mxdirect3d.cpp deleted file mode 100644 index 58a982b3..00000000 --- a/LEGO1/mxdirect3d.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include "mxdirect3d.h" - -#include // for vsprintf - -DECOMP_SIZE_ASSERT(MxDirect3D, 0x894); -DECOMP_SIZE_ASSERT(MxDeviceModeFinder, 0xe4); -DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x198); - -// FUNCTION: LEGO1 0x1009b0a0 -MxDirect3D::MxDirect3D() -{ - this->m_pDirect3d = NULL; - this->m_pDirect3dDevice = NULL; - this->m_unk0x88c = NULL; - this->m_pDeviceModeFinder = NULL; -} - -// FUNCTION: LEGO1 0x1009b140 -MxDirect3D::~MxDirect3D() -{ - Destroy(); -} - -// FUNCTION: LEGO1 0x1009b1a0 -BOOL MxDirect3D::Create( - HWND hWnd, - BOOL fullscreen_1, - BOOL surface_fullscreen, - BOOL onlySystemMemory, - int width, - int height, - int bpp, - const PALETTEENTRY* pPaletteEntries, - int paletteEntryCount -) -{ - BOOL success = FALSE; - - BOOL ret = MxDirectDraw::Create( - hWnd, - fullscreen_1, - surface_fullscreen, - onlySystemMemory, - width, - height, - bpp, - pPaletteEntries, - paletteEntryCount - ); - - if (ret && CreateIDirect3D() && D3DSetMode()) - success = TRUE; - - if (!success) - FUN_1009d920(); - - return success; -} - -// FUNCTION: LEGO1 0x1009b210 -void MxDirect3D::Destroy() -{ - if (this->m_pDirect3dDevice) { - this->m_pDirect3dDevice->Release(); - this->m_pDirect3dDevice = NULL; - } - - if (this->m_pDirect3d) { - this->m_pDirect3d->Release(); - this->m_pDirect3d = NULL; - } - - if (this->m_pDeviceModeFinder) { - delete m_pDeviceModeFinder; - this->m_pDeviceModeFinder = NULL; - } - - // This should get deleted by MxDirectDraw::Destroy - if (m_pCurrentDeviceModesList) { - // delete m_pCurrentDeviceModesList; // missing? - m_pCurrentDeviceModesList = NULL; - } - - MxDirectDraw::Destroy(); -} - -// FUNCTION: LEGO1 0x1009b290 -void MxDirect3D::Clear() -{ - if (this->m_pDirect3dDevice) { - this->m_pDirect3dDevice->Release(); - this->m_pDirect3dDevice = NULL; - } - if (this->m_pDirect3d) { - this->m_pDirect3d->Release(); - this->m_pDirect3d = NULL; - } - MxDirectDraw::DestroyButNotDirectDraw(); -} - -// FUNCTION: LEGO1 0x1009b2d0 -BOOL MxDirect3D::CreateIDirect3D() -{ - MxResult ret = IDirect3D_QueryInterface(m_pDirectDraw, IID_IDirect3D2, (LPVOID*) &m_pDirect3d); - - if (ret) { - Error("Creation of IDirect3D failed", ret); - return FALSE; - } - - return TRUE; -} - -// STUB: LEGO1 0x1009b310 -BOOL MxDirect3D::D3DSetMode() -{ - // TODO - // if (m_pDeviceModeFinder) - Error("This device cannot support the current display mode", 0); - OutputDebugString("MxDirect3D::D3DSetMode() front lock failed\n"); - OutputDebugString("MxDirect3D::D3DSetMode() back lock failed\n"); - return TRUE; -} - -// FUNCTION: LEGO1 0x1009b8b0 -MxDeviceModeFinder::MxDeviceModeFinder() -{ - memset(this, 0, sizeof(*this)); -} - -// FUNCTION: LEGO1 0x1009b8d0 -MxDeviceModeFinder::~MxDeviceModeFinder() -{ - if (m_deviceInfo) { - delete m_deviceInfo; - m_deviceInfo = NULL; - } -} - -// STUB: LEGO1 0x1009c070 -BOOL MxDeviceEnumerate::FUN_1009c070() -{ - // TODO - // HRESULT ret = DirectDrawCreate(); - HRESULT ret = 0; - if (ret) { - MxDirect3D::BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(ret)); - } - // IDirect3D2_EnumDevices - return TRUE; -} - -// FUNCTION: LEGO1 0x1009c4c0 -void MxDirect3D::BuildErrorString(const char* p_format, ...) -{ - va_list args; - char buf[512]; - - va_start(args, p_format); - vsprintf(buf, p_format, args); - va_end(args); - - OutputDebugString(buf); -} - -// FUNCTION: LEGO1 0x1009c6c0 -MxResult MxDeviceEnumerate::DoEnumerate() -{ - // TODO: what does ECX refer to in this context? - if (m_unk0x010) - return FAILURE; - - HRESULT ret = DirectDrawEnumerate(EnumerateCallback, this); - if (ret) { - MxDirect3D::BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); - return FAILURE; - } - - m_unk0x010 = TRUE; - return SUCCESS; -} - -// STUB: LEGO1 0x1009c710 -BOOL FAR PASCAL EnumerateCallback(GUID FAR*, LPSTR, LPSTR, LPVOID) -{ - // TODO - return FALSE; -} - -// STUB: LEGO1 0x1009c730 -const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) -{ - // TODO: This is a list of error messages, similar to the function in - // MxDirectDraw, except that this one now contains the Direct3D errors. - // Probably just copied from a sample file in the dx5 sdk. - return ""; -} diff --git a/LEGO1/mxdirect3d.h b/LEGO1/mxdirect3d.h deleted file mode 100644 index 34178023..00000000 --- a/LEGO1/mxdirect3d.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef MXDIRECT3D_H -#define MXDIRECT3D_H - -#include "decomp.h" -#include "mxdirectdraw.h" -#include "mxtypes.h" - -#include - -// SIZE 0xe4 -class MxDeviceModeFinder { -public: - MxDeviceModeFinder(); - ~MxDeviceModeFinder(); - - undefined4 m_pad[56]; - MxDirectDraw::DeviceModesInfo* m_deviceInfo; // +0xe0 -}; - -// VTABLE: LEGO1 0x100db814 -// or is it 0x100d9cc8? -// SIZE 0x198 -class MxDeviceEnumerate { -public: - MxDeviceEnumerate(); - virtual MxResult DoEnumerate(); - - BOOL FUN_1009c070(); - - const char* EnumerateErrorToString(HRESULT p_error); - - undefined4 m_unk0x004; - undefined4 m_unk0x008; - undefined4 m_unk0x00c; - MxBool m_unk0x010; // +0x10 - - undefined4 m_unk0x014[97]; -}; - -// VTABLE: LEGO1 0x100db800 -// SIZE 0x894 -class MxDirect3D : public MxDirectDraw { -public: - MxDirect3D(); - - void Clear(); - inline MxDeviceModeFinder* GetDeviceModeFinder() { return this->m_pDeviceModeFinder; }; - - virtual ~MxDirect3D(); - virtual BOOL Create( - HWND hWnd, - BOOL fullscreen_1, - BOOL surface_fullscreen, - BOOL onlySystemMemory, - int width, - int height, - int bpp, - const PALETTEENTRY* pPaletteEntries, - int paletteEntryCount - ); - virtual void Destroy(); - - BOOL CreateIDirect3D(); - BOOL D3DSetMode(); - - static void BuildErrorString(const char*, ...); - -private: - MxDeviceModeFinder* m_pDeviceModeFinder; // +0x880 - IDirect3D* m_pDirect3d; // +0x884 - IDirect3DDevice* m_pDirect3dDevice; - undefined4 m_unk0x88c; - undefined4 m_unk0x890; -}; - -BOOL FAR PASCAL EnumerateCallback(GUID FAR*, LPSTR, LPSTR, LPVOID); - -#endif // MXDIRECT3D_H diff --git a/LEGO1/mxdirectdraw.h b/LEGO1/mxdirectdraw.h deleted file mode 100644 index 8c51b220..00000000 --- a/LEGO1/mxdirectdraw.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef MXDIRECTDRAW_H -#define MXDIRECTDRAW_H - -#include "mxtypes.h" - -#include -#include - -// VTABLE: LEGO1 0x100db818 -// SIZE 0x880 -class MxDirectDraw { -public: - typedef void (*ErrorHandler)(const char*, HRESULT, void*); - - // size 0x0c - struct Mode { - MxS32 m_width; - MxS32 m_height; - MxS32 m_bitsPerPixel; - - MxS32 operator==(const Mode& p_mode) const - { - return ( - (m_width == p_mode.m_width) && (m_height == p_mode.m_height) && - (m_bitsPerPixel == p_mode.m_bitsPerPixel) - ); - } - }; - - // SIZE 0x17c - struct DeviceModesInfo { - GUID* m_guid; - Mode* m_modeArray; - MxS32 m_count; - DDCAPS m_ddcaps; - void* m_unk0x178; - - DeviceModesInfo(); - ~DeviceModesInfo(); - }; - -protected: - BOOL m_bOnlySoftRender; - BOOL m_bFlipSurfaces; - IDirectDraw* m_pDirectDraw; - IDirectDrawSurface* m_pFrontBuffer; - IDirectDrawSurface* m_pBackBuffer; - IDirectDrawSurface* m_pZBuffer; - IDirectDrawSurface* m_pText1Surface; - IDirectDrawSurface* m_pText2Surface; - IDirectDrawClipper* m_pClipper; - IDirectDrawPalette* m_pPalette; - PALETTEENTRY m_paletteEntries[256]; - PALETTEENTRY m_originalPaletteEntries[256]; - SIZE m_text1SizeOnSurface; - SIZE m_text2SizeOnSurface; - HWND m_hWndMain; - HFONT m_hFont; - BOOL m_bIgnoreWMSIZE; - BOOL m_bPrimaryPalettized; - BOOL m_bFullScreen; - void* m_unk0x850; - BOOL m_bOnlySystemMemory; - BOOL m_bIsOnPrimaryDevice; - ErrorHandler m_pErrorHandler; - ErrorHandler m_pFatalErrorHandler; - void* m_pErrorHandlerArg; - void* m_pFatalErrorHandlerArg; - int m_pauseCount; - DeviceModesInfo* m_pCurrentDeviceModesList; - Mode m_currentMode; - -public: - __declspec(dllexport) int FlipToGDISurface(); - __declspec(dllexport) static int GetPrimaryBitDepth(); - __declspec(dllexport) int Pause(int); - - MxDirectDraw(); - - virtual ~MxDirectDraw(); - virtual BOOL Create( - HWND hWnd, - BOOL fullscreen_1, - BOOL surface_fullscreen, - BOOL onlySystemMemory, - int width, - int height, - int bpp, - const PALETTEENTRY* pPaletteEntries, - int paletteEntryCount - ); - virtual void Destroy(); - virtual void DestroyButNotDirectDraw(); - virtual const char* ErrorToString(HRESULT p_error); - -protected: - BOOL CacheOriginalPaletteEntries(); - HRESULT CreateDDSurface(LPDDSURFACEDESC a2, LPDIRECTDRAWSURFACE* a3, IUnknown* a4); - BOOL CreateTextSurfaces(); - BOOL CreateZBuffer(DWORD memorytype, DWORD depth); - BOOL DDCreateSurfaces(); - BOOL DDInit(BOOL fullscreen); - BOOL DDSetMode(int width, int height, int bpp); - void Error(const char* p_message, MxS32 p_error); - - BOOL GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf); - BOOL IsSupportedMode(int width, int height, int bpp); - BOOL RecreateDirectDraw(GUID** a2); - BOOL RestoreOriginalPaletteEntries(); - BOOL RestorePaletteEntries(); - BOOL RestoreSurfaces(); - BOOL SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int paletteEntryCount, BOOL fullscreen); - BOOL TextToTextSurface(const char* text, IDirectDrawSurface* pSurface, SIZE& textSizeOnSurface); - BOOL TextToTextSurface1(const char* text); - BOOL TextToTextSurface2(const char* lpString); - void FUN_1009e020(); - void FUN_1009d920(); -}; - -#endif // MXDIRECTDRAW_H diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp new file mode 100644 index 00000000..a224158b --- /dev/null +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -0,0 +1,845 @@ +#include "mxdirect3d.h" + +#include // for vsprintf + +DECOMP_SIZE_ASSERT(MxAssignedDevice, 0xe4); +DECOMP_SIZE_ASSERT(MxDirect3D, 0x894); +DECOMP_SIZE_ASSERT(MxDevice, 0x1a4); +DECOMP_SIZE_ASSERT(MxDisplayMode, 0x0c); +DECOMP_SIZE_ASSERT(MxDriver, 0x190); +DECOMP_SIZE_ASSERT(MxDeviceEnumerate, 0x14); + +// FUNCTION: LEGO1 0x1009b0a0 +MxDirect3D::MxDirect3D() +{ + this->m_pDirect3d = NULL; + this->m_pDirect3dDevice = NULL; + this->m_unk0x88c = 0; + this->m_assignedDevice = NULL; +} + +// FUNCTION: LEGO1 0x1009b140 +MxDirect3D::~MxDirect3D() +{ + Destroy(); +} + +// FUNCTION: LEGO1 0x1009b1a0 +BOOL MxDirect3D::Create( + HWND hWnd, + BOOL fullscreen_1, + BOOL surface_fullscreen, + BOOL onlySystemMemory, + int width, + int height, + int bpp, + const PALETTEENTRY* pPaletteEntries, + int paletteEntryCount +) +{ + BOOL success = FALSE; + BOOL ret = MxDirectDraw::Create( + hWnd, + fullscreen_1, + surface_fullscreen, + onlySystemMemory, + width, + height, + bpp, + pPaletteEntries, + paletteEntryCount + ); + + if (ret && CreateIDirect3D() && D3DSetMode()) { + success = TRUE; + } + + if (!success) { + FUN_1009d920(); + } + + return success; +} + +// FUNCTION: LEGO1 0x1009b210 +void MxDirect3D::Destroy() +{ + if (this->m_pDirect3dDevice) { + this->m_pDirect3dDevice->Release(); + this->m_pDirect3dDevice = NULL; + } + + if (this->m_pDirect3d) { + this->m_pDirect3d->Release(); + this->m_pDirect3d = NULL; + } + + if (this->m_assignedDevice) { + delete m_assignedDevice; + this->m_assignedDevice = NULL; + } + + if (m_pCurrentDeviceModesList) { + m_pCurrentDeviceModesList = NULL; + } + + MxDirectDraw::Destroy(); +} + +// FUNCTION: LEGO1 0x1009b290 +void MxDirect3D::DestroyButNotDirectDraw() +{ + if (this->m_pDirect3dDevice) { + this->m_pDirect3dDevice->Release(); + this->m_pDirect3dDevice = NULL; + } + if (this->m_pDirect3d) { + this->m_pDirect3d->Release(); + this->m_pDirect3d = NULL; + } + MxDirectDraw::DestroyButNotDirectDraw(); +} + +// FUNCTION: LEGO1 0x1009b2d0 +BOOL MxDirect3D::CreateIDirect3D() +{ + HRESULT ret = IDirect3D_QueryInterface(m_pDirectDraw, IID_IDirect3D2, (LPVOID*) &m_pDirect3d); + + if (ret) { + Error("Creation of IDirect3D failed", ret); + return FALSE; + } + + return TRUE; +} + +// FUNCTION: LEGO1 0x1009b310 +BOOL MxDirect3D::D3DSetMode() +{ + 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; + } + + if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + m_unk0x88c = FALSE; + } + else { + m_unk0x88c = TRUE; + } + + DWORD bitDepth = GetZBufferBitDepth(m_assignedDevice); + if (!CreateZBuffer(DDSCAPS_VIDEOMEMORY, bitDepth)) { + return FALSE; + } + } + else { + if (m_assignedDevice->m_desc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) { + m_unk0x88c = FALSE; + } + else { + m_unk0x88c = TRUE; + } + + DWORD bitDepth = GetZBufferBitDepth(m_assignedDevice); + if (!CreateZBuffer(DDSCAPS_SYSTEMMEMORY, bitDepth)) { + return FALSE; + } + } + + HRESULT result = m_pDirect3d->CreateDevice(m_assignedDevice->m_guid, m_pBackBuffer, &m_pDirect3dDevice); + + if (result != DD_OK) { + Error("Create D3D device failed", result); + return FALSE; + } + + MxDirectDraw::Mode mode = m_currentMode; + + if (m_bFullScreen && !IsSupportedMode(mode.width, mode.height, mode.bitsPerPixel)) { + Error("This device cannot support the current display mode", DDERR_GENERIC); + return FALSE; + } + + LPDIRECTDRAWSURFACE frontBuffer = m_pFrontBuffer; + LPDIRECTDRAWSURFACE backBuffer = m_pBackBuffer; + + DDSURFACEDESC desc; + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + + if (backBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { + unsigned char* surface = (unsigned char*) desc.lpSurface; + + for (int i = mode.height; i > 0; i--) { + memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8); + surface += desc.lPitch; + } + + backBuffer->Unlock(desc.lpSurface); + } + else { + OutputDebugString("MxDirect3D::D3DSetMode() back lock failed\n"); + } + + if (m_bFullScreen) { + memset(&desc, 0, sizeof(desc)); + desc.dwSize = sizeof(desc); + + if (frontBuffer->Lock(NULL, &desc, DDLOCK_WAIT, NULL) == DD_OK) { + unsigned char* surface = (unsigned char*) desc.lpSurface; + + for (int i = mode.height; i > 0; i--) { + memset(surface, 0, mode.width * desc.ddpfPixelFormat.dwRGBBitCount / 8); + surface += desc.lPitch; + } + + frontBuffer->Unlock(desc.lpSurface); + } + else { + OutputDebugString("MxDirect3D::D3DSetMode() front lock failed\n"); + } + } + + return TRUE; +} + +// FUNCTION: LEGO1 0x1009b5a0 +DWORD MxDirect3D::GetZBufferBitDepth(MxAssignedDevice* p_assignedDevice) +{ + DWORD bitDepth; + + if (p_assignedDevice->m_desc.dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH) { + bitDepth = p_assignedDevice->m_desc.dwDeviceZBufferBitDepth; + } + else { + bitDepth = 0; + } + + if (bitDepth & DDBD_32) { + return 32; + } + if (bitDepth & DDBD_24) { + return 24; + } + if (bitDepth & DDBD_16) { + return 16; + } + if (bitDepth & DDBD_8) { + return 8; + } + + return -1; +} + +// FUNCTION: LEGO1 0x1009b5f0 +BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, MxDevice* p_device) +{ + if (m_assignedDevice) { + delete m_assignedDevice; + m_assignedDevice = NULL; + m_pCurrentDeviceModesList = NULL; + } + + MxAssignedDevice* assignedDevice = new MxAssignedDevice; + int i = 0; + + for (list::iterator it = p_deviceEnumerate.m_list.begin(); it != p_deviceEnumerate.m_list.end(); it++) { + MxDriver& driver = *it; + + if (&driver == p_driver) { + assignedDevice->m_deviceInfo = new MxDirectDraw::DeviceModesInfo; + + if (driver.m_guid) { + assignedDevice->m_deviceInfo->m_guid = new GUID; + memcpy(assignedDevice->m_deviceInfo->m_guid, driver.m_guid, sizeof(GUID)); + } + + assignedDevice->m_deviceInfo->m_count = driver.m_displayModes.size(); + + if (assignedDevice->m_deviceInfo->m_count > 0) { + assignedDevice->m_deviceInfo->m_modeArray = + new MxDirectDraw::Mode[assignedDevice->m_deviceInfo->m_count]; + + int j = 0; + for (list::iterator it2 = driver.m_displayModes.begin(); + it2 != driver.m_displayModes.end(); + it2++) { + assignedDevice->m_deviceInfo->m_modeArray[j].width = (*it2).m_width; + assignedDevice->m_deviceInfo->m_modeArray[j].height = (*it2).m_height; + assignedDevice->m_deviceInfo->m_modeArray[j].bitsPerPixel = (*it2).m_bitsPerPixel; + j++; + } + } + + memcpy( + &assignedDevice->m_deviceInfo->m_ddcaps, + &driver.m_ddCaps, + sizeof(assignedDevice->m_deviceInfo->m_ddcaps) + ); + + if (i == 0) { + assignedDevice->m_flags |= MxAssignedDevice::c_primaryDevice; + } + + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + MxDevice& device = *it2; + if (&device != p_device) { + continue; + } + + memcpy(&assignedDevice->m_guid, device.m_guid, sizeof(assignedDevice->m_guid)); + + D3DDEVICEDESC* desc; + if (device.m_HWDesc.dcmColorModel) { + assignedDevice->m_flags |= MxAssignedDevice::c_hardwareMode; + desc = &device.m_HWDesc; + } + else { + desc = &device.m_HELDesc; + } + + memcpy(&assignedDevice->m_desc, desc, sizeof(assignedDevice->m_desc)); + m_assignedDevice = assignedDevice; + m_pCurrentDeviceModesList = assignedDevice->m_deviceInfo; + break; + } + } + + i++; + } + + if (!m_assignedDevice) { + delete assignedDevice; + return FALSE; + } + + return TRUE; +} + +// FUNCTION: LEGO1 0x1009b8b0 +MxAssignedDevice::MxAssignedDevice() +{ + memset(this, 0, sizeof(*this)); +} + +// FUNCTION: LEGO1 0x1009b8d0 +MxAssignedDevice::~MxAssignedDevice() +{ + if (m_deviceInfo) { + delete m_deviceInfo; + m_deviceInfo = NULL; + } +} + +// FUNCTION: LEGO1 0x1009ba80 +MxDriver::MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) +{ + m_guid = NULL; + m_driverDesc = NULL; + m_driverName = NULL; + memset(&m_ddCaps, 0, sizeof(m_ddCaps)); + + Init(p_guid, p_driverDesc, p_driverName); +} + +// FUNCTION: LEGO1 0x1009bb80 +MxDriver::~MxDriver() +{ + if (m_guid) { + delete m_guid; + } + if (m_driverDesc) { + delete[] m_driverDesc; + } + if (m_driverName) { + delete[] m_driverName; + } +} + +// FUNCTION: LEGO1 0x1009bc30 +void MxDriver::Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) +{ + if (m_driverDesc) { + delete[] m_driverDesc; + m_driverDesc = NULL; + } + + if (m_driverName) { + delete[] m_driverName; + m_driverName = NULL; + } + + if (p_guid) { + m_guid = new GUID; + memcpy(m_guid, p_guid, sizeof(*m_guid)); + } + + if (p_driverDesc) { + m_driverDesc = new char[strlen(p_driverDesc) + 1]; + strcpy(m_driverDesc, p_driverDesc); + } + + if (p_driverName) { + m_driverName = new char[strlen(p_driverName) + 1]; + strcpy(m_driverName, p_driverName); + } +} + +// FUNCTION: LEGO1 0x1009bd20 +MxDevice::MxDevice( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc +) +{ + memset(this, 0, sizeof(*this)); + + Init(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); +} + +// FUNCTION: LEGO1 0x1009bd60 +MxDevice::~MxDevice() +{ + if (m_guid) { + delete m_guid; + } + if (m_deviceDesc) { + delete[] m_deviceDesc; + } + if (m_deviceName) { + delete[] m_deviceName; + } +} + +// FUNCTION: LEGO1 0x1009bda0 +void MxDevice::Init( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc +) +{ + if (m_deviceDesc) { + delete[] m_deviceDesc; + m_deviceDesc = NULL; + } + + if (m_deviceName) { + delete[] m_deviceName; + m_deviceName = NULL; + } + + if (p_guid) { + m_guid = new GUID; + memcpy(m_guid, p_guid, sizeof(*m_guid)); + } + + if (p_deviceDesc) { + m_deviceDesc = new char[strlen(p_deviceDesc) + 1]; + strcpy(m_deviceDesc, p_deviceDesc); + } + + if (p_deviceName) { + m_deviceName = new char[strlen(p_deviceName) + 1]; + strcpy(m_deviceName, p_deviceName); + } + + if (p_HWDesc) { + memcpy(&m_HWDesc, p_HWDesc, sizeof(m_HWDesc)); + } + + if (p_HELDesc) { + memcpy(&m_HELDesc, p_HELDesc, sizeof(m_HELDesc)); + } +} + +// FUNCTION: LEGO1 0x1009bec0 +MxDeviceEnumerate::MxDeviceEnumerate() +{ + m_initialized = FALSE; +} + +// FUNCTION: LEGO1 0x1009c070 +BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName) +{ + MxDriver driver(p_guid, p_driverDesc, p_driverName); + m_list.push_back(driver); + + // Must be zeroed because held resources are copied by pointer only + // and should not be freed at the end of this function + driver.m_guid = NULL; + driver.m_driverDesc = NULL; + driver.m_driverName = NULL; + memset(&driver.m_ddCaps, 0, sizeof(driver.m_ddCaps)); + + LPDIRECT3D2 lpDirect3d2 = NULL; + LPDIRECTDRAW lpDD = NULL; + MxDriver& newDevice = m_list.back(); + HRESULT result = DirectDrawCreate(newDevice.m_guid, &lpDD, NULL); + + if (result != DD_OK) { + BuildErrorString("DirectDraw Create failed: %s\n", EnumerateErrorToString(result)); + } + else { + lpDD->EnumDisplayModes(0, NULL, this, DisplayModesEnumerateCallback); + newDevice.m_ddCaps.dwSize = sizeof(newDevice.m_ddCaps); + result = lpDD->GetCaps(&newDevice.m_ddCaps, NULL); + + if (result != DD_OK) { + BuildErrorString("GetCaps failed: %s\n", EnumerateErrorToString(result)); + } + else { + result = lpDD->QueryInterface(IID_IDirect3D2, (LPVOID*) &lpDirect3d2); + + if (result != DD_OK) { + BuildErrorString("D3D creation failed: %s\n", EnumerateErrorToString(result)); + } + else { + result = lpDirect3d2->EnumDevices(DevicesEnumerateCallback, this); + + if (result != DD_OK) { + BuildErrorString("D3D enum devices failed: %s\n", EnumerateErrorToString(result)); + } + else { + if (newDevice.m_devices.empty()) { + m_list.pop_back(); + } + } + } + } + } + + if (lpDirect3d2) { + lpDirect3d2->Release(); + } + + if (lpDD) { + lpDD->Release(); + } + + return DDENUMRET_OK; +} + +// FUNCTION: LEGO1 0x1009c4c0 +void MxDeviceEnumerate::BuildErrorString(const char* p_format, ...) +{ + va_list args; + char buf[512]; + + va_start(args, p_format); + vsprintf(buf, p_format, args); + va_end(args); + + OutputDebugString(buf); +} + +// FUNCTION: LEGO1 0x1009c4f0 +HRESULT CALLBACK MxDeviceEnumerate::DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context) +{ + MxDeviceEnumerate* deviceEnumerate = (MxDeviceEnumerate*) p_context; + return deviceEnumerate->EnumDisplayModesCallback(p_ddsd); +} + +// FUNCTION: LEGO1 0x1009c510 +HRESULT CALLBACK MxDeviceEnumerate::DevicesEnumerateCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc, + LPVOID p_context +) +{ + MxDeviceEnumerate* deviceEnumerate = (MxDeviceEnumerate*) p_context; + return deviceEnumerate->EnumDevicesCallback(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); +} + +// FUNCTION: LEGO1 0x1009c540 +HRESULT MxDeviceEnumerate::EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd) +{ + MxDisplayMode displayMode; + displayMode.m_width = p_ddsd->dwWidth; + displayMode.m_height = p_ddsd->dwHeight; + displayMode.m_bitsPerPixel = p_ddsd->ddpfPixelFormat.dwRGBBitCount; + + m_list.back().m_displayModes.push_back(displayMode); + return DDENUMRET_OK; +} + +// FUNCTION: LEGO1 0x1009c5d0 +HRESULT MxDeviceEnumerate::EnumDevicesCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc +) +{ + MxDevice device(p_guid, p_deviceDesc, p_deviceName, p_HWDesc, p_HELDesc); + m_list.back().m_devices.push_back(device); + memset(&device, 0, sizeof(device)); + return DDENUMRET_OK; +} + +// FUNCTION: LEGO1 0x1009c6c0 +int MxDeviceEnumerate::DoEnumerate() +{ + if (m_initialized) { + return -1; + } + + HRESULT ret = DirectDrawEnumerate(DirectDrawEnumerateCallback, this); + if (ret != DD_OK) { + BuildErrorString("DirectDrawEnumerate returned error %s\n", EnumerateErrorToString(ret)); + return -1; + } + + m_initialized = TRUE; + return 0; +} + +// FUNCTION: LEGO1 0x1009c710 +BOOL CALLBACK +MxDeviceEnumerate::DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context) +{ + MxDeviceEnumerate* deviceEnumerate = (MxDeviceEnumerate*) p_context; + return deviceEnumerate->EnumDirectDrawCallback(p_guid, p_driverDesc, p_driverName); +} + +// STUB: LEGO1 0x1009c730 +const char* MxDeviceEnumerate::EnumerateErrorToString(HRESULT p_error) +{ + // TODO: This is a list of error messages, similar to the function in + // MxDirectDraw, except that this one now contains the Direct3D errors. + // Probably just copied from a sample file in the dx5 sdk. + return ""; +} + +// FUNCTION: LEGO1 0x1009ce60 +int MxDeviceEnumerate::ParseDeviceName(const char* p_deviceId) +{ + if (!m_initialized) { + return -1; + } + + int num = -1; + int hex[4]; + + if (sscanf(p_deviceId, "%d 0x%x 0x%x 0x%x 0x%x", &num, &hex[0], &hex[1], &hex[2], &hex[3]) != 5) { + return -1; + } + + if (num < 0) { + return -1; + } + + GUID guid; + memcpy(&guid, hex, sizeof(guid)); + + int result = ProcessDeviceBytes(num, guid); + + if (result < 0) { + return ProcessDeviceBytes(-1, guid); + } + return result; +} + +// FUNCTION: LEGO1 0x1009cf20 +int MxDeviceEnumerate::ProcessDeviceBytes(int p_deviceNum, GUID& p_guid) +{ + if (!m_initialized) { + return -1; + } + + int i = 0; + int j = 0; + + struct GUID4 { + int m_data1; + int m_data2; + int m_data3; + int m_data4; + }; + + static_assert(sizeof(GUID4) == sizeof(GUID), "Equal size"); + + GUID4 deviceGuid; + memcpy(&deviceGuid, &p_guid, sizeof(GUID4)); + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { + if (p_deviceNum >= 0 && p_deviceNum < i) { + return -1; + } + + GUID4 compareGuid; + MxDriver& driver = *it; + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { + memcpy(&compareGuid, (*it2).m_guid, sizeof(GUID4)); + + if (compareGuid.m_data1 == deviceGuid.m_data1 && compareGuid.m_data2 == deviceGuid.m_data2 && + compareGuid.m_data3 == deviceGuid.m_data3 && compareGuid.m_data4 == deviceGuid.m_data4 && + i == p_deviceNum) { + return j; + } + + j++; + } + + i++; + } + + return -1; +} + +// FUNCTION: LEGO1 0x1009d030 +int MxDeviceEnumerate::GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice*& p_device) +{ + if (p_deviceNum >= 0 && m_initialized) { + int i = 0; + + for (list::iterator it = m_list.begin(); it != m_list.end(); it++) { + p_driver = &*it; + + for (list::iterator it2 = p_driver->m_devices.begin(); it2 != p_driver->m_devices.end(); it2++) { + if (i == p_deviceNum) { + p_device = &*it2; + return 0; + } + i++; + } + } + + return -1; + } + + return -1; +} + +// FUNCTION: LEGO1 0x1009d0d0 +int MxDeviceEnumerate::FUN_1009d0d0() +{ + if (!m_initialized) { + return -1; + } + + if (m_list.empty()) { + return -1; + } + + int i = 0; + int j = 0; + int k = -1; + unsigned int und = FUN_1009d1a0(); + + for (list::iterator it = m_list.begin();; it++) { + if (it == m_list.end()) { + return k; + } + + for (list::iterator it2 = (*it).m_devices.begin(); it2 != (*it).m_devices.end(); it2++) { + if ((*it2).m_HWDesc.dcmColorModel) { + return j; + } + + if ((und && (*it2).m_HELDesc.dcmColorModel == D3DCOLOR_RGB && i == 0) || + ((*it2).m_HELDesc.dcmColorModel == D3DCOLOR_MONO && i == 0 && k < 0)) { + k = j; + } + + j++; + } + + i++; + } + + return -1; +} + +// STUB: LEGO1 0x1009d1a0 +undefined4 MxDeviceEnumerate::FUN_1009d1a0() +{ + return 1; +} + +// STUB: LEGO1 0x1009d1e0 +undefined4 MxDeviceEnumerate::FUN_1009d1e0() +{ + return 1; +} + +// FUNCTION: LEGO1 0x1009d210 +int MxDeviceEnumerate::FUN_1009d210() +{ + if (!m_initialized) { + return -1; + } + + for (list::iterator it = m_list.begin(); it != m_list.end();) { + MxDriver& driver = *it; + + if (!FUN_1009d370(driver)) { + m_list.erase(it++); + } + else { + for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end();) { + MxDevice& device = *it2; + + if (!FUN_1009d3d0(device)) { + driver.m_devices.erase(it2++); + } + else { + it2++; + } + } + + if (driver.m_devices.empty()) { + m_list.erase(it++); + } + else { + it++; + } + } + } + + return m_list.empty() ? -1 : 0; +} + +// FUNCTION: LEGO1 0x1009d370 +unsigned char MxDeviceEnumerate::FUN_1009d370(MxDriver& p_driver) +{ + for (list::iterator it = p_driver.m_displayModes.begin(); it != p_driver.m_displayModes.end(); + it++) { + if ((*it).m_width == 640 && (*it).m_height == 480) { + if ((*it).m_bitsPerPixel == 8 || (*it).m_bitsPerPixel == 16) { + return TRUE; + } + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x1009d3d0 +unsigned char MxDeviceEnumerate::FUN_1009d3d0(MxDevice& p_device) +{ + if (m_list.size() <= 0) { + return FALSE; + } + + if (p_device.m_HWDesc.dcmColorModel) { + return p_device.m_HWDesc.dwDeviceZBufferBitDepth & DDBD_16 && p_device.m_HWDesc.dpcTriCaps.dwTextureCaps & 1; + } + + for (list::iterator it = m_list.front().m_devices.begin(); it != m_list.front().m_devices.end(); it++) { + if ((&*it) == &p_device) { + return TRUE; + } + } + + return FALSE; +} diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h new file mode 100644 index 00000000..6ebf46f9 --- /dev/null +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -0,0 +1,236 @@ +#ifndef MXDIRECT3D_H +#define MXDIRECT3D_H + +#include "decomp.h" +#include "mxdirectdraw.h" +#include "mxstl/stlcompat.h" + +#include + +class MxDirect3D; + +// SIZE 0xe4 +class MxAssignedDevice { +public: + enum { + c_hardwareMode = 0x01, + c_primaryDevice = 0x02 + }; + + MxAssignedDevice(); + ~MxAssignedDevice(); + + inline unsigned int GetFlags() { return m_flags; } + inline D3DDEVICEDESC& GetDesc() { return m_desc; } + + friend class MxDirect3D; + +private: + GUID m_guid; // 0x00 + unsigned int m_flags; // 0x10 + D3DDEVICEDESC m_desc; // 0x14 + MxDirectDraw::DeviceModesInfo* m_deviceInfo; // 0xe0 +}; + +class MxDeviceEnumerate; +struct MxDriver; +struct MxDevice; + +// VTABLE: LEGO1 0x100db800 +// SIZE 0x894 +class MxDirect3D : public MxDirectDraw { +public: + MxDirect3D(); + ~MxDirect3D() override; + + BOOL Create( + HWND hWnd, + BOOL fullscreen_1, + BOOL surface_fullscreen, + BOOL onlySystemMemory, + int width, + int height, + int bpp, + const PALETTEENTRY* pPaletteEntries, + int paletteEntryCount + ) override; // vtable+0x04 + void Destroy() override; // vtable+0x08 + void DestroyButNotDirectDraw() override; // vtable+0x0c + + BOOL CreateIDirect3D(); + BOOL D3DSetMode(); + DWORD GetZBufferBitDepth(MxAssignedDevice* p_assignedDevice); + BOOL SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_driver, MxDevice* p_device); + + inline MxAssignedDevice* GetAssignedDevice() { return this->m_assignedDevice; } + inline IDirect3D2* GetDirect3D() { return this->m_pDirect3d; } + inline IDirect3DDevice2* GetDirect3DDevice() { return this->m_pDirect3dDevice; } + + // SYNTHETIC: LEGO1 0x1009b120 + // MxDirect3D::`scalar deleting destructor' + +private: + MxAssignedDevice* m_assignedDevice; // 0x880 + IDirect3D2* m_pDirect3d; // 0x884 + IDirect3DDevice2* m_pDirect3dDevice; // 0x888 + BOOL m_unk0x88c; // 0x88c + undefined4 m_unk0x890; // 0x890 +}; + +// SIZE 0x1a4 +struct MxDevice { + MxDevice() {} + ~MxDevice(); + MxDevice( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc + ); + + void Init( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc + ); + + LPGUID m_guid; // 0x00 + char* m_deviceDesc; // 0x04 + char* m_deviceName; // 0x08 + D3DDEVICEDESC m_HWDesc; // 0x0c + D3DDEVICEDESC m_HELDesc; // 0xd8 + + int operator==(MxDevice) const { return 0; } + int operator<(MxDevice) const { return 0; } +}; + +// SIZE 0x0c +struct MxDisplayMode { + DWORD m_width; // 0x00 + DWORD m_height; // 0x04 + DWORD m_bitsPerPixel; // 0x08 + + int operator==(MxDisplayMode) const { return 0; } + int operator<(MxDisplayMode) const { return 0; } +}; + +// SIZE 0x190 +struct MxDriver { + MxDriver() {} + ~MxDriver(); + MxDriver(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); + + void Init(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); + + LPGUID m_guid; // 0x00 + char* m_driverDesc; // 0x04 + char* m_driverName; // 0x08 + DDCAPS m_ddCaps; // 0x0c + list m_devices; // 0x178 + list m_displayModes; // 0x184 + + int operator==(MxDriver) const { return 0; } + int operator<(MxDriver) const { return 0; } +}; + +// clang-format off +// TEMPLATE: LEGO1 0x1009b900 +// list >::~list > +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x1009b970 +// list >::~list > +// clang-format on + +// TEMPLATE: LEGO1 0x1009b9e0 +// List::~List + +// TEMPLATE: LEGO1 0x1009ba30 +// List::~List + +// clang-format off +// TEMPLATE: LEGO1 0x1009bf50 +// list >::~list > +// clang-format on + +// TEMPLATE: LEGO1 0x1009bfc0 +// List::~List + +// Compiler-generated copy ctor +// SYNTHETIC: LEGO1 0x1009c290 +// MxDriver::MxDriver + +// SYNTHETIC: LEGO1 0x1009c400 +// list >::insert + +// SYNTHETIC: LEGO1 0x1009c460 +// list >::insert + +// SYNTHETIC: LEGO1 0x1009d450 +// MxDriver::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1009d470 +// MxDevice::`scalar deleting destructor' + +// VTABLE: LEGO1 0x100db814 +// SIZE 0x14 +class MxDeviceEnumerate { +public: + MxDeviceEnumerate(); + // FUNCTION: LEGO1 0x1009c010 + ~MxDeviceEnumerate() {} + + virtual int DoEnumerate(); // vtable+0x00 + + BOOL EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName); + HRESULT EnumDisplayModesCallback(LPDDSURFACEDESC p_ddsd); + HRESULT EnumDevicesCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc + ); + const char* EnumerateErrorToString(HRESULT p_error); + int ParseDeviceName(const char* p_deviceId); + int ProcessDeviceBytes(int p_deviceNum, GUID& p_guid); + int GetDevice(int p_deviceNum, MxDriver*& p_driver, MxDevice*& p_device); + int FUN_1009d0d0(); + int FUN_1009d210(); + unsigned char FUN_1009d370(MxDriver& p_driver); + unsigned char FUN_1009d3d0(MxDevice& p_device); + + static void BuildErrorString(const char*, ...); + static BOOL CALLBACK + DirectDrawEnumerateCallback(LPGUID p_guid, LPSTR p_driverDesc, LPSTR p_driverName, LPVOID p_context); + static HRESULT CALLBACK DisplayModesEnumerateCallback(LPDDSURFACEDESC p_ddsd, LPVOID p_context); + static HRESULT CALLBACK DevicesEnumerateCallback( + LPGUID p_guid, + LPSTR p_deviceDesc, + LPSTR p_deviceName, + LPD3DDEVICEDESC p_HWDesc, + LPD3DDEVICEDESC p_HELDesc, + LPVOID p_context + ); + static undefined4 FUN_1009d1a0(); + static undefined4 FUN_1009d1e0(); + + friend class MxDirect3D; + +private: + list m_list; // 0x04 + unsigned char m_initialized; // 0x10 +}; + +// VTABLE: LEGO1 0x100d9cc8 +// SIZE 0x14 +class MxDeviceEnumerate100d9cc8 : public MxDeviceEnumerate {}; + +// SYNTHETIC: LEGO1 0x1007b590 +// MxDeviceEnumerate100d9cc8::~MxDeviceEnumerate100d9cc8 + +#endif // MXDIRECT3D_H diff --git a/LEGO1/mxdirectdraw.cpp b/LEGO1/mxdirectx/mxdirectdraw.cpp similarity index 97% rename from LEGO1/mxdirectdraw.cpp rename to LEGO1/mxdirectx/mxdirectdraw.cpp index 12a7cde0..7b64afe3 100644 --- a/LEGO1/mxdirectdraw.cpp +++ b/LEGO1/mxdirectx/mxdirectdraw.cpp @@ -348,9 +348,9 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) } if (!IsSupportedMode(width, height, bpp)) { - width = m_pCurrentDeviceModesList->m_modeArray[0].m_width; - height = m_pCurrentDeviceModesList->m_modeArray[0].m_height; - bpp = m_pCurrentDeviceModesList->m_modeArray[0].m_bitsPerPixel; + width = m_pCurrentDeviceModesList->m_modeArray[0].width; + height = m_pCurrentDeviceModesList->m_modeArray[0].height; + bpp = m_pCurrentDeviceModesList->m_modeArray[0].bitsPerPixel; } m_bIgnoreWMSIZE = TRUE; @@ -396,9 +396,9 @@ BOOL MxDirectDraw::DDSetMode(int width, int height, int bpp) m_bIgnoreWMSIZE = FALSE; } - m_currentMode.m_width = width; - m_currentMode.m_height = height; - m_currentMode.m_bitsPerPixel = bpp; + m_currentMode.width = width; + m_currentMode.height = height; + m_currentMode.bitsPerPixel = bpp; if (!DDCreateSurfaces()) { return FALSE; @@ -506,12 +506,13 @@ BOOL MxDirectDraw::DDCreateSurfaces() Error("CreateSurface for window front buffer failed", result); return FALSE; } - ddsd.dwHeight = m_currentMode.m_height; - ddsd.dwWidth = m_currentMode.m_width; + ddsd.dwHeight = m_currentMode.height; + ddsd.dwWidth = m_currentMode.width; ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; - if (m_bOnlySystemMemory) + if (m_bOnlySystemMemory) { ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY; + } result = CreateDDSurface(&ddsd, &m_pBackBuffer, NULL); if (result != DD_OK) { Error("CreateSurface for window back buffer failed", result); @@ -640,7 +641,7 @@ BOOL MxDirectDraw::CreateTextSurfaces() } m_hFont = CreateFontA( - m_currentMode.m_width <= 600 ? 12 : 24, + m_currentMode.width <= 600 ? 12 : 24, 0, 0, 0, @@ -666,8 +667,9 @@ BOOL MxDirectDraw::CreateTextSurfaces() ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - if (m_bOnlySystemMemory) + if (m_bOnlySystemMemory) { ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + } ddsd.dwHeight = m_text1SizeOnSurface.cy; ddsd.dwWidth = m_text1SizeOnSurface.cx; @@ -687,8 +689,9 @@ BOOL MxDirectDraw::CreateTextSurfaces() ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; - if (m_bOnlySystemMemory) + if (m_bOnlySystemMemory) { ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + } ddsd.dwHeight = m_text2SizeOnSurface.cy; ddsd.dwWidth = m_text2SizeOnSurface.cx; @@ -774,8 +777,8 @@ BOOL MxDirectDraw::CreateZBuffer(DWORD memorytype, DWORD depth) memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); - ddsd.dwHeight = m_currentMode.m_height; - ddsd.dwWidth = m_currentMode.m_width; + ddsd.dwHeight = m_currentMode.height; + ddsd.dwWidth = m_currentMode.width; ddsd.dwZBufferBitDepth = depth; ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH; ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | memorytype; @@ -889,7 +892,7 @@ int MxDirectDraw::FlipToGDISurface() } // FUNCTION: LEGO1 0x1009e830 -void MxDirectDraw::Error(const char* p_message, MxS32 p_error) +void MxDirectDraw::Error(const char* p_message, int p_error) { // GLOBAL: LEGO1 0x10100c70 static BOOL g_isInsideError = FALSE; @@ -1127,6 +1130,6 @@ MxDirectDraw::DeviceModesInfo::~DeviceModesInfo() } if (m_modeArray != NULL) { - delete m_modeArray; + delete[] m_modeArray; } } diff --git a/LEGO1/mxdirectx/mxdirectdraw.h b/LEGO1/mxdirectx/mxdirectdraw.h new file mode 100644 index 00000000..e082c2d4 --- /dev/null +++ b/LEGO1/mxdirectx/mxdirectdraw.h @@ -0,0 +1,121 @@ +#ifndef MXDIRECTDRAW_H +#define MXDIRECTDRAW_H + +#include +#include + +// VTABLE: LEGO1 0x100db818 +// SIZE 0x880 +class MxDirectDraw { +public: + typedef void (*ErrorHandler)(const char*, HRESULT, void*); + + // SIZE 0x0c + struct Mode { + int operator==(const Mode& p_mode) const + { + return ((width == p_mode.width) && (height == p_mode.height) && (bitsPerPixel == p_mode.bitsPerPixel)); + } + + int width; // 0x00 + int height; // 0x04 + int bitsPerPixel; // 0x08 + }; + + // SIZE 0x17c + struct DeviceModesInfo { + DeviceModesInfo(); + ~DeviceModesInfo(); + + GUID* m_guid; // 0x00 + Mode* m_modeArray; // 0x04 + int m_count; // 0x08 + DDCAPS m_ddcaps; // 0x0c + void* m_unk0x178; // 0x178 + }; + + int FlipToGDISurface(); + static int GetPrimaryBitDepth(); + int Pause(int); + + MxDirectDraw(); + virtual ~MxDirectDraw(); + + virtual BOOL Create( + HWND hWnd, + BOOL fullscreen_1, + BOOL surface_fullscreen, + BOOL onlySystemMemory, + int width, + int height, + int bpp, + const PALETTEENTRY* pPaletteEntries, + int paletteEntryCount + ); // vtable+0x04 + virtual void Destroy(); // vtable+0x08 + virtual void DestroyButNotDirectDraw(); // vtable+0x0c + virtual const char* ErrorToString(HRESULT p_error); // vtable+0x10 + + BOOL CacheOriginalPaletteEntries(); + HRESULT CreateDDSurface(LPDDSURFACEDESC a2, LPDIRECTDRAWSURFACE* a3, IUnknown* a4); + BOOL CreateTextSurfaces(); + BOOL CreateZBuffer(DWORD memorytype, DWORD depth); + BOOL DDCreateSurfaces(); + BOOL DDInit(BOOL fullscreen); + BOOL DDSetMode(int width, int height, int bpp); + void Error(const char* p_message, int p_error); + + BOOL GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf); + BOOL IsSupportedMode(int width, int height, int bpp); + BOOL RecreateDirectDraw(GUID** a2); + BOOL RestoreOriginalPaletteEntries(); + BOOL RestorePaletteEntries(); + BOOL RestoreSurfaces(); + BOOL SetPaletteEntries(const PALETTEENTRY* pPaletteEntries, int paletteEntryCount, BOOL fullscreen); + BOOL TextToTextSurface(const char* text, IDirectDrawSurface* pSurface, SIZE& textSizeOnSurface); + BOOL TextToTextSurface1(const char* text); + BOOL TextToTextSurface2(const char* lpString); + void FUN_1009e020(); + void FUN_1009d920(); + + inline IDirectDraw* GetDirectDraw() { return m_pDirectDraw; } + inline IDirectDrawSurface* GetFrontBuffer() { return m_pFrontBuffer; } + inline IDirectDrawSurface* GetBackBuffer() { return m_pBackBuffer; } + inline IDirectDrawClipper* GetClipper() { return m_pClipper; } + + // SYNTHETIC: LEGO1 0x1009d510 + // MxDirectDraw::`scalar deleting destructor' + +protected: + BOOL m_bOnlySoftRender; // 0x04 + BOOL m_bFlipSurfaces; // 0x08 + IDirectDraw* m_pDirectDraw; // 0x0c + IDirectDrawSurface* m_pFrontBuffer; // 0x10 + IDirectDrawSurface* m_pBackBuffer; // 0x14 + IDirectDrawSurface* m_pZBuffer; // 0x18 + IDirectDrawSurface* m_pText1Surface; // 0x1c + IDirectDrawSurface* m_pText2Surface; // 0x20 + IDirectDrawClipper* m_pClipper; // 0x24 + IDirectDrawPalette* m_pPalette; // 0x28 + PALETTEENTRY m_paletteEntries[256]; // 0x2c + PALETTEENTRY m_originalPaletteEntries[256]; // 0x42c + SIZE m_text1SizeOnSurface; // 0x82c + SIZE m_text2SizeOnSurface; // 0x834 + HWND m_hWndMain; // 0x83c + HFONT m_hFont; // 0x840 + BOOL m_bIgnoreWMSIZE; // 0x844 + BOOL m_bPrimaryPalettized; // 0x848 + BOOL m_bFullScreen; // 0x84c + void* m_unk0x850; // 0x850 + BOOL m_bOnlySystemMemory; // 0x854 + BOOL m_bIsOnPrimaryDevice; // 0x858 + ErrorHandler m_pErrorHandler; // 0x85c + ErrorHandler m_pFatalErrorHandler; // 0x860 + void* m_pErrorHandlerArg; // 0x864 + void* m_pFatalErrorHandlerArg; // 0x868 + int m_pauseCount; // 0x86c + DeviceModesInfo* m_pCurrentDeviceModesList; // 0x870 + Mode m_currentMode; // 0x874 +}; + +#endif // MXDIRECTDRAW_H diff --git a/LEGO1/mxdirectx/mxstopwatch.h b/LEGO1/mxdirectx/mxstopwatch.h new file mode 100644 index 00000000..0630d2f6 --- /dev/null +++ b/LEGO1/mxdirectx/mxstopwatch.h @@ -0,0 +1,191 @@ +#ifndef _MxStopWatch_h +#define _MxStopWatch_h + +#include "assert.h" + +#include +#include + +////////////////////////////////////////////////////////////////////////////// +// +// MxStopWatch +// +// NOTE: MxStopWatch measures elapsed (wall clock) time. +// + +#define HUGE_VAL_IMMEDIATE 1.7976931348623157e+308 + +// SIZE 0x18 +class MxStopWatch { +public: + MxStopWatch(); + ~MxStopWatch() {} + + void Start(); + void Stop(); + void Reset(); + + double ElapsedSeconds() const; + +protected: + unsigned long TicksPerSeconds() const; + +private: + LARGE_INTEGER m_startTick; // 0x00 + // ??? when we provide LARGE_INTEGER arithmetic, use a + // LARGE_INTEGER m_elapsedTicks rather than m_elapsedSeconds + double m_elapsedSeconds; // 0x0c + unsigned long m_ticksPerSeconds; // 0x14 +}; + +inline MxStopWatch::MxStopWatch() +{ + Reset(); + m_ticksPerSeconds = TicksPerSeconds(); +} + +inline void MxStopWatch::Start() +{ + QueryPerformanceCounter(&m_startTick); +} + +inline void MxStopWatch::Stop() +{ + LARGE_INTEGER endTick; + BOOL result; + + result = QueryPerformanceCounter(&endTick); + assert(result); + + if (endTick.HighPart != m_startTick.HighPart) { + // LARGE_INTEGER arithmetic not yet provided + m_elapsedSeconds = HUGE_VAL_IMMEDIATE; + } + else { + m_elapsedSeconds += ((endTick.LowPart - m_startTick.LowPart) / (double) m_ticksPerSeconds); + } +} + +inline void MxStopWatch::Reset() +{ + m_startTick.LowPart = 0; + m_startTick.HighPart = 0; + m_elapsedSeconds = 0; +} + +inline unsigned long MxStopWatch::TicksPerSeconds() const +{ + LARGE_INTEGER ticksPerSeconds; + BOOL result; + + result = QueryPerformanceFrequency(&ticksPerSeconds); + assert(result); + + if (ticksPerSeconds.HighPart) { + // LARGE_INTEGER arithmetic not yet provided + + // timer is too fast (faster than 32bits/s, i.e. faster than 4GHz) + return ULONG_MAX; + } + else { + return ticksPerSeconds.LowPart; + } +} + +inline double MxStopWatch::ElapsedSeconds() const +{ + return m_elapsedSeconds; +} + +// SYNTHETIC: LEGO1 0x100a6fc0 +// MxStopWatch::~MxStopWatch + +////////////////////////////////////////////////////////////////////////////// +// +// MxFrequencyMeter +// + +// SIZE 0x20 +class MxFrequencyMeter { +public: + MxFrequencyMeter(); + + void StartOperation(); + void EndOperation(); + double Frequency() const; + void Reset(); + + unsigned long OperationCount() const; + double ElapsedSeconds() const; + + void IncreaseOperationCount(unsigned long); + +private: + unsigned long m_operationCount; // 0x00 + MxStopWatch m_stopWatch; // 0x08 +}; + +////////////////////////////////////////////////////////////////////////////// +// +// MxFrequencyMeter implementation +// + +inline MxFrequencyMeter::MxFrequencyMeter() : m_operationCount(0) +{ +} + +inline void MxFrequencyMeter::StartOperation() +{ + m_stopWatch.Start(); +} + +inline void MxFrequencyMeter::EndOperation() +{ + m_stopWatch.Stop(); + m_operationCount++; +} + +inline double MxFrequencyMeter::Frequency() const +{ + double elapsedSeconds = m_stopWatch.ElapsedSeconds(); + + if (elapsedSeconds > 0) { + return m_operationCount / elapsedSeconds; + } + else { + if (m_operationCount) { + // operations performed - no time elapsed + return HUGE_VAL; + } + else { + // no operations performed - no time elapsed + return 0; + } + } +} + +inline void MxFrequencyMeter::Reset() +{ + m_stopWatch.Reset(); + m_operationCount = 0; +} + +inline unsigned long MxFrequencyMeter::OperationCount() const +{ + return m_operationCount; +} + +inline void MxFrequencyMeter::IncreaseOperationCount(unsigned long delta) +{ + m_operationCount += delta; +} + +inline double MxFrequencyMeter::ElapsedSeconds() const +{ + return m_stopWatch.ElapsedSeconds(); +} + +// SYNTHETIC: LEGO1 0x100abd10 +// MxFrequencyMeter::~MxFrequencyMeter + +#endif /* _MxStopWatch_h */ diff --git a/LEGO1/mxdiskstreamprovider.cpp b/LEGO1/mxdiskstreamprovider.cpp deleted file mode 100644 index a8d15984..00000000 --- a/LEGO1/mxdiskstreamprovider.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "mxdiskstreamprovider.h" - -#include "mxdsbuffer.h" -#include "mxomni.h" -#include "mxstreamcontroller.h" -#include "mxstring.h" -#include "mxthread.h" - -DECOMP_SIZE_ASSERT(MxDiskStreamProvider, 0x60); - -// FUNCTION: LEGO1 0x100d0f30 -MxResult MxDiskStreamProviderThread::Run() -{ - if (m_target) - ((MxDiskStreamProvider*) m_target)->WaitForWorkToComplete(); - MxThread::Run(); - // They should probably have writen "return MxThread::Run()" but they didn't. - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100d0f50 -MxResult MxDiskStreamProviderThread::StartWithTarget(MxDiskStreamProvider* p_target) -{ - m_target = p_target; - return Start(0x1000, 0); -} - -// FUNCTION: LEGO1 0x100d0f70 -MxDiskStreamProvider::MxDiskStreamProvider() -{ - this->m_pFile = NULL; - this->m_remainingWork = 0; - this->m_unk0x35 = 0; -} - -// STUB: LEGO1 0x100d1240 -MxDiskStreamProvider::~MxDiskStreamProvider() -{ - // TODO -} - -// FUNCTION: LEGO1 0x100d13d0 -MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource) -{ - MxResult result = FAILURE; - MxString path; - m_pLookup = p_resource; - - path = (MxString(MxOmni::GetHD()) + p_resource->GetAtom().GetInternal() + ".si"); - - m_pFile = new MxDSFile(path.GetData(), 0); - if (m_pFile != NULL) { - if (m_pFile->Open(0) != 0) { - path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si"; - m_pFile->SetFileName(path.GetData()); - - if (m_pFile->Open(0) != 0) - goto done; - } - - m_remainingWork = 1; - m_busySemaphore.Init(0, 100); - - if (m_thread.StartWithTarget(this) == SUCCESS && p_resource != NULL) { - result = SUCCESS; - } - } - -done: - return result; -} - -// STUB: LEGO1 0x100d15e0 -void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) -{ - // TODO -} - -// FUNCTION: LEGO1 0x100d1750 -MxResult MxDiskStreamProvider::WaitForWorkToComplete() -{ - while (m_remainingWork != 0) { - m_busySemaphore.Wait(INFINITE); - if (m_unk0x35 != 0) - PerformWork(); - } - return SUCCESS; -} - -// STUB: LEGO1 0x100d1780 -MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action) -{ - // TODO - return FAILURE; -} - -// STUB: LEGO1 0x100d18f0 -void MxDiskStreamProvider::PerformWork() -{ - // TODO -} - -// FUNCTION: LEGO1 0x100d1e90 -MxU32 MxDiskStreamProvider::GetFileSize() -{ - return m_pFile->GetBufferSize(); -} - -// FUNCTION: LEGO1 0x100d1ea0 -MxS32 MxDiskStreamProvider::GetStreamBuffersNum() -{ - return m_pFile->GetStreamBuffersNum(); -} - -// FUNCTION: LEGO1 0x100d1eb0 -MxU32 MxDiskStreamProvider::GetLengthInDWords() -{ - return m_pFile->GetLengthInDWords(); -} - -// FUNCTION: LEGO1 0x100d1ec0 -MxU32* MxDiskStreamProvider::GetBufferForDWords() -{ - return m_pFile->GetBuffer(); -} diff --git a/LEGO1/mxdisplaysurface.cpp b/LEGO1/mxdisplaysurface.cpp deleted file mode 100644 index bc1d2078..00000000 --- a/LEGO1/mxdisplaysurface.cpp +++ /dev/null @@ -1,306 +0,0 @@ -#include "mxdisplaysurface.h" - -#include "mxomni.h" -#include "mxvideomanager.h" - -DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); - -// FUNCTION: LEGO1 0x100ba500 -MxDisplaySurface::MxDisplaySurface() -{ - this->Reset(); -} - -// FUNCTION: LEGO1 0x100ba5a0 -MxDisplaySurface::~MxDisplaySurface() -{ - this->Clear(); -} - -// FUNCTION: LEGO1 0x100ba610 -void MxDisplaySurface::Reset() -{ - this->m_ddSurface1 = NULL; - this->m_ddSurface2 = NULL; - this->m_ddClipper = NULL; - this->m_16bitPal = NULL; - this->m_initialized = FALSE; - memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); -} - -// FUNCTION: LEGO1 0x100ba640 -void MxDisplaySurface::FUN_100ba640() -{ - MxS32 backBuffers; - DDSURFACEDESC desc; - HRESULT hr; - - if (!m_videoParam.Flags().GetFlipSurfaces()) { - backBuffers = 1; - } - else { - backBuffers = m_videoParam.GetBackBuffers() + 1; - } - - for (MxS32 i = 0; i < backBuffers; i++) { - memset(&desc, 0, sizeof(DDSURFACEDESC)); - - desc.dwSize = sizeof(DDSURFACEDESC); - hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL); - if (hr == DDERR_SURFACELOST) { - m_ddSurface2->Restore(); - hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL); - } - - if (hr != S_OK) { - return; - } - - MxU8* surface = (MxU8*) desc.lpSurface; - MxS32 height = m_videoParam.GetRect().GetHeight(); - - while (height--) { - memset(surface, 0, m_videoParam.GetRect().GetWidth() * desc.ddpfPixelFormat.dwRGBBitCount / 8); - surface += desc.lPitch; - } - - m_ddSurface2->Unlock(desc.lpSurface); - if (m_videoParam.Flags().GetFlipSurfaces()) { - m_ddSurface1->Flip(NULL, 1); - } - } -} - -// FUNCTION: LEGO1 0x100ba790 -MxResult MxDisplaySurface::Init( - MxVideoParam& p_videoParam, - LPDIRECTDRAWSURFACE p_ddSurface1, - LPDIRECTDRAWSURFACE p_ddSurface2, - LPDIRECTDRAWCLIPPER p_ddClipper -) -{ - MxResult result = SUCCESS; - - this->m_videoParam = p_videoParam; - this->m_ddSurface1 = p_ddSurface1; - this->m_ddSurface2 = p_ddSurface2; - this->m_ddClipper = p_ddClipper; - this->m_initialized = FALSE; - - memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); - this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc); - - if (this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) - result = FAILURE; - - return result; -} - -// FUNCTION: LEGO1 0x100ba7f0 -MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) -{ - DDSURFACEDESC ddsd; - MxResult result = FAILURE; - LPDIRECTDRAW lpDirectDraw = MVideoManager()->GetDirectDraw(); - HWND hWnd = MxOmni::GetInstance()->GetWindowHandle(); - - this->m_initialized = TRUE; - this->m_videoParam = p_videoParam; - - if (!this->m_videoParam.Flags().GetFullScreen()) - this->m_videoParam.Flags().SetFlipSurfaces(FALSE); - - if (!this->m_videoParam.Flags().GetFlipSurfaces()) { - this->m_videoParam.SetBackBuffers(1); - } - else { - MxU32 backBuffers = this->m_videoParam.GetBackBuffers(); - - if (backBuffers < 1) - this->m_videoParam.SetBackBuffers(1); - else if (backBuffers > 2) - this->m_videoParam.SetBackBuffers(2); - - this->m_videoParam.Flags().SetBackBuffers(TRUE); - } - - if (this->m_videoParam.Flags().GetFullScreen()) { - MxS32 width = this->m_videoParam.GetRect().GetWidth(); - MxS32 height = this->m_videoParam.GetRect().GetHeight(); - - if (lpDirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)) - goto done; - - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - - if (lpDirectDraw->GetDisplayMode(&ddsd)) - goto done; - - MxS32 bitdepth = !this->m_videoParam.Flags().Get16Bit() ? 8 : 16; - - if (ddsd.dwWidth != width || ddsd.dwHeight != height || ddsd.ddpfPixelFormat.dwRGBBitCount != bitdepth) { - if (lpDirectDraw->SetDisplayMode(width, height, bitdepth)) - goto done; - } - } - - if (this->m_videoParam.Flags().GetFlipSurfaces()) { - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwBackBufferCount = this->m_videoParam.GetBackBuffers(); - ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; - - if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) - goto done; - - ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; - - if (this->m_ddSurface1->GetAttachedSurface(&ddsd.ddsCaps, &this->m_ddSurface2)) - goto done; - } - else { - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) - goto done; - - memset(&ddsd, 0, sizeof(ddsd)); - ddsd.dwSize = sizeof(ddsd); - ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS; - ddsd.dwWidth = this->m_videoParam.GetRect().GetWidth(); - ddsd.dwHeight = this->m_videoParam.GetRect().GetHeight(); - ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN; - - if (!this->m_videoParam.Flags().GetBackBuffers()) - ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; - - if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface2, NULL)) - goto done; - } - - memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); - this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc); - - if (!this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) { - if (!lpDirectDraw->CreateClipper(0, &this->m_ddClipper, NULL) && !this->m_ddClipper->SetHWnd(0, hWnd) && - !this->m_ddSurface1->SetClipper(this->m_ddClipper)) - result = SUCCESS; - } - -done: - return result; -} - -// FUNCTION: LEGO1 0x100baa90 -void MxDisplaySurface::Clear() -{ - if (this->m_initialized) { - if (this->m_ddSurface2) - this->m_ddSurface2->Release(); - - if (this->m_ddSurface1) - this->m_ddSurface1->Release(); - - if (this->m_ddClipper) - this->m_ddClipper->Release(); - } - - if (this->m_16bitPal) - delete this->m_16bitPal; - - this->Reset(); -} - -// STUB: LEGO1 0x100baae0 -void MxDisplaySurface::SetPalette(MxPalette* p_palette) -{ -} - -// STUB: LEGO1 0x100bacc0 -MxBool MxDisplaySurface::VTable0x28(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) -{ - return 0; -} - -// STUB: LEGO1 0x100bb1d0 -MxBool MxDisplaySurface::VTable0x30( - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - MxBool -) -{ - return 0; -} - -// STUB: LEGO1 0x100bb850 -undefined4 MxDisplaySurface::VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) -{ - return 0; -} - -// STUB: LEGO1 0x100bba50 -void MxDisplaySurface::Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) -{ -} - -// FUNCTION: LEGO1 0x100bbc10 -void MxDisplaySurface::GetDC(HDC* p_hdc) -{ - if (this->m_ddSurface2 && !this->m_ddSurface2->GetDC(p_hdc)) - return; - - *p_hdc = NULL; -} - -// FUNCTION: LEGO1 0x100bbc40 -void MxDisplaySurface::ReleaseDC(HDC p_hdc) -{ - if (this->m_ddSurface2 && p_hdc) - this->m_ddSurface2->ReleaseDC(p_hdc); -} - -// STUB: LEGO1 0x100bbc60 -LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4) -{ - return NULL; -} - -// STUB: LEGO1 0x100bc200 -void MxDisplaySurface::VTable0x24( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4 -) -{ -} - -// STUB: LEGO1 0x100bc630 -MxBool MxDisplaySurface::VTable0x2c( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - MxBool -) -{ - return 0; -} diff --git a/LEGO1/mxdisplaysurface.h b/LEGO1/mxdisplaysurface.h deleted file mode 100644 index 3d386bb4..00000000 --- a/LEGO1/mxdisplaysurface.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef MXDISPLAYSURFACE_H -#define MXDISPLAYSURFACE_H - -#include "decomp.h" -#include "mxbitmap.h" -#include "mxcore.h" -#include "mxpalette.h" -#include "mxvideoparam.h" - -#include - -// VTABLE: LEGO1 0x100dc768 -// SIZE 0xac -class MxDisplaySurface : public MxCore { -public: - MxDisplaySurface(); - virtual ~MxDisplaySurface() override; - - void Reset(); - - void FUN_100ba640(); - - virtual MxResult Init( - MxVideoParam& p_videoParam, - LPDIRECTDRAWSURFACE p_ddSurface1, - LPDIRECTDRAWSURFACE p_ddSurface2, - LPDIRECTDRAWCLIPPER p_ddClipper - ); - virtual MxResult Create(MxVideoParam& p_videoParam); - virtual void Clear(); - virtual void SetPalette(MxPalette* p_palette); - virtual void VTable0x24( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4 - ); - virtual MxBool VTable0x28(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual MxBool VTable0x2c( - LPDDSURFACEDESC, - MxBitmap*, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - MxBool - ); - virtual MxBool VTable0x30( - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - undefined4, - MxBool - ); - virtual undefined4 VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual void Display(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4); - virtual void GetDC(HDC* p_hdc); - virtual void ReleaseDC(HDC p_hdc); - virtual LPDIRECTDRAWSURFACE VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4); - - inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } - inline LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return this->m_ddSurface2; } - inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } - -private: - MxVideoParam m_videoParam; - LPDIRECTDRAWSURFACE m_ddSurface1; - LPDIRECTDRAWSURFACE m_ddSurface2; - LPDIRECTDRAWCLIPPER m_ddClipper; - MxBool m_initialized; - DDSURFACEDESC m_surfaceDesc; - MxU16* m_16bitPal; -}; - -#endif // MXDISPLAYSURFACE_H diff --git a/LEGO1/mxdsaction.h b/LEGO1/mxdsaction.h deleted file mode 100644 index eb70b18f..00000000 --- a/LEGO1/mxdsaction.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef MXDSACTION_H -#define MXDSACTION_H - -#include "mxdsobject.h" -#include "mxtypes.h" -#include "realtime/vector.h" - -class MxOmni; - -// VTABLE: LEGO1 0x100dc098 -// SIZE 0x94 -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, - }; - - __declspec(dllexport) MxDSAction(); - __declspec(dllexport) virtual ~MxDSAction(); - - void CopyFrom(MxDSAction& p_dsAction); - MxDSAction& operator=(MxDSAction& p_dsAction); - - // FUNCTION: LEGO1 0x100ad980 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x101013f4 - return "MxDSAction"; - } - - // FUNCTION: LEGO1 0x100ad990 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxDSAction::ClassName()) || MxDSObject::IsA(p_name); - } - - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual MxLong GetDuration(); // vtable+24; - virtual void SetDuration(MxLong p_duration); // vtable+28; - virtual MxDSAction* Clone(); // vtable+2c; - virtual void MergeFrom(MxDSAction& p_dsAction); // vtable+30; - virtual MxBool HasId(MxU32 p_objectId); // vtable+34; - virtual void SetUnknown90(MxLong p_unk0x90); // vtable+38; - virtual MxLong GetUnknown90(); // vtable+3c; - virtual MxLong GetElapsedTime(); // vtable+40; - - void AppendData(MxU16 p_extraLength, const char* p_extraData); - - inline MxU32 GetFlags() { return m_flags; } - inline void SetFlags(MxU32 p_flags) { m_flags = p_flags; } - inline char* GetExtraData() { return m_extraData; } - inline MxU16 GetExtraLength() const { return m_extraLength; } - inline MxLong GetStartTime() const { return m_startTime; } - inline MxS32 GetLoopCount() { return m_loopCount; } - inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } - inline const Vector3Data& GetLocation() const { return m_location; } - 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 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); - } - -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 -}; - -#endif // MXDSACTION_H diff --git a/LEGO1/mxdsbuffer.cpp b/LEGO1/mxdsbuffer.cpp deleted file mode 100644 index 634afc6e..00000000 --- a/LEGO1/mxdsbuffer.cpp +++ /dev/null @@ -1,269 +0,0 @@ -#include "mxdsbuffer.h" - -#include "mxdschunk.h" -#include "mxdsstreamingaction.h" -#include "mxomni.h" -#include "mxstreamchunk.h" -#include "mxstreamcontroller.h" -#include "mxstreamer.h" - -DECOMP_SIZE_ASSERT(MxDSBuffer, 0x34); - -// FUNCTION: LEGO1 0x100c6470 -MxDSBuffer::MxDSBuffer() -{ - m_refcount = 0; - m_pBuffer = NULL; - m_pIntoBuffer = NULL; - m_pIntoBuffer2 = NULL; - m_unk0x14 = 0; - m_unk0x18 = 0; - m_unk0x1c = 0; - m_writeOffset = 0; - m_bytesRemaining = 0; - m_mode = MxDSBufferType_Preallocated; - m_unk0x30 = 0; -} - -// FUNCTION: LEGO1 0x100c6530 -MxDSBuffer::~MxDSBuffer() -{ - if (m_pBuffer != NULL) { - if (m_mode == MxDSBufferType_Chunk) { - // TODO - } - else if (m_mode == MxDSBufferType_Allocate || m_mode == MxDSBufferType_Unknown) { - delete[] m_pBuffer; - } - } - - m_unk0x14 = 0; - m_unk0x1c = 0; -} - -// FUNCTION: LEGO1 0x100c6640 -MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode) -{ - MxResult result = FAILURE; - MxU32 i = 0; - if (p_mode == MxDSBufferType_Allocate) { - m_pBuffer = new MxU8[p_bufferSize]; - } - else if (p_mode == MxDSBufferType_Chunk) { - MxStreamer* streamer = Streamer(); - // I have no clue as to what this does, or even if its correct. Maybe it's related to storing chunks in - // MxDiskStreamController? - if (p_bufferSize >> 10 == 0x40) { - i = 0; - while (i < 22) { - if ((*(MxU32*) ((streamer->GetSubclass1().GetUnk08() + ((i & 0xffffffe7) >> 3)) & 1 << ((MxU8) i & 0x1f) - )) == 0) { - MxU32* ptr = (MxU32*) ((streamer->GetSubclass1().GetUnk08() + ((i & 0xffffffe7) >> 3)) & - 1 << ((MxU8) i & 0x1f)); - - // mark it as used? - *ptr = *ptr ^ 1 << (i & 0x1f); - - m_pBuffer = - (MxU8*) (streamer->GetSubclass1().GetSize() * i * 0x400 + streamer->GetSubclass1().GetBuffer()); - break; - } - i++; - } - - m_pBuffer = NULL; - } - else if (p_bufferSize >> 10 == 0x80) { - i = 0; - // Same thing as above but it uses subclass2 - while (i < 22) { - if ((*(MxU32*) ((streamer->GetSubclass2().GetUnk08() + ((i & 0xffffffe7) >> 3)) & 1 << ((MxU8) i & 0x1f) - )) == 0) { - MxU32* ptr = (MxU32*) ((streamer->GetSubclass2().GetUnk08() + ((i & 0xffffffe7) >> 3)) & - 1 << ((MxU8) i & 0x1f)); - - // mark it as used? - *ptr = *ptr ^ 1 << (i & 0x1f); - - m_pBuffer = - (MxU8*) (streamer->GetSubclass2().GetSize() * i * 0x400 + streamer->GetSubclass2().GetBuffer()); - break; - } - i++; - } - - m_pBuffer = NULL; - } - else { - m_pIntoBuffer = NULL; - } - } - - m_pIntoBuffer = m_pBuffer; - m_pIntoBuffer2 = m_pBuffer; - if (m_pBuffer != NULL) { - m_mode = p_mode; - m_bytesRemaining = p_bufferSize; - m_writeOffset = p_bufferSize; - result = SUCCESS; - } - return result; -} - -// FUNCTION: LEGO1 0x100c6780 -MxResult MxDSBuffer::SetBufferPointer(MxU32* p_buffer, MxU32 p_size) -{ - m_pBuffer = (MxU8*) p_buffer; - m_pIntoBuffer = (MxU8*) p_buffer; - m_pIntoBuffer2 = (MxU8*) p_buffer; - m_bytesRemaining = p_size; - m_writeOffset = p_size; - m_mode = MxDSBufferType_Preallocated; - return SUCCESS; -} - -// STUB: LEGO1 0x100c67b0 -MxResult MxDSBuffer::FUN_100c67b0( - MxStreamController* p_controller, - MxDSAction* p_action, - MxDSStreamingAction** p_streamingAction -) -{ - // TODO STUB - return FAILURE; -} - -// FUNCTION: LEGO1 0x100c68a0 -MxResult MxDSBuffer::CreateObject( - MxStreamController* p_controller, - MxU32* p_data, - MxDSAction* p_action, - undefined4 p_undefined -) -{ - if (p_data == NULL) { - return FAILURE; - } - - MxCore* header = ReadChunk(this, p_data, p_action->GetUnknown24()); - - if (header == NULL) { - return FAILURE; - } - - if (*p_data == FOURCC('M', 'x', 'O', 'b')) - return StartPresenterFromAction(p_controller, p_action, (MxDSAction*) header); - else if (*p_data == FOURCC('M', 'x', 'C', 'h')) { - MxStreamChunk* chunk = (MxStreamChunk*) header; - if (!m_unk0x30->HasId((chunk)->GetObjectId())) { - delete header; - return SUCCESS; - } - - return ParseChunk(p_controller, p_data, p_action, p_undefined, chunk); - } - - delete header; - return FAILURE; -} - -// FUNCTION: LEGO1 0x100c6960 -MxResult MxDSBuffer::StartPresenterFromAction( - MxStreamController* p_controller, - MxDSAction* p_action1, - MxDSAction* p_objectheader -) -{ - if (!m_unk0x30->GetInternalAction()) { - p_objectheader->SetAtomId(p_action1->GetAtomId()); - p_objectheader->SetUnknown28(p_action1->GetUnknown28()); - p_objectheader->SetUnknown84(p_action1->GetUnknown84()); - p_objectheader->SetOrigin(p_action1->GetOrigin()); - p_objectheader->SetUnknown90(p_action1->GetUnknown90()); - p_objectheader->MergeFrom(*p_action1); - - m_unk0x30->SetInternalAction(p_objectheader->Clone()); - - p_controller->InsertActionToList54(p_objectheader); - - if (MxOmni::GetInstance()->CreatePresenter(p_controller, *p_objectheader) != SUCCESS) { - return FAILURE; - } - - m_unk0x30->SetLoopCount(p_objectheader->GetLoopCount()); - m_unk0x30->SetFlags(p_objectheader->GetFlags()); - m_unk0x30->SetDuration(p_objectheader->GetDuration()); - - if (m_unk0x30->GetInternalAction() == NULL) { - return FAILURE; - } - } - else if (p_objectheader) { - delete p_objectheader; - } - - return SUCCESS; -} - -// STUB: LEGO1 0x100c6a50 -MxResult MxDSBuffer::ParseChunk( - MxStreamController* p_controller, - MxU32* p_data, - MxDSAction* p_action, - undefined4, - MxStreamChunk* p_header -) -{ - // TODO - return FAILURE; -} - -// FUNCTION: LEGO1 0x100c6d00 -MxCore* MxDSBuffer::ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags) -{ - // This function reads a chunk. If it is an object, this function returns an MxDSObject. If it is a chunk, returns a - // MxDSChunk. - MxCore* result = NULL; - MxU8* dataStart = (MxU8*) p_chunkData + 8; - - switch (*p_chunkData) { - case FOURCC('M', 'x', 'O', 'b'): - result = DeserializeDSObjectDispatch(&dataStart, p_flags); - break; - case FOURCC('M', 'x', 'C', 'h'): - result = new MxStreamChunk(); - if (result != NULL && ((MxStreamChunk*) result)->ReadChunk(p_buffer, (MxU8*) p_chunkData) != SUCCESS) { - delete result; - result = NULL; - } - return result; - } - - return result; -} - -// FUNCTION: LEGO1 0x100c6ec0 -MxU8 MxDSBuffer::ReleaseRef(MxDSChunk*) -{ - if (m_refcount != 0) { - m_refcount--; - } - return 0; -} - -// FUNCTION: LEGO1 0x100c6ee0 -void MxDSBuffer::AddRef(MxDSChunk* p_chunk) -{ - if (p_chunk) { - m_refcount++; - } -} - -// FUNCTION: LEGO1 0x100c6f80 -void MxDSBuffer::FUN_100c6f80(MxU32 p_writeOffset) -{ - if (p_writeOffset < m_writeOffset) { - m_pIntoBuffer2 = m_pBuffer + p_writeOffset; - m_pIntoBuffer = m_pBuffer + p_writeOffset; - } -} diff --git a/LEGO1/mxdssource.h b/LEGO1/mxdssource.h deleted file mode 100644 index 724efca5..00000000 --- a/LEGO1/mxdssource.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef MXDSSOURCE_H -#define MXDSSOURCE_H - -#include "mxcore.h" - -class MxDSBuffer; - -// VTABLE: LEGO1 0x100dc8c8 -class MxDSSource : public MxCore { -public: - MxDSSource() : m_lengthInDWords(0), m_pBuffer(NULL), m_position(-1) {} - - // FUNCTION: LEGO1 0x100c0010 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x10102588 - return "MxDSSource"; - } - - // FUNCTION: LEGO1 0x100c0020 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxDSSource::ClassName()) || MxCore::IsA(p_name); - } - - virtual MxLong Open(MxULong) = 0; - virtual MxLong Close() = 0; - virtual void ReadToBuffer(MxDSBuffer* p_buffer); - virtual MxResult Read(unsigned char*, MxULong) = 0; - virtual MxLong Seek(MxLong, int) = 0; - virtual MxULong GetBufferSize() = 0; - virtual MxULong GetStreamBuffersNum() = 0; - virtual MxLong GetLengthInDWords(); - virtual MxU32* GetBuffer(); // 0x34 - -protected: - MxULong m_lengthInDWords; - MxU32* m_pBuffer; - MxLong m_position; -}; - -#endif // MXDSSOURCE_H diff --git a/LEGO1/mxdssubscriber.cpp b/LEGO1/mxdssubscriber.cpp deleted file mode 100644 index b4fa97a0..00000000 --- a/LEGO1/mxdssubscriber.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "mxdssubscriber.h" - -#include "mxstreamcontroller.h" - -DECOMP_SIZE_ASSERT(MxDSSubscriber, 0x4c); - -// FUNCTION: LEGO1 0x100b7bb0 -MxDSSubscriber::MxDSSubscriber() -{ - m_unk0x48 = -1; - m_objectId = -1; - m_unk0x20 = NULL; - m_unk0x3c = NULL; -} - -// FUNCTION: LEGO1 0x100b7e00 -MxDSSubscriber::~MxDSSubscriber() -{ - if (m_controller) - m_controller->FUN_100c1620(this); - - DeleteChunks(); - - if (m_unk0x20) - delete m_unk0x20; - m_unk0x20 = NULL; - - if (m_unk0x3c) - delete m_unk0x3c; - m_unk0x3c = NULL; -} - -// FUNCTION: LEGO1 0x100b7ed0 -MxResult MxDSSubscriber::Create(MxStreamController* p_controller, MxU32 p_objectId, MxS16 p_unk0x48) -{ - m_objectId = p_objectId; - m_unk0x48 = p_unk0x48; - - if (!p_controller) - return FAILURE; - m_controller = p_controller; - - m_unk0x20 = new MxStreamChunkListCursor(&m_unk0x08); - if (!m_unk0x20) - return FAILURE; - - m_unk0x3c = new MxStreamChunkListCursor(&m_unk0x24); - if (!m_unk0x3c) - return FAILURE; - - m_controller->FUN_100c15d0(this); - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100b8030 -void MxDSSubscriber::DeleteChunks() -{ - if (m_controller) { - MxStreamChunk* chunk = NULL; - - while (m_unk0x20->First(chunk)) { - m_unk0x20->Detach(); - delete chunk; - } - - while (m_unk0x3c->First(chunk)) { - m_unk0x3c->Detach(); - delete chunk; - } - } -} - -// FUNCTION: LEGO1 0x100b8150 -MxResult MxDSSubscriber::AddChunk(MxStreamChunk* p_chunk, MxBool p_append) -{ - if (m_unk0x20) { - if (p_append) - m_unk0x08.Append(p_chunk); - else - m_unk0x08.Prepend(p_chunk); - } - - return SUCCESS; -} - -// FUNCTION: LEGO1 0x100b8250 -MxStreamChunk* MxDSSubscriber::FUN_100b8250() -{ - MxStreamChunk* chunk = NULL; - - if (m_unk0x20) - m_unk0x20->First(chunk); - - if (chunk) { - m_unk0x20->Detach(); - m_unk0x24.Append(chunk); - } - - return chunk; -} - -// FUNCTION: LEGO1 0x100b8360 -MxStreamChunk* MxDSSubscriber::FUN_100b8360() -{ - MxStreamChunk* chunk = NULL; - - if (m_unk0x20) - m_unk0x20->First(chunk); - - return chunk; -} - -// FUNCTION: LEGO1 0x100b8390 -void MxDSSubscriber::FUN_100b8390(MxStreamChunk* p_chunk) -{ - if (p_chunk) { - if (m_unk0x3c->Find(p_chunk)) { - m_unk0x3c->Detach(); - if (p_chunk) - delete p_chunk; - } - else if ((p_chunk->GetFlags() & MxStreamChunk::Flag_Bit1) != 0 && p_chunk) - delete p_chunk; - } -} diff --git a/LEGO1/mxdstypes.h b/LEGO1/mxdstypes.h deleted file mode 100755 index f43742b9..00000000 --- a/LEGO1/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/mxentity.cpp b/LEGO1/mxentity.cpp deleted file mode 100644 index 1f507257..00000000 --- a/LEGO1/mxentity.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#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/mxentity.h b/LEGO1/mxentity.h deleted file mode 100644 index a83462cd..00000000 --- a/LEGO1/mxentity.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MXENTITY_H -#define MXENTITY_H - -#include "decomp.h" -#include "mxatomid.h" -#include "mxcore.h" -#include "mxdsobject.h" -#include "mxtypes.h" - -// VTABLE: LEGO1 0x100d5390 -// SIZE 0x10 -class MxEntity : public MxCore { -public: - MxEntity(); - virtual ~MxEntity() override; - - // FUNCTION: LEGO1 0x1000c180 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f0070 - return "MxEntity"; - } - - // FUNCTION: LEGO1 0x1000c190 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - 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) - { - m_mxEntityId = p_dsObject.GetObjectId(); - m_atom = p_dsObject.GetAtomId(); - return SUCCESS; - } - -protected: - MxS32 m_mxEntityId; // 0x8 - MxAtomId m_atom; // 0xc -}; - -#endif // MXENTITY_H diff --git a/LEGO1/mxeventpresenter.h b/LEGO1/mxeventpresenter.h deleted file mode 100644 index d022f609..00000000 --- a/LEGO1/mxeventpresenter.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef MXEVENTPRESENTER_H -#define MXEVENTPRESENTER_H - -#include "decomp.h" -#include "mxmediapresenter.h" - -// VTABLE: LEGO1 0x100dca88 -// SIZE 0x54 -class MxEventPresenter : public MxMediaPresenter { -public: - MxEventPresenter(); - virtual ~MxEventPresenter() override; - - // FUNCTION: LEGO1 0x100c2c30 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x10101dcc - return "MxEventPresenter"; - } - - // FUNCTION: LEGO1 0x100c2c40 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxEventPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); - } - - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual MxResult PutData() override; // vtable+0x4c - virtual void CopyData(MxStreamChunk* p_chunk); // vtable+0x5c - -private: - void Init(); - - MxU8* m_data; // 0x50 -}; - -#endif // MXEVENTPRESENTER_H diff --git a/LEGO1/mxflcpresenter.cpp b/LEGO1/mxflcpresenter.cpp deleted file mode 100644 index 76cc7efe..00000000 --- a/LEGO1/mxflcpresenter.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "mxflcpresenter.h" - -#include "decomp.h" -#include "mxbitmap.h" -#include "mxomni.h" -#include "mxpalette.h" -#include "mxvideomanager.h" - -DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); - -// FUNCTION: LEGO1 0x100b3310 -MxFlcPresenter::MxFlcPresenter() -{ - this->m_flicHeader = NULL; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; -} - -// FUNCTION: LEGO1 0x100b3420 -MxFlcPresenter::~MxFlcPresenter() -{ - if (this->m_flicHeader) { - delete this->m_flicHeader; - } -} - -// FUNCTION: LEGO1 0x100b3490 -void MxFlcPresenter::LoadHeader(MxStreamChunk* p_chunk) -{ - m_flicHeader = (FLIC_HEADER*) new MxU8[p_chunk->GetLength()]; - memcpy(m_flicHeader, p_chunk->GetData(), p_chunk->GetLength()); -} - -// FUNCTION: LEGO1 0x100b34d0 -void MxFlcPresenter::CreateBitmap() -{ - if (m_bitmap) - delete m_bitmap; - - m_bitmap = new MxBitmap; - m_bitmap->SetSize(m_flicHeader->width, m_flicHeader->height, NULL, FALSE); -} - -// FUNCTION: LEGO1 0x100b3620 -void MxFlcPresenter::RealizePalette() -{ - MxPalette* palette = m_bitmap->CreatePalette(); - MVideoManager()->RealizePalette(palette); - delete palette; -} diff --git a/LEGO1/mxflcpresenter.h b/LEGO1/mxflcpresenter.h deleted file mode 100644 index 393e2810..00000000 --- a/LEGO1/mxflcpresenter.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MXFLCPRESENTER_H -#define MXFLCPRESENTER_H - -#include "decomp.h" -#include "mxvideopresenter.h" - -#include - -// VTABLE: LEGO1 0x100dc2c0 -// SIZE 0x68 -class MxFlcPresenter : public MxVideoPresenter { -public: - MxFlcPresenter(); - virtual ~MxFlcPresenter() override; - - // FUNCTION: LEGO1 0x1004e200 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxFlcPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); - } - - // FUNCTION: LEGO1 0x100b33f0 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f43c8 - return "MxFlcPresenter"; - } - - virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c - virtual void CreateBitmap() override; // vtable+0x60 - virtual void RealizePalette() override; // vtable+0x70 - -protected: - FLIC_HEADER* m_flicHeader; -}; - -#endif // MXFLCPRESENTER_H diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h new file mode 100644 index 00000000..837a5b3a --- /dev/null +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -0,0 +1,52 @@ +#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; + } + + // SYNTHETIC: LEGO1 0x1001d170 + // Mx3DPointFloat::Mx3DPointFloat + + // 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.h b/LEGO1/mxgeometry/mxmatrix.h new file mode 100644 index 00000000..81cdaa2c --- /dev/null +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -0,0 +1,25 @@ +#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); } + + // FUNCTION: LEGO1 0x10002850 + void operator=(const Matrix4& p_matrix) override { Equals(p_matrix); } // vtable+0x28 + + // No idea why there's another equals. Maybe to some other type like the + // DirectX Retained Mode Matrix type which is also a float* alias? + // 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/mxloopingflcpresenter.cpp b/LEGO1/mxloopingflcpresenter.cpp deleted file mode 100644 index cb4fd40b..00000000 --- a/LEGO1/mxloopingflcpresenter.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "mxloopingflcpresenter.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(MxLoopingFlcPresenter, 0x6c); - -// FUNCTION: LEGO1 0x100b4310 -MxLoopingFlcPresenter::MxLoopingFlcPresenter() -{ - Init(); -} - -// FUNCTION: LEGO1 0x100b43b0 -MxLoopingFlcPresenter::~MxLoopingFlcPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x100b4410 -void MxLoopingFlcPresenter::Init() -{ - this->m_unk0x68 = 0; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; -} - -// STUB: LEGO1 0x100b4432 -void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor) -{ - // TODO -} - -// FUNCTION: LEGO1 0x100b4470 -void MxLoopingFlcPresenter::NextFrame() -{ - MxStreamChunk* chunk = NextChunk(); - - if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; - } - else { - LoadFrame(chunk); - AppendChunk(chunk); - m_unk0x68 += m_flicHeader->speed; - } - - m_subscriber->FUN_100b8390(chunk); -} diff --git a/LEGO1/mxloopingflcpresenter.h b/LEGO1/mxloopingflcpresenter.h deleted file mode 100644 index e4f781c9..00000000 --- a/LEGO1/mxloopingflcpresenter.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef MXLOOPINGFLCPRESENTER_H -#define MXLOOPINGFLCPRESENTER_H - -#include "decomp.h" -#include "mxflcpresenter.h" - -// VTABLE: LEGO1 0x100dc480 -// SIZE 0x6c -class MxLoopingFlcPresenter : public MxFlcPresenter { -public: - MxLoopingFlcPresenter(); - virtual ~MxLoopingFlcPresenter() override; - - // FUNCTION: LEGO1 0x100b4380 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x10101e20 - return "MxLoopingFlcPresenter"; - } - - virtual void NextFrame() override; // vtable+0x64 - -private: - void Init(); - void Destroy(MxBool p_fromDestructor); - - undefined4 m_unk0x68; -}; - -#endif // MXLOOPINGFLCPRESENTER_H diff --git a/LEGO1/mxmediamanager.h b/LEGO1/mxmediamanager.h deleted file mode 100644 index 47f7f0d1..00000000 --- a/LEGO1/mxmediamanager.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef MXMEDIAMANGER_H -#define MXMEDIAMANGER_H - -#include "mxcore.h" -#include "mxcriticalsection.h" -#include "mxpresenterlist.h" -#include "mxthread.h" -#include "mxtypes.h" - -// VTABLE: LEGO1 0x100dc6b0 -// SIZE 0x2c -class MxMediaManager : public MxCore { -public: - 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 - - MxResult Init(); - -protected: - MxPresenterList* m_presenters; - MxThread* m_thread; // 0xc - MxCriticalSection m_criticalSection; // 0x10 -}; - -#endif // MXMEDIAMANGER_H diff --git a/LEGO1/mxmediapresenter.h b/LEGO1/mxmediapresenter.h deleted file mode 100644 index 4a482a78..00000000 --- a/LEGO1/mxmediapresenter.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef MXMEDIAPRESENTER_H -#define MXMEDIAPRESENTER_H - -#include "decomp.h" -#include "mxdssubscriber.h" -#include "mxpresenter.h" -#include "mxstreamchunklist.h" - -// VTABLE: LEGO1 0x100d4cd8 -// SIZE 0x50 -class MxMediaPresenter : public MxPresenter { -public: - inline MxMediaPresenter() { Init(); } - virtual ~MxMediaPresenter() override; - - virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x1000c5c0 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f074c - return "MxMediaPresenter"; - } - - // FUNCTION: LEGO1 0x1000c5d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxMediaPresenter::ClassName()) || MxPresenter::IsA(p_name); - } - - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void DoneTickle() override; // vtable+0x2c - virtual void Destroy() override; // vtable+0x38 - virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void AppendChunk(MxStreamChunk* p_chunk); // vtable+0x58 - -protected: - MxDSSubscriber* m_subscriber; // 0x40 - MxStreamChunkList* m_chunks; // 0x44 - MxStreamChunkListCursor* m_cursor; // 0x48 - MxStreamChunk* m_currentChunk; // 0x4c - - void Init(); - void Destroy(MxBool p_fromDestructor); - -public: - MxStreamChunk* FUN_100b5650(); - MxStreamChunk* NextChunk(); -}; - -// SYNTHETIC: LEGO1 0x100b46e0 -// MxStreamChunkListCursor::`scalar deleting destructor' - -// TEMPLATE: LEGO1 0x100b4750 -// MxListCursor::~MxListCursor - -// SYNTHETIC: LEGO1 0x100b47a0 -// MxListCursor::`scalar deleting destructor' - -// FUNCTION: LEGO1 0x100b4810 -// MxStreamChunkListCursor::~MxStreamChunkListCursor - -#endif // MXMEDIAPRESENTER_H diff --git a/LEGO1/mxmidipresenter.h b/LEGO1/mxmidipresenter.h deleted file mode 100644 index 09e11dde..00000000 --- a/LEGO1/mxmidipresenter.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef MXMIDIPRESENTER_H -#define MXMIDIPRESENTER_H - -#include "mxmusicpresenter.h" -#include "mxstreamchunk.h" - -// VTABLE: LEGO1 0x100dca20 -// SIZE 0x58 -class MxMIDIPresenter : public MxMusicPresenter { -public: - MxMIDIPresenter(); - virtual ~MxMIDIPresenter() override; - - // FUNCTION: LEGO1 0x100c2650 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x10101df8 - return "MxMIDIPresenter"; - } - - // FUNCTION: LEGO1 0x100c2660 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxMIDIPresenter::ClassName()) || MxMusicPresenter::IsA(p_name); - } - - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual void Destroy() override; // vtable+0x38 - virtual void EndAction() override; // vtable+0x40 - virtual MxResult PutData() override; // vtable+0x4c - virtual void SetVolume(MxS32 p_volume) override; // vtable+0x60 - -private: - void Init(); - void Destroy(MxBool p_fromDestructor); - -protected: - MxStreamChunk* m_chunk; -}; - -#endif // MXMIDIPRESENTER_H diff --git a/LEGO1/mxmusicmanager.cpp b/LEGO1/mxmusicmanager.cpp deleted file mode 100644 index 244e3861..00000000 --- a/LEGO1/mxmusicmanager.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "mxmusicmanager.h" - -#include "mxomni.h" -#include "mxticklemanager.h" - -#include - -DECOMP_SIZE_ASSERT(MxMusicManager, 0x58); - -// FUNCTION: LEGO1 0x100c05a0 -MxMusicManager::MxMusicManager() -{ - Init(); -} - -// FUNCTION: LEGO1 0x100c0630 -MxMusicManager::~MxMusicManager() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x100c0690 -void MxMusicManager::Init() -{ - m_multiplier = 100; - InitData(); -} - -// FUNCTION: LEGO1 0x100c06a0 -void MxMusicManager::InitData() -{ - m_midiStreamH = 0; - m_midiInitialized = FALSE; - m_unk0x38 = 0; - m_unk0x3c = 0; - m_unk0x40 = 0; - m_unk0x44 = 0; - m_unk0x48 = 0; - m_midiHdrP = NULL; -} - -// FUNCTION: LEGO1 0x100c06c0 -void MxMusicManager::Destroy(MxBool p_fromDestructor) -{ - if (m_thread) { - m_thread->Terminate(); - if (m_thread) { - delete m_thread; - } - } - else { - TickleManager()->UnregisterClient(this); - } - - m_criticalSection.Enter(); - DeinitializeMIDI(); - Init(); - m_criticalSection.Leave(); - - if (!p_fromDestructor) { - MxAudioManager::Destroy(); - } -} - -// FUNCTION: LEGO1 0x100c07f0 -void MxMusicManager::SetMIDIVolume() -{ - MxS32 result = (m_volume * m_multiplier) / 0x64; - HMIDISTRM streamHandle = m_midiStreamH; - - if (streamHandle) { - MxS32 volume = CalculateVolume(result); - midiOutSetVolume((HMIDIOUT) streamHandle, volume); - } -} - -// FUNCTION: LEGO1 0x100c0840 -MxResult MxMusicManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) -{ - MxResult status = FAILURE; - MxBool locked = FALSE; - - if (MxAudioManager::InitPresenters() == SUCCESS) { - if (p_createThread) { - m_criticalSection.Enter(); - locked = TRUE; - m_thread = new MxTickleThread(this, p_frequencyMS); - - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) - goto done; - } - else - TickleManager()->RegisterClient(this, p_frequencyMS); - - status = SUCCESS; - } - -done: - if (status != SUCCESS) - Destroy(); - - if (locked) - m_criticalSection.Leave(); - - return status; -} - -// FUNCTION: LEGO1 0x100c0930 -void MxMusicManager::Destroy() -{ - Destroy(FALSE); -} - -// FUNCTION: LEGO1 0x100c0940 -void MxMusicManager::SetVolume(MxS32 p_volume) -{ - MxAudioManager::SetVolume(p_volume); - m_criticalSection.Enter(); - SetMIDIVolume(); - m_criticalSection.Leave(); -} - -// FUNCTION: LEGO1 0x100c0970 -void MxMusicManager::SetMultiplier(MxS32 p_multiplier) -{ - m_criticalSection.Enter(); - m_multiplier = p_multiplier; - SetMIDIVolume(); - m_criticalSection.Leave(); -} - -// FUNCTION: LEGO1 0x100c09a0 -MxS32 MxMusicManager::CalculateVolume(MxS32 p_volume) -{ - MxS32 result = (p_volume * 0xffff) / 100; - return (result << 0x10) | result; -} - -// STUB: LEGO1 0x100c09c0 -undefined4 MxMusicManager::FUN_100c09c0(MxU8* p_data, MxS32 p_loopCount) -{ - // TODO - return 0; -} - -// FUNCTION: LEGO1 0x100c0b20 -void MxMusicManager::DeinitializeMIDI() -{ - m_criticalSection.Enter(); - - if (m_midiInitialized) { - m_midiInitialized = FALSE; - midiStreamStop(m_midiStreamH); - midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR)); - midiOutSetVolume((HMIDIOUT) m_midiStreamH, m_midiVolume); - midiStreamClose(m_midiStreamH); - delete m_midiHdrP; - InitData(); - } - - m_criticalSection.Leave(); -} diff --git a/LEGO1/mxmusicmanager.h b/LEGO1/mxmusicmanager.h deleted file mode 100644 index d9f6d46d..00000000 --- a/LEGO1/mxmusicmanager.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef MXMUSICMANAGER_H -#define MXMUSICMANAGER_H - -#include "decomp.h" -#include "mxaudiomanager.h" - -// VTABLE: LEGO1 0x100dc930 -// SIZE 0x58 -class MxMusicManager : public MxAudioManager { -public: - MxMusicManager(); - virtual ~MxMusicManager() override; - - virtual void Destroy() override; // vtable+18 - virtual void SetVolume(MxS32 p_volume) override; // vtable+2c - virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+30 - - inline MxBool GetMIDIInitialized() { return m_midiInitialized; } - - void DeinitializeMIDI(); - undefined4 FUN_100c09c0(MxU8* p_data, MxS32 p_loopCount); - void SetMultiplier(MxS32 p_multiplier); - -private: - void Destroy(MxBool p_fromDestructor); - - MxS32 CalculateVolume(MxS32 p_volume); - void SetMIDIVolume(); - - HMIDISTRM m_midiStreamH; // 0x30 - MxBool m_midiInitialized; // 0x34 - undefined4 m_unk0x38; // 0x38 - undefined4 m_unk0x3c; // 0x3c - undefined4 m_unk0x40; // 0x40 - undefined4 m_unk0x44; // 0x44 - undefined4 m_unk0x48; // 0x48 - MIDIHDR* m_midiHdrP; // 0x4c - MxS32 m_multiplier; // 0x50 - DWORD m_midiVolume; // 0x54 - -protected: - void Init(); - void InitData(); -}; - -#endif // MXMUSICMANAGER_H diff --git a/LEGO1/mxnotificationparam.cpp b/LEGO1/mxnotificationparam.cpp deleted file mode 100644 index 0797c9f1..00000000 --- a/LEGO1/mxnotificationparam.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "mxnotificationparam.h" - -#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/mxomnicreateflags.h b/LEGO1/mxomnicreateflags.h deleted file mode 100644 index a94ed45a..00000000 --- a/LEGO1/mxomnicreateflags.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef MXOMNICREATEFLAGS_H -#define MXOMNICREATEFLAGS_H - -#include "mxtypes.h" - -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 - }; - - enum HighFlags { - Flag_CreateTimer = 0x02, - Flag_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 CreateTimer() const { return this->m_flags2 & Flag_CreateTimer; } - inline const MxBool CreateStreamer() const { return this->m_flags2 & Flag_CreateStreamer; } - - inline void CreateObjectFactory(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateObjectFactory : this->m_flags1 & ~Flag_CreateObjectFactory); - } - inline void CreateVariableTable(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateVariableTable : this->m_flags1 & ~Flag_CreateVariableTable); - } - inline void CreateTickleManager(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateTickleManager : this->m_flags1 & ~Flag_CreateTickleManager); - } - inline void CreateNotificationManager(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateNotificationManager - : this->m_flags1 & ~Flag_CreateNotificationManager); - } - inline void CreateVideoManager(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateVideoManager : this->m_flags1 & ~Flag_CreateVideoManager); - } - inline void CreateSoundManager(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateSoundManager : this->m_flags1 & ~Flag_CreateSoundManager); - } - inline void CreateMusicManager(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateMusicManager : this->m_flags1 & ~Flag_CreateMusicManager); - } - inline void CreateEventManager(MxBool p_enable) - { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateEventManager : this->m_flags1 & ~Flag_CreateEventManager); - } - - inline void CreateTimer(MxBool p_enable) - { - this->m_flags2 = (p_enable ? this->m_flags2 | Flag_CreateTimer : this->m_flags2 & ~Flag_CreateTimer); - } - inline void CreateStreamer(MxBool p_enable) - { - this->m_flags2 = (p_enable ? this->m_flags2 | Flag_CreateStreamer : this->m_flags2 & ~Flag_CreateStreamer); - } - -private: - MxU8 m_flags1; - MxU8 m_flags2; -}; - -#endif // MXOMNICREATEFLAGS_H diff --git a/LEGO1/mxparam.cpp b/LEGO1/mxparam.cpp deleted file mode 100644 index 4faa1625..00000000 --- a/LEGO1/mxparam.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "mxparam.h" diff --git a/LEGO1/mxparam.h b/LEGO1/mxparam.h deleted file mode 100644 index 19e92e0e..00000000 --- a/LEGO1/mxparam.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MXPARAM_H -#define MXPARAM_H - -class MxParam { -public: - virtual ~MxParam() {} -}; - -#endif // MXPARAM_H diff --git a/LEGO1/mxpresenter.h b/LEGO1/mxpresenter.h deleted file mode 100644 index 160329c1..00000000 --- a/LEGO1/mxpresenter.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef MXPRESENTER_H -#define MXPRESENTER_H - -#include "decomp.h" -#include "mxcore.h" -#include "mxcriticalsection.h" -#include "mxdsaction.h" -#include "mxomni.h" -#include "mxpoint32.h" - -class MxCompositePresenter; -class MxStreamController; - -// VTABLE: LEGO1 0x100d4d38 -// SIZE 0x40 -class MxPresenter : public MxCore { -public: - enum TickleState { - TickleState_Idle = 0, - TickleState_Ready, - TickleState_Starting, - TickleState_Streaming, - TickleState_Repeating, - TickleState_unk5, - TickleState_Done, - }; - - MxPresenter() { Init(); } - - __declspec(dllexport) virtual ~MxPresenter(); // vtable+0x0 - __declspec(dllexport) virtual MxResult Tickle() override; // vtable+0x8 - - // FUNCTION: LEGO1 0x1000bfe0 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f0740 - return "MxPresenter"; - } - - // FUNCTION: LEGO1 0x1000bff0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - 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 - -protected: - __declspec(dllexport) virtual void DoneTickle(); // vtable+0x2c - __declspec(dllexport) virtual void ParseExtra(); // vtable+0x30 - -public: - virtual MxResult AddToManager(); // vtable+0x34 - virtual void Destroy(); // 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 - - MxBool IsEnabled(); - - inline MxS32 GetCurrentTickleState() const { return this->m_currentTickleState; } - inline MxPoint32 GetLocation() const { return this->m_location; } - inline MxS32 GetDisplayZ() const { return this->m_displayZ; } - inline MxDSAction* GetAction() const { return this->m_action; } - - inline void SetCompositePresenter(MxCompositePresenter* p_compositePresenter) - { - m_compositePresenter = p_compositePresenter; - } - -protected: - __declspec(dllexport) void Init(); - void SendToCompositePresenter(MxOmni*); - - TickleState m_currentTickleState; // 0x8 - MxU32 m_previousTickleStates; // 0x0c - MxPoint32 m_location; // 0x10 - MxS32 m_displayZ; // 0x18 - MxDSAction* m_action; // 0x1c - MxCriticalSection m_criticalSection; // 0x20 - MxCompositePresenter* m_compositePresenter; // 0x3c -}; - -const char* PresenterNameDispatch(const MxDSAction&); - -#endif // MXPRESENTER_H diff --git a/LEGO1/mxramstreamprovider.h b/LEGO1/mxramstreamprovider.h deleted file mode 100644 index 112f6b71..00000000 --- a/LEGO1/mxramstreamprovider.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MXRAMSTREAMPROVIDER_H -#define MXRAMSTREAMPROVIDER_H - -#include "mxstreamprovider.h" - -// VTABLE: LEGO1 0x100dd0d0 -class MxRAMStreamProvider : public MxStreamProvider { -public: - MxRAMStreamProvider(); - virtual ~MxRAMStreamProvider() override; - - // FUNCTION: LEGO1 0x100d0970 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x10102864 - return "MxRAMStreamProvider"; - } - - // FUNCTION: LEGO1 0x100d0980 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxRAMStreamProvider::ClassName()) || MxStreamProvider::IsA(p_name); - } - - virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 - virtual MxU32 GetFileSize() override; // vtable+0x18 - virtual MxS32 GetStreamBuffersNum() override; // vtable+0x1c - virtual MxU32 GetLengthInDWords() override; // vtable+0x24 - virtual MxU32* GetBufferForDWords() override; // vtable+0x28 - - inline MxU32* GetBufferOfFileSize() { return m_pBufferOfFileSize; } - -protected: - MxU32 m_bufferSize; - MxU32 m_fileSize; - MxU32* m_pBufferOfFileSize; - MxU32 m_lengthInDWords; - MxU32* m_bufferForDWords; -}; - -#endif // MXRAMSTREAMPROVIDER_H diff --git a/LEGO1/mxregion.h b/LEGO1/mxregion.h deleted file mode 100644 index be15a672..00000000 --- a/LEGO1/mxregion.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef MXREGION_H -#define MXREGION_H - -#include "decomp.h" -#include "mxcore.h" -#include "mxrect32.h" -#include "mxregionlist.h" - -// VTABLE: LEGO1 0x100dcae8 -// SIZE 0x1c -class MxRegion : public MxCore { -public: - MxRegion(); - virtual ~MxRegion() override; - - virtual void Reset(); - virtual void VTable0x18(MxRect32& p_rect); - virtual MxBool VTable0x1c(MxRect32& p_rect); - virtual MxBool VTable0x20(); - - inline MxRect32& GetRect() { return this->m_rect; } - -private: - MxRegionList* m_list; - MxRect32 m_rect; -}; - -#endif // MXREGION_H diff --git a/LEGO1/mxsmkpresenter.h b/LEGO1/mxsmkpresenter.h deleted file mode 100644 index 95b6a201..00000000 --- a/LEGO1/mxsmkpresenter.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef MXSMKPRESENTER_H -#define MXSMKPRESENTER_H - -#include "decomp.h" -#include "mxsmack.h" -#include "mxvideopresenter.h" - -// VTABLE: LEGO1 0x100dc348 -// SIZE 0x720 -class MxSmkPresenter : public MxVideoPresenter { -public: - MxSmkPresenter(); - virtual ~MxSmkPresenter() override; - - // FUNCTION: LEGO1 0x100b3730 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x10101e38 - return "MxSmkPresenter"; - } - - // FUNCTION: LEGO1 0x100b3740 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxSmkPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); - } - - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c - virtual void CreateBitmap() override; // vtable+0x60 - virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 - virtual void RealizePalette() override; // vtable+0x70 - virtual void VTable0x88(); // vtable+0x88 - -private: - void Init(); - void Destroy(MxBool p_fromDestructor); - -protected: - MxSmack m_mxSmack; // 0x64 - MxU32 m_currentFrame; // 0x71c -}; - -#endif // MXSMKPRESENTER_H diff --git a/LEGO1/mxstillpresenter.h b/LEGO1/mxstillpresenter.h deleted file mode 100644 index e28ab84f..00000000 --- a/LEGO1/mxstillpresenter.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MXSTILLPRESENTER_H -#define MXSTILLPRESENTER_H - -#include "decomp.h" -#include "mxvideopresenter.h" - -// VTABLE: LEGO1 0x100d7a38 -// SIZE 0x6c -class MxStillPresenter : public MxVideoPresenter { -public: - MxStillPresenter() { m_bitmapInfo = NULL; } - // FUNCTION: LEGO1 0x10043550 - virtual ~MxStillPresenter() override { Destroy(TRUE); }; // vtable+0x00 - - // FUNCTION: LEGO1 0x100435c0 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f0184 - return "MxStillPresenter"; - } - - // FUNCTION: LEGO1 0x100435d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxStillPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); - } - - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual void Destroy() override; // vtable+0x38 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c - virtual void CreateBitmap() override; // vtable+0x60 - virtual void NextFrame() override; // vtable+0x64 - virtual void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 - virtual void RealizePalette() override; // vtable+0x70 - virtual void VTable0x88(MxS32 p_x, MxS32 p_y); // vtable+0x88 - virtual MxStillPresenter* Clone(); // vtable+0x8c - -private: - void Destroy(MxBool p_fromDestructor); - - MxLong m_chunkTime; // 0x64 - MxBITMAPINFO* m_bitmapInfo; // 0x68 -}; - -// SYNTHETIC: LEGO1 0x100436e0 -// MxStillPresenter::`scalar deleting destructor' - -#endif // MXSTILLPRESENTER_H diff --git a/LEGO1/mxstl/stlcompat.h b/LEGO1/mxstl/stlcompat.h index bc0076bf..29c31549 100644 --- a/LEGO1/mxstl/stlcompat.h +++ b/LEGO1/mxstl/stlcompat.h @@ -10,9 +10,13 @@ #else #include #include +#include #include +#include using std::list; +using std::map; using std::set; +using std::vector; #endif #endif // STLCOMPAT_H diff --git a/LEGO1/mxstreamlist.h b/LEGO1/mxstreamlist.h deleted file mode 100644 index 9b65c53d..00000000 --- a/LEGO1/mxstreamlist.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MXSTREAMLIST_H -#define MXSTREAMLIST_H - -#include "mxdsaction.h" -#include "mxdssubscriber.h" -#include "mxnextactiondatastart.h" -#include "mxstl/stlcompat.h" - -template -class MxStreamList : public list { -public: - MxBool PopFront(T& p_obj) - { - if (empty()) - return FALSE; - - p_obj = front(); - pop_front(); - return TRUE; - } -}; - -// SIZE 0xc -class MxStreamListMxDSAction : public MxStreamList { -public: - MxDSAction* Find(MxDSAction* p_action, MxBool p_delete); -}; - -// SIZE 0xc -class MxStreamListMxNextActionDataStart : public MxStreamList { -public: - MxNextActionDataStart* Find(MxU32, MxS16); -}; - -// SIZE 0xc -class MxStreamListMxDSSubscriber : public MxStreamList {}; - -#endif // MXSTREAMLIST_H diff --git a/LEGO1/mxtransitionmanager.h b/LEGO1/mxtransitionmanager.h deleted file mode 100644 index e55e4804..00000000 --- a/LEGO1/mxtransitionmanager.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef MXTRANSITIONMANAGER_H -#define MXTRANSITIONMANAGER_H - -#include "legoomni.h" -#include "mxcore.h" -#include "mxvideopresenter.h" - -#include - -// VTABLE: LEGO1 0x100d7ea0 -class MxTransitionManager : public MxCore { -public: - MxTransitionManager(); - virtual ~MxTransitionManager() override; // vtable+0x0 - - __declspec(dllexport) void SetWaitIndicator(MxVideoPresenter* p_waitIndicator); - - virtual MxResult Tickle(); // vtable+0x8 - - // FUNCTION: LEGO1 0x1004b950 - inline virtual const char* ClassName() const override // vtable+0x0c - { - return "MxTransitionManager"; - } - - // FUNCTION: LEGO1 0x1004b960 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxTransitionManager::ClassName()) || MxCore::IsA(p_name); - } - - 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 - }; - - MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim); - -private: - void EndTransition(MxBool p_notifyWorld); - void TransitionNone(); - void TransitionDissolve(); - void TransitionPixelation(); - void TransitionWipe(); - void TransitionWindows(); - void TransitionBroken(); - - void SubmitCopyRect(LPDDSURFACEDESC p_ddsc); - void SetupCopyRect(LPDDSURFACEDESC p_ddsc); - - MxVideoPresenter* m_waitIndicator; - RECT m_copyRect; - MxU8* m_copyBuffer; - - FlagBitfield m_copyFlags; - undefined4 m_unk0x24; - FlagBitfield m_unk0x28; - - TransitionType m_transitionType; - LPDIRECTDRAWSURFACE m_ddSurface; - MxU16 m_animationTimer; - MxU16 m_columnOrder[640]; // 0x36 - MxU16 m_randomShift[480]; // 0x536 - MxULong m_systemTime; // 0x8f8 - MxS32 m_animationSpeed; // 0x8fc -}; - -#endif // MXTRANSITIONMANAGER_H diff --git a/LEGO1/mxtype17notificationparam.cpp b/LEGO1/mxtype17notificationparam.cpp deleted file mode 100644 index dbb047f6..00000000 --- a/LEGO1/mxtype17notificationparam.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "mxtype17notificationparam.h" - -DECOMP_SIZE_ASSERT(MxType17NotificationParam, 0x2c) diff --git a/LEGO1/mxtype17notificationparam.h b/LEGO1/mxtype17notificationparam.h deleted file mode 100644 index cf4e78fa..00000000 --- a/LEGO1/mxtype17notificationparam.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef MXTYPE17NOTIFICATIONPARAM_H -#define MXTYPE17NOTIFICATIONPARAM_H - -#include "decomp.h" -#include "mxnotificationparam.h" - -// ??? This type is handled, but seemingly never created and no VTABLE fits -class MxType17NotificationParam : public MxNotificationParam { -public: - inline MxU32 GetUnknown20() { return m_unk0x20; } - inline MxU16 GetUnknown28() { return m_unk0x28; } - -protected: - undefined m_unk0xc[0x14]; - MxU32 m_unk0x20; - undefined4 m_unk0x24; - MxU16 m_unk0x28; -}; - -#endif // MXTYPE17NOTIFICATIONPARAM_H diff --git a/LEGO1/mxunknown100dbdbc.cpp b/LEGO1/mxunknown100dbdbc.cpp deleted file mode 100644 index a420454a..00000000 --- a/LEGO1/mxunknown100dbdbc.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "mxunknown100dbdbc.h" - -#include "decomp.h" - -DECOMP_SIZE_ASSERT(MxUnknown100dbdbc, 0x14) - -// STUB: LEGO1 0x100a6fd0 -MxUnknown100dbdbc::MxUnknown100dbdbc() -{ - // TODO -} diff --git a/LEGO1/mxunknown100dbdbc.h b/LEGO1/mxunknown100dbdbc.h deleted file mode 100644 index 157058a7..00000000 --- a/LEGO1/mxunknown100dbdbc.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef MXUNKNOWN100DBDBC_H -#define MXUNKNOWN100DBDBC_H - -#include "decomp.h" -#include "mxtypes.h" - -// VTABLE: LEGO1 0x100dbdbc -// SIZE 0x14 -class MxUnknown100dbdbc { -public: - MxUnknown100dbdbc(); - -private: - undefined m_unk0x4[0x14]; // TODO: change to 0x10 once scalar deconstructor is added -}; - -#endif // MXUNKNOWN100DBDBC_H diff --git a/LEGO1/mxvariable.cpp b/LEGO1/mxvariable.cpp deleted file mode 100644 index a60051fd..00000000 --- a/LEGO1/mxvariable.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "mxvariable.h" - -#include "decomp.h" -#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/mxvideopresenter.h b/LEGO1/mxvideopresenter.h deleted file mode 100644 index d25ecb2b..00000000 --- a/LEGO1/mxvideopresenter.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef MXVIDEOPRESENTER_H -#define MXVIDEOPRESENTER_H - -#include "decomp.h" -#include "mxbitmap.h" -#include "mxmediapresenter.h" - -// VTABLE: LEGO1 0x100d4be8 -// SIZE 0x64 -class MxVideoPresenter : public MxMediaPresenter { -public: - enum { - Flag_Bit1 = 0x01, - Flag_Bit2 = 0x02, - Flag_Bit3 = 0x04, - Flag_Bit4 = 0x08, - Flag_Bit5 = 0x10, - }; - - MxVideoPresenter() { Init(); } - virtual ~MxVideoPresenter() override; // vtable+0x0 - - // FUNCTION: LEGO1 0x1000c820 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0760 - return "MxVideoPresenter"; - } - - // FUNCTION: LEGO1 0x1000c830 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxVideoPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); - } - - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void Unk5Tickle() override; // vtable+0x28 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // 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 VTable0x6c(); // 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 - - // SIZE 0xc - struct AlphaMask { - MxU8* m_bitmask; - MxU16 m_width; - MxU16 m_height; - - AlphaMask(const MxBitmap&); - AlphaMask(const AlphaMask&); - virtual ~AlphaMask(); - - MxS32 IsHit(MxU32 p_x, MxU32 p_y); - }; - - inline MxBitmap* GetBitmap() { return m_bitmap; } - -private: - void Init(); - -protected: - void Destroy(MxBool p_fromDestructor); - - MxBitmap* m_bitmap; // 0x50 - AlphaMask* m_alpha; // 0x54 - LPDIRECTDRAWSURFACE m_unk0x58; // 0x58 - MxS16 m_unk0x5c; // 0x5c - MxU8 m_flags; // 0x5e - MxLong m_unk0x60; // 0x60 -}; - -#endif // MXVIDEOPRESENTER_H diff --git a/LEGO1/mxwavepresenter.h b/LEGO1/mxwavepresenter.h deleted file mode 100644 index ddb2b480..00000000 --- a/LEGO1/mxwavepresenter.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef MXWAVEPRESENTER_H -#define MXWAVEPRESENTER_H - -#include "decomp.h" -#include "mxsoundpresenter.h" - -#include - -// VTABLE: LEGO1 0x100d49a8 -// SIZE 0x6c -class MxWavePresenter : public MxSoundPresenter { -public: - MxWavePresenter() { Init(); } - virtual ~MxWavePresenter() override; // vtable+0x00 - - // FUNCTION: LEGO1 0x1000d6c0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f07b4 - return "MxWavePresenter"; - } - - // FUNCTION: LEGO1 0x1000d6d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, MxWavePresenter::ClassName()) || MxSoundPresenter::IsA(p_name); - } - - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void EndAction() override; // vtable+0x40 - virtual MxResult PutData() override; // vtable+0x4c - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void AppendChunk(MxStreamChunk* p_chunk) override; // vtable+0x58 - virtual void SetVolume(MxS32 p_volume) override; // vtable+0x60 - virtual void Pause(); // vtable+0x64 - virtual void Resume(); // vtable+0x68 - virtual MxBool IsPaused(); // vtable+0x6c - - // Reference: https://github.com/itsmattkc/SIEdit/blob/master/lib/othertypes.h - // SIZE 0x1c - struct WaveFormat { - WAVEFORMATEX m_waveFormatEx; - MxU32 m_dataSize; - MxU32 m_flags; - }; - -private: - void Init(); - void Destroy(MxBool p_fromDestructor); - MxS8 GetPlayedChunks(); - MxBool FUN_100b1ba0(); - void WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length); - - WaveFormat* m_waveFormat; // 0x54 - LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x58 - MxU32 m_chunkLength; // 0x5c - MxU32 m_lockSize; // 0x60 - MxU8 m_writtenChunks; // 0x64 - MxBool m_started; // 0x65 - MxBool m_unk0x66; // 0x66 - MxS8 m_silenceData; // 0x67 - MxBool m_paused; // 0x68 -}; - -#endif // MXWAVEPRESENTER_H diff --git a/LEGO1/mxactionnotificationparam.h b/LEGO1/omni/include/mxactionnotificationparam.h similarity index 66% rename from LEGO1/mxactionnotificationparam.h rename to LEGO1/omni/include/mxactionnotificationparam.h index 24d9e5e1..96c44a93 100644 --- a/LEGO1/mxactionnotificationparam.h +++ b/LEGO1/omni/include/mxactionnotificationparam.h @@ -21,8 +21,9 @@ class MxActionNotificationParam : public MxNotificationParam { MxDSAction* oldAction = p_action; this->m_realloc = p_reallocAction; - if (p_reallocAction) + if (p_reallocAction) { this->m_action = new MxDSAction(); + } else { this->m_action = oldAction; return; @@ -34,21 +35,27 @@ class MxActionNotificationParam : public MxNotificationParam { } // FUNCTION: LEGO1 0x10051050 - inline virtual ~MxActionNotificationParam() override + inline ~MxActionNotificationParam() override { - if (!this->m_realloc) + if (!this->m_realloc) { return; + } - if (this->m_action) + if (this->m_action) { delete this->m_action; + } } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + // FUNCTION: LEGO1 0x100510c0 + MxNotificationParam* Clone() override + { + return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc); + } // vtable+0x04 inline MxDSAction* GetAction() { return m_action; } protected: - MxDSAction* m_action; // 0xc + MxDSAction* m_action; // 0x0c MxBool m_realloc; // 0x10 }; @@ -66,7 +73,7 @@ class MxStartActionNotificationParam : public MxActionNotificationParam { { } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + MxNotificationParam* Clone() override; // vtable+0x04 }; // VTABLE: LEGO1 0x100d8358 @@ -83,7 +90,16 @@ class MxEndActionNotificationParam : public MxActionNotificationParam { { } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + // FUNCTION: LEGO1 0x10051270 + MxNotificationParam* Clone() override + { + return new MxEndActionNotificationParam( + c_notificationEndAction, + this->m_sender, + this->m_action, + this->m_realloc + ); + } // vtable+0x04 }; // VTABLE: LEGO1 0x100dc208 @@ -91,24 +107,36 @@ 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; } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + MxNotificationParam* Clone() override; // vtable+0x04 private: 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/mxatomid.h b/LEGO1/omni/include/mxatomid.h similarity index 60% rename from LEGO1/mxatomid.h rename to LEGO1/omni/include/mxatomid.h index 5d4cd10f..337f0b76 100644 --- a/LEGO1/mxatomid.h +++ b/LEGO1/omni/include/mxatomid.h @@ -5,21 +5,23 @@ #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); - __declspec(dllexport) MxAtomId& operator=(const MxAtomId& p_atomId); - __declspec(dllexport) ~MxAtomId(); + MxAtomId(const char*, LookupMode); + MxAtomId& operator=(const MxAtomId& p_atomId); + ~MxAtomId(); MxAtomId() { this->m_internal = 0; } inline MxBool operator==(const MxAtomId& p_atomId) const { return this->m_internal == p_atomId.m_internal; } + inline MxBool operator!=(const MxAtomId& p_atomId) const { return this->m_internal != p_atomId.m_internal; } void Clear(); @@ -29,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 new file mode 100644 index 00000000..4d8bfe38 --- /dev/null +++ b/LEGO1/omni/include/mxatomidcounter.h @@ -0,0 +1,92 @@ +#ifndef MXATOMIDCOUNTER_H +#define MXATOMIDCOUNTER_H + +#include "mxstl/stlcompat.h" +#include "mxstring.h" + +// Counts the number of existing MxAtomId objects based +// on the matching char* string. A seems fit for purpose here: +// We have an MxString as a key and MxU16 as the value. +// And yet a is the best match. The malloc in MxOmni::Create +// for the _Nil node asks for more bytes than a regular node if a +// is used, but all nodes are 20 bytes wide with a . +// Also: the increment/decrement methods suggest a custom type was used +// for the combined key_value_pair, which doesn't seem possible with . + +// SIZE 0x14 +class MxAtomIdCounter { +public: + // always inlined + MxAtomIdCounter(const char* p_str) + { + m_key = p_str; + m_value = 0; + } + + void Inc(); + void Dec(); + inline MxString* GetKey() { return &m_key; } + inline MxU16 GetValue() { return m_value; } + +private: + MxString m_key; + MxU16 m_value; +}; + +struct MxAtomIdCounterCompare { + // FUNCTION: LEGO1 0x100ad120 + int operator()(MxAtomIdCounter* const& p_val0, MxAtomIdCounter* const& p_val1) const + { + return strcmp(p_val0->GetKey()->GetData(), p_val1->GetKey()->GetData()) > 0; + } +}; + +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 new file mode 100644 index 00000000..020bda54 --- /dev/null +++ b/LEGO1/omni/include/mxaudiomanager.h @@ -0,0 +1,36 @@ +#ifndef MXAUDIOMANAGER_H +#define MXAUDIOMANAGER_H + +#include "decomp.h" +#include "mxmediamanager.h" + +// VTABLE: LEGO1 0x100dc6e0 +// SIZE 0x30 +class MxAudioManager : public MxMediaManager { +public: + MxAudioManager(); + ~MxAudioManager() override; + + MxResult InitPresenters() override; // vtable+14 + void Destroy() override; // vtable+18 + + // FUNCTION: LEGO1 0x10029910 + virtual MxS32 GetVolume() { return this->m_volume; } // vtable+28 + + virtual void SetVolume(MxS32 p_volume); // vtable+2c + + // SYNTHETIC: LEGO1 0x100b8d70 + // MxAudioManager::`scalar deleting destructor' + +private: + void Destroy(MxBool p_fromDestructor); + + static MxS32 g_count; + +protected: + void Init(); + + MxS32 m_volume; // 0x2c +}; + +#endif // MXAUDIOMANAGER_H diff --git a/LEGO1/omni/include/mxaudiopresenter.h b/LEGO1/omni/include/mxaudiopresenter.h new file mode 100644 index 00000000..873871ec --- /dev/null +++ b/LEGO1/omni/include/mxaudiopresenter.h @@ -0,0 +1,42 @@ +#ifndef MXAUDIOPRESENTER_H +#define MXAUDIOPRESENTER_H + +#include "decomp.h" +#include "mxmediapresenter.h" + +// VTABLE: LEGO1 0x100d4c70 +// SIZE 0x54 +class MxAudioPresenter : public MxMediaPresenter { +public: + MxAudioPresenter() { m_volume = 100; } + + // FUNCTION: LEGO1 0x1000d280 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f078c + return "MxAudioPresenter"; + } + + // FUNCTION: LEGO1 0x1000d290 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxAudioPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); + } + + // FUNCTION: LEGO1 0x1000d260 + virtual MxS32 GetVolume() { return m_volume; } // vtable+0x5c + + // 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/mxautolocker.h b/LEGO1/omni/include/mxautolocker.h similarity index 100% rename from LEGO1/mxautolocker.h rename to LEGO1/omni/include/mxautolocker.h diff --git a/LEGO1/omni/include/mxbitmap.h b/LEGO1/omni/include/mxbitmap.h new file mode 100644 index 00000000..465b2026 --- /dev/null +++ b/LEGO1/omni/include/mxbitmap.h @@ -0,0 +1,152 @@ +#ifndef MXBITMAP_H +#define MXBITMAP_H + +#include "mxcore.h" +#include "mxpalette.h" +#include "mxtypes.h" + +#include + +// The stock BITMAPINFO struct from wingdi.h only makes room for one color +// in the palette. It seems like the expectation (if you use the struct) +// is to malloc as much as you actually need, and then index into the array +// anyway even though its stated size is [1]. +// https://learn.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapinfo +// In our case, the size 0x428 is used frequently, which matches +// a 40-byte header plus 256 colors, so just use that as our template. + +// SIZE 0x428 +struct MxBITMAPINFO { + BITMAPINFOHEADER m_bmiHeader; + RGBQUAD m_bmiColors[256]; + + static MxU32 Size() { return sizeof(MxBITMAPINFO); } +}; + +// Non-standard value for biCompression in the BITMAPINFOHEADER struct. +// By default, uncompressed bitmaps (BI_RGB) are stored in bottom-up order. +// You can specify that the bitmap has top-down order instead by providing +// a negative number for biHeight. It could be that Mindscape decided on a +// belt & suspenders approach here. +#define BI_RGB_TOPDOWN 0x10 + +// SIZE 0x20 +// VTABLE: LEGO1 0x100dc7b0 +class MxBitmap : public MxCore { +public: + MxBitmap(); + ~MxBitmap() override; // vtable+00 + + virtual MxResult ImportBitmap(MxBitmap* p_bitmap); // vtable+14 + virtual MxResult ImportBitmapInfo(MxBITMAPINFO* p_info); // vtable+18 + virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool); // vtable+1c + virtual MxResult LoadFile(HANDLE p_handle); // vtable+20 + virtual MxLong Read(const char* p_filename); // vtable+24 + + // FUNCTION: LEGO1 0x1004e0d0 + virtual int VTable0x28(int) { return -1; } // vtable+28 + + virtual void BitBlt( + MxBitmap* p_src, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height + ); // vtable+2c + virtual void BitBltTransparent( + MxBitmap* p_src, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height + ); // vtable+30 + virtual MxPalette* CreatePalette(); // vtable+34 + virtual void ImportPalette(MxPalette* p_palette); // vtable+38 + virtual MxResult SetBitDepth(MxBool); // vtable+3c + virtual MxResult StretchBits( + HDC p_hdc, + MxS32 p_xSrc, + MxS32 p_ySrc, + MxS32 p_xDest, + MxS32 p_yDest, + MxS32 p_destWidth, + MxS32 p_destHeight + ); // vtable+40 + + // Bit mask trick to round up to the nearest multiple of four. + // Pixel data may be stored with padding. + // https://learn.microsoft.com/en-us/windows/win32/medfound/image-stride + inline MxLong AlignToFourByte(MxLong p_value) const { return (p_value + 3) & -4; } + + // Same as the one from legoutil.h, but flipped the other way + // TODO: While it's not outside the realm of possibility that they + // reimplemented Abs for only this file, that seems odd, right? + inline MxLong AbsFlipped(MxLong p_value) const { return p_value > 0 ? p_value : -p_value; } + + inline BITMAPINFOHEADER* GetBmiHeader() const { return m_bmiHeader; } + inline MxLong GetBmiWidth() const { return m_bmiHeader->biWidth; } + inline MxLong GetBmiStride() const { return ((m_bmiHeader->biWidth + 3) & -4); } + inline MxLong GetBmiHeight() const { return m_bmiHeader->biHeight; } + inline MxLong GetBmiHeightAbs() const { return AbsFlipped(m_bmiHeader->biHeight); } + inline MxU8* GetBitmapData() const { return m_data; } + inline MxBITMAPINFO* GetBitmapInfo() const { return m_info; } + inline MxLong GetDataSize() const + { + MxLong absHeight = GetBmiHeightAbs(); + MxLong alignedWidth = AlignToFourByte(m_bmiHeader->biWidth); + return alignedWidth * absHeight; + } + inline MxLong GetAdjustedStride() + { + if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) { + return GetBmiStride(); + } + else { + return -GetBmiStride(); + } + } + + inline MxLong GetLine(MxS32 p_top) + { + MxS32 height; + if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN || m_bmiHeader->biHeight < 0) { + height = p_top; + } + else { + height = GetBmiHeightAbs() - p_top - 1; + } + return GetBmiStride() * height; + } + + inline MxU8* GetStart(MxS32 p_left, MxS32 p_top) + { + if (m_bmiHeader->biCompression == BI_RGB) { + return GetLine(p_top) + m_data + p_left; + } + else if (m_bmiHeader->biCompression == BI_RGB_TOPDOWN) { + return m_data; + } + else { + return GetLine(0) + m_data; + } + } + + // SYNTHETIC: LEGO1 0x100bc9f0 + // MxBitmap::`scalar deleting destructor' + +private: + MxResult ImportColorsToPalette(RGBQUAD*, MxPalette*); + + MxBITMAPINFO* m_info; // 0x08 + BITMAPINFOHEADER* m_bmiHeader; // 0x0c + RGBQUAD* m_paletteData; // 0x10 + MxU8* m_data; // 0x14 + MxBool m_isHighColor; // 0x18 + MxPalette* m_palette; // 0x1c +}; + +#endif // MXBITMAP_H diff --git a/LEGO1/mxcollection.h b/LEGO1/omni/include/mxcollection.h similarity index 78% rename from LEGO1/mxcollection.h rename to LEGO1/omni/include/mxcollection.h index b0b4da88..84acdeef 100644 --- a/LEGO1/mxcollection.h +++ b/LEGO1/omni/include/mxcollection.h @@ -16,12 +16,12 @@ class MxCollection : public MxCore { void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; } - virtual ~MxCollection() {} + ~MxCollection() override {} virtual MxS8 Compare(T, T) { return 0; } protected: - MxU32 m_count; // 0x8 - void (*m_customDestructor)(T); // 0xc + MxU32 m_count; // 0x08 + void (*m_customDestructor)(T); // 0x0c }; #endif // MXCOLLECTION_H diff --git a/LEGO1/mxcompositepresenter.h b/LEGO1/omni/include/mxcompositepresenter.h similarity index 53% rename from LEGO1/mxcompositepresenter.h rename to LEGO1/omni/include/mxcompositepresenter.h index f6929b6d..a39507c0 100644 --- a/LEGO1/mxcompositepresenter.h +++ b/LEGO1/omni/include/mxcompositepresenter.h @@ -12,32 +12,42 @@ class MxCompositePresenterList : public list {}; class MxCompositePresenter : public MxPresenter { public: MxCompositePresenter(); - virtual ~MxCompositePresenter() override; // vtable+0x0 + ~MxCompositePresenter() override; // vtable+0x00 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100b6210 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0774 + // STRING: LEGO1 0x100f0774 return "MxCompositePresenter"; } // FUNCTION: LEGO1 0x100b6220 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxCompositePresenter::ClassName()) || MxPresenter::IsA(p_name); } - virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c - virtual void EndAction() override; // vtable+0x40 - virtual void SetTickleState(TickleState p_tickleState) override; // vtable+0x44 - virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 - virtual void Enable(MxBool p_enable) override; // vtable+0x54 - virtual void VTable0x58(MxEndActionNotificationParam& p_param); // vtable+0x58 - virtual void VTable0x5c(MxNotificationParam& p_param); // vtable+0x5c - virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 - virtual MxBool VTable0x64(undefined4 p_undefined); // vtable+0x64 + MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void SetTickleState(TickleState p_tickleState) override; // vtable+0x44 + MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 + void Enable(MxBool p_enable) override; // vtable+0x54 + virtual void VTable0x58(MxEndActionNotificationParam& p_param); // vtable+0x58 + virtual void VTable0x5c(MxNotificationParam& p_param); // vtable+0x5c + virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 + + // FUNCTION: LEGO1 0x1000caf0 + virtual MxBool VTable0x64(undefined4 p_undefined) + { + if (m_compositePresenter) { + return m_compositePresenter->VTable0x64(p_undefined); + } + return TRUE; + } // vtable+0x64 + + inline MxCompositePresenterList& GetList() { return m_list; } protected: MxCompositePresenterList m_list; // 0x40 diff --git a/LEGO1/mxcore.h b/LEGO1/omni/include/mxcore.h similarity index 61% rename from LEGO1/mxcore.h rename to LEGO1/omni/include/mxcore.h index 5792eaf2..dc167f2b 100644 --- a/LEGO1/mxcore.h +++ b/LEGO1/omni/include/mxcore.h @@ -9,18 +9,20 @@ class MxParam; // VTABLE: LEGO1 0x100dc0f8 -// SIZE 0x8 +// SIZE 0x08 class MxCore { public: - __declspec(dllexport) MxCore(); - __declspec(dllexport) virtual ~MxCore(); // vtable+00 - __declspec(dllexport) virtual MxLong Notify(MxParam& p_param); // vtable+04 - virtual MxResult Tickle(); // vtable+08 + MxCore(); + virtual ~MxCore(); // vtable+00 + virtual MxLong Notify(MxParam& p_param); // vtable+04 + + // FUNCTION: LEGO1 0x10001f70 + virtual MxResult Tickle() { return SUCCESS; } // vtable+08 // FUNCTION: LEGO1 0x100144c0 inline virtual const char* ClassName() const // vtable+0c { - // GLOBAL: LEGO1 0x100f007c + // STRING: LEGO1 0x100f007c return "MxCore"; } @@ -32,6 +34,9 @@ class MxCore { inline MxU32 GetId() { return m_id; } + // SYNTHETIC: LEGO1 0x100ae1c0 + // MxCore::`scalar deleting destructor' + private: MxU32 m_id; // 0x04 }; diff --git a/LEGO1/mxcriticalsection.h b/LEGO1/omni/include/mxcriticalsection.h similarity index 51% rename from LEGO1/mxcriticalsection.h rename to LEGO1/omni/include/mxcriticalsection.h index 8756853c..011ac680 100644 --- a/LEGO1/mxcriticalsection.h +++ b/LEGO1/omni/include/mxcriticalsection.h @@ -6,15 +6,15 @@ // SIZE 0x1c class MxCriticalSection { public: - __declspec(dllexport) MxCriticalSection(); - __declspec(dllexport) ~MxCriticalSection(); - __declspec(dllexport) static void SetDoMutex(); + MxCriticalSection(); + ~MxCriticalSection(); + static void SetDoMutex(); void Enter(); void Leave(); private: - CRITICAL_SECTION m_criticalSection; - HANDLE m_mutex; + CRITICAL_SECTION m_criticalSection; // 0x00 + HANDLE m_mutex; // 0x18 }; #endif // MXCRITICALSECTION_H diff --git a/LEGO1/mxdiskstreamcontroller.h b/LEGO1/omni/include/mxdiskstreamcontroller.h similarity index 56% rename from LEGO1/mxdiskstreamcontroller.h rename to LEGO1/omni/include/mxdiskstreamcontroller.h index 1d1cf7d5..ab13c73d 100644 --- a/LEGO1/mxdiskstreamcontroller.h +++ b/LEGO1/omni/include/mxdiskstreamcontroller.h @@ -15,53 +15,64 @@ class MxDiskStreamController : public MxStreamController { public: MxDiskStreamController(); - virtual ~MxDiskStreamController() override; + ~MxDiskStreamController() override; - virtual MxResult Tickle() override; // vtable+0x8 - virtual MxResult Open(const char* p_filename) override; // vtable+0x14 - virtual MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 - virtual MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 - virtual MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 - virtual MxDSStreamingAction* VTable0x28() override; // vtable+0x28 - virtual MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 - virtual MxResult VTable0x34(undefined4); // vtable+0x34 + MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x100c7360 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102144 + // STRING: LEGO1 0x10102144 return "MxDiskStreamController"; } // FUNCTION: LEGO1 0x100c7370 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDiskStreamController::ClassName()) || MxStreamController::IsA(p_name); } + MxResult Open(const char* p_filename) override; // vtable+0x14 + MxResult VTable0x18(undefined4, undefined4) override; // vtable+0x18 + MxResult VTable0x20(MxDSAction* p_action) override; // vtable+0x20 + MxResult VTable0x24(MxDSAction* p_action) override; // vtable+0x24 + MxDSStreamingAction* VTable0x28() override; // vtable+0x28 + MxResult VTable0x30(MxDSAction* p_action) override; // vtable+0x30 + virtual MxResult VTable0x34(undefined4); // vtable+0x34 + + inline MxBool GetUnk0xc4() const { return m_unk0xc4; } + + 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 - undefined m_unk0x70; // 0x70 + MxBool m_unk0x70; // 0x70 list m_list0x74; // 0x74 MxStreamListMxDSAction m_list0x80; // 0x80 undefined2 m_unk0x8c; // 0x8c MxStreamListMxDSAction m_list0x90; // 0x90 MxCriticalSection m_critical9c; // 0x9c MxStreamListMxDSAction m_list0xb8; // 0xb8 - undefined m_unk0xc4; // 0xc4 + MxBool m_unk0xc4; // 0xc4 - void FUN_100c7cb0(MxDSStreamingAction* p_action); + void FUN_100c7970(); void FUN_100c7ce0(MxDSBuffer* p_buffer); MxResult FUN_100c7d10(); void FUN_100c7980(); MxDSStreamingAction* FUN_100c7db0(); - void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); MxResult FUN_100c8360(MxDSStreamingAction* p_action); - void InsertToList74(MxDSBuffer* p_buffer); void FUN_100c8540(); void FUN_100c8720(); }; +// TEMPLATE: LEGO1 0x100c14d0 +// list >::erase + // TEMPLATE: LEGO1 0x100c7330 // list >::_Buynode @@ -71,7 +82,13 @@ class MxDiskStreamController : public MxStreamController { // TEMPLATE: LEGO1 0x100c7490 // list >::_Buynode +// SYNTHETIC: LEGO1 0x100c74c0 +// MxDiskStreamController::`scalar deleting destructor' + // TEMPLATE: LEGO1 0x100c74e0 // List::~List +// TEMPLATE: LEGO1 0x100c7ef0 +// list::insert + #endif // MXDISKSTREAMCONTROLLER_H diff --git a/LEGO1/mxdiskstreamprovider.h b/LEGO1/omni/include/mxdiskstreamprovider.h similarity index 50% rename from LEGO1/mxdiskstreamprovider.h rename to LEGO1/omni/include/mxdiskstreamprovider.h index 55d4f0f2..7bac3a0b 100644 --- a/LEGO1/mxdiskstreamprovider.h +++ b/LEGO1/omni/include/mxdiskstreamprovider.h @@ -13,32 +13,31 @@ class MxDiskStreamProvider; class MxDSStreamingAction; // VTABLE: LEGO1 0x100dd130 +// SIZE 0x1c class MxDiskStreamProviderThread : public MxThread { public: - // Only inlined, no offset inline MxDiskStreamProviderThread() : MxThread() { m_target = NULL; } MxResult Run() override; - MxResult StartWithTarget(MxDiskStreamProvider* p_target); }; // VTABLE: LEGO1 0x100dd138 +// SIZE 0x60 class MxDiskStreamProvider : public MxStreamProvider { public: MxDiskStreamProvider(); - - virtual ~MxDiskStreamProvider() override; + ~MxDiskStreamProvider() override; // FUNCTION: LEGO1 0x100d1160 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010287c + // STRING: LEGO1 0x1010287c return "MxDiskStreamProvider"; } // FUNCTION: LEGO1 0x100d1170 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDiskStreamProvider::ClassName()) || MxStreamProvider::IsA(p_name); } @@ -46,21 +45,32 @@ class MxDiskStreamProvider : public MxStreamProvider { MxResult WaitForWorkToComplete(); MxResult FUN_100d1780(MxDSStreamingAction* p_action); void PerformWork(); + static MxBool FUN_100d1af0(MxDSStreamingAction* p_action); + MxResult FUN_100d1b20(MxDSStreamingAction* p_action); - virtual MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 - virtual MxU32 GetFileSize() override; // vtable+0x18 - virtual MxS32 GetStreamBuffersNum() override; // vtable+0x1c - virtual void VTable0x20(MxDSAction* p_action) override; // vtable+0x20 - virtual MxU32 GetLengthInDWords() override; // vtable+0x24 - virtual MxU32* GetBufferForDWords() override; // vtable+0x28 + MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 + MxU32 GetFileSize() override; // vtable+0x18 + MxS32 GetStreamBuffersNum() override; // vtable+0x1c + void VTable0x20(MxDSAction* p_action) override; // vtable+0x20 + MxU32 GetLengthInDWords() override; // vtable+0x24 + MxU32* GetBufferForDWords() override; // vtable+0x28 private: MxDiskStreamProviderThread m_thread; // 0x10 MxSemaphore m_busySemaphore; // 0x2c - undefined m_remainingWork; // 0x34 - undefined m_unk0x35; // 0x35 + MxBool m_remainingWork; // 0x34 + MxBool m_unk0x35; // 0x35 MxCriticalSection m_criticalSection; // 0x38 MxStreamListMxDSAction m_list; // 0x54 }; +// SYNTHETIC: LEGO1 0x100d10a0 +// MxDiskStreamProviderThread::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100d1110 +// MxDiskStreamProviderThread::~MxDiskStreamProviderThread + +// SYNTHETIC: LEGO1 0x100d1220 +// MxDiskStreamProvider::`scalar deleting destructor' + #endif // MXDISKSTREAMPROVIDER_H diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h new file mode 100644 index 00000000..4e107f60 --- /dev/null +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -0,0 +1,119 @@ +#ifndef MXDISPLAYSURFACE_H +#define MXDISPLAYSURFACE_H + +#include "decomp.h" +#include "mxbitmap.h" +#include "mxcore.h" +#include "mxpalette.h" +#include "mxvideoparam.h" + +#include + +// VTABLE: LEGO1 0x100dc768 +// SIZE 0xac +class MxDisplaySurface : public MxCore { +public: + MxDisplaySurface(); + ~MxDisplaySurface() override; + + virtual MxResult Init( + MxVideoParam& p_videoParam, + LPDIRECTDRAWSURFACE p_ddSurface1, + LPDIRECTDRAWSURFACE p_ddSurface2, + LPDIRECTDRAWCLIPPER p_ddClipper + ); // vtable+0x14 + virtual MxResult Create(MxVideoParam& p_videoParam); // vtable+0x18 + virtual void Destroy(); // vtable+0x1c + virtual void SetPalette(MxPalette* p_palette); // vtable+0x20 + virtual void VTable0x24( + LPDDSURFACEDESC, + MxBitmap*, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4 + ); // vtable+0x24 + virtual void VTable0x28( + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height + ); // vtable+0x28 + virtual MxBool VTable0x2c( + LPDDSURFACEDESC, + MxBitmap*, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + MxBool + ); // vtable+0x2c + virtual MxBool VTable0x30( + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height, + MxBool + ); // vtable+0x30 + virtual undefined4 VTable0x34( + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4 + ); // vtable+0x34 + virtual void Display( + MxS32 p_left, + MxS32 p_top, + MxS32 p_left2, + MxS32 p_top2, + MxS32 p_width, + MxS32 p_height + ); // vtable+0x38 + virtual void GetDC(HDC* p_hdc); // vtable+0x3c + virtual void ReleaseDC(HDC p_hdc); // vtable+0x40 + virtual LPDIRECTDRAWSURFACE VTable0x44( + MxBitmap* p_bitmap, + undefined4* p_ret, + undefined4 p_doNotWriteToSurface, + undefined4 p_transparent + ); // vtable+0x44 + + void ClearScreen(); + static LPDIRECTDRAWSURFACE CreateCursorSurface(); + static LPDIRECTDRAWSURFACE FUN_100bbfb0(LPDIRECTDRAWSURFACE p_und); + + inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } + inline LPDIRECTDRAWSURFACE GetDirectDrawSurface2() { return this->m_ddSurface2; } + inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } + +private: + MxU8 CountTotalBitsSetTo1(MxU32 p_param); + MxU8 CountContiguousBitsSetTo1(MxU32 p_param); + + void Init(); + + MxVideoParam m_videoParam; // 0x08 + LPDIRECTDRAWSURFACE m_ddSurface1; // 0x2c + LPDIRECTDRAWSURFACE m_ddSurface2; // 0x30 + LPDIRECTDRAWCLIPPER m_ddClipper; // 0x34 + MxBool m_initialized; // 0x38 + DDSURFACEDESC m_surfaceDesc; // 0x3c + MxU16* m_16bitPal; // 0xa8 +}; + +// SYNTHETIC: LEGO1 0x100ba580 +// MxDisplaySurface::`scalar deleting destructor' + +#endif // MXDISPLAYSURFACE_H diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h new file mode 100644 index 00000000..0146ba04 --- /dev/null +++ b/LEGO1/omni/include/mxdsaction.h @@ -0,0 +1,108 @@ +#ifndef MXDSACTION_H +#define MXDSACTION_H + +#include "mxdsobject.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxtypes.h" + +class MxOmni; + +// VTABLE: LEGO1 0x100dc098 +// SIZE 0x94 +class MxDSAction : public MxDSObject { +public: + enum { + 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, + }; + + MxDSAction(); + ~MxDSAction() override; + + void CopyFrom(MxDSAction& p_dsAction); + MxDSAction& operator=(MxDSAction& p_dsAction); + + // FUNCTION: LEGO1 0x100ad980 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x101013f4 + return "MxDSAction"; + } + + // FUNCTION: LEGO1 0x100ad990 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxDSAction::ClassName()) || MxDSObject::IsA(p_name); + } + + undefined4 VTable0x14() override; // vtable+14; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + virtual MxLong GetDuration(); // vtable+24; + virtual void SetDuration(MxLong p_duration); // vtable+28; + virtual MxDSAction* Clone(); // vtable+2c; + virtual void MergeFrom(MxDSAction& p_dsAction); // vtable+30; + virtual MxBool HasId(MxU32 p_objectId); // vtable+34; + virtual void SetUnknown90(MxLong p_unk0x90); // vtable+38; + virtual MxLong GetUnknown90(); // vtable+3c; + virtual MxLong GetElapsedTime(); // vtable+40; + + void AppendData(MxU16 p_extraLength, const char* p_extraData); + + inline MxU32 GetFlags() { return m_flags; } + inline void SetFlags(MxU32 p_flags) { m_flags = p_flags; } + inline char* GetExtraData() { return m_extraData; } + inline MxU16 GetExtraLength() const { return m_extraLength; } + inline MxLong GetStartTime() const { return m_startTime; } + inline MxS32 GetLoopCount() { return m_loopCount; } + inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } + 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 & c_looping; } + inline MxBool IsBit3() const { return m_flags & c_bit3; } + + inline void CopyFlags(MxU32 p_flags) + { + if (p_flags & MxDSAction::c_looping) { + SetFlags(GetFlags() | MxDSAction::c_looping); + } + else if (p_flags & MxDSAction::c_bit3) { + SetFlags(GetFlags() | MxDSAction::c_bit3); + } + } + + // SYNTHETIC: LEGO1 0x100ada60 + // MxDSAction::`scalar deleting destructor' + +protected: + 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/mxdsactionlist.h b/LEGO1/omni/include/mxdsactionlist.h similarity index 84% rename from LEGO1/mxdsactionlist.h rename to LEGO1/omni/include/mxdsactionlist.h index fbccd5cf..b413cd2b 100644 --- a/LEGO1/mxdsactionlist.h +++ b/LEGO1/omni/include/mxdsactionlist.h @@ -19,7 +19,7 @@ class MxDSActionList : public MxList { MxDSActionList() { this->m_unk0x18 = 0; } // FUNCTION: LEGO1 0x100c9c90 - virtual MxS8 Compare(MxDSAction* p_a, MxDSAction* p_b) override + MxS8 Compare(MxDSAction* p_a, MxDSAction* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 @@ -27,6 +27,9 @@ class MxDSActionList : public MxList { // FUNCTION: LEGO1 0x100c9cb0 static void Destroy(MxDSAction* p_action) { delete p_action; } + // SYNTHETIC: LEGO1 0x100c9dc0 + // MxDSActionList::`scalar deleting destructor' + private: undefined m_unk0x18; }; @@ -35,6 +38,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 +47,9 @@ class MxDSActionListCursor : public MxListCursor { // TEMPLATE: LEGO1 0x100c9cc0 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100c9cd0 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100c9d20 // MxCollection::Destroy diff --git a/LEGO1/mxdsanim.h b/LEGO1/omni/include/mxdsanim.h similarity index 59% rename from LEGO1/mxdsanim.h rename to LEGO1/omni/include/mxdsanim.h index ee206e6a..09f9c72c 100644 --- a/LEGO1/mxdsanim.h +++ b/LEGO1/omni/include/mxdsanim.h @@ -8,25 +8,28 @@ class MxDSAnim : public MxDSMediaAction { public: MxDSAnim(); - virtual ~MxDSAnim() override; + ~MxDSAnim() override; void CopyFrom(MxDSAnim& p_dsAnim); MxDSAnim& operator=(MxDSAnim& p_dsAnim); // FUNCTION: LEGO1 0x100c9060 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025d8 + // STRING: LEGO1 0x101025d8 return "MxDSAnim"; } // FUNCTION: LEGO1 0x100c9070 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSAnim::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100c9180 + // MxDSAnim::`scalar deleting destructor' }; #endif // MXDSANIM_H diff --git a/LEGO1/mxdsbuffer.h b/LEGO1/omni/include/mxdsbuffer.h similarity index 56% rename from LEGO1/mxdsbuffer.h rename to LEGO1/omni/include/mxdsbuffer.h index d8532a55..79dee7d7 100644 --- a/LEGO1/mxdsbuffer.h +++ b/LEGO1/omni/include/mxdsbuffer.h @@ -10,29 +10,29 @@ 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; + ~MxDSBuffer() override; // FUNCTION: LEGO1 0x100c6500 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025b8 + // STRING: LEGO1 0x101025b8 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, @@ -42,25 +42,41 @@ class MxDSBuffer : public MxCore { MxStreamController* p_controller, MxU32* p_data, MxDSAction* p_action, - undefined4 p_undefined + MxDSStreamingAction** p_streamingAction ); MxResult StartPresenterFromAction(MxStreamController* p_controller, MxDSAction* p_action1, MxDSAction* p_action2); MxResult ParseChunk( MxStreamController* p_controller, MxU32* p_data, MxDSAction* p_action, - undefined4, + 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 MxU32 GetWriteOffset() { return m_writeOffset; } + inline MxU8** GetBufferRef() { return &m_pBuffer; } + inline undefined4 GetUnknown14() { return m_unk0x14; } inline MxU16 GetRefCount() { return m_refcount; } - inline MxDSBufferType GetMode() { return m_mode; } + inline Type GetMode() { return m_mode; } + inline MxU32 GetWriteOffset() { return m_writeOffset; } + inline MxU32 GetBytesRemaining() { return m_bytesRemaining; } + 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; } + + // SYNTHETIC: LEGO1 0x100c6510 + // MxDSBuffer::`scalar deleting destructor' private: MxU8* m_pBuffer; // 0x08 @@ -70,7 +86,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/mxdschunk.h b/LEGO1/omni/include/mxdschunk.h similarity index 53% rename from LEGO1/mxdschunk.h rename to LEGO1/omni/include/mxdschunk.h index 4cbb2fc9..c21816e6 100644 --- a/LEGO1/mxdschunk.h +++ b/LEGO1/omni/include/mxdschunk.h @@ -10,29 +10,35 @@ class MxDSChunk : public MxCore { public: enum { - Flag_Bit1 = 0x01, - Flag_Bit2 = 0x02, - Flag_Bit3 = 0x04, - Flag_Bit8 = 0x80, - Flag_Bit16 = 0x8000 + c_bit1 = 0x01, + c_end = 0x02, + c_bit3 = 0x04, + c_split = 0x10, + c_bit16 = 0x8000 }; MxDSChunk(); - virtual ~MxDSChunk() override; + ~MxDSChunk() override; // FUNCTION: LEGO1 0x100be0c0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101e6c + // STRING: LEGO1 0x10101e6c return "MxDSChunk"; } // FUNCTION: LEGO1 0x100be0d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSChunk::ClassName()) || MxCore::IsA(p_name); } + 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; } inline void SetTime(MxLong p_time) { m_time = p_time; } @@ -47,16 +53,20 @@ class MxDSChunk : public MxCore { inline void Release() { - if (m_data) + if (m_data) { delete[] m_data; + } } + // SYNTHETIC: LEGO1 0x100be150 + // MxDSChunk::`scalar deleting destructor' + protected: - MxU16 m_flags; // 0x8 - undefined4 m_objectId; // 0xc - MxLong m_time; // 0x10 - MxU32 m_length; // 0x14 - MxU8* m_data; // 0x18 + MxU16 m_flags; // 0x08 + MxU32 m_objectId; // 0x0c + MxLong m_time; // 0x10 + MxU32 m_length; // 0x14 + MxU8* m_data; // 0x18 }; #endif // MXDSCHUNK_H diff --git a/LEGO1/mxdsevent.h b/LEGO1/omni/include/mxdsevent.h similarity index 56% rename from LEGO1/mxdsevent.h rename to LEGO1/omni/include/mxdsevent.h index 8c6e825e..492cfd10 100644 --- a/LEGO1/mxdsevent.h +++ b/LEGO1/omni/include/mxdsevent.h @@ -3,28 +3,32 @@ #include "mxdsmediaaction.h" +// VTABLE: LEGO1 0x100dce18 class MxDSEvent : public MxDSMediaAction { public: MxDSEvent(); - virtual ~MxDSEvent() override; + ~MxDSEvent() override; void CopyFrom(MxDSEvent& p_dsEvent); MxDSEvent& operator=(MxDSEvent& p_dsEvent); // FUNCTION: LEGO1 0x100c9660 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025f0 + // STRING: LEGO1 0x101025f0 return "MxDSEvent"; } // FUNCTION: LEGO1 0x100c9670 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSEvent::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100c9780 + // MxDSEvent::`scalar deleting destructor' }; #endif // MXDSEVENT_H diff --git a/LEGO1/mxdsfile.h b/LEGO1/omni/include/mxdsfile.h similarity index 56% rename from LEGO1/mxdsfile.h rename to LEGO1/omni/include/mxdsfile.h index e453cb9a..d1c93771 100644 --- a/LEGO1/mxdsfile.h +++ b/LEGO1/omni/include/mxdsfile.h @@ -11,33 +11,36 @@ // VTABLE: LEGO1 0x100dc890 class MxDSFile : public MxDSSource { public: - __declspec(dllexport) MxDSFile(const char* p_filename, MxULong p_skipReadingChunks); - __declspec(dllexport) virtual ~MxDSFile(); // vtable+0x0 + MxDSFile(const char* p_filename, MxULong p_skipReadingChunks); + ~MxDSFile() override; // vtable+0x00 // FUNCTION: LEGO1 0x100c0120 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102594 + // STRING: LEGO1 0x10102594 return "MxDSFile"; } // FUNCTION: LEGO1 0x100c0130 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSFile::ClassName()) || MxDSSource::IsA(p_name); } - __declspec(dllexport) virtual MxLong Open(MxULong); // vtable+0x14 - __declspec(dllexport) virtual MxLong Close(); // vtable+0x18 - __declspec(dllexport) virtual MxResult Read(unsigned char*, MxULong); // vtable+0x20 - __declspec(dllexport) virtual MxLong Seek(MxLong, int); // vtable+0x24 - __declspec(dllexport) virtual MxULong GetBufferSize(); // vtable+0x28 - __declspec(dllexport) virtual MxULong GetStreamBuffersNum(); // vtable+0x2c + MxLong Open(MxULong) override; // vtable+0x14 + MxLong Close() override; // vtable+0x18 + MxResult Read(unsigned char*, MxULong) override; // vtable+0x20 + MxLong Seek(MxLong, int) override; // vtable+0x24 + MxULong GetBufferSize() override; // vtable+0x28 + MxULong GetStreamBuffersNum() override; // vtable+0x2c inline void SetFileName(const char* p_filename) { m_filename = p_filename; } inline MxS32 CalcFileSize() { return GetFileSize(m_io.m_info.hmmio, NULL); } + // SYNTHETIC: LEGO1 0x100c01e0 + // MxDSFile::`scalar deleting destructor' + private: MxLong ReadChunks(); struct ChunkHeader { diff --git a/LEGO1/mxdsmediaaction.h b/LEGO1/omni/include/mxdsmediaaction.h similarity index 68% rename from LEGO1/mxdsmediaaction.h rename to LEGO1/omni/include/mxdsmediaaction.h index 72fcf036..32664156 100644 --- a/LEGO1/mxdsmediaaction.h +++ b/LEGO1/omni/include/mxdsmediaaction.h @@ -10,26 +10,31 @@ class MxDSMediaAction : public MxDSAction { public: MxDSMediaAction(); - virtual ~MxDSMediaAction() override; + ~MxDSMediaAction() override; void CopyFrom(MxDSMediaAction& p_dsMediaAction); MxDSMediaAction& operator=(MxDSMediaAction& p_dsMediaAction); // FUNCTION: LEGO1 0x100c8be0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f7624 + // STRING: LEGO1 0x100f7624 return "MxDSMediaAction"; } // FUNCTION: LEGO1 0x100c8bf0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSMediaAction::ClassName()) || MxDSAction::IsA(p_name); } - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + // SYNTHETIC: LEGO1 0x100c8cd0 + // MxDSMediaAction::`scalar deleting destructor' + + undefined4 VTable0x14() override; // vtable+14; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + MxDSAction* Clone() override; // vtable+2c; void CopyMediaSrcPath(const char* p_mediaSrcPath); diff --git a/LEGO1/mxdsmultiaction.h b/LEGO1/omni/include/mxdsmultiaction.h similarity index 54% rename from LEGO1/mxdsmultiaction.h rename to LEGO1/omni/include/mxdsmultiaction.h index 5003a378..d97e6116 100644 --- a/LEGO1/mxdsmultiaction.h +++ b/LEGO1/omni/include/mxdsmultiaction.h @@ -9,34 +9,37 @@ class MxDSMultiAction : public MxDSAction { public: MxDSMultiAction(); - virtual ~MxDSMultiAction() override; + ~MxDSMultiAction() override; void CopyFrom(MxDSMultiAction& p_dsMultiAction); MxDSMultiAction& operator=(MxDSMultiAction& p_dsMultiAction); // FUNCTION: LEGO1 0x100c9f50 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101dbc + // STRING: LEGO1 0x10101dbc return "MxDSMultiAction"; } // FUNCTION: LEGO1 0x100c9f60 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSMultiAction::ClassName()) || MxDSAction::IsA(p_name); } - virtual undefined4 VTable0x14() override; // vtable+14; - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual void SetAtomId(MxAtomId p_atomId) override; // vtable+20; - virtual MxDSAction* Clone() override; // vtable+2c; - virtual void MergeFrom(MxDSAction& p_dsAction) override; // vtable+30; - virtual MxBool HasId(MxU32 p_objectId) override; // vtable+34; - virtual void SetUnknown90(MxLong p_unk0x90) override; // vtable+38; + undefined4 VTable0x14() override; // vtable+14; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + void SetAtomId(MxAtomId p_atomId) override; // vtable+20; + MxDSAction* Clone() override; // vtable+2c; + void MergeFrom(MxDSAction& p_dsAction) override; // vtable+30; + MxBool HasId(MxU32 p_objectId) override; // vtable+34; + void SetUnknown90(MxLong p_unk0x90) override; // vtable+38; - inline MxDSActionList* GetActionList() const { return m_actions; }; + inline MxDSActionList* GetActionList() const { return m_actions; } + + // SYNTHETIC: LEGO1 0x100ca040 + // MxDSMultiAction::`scalar deleting destructor' protected: MxU32 m_sizeOnDisk; // 0x94 diff --git a/LEGO1/mxdsobject.h b/LEGO1/omni/include/mxdsobject.h similarity index 71% rename from LEGO1/mxdsobject.h rename to LEGO1/omni/include/mxdsobject.h index a05d319b..c7156004 100644 --- a/LEGO1/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,46 +11,65 @@ 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; + ~MxDSObject() override; void CopyFrom(MxDSObject& p_dsObject); MxDSObject& operator=(MxDSObject& p_dsObject); - __declspec(dllexport) void SetObjectName(const char* p_objectName); + void SetObjectName(const char* p_objectName); void SetSourceName(const char* p_sourceName); // FUNCTION: LEGO1 0x100bf730 - inline virtual const char* ClassName() const override { return "MxDSObject"; }; // vtable+0c + inline const char* ClassName() const override { return "MxDSObject"; } // vtable+0c // FUNCTION: LEGO1 0x100bf740 - inline virtual MxBool IsA(const char* p_name) const override + inline MxBool IsA(const char* p_name) const override { return !strcmp(p_name, MxDSObject::ClassName()) || MxCore::IsA(p_name); - }; // vtable+10; + } // vtable+10; virtual undefined4 VTable0x14(); // vtable+14; virtual MxU32 GetSizeOnDisk(); // vtable+18; 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 const char* GetObjectName() const { return this->m_objectName; } inline MxU32 GetObjectId() { return this->m_objectId; } inline const MxAtomId& GetAtomId() { return this->m_atomId; } inline MxS16 GetUnknown24() { return this->m_unk0x24; } 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; } inline void ClearAtom() { m_atomId.Clear(); } + // SYNTHETIC: LEGO1 0x100bf7c0 + // MxDSObject::`scalar deleting destructor' + private: - MxU32 m_sizeOnDisk; // 0x8 - MxU16 m_type; // 0xc + MxU32 m_sizeOnDisk; // 0x08 + MxU16 m_type; // 0x0c char* m_sourceName; // 0x10 undefined4 m_unk0x14; // 0x14 char* m_objectName; // 0x18 diff --git a/LEGO1/mxdsobjectaction.h b/LEGO1/omni/include/mxdsobjectaction.h similarity index 63% rename from LEGO1/mxdsobjectaction.h rename to LEGO1/omni/include/mxdsobjectaction.h index 3286f110..205c6d81 100644 --- a/LEGO1/mxdsobjectaction.h +++ b/LEGO1/omni/include/mxdsobjectaction.h @@ -8,25 +8,28 @@ class MxDSObjectAction : public MxDSMediaAction { public: MxDSObjectAction(); - virtual ~MxDSObjectAction() override; + ~MxDSObjectAction() override; MxDSObjectAction& operator=(MxDSObjectAction& p_dsObjectAction); // FUNCTION: LEGO1 0x100c88e0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025c4 + // STRING: LEGO1 0x101025c4 return "MxDSObjectAction"; } // FUNCTION: LEGO1 0x100c88f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSObjectAction::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; virtual void CopyFrom(MxDSObjectAction& p_dsObjectAction); // vtable+44; + + // SYNTHETIC: LEGO1 0x100c8a00 + // MxDSObjectAction::`scalar deleting destructor' }; #endif // MXDSOBJECTACTION_H diff --git a/LEGO1/mxdsparallelaction.h b/LEGO1/omni/include/mxdsparallelaction.h similarity index 53% rename from LEGO1/mxdsparallelaction.h rename to LEGO1/omni/include/mxdsparallelaction.h index 65028ce3..212fb8f0 100644 --- a/LEGO1/mxdsparallelaction.h +++ b/LEGO1/omni/include/mxdsparallelaction.h @@ -8,26 +8,33 @@ class MxDSParallelAction : public MxDSMultiAction { public: MxDSParallelAction(); - virtual ~MxDSParallelAction() override; + ~MxDSParallelAction() override; void CopyFrom(MxDSParallelAction& p_dsParallelAction); MxDSParallelAction& operator=(MxDSParallelAction& p_dsParallelAction); // FUNCTION: LEGO1 0x100caf00 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102608 + // STRING: LEGO1 0x10102608 return "MxDSParallelAction"; } // FUNCTION: LEGO1 0x100caf10 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSParallelAction::ClassName()) || MxDSMultiAction::IsA(p_name); } - virtual MxLong GetDuration() override; // vtable+24; - virtual MxDSAction* Clone() override; // vtable+2c; + // SYNTHETIC: LEGO1 0x100cb020 + // MxDSParallelAction::`scalar deleting destructor' + + MxLong GetDuration() override; // vtable+24; + + // FUNCTION: LEGO1 0x100caef0 + void SetDuration(MxLong p_duration) override { m_duration = p_duration; } // vtable+0x28 + + MxDSAction* Clone() override; // vtable+2c; }; #endif // MXDSPARALLELACTION_H diff --git a/LEGO1/mxdsselectaction.h b/LEGO1/omni/include/mxdsselectaction.h similarity index 66% rename from LEGO1/mxdsselectaction.h rename to LEGO1/omni/include/mxdsselectaction.h index 187e3a72..ab2e6609 100644 --- a/LEGO1/mxdsselectaction.h +++ b/LEGO1/omni/include/mxdsselectaction.h @@ -10,27 +10,30 @@ class MxDSSelectAction : public MxDSParallelAction { public: MxDSSelectAction(); - virtual ~MxDSSelectAction() override; + ~MxDSSelectAction() override; void CopyFrom(MxDSSelectAction& p_dsSelectAction); MxDSSelectAction& operator=(MxDSSelectAction& p_dsSelectAction); // FUNCTION: LEGO1 0x100cb6f0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010261c + // STRING: LEGO1 0x1010261c return "MxDSSelectAction"; } // FUNCTION: LEGO1 0x100cb700 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSelectAction::ClassName()) || MxDSParallelAction::IsA(p_name); } - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual MxDSAction* Clone() override; // vtable+2c; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100cb840 + // MxDSSelectAction::`scalar deleting destructor' private: MxString m_unk0x9c; diff --git a/LEGO1/mxdsserialaction.h b/LEGO1/omni/include/mxdsserialaction.h similarity index 59% rename from LEGO1/mxdsserialaction.h rename to LEGO1/omni/include/mxdsserialaction.h index ea758afa..b1c2a695 100644 --- a/LEGO1/mxdsserialaction.h +++ b/LEGO1/omni/include/mxdsserialaction.h @@ -9,27 +9,30 @@ class MxDSSerialAction : public MxDSMultiAction { public: MxDSSerialAction(); - virtual ~MxDSSerialAction() override; + ~MxDSSerialAction() override; void CopyFrom(MxDSSerialAction& p_dsSerialAction); MxDSSerialAction& operator=(MxDSSerialAction& p_dsSerialAction); // FUNCTION: LEGO1 0x100caad0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f75dc + // STRING: LEGO1 0x100f75dc return "MxDSSerialAction"; } // FUNCTION: LEGO1 0x100caae0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSerialAction::ClassName()) || MxDSMultiAction::IsA(p_name); } - virtual MxLong GetDuration() override; // vtable+24; - virtual void SetDuration(MxLong p_duration) override; // vtable+28; - virtual MxDSAction* Clone() override; // vtable+2c; + MxLong GetDuration() override; // vtable+24; + void SetDuration(MxLong p_duration) override; // vtable+28; + MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100cabf0 + // MxDSSerialAction::`scalar deleting destructor' private: MxDSActionListCursor* m_cursor; diff --git a/LEGO1/mxdssound.h b/LEGO1/omni/include/mxdssound.h similarity index 54% rename from LEGO1/mxdssound.h rename to LEGO1/omni/include/mxdssound.h index 45f93942..193fde3a 100644 --- a/LEGO1/mxdssound.h +++ b/LEGO1/omni/include/mxdssound.h @@ -8,30 +8,33 @@ class MxDSSound : public MxDSMediaAction { public: MxDSSound(); - virtual ~MxDSSound() override; + ~MxDSSound() override; void CopyFrom(MxDSSound& p_dsSound); MxDSSound& operator=(MxDSSound& p_dsSound); // FUNCTION: LEGO1 0x100c9330 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025e4 + // STRING: LEGO1 0x101025e4 return "MxDSSound"; } // FUNCTION: LEGO1 0x100c9340 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSound::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxU32 GetSizeOnDisk() override; // vtable+18; - virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; - virtual MxDSAction* Clone() override; // vtable+2c; + MxU32 GetSizeOnDisk() override; // vtable+18; + void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + MxDSAction* Clone() override; // vtable+2c; inline MxS32 GetVolume() const { return m_volume; } + // SYNTHETIC: LEGO1 0x100c9450 + // MxDSSound::`scalar deleting destructor' + private: MxU32 m_sizeOnDisk; MxS32 m_volume; // 0xbc diff --git a/LEGO1/omni/include/mxdssource.h b/LEGO1/omni/include/mxdssource.h new file mode 100644 index 00000000..d3b9474b --- /dev/null +++ b/LEGO1/omni/include/mxdssource.h @@ -0,0 +1,50 @@ +#ifndef MXDSSOURCE_H +#define MXDSSOURCE_H + +#include "mxcore.h" + +class MxDSBuffer; + +// VTABLE: LEGO1 0x100dc8c8 +// SIZE 0x14 +class MxDSSource : public MxCore { +public: + MxDSSource() : m_lengthInDWords(0), m_pBuffer(NULL), m_position(-1) {} + + // FUNCTION: LEGO1 0x100bff60 + ~MxDSSource() override { delete[] m_pBuffer; } + + // FUNCTION: LEGO1 0x100c0010 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x10102588 + return "MxDSSource"; + } + + // FUNCTION: LEGO1 0x100c0020 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxDSSource::ClassName()) || MxCore::IsA(p_name); + } + + virtual MxLong Open(MxULong) = 0; // vtable+0x14 + virtual MxLong Close() = 0; // vtable+0x18 + virtual MxResult ReadToBuffer(MxDSBuffer* p_buffer); // vtable+0x1c + virtual MxResult Read(unsigned char*, MxULong) = 0; // vtable+0x20 + virtual MxLong Seek(MxLong, int) = 0; // vtable+0x24 + virtual MxULong GetBufferSize() = 0; // vtable+0x28 + virtual MxULong GetStreamBuffersNum() = 0; // vtable+0x2c + virtual MxLong GetLengthInDWords(); // vtable+0x30 + virtual MxU32* GetBuffer(); // vtable+0x34 + inline MxLong GetPosition() const { return m_position; } + +protected: + MxULong m_lengthInDWords; // 0x08 + MxU32* m_pBuffer; // 0x0c + MxLong m_position; // 0x10 +}; + +// SYNTHETIC: LEGO1 0x100c00a0 +// MxDSSource::`scalar deleting destructor' + +#endif // MXDSSOURCE_H diff --git a/LEGO1/mxdsstill.h b/LEGO1/omni/include/mxdsstill.h similarity index 60% rename from LEGO1/mxdsstill.h rename to LEGO1/omni/include/mxdsstill.h index 846f8293..f46fff32 100644 --- a/LEGO1/mxdsstill.h +++ b/LEGO1/omni/include/mxdsstill.h @@ -8,25 +8,28 @@ class MxDSStill : public MxDSMediaAction { public: MxDSStill(); - virtual ~MxDSStill() override; + ~MxDSStill() override; void CopyFrom(MxDSStill& p_dsStill); MxDSStill& operator=(MxDSStill& p_dsStill); // FUNCTION: LEGO1 0x100c9930 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025fc + // STRING: LEGO1 0x101025fc return "MxDSStill"; } // FUNCTION: LEGO1 0x100c9940 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSStill::ClassName()) || MxDSMediaAction::IsA(p_name); } - virtual MxDSAction* Clone() override; // vtable+2c; + MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100c9a50 + // MxDSStill::`scalar deleting destructor' }; #endif // MXDSSTILL_H diff --git a/LEGO1/mxdsstreamingaction.h b/LEGO1/omni/include/mxdsstreamingaction.h similarity index 79% rename from LEGO1/mxdsstreamingaction.h rename to LEGO1/omni/include/mxdsstreamingaction.h index 1766bd76..94e652ae 100644 --- a/LEGO1/mxdsstreamingaction.h +++ b/LEGO1/omni/include/mxdsstreamingaction.h @@ -11,7 +11,7 @@ class MxDSStreamingAction : public MxDSAction { public: MxDSStreamingAction(MxDSAction& p_dsAction, MxU32 p_offset); MxDSStreamingAction(MxDSStreamingAction& p_dsStreamingAction); - virtual ~MxDSStreamingAction(); + ~MxDSStreamingAction() override; MxDSStreamingAction* CopyFrom(MxDSStreamingAction& p_dsStreamingAction); MxDSStreamingAction& operator=(MxDSAction& p_dsAction) @@ -25,21 +25,28 @@ class MxDSStreamingAction : public MxDSAction { return *this; } - virtual MxBool HasId(MxU32 p_objectId) override; // vtable+34; + MxBool HasId(MxU32 p_objectId) override; // vtable+34; MxResult Init(); void SetInternalAction(MxDSAction* p_dsAction); void FUN_100cd2d0(); inline MxU32 GetUnknown94() { return m_unk0x94; } + inline MxS32 GetUnknown9c() { return m_unk0x9c; } inline MxDSBuffer* GetUnknowna0() { return m_unk0xa0; } inline MxDSBuffer* GetUnknowna4() { return m_unk0xa4; } + inline MxLong GetUnknowna8() { return m_unk0xa8; } inline MxDSAction* GetInternalAction() { return m_internalAction; } inline MxU32 GetBufferOffset() { return m_bufferOffset; } 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; } + // SYNTHETIC: LEGO1 0x100cd0b0 + // MxDSStreamingAction::`scalar deleting destructor' + private: MxU32 m_unk0x94; // 0x94 MxU32 m_bufferOffset; // 0x98 diff --git a/LEGO1/mxdssubscriber.h b/LEGO1/omni/include/mxdssubscriber.h similarity index 57% rename from LEGO1/mxdssubscriber.h rename to LEGO1/omni/include/mxdssubscriber.h index 13d62040..4f8d0843 100644 --- a/LEGO1/mxdssubscriber.h +++ b/LEGO1/omni/include/mxdssubscriber.h @@ -14,17 +14,17 @@ class MxStreamController; class MxDSSubscriber : public MxCore { public: MxDSSubscriber(); - virtual ~MxDSSubscriber() override; + ~MxDSSubscriber() override; // FUNCTION: LEGO1 0x100b7d50 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101020f8 + // STRING: LEGO1 0x101020f8 return "MxDSSubscriber"; } // FUNCTION: LEGO1 0x100b7d60 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxDSSubscriber::ClassName()) || MxCore::IsA(p_name); } @@ -32,21 +32,21 @@ class MxDSSubscriber : public MxCore { MxResult Create(MxStreamController* p_controller, MxU32 p_objectId, MxS16 p_unk0x48); void DeleteChunks(); MxResult AddChunk(MxStreamChunk* p_chunk, MxBool p_append); - MxStreamChunk* FUN_100b8250(); - MxStreamChunk* FUN_100b8360(); - void FUN_100b8390(MxStreamChunk* p_chunk); + MxStreamChunk* NextChunk(); + MxStreamChunk* CurrentChunk(); + void DestroyChunk(MxStreamChunk* p_chunk); inline MxU32 GetObjectId() { return m_objectId; } inline MxS16 GetUnknown48() { return m_unk0x48; } private: - MxStreamChunkList m_unk0x08; // 0x08 - MxStreamChunkListCursor* m_unk0x20; // 0x20 - MxStreamChunkList m_unk0x24; // 0x24 - MxStreamChunkListCursor* m_unk0x3c; // 0x3c - MxStreamController* m_controller; // 0x40 - MxU32 m_objectId; // 0x44 - MxS16 m_unk0x48; // 0x48 + MxStreamChunkList m_pendingChunks; // 0x08 + MxStreamChunkListCursor* m_pendingChunkCursor; // 0x20 + MxStreamChunkList m_consumedChunks; // 0x24 + MxStreamChunkListCursor* m_consumedChunkCursor; // 0x3c + MxStreamController* m_controller; // 0x40 + MxU32 m_objectId; // 0x44 + MxS16 m_unk0x48; // 0x48 }; // SYNTHETIC: LEGO1 0x100b7de0 diff --git a/LEGO1/omni/include/mxentity.h b/LEGO1/omni/include/mxentity.h new file mode 100644 index 00000000..ed75d148 --- /dev/null +++ b/LEGO1/omni/include/mxentity.h @@ -0,0 +1,59 @@ +#ifndef MXENTITY_H +#define MXENTITY_H + +#include "decomp.h" +#include "mxatomid.h" +#include "mxcore.h" +#include "mxdsaction.h" +#include "mxtypes.h" + +// VTABLE: LEGO1 0x100d5390 +// SIZE 0x10 +class MxEntity : public MxCore { +public: + // FUNCTION: LEGO1 0x1001d190 + MxEntity() { this->m_mxEntityId = -1; } + + // FUNCTION: LEGO1 0x1000c110 + ~MxEntity() override{}; + + // FUNCTION: LEGO1 0x1000c180 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0070 + return "MxEntity"; + } + + // FUNCTION: LEGO1 0x1000c190 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxEntity::ClassName()) || MxCore::IsA(p_name); + } + + // FUNCTION: LEGO1 0x10001070 + virtual MxResult Create(MxS32 p_id, const MxAtomId& p_atom) + { + 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; } + + // SYNTHETIC: LEGO1 0x1000c210 + // MxEntity::`scalar deleting destructor' + +protected: + MxS32 m_mxEntityId; // 0x08 + MxAtomId m_atom; // 0x0c +}; + +#endif // MXENTITY_H diff --git a/LEGO1/mxeventmanager.h b/LEGO1/omni/include/mxeventmanager.h similarity index 70% rename from LEGO1/mxeventmanager.h rename to LEGO1/omni/include/mxeventmanager.h index e7f41a6d..b23a2ad0 100644 --- a/LEGO1/mxeventmanager.h +++ b/LEGO1/omni/include/mxeventmanager.h @@ -9,11 +9,14 @@ class MxEventManager : public MxMediaManager { public: MxEventManager(); - virtual ~MxEventManager() override; + ~MxEventManager() override; - virtual void Destroy() override; // vtable+18 + void Destroy() override; // vtable+18 virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+28 + // SYNTHETIC: LEGO1 0x100c03d0 + // MxEventManager::`scalar deleting destructor' + private: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxeventpresenter.h b/LEGO1/omni/include/mxeventpresenter.h new file mode 100644 index 00000000..1812280f --- /dev/null +++ b/LEGO1/omni/include/mxeventpresenter.h @@ -0,0 +1,43 @@ +#ifndef MXEVENTPRESENTER_H +#define MXEVENTPRESENTER_H + +#include "decomp.h" +#include "mxmediapresenter.h" + +// VTABLE: LEGO1 0x100dca88 +// SIZE 0x54 +class MxEventPresenter : public MxMediaPresenter { +public: + MxEventPresenter(); + ~MxEventPresenter() override; + + // FUNCTION: LEGO1 0x100c2c30 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x10101dcc + return "MxEventPresenter"; + } + + // FUNCTION: LEGO1 0x100c2c40 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxEventPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + MxResult PutData() override; // vtable+0x4c + virtual void CopyData(MxStreamChunk* p_chunk); // vtable+0x5c + + // SYNTHETIC: LEGO1 0x100c2d20 + // MxEventPresenter::`scalar deleting destructor' + +private: + void Init(); + + MxU8* m_data; // 0x50 +}; + +#endif // MXEVENTPRESENTER_H diff --git a/LEGO1/omni/include/mxflcpresenter.h b/LEGO1/omni/include/mxflcpresenter.h new file mode 100644 index 00000000..569fa06c --- /dev/null +++ b/LEGO1/omni/include/mxflcpresenter.h @@ -0,0 +1,41 @@ +#ifndef MXFLCPRESENTER_H +#define MXFLCPRESENTER_H + +#include "decomp.h" +#include "mxvideopresenter.h" + +#include + +// VTABLE: LEGO1 0x100dc2c0 +// SIZE 0x68 +class MxFlcPresenter : public MxVideoPresenter { +public: + MxFlcPresenter(); + ~MxFlcPresenter() override; + + // FUNCTION: LEGO1 0x1004e200 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxFlcPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); + } + + // FUNCTION: LEGO1 0x100b33f0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f43c8 + return "MxFlcPresenter"; + } + + void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c + void CreateBitmap() override; // vtable+0x60 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void RealizePalette() override; // vtable+0x70 + + // SYNTHETIC: LEGO1 0x100b3400 + // MxFlcPresenter::`scalar deleting destructor' + +protected: + FLIC_HEADER* m_flcHeader; // 0x64 +}; + +#endif // MXFLCPRESENTER_H diff --git a/LEGO1/mxhashtable.h b/LEGO1/omni/include/mxhashtable.h similarity index 91% rename from LEGO1/mxhashtable.h rename to LEGO1/omni/include/mxhashtable.h index 8d6be0cf..f2506758 100644 --- a/LEGO1/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,10 +43,10 @@ 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; + ~MxHashTable() override; void Resize(); void Add(T); @@ -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. @@ -99,8 +99,9 @@ MxBool MxHashTableCursor::Find(T p_obj) MxHashTableNode* t = m_table->m_slots[bucket]; while (t) { - if (t->m_hash == hash && !m_table->Compare(t->m_obj, p_obj)) + if (t->m_hash == hash && !m_table->Compare(t->m_obj, p_obj)) { m_match = t; + } t = t->m_next; } @@ -122,8 +123,9 @@ void MxHashTableCursor::DeleteMatch() { // Cut the matching node out of the linked list // by updating pointer references. - if (m_match == NULL) + if (m_match == NULL) { return; + } if (m_match->m_prev) { m_match->m_prev->m_next = m_match->m_next; @@ -134,8 +136,9 @@ void MxHashTableCursor::DeleteMatch() m_table->m_slots[bucket] = m_match->m_next; } - if (m_match->m_next) + if (m_match->m_next) { m_match->m_next->m_prev = m_match->m_prev; + } m_table->m_customDestructor(m_match->m_obj); delete m_match; @@ -177,10 +180,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; } @@ -210,8 +213,9 @@ inline void MxHashTable::NodeInsert(MxHashTableNode* p_node) p_node->m_next = m_slots[bucket]; - if (m_slots[bucket]) + if (m_slots[bucket]) { m_slots[bucket]->m_prev = p_node; + } m_slots[bucket] = p_node; this->m_count++; @@ -220,8 +224,9 @@ inline void MxHashTable::NodeInsert(MxHashTableNode* p_node) template inline void MxHashTable::Add(T p_newobj) { - if (m_resizeOption && ((this->m_count + 1) / m_numSlots) > m_autoResizeRatio) + if (m_resizeOption && ((this->m_count + 1) / m_numSlots) > m_autoResizeRatio) { MxHashTable::Resize(); + } MxU32 hash = Hash(p_newobj); MxHashTableNode* node = new MxHashTableNode(p_newobj, hash); diff --git a/LEGO1/mxioinfo.h b/LEGO1/omni/include/mxioinfo.h similarity index 94% rename from LEGO1/mxioinfo.h rename to LEGO1/omni/include/mxioinfo.h index 2a978b63..94901c4a 100644 --- a/LEGO1/mxioinfo.h +++ b/LEGO1/omni/include/mxioinfo.h @@ -12,7 +12,7 @@ class MXIOINFO { public: MXIOINFO(); - __declspec(dllexport) ~MXIOINFO(); + ~MXIOINFO(); MxU16 Open(const char*, MxULong); MxU16 Close(MxLong); diff --git a/LEGO1/mxlist.h b/LEGO1/omni/include/mxlist.h similarity index 77% rename from LEGO1/mxlist.h rename to LEGO1/omni/include/mxlist.h index 8a5f3e0e..5ad02492 100644 --- a/LEGO1/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -51,10 +51,10 @@ class MxList : protected MxCollection { m_first = NULL; } - virtual ~MxList() override; + ~MxList() override; - void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); }; - void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); }; + void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); } + void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); } void DeleteAll(MxBool p_destroy = TRUE); MxU32 GetCount() { return this->m_count; } @@ -69,16 +69,21 @@ class MxList : protected MxCollection { MxListEntry* InsertEntry(T, MxListEntry*, MxListEntry*); }; +// SIZE 0x18 template class MxPtrList : public MxList { public: MxPtrList(MxBool p_ownership) { SetOwnership(p_ownership); } - static void Destroy(T* p_obj) { delete p_obj; }; + static void Destroy(T* p_obj) { delete p_obj; } - void SetOwnership(MxBool p_ownership) { SetDestroy(p_ownership ? Destroy : MxCollection::Destroy); } + void SetOwnership(MxBool p_ownership) + { + MxCollection::SetDestroy(p_ownership ? MxPtrList::Destroy : MxCollection::Destroy); + } }; +// SIZE 0x10 template class MxListCursor : public MxCore { public: @@ -91,29 +96,42 @@ class MxListCursor : public MxCore { MxBool Find(T p_obj); void Detach(); void Destroy(); + MxBool Next(); MxBool Next(T& p_obj); + MxBool Prev(); + MxBool Prev(T& p_obj); MxBool Current(T& p_obj); MxBool First(T& p_obj); MxBool Last(T& p_obj); - MxBool Advance(); MxBool HasMatch() { return m_match != NULL; } void SetValue(T p_obj); - void Head() { m_match = m_list->m_first; } + MxBool Head() + { + m_match = m_list->m_first; + return m_match != NULL; + } + MxBool Tail() + { + m_match = m_list->m_last; + return m_match != NULL; + } void Reset() { m_match = NULL; } void Prepend(T p_newobj); // TODO: Probably shouldn't exist void NextFragment() { - if (m_match) + if (m_match) { m_match = m_match->GetNext(); + } } private: - MxList* m_list; - MxListEntry* m_match; + MxList* m_list; // 0x08 + MxListEntry* m_match; // 0x0c }; +// SIZE 0x10 template class MxPtrListCursor : public MxListCursor { public: @@ -130,13 +148,15 @@ template inline void MxList::DeleteAll(MxBool p_destroy) { for (MxListEntry* t = m_first;;) { - if (!t) + if (!t) { break; + } MxListEntry* next = t->GetNext(); - if (p_destroy) + if (p_destroy) { this->m_customDestructor(t->GetValue()); + } delete t; t = next; @@ -152,15 +172,19 @@ inline MxListEntry* MxList::InsertEntry(T p_newobj, MxListEntry* p_prev { MxListEntry* newEntry = new MxListEntry(p_newobj, p_prev, p_next); - if (p_prev) + if (p_prev) { p_prev->SetNext(newEntry); - else + } + else { this->m_first = newEntry; + } - if (p_next) + if (p_next) { p_next->SetPrev(newEntry); - else + } + else { this->m_last = newEntry; + } this->m_count++; return newEntry; @@ -169,15 +193,19 @@ inline MxListEntry* MxList::InsertEntry(T p_newobj, MxListEntry* p_prev template inline void MxList::DeleteEntry(MxListEntry* p_match) { - if (p_match->GetPrev()) + if (p_match->GetPrev()) { p_match->GetPrev()->SetNext(p_match->GetNext()); - else + } + else { m_first = p_match->GetNext(); + } - if (p_match->GetNext()) + if (p_match->GetNext()) { p_match->GetNext()->SetPrev(p_match->GetPrev()); - else + } + else { m_last = p_match->GetPrev(); + } delete p_match; this->m_count--; @@ -187,8 +215,9 @@ template inline MxBool MxListCursor::Find(T p_obj) { for (m_match = m_list->m_first; m_match && m_list->Compare(m_match->GetValue(), p_obj); - m_match = m_match->GetNext()) + m_match = m_match->GetNext()) { ; + } return m_match != NULL; } @@ -212,16 +241,62 @@ inline void MxListCursor::Destroy() } } +template +inline MxBool MxListCursor::Next() +{ + if (!m_match) { + m_match = m_list->m_first; + } + else { + m_match = m_match->GetNext(); + } + + return m_match != NULL; +} + template inline MxBool MxListCursor::Next(T& p_obj) { - if (!m_match) + if (!m_match) { m_match = m_list->m_first; - else + } + else { m_match = m_match->GetNext(); + } - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } + + return m_match != NULL; +} + +template +inline MxBool MxListCursor::Prev() +{ + if (!m_match) { + m_match = m_list->m_last; + } + else { + m_match = m_match->GetPrev(); + } + + return m_match != NULL; +} + +template +inline MxBool MxListCursor::Prev(T& p_obj) +{ + if (!m_match) { + m_match = m_list->m_last; + } + else { + m_match = m_match->GetPrev(); + } + + if (m_match) { + p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -229,8 +304,9 @@ inline MxBool MxListCursor::Next(T& p_obj) template inline MxBool MxListCursor::Current(T& p_obj) { - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -239,8 +315,9 @@ template inline MxBool MxListCursor::First(T& p_obj) { m_match = m_list->m_first; - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); + } return m_match != NULL; } @@ -249,19 +326,9 @@ template inline MxBool MxListCursor::Last(T& p_obj) { m_match = m_list->m_last; - if (m_match) + if (m_match) { p_obj = m_match->GetValue(); - - return m_match != NULL; -} - -template -inline MxBool MxListCursor::Advance() -{ - if (!m_match) - m_match = m_list->m_first; - else - m_match = m_match->GetNext(); + } return m_match != NULL; } @@ -269,15 +336,17 @@ inline MxBool MxListCursor::Advance() template inline void MxListCursor::SetValue(T p_obj) { - if (m_match) + if (m_match) { m_match->SetValue(p_obj); + } } template inline void MxListCursor::Prepend(T p_newobj) { - if (m_match) + if (m_match) { m_list->InsertEntry(p_newobj, m_match->GetPrev(), m_match); + } } #endif // MXLIST_H diff --git a/LEGO1/omni/include/mxloopingflcpresenter.h b/LEGO1/omni/include/mxloopingflcpresenter.h new file mode 100644 index 00000000..1bc76e18 --- /dev/null +++ b/LEGO1/omni/include/mxloopingflcpresenter.h @@ -0,0 +1,37 @@ +#ifndef MXLOOPINGFLCPRESENTER_H +#define MXLOOPINGFLCPRESENTER_H + +#include "decomp.h" +#include "mxflcpresenter.h" + +// VTABLE: LEGO1 0x100dc480 +// SIZE 0x6c +class MxLoopingFlcPresenter : public MxFlcPresenter { +public: + MxLoopingFlcPresenter(); + ~MxLoopingFlcPresenter() override; + + // FUNCTION: LEGO1 0x100b4380 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x10101e20 + return "MxLoopingFlcPresenter"; + } + + void RepeatingTickle() override; // vtable+0x24 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void NextFrame() override; // vtable+0x64 + virtual void VTable0x88(); // vtable+0x88 + + // SYNTHETIC: LEGO1 0x100b4390 + // MxLoopingFlcPresenter::`scalar deleting destructor' + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + + MxLong m_elapsedDuration; // 0x68 +}; + +#endif // MXLOOPINGFLCPRESENTER_H diff --git a/LEGO1/mxloopingmidipresenter.h b/LEGO1/omni/include/mxloopingmidipresenter.h similarity index 60% rename from LEGO1/mxloopingmidipresenter.h rename to LEGO1/omni/include/mxloopingmidipresenter.h index 49df30f4..1a9eff73 100644 --- a/LEGO1/mxloopingmidipresenter.h +++ b/LEGO1/omni/include/mxloopingmidipresenter.h @@ -8,21 +8,21 @@ class MxLoopingMIDIPresenter : public MxMIDIPresenter { public: // FUNCTION: LEGO1 0x100b1830 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101de0 + // STRING: LEGO1 0x10101de0 return "MxLoopingMIDIPresenter"; } // FUNCTION: LEGO1 0x100b1840 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxLoopingMIDIPresenter::ClassName()) || MxMIDIPresenter::IsA(p_name); } - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual MxResult PutData() override; // vtable+0x4c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + MxResult PutData() override; // vtable+0x4c }; // SYNTHETIC: LEGO1 0x100b19c0 diff --git a/LEGO1/mxloopingsmkpresenter.h b/LEGO1/omni/include/mxloopingsmkpresenter.h similarity index 51% rename from LEGO1/mxloopingsmkpresenter.h rename to LEGO1/omni/include/mxloopingsmkpresenter.h index 2f20676e..de0f506f 100644 --- a/LEGO1/mxloopingsmkpresenter.h +++ b/LEGO1/omni/include/mxloopingsmkpresenter.h @@ -9,21 +9,21 @@ class MxLoopingSmkPresenter : public MxSmkPresenter { public: MxLoopingSmkPresenter(); - virtual ~MxLoopingSmkPresenter() override; // vtable+0x0 + ~MxLoopingSmkPresenter() override; // vtable+0x00 // FUNCTION: LEGO1 0x100b4920 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101e08 + // STRING: LEGO1 0x10101e08 return "MxLoopingSmkPresenter"; } - virtual void RepeatingTickle() override; // vtable+0x24 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 - virtual void NextFrame() override; // vtable+0x64 - virtual void VTable0x88() override; // vtable+0x88 - virtual void VTable0x8c(); // vtable+0x8c + void RepeatingTickle() override; // vtable+0x24 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void NextFrame() override; // vtable+0x64 + void VTable0x88() override; // vtable+0x88 + virtual void VTable0x8c(); // vtable+0x8c private: void Init(); diff --git a/LEGO1/omni/include/mxmediamanager.h b/LEGO1/omni/include/mxmediamanager.h new file mode 100644 index 00000000..77720bf3 --- /dev/null +++ b/LEGO1/omni/include/mxmediamanager.h @@ -0,0 +1,35 @@ +#ifndef MXMEDIAMANGER_H +#define MXMEDIAMANGER_H + +#include "mxcore.h" +#include "mxcriticalsection.h" +#include "mxpresenterlist.h" +#include "mxthread.h" +#include "mxtypes.h" + +// VTABLE: LEGO1 0x100dc6b0 +// SIZE 0x2c +class MxMediaManager : public MxCore { +public: + MxMediaManager(); + ~MxMediaManager() override; + + 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(); + + // SYNTHETIC: LEGO1 0x100b8540 + // MxMediaManager::`scalar deleting destructor' + +protected: + MxPresenterList* m_presenters; // 0x08 + MxThread* m_thread; // 0x0c + MxCriticalSection m_criticalSection; // 0x10 +}; + +#endif // MXMEDIAMANGER_H diff --git a/LEGO1/omni/include/mxmediapresenter.h b/LEGO1/omni/include/mxmediapresenter.h new file mode 100644 index 00000000..fba44880 --- /dev/null +++ b/LEGO1/omni/include/mxmediapresenter.h @@ -0,0 +1,74 @@ +#ifndef MXMEDIAPRESENTER_H +#define MXMEDIAPRESENTER_H + +#include "decomp.h" +#include "mxdssubscriber.h" +#include "mxpresenter.h" +#include "mxstreamchunklist.h" + +// VTABLE: LEGO1 0x100d4cd8 +// SIZE 0x50 +class MxMediaPresenter : public MxPresenter { +public: + inline MxMediaPresenter() { Init(); } + + // FUNCTION: LEGO1 0x1000c550 + ~MxMediaPresenter() override { Destroy(TRUE); } + + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1000c5c0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f074c + return "MxMediaPresenter"; + } + + // FUNCTION: LEGO1 0x1000c5d0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxMediaPresenter::ClassName()) || MxPresenter::IsA(p_name); + } + + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void DoneTickle() override; // vtable+0x2c + + // FUNCTION: LEGO1 0x1000c5b0 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 + + MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c + void EndAction() override; // vtable+0x40 + void Enable(MxBool p_enable) override; // vtable+0x54 + virtual void LoopChunk(MxStreamChunk* p_chunk); // vtable+0x58 + + // SYNTHETIC: LEGO1 0x1000c680 + // MxMediaPresenter::`scalar deleting destructor' + +protected: + MxDSSubscriber* m_subscriber; // 0x40 + MxStreamChunkList* m_loopingChunks; // 0x44 + MxStreamChunkListCursor* m_loopingChunkCursor; // 0x48 + MxStreamChunk* m_currentChunk; // 0x4c + + void Init(); + void Destroy(MxBool p_fromDestructor); + +public: + MxStreamChunk* CurrentChunk(); + MxStreamChunk* NextChunk(); +}; + +// SYNTHETIC: LEGO1 0x100b46e0 +// MxStreamChunkListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x100b4750 +// MxListCursor::~MxListCursor + +// SYNTHETIC: LEGO1 0x100b47a0 +// MxListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x100b4810 +// MxStreamChunkListCursor::~MxStreamChunkListCursor + +#endif // MXMEDIAPRESENTER_H diff --git a/LEGO1/omni/include/mxmidipresenter.h b/LEGO1/omni/include/mxmidipresenter.h new file mode 100644 index 00000000..3dabbc0e --- /dev/null +++ b/LEGO1/omni/include/mxmidipresenter.h @@ -0,0 +1,47 @@ +#ifndef MXMIDIPRESENTER_H +#define MXMIDIPRESENTER_H + +#include "mxmusicpresenter.h" +#include "mxstreamchunk.h" + +// VTABLE: LEGO1 0x100dca20 +// SIZE 0x58 +class MxMIDIPresenter : public MxMusicPresenter { +public: + MxMIDIPresenter(); + ~MxMIDIPresenter() override; + + // FUNCTION: LEGO1 0x100c2650 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x10101df8 + return "MxMIDIPresenter"; + } + + // FUNCTION: LEGO1 0x100c2660 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxMIDIPresenter::ClassName()) || MxMusicPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + void Destroy() override; // vtable+0x38 + void EndAction() override; // vtable+0x40 + MxResult PutData() override; // vtable+0x4c + void SetVolume(MxS32 p_volume) override; // vtable+0x60 + + // SYNTHETIC: LEGO1 0x100c27a0 + // MxMIDIPresenter::`scalar deleting destructor' + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + +protected: + MxStreamChunk* m_chunk; +}; + +#endif // MXMIDIPRESENTER_H diff --git a/LEGO1/omni/include/mxmusicmanager.h b/LEGO1/omni/include/mxmusicmanager.h new file mode 100644 index 00000000..1107e7e3 --- /dev/null +++ b/LEGO1/omni/include/mxmusicmanager.h @@ -0,0 +1,61 @@ +#ifndef MXMUSICMANAGER_H +#define MXMUSICMANAGER_H + +#include "decomp.h" +#include "mxaudiomanager.h" + +#include + +// VTABLE: LEGO1 0x100dc930 +// SIZE 0x58 +class MxMusicManager : public MxAudioManager { +public: + MxMusicManager(); + ~MxMusicManager() override; + + void Destroy() override; // vtable+18 + void SetVolume(MxS32 p_volume) override; // vtable+2c + virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+30 + + inline MxBool GetMIDIInitialized() { return m_midiInitialized; } + inline void GetMIDIVolume(DWORD& p_volume) + { + if (midiOutGetVolume((HMIDIOUT) m_midiStreamH, &p_volume)) { + p_volume = CalculateVolume(100); + } + } + + MxResult ResetStream(); + void ResetBuffer(); + MxResult InitializeMIDI(MxU8* p_data, MxS32 p_loopCount); + void DeinitializeMIDI(); + void SetMultiplier(MxS32 p_multiplier); + +private: + void Destroy(MxBool p_fromDestructor); + + MxS32 CalculateVolume(MxS32 p_volume); + void SetMIDIVolume(); + + static void CALLBACK MidiCallbackProc(HDRVR p_hdrvr, UINT p_uMsg, DWORD p_dwUser, DWORD p_dw1, DWORD p_dw2); + + HMIDISTRM m_midiStreamH; // 0x30 + MxBool m_midiInitialized; // 0x34 + MxU32 m_bufferSize; // 0x38 + MxU32 m_bufferCurrentSize; // 0x3c + MxU8* m_bufferOffset; // 0x40 + MxU8* m_bufferCurrentOffset; // 0x44 + MxU32 m_loopCount; // 0x48 + MIDIHDR* m_midiHdrP; // 0x4c + MxS32 m_multiplier; // 0x50 + DWORD m_midiVolume; // 0x54 + + // SYNTHETIC: LEGO1 0x100c0610 + // MxMusicManager::`scalar deleting destructor' + +protected: + void Init(); + void InitData(); +}; + +#endif // MXMUSICMANAGER_H diff --git a/LEGO1/mxmusicpresenter.h b/LEGO1/omni/include/mxmusicpresenter.h similarity index 57% rename from LEGO1/mxmusicpresenter.h rename to LEGO1/omni/include/mxmusicpresenter.h index 965c38df..a66afa78 100644 --- a/LEGO1/mxmusicpresenter.h +++ b/LEGO1/omni/include/mxmusicpresenter.h @@ -8,23 +8,26 @@ class MxMusicPresenter : public MxAudioPresenter { public: MxMusicPresenter(); - virtual ~MxMusicPresenter() override; + ~MxMusicPresenter() override; // FUNCTION: LEGO1 0x100c23a0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101e48 + // STRING: LEGO1 0x10101e48 return "MxMusicPresenter"; } // FUNCTION: LEGO1 0x100c23b0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxMusicPresenter::ClassName()) || MxAudioPresenter::IsA(p_name); } - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + + // SYNTHETIC: LEGO1 0x100c24c0 + // MxMusicPresenter::`scalar deleting destructor' private: void Init(); diff --git a/LEGO1/mxnextactiondatastart.h b/LEGO1/omni/include/mxnextactiondatastart.h similarity index 62% rename from LEGO1/mxnextactiondatastart.h rename to LEGO1/omni/include/mxnextactiondatastart.h index 10d2a2f2..0f08ec75 100644 --- a/LEGO1/mxnextactiondatastart.h +++ b/LEGO1/omni/include/mxnextactiondatastart.h @@ -16,25 +16,30 @@ class MxNextActionDataStart : public MxCore { } // FUNCTION: LEGO1 0x100c1900 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x101025a0 + // STRING: LEGO1 0x101025a0 return "MxNextActionDataStart"; } // FUNCTION: LEGO1 0x100c1910 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxNextActionDataStart::ClassName()) || MxCore::IsA(p_name); } inline MxU32 GetObjectId() const { return m_objectId; } inline MxS16 GetUnknown24() const { return m_unk0x24; } + inline MxU32 GetData() const { return m_data; } + inline void SetData(MxU32 p_data) { m_data = p_data; } + + // SYNTHETIC: LEGO1 0x100c1990 + // MxNextActionDataStart::`scalar deleting destructor' private: - MxU32 m_objectId; - MxS16 m_unk0x24; - MxU32 m_data; + MxU32 m_objectId; // 0x08 + MxS16 m_unk0x24; // 0x0c + MxU32 m_data; // 0x10 }; #endif // MXNEXTACTIONDATASTART_H diff --git a/LEGO1/mxnotificationmanager.h b/LEGO1/omni/include/mxnotificationmanager.h similarity index 50% rename from LEGO1/mxnotificationmanager.h rename to LEGO1/omni/include/mxnotificationmanager.h index 4a3d8726..287ae40b 100644 --- a/LEGO1/mxnotificationmanager.h +++ b/LEGO1/omni/include/mxnotificationmanager.h @@ -16,8 +16,8 @@ class MxNotification { inline MxNotificationParam* GetParam() { return m_param; } private: - MxCore* m_target; // 0x0 - MxNotificationParam* m_param; // 0x4 + MxCore* m_target; // 0x00 + MxNotificationParam* m_param; // 0x04 }; class MxIdList : public list {}; @@ -27,8 +27,8 @@ class MxNotificationPtrList : public list {}; // VTABLE: LEGO1 0x100dc078 class MxNotificationManager : public MxCore { private: - MxNotificationPtrList* m_queue; // 0x8 - MxNotificationPtrList* m_sendList; // 0xc + MxNotificationPtrList* m_queue; // 0x08 + MxNotificationPtrList* m_sendList; // 0x0c MxCriticalSection m_lock; // 0x10 MxS32 m_unk0x2c; // 0x2c MxIdList m_listenerIds; // 0x30 @@ -36,9 +36,9 @@ class MxNotificationManager : public MxCore { public: MxNotificationManager(); - virtual ~MxNotificationManager(); // vtable+0x0 (scalar deleting destructor) + ~MxNotificationManager() override; // vtable+0x00 (scalar deleting destructor) - virtual MxResult Tickle(); // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 // TODO: Where does this method come from? virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x14 void Register(MxCore* p_listener); @@ -48,8 +48,41 @@ class MxNotificationManager : public MxCore { inline MxNotificationPtrList* GetQueue() { return m_queue; } inline void SetActive(MxBool p_active) { m_active = p_active; } + // SYNTHETIC: LEGO1 0x100ac390 + // MxNotificationManager::`scalar deleting destructor' + private: 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/mxnotificationparam.h b/LEGO1/omni/include/mxnotificationparam.h similarity index 52% rename from LEGO1/mxnotificationparam.h rename to LEGO1/omni/include/mxnotificationparam.h index 66f9dd95..d0ad675f 100644 --- a/LEGO1/mxnotificationparam.h +++ b/LEGO1/omni/include/mxnotificationparam.h @@ -8,48 +8,58 @@ 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_notificationClick = 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+0x04 inline NotificationId GetNotification() const { return m_type; } inline MxCore* GetSender() const { return m_sender; } inline NotificationId GetType() const { return m_type; } + inline void SetType(NotificationId p_type) { m_type = p_type; } + inline void SetSender(MxCore* p_sender) { m_sender = p_sender; } + protected: - NotificationId m_type; // 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/mxobjectfactory.h b/LEGO1/omni/include/mxobjectfactory.h similarity index 89% rename from LEGO1/mxobjectfactory.h rename to LEGO1/omni/include/mxobjectfactory.h index cfc97308..aed354c4 100644 --- a/LEGO1/mxobjectfactory.h +++ b/LEGO1/omni/include/mxobjectfactory.h @@ -24,14 +24,14 @@ class MxObjectFactory : public MxCore { MxObjectFactory(); // FUNCTION: LEGO1 0x10008f70 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f0730 + // STRING: LEGO1 0x100f0730 return "MxObjectFactory"; } // FUNCTION: LEGO1 0x10008f80 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxObjectFactory::ClassName()) || MxCore::IsA(p_name); } @@ -39,6 +39,9 @@ class MxObjectFactory : public MxCore { virtual MxCore* Create(const char* p_name); // vtable 0x14 virtual void Destroy(MxCore* p_object); // vtable 0x18 + // SYNTHETIC: LEGO1 0x100b1160 + // MxObjectFactory::`scalar deleting destructor' + private: #define X(V) MxAtomId m_id##V; FOR_MXOBJECTFACTORY_OBJECTS(X) diff --git a/LEGO1/mxomni.h b/LEGO1/omni/include/mxomni.h similarity index 73% rename from LEGO1/mxomni.h rename to LEGO1/omni/include/mxomni.h index 7bac0723..7f0a0362 100644 --- a/LEGO1/mxomni.h +++ b/LEGO1/omni/include/mxomni.h @@ -28,19 +28,19 @@ class MxStreamController; // SIZE 0x68 class MxOmni : public MxCore { public: - __declspec(dllexport) static void DestroyInstance(); - __declspec(dllexport) static const char* GetCD(); - __declspec(dllexport) static const char* GetHD(); - __declspec(dllexport) static MxOmni* GetInstance(); - __declspec(dllexport) static MxBool IsSound3D(); - __declspec(dllexport) static void SetCD(const char* p_cd); - __declspec(dllexport) static void SetHD(const char* p_hd); - __declspec(dllexport) static void SetSound3D(MxBool p_use3dSound); + static void DestroyInstance(); + static const char* GetCD(); + static const char* GetHD(); + static MxOmni* GetInstance(); + static MxBool IsSound3D(); + static void SetCD(const char* p_cd); + static void SetHD(const char* p_hd); + static void SetSound3D(MxBool p_use3dSound); MxOmni(); - virtual ~MxOmni() override; + ~MxOmni() override; - virtual MxLong Notify(MxParam& p_param) override; // vtable+04 + MxLong Notify(MxParam& p_param) override; // vtable+04 virtual void Init(); // vtable+14 virtual MxResult Create(MxOmniCreateParam& p_param); // vtable+18 virtual void Destroy(); // vtable+1c @@ -48,14 +48,16 @@ class MxOmni : public MxCore { virtual void DeleteObject(MxDSAction& p_dsAction); // vtable+24 virtual MxBool DoesEntityExist(MxDSAction& p_dsAction); // vtable+28 virtual MxResult CreatePresenter(MxStreamController* p_controller, MxDSAction& p_action); // vtable+2c - virtual MxEntity* FindWorld(const char*, MxS32, MxPresenter*); // vtable+30 + virtual MxEntity* AddToWorld(const char*, MxS32, MxPresenter*); // vtable+30 virtual void NotifyCurrentEntity(MxNotificationParam* p_param); // vtable+34 virtual void StartTimer(); // vtable+38 virtual void StopTimer(); // vtable+3c - 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); + static MxBool ActionSourceEquals(MxDSAction* p_action, const char* p_name); HWND GetWindowHandle() const { return this->m_windowHandle; } MxObjectFactory* GetObjectFactory() const { return this->m_objectFactory; } @@ -71,10 +73,13 @@ class MxOmni : public MxCore { MxAtomIdCounterSet* GetAtomIdCounterSet() const { return this->m_atomIdCounterSet; } MxLong HandleActionEnd(MxParam& p_param); + // SYNTHETIC: LEGO1 0x100aefd0 + // MxOmni::`scalar deleting destructor' + protected: static MxOmni* g_instance; - MxString m_mediaPath; // 0x8 + MxString m_mediaPath; // 0x08 HWND m_windowHandle; // 0x18 MxObjectFactory* m_objectFactory; // 0x1C MxVariableTable* m_variableTable; // 0x20 @@ -91,19 +96,19 @@ class MxOmni : public MxCore { MxBool m_timerRunning; // 0x64 }; -__declspec(dllexport) MxTickleManager* TickleManager(); -__declspec(dllexport) MxTimer* Timer(); -__declspec(dllexport) MxStreamer* Streamer(); -__declspec(dllexport) MxSoundManager* MSoundManager(); -__declspec(dllexport) MxVariableTable* VariableTable(); -__declspec(dllexport) MxMusicManager* MusicManager(); -__declspec(dllexport) MxEventManager* EventManager(); -__declspec(dllexport) MxNotificationManager* NotificationManager(); +MxTickleManager* TickleManager(); +MxTimer* Timer(); +MxStreamer* Streamer(); +MxSoundManager* MSoundManager(); +MxVariableTable* VariableTable(); +MxMusicManager* MusicManager(); +MxEventManager* EventManager(); +MxResult Start(MxDSAction*); +MxNotificationManager* NotificationManager(); MxVideoManager* MVideoManager(); MxAtomIdCounterSet* AtomIdCounterSet(); 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 new file mode 100644 index 00000000..1e9f334d --- /dev/null +++ b/LEGO1/omni/include/mxomnicreateflags.h @@ -0,0 +1,86 @@ +#ifndef MXOMNICREATEFLAGS_H +#define MXOMNICREATEFLAGS_H + +#include "mxtypes.h" + +class MxOmniCreateFlags { +public: + enum LowFlags { + 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 { + c_createTimer = 0x02, + c_createStreamer = 0x04 + }; + + MxOmniCreateFlags(); + + 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 & 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 | c_createObjectFactory : this->m_flags1 & ~c_createObjectFactory); + } + inline void CreateVariableTable(MxBool p_enable) + { + 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 | c_createTickleManager : this->m_flags1 & ~c_createTickleManager); + } + inline void CreateNotificationManager(MxBool p_enable) + { + this->m_flags1 = + (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 | c_createVideoManager : this->m_flags1 & ~c_createVideoManager); + } + inline void CreateSoundManager(MxBool p_enable) + { + 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 | c_createMusicManager : this->m_flags1 & ~c_createMusicManager); + } + inline void CreateEventManager(MxBool p_enable) + { + 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 | c_createTimer : this->m_flags2 & ~c_createTimer); + } + inline void CreateStreamer(MxBool p_enable) + { + this->m_flags2 = (p_enable ? this->m_flags2 | c_createStreamer : this->m_flags2 & ~c_createStreamer); + } + +private: + MxU8 m_flags1; + MxU8 m_flags2; +}; + +#endif // MXOMNICREATEFLAGS_H diff --git a/LEGO1/mxomnicreateparam.h b/LEGO1/omni/include/mxomnicreateparam.h similarity index 80% rename from LEGO1/mxomnicreateparam.h rename to LEGO1/omni/include/mxomnicreateparam.h index 825b5053..8d04ed18 100644 --- a/LEGO1/mxomnicreateparam.h +++ b/LEGO1/omni/include/mxomnicreateparam.h @@ -8,9 +8,10 @@ #include +// VTABLE: LEGO1 0x100dc218 class MxOmniCreateParam : public MxParam { public: - __declspec(dllexport) MxOmniCreateParam( + MxOmniCreateParam( const char* p_mediaPath, struct HWND__* p_windowHandle, MxVideoParam& p_vparam, @@ -23,6 +24,9 @@ class MxOmniCreateParam : public MxParam { MxVideoParam& GetVideoParam() { return m_videoParam; } const MxVideoParam& GetVideoParam() const { return m_videoParam; } + // SYNTHETIC: LEGO1 0x100b0a70 + // MxOmniCreateParam::`scalar deleting destructor' + private: MxString m_mediaPath; HWND m_windowHandle; @@ -30,4 +34,7 @@ class MxOmniCreateParam : public MxParam { MxOmniCreateFlags m_createFlags; }; +// SYNTHETIC: ISLE 0x4014b0 +// MxOmniCreateParam::~MxOmniCreateParam + #endif // MXOMNICREATEPARAM_H diff --git a/LEGO1/mxpalette.h b/LEGO1/omni/include/mxpalette.h similarity index 80% rename from LEGO1/mxpalette.h rename to LEGO1/omni/include/mxpalette.h index 90ffa605..4f38c91b 100644 --- a/LEGO1/mxpalette.h +++ b/LEGO1/omni/include/mxpalette.h @@ -10,12 +10,12 @@ // SIZE 0x414 class MxPalette : public MxCore { public: - __declspec(dllexport) MxBool operator==(MxPalette& p_other); - __declspec(dllexport) void Detach(); + MxBool operator==(MxPalette& p_other); + void Detach(); MxPalette(); MxPalette(const RGBQUAD*); - virtual ~MxPalette(); + ~MxPalette() override; void ApplySystemEntriesToPalette(LPPALETTEENTRY p_entries); MxPalette* Clone(); @@ -28,9 +28,12 @@ class MxPalette : public MxCore { inline void SetOverrideSkyColor(MxBool p_value) { this->m_overrideSkyColor = p_value; } + // SYNTHETIC: LEGO1 0x100beeb0 + // MxPalette::`scalar deleting destructor' + private: LPDIRECTDRAWPALETTE m_palette; - PALETTEENTRY m_entries[256]; // 0xc + PALETTEENTRY m_entries[256]; // 0x0c MxBool m_overrideSkyColor; // 0x40c PALETTEENTRY m_skyColor; // 0x40d }; diff --git a/LEGO1/omni/include/mxparam.h b/LEGO1/omni/include/mxparam.h new file mode 100644 index 00000000..a266b12b --- /dev/null +++ b/LEGO1/omni/include/mxparam.h @@ -0,0 +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/mxpoint32.h b/LEGO1/omni/include/mxpoint32.h old mode 100755 new mode 100644 similarity index 76% rename from LEGO1/mxpoint32.h rename to LEGO1/omni/include/mxpoint32.h index d041e894..37c6dd19 --- a/LEGO1/mxpoint32.h +++ b/LEGO1/omni/include/mxpoint32.h @@ -6,12 +6,7 @@ class MxPoint32 { public: MxPoint32() {} - MxPoint32(MxS32 p_x, MxS32 p_y) - { - this->m_x = p_x; - this->m_y = p_y; - } - + MxPoint32(MxS32 p_x, MxS32 p_y) { CopyFrom(p_x, p_y); } MxPoint32(const MxPoint32& p_point) { this->m_x = p_point.m_x; @@ -25,8 +20,14 @@ class MxPoint32 { inline void SetY(MxS32 p_y) { m_y = p_y; } private: - MxS32 m_x; - MxS32 m_y; + inline void CopyFrom(MxS32 p_x, MxS32 p_y) + { + this->m_x = p_x; + this->m_y = p_y; + } + + MxS32 m_x; // 0x00 + MxS32 m_y; // 0x04 }; #endif // MXPOINT32_H diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h new file mode 100644 index 00000000..cd403949 --- /dev/null +++ b/LEGO1/omni/include/mxpresenter.h @@ -0,0 +1,143 @@ +#ifndef MXPRESENTER_H +#define MXPRESENTER_H + +#include "decomp.h" +#include "mxcore.h" +#include "mxcriticalsection.h" +#include "mxdsaction.h" +#include "mxomni.h" +#include "mxpoint32.h" + +class MxCompositePresenter; +class MxStreamController; +class MxEntity; + +// VTABLE: LEGO1 0x100d4d38 +// SIZE 0x40 +class MxPresenter : public MxCore { +public: + enum TickleState { + e_idle = 0, + e_ready, + e_starting, + e_streaming, + e_repeating, + e_unk5, + e_done, + }; + + MxPresenter() { Init(); } + + // FUNCTION: LEGO1 0x1000bf00 + ~MxPresenter() override{}; // vtable+0x00 + + MxResult Tickle() override; // vtable+0x08 + + // FUNCTION: LEGO1 0x1000bfe0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0740 + return "MxPresenter"; + } + + // FUNCTION: LEGO1 0x1000bff0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxPresenter::ClassName()) || MxCore::IsA(p_name); + } + + // 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: + // FUNCTION: LEGO1 0x1000bee0 + virtual void DoneTickle() { ProgressTickleState(e_idle); } // vtable+0x2c + + virtual void ParseExtra(); // vtable+0x30 + + inline void ProgressTickleState(TickleState p_tickleState) + { + m_previousTickleStates |= 1 << (MxU8) m_currentTickleState; + m_currentTickleState = p_tickleState; + } + +public: + // FUNCTION: LEGO1 0x1000bf70 + virtual MxResult AddToManager() { return SUCCESS; } // vtable+0x34 + + // FUNCTION: LEGO1 0x1000bf80 + virtual void Destroy() { Init(); } // vtable+0x38 + + virtual MxResult StartAction(MxStreamController*, MxDSAction*); // vtable+0x3c + virtual void EndAction(); // vtable+0x40 + + // FUNCTION: LEGO1 0x1000bf90 + virtual void SetTickleState(TickleState p_tickleState) { ProgressTickleState(p_tickleState); } // vtable+0x44 + + // 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 + + 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; } + inline MxPoint32 GetLocation() const { return this->m_location; } + inline MxS32 GetDisplayZ() const { return this->m_displayZ; } + inline MxDSAction* GetAction() const { return this->m_action; } + + inline void SetCompositePresenter(MxCompositePresenter* p_compositePresenter) + { + m_compositePresenter = p_compositePresenter; + } + + inline void SetDisplayZ(MxS32 p_displayZ) { m_displayZ = p_displayZ; } + + // SYNTHETIC: LEGO1 0x1000c070 + // MxPresenter::`scalar deleting destructor' + +protected: + void Init(); + + TickleState m_currentTickleState; // 0x08 + MxU32 m_previousTickleStates; // 0x0c + MxPoint32 m_location; // 0x10 + MxS32 m_displayZ; // 0x18 + MxDSAction* m_action; // 0x1c + MxCriticalSection m_criticalSection; // 0x20 + MxCompositePresenter* m_compositePresenter; // 0x3c +}; + +const char* PresenterNameDispatch(const MxDSAction&); + +#endif // MXPRESENTER_H diff --git a/LEGO1/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h similarity index 59% rename from LEGO1/mxpresenterlist.h rename to LEGO1/omni/include/mxpresenterlist.h index d8b74a3f..1c52f360 100644 --- a/LEGO1/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -14,10 +14,13 @@ class MxPresenterList : public MxPtrList { MxPresenterList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} // FUNCTION: LEGO1 0x1001cd00 - virtual MxS8 Compare(MxPresenter* p_a, MxPresenter* p_b) override + MxS8 Compare(MxPresenter* p_a, MxPresenter* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; - }; // vtable+0x14 + } // vtable+0x14 + + // SYNTHETIC: LEGO1 0x1001ceb0 + // MxPresenterList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100d6488 @@ -53,6 +56,9 @@ class MxPresenterListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x1001ce20 // MxList::~MxList +// TEMPLATE: LEGO1 0x1001cf20 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x1001cf70 // MxCollection::`scalar deleting destructor' @@ -62,4 +68,34 @@ class MxPresenterListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x1001d090 // MxPtrList::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x1001d100 +// MxPresenterList::~MxPresenterList + +// SYNTHETIC: LEGO1 0x1001eed0 +// MxPresenterListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001ef40 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001ef90 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f000 +// MxPtrListCursor::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001f070 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001f0c0 +// MxPresenterListCursor::~MxPresenterListCursor + +// TEMPLATE: LEGO1 0x10020760 +// MxListCursor::MxListCursor + +// TEMPLATE: LEGO1 0x10022380 +// MxList::InsertEntry + +// TEMPLATE: LEGO1 0x100225e0 +// MxList::DeleteEntry + #endif // MXPRESENTERLIST_H diff --git a/LEGO1/mxqueue.h b/LEGO1/omni/include/mxqueue.h similarity index 62% rename from LEGO1/mxqueue.h rename to LEGO1/omni/include/mxqueue.h index b6eaad55..4e45c035 100644 --- a/LEGO1/mxqueue.h +++ b/LEGO1/omni/include/mxqueue.h @@ -13,10 +13,10 @@ class MxQueue : public MxList { MxBool Dequeue(T& p_obj) { - MxBool hasNext = (m_first != NULL); - if (m_first) { - p_obj = m_first->GetValue(); - DeleteEntry(m_first); + MxBool hasNext = (this->m_first != NULL); + if (this->m_first) { + p_obj = this->m_first->GetValue(); + this->DeleteEntry(this->m_first); } return hasNext; diff --git a/LEGO1/mxramstreamcontroller.h b/LEGO1/omni/include/mxramstreamcontroller.h similarity index 60% rename from LEGO1/mxramstreamcontroller.h rename to LEGO1/omni/include/mxramstreamcontroller.h index 008fe458..820fc3f7 100644 --- a/LEGO1/mxramstreamcontroller.h +++ b/LEGO1/omni/include/mxramstreamcontroller.h @@ -12,27 +12,30 @@ class MxRAMStreamController : public MxStreamController { inline MxRAMStreamController() {} // FUNCTION: LEGO1 0x100b9430 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102118 + // STRING: LEGO1 0x10102118 return "MxRAMStreamController"; } // FUNCTION: LEGO1 0x100b9440 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxRAMStreamController::ClassName()) || !strcmp(p_name, MxStreamController::ClassName()) || MxCore::IsA(p_name); } - virtual MxResult Open(const char* p_filename) override; - virtual MxResult VTable0x20(MxDSAction* p_action) override; - virtual MxResult VTable0x24(MxDSAction* p_action) override; + MxResult Open(const char* p_filename) override; + MxResult VTable0x20(MxDSAction* p_action) override; + MxResult VTable0x24(MxDSAction* p_action) override; private: - MxDSBuffer m_buffer; + MxDSBuffer m_buffer; // 0x64 MxResult DeserializeObject(MxDSStreamingAction& p_action); }; +// SYNTHETIC: LEGO1 0x100b94f0 +// MxRAMStreamController::`scalar deleting destructor' + #endif // MXRAMSTREAMCONTROLLER_H diff --git a/LEGO1/omni/include/mxramstreamprovider.h b/LEGO1/omni/include/mxramstreamprovider.h new file mode 100644 index 00000000..08c1ea95 --- /dev/null +++ b/LEGO1/omni/include/mxramstreamprovider.h @@ -0,0 +1,47 @@ +#ifndef MXRAMSTREAMPROVIDER_H +#define MXRAMSTREAMPROVIDER_H + +#include "mxstreamprovider.h" + +// VTABLE: LEGO1 0x100dd0d0 +// SIZE 0x24 +class MxRAMStreamProvider : public MxStreamProvider { +public: + MxRAMStreamProvider(); + ~MxRAMStreamProvider() override; + + // FUNCTION: LEGO1 0x100d0970 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x10102864 + return "MxRAMStreamProvider"; + } + + // FUNCTION: LEGO1 0x100d0980 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxRAMStreamProvider::ClassName()) || MxStreamProvider::IsA(p_name); + } + + MxResult SetResourceToGet(MxStreamController* p_resource) override; // vtable+0x14 + MxU32 GetFileSize() override; // vtable+0x18 + MxS32 GetStreamBuffersNum() override; // vtable+0x1c + MxU32 GetLengthInDWords() override; // vtable+0x24 + MxU32* GetBufferForDWords() override; // vtable+0x28 + + inline MxU8* GetBufferOfFileSize() { return m_pBufferOfFileSize; } + +protected: + 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/mxrect32.h b/LEGO1/omni/include/mxrect32.h similarity index 76% rename from LEGO1/mxrect32.h rename to LEGO1/omni/include/mxrect32.h index b54a9d92..207d93fa 100644 --- a/LEGO1/mxrect32.h +++ b/LEGO1/omni/include/mxrect32.h @@ -8,22 +8,8 @@ class MxRect32 { public: MxRect32() {} - MxRect32(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) - { - this->m_left = p_left; - this->m_top = p_top; - this->m_right = p_right; - this->m_bottom = p_bottom; - } - - MxRect32(const MxPoint32& p_point, const MxSize32& p_size) - { - this->m_left = p_point.GetX(); - this->m_top = p_point.GetY(); - this->m_right = p_size.GetWidth(); - this->m_bottom = p_size.GetHeight(); - } - + MxRect32(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) { CopyFrom(p_left, p_top, p_right, p_bottom); } + MxRect32(const MxPoint32& p_point, const MxSize32& p_size) { CopyFrom(p_point, p_size); } MxRect32(const MxRect32& p_a, const MxRect32& p_b) { m_left = Max(p_a.m_left, p_b.m_left); @@ -62,10 +48,12 @@ class MxRect32 { this->m_bottom += p_point.GetY(); } - inline void SetSize(const MxSize32& p_size) + inline void SubtractPoint(const MxPoint32& p_point) { - this->m_right = p_size.GetWidth(); - this->m_bottom = p_size.GetHeight(); + this->m_left -= p_point.GetX(); + this->m_top -= p_point.GetY(); + this->m_right -= p_point.GetX(); + this->m_bottom -= p_point.GetY(); } inline void UpdateBounds(const MxRect32& p_rect) @@ -77,6 +65,7 @@ class MxRect32 { } inline MxBool IsValid() const { return m_left < m_right && m_top < m_bottom; } + inline MxBool IntersectsWith(const MxRect32& p_rect) const { return m_left < p_rect.m_right && p_rect.m_left < m_right && m_top < p_rect.m_bottom && p_rect.m_top < m_bottom; @@ -99,6 +88,14 @@ class MxRect32 { inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; } private: + inline void CopyFrom(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) + { + this->m_left = p_left; + this->m_top = p_top; + this->m_right = p_right; + this->m_bottom = p_bottom; + } + inline void CopyFrom(const MxRect32& p_rect) { this->m_left = p_rect.m_left; @@ -107,13 +104,24 @@ class MxRect32 { this->m_bottom = p_rect.m_bottom; } - inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; }; - inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; }; + // The address might also be the constructor that calls CopyFrom + // FUNCTION: LEGO1 0x100b6fc0 + inline MxRect32* CopyFrom(const MxPoint32& p_point, const MxSize32& p_size) + { + this->m_left = p_point.GetX(); + this->m_top = p_point.GetY(); + this->m_right = p_size.GetWidth() + p_point.GetX() - 1; + this->m_bottom = p_size.GetHeight() + p_point.GetY() - 1; + return this; + } - MxS32 m_left; - MxS32 m_top; - MxS32 m_right; - MxS32 m_bottom; + inline static MxS32 Min(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_a : p_b; } + inline static MxS32 Max(MxS32 p_a, MxS32 p_b) { return p_a <= p_b ? p_b : p_a; } + + MxS32 m_left; // 0x00 + MxS32 m_top; // 0x04 + MxS32 m_right; // 0x08 + MxS32 m_bottom; // 0x0c }; #endif // MXRECT32_H diff --git a/LEGO1/mxrectlist.h b/LEGO1/omni/include/mxrectlist.h similarity index 91% rename from LEGO1/mxrectlist.h rename to LEGO1/omni/include/mxrectlist.h index c0527f01..c25c2483 100644 --- a/LEGO1/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' @@ -69,13 +72,13 @@ class MxRectListCursor : public MxPtrListCursor { // MxRectListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b4090 -// MxPtrListCursor::~MxPtrListCursor +// MxPtrListCursor::~MxPtrListCursor // SYNTHETIC: LEGO1 0x100b40e0 // MxListCursor::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100b4150 -// MxPtrListCursor::`scalar deleting destructor' +// MxPtrListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100b41c0 // MxListCursor::~MxListCursor diff --git a/LEGO1/omni/include/mxregion.h b/LEGO1/omni/include/mxregion.h new file mode 100644 index 00000000..3bf639e1 --- /dev/null +++ b/LEGO1/omni/include/mxregion.h @@ -0,0 +1,34 @@ +#ifndef MXREGION_H +#define MXREGION_H + +#include "decomp.h" +#include "mxcore.h" +#include "mxrect32.h" +#include "mxregionlist.h" + +// VTABLE: LEGO1 0x100dcae8 +// SIZE 0x1c +class MxRegion : public MxCore { +public: + MxRegion(); + ~MxRegion() override; + + virtual void Reset(); // vtable+0x14 + virtual void VTable0x18(MxRect32& p_rect); // vtable+0x18 + virtual MxBool VTable0x1c(MxRect32& p_rect); // vtable+0x1c + virtual MxBool VTable0x20(); // vtable+0x20 + + inline MxRegionTopBottomList* GetTopBottomList() const { return m_list; } + inline const MxRect32& GetRect() const { return m_rect; } + + friend class MxRegionCursor; + + // SYNTHETIC: LEGO1 0x100c3670 + // MxRegion::`scalar deleting destructor' + +private: + MxRegionTopBottomList* m_list; // 0x08 + MxRect32 m_rect; // 0x0c +}; + +#endif // MXREGION_H diff --git a/LEGO1/omni/include/mxregioncursor.h b/LEGO1/omni/include/mxregioncursor.h new file mode 100644 index 00000000..e114c7ed --- /dev/null +++ b/LEGO1/omni/include/mxregioncursor.h @@ -0,0 +1,45 @@ +#ifndef MXREGIONCURSOR_H +#define MXREGIONCURSOR_H + +#include "mxregion.h" + +// VTABLE: LEGO1 0x100dcbb8 +// SIZE 0x18 +class MxRegionCursor : public MxCore { +public: + MxRegionCursor(MxRegion* p_region); + ~MxRegionCursor() override; + + virtual MxRect32* VTable0x14(MxRect32& p_rect); // vtable+0x14 + virtual MxRect32* VTable0x18(); // vtable+0x18 + virtual MxRect32* VTable0x1c(MxRect32& p_rect); // vtable+0x1c + virtual MxRect32* VTable0x20(); // vtable+0x20 + virtual MxRect32* VTable0x24(MxRect32& p_rect); // vtable+0x24 + virtual MxRect32* VTable0x28(); // vtable+0x28 + virtual MxRect32* VTable0x2c(MxRect32& p_rect); // vtable+0x2c + virtual MxRect32* VTable0x30(); // vtable+0x30 + + // FUNCTION: LEGO1 0x100c4070 + virtual MxRect32* GetRect() { return m_rect; } // vtable+0x34 + + // FUNCTION: LEGO1 0x100c4080 + virtual MxBool HasRect() { return m_rect != NULL; } // vtable+0x38 + + virtual void Reset(); // vtable+0x3c + +private: + void FUN_100c46c0(MxRegionLeftRightList& p_leftRightList); + void UpdateRect(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom); + void FUN_100c4a20(MxRect32& p_rect); + void FUN_100c4b50(MxRect32& p_rect); + + MxRegion* m_region; // 0x08 + MxRect32* m_rect; // 0x0c + MxRegionTopBottomListCursor* m_topBottomCursor; // 0x10 + MxRegionLeftRightListCursor* m_leftRightCursor; // 0x14 +}; + +// SYNTHETIC: LEGO1 0x100c4090 +// MxRegionCursor::`scalar deleting destructor' + +#endif // MXREGIONCURSOR_H diff --git a/LEGO1/mxregionlist.h b/LEGO1/omni/include/mxregionlist.h similarity index 73% rename from LEGO1/mxregionlist.h rename to LEGO1/omni/include/mxregionlist.h index ef3712cb..9dfd78bd 100644 --- a/LEGO1/mxregionlist.h +++ b/LEGO1/omni/include/mxregionlist.h @@ -19,9 +19,11 @@ struct MxRegionLeftRight { inline void SetLeft(MxS32 p_left) { m_left = p_left; } inline void SetRight(MxS32 p_right) { m_right = p_right; } + inline MxBool IntersectsWith(MxRect32& p_rect) { return m_left < p_rect.GetRight() && p_rect.GetTop() < m_right; } + private: - MxS32 m_left; - MxS32 m_right; + MxS32 m_left; // 0x00 + MxS32 m_right; // 0x04 }; // VTABLE: LEGO1 0x100dcc40 @@ -38,6 +40,9 @@ struct MxRegionLeftRight { class MxRegionLeftRightList : public MxPtrList { public: MxRegionLeftRightList() : MxPtrList(TRUE) {} + + // SYNTHETIC: LEGO1 0x100c4e90 + // MxRegionLeftRightList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dcbf8 @@ -68,12 +73,15 @@ struct MxRegionTopBottom { inline void SetTop(MxS32 p_top) { m_top = p_top; } inline void SetBottom(MxS32 p_bottom) { m_bottom = p_bottom; } - friend class MxRegionList; + inline MxBool IntersectsWith(MxRect32& p_rect) { return m_top < p_rect.GetBottom() && p_rect.GetTop() < m_bottom; } + + friend class MxRegionTopBottomList; + friend class MxRegionCursor; private: - MxS32 m_top; - MxS32 m_bottom; - MxRegionLeftRightList* m_leftRightList; + MxS32 m_top; // 0x00 + MxS32 m_bottom; // 0x04 + MxRegionLeftRightList* m_leftRightList; // 0x08 }; // VTABLE: LEGO1 0x100dcb10 @@ -87,9 +95,12 @@ struct MxRegionTopBottom { // VTABLE: LEGO1 0x100dcb58 // SIZE 0x18 -class MxRegionList : public MxPtrList { +class MxRegionTopBottomList : public MxPtrList { public: - MxRegionList() : MxPtrList(TRUE) {} + MxRegionTopBottomList() : MxPtrList(TRUE) {} + + // SYNTHETIC: LEGO1 0x100c3410 + // MxRegionTopBottomList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dcb70 @@ -98,25 +109,34 @@ class MxRegionList : public MxPtrList { // VTABLE: LEGO1 0x100dcba0 // class MxListCursor -// TODO: The initialize list param type should be MxRegionList, but doing that +// TODO: The initialize list param type should be MxRegionTopBottomList, but doing that // drastically reduced the match percentage for MxRegion::VTable0x18. // It also works with MxPtrList, so we'll do that until we figure this out. // VTABLE: LEGO1 0x100dcb88 -class MxRegionListCursor : public MxPtrListCursor { +class MxRegionTopBottomListCursor : public MxPtrListCursor { public: - MxRegionListCursor(MxPtrList* p_list) : MxPtrListCursor(p_list){}; + MxRegionTopBottomListCursor(MxPtrList* p_list) : MxPtrListCursor(p_list){}; }; // 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' @@ -127,7 +147,7 @@ class MxRegionListCursor : public MxPtrListCursor { // MxPtrList::`scalar deleting destructor' // SYNTHETIC: LEGO1 0x100c3be0 -// MxRegionListCursor::`scalar deleting destructor' +// MxRegionTopBottomListCursor::`scalar deleting destructor' // TEMPLATE: LEGO1 0x100c3c50 // MxPtrListCursor::~MxPtrListCursor @@ -142,7 +162,7 @@ class MxRegionListCursor : public MxPtrListCursor { // MxListCursor::~MxListCursor // FUNCTION: LEGO1 0x100c3dd0 -// MxRegionListCursor::~MxRegionListCursor +// MxRegionTopBottomListCursor::~MxRegionTopBottomListCursor // SYNTHETIC: LEGO1 0x100c4790 // MxRegionLeftRightListCursor::`scalar deleting destructor' @@ -162,9 +182,18 @@ class MxRegionListCursor : 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/mxscheduler.h b/LEGO1/omni/include/mxscheduler.h similarity index 51% rename from LEGO1/mxscheduler.h rename to LEGO1/omni/include/mxscheduler.h index 17b7ecb8..1f60029d 100644 --- a/LEGO1/mxscheduler.h +++ b/LEGO1/omni/include/mxscheduler.h @@ -5,8 +5,8 @@ class MxScheduler { public: - __declspec(dllexport) static MxScheduler* GetInstance(); - __declspec(dllexport) void StartMultiTasking(MxULong); + static MxScheduler* GetInstance(); + void StartMultiTasking(MxULong); }; #endif // MXSCHEDULER_H diff --git a/LEGO1/mxsemaphore.h b/LEGO1/omni/include/mxsemaphore.h similarity index 77% rename from LEGO1/mxsemaphore.h rename to LEGO1/omni/include/mxsemaphore.h index 3bc6d66b..4e692395 100644 --- a/LEGO1/mxsemaphore.h +++ b/LEGO1/omni/include/mxsemaphore.h @@ -5,11 +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); @@ -18,7 +20,7 @@ class MxSemaphore { void Release(MxU32 p_releaseCount); private: - HANDLE m_hSemaphore; + HANDLE m_hSemaphore; // 0x04 }; #endif // MX_SEMAPHORE_H diff --git a/LEGO1/mxsize32.h b/LEGO1/omni/include/mxsize32.h similarity index 72% rename from LEGO1/mxsize32.h rename to LEGO1/omni/include/mxsize32.h index a8b30368..8fb90210 100644 --- a/LEGO1/mxsize32.h +++ b/LEGO1/omni/include/mxsize32.h @@ -6,16 +6,18 @@ class MxSize32 { public: MxSize32() {} - MxSize32(MxS32 p_width, MxS32 p_height) - { - this->m_width = p_width; - this->m_height = p_height; - } + MxSize32(MxS32 p_width, MxS32 p_height) { CopyFrom(p_width, p_height); } inline MxS32 GetWidth() const { return m_width; } inline MxS32 GetHeight() const { return m_height; } private: + inline void CopyFrom(MxS32 p_width, MxS32 p_height) + { + this->m_width = p_width; + this->m_height = p_height; + } + MxS32 m_width; MxS32 m_height; }; diff --git a/LEGO1/mxsmack.h b/LEGO1/omni/include/mxsmack.h similarity index 86% rename from LEGO1/mxsmack.h rename to LEGO1/omni/include/mxsmack.h index e0f8c76e..227dbd6d 100644 --- a/LEGO1/mxsmack.h +++ b/LEGO1/omni/include/mxsmack.h @@ -12,10 +12,7 @@ // but present in SMACK.LIB and used directly by Mindscape. extern "C" { - // (SMACK.LIB) FUNCTION: LEGO1 0x100cd782 u32 SmackGetSizeTables(); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100cd7e8 void SmackDoTables( u8* p_huffmanTrees, u8* p_huffmanTables, @@ -24,14 +21,8 @@ extern "C" u32 p_detailSize, u32 p_typeSize ); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100cda83 void SmackDoFrameToBuffer(u8* p_source, u8* p_huffmanTables, u8* p_unk0x6b4); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100d052c u32 SmackGetSizeDeltas(u32 p_width, u32 p_height); - - // (SMACK.LIB) FUNCTION: LEGO1 0x100d0543 u8 SmackGetRect(u8* p_unk0x6b4, u32* p_rect); } diff --git a/LEGO1/omni/include/mxsmkpresenter.h b/LEGO1/omni/include/mxsmkpresenter.h new file mode 100644 index 00000000..d17ce59d --- /dev/null +++ b/LEGO1/omni/include/mxsmkpresenter.h @@ -0,0 +1,48 @@ +#ifndef MXSMKPRESENTER_H +#define MXSMKPRESENTER_H + +#include "decomp.h" +#include "mxsmack.h" +#include "mxvideopresenter.h" + +// VTABLE: LEGO1 0x100dc348 +// SIZE 0x720 +class MxSmkPresenter : public MxVideoPresenter { +public: + MxSmkPresenter(); + ~MxSmkPresenter() override; + + // FUNCTION: LEGO1 0x100b3730 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x10101e38 + return "MxSmkPresenter"; + } + + // FUNCTION: LEGO1 0x100b3740 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxSmkPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); + } + + MxResult AddToManager() override; // vtable+0x34 + void Destroy() override; // vtable+0x38 + void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c + void CreateBitmap() override; // vtable+0x60 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void RealizePalette() override; // vtable+0x70 + virtual void VTable0x88(); // vtable+0x88 + + // SYNTHETIC: LEGO1 0x100b3850 + // MxSmkPresenter::`scalar deleting destructor' + +private: + void Init(); + void Destroy(MxBool p_fromDestructor); + +protected: + MxSmack m_mxSmack; // 0x64 + MxU32 m_currentFrame; // 0x71c +}; + +#endif // MXSMKPRESENTER_H diff --git a/LEGO1/mxsoundmanager.h b/LEGO1/omni/include/mxsoundmanager.h similarity index 85% rename from LEGO1/mxsoundmanager.h rename to LEGO1/omni/include/mxsoundmanager.h index 1d897fe4..6dde7d5c 100644 --- a/LEGO1/mxsoundmanager.h +++ b/LEGO1/omni/include/mxsoundmanager.h @@ -12,10 +12,10 @@ class MxSoundManager : public MxAudioManager { public: MxSoundManager(); - virtual ~MxSoundManager() override; // vtable+0x0 + ~MxSoundManager() override; // vtable+0x00 - virtual void Destroy() override; // vtable+0x18 - virtual void SetVolume(MxS32 p_volume) override; // vtable+0x2c + void Destroy() override; // vtable+0x18 + void SetVolume(MxS32 p_volume) override; // vtable+0x2c virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x30 virtual void Pause(); // vtable+0x34 virtual void Resume(); // vtable+0x38 diff --git a/LEGO1/mxsoundpresenter.h b/LEGO1/omni/include/mxsoundpresenter.h similarity index 50% rename from LEGO1/mxsoundpresenter.h rename to LEGO1/omni/include/mxsoundpresenter.h index 1c4051ee..1281b2be 100644 --- a/LEGO1/mxsoundpresenter.h +++ b/LEGO1/omni/include/mxsoundpresenter.h @@ -8,23 +8,29 @@ // SIZE 0x54 class MxSoundPresenter : public MxAudioPresenter { public: - virtual ~MxSoundPresenter() override; + // FUNCTION: LEGO1 0x1000d430 + ~MxSoundPresenter() override { Destroy(TRUE); } // FUNCTION: LEGO1 0x1000d4a0 - inline virtual const char* ClassName() const // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x100f07a0 + // STRING: LEGO1 0x100f07a0 return "MxSoundPresenter"; - }; + } // FUNCTION: LEGO1 0x1000d4b0 - inline virtual MxBool IsA(const char* p_name) const // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxSoundPresenter::ClassName()) || MxAudioPresenter::IsA(p_name); - }; + } - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + MxResult AddToManager() override; // vtable+0x34 + + // FUNCTION: LEGO1 0x1000d490 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 + + // SYNTHETIC: LEGO1 0x1000d5c0 + // MxSoundPresenter::`scalar deleting destructor' protected: void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxstillpresenter.h b/LEGO1/omni/include/mxstillpresenter.h new file mode 100644 index 00000000..2a64aa09 --- /dev/null +++ b/LEGO1/omni/include/mxstillpresenter.h @@ -0,0 +1,56 @@ +#ifndef MXSTILLPRESENTER_H +#define MXSTILLPRESENTER_H + +#include "decomp.h" +#include "mxvideopresenter.h" + +// VTABLE: LEGO1 0x100d7a38 +// SIZE 0x6c +class MxStillPresenter : public MxVideoPresenter { +public: + MxStillPresenter() { m_bitmapInfo = NULL; } + + // FUNCTION: LEGO1 0x10043550 + ~MxStillPresenter() override { Destroy(TRUE); } // vtable+0x00 + + // FUNCTION: LEGO1 0x100435c0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0184 + return "MxStillPresenter"; + } + + // FUNCTION: LEGO1 0x100435d0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxStillPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); + } + + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void ParseExtra() override; // vtable+0x30 + + // FUNCTION: LEGO1 0x100435b0 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 + + void Enable(MxBool p_enable) override; // vtable+0x54 + void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c + void CreateBitmap() override; // vtable+0x60 + void NextFrame() override; // vtable+0x64 + void LoadFrame(MxStreamChunk* p_chunk) override; // vtable+0x68 + void RealizePalette() override; // vtable+0x70 + virtual void VTable0x88(MxS32 p_x, MxS32 p_y); // vtable+0x88 + virtual MxStillPresenter* Clone(); // vtable+0x8c + +private: + void Destroy(MxBool p_fromDestructor); + + MxLong m_chunkTime; // 0x64 + MxBITMAPINFO* m_bitmapInfo; // 0x68 +}; + +// SYNTHETIC: LEGO1 0x100436e0 +// MxStillPresenter::`scalar deleting destructor' + +#endif // MXSTILLPRESENTER_H diff --git a/LEGO1/mxstreamchunk.h b/LEGO1/omni/include/mxstreamchunk.h similarity index 59% rename from LEGO1/mxstreamchunk.h rename to LEGO1/omni/include/mxstreamchunk.h index 53cbfc68..00e242d0 100644 --- a/LEGO1/mxstreamchunk.h +++ b/LEGO1/omni/include/mxstreamchunk.h @@ -2,25 +2,27 @@ #define MXSTREAMCHUNK_H #include "mxdschunk.h" +#include "mxdsobject.h" class MxDSBuffer; +class MxStreamListMxDSSubscriber; // VTABLE: LEGO1 0x100dc2a8 // SIZE 0x20 class MxStreamChunk : public MxDSChunk { public: inline MxStreamChunk() : m_buffer(NULL) {} - virtual ~MxStreamChunk() override; + ~MxStreamChunk() override; // FUNCTION: LEGO1 0x100b1fe0 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10101e5c + // STRING: LEGO1 0x10101e5c return "MxStreamChunk"; } // FUNCTION: LEGO1 0x100b1ff0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamChunk::ClassName()) || MxDSChunk::IsA(p_name); } @@ -29,8 +31,14 @@ class MxStreamChunk : public MxDSChunk { MxResult ReadChunk(MxDSBuffer* p_buffer, MxU8* p_chunkData); MxU32 ReadChunkHeader(MxU8* p_chunkData); + MxResult SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_append, MxS16 p_obj24val); void SetBuffer(MxDSBuffer* p_buffer); + static MxU16* IntoFlags(MxU8* p_buffer); + static MxU32* IntoObjectId(MxU8* p_buffer); + static MxLong* IntoTime(MxU8* p_buffer); + static MxU32* IntoLength(MxU8* p_buffer); + private: MxDSBuffer* m_buffer; // 0x1c }; diff --git a/LEGO1/mxstreamchunklist.h b/LEGO1/omni/include/mxstreamchunklist.h similarity index 83% rename from LEGO1/mxstreamchunklist.h rename to LEGO1/omni/include/mxstreamchunklist.h index 02dcd2d9..defdd4a0 100644 --- a/LEGO1/mxstreamchunklist.h +++ b/LEGO1/omni/include/mxstreamchunklist.h @@ -19,16 +19,20 @@ class MxStreamChunkList : public MxList { MxStreamChunkList() { m_customDestructor = Destroy; } // FUNCTION: LEGO1 0x100b5900 - virtual MxS8 Compare(MxStreamChunk* p_a, MxStreamChunk* p_b) override + MxS8 Compare(MxStreamChunk* p_a, MxStreamChunk* p_b) override { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 // FUNCTION: LEGO1 0x100b5920 static void Destroy(MxStreamChunk* p_chunk) { delete p_chunk; } + + // SYNTHETIC: LEGO1 0x100b5a30 + // MxStreamChunkList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dc510 +// SIZE 0x10 class MxStreamChunkListCursor : public MxListCursor { public: MxStreamChunkListCursor(MxStreamChunkList* p_list) : MxListCursor(p_list){}; @@ -40,6 +44,9 @@ class MxStreamChunkListCursor : public MxListCursor { // TEMPLATE: LEGO1 0x100b5930 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100b5940 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100b5990 // MxCollection::Destroy diff --git a/LEGO1/mxstreamcontroller.h b/LEGO1/omni/include/mxstreamcontroller.h similarity index 80% rename from LEGO1/mxstreamcontroller.h rename to LEGO1/omni/include/mxstreamcontroller.h index ca3b09b3..f4bd328f 100644 --- a/LEGO1/mxstreamcontroller.h +++ b/LEGO1/omni/include/mxstreamcontroller.h @@ -19,17 +19,17 @@ class MxDSStreamingAction; class MxStreamController : public MxCore { public: MxStreamController(); - virtual ~MxStreamController() override; // vtable+0x0 + ~MxStreamController() override; // vtable+0x00 // FUNCTION: LEGO1 0x100c0f10 - inline virtual const char* ClassName() const override // vtable+0xc + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x10102130 + // STRING: LEGO1 0x10102130 return "MxStreamController"; } // FUNCTION: LEGO1 0x100c0f20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamController::ClassName()) || MxCore::IsA(p_name); } @@ -43,20 +43,24 @@ class MxStreamController : public MxCore { virtual MxResult VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval); // vtable+0x2c virtual MxResult VTable0x30(MxDSAction* p_action); // vtable+0x30 - void FUN_100c15d0(MxDSSubscriber* p_subscriber); - void FUN_100c1620(MxDSSubscriber* p_subscriber); + void AddSubscriber(MxDSSubscriber* p_subscriber); + void RemoveSubscriber(MxDSSubscriber* p_subscriber); MxResult FUN_100c1800(MxDSAction* p_action, MxU32 p_val); MxResult FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset); MxPresenter* FUN_100c1e70(MxDSAction& p_action); MxResult FUN_100c1f00(MxDSAction* p_action); MxBool FUN_100c20d0(MxDSObject& p_obj); MxResult InsertActionToList54(MxDSAction* p_action); + MxNextActionDataStart* FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action); - inline MxAtomId& GetAtom() { return m_atom; }; - inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; }; + inline MxAtomId& GetAtom() { return m_atom; } + inline MxStreamProvider* GetProvider() { return m_provider; } + inline MxStreamListMxDSAction& GetUnk0x3c() { return m_unk0x3c; } + inline MxStreamListMxDSAction& GetUnk0x54() { return m_unk0x54; } + inline MxStreamListMxDSSubscriber& GetSubscriberList() { return m_subscriberList; } protected: - MxCriticalSection m_criticalSection; // 0x8 + MxCriticalSection m_criticalSection; // 0x08 MxAtomId m_atom; // 0x24 MxStreamProvider* m_provider; // 0x28 undefined4* m_unk0x2c; // 0x2c @@ -84,6 +88,9 @@ class MxStreamController : public MxCore { // TEMPLATE: LEGO1 0x100c0ee0 // list >::_Buynode +// SYNTHETIC: LEGO1 0x100c0fa0 +// MxStreamController::`scalar deleting destructor' + // FUNCTION: LEGO1 0x100c0fc0 // MxStreamListMxDSSubscriber::~MxStreamListMxDSSubscriber @@ -111,4 +118,7 @@ class MxStreamController : public MxCore { // TEMPLATE: LEGO1 0x100c1240 // List::~List +// TEMPLATE: LEGO1 0x100c1bc0 +// list >::insert + #endif // MXSTREAMCONTROLLER_H diff --git a/LEGO1/mxstreamer.h b/LEGO1/omni/include/mxstreamer.h similarity index 62% rename from LEGO1/mxstreamer.h rename to LEGO1/omni/include/mxstreamer.h index 3b58b260..2308981d 100644 --- a/LEGO1/mxstreamer.h +++ b/LEGO1/omni/include/mxstreamer.h @@ -14,15 +14,24 @@ // STL. But I haven't figured out what yet (it's definitely not a vector). class MxStreamerSubClass1 { public: - inline MxStreamerSubClass1(undefined4 p_size); + inline MxStreamerSubClass1(undefined4 p_size) + { + m_buffer = NULL; + m_size = p_size; + undefined4* ptr = &m_unk0x08; + for (int i = 0; i >= 0; i--) { + ptr[i] = 0; + } + } + // FUNCTION: LEGO1 0x100b9110 ~MxStreamerSubClass1() { delete[] m_buffer; } undefined4 GetSize() const { return m_size; } void SetBuffer(undefined* p_buf) { m_buffer = p_buf; } inline undefined* GetBuffer() const { return m_buffer; } - inline undefined4 GetUnk08() const { return m_unk0x08; } + inline undefined* GetUnk08Ref() const { return (undefined*) &m_unk0x08; } private: undefined* m_buffer; @@ -40,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) @@ -48,9 +58,7 @@ class MxStreamerNotification : public MxNotificationParam { m_controller = p_ctrlr; } - virtual ~MxStreamerNotification() override {} - - virtual MxNotificationParam* Clone() override; + MxNotificationParam* Clone() override; MxStreamController* GetController() { return m_controller; } @@ -63,27 +71,27 @@ class MxStreamerNotification : public MxNotificationParam { class MxStreamer : public MxCore { public: enum OpenMode { - e_DiskStream, + e_diskStream = 0, e_RAMStream }; MxStreamer(); - virtual ~MxStreamer() override; // vtable+0x0 + ~MxStreamer() override; // vtable+0x00 - __declspec(dllexport) MxStreamController* Open(const char* p_name, MxU16 p_openMode); - __declspec(dllexport) MxLong Close(const char* p_name); + MxStreamController* Open(const char* p_name, MxU16 p_openMode); + MxLong Close(const char* p_name); - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 // FUNCTION: LEGO1 0x100b9000 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { - // GLOBAL: LEGO1 0x1010210c + // STRING: LEGO1 0x1010210c return "MxStreamer"; } // FUNCTION: LEGO1 0x100b9010 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamer::ClassName()) || MxCore::IsA(p_name); } @@ -92,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); @@ -100,9 +109,26 @@ class MxStreamer : public MxCore { inline const MxStreamerSubClass3& GetSubclass2() { return m_subclass2; } private: - list m_openStreams; // 0x8 + list m_openStreams; // 0x08 MxStreamerSubClass2 m_subclass1; // 0x14 MxStreamerSubClass3 m_subclass2; // 0x20 }; +// 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/mxstreamlist.h b/LEGO1/omni/include/mxstreamlist.h new file mode 100644 index 00000000..0e0f1e9f --- /dev/null +++ b/LEGO1/omni/include/mxstreamlist.h @@ -0,0 +1,56 @@ +#ifndef MXSTREAMLIST_H +#define MXSTREAMLIST_H + +#include "mxdsstreamingaction.h" +#include "mxdssubscriber.h" +#include "mxnextactiondatastart.h" +#include "mxstl/stlcompat.h" + +template +class MxStreamList : public list { +public: + MxBool PopFront(T& p_obj) + { + if (this->empty()) { + return FALSE; + } + + p_obj = this->front(); + this->pop_front(); + return TRUE; + } +}; + +// SIZE 0x0c +class MxStreamListMxDSAction : public MxStreamList { +public: + MxDSAction* Find(MxDSAction* p_action, MxBool p_delete); + + // There chance this list actually holds MxDSStreamingListAction + // instead of MxDSAction. Until then, we use this helper. + MxBool PopFrontStreamingAction(MxDSStreamingAction*& p_obj) + { + if (empty()) { + return FALSE; + } + + p_obj = (MxDSStreamingAction*) front(); + pop_front(); + return TRUE; + } +}; + +// SIZE 0x0c +class MxStreamListMxNextActionDataStart : public MxStreamList { +public: + MxNextActionDataStart* Find(MxU32 p_id, MxS16 p_value); + MxNextActionDataStart* FindAndErase(MxU32 p_id, MxS16 p_value); +}; + +// SIZE 0x0c +class MxStreamListMxDSSubscriber : public MxStreamList { +public: + MxDSSubscriber* Find(MxDSObject* p_object); +}; + +#endif // MXSTREAMLIST_H diff --git a/LEGO1/mxstreamprovider.h b/LEGO1/omni/include/mxstreamprovider.h similarity index 74% rename from LEGO1/mxstreamprovider.h rename to LEGO1/omni/include/mxstreamprovider.h index ecbe9ab4..1082fffe 100644 --- a/LEGO1/mxstreamprovider.h +++ b/LEGO1/omni/include/mxstreamprovider.h @@ -15,13 +15,13 @@ class MxStreamProvider : public MxCore { inline MxStreamProvider() : m_pLookup(NULL), m_pFile(NULL) {} // FUNCTION: LEGO1 0x100d07e0 - inline virtual const char* ClassName() const override // vtable+0x0c + inline const char* ClassName() const override // vtable+0x0c { return "MxStreamProvider"; } // FUNCTION: LEGO1 0x100d07f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxStreamProvider::ClassName()) || MxCore::IsA(p_name); } @@ -34,8 +34,14 @@ class MxStreamProvider : public MxCore { virtual MxU32* GetBufferForDWords() = 0; // vtable+0x28 protected: - MxStreamController* m_pLookup; - MxDSFile* m_pFile; + MxStreamController* m_pLookup; // 0x08 + MxDSFile* m_pFile; // 0x0c }; +// SYNTHETIC: LEGO1 0x100d0870 +// MxStreamProvider::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100d08e0 +// MxStreamProvider::~MxStreamProvider + #endif // MXSTREAMPROVIDER_H diff --git a/LEGO1/mxstring.h b/LEGO1/omni/include/mxstring.h similarity index 67% rename from LEGO1/mxstring.h rename to LEGO1/omni/include/mxstring.h index 13130a70..3ad5ac4e 100644 --- a/LEGO1/mxstring.h +++ b/LEGO1/omni/include/mxstring.h @@ -4,11 +4,12 @@ #include "mxcore.h" // VTABLE: LEGO1 0x100dc110 +// SIZE 0x10 class MxString : public MxCore { public: - __declspec(dllexport) MxString(const MxString& p_str); - __declspec(dllexport) virtual ~MxString(); - __declspec(dllexport) const MxString& operator=(const char* p_data); + MxString(const MxString& p_str); + ~MxString() override; + const MxString& operator=(const char* p_data); MxString(); MxString(const char*); @@ -21,9 +22,12 @@ class MxString : public MxCore { inline MxS8 Compare(const MxString& p_str) const { return strcmp(m_data, p_str.m_data); } inline const char* GetData() const { return m_data; } + // SYNTHETIC: LEGO1 0x100ae280 + // MxString::`scalar deleting destructor' + private: - char* m_data; - MxU16 m_length; + char* m_data; // 0x08 + MxU16 m_length; // 0x0c }; #endif // MXSTRING_H diff --git a/LEGO1/mxstringlist.h b/LEGO1/omni/include/mxstringlist.h similarity index 66% rename from LEGO1/mxstringlist.h rename to LEGO1/omni/include/mxstringlist.h index 6e75683d..6d07584f 100644 --- a/LEGO1/mxstringlist.h +++ b/LEGO1/omni/include/mxstringlist.h @@ -9,23 +9,42 @@ class MxStringList : public MxList {}; // VTABLE: LEGO1 0x100dd058 +// SIZE 0x10 class MxStringListCursor : public MxListCursor { public: MxStringListCursor(MxStringList* p_list) : MxListCursor(p_list){}; + + // SYNTHETIC: LEGO1 0x100cb860 + // MxStringList::`scalar deleting destructor' }; +// 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/mxthread.h b/LEGO1/omni/include/mxthread.h similarity index 63% rename from LEGO1/mxthread.h rename to LEGO1/omni/include/mxthread.h index 3c7faab0..93b14fb1 100644 --- a/LEGO1/mxthread.h +++ b/LEGO1/omni/include/mxthread.h @@ -8,6 +8,7 @@ class MxCore; // VTABLE: LEGO1 0x100dc860 +// SIZE 0x1c class MxThread { public: // Note: Comes before virtual destructor @@ -16,12 +17,13 @@ class MxThread { MxResult Start(MxS32 p_stack, MxS32 p_flag); void Terminate(); - void Sleep(MxS32 p_milliseconds); - // Inferred, not in DLL inline MxBool IsRunning() { return m_running; } + // SYNTHETIC: LEGO1 0x100bf580 + // MxThread::`scalar deleting destructor' + protected: MxThread(); @@ -31,27 +33,29 @@ class MxThread { private: static unsigned ThreadProc(void* p_thread); - MxULong m_hThread; - MxU32 m_threadId; - MxBool m_running; - MxSemaphore m_semaphore; + MxULong m_hThread; // 0x04 + MxU32 m_threadId; // 0x08 + MxBool m_running; // 0x0c + MxSemaphore m_semaphore; // 0x10 protected: - MxCore* m_target; + MxCore* m_target; // 0x18 }; // VTABLE: LEGO1 0x100dc6d8 +// SIZE 0x20 class MxTickleThread : public MxThread { public: MxTickleThread(MxCore* p_target, MxS32 p_frequencyMS); - - // Only inlined, no offset - virtual ~MxTickleThread() {} + ~MxTickleThread() override {} MxResult Run() override; + // SYNTHETIC: LEGO1 0x100b8c20 + // MxTickleThread::`scalar deleting destructor' + private: - MxS32 m_frequencyMS; + MxS32 m_frequencyMS; // 0x1c }; #endif // MXTHREAD_H diff --git a/LEGO1/mxticklemanager.h b/LEGO1/omni/include/mxticklemanager.h similarity index 67% rename from LEGO1/mxticklemanager.h rename to LEGO1/omni/include/mxticklemanager.h index 44694a61..f07d0dc3 100644 --- a/LEGO1/mxticklemanager.h +++ b/LEGO1/omni/include/mxticklemanager.h @@ -24,10 +24,10 @@ class MxTickleClient { inline void SetFlags(MxU16 p_flags) { m_flags = p_flags; } private: - MxCore* m_client; // 0x0 - MxTime m_interval; // 0x4 - MxTime m_lastUpdateTime; // 0x8 - MxU16 m_flags; // 0xc + MxCore* m_client; // 0x00 + MxTime m_interval; // 0x04 + MxTime m_lastUpdateTime; // 0x08 + MxU16 m_flags; // 0x0c }; typedef list MxTickleClientPtrList; @@ -36,18 +36,27 @@ typedef list MxTickleClientPtrList; class MxTickleManager : public MxCore { public: inline MxTickleManager() {} - virtual ~MxTickleManager(); // vtable+0x0 (scalar deleting destructor) + ~MxTickleManager() override; // vtable+0x00 (scalar deleting destructor) - virtual MxResult Tickle(); // vtable+0x8 + MxResult Tickle() override; // vtable+0x08 virtual void RegisterClient(MxCore* p_client, MxTime p_interval); // vtable+0x14 virtual void UnregisterClient(MxCore* p_client); // vtable+0x18 virtual void SetClientTickleInterval(MxCore* p_client, MxTime p_interval); // vtable+0x1c virtual MxTime GetClientTickleInterval(MxCore* p_client); // vtable+0x20 + // SYNTHETIC: LEGO1 0x1005a510 + // MxTickleManager::`scalar deleting destructor' + private: - MxTickleClientPtrList m_clients; // 0x8 + MxTickleClientPtrList m_clients; // 0x08 }; #define TICKLE_MANAGER_NOT_FOUND 0x80000000 +// TEMPLATE: LEGO1 0x1005a4a0 +// list >::~list > + +// TEMPLATE: LEGO1 0x1005a530 +// List::~List + #endif // MXTICKLEMANAGER_H diff --git a/LEGO1/mxtimer.h b/LEGO1/omni/include/mxtimer.h similarity index 76% rename from LEGO1/mxtimer.h rename to LEGO1/omni/include/mxtimer.h index 70d52d79..468cd602 100644 --- a/LEGO1/mxtimer.h +++ b/LEGO1/omni/include/mxtimer.h @@ -12,16 +12,21 @@ class MxTimer : public MxCore { void Start(); void Stop(); - __declspec(dllexport) MxLong GetRealTime(); + MxLong GetRealTime(); inline MxLong GetTime() { - if (this->m_isRunning) + if (this->m_isRunning) { return g_lastTimeTimerStarted; - else + } + else { return g_lastTimeCalculated - this->m_startTime; + } } + // SYNTHETIC: LEGO1 0x100ae0d0 + // MxTimer::`scalar deleting destructor' + private: MxLong m_startTime; MxBool m_isRunning; diff --git a/LEGO1/mxtype18notificationparam.h b/LEGO1/omni/include/mxtype18notificationparam.h similarity index 90% rename from LEGO1/mxtype18notificationparam.h rename to LEGO1/omni/include/mxtype18notificationparam.h index bce896e3..589fd2bb 100644 --- a/LEGO1/mxtype18notificationparam.h +++ b/LEGO1/omni/include/mxtype18notificationparam.h @@ -8,7 +8,7 @@ // SIZE 0x10 class MxType18NotificationParam : public MxNotificationParam { protected: - undefined4 m_unk0xc; // 0xc + undefined4 m_unk0x0c; // 0x0c }; #endif // MXTYPE18NOTIFICATIONPARAM_H diff --git a/LEGO1/mxtype19notificationparam.h b/LEGO1/omni/include/mxtype19notificationparam.h similarity index 84% rename from LEGO1/mxtype19notificationparam.h rename to LEGO1/omni/include/mxtype19notificationparam.h index ddd47998..51a6a713 100644 --- a/LEGO1/mxtype19notificationparam.h +++ b/LEGO1/omni/include/mxtype19notificationparam.h @@ -8,8 +8,8 @@ // SIZE 0x10 class MxType19NotificationParam : public MxNotificationParam { protected: - MxU16 m_unk0xc; // 0xc - MxU8 m_unk0xe; // 0xe + MxU16 m_unk0x0c; // 0x0c + MxU8 m_unk0x0e; // 0x0e }; #endif // MXTYPE19NOTIFICATIONPARAM_H diff --git a/LEGO1/mxtypes.h b/LEGO1/omni/include/mxtypes.h similarity index 100% rename from LEGO1/mxtypes.h rename to LEGO1/omni/include/mxtypes.h diff --git a/LEGO1/omni/include/mxutil.h b/LEGO1/omni/include/mxutil.h new file mode 100644 index 00000000..c85259bb --- /dev/null +++ b/LEGO1/omni/include/mxutil.h @@ -0,0 +1,82 @@ +#ifndef MXUTIL_H +#define MXUTIL_H + +#include "mxtypes.h" + +#include + +class MxDSFile; +class MxDSObject; +class MxDSAction; +class MxCompositePresenterList; +class MxPresenter; + +template +inline T Abs(T p_t) +{ + return p_t < 0 ? -p_t : p_t; +} + +template +inline T Min(T p_t1, T p_t2) +{ + return p_t1 < p_t2 ? p_t1 : p_t2; +} + +template +inline T Max(T p_t1, T p_t2) +{ + return p_t1 > p_t2 ? p_t1 : p_t2; +} + +template +inline void GetScalar(MxU8** p_source, T& p_dest) +{ + p_dest = *(T*) *p_source; + *p_source += sizeof(T); +} + +template +inline T GetScalar(T** p_source) +{ + T val = **p_source; + *p_source += 1; + return val; +} + +template +inline void GetDouble(MxU8** p_source, T& p_dest) +{ + p_dest = *(double*) *p_source; + *p_source += sizeof(double); +} + +template +inline void GetString(MxU8** p_source, char** p_dest, T* p_obj, void (T::*p_setter)(const char*)) +{ + (p_obj->*p_setter)((char*) *p_source); + *p_source += strlen(*p_dest) + 1; +} + +MxBool GetRectIntersection( + MxS32 p_rect1Width, + MxS32 p_rect1Height, + MxS32 p_rect2Width, + MxS32 p_rect2Height, + MxS32* p_rect1Left, + MxS32* p_rect1Top, + MxS32* p_rect2Left, + MxS32* p_rect2Top, + MxS32* p_width, + MxS32* p_height +); + +void MakeSourceName(char*, const char*); +void SetOmniUserMessage(void (*)(const char*, int)); +MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter); +void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags); +MxDSObject* CreateStreamObject(MxDSFile*, MxS16); + +MxBool KeyValueStringParse(char*, const char*, const char*); + +#endif // MXUTIL_H diff --git a/LEGO1/mxvariable.h b/LEGO1/omni/include/mxvariable.h similarity index 55% rename from LEGO1/mxvariable.h rename to LEGO1/omni/include/mxvariable.h index d1434467..9b0a3816 100644 --- a/LEGO1/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/mxvariabletable.h b/LEGO1/omni/include/mxvariabletable.h similarity index 67% rename from LEGO1/mxvariabletable.h rename to LEGO1/omni/include/mxvariabletable.h index 7821311e..81059f9d 100644 --- a/LEGO1/mxvariabletable.h +++ b/LEGO1/omni/include/mxvariabletable.h @@ -10,14 +10,17 @@ class MxVariableTable : public MxHashTable { public: MxVariableTable() { m_customDestructor = Destroy; } - __declspec(dllexport) void SetVariable(const char* p_key, const char* p_value); - __declspec(dllexport) void SetVariable(MxVariable* p_var); - __declspec(dllexport) const char* GetVariable(const char* p_key); + void SetVariable(const char* p_key, const char* p_value); + void SetVariable(MxVariable* p_var); + const char* GetVariable(const char* p_key); static void Destroy(MxVariable* p_obj) { p_obj->Destroy(); } - virtual MxS8 Compare(MxVariable*, MxVariable*) override; // vtable+0x14 - virtual MxU32 Hash(MxVariable*) override; // vtable+0x18 + MxS8 Compare(MxVariable*, MxVariable*) override; // vtable+0x14 + MxU32 Hash(MxVariable*) override; // vtable+0x18 + + // SYNTHETIC: LEGO1 0x100afdd0 + // MxVariableTable::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dc1b0 @@ -26,6 +29,9 @@ class MxVariableTable : public MxHashTable { // VTABLE: LEGO1 0x100dc1e8 // class MxHashTable +// VTABLE: LEGO1 0x100dc680 +// class MxHashTableCursor + // TEMPLATE: LEGO1 0x100afcd0 // MxCollection::Compare @@ -50,6 +56,12 @@ class MxVariableTable : public MxHashTable { // SYNTHETIC: LEGO1 0x100b0ca0 // MxHashTable::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x100b7680 +// MxHashTableCursor::~MxHashTableCursor + +// SYNTHETIC: LEGO1 0x100b76d0 +// MxHashTableCursor::`scalar deleting destructor' + // TEMPLATE: LEGO1 0x100b7ab0 // MxHashTable::Resize diff --git a/LEGO1/mxvideomanager.h b/LEGO1/omni/include/mxvideomanager.h similarity index 72% rename from LEGO1/mxvideomanager.h rename to LEGO1/omni/include/mxvideomanager.h index 6d03d84e..a915f5f5 100644 --- a/LEGO1/mxvideomanager.h +++ b/LEGO1/omni/include/mxvideomanager.h @@ -7,19 +7,21 @@ #include "mxregion.h" #include "mxvideoparam.h" +#include + // VTABLE: LEGO1 0x100dc810 // SIZE 0x64 class MxVideoManager : public MxMediaManager { public: MxVideoManager(); - virtual ~MxVideoManager() override; + ~MxVideoManager() override; - virtual MxResult Tickle() override; // vtable+0x8 - virtual void Destroy() override; // vtable+0x18 + MxResult Tickle() override; // vtable+0x08 + void Destroy() override; // vtable+0x18 virtual MxResult VTable0x28( MxVideoParam& p_videoParam, LPDIRECTDRAW p_pDirectDraw, - LPDIRECTDRAWSURFACE p_pDDSurface, + LPDIRECT3D2 p_pDirect3D, LPDIRECTDRAWSURFACE p_ddSurface1, LPDIRECTDRAWSURFACE p_ddSurface2, LPDIRECTDRAWCLIPPER p_ddClipper, @@ -28,9 +30,9 @@ class MxVideoManager : public MxMediaManager { ); // vtable+0x28 virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x2c - __declspec(dllexport) void InvalidateRect(MxRect32&); - __declspec(dllexport) virtual MxResult RealizePalette(MxPalette*); // vtable+0x30 - virtual void VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height); // vtable+0x34 + void InvalidateRect(MxRect32&); + virtual MxResult RealizePalette(MxPalette*); // vtable+0x30 + virtual void UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height); // vtable+0x34 MxResult Init(); void Destroy(MxBool p_fromDestructor); @@ -40,11 +42,15 @@ class MxVideoManager : public MxMediaManager { inline MxVideoParam& GetVideoParam() { return this->m_videoParam; } inline LPDIRECTDRAW GetDirectDraw() { return this->m_pDirectDraw; } inline MxDisplaySurface* GetDisplaySurface() { return this->m_displaySurface; } + inline MxRegion* GetRegion() { return this->m_region; } + + // SYNTHETIC: LEGO1 0x100be280 + // MxVideoManager::`scalar deleting destructor' protected: MxVideoParam m_videoParam; // 0x2c LPDIRECTDRAW m_pDirectDraw; // 0x50 - LPDIRECTDRAWSURFACE m_pDDSurface; // 0x54 + LPDIRECT3D2 m_pDirect3D; // 0x54 MxDisplaySurface* m_displaySurface; // 0x58 MxRegion* m_region; // 0x5c MxBool m_unk0x60; // 0x60 diff --git a/LEGO1/mxvideoparam.h b/LEGO1/omni/include/mxvideoparam.h similarity index 66% rename from LEGO1/mxvideoparam.h rename to LEGO1/omni/include/mxvideoparam.h index 977c0b48..b9ae10ba 100644 --- a/LEGO1/mxvideoparam.h +++ b/LEGO1/omni/include/mxvideoparam.h @@ -13,18 +13,13 @@ // SIZE 0x24 class MxVideoParam { public: - __declspec(dllexport) MxVideoParam(); - __declspec(dllexport) MxVideoParam(MxVideoParam& p_videoParam); - __declspec(dllexport) MxVideoParam( - COMPAT_CONST MxRect32& p_rect, - MxPalette* p_palette, - MxULong p_backBuffers, - COMPAT_CONST MxVideoParamFlags& p_flags - ); - __declspec(dllexport) MxVideoParam& operator=(const MxVideoParam& p_videoParam); - __declspec(dllexport) ~MxVideoParam(); - - __declspec(dllexport) void SetDeviceName(char* p_deviceId); + MxVideoParam(); + MxVideoParam(MxVideoParam& p_videoParam); + __declspec(dllexport) + MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_backBuffers, MxVideoParamFlags& p_flags); + MxVideoParam& operator=(const MxVideoParam& p_videoParam); + ~MxVideoParam(); + void SetDeviceName(char* p_deviceId); inline MxVideoParamFlags& Flags() { return m_flags; } @@ -34,6 +29,7 @@ class MxVideoParam { inline MxRect32& GetRect() { return this->m_rect; } inline MxPalette* GetPalette() { return this->m_palette; } inline MxU32 GetBackBuffers() { return this->m_backBuffers; } + inline char* GetDeviceName() { return this->m_deviceId; } private: MxRect32 m_rect; // 0x00 diff --git a/LEGO1/mxvideoparamflags.h b/LEGO1/omni/include/mxvideoparamflags.h similarity index 97% rename from LEGO1/mxvideoparamflags.h rename to LEGO1/omni/include/mxvideoparamflags.h index 551a6c0a..8b937d38 100644 --- a/LEGO1/mxvideoparamflags.h +++ b/LEGO1/omni/include/mxvideoparamflags.h @@ -7,7 +7,7 @@ class MxVideoParamFlags { public: - __declspec(dllexport) MxVideoParamFlags(); + MxVideoParamFlags(); inline void SetFullScreen(BOOL p_e) { m_flags1.m_bit0 = p_e; } inline void SetFlipSurfaces(BOOL p_e) { m_flags1.m_bit1 = p_e; } diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h new file mode 100644 index 00000000..06436163 --- /dev/null +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -0,0 +1,125 @@ +#ifndef MXVIDEOPRESENTER_H +#define MXVIDEOPRESENTER_H + +#include "decomp.h" +#include "mxbitmap.h" +#include "mxmediapresenter.h" +#include "mxrect32.h" + +// VTABLE: LEGO1 0x100d4be8 +// SIZE 0x64 +class MxVideoPresenter : public MxMediaPresenter { +public: + MxVideoPresenter() { Init(); } + + // FUNCTION: LEGO1 0x1000c740 + ~MxVideoPresenter() override { Destroy(TRUE); } // vtable+0x00 + + // FUNCTION: LEGO1 0x1000c820 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f0760 + return "MxVideoPresenter"; + } + + // FUNCTION: LEGO1 0x1000c830 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxVideoPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void RepeatingTickle() override; // vtable+0x24 + void Unk5Tickle() override; // vtable+0x28 + MxResult AddToManager() override; // vtable+0x34 + + // FUNCTION: LEGO1 0x1000c7a0 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 + + void EndAction() override; // vtable+0x40 + MxResult PutData() override; // vtable+0x4c + MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 + + // FUNCTION: LEGO1 0x1000c700 + virtual void LoadHeader(MxStreamChunk* p_chunk){}; // vtable+0x5c + + // 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 0x0c + struct AlphaMask { + MxU8* m_bitmask; + MxU16 m_width; + MxU16 m_height; + + AlphaMask(const MxBitmap&); + AlphaMask(const AlphaMask&); + virtual ~AlphaMask(); + + MxS32 IsHit(MxU32 p_x, MxU32 p_y); + + // SYNTHETIC: LEGO1 0x100b2650 + // MxVideoPresenter::AlphaMask::`scalar deleting destructor' + }; + + inline MxS32 PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc); + inline MxBitmap* GetBitmap() { return m_bitmap; } + inline AlphaMask* GetAlphaMask() { return m_alpha; } + + inline void SetBit0(BOOL p_e) { m_flags.m_bit0 = p_e; } + inline void SetBit1(BOOL p_e) { m_flags.m_bit1 = p_e; } + inline void SetBit2(BOOL p_e) { m_flags.m_bit2 = p_e; } + inline void SetBit3(BOOL p_e) { m_flags.m_bit3 = p_e; } + inline void SetBit4(BOOL p_e) { m_flags.m_bit4 = p_e; } + + inline BYTE GetBit0() { return m_flags.m_bit0; } + inline BYTE GetBit1() { return m_flags.m_bit1; } + inline BYTE GetBit2() { return m_flags.m_bit2; } + inline BYTE GetBit3() { return m_flags.m_bit3; } + inline BYTE GetBit4() { return m_flags.m_bit4; } + + // SYNTHETIC: LEGO1 0x1000c910 + // MxVideoPresenter::`scalar deleting destructor' + +private: + void Init(); + +protected: + void Destroy(MxBool p_fromDestructor); + + MxBitmap* m_bitmap; // 0x50 + AlphaMask* m_alpha; // 0x54 + LPDIRECTDRAWSURFACE m_unk0x58; // 0x58 + MxS16 m_unk0x5c; // 0x5c + FlagBitfield m_flags; // 0x5e + MxLong m_unk0x60; // 0x60 +}; + +#endif // MXVIDEOPRESENTER_H diff --git a/LEGO1/omni/include/mxwavepresenter.h b/LEGO1/omni/include/mxwavepresenter.h new file mode 100644 index 00000000..982914bf --- /dev/null +++ b/LEGO1/omni/include/mxwavepresenter.h @@ -0,0 +1,82 @@ +#ifndef MXWAVEPRESENTER_H +#define MXWAVEPRESENTER_H + +#include "decomp.h" +#include "mxsoundpresenter.h" + +#include + +// VTABLE: LEGO1 0x100d49a8 +// SIZE 0x6c +class MxWavePresenter : public MxSoundPresenter { +public: + MxWavePresenter() { Init(); } + + // FUNCTION: LEGO1 0x1000d640 + ~MxWavePresenter() override { Destroy(TRUE); } // vtable+0x00 + + // FUNCTION: LEGO1 0x1000d6c0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f07b4 + return "MxWavePresenter"; + } + + // FUNCTION: LEGO1 0x1000d6d0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, MxWavePresenter::ClassName()) || MxSoundPresenter::IsA(p_name); + } + + void ReadyTickle() override; // vtable+0x18 + void StartingTickle() override; // vtable+0x1c + void StreamingTickle() override; // vtable+0x20 + void DoneTickle() override; // vtable+0x2c + void ParseExtra() override; // vtable+0x30 + MxResult AddToManager() override; // vtable+0x34 + + // FUNCTION: LEGO1 0x1000d6a0 + void Destroy() override { Destroy(FALSE); } // vtable+0x38 + + void EndAction() override; // vtable+0x40 + MxResult PutData() override; // vtable+0x4c + void Enable(MxBool p_enable) override; // vtable+0x54 + void LoopChunk(MxStreamChunk* p_chunk) override; // vtable+0x58 + void SetVolume(MxS32 p_volume) override; // vtable+0x60 + virtual void Pause(); // vtable+0x64 + virtual void Resume(); // vtable+0x68 + + // FUNCTION: LEGO1 0x1000d6b0 + virtual MxBool IsPaused() { return m_paused; } // vtable+0x6c + + // SIZE 0x18 + struct WaveFormat { + PCMWAVEFORMAT m_pcmWaveFormat; // 0x00 + MxU32 m_dataSize; // 0x10 + MxU32 m_flags; // 0x14 + }; + + // SYNTHETIC: LEGO1 0x1000d810 + // MxWavePresenter::`scalar deleting destructor' + +protected: + void Destroy(MxBool p_fromDestructor); + +private: + void Init(); + MxS8 GetPlayedChunks(); + MxBool FUN_100b1ba0(); + void WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length); + + WaveFormat* m_waveFormat; // 0x54 + LPDIRECTSOUNDBUFFER m_dsBuffer; // 0x58 + MxU32 m_chunkLength; // 0x5c + MxU32 m_lockSize; // 0x60 + MxU8 m_writtenChunks; // 0x64 + MxBool m_started; // 0x65 + MxBool m_unk0x66; // 0x66 + MxS8 m_silenceData; // 0x67 + MxBool m_paused; // 0x68 +}; + +#endif // MXWAVEPRESENTER_H diff --git a/LEGO1/mxdsaction.cpp b/LEGO1/omni/src/action/mxdsaction.cpp similarity index 86% rename from LEGO1/mxdsaction.cpp rename to LEGO1/omni/src/action/mxdsaction.cpp index 36533a1a..49f40561 100644 --- a/LEGO1/mxdsaction.cpp +++ b/LEGO1/omni/src/action/mxdsaction.cpp @@ -1,8 +1,8 @@ #include "mxdsaction.h" -#include "legoutil.h" #include "mxomni.h" #include "mxtimer.h" +#include "mxutil.h" #include #include @@ -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() { @@ -102,8 +108,9 @@ MxU32 MxDSAction::GetSizeOnDisk() // FUNCTION: LEGO1 0x100adc10 MxDSAction& MxDSAction::operator=(MxDSAction& p_dsAction) { - if (this == &p_dsAction) + if (this == &p_dsAction) { return *this; + } MxDSObject::operator=(p_dsAction); this->CopyFrom(p_dsAction); @@ -115,8 +122,9 @@ MxDSAction* MxDSAction::Clone() { MxDSAction* clone = new MxDSAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -130,35 +138,47 @@ MxLong MxDSAction::GetElapsedTime() // FUNCTION: LEGO1 0x100add00 void MxDSAction::MergeFrom(MxDSAction& p_dsAction) { - if (p_dsAction.m_startTime != INT_MIN) + if (p_dsAction.m_startTime != INT_MIN) { this->m_startTime = p_dsAction.m_startTime; + } - if (p_dsAction.GetDuration() != INT_MIN) + if (p_dsAction.GetDuration() != INT_MIN) { this->m_duration = p_dsAction.GetDuration(); + } - if (p_dsAction.m_loopCount != -1) + if (p_dsAction.m_loopCount != -1) { this->m_loopCount = p_dsAction.m_loopCount; + } - if (p_dsAction.m_location[0] != FLT_MAX) + if (p_dsAction.m_location[0] != FLT_MAX) { this->m_location[0] = p_dsAction.m_location[0]; - if (p_dsAction.m_location[1] != FLT_MAX) + } + if (p_dsAction.m_location[1] != FLT_MAX) { this->m_location[1] = p_dsAction.m_location[1]; - if (p_dsAction.m_location[2] != FLT_MAX) + } + if (p_dsAction.m_location[2] != FLT_MAX) { this->m_location[2] = p_dsAction.m_location[2]; + } - if (p_dsAction.m_direction[0] != FLT_MAX) + if (p_dsAction.m_direction[0] != FLT_MAX) { this->m_direction[0] = p_dsAction.m_direction[0]; - if (p_dsAction.m_direction[1] != FLT_MAX) + } + if (p_dsAction.m_direction[1] != FLT_MAX) { this->m_direction[1] = p_dsAction.m_direction[1]; - if (p_dsAction.m_direction[2] != FLT_MAX) + } + if (p_dsAction.m_direction[2] != FLT_MAX) { this->m_direction[2] = p_dsAction.m_up[2]; // This is correct + } - if (p_dsAction.m_up[0] != FLT_MAX) + if (p_dsAction.m_up[0] != FLT_MAX) { this->m_up[0] = p_dsAction.m_up[0]; - if (p_dsAction.m_up[1] != FLT_MAX) + } + if (p_dsAction.m_up[1] != FLT_MAX) { this->m_up[1] = p_dsAction.m_up[1]; - if (p_dsAction.m_up[2] != FLT_MAX) + } + if (p_dsAction.m_up[2] != FLT_MAX) { this->m_up[2] = p_dsAction.m_up[2]; + } MxU16 extraLength = p_dsAction.m_extraLength; char* extraData = p_dsAction.m_extraData; @@ -179,8 +199,9 @@ void MxDSAction::MergeFrom(MxDSAction& p_dsAction) // FUNCTION: LEGO1 0x100ade60 void MxDSAction::AppendData(MxU16 p_extraLength, const char* p_extraData) { - if (this->m_extraData == p_extraData || !p_extraData) + if (this->m_extraData == p_extraData || !p_extraData) { return; + } if (this->m_extraLength) { char* concat = new char[p_extraLength + this->m_extraLength + sizeof(g_sep)]; diff --git a/LEGO1/mxdsanim.cpp b/LEGO1/omni/src/action/mxdsanim.cpp similarity index 89% rename from LEGO1/mxdsanim.cpp rename to LEGO1/omni/src/action/mxdsanim.cpp index c62be34c..c90933b1 100644 --- a/LEGO1/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 @@ -21,8 +21,9 @@ void MxDSAnim::CopyFrom(MxDSAnim& p_dsAnim) // FUNCTION: LEGO1 0x100c9200 MxDSAnim& MxDSAnim::operator=(MxDSAnim& p_dsAnim) { - if (this == &p_dsAnim) + if (this == &p_dsAnim) { return *this; + } MxDSMediaAction::operator=(p_dsAnim); this->CopyFrom(p_dsAnim); @@ -34,8 +35,9 @@ MxDSAction* MxDSAnim::Clone() { MxDSAnim* clone = new MxDSAnim(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/mxdsevent.cpp b/LEGO1/omni/src/action/mxdsevent.cpp similarity index 89% rename from LEGO1/mxdsevent.cpp rename to LEGO1/omni/src/action/mxdsevent.cpp index 198c9ca0..64702e65 100644 --- a/LEGO1/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 @@ -21,8 +21,9 @@ void MxDSEvent::CopyFrom(MxDSEvent& p_dsEvent) // FUNCTION: LEGO1 0x100c9800 MxDSEvent& MxDSEvent::operator=(MxDSEvent& p_dsEvent) { - if (this == &p_dsEvent) + if (this == &p_dsEvent) { return *this; + } MxDSMediaAction::operator=(p_dsEvent); this->CopyFrom(p_dsEvent); @@ -34,8 +35,9 @@ MxDSAction* MxDSEvent::Clone() { MxDSEvent* clone = new MxDSEvent(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/mxdsmediaaction.cpp b/LEGO1/omni/src/action/mxdsmediaaction.cpp similarity index 78% rename from LEGO1/mxdsmediaaction.cpp rename to LEGO1/omni/src/action/mxdsmediaaction.cpp index 9e07f2d3..c563b380 100644 --- a/LEGO1/mxdsmediaaction.cpp +++ b/LEGO1/omni/src/action/mxdsmediaaction.cpp @@ -1,6 +1,6 @@ #include "mxdsmediaaction.h" -#include "legoutil.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxDSMediaAction, 0xb8) @@ -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 @@ -39,29 +39,51 @@ void MxDSMediaAction::CopyFrom(MxDSMediaAction& p_dsMediaAction) // FUNCTION: LEGO1 0x100c8dc0 MxDSMediaAction& MxDSMediaAction::operator=(MxDSMediaAction& p_dsMediaAction) { - if (this == &p_dsMediaAction) + if (this == &p_dsMediaAction) { return *this; + } MxDSAction::operator=(p_dsMediaAction); this->CopyFrom(p_dsMediaAction); 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) { - if (this->m_mediaSrcPath == p_mediaSrcPath) + if (this->m_mediaSrcPath == p_mediaSrcPath) { return; + } delete[] this->m_mediaSrcPath; if (p_mediaSrcPath) { this->m_mediaSrcPath = new char[strlen(p_mediaSrcPath) + 1]; - if (this->m_mediaSrcPath) + if (this->m_mediaSrcPath) { strcpy(this->m_mediaSrcPath, p_mediaSrcPath); + } } - else + else { this->m_mediaSrcPath = NULL; + } +} + +// FUNCTION: LEGO1 0x100c8f00 +undefined4 MxDSMediaAction::VTable0x14() +{ + return MxDSAction::VTable0x14(); } // FUNCTION: LEGO1 0x100c8f10 @@ -69,10 +91,12 @@ MxU32 MxDSMediaAction::GetSizeOnDisk() { MxU32 totalSizeOnDisk = MxDSAction::GetSizeOnDisk(); - if (this->m_mediaSrcPath) + if (this->m_mediaSrcPath) { totalSizeOnDisk += strlen(this->m_mediaSrcPath) + 1; - else + } + else { totalSizeOnDisk++; + } totalSizeOnDisk += 24; this->m_sizeOnDisk = totalSizeOnDisk - MxDSAction::GetSizeOnDisk(); @@ -84,7 +108,7 @@ void MxDSMediaAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) { MxDSAction::Deserialize(p_source, p_unk0x24); - GetString(p_source, this->m_mediaSrcPath, this, &MxDSMediaAction::CopyMediaSrcPath); + GetString(p_source, &this->m_mediaSrcPath, this, &MxDSMediaAction::CopyMediaSrcPath); GetScalar(p_source, this->m_unk0x9c.m_unk0x00); GetScalar(p_source, this->m_unk0x9c.m_unk0x04); GetScalar(p_source, this->m_framesPerSecond); diff --git a/LEGO1/mxdsmultiaction.cpp b/LEGO1/omni/src/action/mxdsmultiaction.cpp similarity index 88% rename from LEGO1/mxdsmultiaction.cpp rename to LEGO1/omni/src/action/mxdsmultiaction.cpp index b986c23d..40216ae7 100644 --- a/LEGO1/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); } @@ -15,8 +15,9 @@ MxDSMultiAction::MxDSMultiAction() // FUNCTION: LEGO1 0x100ca060 MxDSMultiAction::~MxDSMultiAction() { - if (this->m_actions) + if (this->m_actions) { delete this->m_actions; + } } // FUNCTION: LEGO1 0x100ca0d0 @@ -26,15 +27,17 @@ void MxDSMultiAction::CopyFrom(MxDSMultiAction& p_dsMultiAction) MxDSActionListCursor cursor(p_dsMultiAction.m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { this->m_actions->Append(action->Clone()); + } } // FUNCTION: LEGO1 0x100ca260 MxDSMultiAction& MxDSMultiAction::operator=(MxDSMultiAction& p_dsMultiAction) { - if (this == &p_dsMultiAction) + if (this == &p_dsMultiAction) { return *this; + } MxDSAction::operator=(p_dsMultiAction); this->CopyFrom(p_dsMultiAction); @@ -48,8 +51,9 @@ void MxDSMultiAction::SetUnknown90(MxLong p_unk0x90) MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { action->SetUnknown90(p_unk0x90); + } } // FUNCTION: LEGO1 0x100ca370 @@ -59,21 +63,24 @@ void MxDSMultiAction::MergeFrom(MxDSAction& p_dsMultiAction) MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { action->MergeFrom(p_dsMultiAction); + } } // FUNCTION: LEGO1 0x100ca450 MxBool MxDSMultiAction::HasId(MxU32 p_objectId) { - if (this->GetObjectId() == p_objectId) + if (this->GetObjectId() == p_objectId) { return TRUE; + } MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; while (cursor.Next(action)) { - if (action->HasId(p_objectId)) + if (action->HasId(p_objectId)) { return TRUE; + } } return FALSE; @@ -84,8 +91,9 @@ MxDSAction* MxDSMultiAction::Clone() { MxDSMultiAction* clone = new MxDSMultiAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -97,8 +105,9 @@ undefined4 MxDSMultiAction::VTable0x14() MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { result += action->VTable0x14(); + } return result; } @@ -110,8 +119,9 @@ MxU32 MxDSMultiAction::GetSizeOnDisk() MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { totalSizeOnDisk += action->GetSizeOnDisk(); + } this->m_sizeOnDisk = totalSizeOnDisk - MxDSAction::GetSizeOnDisk(); @@ -151,6 +161,7 @@ void MxDSMultiAction::SetAtomId(MxAtomId p_atomId) MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; - while (cursor.Next(action)) + while (cursor.Next(action)) { action->SetAtomId(p_atomId); + } } diff --git a/LEGO1/mxdsobject.cpp b/LEGO1/omni/src/action/mxdsobject.cpp similarity index 83% rename from LEGO1/mxdsobject.cpp rename to LEGO1/omni/src/action/mxdsobject.cpp index fa0b944c..9bbdf195 100644 --- a/LEGO1/mxdsobject.cpp +++ b/LEGO1/omni/src/action/mxdsobject.cpp @@ -1,6 +1,5 @@ #include "mxdsobject.h" -#include "legoutil.h" #include "mxdsaction.h" #include "mxdsanim.h" #include "mxdsevent.h" @@ -12,7 +11,7 @@ #include "mxdsserialaction.h" #include "mxdssound.h" #include "mxdsstill.h" -#include "mxdstypes.h" +#include "mxutil.h" #include #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; @@ -53,8 +52,9 @@ void MxDSObject::CopyFrom(MxDSObject& p_dsObject) // FUNCTION: LEGO1 0x100bf8c0 MxDSObject& MxDSObject::operator=(MxDSObject& p_dsObject) { - if (this == &p_dsObject) + if (this == &p_dsObject) { return *this; + } this->CopyFrom(p_dsObject); return *this; @@ -109,17 +109,21 @@ MxU32 MxDSObject::GetSizeOnDisk() { MxU32 sizeOnDisk; - if (this->m_sourceName) + if (this->m_sourceName) { sizeOnDisk = strlen(this->m_sourceName) + 3; - else + } + else { sizeOnDisk = 3; + } sizeOnDisk += 4; - if (this->m_objectName) + if (this->m_objectName) { sizeOnDisk += strlen(this->m_objectName) + 1; - else + } + else { sizeOnDisk++; + } sizeOnDisk += 4; this->m_sizeOnDisk = sizeOnDisk; @@ -129,9 +133,9 @@ MxU32 MxDSObject::GetSizeOnDisk() // FUNCTION: LEGO1 0x100bfa20 void MxDSObject::Deserialize(MxU8** p_source, MxS16 p_unk0x24) { - GetString(p_source, this->m_sourceName, this, &MxDSObject::SetSourceName); + GetString(p_source, &this->m_sourceName, this, &MxDSObject::SetSourceName); GetScalar(p_source, this->m_unk0x14); - GetString(p_source, this->m_objectName, this, &MxDSObject::SetObjectName); + GetString(p_source, &this->m_objectName, this, &MxDSObject::SetObjectName); GetScalar(p_source, this->m_objectId); this->m_unk0x24 = p_unk0x24; @@ -148,40 +152,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/mxdsobjectaction.cpp b/LEGO1/omni/src/action/mxdsobjectaction.cpp similarity index 89% rename from LEGO1/mxdsobjectaction.cpp rename to LEGO1/omni/src/action/mxdsobjectaction.cpp index 1155d3a5..40eadec3 100644 --- a/LEGO1/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 @@ -21,8 +21,9 @@ void MxDSObjectAction::CopyFrom(MxDSObjectAction& p_dsObjectAction) // FUNCTION: LEGO1 0x100c8a80 MxDSObjectAction& MxDSObjectAction::operator=(MxDSObjectAction& p_dsObjectAction) { - if (this == &p_dsObjectAction) + if (this == &p_dsObjectAction) { return *this; + } MxDSMediaAction::operator=(p_dsObjectAction); this->CopyFrom(p_dsObjectAction); @@ -34,8 +35,9 @@ MxDSAction* MxDSObjectAction::Clone() { MxDSObjectAction* clone = new MxDSObjectAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/mxdsparallelaction.cpp b/LEGO1/omni/src/action/mxdsparallelaction.cpp similarity index 84% rename from LEGO1/mxdsparallelaction.cpp rename to LEGO1/omni/src/action/mxdsparallelaction.cpp index 07b0fef2..f4e61245 100644 --- a/LEGO1/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 @@ -23,8 +23,9 @@ void MxDSParallelAction::CopyFrom(MxDSParallelAction& p_dsParallelAction) // FUNCTION: LEGO1 0x100cb0a0 MxDSParallelAction& MxDSParallelAction::operator=(MxDSParallelAction& p_dsParallelAction) { - if (this == &p_dsParallelAction) + if (this == &p_dsParallelAction) { return *this; + } MxDSMultiAction::operator=(p_dsParallelAction); this->CopyFrom(p_dsParallelAction); @@ -36,8 +37,9 @@ MxDSAction* MxDSParallelAction::Clone() { MxDSParallelAction* clone = new MxDSParallelAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -45,15 +47,17 @@ MxDSAction* MxDSParallelAction::Clone() // FUNCTION: LEGO1 0x100cb160 MxLong MxDSParallelAction::GetDuration() { - if (this->m_duration) + if (this->m_duration) { return this->m_duration; + } MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; while (cursor.Next(action)) { - if (!action) + if (!action) { continue; + } MxLong duration = action->GetDuration(); if (duration == -1) { @@ -65,10 +69,12 @@ MxLong MxDSParallelAction::GetDuration() if (action->IsA("MxDSMediaAction")) { MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime(); - if (sustainTime == -1) + if (sustainTime == -1) { duration = -1; - else if (sustainTime) + } + else if (sustainTime) { duration += sustainTime; + } } if (duration == -1) { @@ -76,12 +82,14 @@ MxLong MxDSParallelAction::GetDuration() break; } - if (this->m_duration < duration) + if (this->m_duration < duration) { this->m_duration = duration; + } } - if (this->IsBit3()) + if (this->IsBit3()) { this->m_duration *= this->m_loopCount; + } return this->m_duration; } diff --git a/LEGO1/mxdsselectaction.cpp b/LEGO1/omni/src/action/mxdsselectaction.cpp similarity index 89% rename from LEGO1/mxdsselectaction.cpp rename to LEGO1/omni/src/action/mxdsselectaction.cpp index 27f3a9cf..97e9ff73 100644 --- a/LEGO1/mxdsselectaction.cpp +++ b/LEGO1/omni/src/action/mxdsselectaction.cpp @@ -5,20 +5,23 @@ #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; } // FUNCTION: LEGO1 0x100cb8d0 MxDSSelectAction::~MxDSSelectAction() { - if (this->m_unk0xac) + if (this->m_unk0xac) { delete this->m_unk0xac; + } } // FUNCTION: LEGO1 0x100cb950 @@ -30,8 +33,9 @@ void MxDSSelectAction::CopyFrom(MxDSSelectAction& p_dsSelectAction) MxStringListCursor cursor(p_dsSelectAction.m_unk0xac); MxString string; - while (cursor.Next(string)) + while (cursor.Next(string)) { this->m_unk0xac->Append(string); + } } // FUNCTION: LEGO1 0x100cbd50 @@ -49,8 +53,9 @@ MxDSAction* MxDSSelectAction::Clone() { MxDSSelectAction* clone = new MxDSSelectAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -64,8 +69,9 @@ MxU32 MxDSSelectAction::GetSizeOnDisk() MxStringListCursor cursor(this->m_unk0xac); MxString string; - while (cursor.Next(string)) + while (cursor.Next(string)) { totalSizeOnDisk += strlen(string.GetData()) + 1; + } // Note: unlike the other classes, MxDSSelectAction does not have its own // sizeOnDisk member. Instead, it overrides the one from MxDSMultiAction. @@ -93,8 +99,9 @@ void MxDSSelectAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) MxS32 random = rand() % value; string = itoa((MxS16) random, buffer, 10); } - else + else { string = VariableTable()->GetVariable((char*) *p_source); + } *p_source += strlen((char*) *p_source) + 1; @@ -107,8 +114,9 @@ void MxDSSelectAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) MxU32 i; for (i = 0; i < count; i++) { - if (!strcmp(string.GetData(), (char*) *p_source)) + if (!strcmp(string.GetData(), (char*) *p_source)) { index = i; + } this->m_unk0xac->Append((char*) *p_source); *p_source += strlen((char*) *p_source) + 1; @@ -120,10 +128,12 @@ void MxDSSelectAction::Deserialize(MxU8** p_source, MxS16 p_unk0x24) MxDSAction* action = (MxDSAction*) DeserializeDSObjectDispatch(p_source, p_unk0x24); - if (index == i) + if (index == i) { this->m_actions->Append(action); - else + } + else { delete action; + } *p_source += extraFlag; } diff --git a/LEGO1/mxdsserialaction.cpp b/LEGO1/omni/src/action/mxdsserialaction.cpp similarity index 87% rename from LEGO1/mxdsserialaction.cpp rename to LEGO1/omni/src/action/mxdsserialaction.cpp index 59cda938..b03efdf0 100644 --- a/LEGO1/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; } @@ -21,8 +21,9 @@ void MxDSSerialAction::SetDuration(MxLong p_duration) // FUNCTION: LEGO1 0x100cac10 MxDSSerialAction::~MxDSSerialAction() { - if (this->m_cursor) + if (this->m_cursor) { delete this->m_cursor; + } this->m_cursor = NULL; } @@ -35,8 +36,9 @@ void MxDSSerialAction::CopyFrom(MxDSSerialAction& p_dsSerialAction) // FUNCTION: LEGO1 0x100caca0 MxDSSerialAction& MxDSSerialAction::operator=(MxDSSerialAction& p_dsSerialAction) { - if (this == &p_dsSerialAction) + if (this == &p_dsSerialAction) { return *this; + } MxDSMultiAction::operator=(p_dsSerialAction); this->CopyFrom(p_dsSerialAction); @@ -48,8 +50,9 @@ MxDSAction* MxDSSerialAction::Clone() { MxDSSerialAction* clone = new MxDSSerialAction(); - if (clone) + if (clone) { *clone = *this; + } return clone; } @@ -57,23 +60,26 @@ MxDSAction* MxDSSerialAction::Clone() // FUNCTION: LEGO1 0x100cad60 MxLong MxDSSerialAction::GetDuration() { - if (this->m_duration) + if (this->m_duration) { return this->m_duration; + } MxDSActionListCursor cursor(this->m_actions); MxDSAction* action; while (cursor.Next(action)) { - if (!action) + if (!action) { continue; + } this->m_duration += action->GetDuration() + action->GetStartTime(); if (action->IsA("MxDSMediaAction")) { MxLong sustainTime = ((MxDSMediaAction*) action)->GetSustainTime(); - if (sustainTime && sustainTime != -1) + if (sustainTime && sustainTime != -1) { this->m_duration += sustainTime; + } } } diff --git a/LEGO1/mxdssound.cpp b/LEGO1/omni/src/action/mxdssound.cpp similarity index 92% rename from LEGO1/mxdssound.cpp rename to LEGO1/omni/src/action/mxdssound.cpp index 359ff906..e75ad0c9 100644 --- a/LEGO1/mxdssound.cpp +++ b/LEGO1/omni/src/action/mxdssound.cpp @@ -1,6 +1,6 @@ #include "mxdssound.h" -#include "legoutil.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxDSSound, 0xc0) @@ -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 @@ -26,8 +26,9 @@ void MxDSSound::CopyFrom(MxDSSound& p_dsSound) // FUNCTION: LEGO1 0x100c94e0 MxDSSound& MxDSSound::operator=(MxDSSound& p_dsSound) { - if (this == &p_dsSound) + if (this == &p_dsSound) { return *this; + } MxDSMediaAction::operator=(p_dsSound); this->CopyFrom(p_dsSound); @@ -39,8 +40,9 @@ MxDSAction* MxDSSound::Clone() { MxDSSound* clone = new MxDSSound(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/mxdsstill.cpp b/LEGO1/omni/src/action/mxdsstill.cpp similarity index 89% rename from LEGO1/mxdsstill.cpp rename to LEGO1/omni/src/action/mxdsstill.cpp index 6ee1ede3..c044a2e6 100644 --- a/LEGO1/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 @@ -21,8 +21,9 @@ void MxDSStill::CopyFrom(MxDSStill& p_dsStill) // FUNCTION: LEGO1 0x100c9ad0 MxDSStill& MxDSStill::operator=(MxDSStill& p_dsStill) { - if (this == &p_dsStill) + if (this == &p_dsStill) { return *this; + } MxDSMediaAction::operator=(p_dsStill); this->CopyFrom(p_dsStill); @@ -34,8 +35,9 @@ MxDSAction* MxDSStill::Clone() { MxDSStill* clone = new MxDSStill(); - if (clone) + if (clone) { *clone = *this; + } return clone; } diff --git a/LEGO1/mxdsstreamingaction.cpp b/LEGO1/omni/src/action/mxdsstreamingaction.cpp similarity index 91% rename from LEGO1/mxdsstreamingaction.cpp rename to LEGO1/omni/src/action/mxdsstreamingaction.cpp index e8eb4dc1..85759897 100644 --- a/LEGO1/mxdsstreamingaction.cpp +++ b/LEGO1/omni/src/action/mxdsstreamingaction.cpp @@ -17,8 +17,9 @@ MxDSStreamingAction::MxDSStreamingAction(MxDSAction& p_dsAction, MxU32 p_offset) // FUNCTION: LEGO1 0x100cd090 MxBool MxDSStreamingAction::HasId(MxU32 p_objectId) { - if (this->m_internalAction) + if (this->m_internalAction) { return this->m_internalAction->HasId(p_objectId); + } return FALSE; } @@ -32,12 +33,15 @@ MxDSStreamingAction::MxDSStreamingAction(MxDSStreamingAction& p_dsStreamingActio // FUNCTION: LEGO1 0x100cd150 MxDSStreamingAction::~MxDSStreamingAction() { - if (this->m_unk0xa0) + if (this->m_unk0xa0) { delete this->m_unk0xa0; - if (this->m_unk0xa4) + } + if (this->m_unk0xa4) { delete this->m_unk0xa4; - if (this->m_internalAction) + } + if (this->m_internalAction) { delete this->m_internalAction; + } } // FUNCTION: LEGO1 0x100cd1e0 @@ -73,16 +77,18 @@ MxDSStreamingAction* MxDSStreamingAction::CopyFrom(MxDSStreamingAction& p_dsStre // FUNCTION: LEGO1 0x100cd2a0 void MxDSStreamingAction::SetInternalAction(MxDSAction* p_dsAction) { - if (this->m_internalAction) + if (this->m_internalAction) { delete this->m_internalAction; + } this->m_internalAction = p_dsAction; } // FUNCTION: LEGO1 0x100cd2d0 void MxDSStreamingAction::FUN_100cd2d0() { - if (this->m_duration == -1) + if (this->m_duration == -1) { return; + } MxLong duration = this->m_duration / this->m_loopCount; this->m_loopCount--; diff --git a/LEGO1/mxaudiomanager.cpp b/LEGO1/omni/src/audio/mxaudiomanager.cpp similarity index 89% rename from LEGO1/mxaudiomanager.cpp rename to LEGO1/omni/src/audio/mxaudiomanager.cpp index 318a8446..0be79a24 100644 --- a/LEGO1/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() { @@ -37,8 +31,9 @@ void MxAudioManager::Destroy(MxBool p_fromDestructor) Init(); this->m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaManager::Destroy(); + } } // FUNCTION: LEGO1 0x100b8e40 @@ -54,11 +49,13 @@ MxResult MxAudioManager::InitPresenters() g_count++; } - if (result) + if (result) { Destroy(); + } - if (success) + if (success) { this->m_criticalSection.Leave(); + } return result; } diff --git a/LEGO1/omni/src/audio/mxaudiopresenter.cpp b/LEGO1/omni/src/audio/mxaudiopresenter.cpp new file mode 100644 index 00000000..ac634362 --- /dev/null +++ b/LEGO1/omni/src/audio/mxaudiopresenter.cpp @@ -0,0 +1,5 @@ +#include "mxaudiopresenter.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxAudioPresenter, 0x54); diff --git a/LEGO1/mxloopingmidipresenter.cpp b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp similarity index 69% rename from LEGO1/mxloopingmidipresenter.cpp rename to LEGO1/omni/src/audio/mxloopingmidipresenter.cpp index 84b33229..c7f4ea1c 100644 --- a/LEGO1/mxloopingmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp @@ -21,18 +21,19 @@ void MxLoopingMIDIPresenter::StreamingTickle() } if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } } // FUNCTION: LEGO1 0x100c2ae0 void MxLoopingMIDIPresenter::DoneTickle() { - if (m_action->GetLoopCount()) + if (m_action->GetLoopCount()) { MxMIDIPresenter::DoneTickle(); - else + } + else { EndAction(); + } } // FUNCTION: LEGO1 0x100c2b00 @@ -40,9 +41,9 @@ 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()); + MusicManager()->InitializeMIDI(m_chunk->GetData(), !m_action->GetLoopCount() ? -1 : m_action->GetLoopCount()); } m_criticalSection.Leave(); diff --git a/LEGO1/mxmidipresenter.cpp b/LEGO1/omni/src/audio/mxmidipresenter.cpp similarity index 70% rename from LEGO1/mxmidipresenter.cpp rename to LEGO1/omni/src/audio/mxmidipresenter.cpp index b648eff7..b281ac64 100644 --- a/LEGO1/mxmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxmidipresenter.cpp @@ -1,7 +1,6 @@ #include "mxmidipresenter.h" #include "decomp.h" -#include "legoomni.h" #include "mxautolocker.h" #include "mxdssound.h" #include "mxmusicmanager.h" @@ -35,14 +34,16 @@ void MxMIDIPresenter::Destroy(MxBool p_fromDestructor) m_criticalSection.Enter(); - if (m_subscriber && m_chunk) - m_subscriber->FUN_100b8390(m_chunk); + if (m_subscriber && m_chunk) { + m_subscriber->DestroyChunk(m_chunk); + } Init(); m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMusicPresenter::Destroy(); + } } // FUNCTION: LEGO1 0x100c2890 @@ -51,21 +52,19 @@ void MxMIDIPresenter::ReadyTickle() MxStreamChunk* chunk = NextChunk(); if (chunk) { - m_subscriber->FUN_100b8390(chunk); + m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } // FUNCTION: LEGO1 0x100c28d0 void MxMIDIPresenter::StartingTickle() { - MxStreamChunk* chunk = FUN_100b5650(); + MxStreamChunk* chunk = CurrentChunk(); if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); } } @@ -73,18 +72,19 @@ void MxMIDIPresenter::StartingTickle() void MxMIDIPresenter::StreamingTickle() { if (m_chunk) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } - else + else { m_chunk = NextChunk(); + } } // FUNCTION: LEGO1 0x100c2940 void MxMIDIPresenter::DoneTickle() { - if (!MusicManager()->GetMIDIInitialized()) + if (!MusicManager()->GetMIDIInitialized()) { EndAction(); + } } // FUNCTION: LEGO1 0x100c2960 @@ -98,11 +98,12 @@ 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)) + if (MusicManager()->InitializeMIDI(m_chunk->GetData(), 1) != SUCCESS) { EndAction(); + } } m_criticalSection.Leave(); diff --git a/LEGO1/omni/src/audio/mxmusicmanager.cpp b/LEGO1/omni/src/audio/mxmusicmanager.cpp new file mode 100644 index 00000000..23562678 --- /dev/null +++ b/LEGO1/omni/src/audio/mxmusicmanager.cpp @@ -0,0 +1,293 @@ +#include "mxmusicmanager.h" + +#include "mxomni.h" +#include "mxticklemanager.h" + +#include + +DECOMP_SIZE_ASSERT(MxMusicManager, 0x58); + +// FUNCTION: LEGO1 0x100c05a0 +MxMusicManager::MxMusicManager() +{ + Init(); +} + +// FUNCTION: LEGO1 0x100c0630 +MxMusicManager::~MxMusicManager() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x100c0690 +void MxMusicManager::Init() +{ + m_multiplier = 100; + InitData(); +} + +// FUNCTION: LEGO1 0x100c06a0 +void MxMusicManager::InitData() +{ + m_midiStreamH = 0; + m_midiInitialized = FALSE; + m_bufferSize = 0; + m_bufferCurrentSize = 0; + m_bufferOffset = 0; + m_bufferCurrentOffset = 0; + m_loopCount = 0; + m_midiHdrP = NULL; +} + +// FUNCTION: LEGO1 0x100c06c0 +void MxMusicManager::Destroy(MxBool p_fromDestructor) +{ + if (m_thread) { + m_thread->Terminate(); + if (m_thread) { + delete m_thread; + } + } + else { + TickleManager()->UnregisterClient(this); + } + + m_criticalSection.Enter(); + DeinitializeMIDI(); + Init(); + m_criticalSection.Leave(); + + if (!p_fromDestructor) { + MxAudioManager::Destroy(); + } +} + +// FUNCTION: LEGO1 0x100c0720 +MxResult MxMusicManager::ResetStream() +{ + MxResult result = FAILURE; + + if (m_midiInitialized) { + if (m_bufferCurrentSize == 0) { + if (m_loopCount != -1) { + m_loopCount += -1; + + if (!m_loopCount) { + DeinitializeMIDI(); + goto done; + } + } + + ResetBuffer(); + } + + if (m_midiHdrP->dwFlags & MHDR_DONE || m_midiHdrP->dwFlags & MHDR_PREPARED) { + if (midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR)) != MMSYSERR_NOERROR) { + goto done; + } + + memset(m_midiHdrP, 0, sizeof(MIDIHDR)); + } + + m_bufferCurrentOffset += 4; + DWORD length = *((DWORD*) m_bufferCurrentOffset); + m_bufferCurrentOffset += sizeof(DWORD); + + m_midiHdrP->lpData = (LPSTR) m_bufferCurrentOffset; + m_midiHdrP->dwBufferLength = length; + m_midiHdrP->dwBytesRecorded = length; + + if (!midiOutPrepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR))) { + if (!midiStreamOut(m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR))) { + result = SUCCESS; + m_bufferCurrentOffset += length; + m_bufferCurrentSize--; + } + } + } + +done: + return result; +} + +// FUNCTION: LEGO1 0x100c07e0 +void MxMusicManager::ResetBuffer() +{ + m_bufferCurrentOffset = m_bufferOffset; + m_bufferCurrentSize = m_bufferSize; +} + +// FUNCTION: LEGO1 0x100c07f0 +void MxMusicManager::SetMIDIVolume() +{ + MxS32 result = (m_volume * m_multiplier) / 0x64; + HMIDISTRM streamHandle = m_midiStreamH; + + if (streamHandle) { + MxS32 volume = CalculateVolume(result); + midiOutSetVolume((HMIDIOUT) streamHandle, volume); + } +} + +// FUNCTION: LEGO1 0x100c0820 +void CALLBACK MxMusicManager::MidiCallbackProc(HDRVR p_hdrvr, UINT p_uMsg, DWORD p_dwUser, DWORD p_dw1, DWORD p_dw2) +{ + if (p_uMsg == MOM_DONE) { + ((MxMusicManager*) p_dwUser)->ResetStream(); + } +} + +// FUNCTION: LEGO1 0x100c0840 +MxResult MxMusicManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) +{ + MxResult status = FAILURE; + MxBool locked = FALSE; + + if (MxAudioManager::InitPresenters() == SUCCESS) { + if (p_createThread) { + m_criticalSection.Enter(); + locked = TRUE; + m_thread = new MxTickleThread(this, p_frequencyMS); + + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { + goto done; + } + } + else { + TickleManager()->RegisterClient(this, p_frequencyMS); + } + + status = SUCCESS; + } + +done: + if (status != SUCCESS) { + Destroy(); + } + + if (locked) { + m_criticalSection.Leave(); + } + + return status; +} + +// FUNCTION: LEGO1 0x100c0930 +void MxMusicManager::Destroy() +{ + Destroy(FALSE); +} + +// FUNCTION: LEGO1 0x100c0940 +void MxMusicManager::SetVolume(MxS32 p_volume) +{ + MxAudioManager::SetVolume(p_volume); + m_criticalSection.Enter(); + SetMIDIVolume(); + m_criticalSection.Leave(); +} + +// FUNCTION: LEGO1 0x100c0970 +void MxMusicManager::SetMultiplier(MxS32 p_multiplier) +{ + m_criticalSection.Enter(); + m_multiplier = p_multiplier; + SetMIDIVolume(); + m_criticalSection.Leave(); +} + +// FUNCTION: LEGO1 0x100c09a0 +MxS32 MxMusicManager::CalculateVolume(MxS32 p_volume) +{ + MxS32 result = (p_volume * 0xffff) / 100; + return (result << 0x10) | result; +} + +// FUNCTION: LEGO1 0x100c09c0 +MxResult MxMusicManager::InitializeMIDI(MxU8* p_data, MxS32 p_loopCount) +{ + MxResult result = FAILURE; + + m_criticalSection.Enter(); + + if (!m_midiInitialized) { + MxU32 total = midiOutGetNumDevs(); + MxU32 device = 0; + + for (; device < total; device++) { + MIDIOUTCAPSA caps; + midiOutGetDevCapsA(device, &caps, sizeof(MIDIOUTCAPSA)); + if (caps.wTechnology == MOD_FMSYNTH) { + break; + } + } + + if (device >= total) { + device = -1; + } + + if (midiStreamOpen(&m_midiStreamH, &device, 1, (DWORD) MidiCallbackProc, (DWORD) this, CALLBACK_FUNCTION) != + MMSYSERR_NOERROR) { + goto done; + } + + GetMIDIVolume(m_midiVolume); + + m_midiHdrP = new MIDIHDR(); + if (!m_midiHdrP) { + goto done; + } + + memset(m_midiHdrP, 0, sizeof(MIDIHDR)); + + MIDIPROPTIMEDIV timediv; + timediv.cbStruct = 8; + m_bufferOffset = p_data; + m_bufferOffset += 0x14; + timediv.dwTimeDiv = *((DWORD*) m_bufferOffset); + + if (midiStreamProperty(m_midiStreamH, (LPBYTE) &timediv, MIDIPROP_SET | MIDIPROP_TIMEDIV) != MMSYSERR_NOERROR) { + goto done; + } + + m_bufferOffset += 0x14; + m_bufferSize = *((MxU32*) m_bufferOffset); + m_bufferOffset += sizeof(MxU32); + m_loopCount = p_loopCount; + m_midiInitialized = TRUE; + + ResetBuffer(); + if (ResetStream() != SUCCESS) { + goto done; + } + + SetMIDIVolume(); + if (midiStreamRestart(m_midiStreamH) != MMSYSERR_NOERROR) { + goto done; + } + + result = SUCCESS; + } + +done: + m_criticalSection.Leave(); + return result; +} + +// FUNCTION: LEGO1 0x100c0b20 +void MxMusicManager::DeinitializeMIDI() +{ + m_criticalSection.Enter(); + + if (m_midiInitialized) { + m_midiInitialized = FALSE; + midiStreamStop(m_midiStreamH); + midiOutUnprepareHeader((HMIDIOUT) m_midiStreamH, m_midiHdrP, sizeof(MIDIHDR)); + midiOutSetVolume((HMIDIOUT) m_midiStreamH, m_midiVolume); + midiStreamClose(m_midiStreamH); + delete m_midiHdrP; + InitData(); + } + + m_criticalSection.Leave(); +} diff --git a/LEGO1/mxmusicpresenter.cpp b/LEGO1/omni/src/audio/mxmusicpresenter.cpp similarity index 90% rename from LEGO1/mxmusicpresenter.cpp rename to LEGO1/omni/src/audio/mxmusicpresenter.cpp index dc2f4b7f..437cd52d 100644 --- a/LEGO1/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/mxsoundmanager.cpp b/LEGO1/omni/src/audio/mxsoundmanager.cpp similarity index 83% rename from LEGO1/mxsoundmanager.cpp rename to LEGO1/omni/src/audio/mxsoundmanager.cpp index b06c5e37..55055107 100644 --- a/LEGO1/mxsoundmanager.cpp +++ b/LEGO1/omni/src/audio/mxsoundmanager.cpp @@ -59,46 +59,55 @@ MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) MxResult status = FAILURE; MxBool locked = FALSE; - if (MxAudioManager::InitPresenters() != SUCCESS) + if (MxAudioManager::InitPresenters() != SUCCESS) { goto done; + } m_criticalSection.Enter(); locked = TRUE; - if (DirectSoundCreate(NULL, &m_directSound, NULL) != DS_OK) + if (DirectSoundCreate(NULL, &m_directSound, NULL) != DS_OK) { goto done; + } - if (m_directSound->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DSSCL_PRIORITY) != DS_OK) + if (m_directSound->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DSSCL_PRIORITY) != DS_OK) { goto done; + } DSBUFFERDESC desc; memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); - if (MxOmni::IsSound3D()) + if (MxOmni::IsSound3D()) { desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D; - else + } + else { desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; + } if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) { - if (!MxOmni::IsSound3D()) + if (!MxOmni::IsSound3D()) { goto done; + } MxOmni::SetSound3D(FALSE); desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; - if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) + if (m_directSound->CreateSoundBuffer(&desc, &m_dsBuffer, NULL) != DS_OK) { goto done; + } } WAVEFORMATEX format; format.wFormatTag = WAVE_FORMAT_PCM; - if (MxOmni::IsSound3D()) + if (MxOmni::IsSound3D()) { format.nChannels = 2; - else + } + else { format.nChannels = 1; + } format.nSamplesPerSec = 11025; // KHz format.wBitsPerSample = 16; @@ -111,20 +120,24 @@ MxResult MxSoundManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) if (p_createThread) { m_thread = new MxTickleThread(this, p_frequencyMS); - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return status; } @@ -144,8 +157,9 @@ void MxSoundManager::SetVolume(MxS32 p_volume) MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { ((MxAudioPresenter*) presenter)->SetVolume(((MxAudioPresenter*) presenter)->GetVolume()); + } m_criticalSection.Leave(); } @@ -160,8 +174,9 @@ MxPresenter* MxSoundManager::FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_obje while (cursor.Next(presenter)) { if (presenter->GetAction()->GetAtomId().GetInternal() == p_atomId.GetInternal() && - presenter->GetAction()->GetObjectId() == p_objectId) + presenter->GetAction()->GetObjectId() == p_objectId) { return presenter; + } } return NULL; @@ -170,8 +185,9 @@ MxPresenter* MxSoundManager::FUN_100aebd0(const MxAtomId& p_atomId, MxU32 p_obje // FUNCTION: LEGO1 0x100aecf0 MxS32 MxSoundManager::FUN_100aecf0(MxU32 p_undefined) { - if (!p_undefined) + if (!p_undefined) { return -10000; + } return g_mxcoreCount[p_undefined]; } @@ -183,9 +199,11 @@ void MxSoundManager::Pause() MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - while (cursor.Next(presenter)) - if (presenter->IsA("MxWavePresenter")) + while (cursor.Next(presenter)) { + if (presenter->IsA("MxWavePresenter")) { ((MxWavePresenter*) presenter)->Pause(); + } + } } // FUNCTION: LEGO1 0x100aee10 @@ -196,7 +214,9 @@ void MxSoundManager::Resume() MxPresenter* presenter; MxPresenterListCursor cursor(m_presenters); - while (cursor.Next(presenter)) - if (presenter->IsA("MxWavePresenter")) + while (cursor.Next(presenter)) { + if (presenter->IsA("MxWavePresenter")) { ((MxWavePresenter*) presenter)->Resume(); + } + } } diff --git a/LEGO1/mxsoundpresenter.cpp b/LEGO1/omni/src/audio/mxsoundpresenter.cpp similarity index 62% rename from LEGO1/mxsoundpresenter.cpp rename to LEGO1/omni/src/audio/mxsoundpresenter.cpp index 1065fc99..60459d2c 100644 --- a/LEGO1/mxsoundpresenter.cpp +++ b/LEGO1/omni/src/audio/mxsoundpresenter.cpp @@ -5,30 +5,20 @@ 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); + if (MSoundManager()) { + MSoundManager()->UnregisterPresenter(*this); + } this->m_criticalSection.Enter(); MxMediaPresenter::Init(); this->m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b1aa0 @@ -38,7 +28,7 @@ MxResult MxSoundPresenter::AddToManager() if (MSoundManager()) { ret = SUCCESS; - MSoundManager()->AddPresenter(*this); + MSoundManager()->RegisterPresenter(*this); } return ret; diff --git a/LEGO1/mxwavepresenter.cpp b/LEGO1/omni/src/audio/mxwavepresenter.cpp similarity index 73% rename from LEGO1/mxwavepresenter.cpp rename to LEGO1/omni/src/audio/mxwavepresenter.cpp index 80096f73..cb9f4d56 100644 --- a/LEGO1/mxwavepresenter.cpp +++ b/LEGO1/omni/src/audio/mxwavepresenter.cpp @@ -2,32 +2,14 @@ #include "decomp.h" #include "define.h" -#include "legoomni.h" #include "mxautolocker.h" #include "mxdssound.h" #include "mxomni.h" #include "mxsoundmanager.h" +#include "mxutil.h" 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; -} +DECOMP_SIZE_ASSERT(MxWavePresenter::WaveFormat, 0x18); // FUNCTION: LEGO1 0x100b1ad0 void MxWavePresenter::Init() @@ -58,13 +40,15 @@ void MxWavePresenter::Destroy(MxBool p_fromDestructor) m_dsBuffer->Release(); } - if (m_waveFormat) + if (m_waveFormat) { delete[] ((MxU8*) m_waveFormat); + } Init(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxSoundPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b1b60 @@ -73,8 +57,9 @@ MxS8 MxWavePresenter::GetPlayedChunks() DWORD dwCurrentPlayCursor, dwCurrentWriteCursor; MxS8 playedChunks = -1; - if (m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor) == DS_OK) + if (m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor) == DS_OK) { playedChunks = dwCurrentPlayCursor / m_chunkLength; + } return playedChunks; } @@ -104,7 +89,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 +102,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); } @@ -134,17 +119,16 @@ void MxWavePresenter::ReadyTickle() if (chunk) { m_waveFormat = (WaveFormat*) new MxU8[chunk->GetLength()]; memcpy(m_waveFormat, chunk->GetData(), chunk->GetLength()); - m_subscriber->FUN_100b8390(chunk); + m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } // FUNCTION: LEGO1 0x100b1d50 void MxWavePresenter::StartingTickle() { - MxStreamChunk* chunk = NextChunk(); + MxStreamChunk* chunk = CurrentChunk(); if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { MxU32 length = chunk->GetLength(); @@ -153,33 +137,39 @@ void MxWavePresenter::StartingTickle() m_chunkLength = length; memset(&waveFormatEx, 0, sizeof(waveFormatEx)); - waveFormatEx.wFormatTag = m_waveFormat->m_waveFormatEx.wFormatTag; - waveFormatEx.nChannels = m_waveFormat->m_waveFormatEx.nChannels; - waveFormatEx.nSamplesPerSec = m_waveFormat->m_waveFormatEx.nSamplesPerSec; - waveFormatEx.nAvgBytesPerSec = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec; - waveFormatEx.nBlockAlign = m_waveFormat->m_waveFormatEx.nBlockAlign; - waveFormatEx.wBitsPerSample = m_waveFormat->m_waveFormatEx.wBitsPerSample; + waveFormatEx.wFormatTag = m_waveFormat->m_pcmWaveFormat.wf.wFormatTag; + waveFormatEx.nChannels = m_waveFormat->m_pcmWaveFormat.wf.nChannels; + waveFormatEx.nSamplesPerSec = m_waveFormat->m_pcmWaveFormat.wf.nSamplesPerSec; + waveFormatEx.nAvgBytesPerSec = m_waveFormat->m_pcmWaveFormat.wf.nAvgBytesPerSec; + waveFormatEx.nBlockAlign = m_waveFormat->m_pcmWaveFormat.wf.nBlockAlign; + waveFormatEx.wBitsPerSample = m_waveFormat->m_pcmWaveFormat.wBitsPerSample; - if (waveFormatEx.wBitsPerSample == 8) + if (waveFormatEx.wBitsPerSample == 8) { m_silenceData = 0x7F; + } - if (waveFormatEx.wBitsPerSample == 16) + if (waveFormatEx.wBitsPerSample == 16) { m_silenceData = 0; + } DSBUFFERDESC desc; memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); - if (m_unk0x66) + if (m_unk0x66) { desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME; - else + } + else { desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME; + } - if (m_action->GetFlags() & MxDSAction::Flag_Looping) - desc.dwBufferBytes = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec * + if (m_action->GetFlags() & MxDSAction::c_looping) { + desc.dwBufferBytes = m_waveFormat->m_pcmWaveFormat.wf.nAvgBytesPerSec * (m_action->GetDuration() / m_action->GetLoopCount()) / 1000; - else + } + else { desc.dwBufferBytes = 2 * length; + } desc.lpwfxFormat = &waveFormatEx; @@ -188,8 +178,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 +187,11 @@ void MxWavePresenter::StartingTickle() void MxWavePresenter::StreamingTickle() { if (!m_currentChunk) { - if (!(m_action->GetFlags() & MxDSAction::Flag_Looping)) { - MxStreamChunk* chunk = FUN_100b5650(); + if (!(m_action->GetFlags() & MxDSAction::c_looping)) { + MxStreamChunk* chunk = CurrentChunk(); - if (chunk && chunk->GetFlags() & MxDSChunk::Flag_Bit2 && !(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 +201,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,20 +217,23 @@ 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 || - m_writtenChunks != playedChunks || m_lockSize + (m_chunkLength * playedChunks) <= dwCurrentPlayCursor) + if (m_action->GetFlags() & MxDSAction::c_bit7 || m_action->GetFlags() & MxDSAction::c_looping || + m_writtenChunks != playedChunks || m_lockSize + (m_chunkLength * playedChunks) <= dwCurrentPlayCursor) { MxMediaPresenter::DoneTickle(); + } } - else + else { MxMediaPresenter::DoneTickle(); + } } // FUNCTION: LEGO1 0x100b2130 -void MxWavePresenter::AppendChunk(MxStreamChunk* p_chunk) +void MxWavePresenter::LoopChunk(MxStreamChunk* p_chunk) { WriteToSoundBuffer(p_chunk->GetData(), p_chunk->GetLength()); - if (IsEnabled()) - m_subscriber->FUN_100b8390(p_chunk); + if (IsEnabled()) { + m_subscriber->DestroyChunk(p_chunk); + } } // FUNCTION: LEGO1 0x100b2160 @@ -251,28 +243,31 @@ 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->FUN_100b8390(m_currentChunk); + m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; } if (!m_started) { m_dsBuffer->SetCurrentPosition(0); - if (m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK) + if (m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING) == DS_OK) { m_started = TRUE; + } } break; - case TickleState_Repeating: - if (m_started) + case e_repeating: + if (m_started) { break; + } m_dsBuffer->SetCurrentPosition(0); - if (m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1) == DS_OK) + if (m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1) == DS_OK) { m_started = TRUE; + } } } @@ -286,8 +281,9 @@ void MxWavePresenter::EndAction() MxAutoLocker lock(&m_criticalSection); MxMediaPresenter::EndAction(); - if (m_dsBuffer) + if (m_dsBuffer) { m_dsBuffer->Stop(); + } } } @@ -316,8 +312,9 @@ void MxWavePresenter::Enable(MxBool p_enable) m_writtenChunks = 0; m_started = FALSE; } - else if (m_dsBuffer) + else if (m_dsBuffer) { m_dsBuffer->Stop(); + } } } @@ -337,8 +334,9 @@ void MxWavePresenter::ParseExtra() char soundValue[512]; if (KeyValueStringParse(soundValue, g_strSOUND, extraCopy)) { - if (!strcmpi(soundValue, "FALSE")) + if (!strcmpi(soundValue, "FALSE")) { Enable(FALSE); + } } } } @@ -347,8 +345,9 @@ void MxWavePresenter::ParseExtra() void MxWavePresenter::Pause() { if (!m_paused && m_started) { - if (m_dsBuffer) + if (m_dsBuffer) { m_dsBuffer->Stop(); + } m_paused = TRUE; } } @@ -359,13 +358,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/mxatomid.cpp b/LEGO1/omni/src/common/mxatomid.cpp similarity index 77% rename from LEGO1/mxatomid.cpp rename to LEGO1/omni/src/common/mxatomid.cpp index 722f5432..c5b7412c 100644 --- a/LEGO1/mxatomid.cpp +++ b/LEGO1/omni/src/common/mxatomid.cpp @@ -5,11 +5,13 @@ // FUNCTION: LEGO1 0x100acf90 MxAtomId::MxAtomId(const char* p_str, LookupMode p_mode) { - if (!MxOmni::GetInstance()) + if (!MxOmni::GetInstance()) { return; + } - if (!AtomIdCounterSet()) + if (!AtomIdCounterSet()) { return; + } MxAtomIdCounter* counter = GetCounter(p_str, p_mode); m_internal = counter->GetKey()->GetData(); @@ -25,18 +27,27 @@ MxAtomId::~MxAtomId() // FUNCTION: LEGO1 0x100acfe0 void MxAtomId::Destroy() { - if (!m_internal) + if (!m_internal) { return; + } - if (!MxOmni::GetInstance()) + if (!MxOmni::GetInstance()) { return; + } - if (!AtomIdCounterSet()) + if (!AtomIdCounterSet()) { return; + } - // The dtor is called on the counter object immediately, - // so this syntax should be correct. +#ifdef COMPAT_MODE + MxAtomIdCounterSet::iterator it; + { + MxAtomIdCounter id_counter(m_internal); + it = AtomIdCounterSet()->find(&id_counter); + } +#else MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find(&MxAtomIdCounter(m_internal)); +#endif MxAtomIdCounter* counter = (MxAtomIdCounter*) (*it); counter->Dec(); @@ -45,11 +56,12 @@ void MxAtomId::Destroy() // FUNCTION: LEGO1 0x100ad1c0 MxAtomId& MxAtomId::operator=(const MxAtomId& p_atomId) { - if (m_internal) + if (m_internal) { Destroy(); + } if (p_atomId.m_internal && MxOmni::GetInstance() && AtomIdCounterSet()) { - MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, LookupMode_Exact); + MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, e_exact); counter->Inc(); } @@ -65,11 +77,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/mxatomidcounter.cpp b/LEGO1/omni/src/common/mxatomidcounter.cpp similarity index 93% rename from LEGO1/mxatomidcounter.cpp rename to LEGO1/omni/src/common/mxatomidcounter.cpp index f3be8764..cfec47b1 100644 --- a/LEGO1/mxatomidcounter.cpp +++ b/LEGO1/omni/src/common/mxatomidcounter.cpp @@ -14,6 +14,7 @@ void MxAtomIdCounter::Inc() // FUNCTION: LEGO1 0x100ad800 void MxAtomIdCounter::Dec() { - if (m_value) + if (m_value) { m_value--; + } } diff --git a/LEGO1/mxcompositepresenter.cpp b/LEGO1/omni/src/common/mxcompositepresenter.cpp similarity index 83% rename from LEGO1/mxcompositepresenter.cpp rename to LEGO1/omni/src/common/mxcompositepresenter.cpp index 7685fe57..5996f634 100644 --- a/LEGO1/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() { @@ -58,16 +50,18 @@ MxResult MxCompositePresenter::StartAction(MxStreamController* p_controller, MxD if (presenter && presenter->AddToManager() == SUCCESS) { presenter->SetCompositePresenter(this); - if (presenter->StartAction(p_controller, action) == SUCCESS) + if (presenter->StartAction(p_controller, action) == SUCCESS) { success = TRUE; + } } if (success) { action->SetOrigin(this); m_list.push_back(presenter); } - else if (presenter) + else if (presenter) { delete presenter; + } } result = SUCCESS; @@ -81,8 +75,9 @@ void MxCompositePresenter::EndAction() { MxAutoLocker lock(&m_criticalSection); - if (!m_action) + if (!m_action) { return; + } ((MxDSMultiAction*) m_action)->GetActionList()->DeleteAll(FALSE); @@ -97,10 +92,17 @@ void MxCompositePresenter::EndAction() MxPresenter::EndAction(); if (action && action->GetOrigin()) { +#ifdef COMPAT_MODE + { + MxEndActionNotificationParam param(c_notificationEndAction, this, action, FALSE); + NotificationManager()->Send(action->GetOrigin(), ¶m); + } +#else NotificationManager()->Send( action->GetOrigin(), &MxEndActionNotificationParam(c_notificationEndAction, this, action, FALSE) ); +#endif } } @@ -113,7 +115,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); } @@ -140,15 +142,18 @@ void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param) MxDSActionList* actions = ((MxDSMultiAction*) m_action)->GetActionList(); MxDSActionListCursor cursor(actions); - if (cursor.Find(action)) + if (cursor.Find(action)) { cursor.Detach(); + } } - if (presenter) + if (presenter) { delete presenter; + } - if (action) + if (action) { delete action; + } if (m_list.empty()) { EndAction(); @@ -156,8 +161,9 @@ void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param) else { if (m_action->IsA("MxDSSerialAction") && it != m_list.end()) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) { + presenter->SetTickleState(e_ready); + } } } } @@ -172,14 +178,16 @@ 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); - if (cursor.Find(presenter->GetAction())) + if (cursor.Find(presenter->GetAction())) { cursor.Detach(); + } if (m_list.empty()) { EndAction(); @@ -187,8 +195,9 @@ 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); + } } } @@ -206,13 +215,15 @@ void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter) for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { if (*it == p_presenter) { if (++it == m_list.end()) { - if (m_compositePresenter) + if (m_compositePresenter) { m_compositePresenter->VTable0x60(this); + } } else if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) { + presenter->SetTickleState(e_ready); + } } return; } @@ -222,15 +233,15 @@ 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; + } } } @@ -250,8 +261,9 @@ MxBool MxCompositePresenter::HasTickleStatePassed(TickleState p_tickleState) { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { MxPresenter* presenter = *it; - if (!presenter->HasTickleStatePassed(p_tickleState)) + if (!presenter->HasTickleStatePassed(p_tickleState)) { return FALSE; + } } return TRUE; diff --git a/LEGO1/mxcore.cpp b/LEGO1/omni/src/common/mxcore.cpp similarity index 70% rename from LEGO1/mxcore.cpp rename to LEGO1/omni/src/common/mxcore.cpp index 18c37597..1266a1cb 100644 --- a/LEGO1/mxcore.cpp +++ b/LEGO1/omni/src/common/mxcore.cpp @@ -2,16 +2,10 @@ #include "define.h" -// FUNCTION: LEGO1 0x10001f70 -MxResult MxCore::Tickle() -{ - return SUCCESS; -} - // FUNCTION: LEGO1 0x100ae1a0 MxCore::MxCore() { - m_id = g_mxcoreCount[0]; + m_id = (MxU32) g_mxcoreCount[0]; g_mxcoreCount[0]++; } diff --git a/LEGO1/mxmediamanager.cpp b/LEGO1/omni/src/common/mxmediamanager.cpp similarity index 85% rename from LEGO1/mxmediamanager.cpp rename to LEGO1/omni/src/common/mxmediamanager.cpp index e9b4fe6d..6a9d99c5 100644 --- a/LEGO1/mxmediamanager.cpp +++ b/LEGO1/omni/src/common/mxmediamanager.cpp @@ -50,8 +50,9 @@ void MxMediaManager::Destroy() { MxAutoLocker lock(&this->m_criticalSection); - if (this->m_presenters) + if (this->m_presenters) { delete this->m_presenters; + } Init(); } @@ -63,19 +64,21 @@ MxResult MxMediaManager::Tickle() MxPresenter* presenter; MxPresenterListCursor cursor(this->m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->Tickle(); + } cursor.Reset(); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->PutData(); + } return SUCCESS; } // FUNCTION: LEGO1 0x100b88c0 -void MxMediaManager::AddPresenter(MxPresenter& p_presenter) +void MxMediaManager::RegisterPresenter(MxPresenter& p_presenter) { MxAutoLocker lock(&this->m_criticalSection); @@ -83,13 +86,14 @@ 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); - if (cursor.Find(&p_presenter)) + if (cursor.Find(&p_presenter)) { cursor.Detach(); + } } // FUNCTION: LEGO1 0x100b8ac0 @@ -99,6 +103,7 @@ void MxMediaManager::StopPresenters() MxPresenter* presenter; MxPresenterListCursor cursor(this->m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->EndAction(); + } } diff --git a/LEGO1/mxmediapresenter.cpp b/LEGO1/omni/src/common/mxmediapresenter.cpp similarity index 53% rename from LEGO1/mxmediapresenter.cpp rename to LEGO1/omni/src/common/mxmediapresenter.cpp index b3eb2274..48450b58 100644 --- a/LEGO1/mxmediapresenter.cpp +++ b/LEGO1/omni/src/common/mxmediapresenter.cpp @@ -11,24 +11,12 @@ 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() { this->m_subscriber = NULL; - this->m_chunks = NULL; - this->m_cursor = NULL; + this->m_loopingChunks = NULL; + this->m_loopingChunkCursor = NULL; this->m_currentChunk = NULL; } @@ -38,71 +26,74 @@ void MxMediaPresenter::Destroy(MxBool p_fromDestructor) { MxAutoLocker lock(&m_criticalSection); - if (m_currentChunk && m_subscriber) - m_subscriber->FUN_100b8390(m_currentChunk); + if (m_currentChunk && m_subscriber) { + m_subscriber->DestroyChunk(m_currentChunk); + } - if (m_subscriber) + if (m_subscriber) { delete m_subscriber; + } - if (m_cursor) - delete m_cursor; + if (m_loopingChunkCursor) { + delete m_loopingChunkCursor; + } - if (m_chunks) { - MxStreamChunkListCursor cursor(m_chunks); + if (m_loopingChunks) { + MxStreamChunkListCursor cursor(m_loopingChunks); MxStreamChunk* chunk; - while (cursor.Next(chunk)) + while (cursor.Next(chunk)) { chunk->Release(); + } - delete m_chunks; + delete m_loopingChunks; } Init(); } - if (!p_fromDestructor) + if (!p_fromDestructor) { MxPresenter::Destroy(); + } } // FUNCTION: LEGO1 0x100b5650 -MxStreamChunk* MxMediaPresenter::FUN_100b5650() +MxStreamChunk* MxMediaPresenter::CurrentChunk() { - MxStreamChunk* result = NULL; + MxStreamChunk* chunk = NULL; if (m_subscriber) { - result = m_subscriber->FUN_100b8360(); + chunk = m_subscriber->CurrentChunk(); - if (result && result->GetFlags() & MxDSChunk::Flag_Bit3) { - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); - m_subscriber->FUN_100b8250(); - m_subscriber->FUN_100b8390(result); - result = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + 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; + ProgressTickleState(e_done); } } - return result; + return chunk; } // FUNCTION: LEGO1 0x100b56b0 MxStreamChunk* MxMediaPresenter::NextChunk() { - MxStreamChunk* result = NULL; + MxStreamChunk* chunk = NULL; if (m_subscriber) { - result = m_subscriber->FUN_100b8250(); + chunk = m_subscriber->NextChunk(); - if (result && result->GetFlags() & MxDSChunk::Flag_Bit3) { - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); - m_subscriber->FUN_100b8390(result); - result = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + if (chunk && chunk->GetFlags() & MxDSChunk::c_bit3) { + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_bit7); + m_subscriber->DestroyChunk(chunk); + chunk = NULL; + ProgressTickleState(e_done); } } - return result; + return chunk; } // FUNCTION: LEGO1 0x100b5700 @@ -112,20 +103,22 @@ 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) { - m_chunks = new MxStreamChunkList; - m_cursor = new MxStreamChunkListCursor(m_chunks); + if (m_action->GetFlags() & MxDSAction::c_looping) { + m_loopingChunks = new MxStreamChunkList; + m_loopingChunkCursor = new MxStreamChunkListCursor(m_loopingChunks); - if (!m_chunks && !m_cursor) + if (!m_loopingChunks && !m_loopingChunkCursor) { goto done; + } } if (p_controller) { m_subscriber = new MxDSSubscriber; if (!m_subscriber || - m_subscriber->Create(p_controller, p_action->GetObjectId(), p_action->GetUnknown24()) != SUCCESS) + m_subscriber->Create(p_controller, p_action->GetObjectId(), p_action->GetUnknown24()) != SUCCESS) { goto done; + } } result = SUCCESS; @@ -140,15 +133,15 @@ void MxMediaPresenter::EndAction() { MxAutoLocker lock(&m_criticalSection); - if (!m_action) + if (!m_action) { return; + } 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; @@ -160,10 +153,17 @@ void MxMediaPresenter::EndAction() } if (action && action->GetOrigin()) { +#ifdef COMPAT_MODE + { + MxEndActionNotificationParam param(c_notificationEndAction, this, action, FALSE); + NotificationManager()->Send(action->GetOrigin(), ¶m); + } +#else NotificationManager()->Send( action->GetOrigin(), &MxEndActionNotificationParam(c_notificationEndAction, this, action, FALSE) ); +#endif } } } @@ -173,7 +173,7 @@ MxResult MxMediaPresenter::Tickle() { MxAutoLocker lock(&m_criticalSection); - FUN_100b5650(); + CurrentChunk(); return MxPresenter::Tickle(); } @@ -185,17 +185,16 @@ void MxMediaPresenter::StreamingTickle() m_currentChunk = NextChunk(); if (m_currentChunk) { - if (m_currentChunk->GetFlags() & MxDSChunk::Flag_Bit2) { - m_subscriber->FUN_100b8390(m_currentChunk); + 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) { - AppendChunk(m_currentChunk); + else if (m_action->GetFlags() & MxDSAction::c_looping) { + LoopChunk(m_currentChunk); if (!IsEnabled()) { - m_subscriber->FUN_100b8390(m_currentChunk); + m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; } } @@ -207,21 +206,21 @@ void MxMediaPresenter::StreamingTickle() void MxMediaPresenter::RepeatingTickle() { if (IsEnabled() && !m_currentChunk) { - if (m_cursor) - if (!m_cursor->Next(m_currentChunk)) - m_cursor->Next(m_currentChunk); + if (m_loopingChunkCursor) { + if (!m_loopingChunkCursor->Next(m_currentChunk)) { + m_loopingChunkCursor->Next(m_currentChunk); + } + } if (m_currentChunk) { MxLong time = m_currentChunk->GetTime(); if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; + 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); } } } @@ -230,13 +229,12 @@ void MxMediaPresenter::RepeatingTickle() // FUNCTION: LEGO1 0x100b5ef0 void MxMediaPresenter::DoneTickle() { - m_previousTickleStates |= 1 << m_currentTickleState; - m_currentTickleState = TickleState_Idle; + ProgressTickleState(e_idle); EndAction(); } // FUNCTION: LEGO1 0x100b5f10 -void MxMediaPresenter::AppendChunk(MxStreamChunk* p_chunk) +void MxMediaPresenter::LoopChunk(MxStreamChunk* p_chunk) { MxStreamChunk* chunk = new MxStreamChunk; @@ -246,7 +244,7 @@ void MxMediaPresenter::AppendChunk(MxStreamChunk* p_chunk) chunk->SetTime(p_chunk->GetTime()); memcpy(chunk->GetData(), p_chunk->GetData(), chunk->GetLength()); - m_chunks->Append(chunk); + m_loopingChunks->Append(chunk); } // FUNCTION: LEGO1 0x100b6030 @@ -258,13 +256,14 @@ 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_cursor) - m_cursor->Reset(); + if (m_loopingChunkCursor) { + m_loopingChunkCursor->Reset(); + } m_currentChunk = NULL; - SetTickleState(TickleState_Done); + SetTickleState(e_done); } } } diff --git a/LEGO1/mxobjectfactory.cpp b/LEGO1/omni/src/common/mxobjectfactory.cpp similarity index 92% rename from LEGO1/mxobjectfactory.cpp rename to LEGO1/omni/src/common/mxobjectfactory.cpp index a4e5efd1..93f2e0a0 100644 --- a/LEGO1/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/mxpresenter.cpp b/LEGO1/omni/src/common/mxpresenter.cpp similarity index 55% rename from LEGO1/mxpresenter.cpp rename to LEGO1/omni/src/common/mxpresenter.cpp index 31279513..794d1227 100644 --- a/LEGO1/mxpresenter.cpp +++ b/LEGO1/omni/src/common/mxpresenter.cpp @@ -2,115 +2,26 @@ #include "decomp.h" #include "define.h" -#include "legoomni.h" #include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxcompositepresenter.h" #include "mxdsanim.h" #include "mxdssound.h" +#include "mxentity.h" #include "mxnotificationmanager.h" +#include "mxobjectfactory.h" #include "mxparam.h" #include "mxstreamer.h" +#include "mxutil.h" #include 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; @@ -125,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; } @@ -139,21 +49,29 @@ MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action) // FUNCTION: LEGO1 0x100b4e40 void MxPresenter::EndAction() { - if (this->m_action == NULL) + if (this->m_action == NULL) { return; + } MxAutoLocker lock(&this->m_criticalSection); if (!this->m_compositePresenter) { +#ifdef COMPAT_MODE + { + MxEndActionNotificationParam param(c_notificationEndAction, NULL, this->m_action, TRUE); + MxOmni::GetInstance()->NotifyCurrentEntity(¶m); + } +#else MxOmni::GetInstance()->NotifyCurrentEntity( &MxEndActionNotificationParam(c_notificationEndAction, NULL, this->m_action, TRUE) ); +#endif } 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 @@ -177,12 +95,13 @@ void MxPresenter::ParseExtra() token = strtok(NULL, g_parseExtraTokens); MxS32 val = token ? atoi(token) : 0; - MxEntity* result = MxOmni::GetInstance()->FindWorld(buf, val, this); + MxEntity* result = MxOmni::GetInstance()->AddToWorld(buf, val, this); - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_World); + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_world); - if (result) + if (result) { SendToCompositePresenter(MxOmni::GetInstance()); + } } } } @@ -193,7 +112,14 @@ void MxPresenter::SendToCompositePresenter(MxOmni* p_omni) if (m_compositePresenter) { MxAutoLocker lock(&m_criticalSection); - NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(MXPRESENTER_NOTIFICATION, this)); +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationPresenter, this); + NotificationManager()->Send(m_compositePresenter, ¶m); + } +#else + NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(c_notificationPresenter, this)); +#endif m_action->SetOrigin(p_omni ? p_omni : MxOmni::GetInstance()); m_compositePresenter = NULL; @@ -206,32 +132,37 @@ 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; @@ -246,10 +177,12 @@ void MxPresenter::Enable(MxBool p_enable) if (this->m_action && this->IsEnabled() != p_enable) { MxU32 flags = this->m_action->GetFlags(); - if (p_enable) - this->m_action->SetFlags(flags | MxDSAction::Flag_Enabled); - else - this->m_action->SetFlags(flags & ~MxDSAction::Flag_Enabled); + if (p_enable) { + this->m_action->SetFlags(flags | MxDSAction::c_enabled); + } + else { + this->m_action->SetFlags(flags & ~MxDSAction::c_enabled); + } } } @@ -261,7 +194,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'): @@ -273,7 +206,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'): @@ -285,17 +218,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; } @@ -304,8 +237,29 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) return name; } +// FUNCTION: LEGO1 0x100b5410 +MxEntity* MxPresenter::CreateEntity(const char* p_name) +{ + char buffer[512]; + char buffer2[512]; + strcpy(buffer, p_name); + + MxU16 extraLen = m_action->GetExtraLength(); + + buffer[0] = extraLen; + buffer[1] = extraLen >> 8; + if (extraLen) { + extraLen &= MAXWORD; + memcpy(buffer2 + 2, m_action->GetExtraData(), extraLen); + buffer2[extraLen + 2] = 0; + KeyValueStringParse(buffer, g_strOBJECT, buffer2 + 2); + } + + return (MxEntity*) ObjectFactory()->Create(buffer); +} + // 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/mxstring.cpp b/LEGO1/omni/src/common/mxstring.cpp similarity index 100% rename from LEGO1/mxstring.cpp rename to LEGO1/omni/src/common/mxstring.cpp diff --git a/LEGO1/mxticklemanager.cpp b/LEGO1/omni/src/common/mxticklemanager.cpp similarity index 94% rename from LEGO1/mxticklemanager.cpp rename to LEGO1/omni/src/common/mxticklemanager.cpp index 29f8428c..e8b0d410 100644 --- a/LEGO1/mxticklemanager.cpp +++ b/LEGO1/omni/src/common/mxticklemanager.cpp @@ -5,7 +5,7 @@ #include "mxtimer.h" #include "mxtypes.h" -#define TICKLE_MANAGER_FLAG_DESTROY 0x1 +#define TICKLE_MANAGER_FLAG_DESTROY 0x01 DECOMP_SIZE_ASSERT(MxTickleClient, 0x10); DECOMP_SIZE_ASSERT(MxTickleManager, 0x14); @@ -45,8 +45,9 @@ MxResult MxTickleManager::Tickle() else { it++; - if (client->GetLastUpdateTime() > time) + if (client->GetLastUpdateTime() > time) { client->SetLastUpdateTime(-client->GetTickleInterval()); + } if ((client->GetTickleInterval() + client->GetLastUpdateTime()) < time) { client->GetClient()->Tickle(); @@ -64,8 +65,9 @@ void MxTickleManager::RegisterClient(MxCore* p_client, MxTime p_interval) MxTime interval = GetClientTickleInterval(p_client); if (interval == TICKLE_MANAGER_NOT_FOUND) { MxTickleClient* client = new MxTickleClient(p_client, p_interval); - if (client != NULL) + if (client != NULL) { m_clients.push_back(client); + } } } @@ -102,8 +104,9 @@ MxTime MxTickleManager::GetClientTickleInterval(MxCore* p_client) MxTickleClientPtrList::iterator it = m_clients.begin(); while (it != m_clients.end()) { MxTickleClient* client = *it; - if ((client->GetClient() == p_client) && ((client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) == 0)) + if ((client->GetClient() == p_client) && ((client->GetFlags() & TICKLE_MANAGER_FLAG_DESTROY) == 0)) { return client->GetTickleInterval(); + } it++; } diff --git a/LEGO1/mxtimer.cpp b/LEGO1/omni/src/common/mxtimer.cpp similarity index 100% rename from LEGO1/mxtimer.cpp rename to LEGO1/omni/src/common/mxtimer.cpp diff --git a/LEGO1/omni/src/common/mxutil.cpp b/LEGO1/omni/src/common/mxutil.cpp new file mode 100644 index 00000000..5ffab77c --- /dev/null +++ b/LEGO1/omni/src/common/mxutil.cpp @@ -0,0 +1,185 @@ +#include "mxutil.h" + +#include "mxcompositepresenter.h" +#include "mxdsaction.h" +#include "mxdsactionlist.h" +#include "mxdsfile.h" +#include "mxdsmultiaction.h" +#include "mxdsobject.h" +#include "mxpresenterlist.h" +#include "mxrect32.h" + +// GLOBAL: LEGO1 0x101020e8 +void (*g_omniUserMessage)(const char*, int); + +// FUNCTION: LEGO1 0x100b6e10 +MxBool GetRectIntersection( + MxS32 p_rect1Width, + MxS32 p_rect1Height, + MxS32 p_rect2Width, + MxS32 p_rect2Height, + MxS32* p_rect1Left, + MxS32* p_rect1Top, + MxS32* p_rect2Left, + MxS32* p_rect2Top, + MxS32* p_width, + MxS32* p_height +) +{ + MxPoint32 rect1Origin(*p_rect1Left, *p_rect1Top); + MxRect32 rect1(MxPoint32(0, 0), MxSize32(p_rect1Width, p_rect1Height)); + + MxPoint32 rect2Origin(*p_rect2Left, *p_rect2Top); + MxRect32 rect2(MxPoint32(0, 0), MxSize32(p_rect2Width, p_rect2Height)); + + MxRect32 rect(0, 0, *p_width, *p_height); + rect.AddPoint(rect1Origin); + + if (!rect.IntersectsWith(rect1)) { + return FALSE; + } + + rect.Intersect(rect1); + rect.SubtractPoint(rect1Origin); + rect.AddPoint(rect2Origin); + + if (!rect.IntersectsWith(rect2)) { + return FALSE; + } + + rect.Intersect(rect2); + rect.SubtractPoint(rect2Origin); + + *p_rect1Left += rect.GetLeft(); + *p_rect1Top += rect.GetTop(); + *p_rect2Left += rect.GetLeft(); + *p_rect2Top += rect.GetTop(); + *p_width = rect.GetWidth(); + *p_height = rect.GetHeight(); + return TRUE; +} + +// FUNCTION: LEGO1 0x100b6ff0 +void MakeSourceName(char* p_output, const char* p_input) +{ + const char* cln = strchr(p_input, ':'); + if (cln) { + p_input = cln + 1; + } + + strcpy(p_output, p_input); + + strlwr(p_output); + + char* extLoc = strstr(p_output, ".si"); + if (extLoc) { + *extLoc = 0; + } +} + +// FUNCTION: LEGO1 0x100b7050 +MxBool KeyValueStringParse(char* p_outputValue, const char* p_key, const char* p_source) +{ + MxBool didMatch = FALSE; + + MxS16 len = strlen(p_source); + char* temp = new char[len + 1]; + strcpy(temp, p_source); + + char* token = strtok(temp, ", \t\r\n:"); + while (token) { + len -= (strlen(token) + 1); + + if (strcmpi(token, p_key) == 0) { + if (p_outputValue && len > 0) { + char* cur = &token[strlen(p_key)]; + cur++; + while (*cur != ',') { + if (*cur == ' ' || *cur == '\0' || *cur == '\t' || *cur == '\n' || *cur == '\r') { + break; + } + *p_outputValue++ = *cur++; + } + *p_outputValue = '\0'; + } + + didMatch = TRUE; + break; + } + + token = strtok(NULL, ", \t\r\n:"); + } + + delete[] temp; + return didMatch; +} + +// FUNCTION: LEGO1 0x100b7170 +MxBool ContainsPresenter(MxCompositePresenterList& p_presenterList, MxPresenter* p_presenter) +{ + for (MxCompositePresenterList::iterator it = p_presenterList.begin(); it != p_presenterList.end(); it++) { + if (p_presenter == *it || ((*it)->IsA("MxCompositePresenter") && + ContainsPresenter(((MxCompositePresenter*) *it)->GetList(), p_presenter))) { + return TRUE; + } + } + + return FALSE; +} + +// FUNCTION: LEGO1 0x100b7210 +void SetOmniUserMessage(void (*p_userMsg)(const char*, int)) +{ + 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) +{ + MxU8* buf; + _MMCKINFO tmpChunk; + + if (p_file->Seek(((MxLong*) p_file->GetBuffer())[p_ofs], 0)) { + return NULL; + } + + if (p_file->Read((MxU8*) &tmpChunk.ckid, 8) == 0 && tmpChunk.ckid == FOURCC('M', 'x', 'S', 't')) { + if (p_file->Read((MxU8*) &tmpChunk.ckid, 8) == 0 && tmpChunk.ckid == FOURCC('M', 'x', 'O', 'b')) { + + buf = new MxU8[tmpChunk.cksize]; + if (!buf) { + return NULL; + } + + if (p_file->Read(buf, tmpChunk.cksize) != 0) { + return NULL; + } + + // Save a copy so we can clean up properly, because + // this function will alter the pointer value. + MxU8* copy = buf; + MxDSObject* obj = DeserializeDSObjectDispatch(&buf, -1); + delete[] copy; + return obj; + } + return NULL; + } + + return NULL; +} diff --git a/LEGO1/omni/src/common/mxvariable.cpp b/LEGO1/omni/src/common/mxvariable.cpp new file mode 100644 index 00000000..7b0a46c1 --- /dev/null +++ b/LEGO1/omni/src/common/mxvariable.cpp @@ -0,0 +1,6 @@ +#include "mxvariable.h" + +#include "decomp.h" +#include "mxstring.h" + +DECOMP_SIZE_ASSERT(MxVariable, 0x24) diff --git a/LEGO1/mxvariabletable.cpp b/LEGO1/omni/src/common/mxvariabletable.cpp similarity index 94% rename from LEGO1/mxvariabletable.cpp rename to LEGO1/omni/src/common/mxvariabletable.cpp index d7c6f54f..94bdbacb 100644 --- a/LEGO1/mxvariabletable.cpp +++ b/LEGO1/omni/src/common/mxvariabletable.cpp @@ -41,8 +41,9 @@ void MxVariableTable::SetVariable(MxVariable* p_var) MxHashTableCursor cursor(this); MxBool found = cursor.Find(p_var); - if (found) + if (found) { cursor.DeleteMatch(); + } MxHashTable::Add(p_var); } @@ -50,6 +51,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 new file mode 100644 index 00000000..2edc65f6 --- /dev/null +++ b/LEGO1/omni/src/entity/mxentity.cpp @@ -0,0 +1,3 @@ +#include "mxentity.h" + +DECOMP_SIZE_ASSERT(MxEntity, 0x10) diff --git a/LEGO1/mxeventmanager.cpp b/LEGO1/omni/src/event/mxeventmanager.cpp similarity index 92% rename from LEGO1/mxeventmanager.cpp rename to LEGO1/omni/src/event/mxeventmanager.cpp index 7819c38f..c0ee3229 100644 --- a/LEGO1/mxeventmanager.cpp +++ b/LEGO1/omni/src/event/mxeventmanager.cpp @@ -30,11 +30,13 @@ void MxEventManager::Destroy(MxBool p_fromDestructor) m_thread->Terminate(); delete m_thread; } - else + else { TickleManager()->UnregisterClient(this); + } - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaManager::Destroy(); + } } // FUNCTION: LEGO1 0x100c04a0 @@ -50,21 +52,25 @@ MxResult MxEventManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) locked = TRUE; this->m_thread = new MxTickleThread(this, p_frequencyMS); - if (!this->m_thread || this->m_thread->Start(0, 0) != SUCCESS) + if (!this->m_thread || this->m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; } done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { this->m_criticalSection.Leave(); + } return status; } diff --git a/LEGO1/mxeventpresenter.cpp b/LEGO1/omni/src/event/mxeventpresenter.cpp similarity index 72% rename from LEGO1/mxeventpresenter.cpp rename to LEGO1/omni/src/event/mxeventpresenter.cpp index ce3fdbdf..6072bdd5 100644 --- a/LEGO1/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; @@ -42,13 +42,15 @@ MxResult MxEventPresenter::AddToManager() // FUNCTION: LEGO1 0x100c2de0 void MxEventPresenter::Destroy() { - if (EventManager()) - EventManager()->RemovePresenter(*this); + if (EventManager()) { + EventManager()->UnregisterPresenter(*this); + } m_criticalSection.Enter(); - if (m_data) + if (m_data) { delete[] m_data; + } Init(); @@ -69,21 +71,19 @@ void MxEventPresenter::ReadyTickle() if (chunk) { CopyData(chunk); - m_subscriber->FUN_100b8390(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; + ProgressTickleState(e_streaming); } } @@ -93,8 +93,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,8 +106,9 @@ MxResult MxEventPresenter::PutData() variableTable->SetVariable(key, value); } - if (m_currentTickleState == TickleState_Streaming) - m_subscriber->FUN_100b8390(m_currentChunk); + if (m_currentTickleState == e_streaming) { + m_subscriber->DestroyChunk(m_currentChunk); + } m_currentChunk = NULL; } } diff --git a/LEGO1/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp similarity index 80% rename from LEGO1/mxomni.cpp rename to LEGO1/omni/src/main/mxomni.cpp index 561974da..c04425b1 100644 --- a/LEGO1/mxomni.cpp +++ b/LEGO1/omni/src/main/mxomni.cpp @@ -3,6 +3,7 @@ #include "mxactionnotificationparam.h" #include "mxatomidcounter.h" #include "mxautolocker.h" +#include "mxdsmultiaction.h" #include "mxeventmanager.h" #include "mxmusicmanager.h" #include "mxnotificationmanager.h" @@ -27,26 +28,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 +94,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) { @@ -126,7 +113,7 @@ MxOmni::MxOmni() } // FUNCTION: LEGO1 0x100aefb0 -MxEntity* MxOmni::FindWorld(const char*, MxS32, MxPresenter*) +MxEntity* MxOmni::AddToWorld(const char*, MxS32, MxPresenter*) { return NULL; } @@ -157,7 +144,7 @@ void MxOmni::Init() m_timer = NULL; m_streamer = NULL; m_atomIdCounterSet = NULL; - m_timerRunning = NULL; + m_timerRunning = FALSE; } // FUNCTION: LEGO1 0x100af0b0 @@ -171,48 +158,56 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) { MxResult result = FAILURE; - if (!(m_atomIdCounterSet = new MxAtomIdCounterSet())) + if (!(m_atomIdCounterSet = new MxAtomIdCounterSet())) { goto done; + } m_mediaPath = p_param.GetMediaPath(); m_windowHandle = p_param.GetWindowHandle(); if (p_param.CreateFlags().CreateObjectFactory()) { - if (!(m_objectFactory = new MxObjectFactory())) + if (!(m_objectFactory = new MxObjectFactory())) { goto done; + } } if (p_param.CreateFlags().CreateVariableTable()) { - if (!(m_variableTable = new MxVariableTable())) + if (!(m_variableTable = new MxVariableTable())) { goto done; + } } if (p_param.CreateFlags().CreateTimer()) { - if (!(m_timer = new MxTimer())) + if (!(m_timer = new MxTimer())) { goto done; + } } if (p_param.CreateFlags().CreateTickleManager()) { - if (!(m_tickleManager = new MxTickleManager())) + if (!(m_tickleManager = new MxTickleManager())) { goto done; + } } if (p_param.CreateFlags().CreateNotificationManager()) { - if (m_notificationManager = new MxNotificationManager()) { - if (m_notificationManager->Create(100, 0) != SUCCESS) + if ((m_notificationManager = new MxNotificationManager())) { + if (m_notificationManager->Create(100, 0) != SUCCESS) { goto done; + } } - else + else { goto done; + } } if (p_param.CreateFlags().CreateStreamer()) { - if (!(m_streamer = new MxStreamer()) || m_streamer->Create() != SUCCESS) + if (!(m_streamer = new MxStreamer()) || m_streamer->Create() != SUCCESS) { goto done; + } } if (p_param.CreateFlags().CreateVideoManager()) { - if (m_videoManager = new MxVideoManager()) { + if ((m_videoManager = new MxVideoManager())) { if (m_videoManager->Create(p_param.GetVideoParam(), 100, 0) != SUCCESS) { delete m_videoManager; m_videoManager = NULL; @@ -221,7 +216,7 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } if (p_param.CreateFlags().CreateSoundManager()) { - if (m_soundManager = new MxSoundManager()) { + if ((m_soundManager = new MxSoundManager())) { if (m_soundManager->Create(10, 0) != SUCCESS) { delete m_soundManager; m_soundManager = NULL; @@ -230,7 +225,7 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } if (p_param.CreateFlags().CreateMusicManager()) { - if (m_musicManager = new MxMusicManager()) { + if ((m_musicManager = new MxMusicManager())) { if (m_musicManager->Create(50, 0) != SUCCESS) { delete m_musicManager; m_musicManager = NULL; @@ -239,7 +234,7 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } if (p_param.CreateFlags().CreateEventManager()) { - if (m_eventManager = new MxEventManager()) { + if ((m_eventManager = new MxEventManager())) { if (m_eventManager->Create(50, 0) != SUCCESS) { delete m_eventManager; m_eventManager = NULL; @@ -248,9 +243,11 @@ MxResult MxOmni::Create(MxOmniCreateParam& p_param) } result = SUCCESS; + done: - if (result != SUCCESS) + if (result != SUCCESS) { Destroy(); + } return result; } @@ -268,8 +265,9 @@ void MxOmni::Destroy() // TODO: private members if (m_notificationManager) { while (m_notificationManager->GetQueue()) { - if (m_notificationManager->GetQueue()->size() == 0) + if (m_notificationManager->GetQueue()->size() == 0) { break; + } m_notificationManager->Tickle(); } @@ -324,38 +322,57 @@ void MxOmni::DeleteObject(MxDSAction& p_dsAction) MxResult MxOmni::CreatePresenter(MxStreamController* p_controller, MxDSAction& p_action) { MxResult result = FAILURE; - MxPresenter* object = (MxPresenter*) m_objectFactory->Create(PresenterNameDispatch(p_action)); + const char* name = PresenterNameDispatch(p_action); + MxPresenter* object = (MxPresenter*) m_objectFactory->Create(name); if (object) { if (object->AddToManager() == SUCCESS) { MxPresenter* sender = p_action.GetUnknown28(); - if (sender == NULL && (sender = p_controller->FUN_100c1e70(p_action)) == NULL) { - if (p_action.GetOrigin() == NULL) { - p_action.SetOrigin(this); - } - - object->SetCompositePresenter(NULL); + if (!sender) { + sender = p_controller->FUN_100c1e70(p_action); } - else { + + if (sender) { p_action.SetOrigin(sender); object->SetCompositePresenter((MxCompositePresenter*) sender); } + else { + if (!p_action.GetOrigin()) { + p_action.SetOrigin(this); + } + object->SetCompositePresenter(NULL); + } if (object->StartAction(p_controller, &p_action) == SUCCESS) { if (sender) { +#ifdef COMPAT_MODE + { + MxType4NotificationParam param(this, &p_action, object); + NotificationManager()->Send(sender, ¶m); + } +#else NotificationManager()->Send(sender, &MxType4NotificationParam(this, &p_action, object)); +#endif } if (p_action.GetUnknown84()) { +#ifdef COMPAT_MODE + { + MxStartActionNotificationParam param(c_notificationStartAction, object, &p_action, FALSE); + NotificationManager()->Send(p_action.GetUnknown84(), ¶m); + } +#else NotificationManager()->Send( p_action.GetUnknown84(), - &MxStartActionNotificationParam(c_notificationStartAction, this, &p_action, FALSE) + &MxStartActionNotificationParam(c_notificationStartAction, object, &p_action, FALSE) ); +#endif } result = SUCCESS; } } } + return result; } @@ -374,11 +391,25 @@ void MxOmni::DestroyInstance() } } -// STUB: LEGO1 0x100b06b0 -MxBool MxOmni::FUN_100b06b0(MxDSAction* p_action, const char* p_name) +// FUNCTION: LEGO1 0x100b06b0 +MxBool MxOmni::ActionSourceEquals(MxDSAction* p_action, const char* p_name) { - // TODO - return FAILURE; + if (!strcmp(p_action->GetSourceName(), p_name)) { + return TRUE; + } + + if (p_action->IsA("MxDSMultiAction")) { + MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList()); + MxDSAction* action; + + while (cursor.Next(action)) { + if (ActionSourceEquals(action, p_name)) { + return TRUE; + } + } + } + + return FALSE; } // FUNCTION: LEGO1 0x100b07f0 @@ -386,8 +417,9 @@ MxLong MxOmni::Notify(MxParam& p_param) { MxAutoLocker lock(&this->m_criticalsection); - if (((MxNotificationParam&) p_param).GetNotification() != c_notificationEndAction) + if (((MxNotificationParam&) p_param).GetNotification() != c_notificationEndAction) { return 0; + } return HandleActionEnd(p_param); } @@ -401,7 +433,7 @@ MxLong MxOmni::HandleActionEnd(MxParam& p_param) if (controller != NULL) { action = controller->GetUnk0x54().Find(action, FALSE); if (action) { - if (FUN_100b06b0(action, "LegoLoopingAnimPresenter") == FALSE) { + if (ActionSourceEquals(action, "LegoLoopingAnimPresenter") == FALSE) { delete controller->GetUnk0x54().Find(action, TRUE); } } @@ -460,8 +492,9 @@ MxBool MxOmni::DoesEntityExist(MxDSAction& p_dsAction) if (m_streamer->FUN_100b9b30(p_dsAction)) { MxNotificationPtrList* queue = m_notificationManager->GetQueue(); - if (!queue || queue->size() == 0) + if (!queue || queue->size() == 0) { return TRUE; + } } return FALSE; } diff --git a/LEGO1/mxomnicreateflags.cpp b/LEGO1/omni/src/main/mxomnicreateflags.cpp similarity index 100% rename from LEGO1/mxomnicreateflags.cpp rename to LEGO1/omni/src/main/mxomnicreateflags.cpp diff --git a/LEGO1/mxomnicreateparam.cpp b/LEGO1/omni/src/main/mxomnicreateparam.cpp similarity index 100% rename from LEGO1/mxomnicreateparam.cpp rename to LEGO1/omni/src/main/mxomnicreateparam.cpp diff --git a/LEGO1/omni/src/notify/mxactionnotificationparam.cpp b/LEGO1/omni/src/notify/mxactionnotificationparam.cpp new file mode 100644 index 00000000..c5f816e7 --- /dev/null +++ b/LEGO1/omni/src/notify/mxactionnotificationparam.cpp @@ -0,0 +1,21 @@ +#include "mxactionnotificationparam.h" + +DECOMP_SIZE_ASSERT(MxActionNotificationParam, 0x14) +DECOMP_SIZE_ASSERT(MxEndActionNotificationParam, 0x14) + +// FUNCTION: LEGO1 0x100b0300 +MxNotificationParam* MxStartActionNotificationParam::Clone() +{ + return new MxStartActionNotificationParam( + c_notificationStartAction, + this->m_sender, + this->m_action, + this->m_realloc + ); +} + +// FUNCTION: LEGO1 0x100b04f0 +MxNotificationParam* MxType4NotificationParam::Clone() +{ + return new MxType4NotificationParam(this->m_sender, this->m_action, this->m_unk0x14); +} diff --git a/LEGO1/mxnotificationmanager.cpp b/LEGO1/omni/src/notify/mxnotificationmanager.cpp similarity index 89% rename from LEGO1/mxnotificationmanager.cpp rename to LEGO1/omni/src/notify/mxnotificationmanager.cpp index cc9f3930..fe10a82c 100644 --- a/LEGO1/mxnotificationmanager.cpp +++ b/LEGO1/omni/src/notify/mxnotificationmanager.cpp @@ -2,13 +2,13 @@ #include "compat.h" #include "decomp.h" -#include "legoomni.h" #include "mxautolocker.h" +#include "mxomni.h" #include "mxparam.h" #include "mxticklemanager.h" #include "mxtypes.h" -DECOMP_SIZE_ASSERT(MxNotification, 0x8); +DECOMP_SIZE_ASSERT(MxNotification, 0x08); DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40); // FUNCTION: LEGO1 0x100ac220 @@ -128,9 +128,9 @@ void MxNotificationManager::FlushPending(MxCore* p_listener) MxNotificationPtrList::iterator it = m_sendList->begin(); while (it != m_sendList->end()) { notif = *it; - if ((notif->GetTarget()->GetId() == p_listener->GetId()) || - (notif->GetParam()->GetSender()) && - (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { + if (notif->GetTarget()->GetId() == p_listener->GetId() || + (notif->GetParam()->GetSender() && notif->GetParam()->GetSender()->GetId() == p_listener->GetId() + )) { m_sendList->erase(it++); pending.push_back(notif); } @@ -143,8 +143,8 @@ void MxNotificationManager::FlushPending(MxCore* p_listener) MxNotificationPtrList::iterator it = m_queue->begin(); while (it != m_queue->end()) { notif = *it; - if ((notif->GetTarget()->GetId() == p_listener->GetId()) || - (notif->GetParam()->GetSender()) && (notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { + if (notif->GetTarget()->GetId() == p_listener->GetId() || + (notif->GetParam()->GetSender() && notif->GetParam()->GetSender()->GetId() == p_listener->GetId())) { m_queue->erase(it++); pending.push_back(notif); } @@ -169,8 +169,9 @@ void MxNotificationManager::Register(MxCore* p_listener) MxAutoLocker lock(&m_lock); MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId()); - if (it != m_listenerIds.end()) + if (it != m_listenerIds.end()) { return; + } m_listenerIds.push_back(p_listener->GetId()); } diff --git a/LEGO1/omni/src/notify/mxnotificationparam.cpp b/LEGO1/omni/src/notify/mxnotificationparam.cpp new file mode 100644 index 00000000..cf5bf8b9 --- /dev/null +++ b/LEGO1/omni/src/notify/mxnotificationparam.cpp @@ -0,0 +1,5 @@ +#include "mxnotificationparam.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxNotificationParam, 0x0c); diff --git a/LEGO1/mxdiskstreamcontroller.cpp b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp similarity index 59% rename from LEGO1/mxdiskstreamcontroller.cpp rename to LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp index 71ebc827..a2b2edf9 100644 --- a/LEGO1/mxdiskstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp @@ -1,5 +1,6 @@ #include "mxdiskstreamcontroller.h" +#include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxdiskstreamprovider.h" #include "mxdsstreamingaction.h" @@ -14,10 +15,52 @@ MxDiskStreamController::MxDiskStreamController() m_unk0x8c = 0; } -// STUB: LEGO1 0x100c7530 +// FUNCTION: LEGO1 0x100c7530 MxDiskStreamController::~MxDiskStreamController() { - // TODO + MxAutoLocker lock(&this->m_criticalSection); + + m_unk0xc4 = FALSE; + m_unk0x70 = FALSE; + + if (m_provider) { +#ifdef COMPAT_MODE + { + MxDSAction action; + m_provider->VTable0x20(&action); + } +#else + m_provider->VTable0x20(&MxDSAction()); +#endif + } + + MxDSAction* action; + while (m_unk0x3c.PopFront(action)) { + delete action; + } + + if (m_provider) { + delete m_provider; + m_provider = NULL; + } + + FUN_100c8720(); + + while (m_list0x80.PopFront(action)) { + FUN_100c7cb0((MxDSStreamingAction*) action); + } + + while (m_list0x64.PopFront(action)) { + FUN_100c7cb0((MxDSStreamingAction*) action); + } + + while (!m_list0x74.empty()) { + MxDSBuffer* buffer = m_list0x74.front(); + m_list0x74.pop_front(); + FUN_100c7ce0(buffer); + } + + TickleManager()->UnregisterClient(this); } // FUNCTION: LEGO1 0x100c7790 @@ -52,12 +95,31 @@ MxResult MxDiskStreamController::VTable0x18(undefined4, undefined4) return SUCCESS; } +// FUNCTION: LEGO1 0x100c7890 +MxResult MxDiskStreamController::FUN_100c7890(MxDSStreamingAction* p_action) +{ + MxAutoLocker lock(&this->m_criticalSection); + if (p_action == NULL) { + return FAILURE; + } + + m_list0x80.push_back(p_action); + FUN_100c7970(); + return SUCCESS; +} + // FUNCTION: LEGO1 0x100c7960 MxResult MxDiskStreamController::VTable0x34(undefined4) { return FAILURE; } +// FUNCTION: LEGO1 0x100c7970 +void MxDiskStreamController::FUN_100c7970() +{ + // Empty +} + // FUNCTION: LEGO1 0x100c7980 void MxDiskStreamController::FUN_100c7980() { @@ -70,16 +132,18 @@ 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) + if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBuffer::e_chunk) != SUCCESS) { + if (buffer) { delete buffer; + } return; } action = VTable0x28(); if (!action) { - if (buffer) + if (buffer) { delete buffer; + } return; } @@ -154,10 +218,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; } @@ -169,8 +233,9 @@ MxResult MxDiskStreamController::FUN_100c7d10() MxAutoLocker lock(&this->m_criticalSection); MxDSStreamingAction* action = FUN_100c7db0(); - if (!action) + if (!action) { return FAILURE; + } if (FUN_100c8360(action) != SUCCESS) { VTable0x24(action); @@ -181,10 +246,29 @@ MxResult MxDiskStreamController::FUN_100c7d10() return SUCCESS; } -// STUB: LEGO1 0x100c7db0 +// FUNCTION: LEGO1 0x100c7db0 MxDSStreamingAction* MxDiskStreamController::FUN_100c7db0() { - // TODO + MxAutoLocker lock(&this->m_criticalSection); + + for (MxStreamListMxNextActionDataStart::iterator it = m_nextActionList.begin(); it != m_nextActionList.end(); + it++) { + MxNextActionDataStart* data = *it; + for (MxStreamListMxDSAction::iterator it2 = m_list0x64.begin(); it2 != m_list0x64.end(); it2++) { + MxDSStreamingAction* streamingAction = (MxDSStreamingAction*) *it2; + if (streamingAction->GetObjectId() == data->GetObjectId() && + streamingAction->GetUnknown24() == data->GetUnknown24() && + streamingAction->GetBufferOffset() == data->GetData()) { + m_nextActionList.erase(it); + + data->SetData(m_provider->GetFileSize() + data->GetData()); + m_nextActionList.push_back(data); + + m_list0x64.erase(it2); + return streamingAction; + } + } + } return NULL; } @@ -203,7 +287,6 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) MxAutoLocker lock(&this->m_criticalSection); MxDSStreamingAction* entry = (MxDSStreamingAction*) m_list0x80.Find(p_action, FALSE); // TODO: is this a seperate class? - if (entry) { MxDSStreamingAction* action = new MxDSStreamingAction(*p_action, 0); action->SetUnknown28(entry->GetUnknown28()); @@ -213,22 +296,77 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) FUN_100c7f40(action); - if (VTable0x2c(p_action, entry->GetUnknown94()) != SUCCESS) + if (VTable0x2c(p_action, entry->GetUnknown94()) != SUCCESS) { return FAILURE; + } } - else if (MxStreamController::VTable0x20(p_action) != SUCCESS) + else if (MxStreamController::VTable0x20(p_action) != SUCCESS) { return FAILURE; + } - m_unk0x70 = 1; - m_unk0xc4 = 1; + m_unk0x70 = TRUE; + m_unk0xc4 = TRUE; return SUCCESS; } -// STUB: LEGO1 0x100c8160 +// 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) { - // TODO - return FAILURE; + MxAutoLocker lock(&this->m_criticalSection); + if (m_unk0x54.Find(p_action, FALSE) == NULL) { + if (VTable0x30(p_action) == SUCCESS) { +#ifdef COMPAT_MODE + { + MxEndActionNotificationParam param(c_notificationEndAction, NULL, p_action, TRUE); + MxOmni::GetInstance()->NotifyCurrentEntity(¶m); + } +#else + MxOmni::GetInstance()->NotifyCurrentEntity( + &MxEndActionNotificationParam(c_notificationEndAction, NULL, p_action, TRUE) + ); +#endif + } + } + + MxDSAction action; + if (m_provider) { + m_provider->VTable0x20(p_action); + } + + do { + if (m_action0x60 != NULL) { + delete m_action0x60; + m_action0x60 = NULL; + } + + action = *p_action; + MxStreamController::VTable0x24(&action); + } while (m_action0x60 != NULL); + + if (m_unk0x3c.empty()) { + m_unk0x70 = FALSE; + m_unk0xc4 = FALSE; + } + + return SUCCESS; } // FUNCTION: LEGO1 0x100c8360 @@ -269,10 +407,28 @@ void MxDiskStreamController::InsertToList74(MxDSBuffer* p_buffer) m_list0x74.push_back(p_buffer); } -// STUB: LEGO1 0x100c8540 +// FUNCTION: LEGO1 0x100c8540 void MxDiskStreamController::FUN_100c8540() { - // TODO + MxAutoLocker lock(&this->m_criticalSection); + for (list::iterator it = m_list0x74.begin(); it != m_list0x74.end();) { + MxDSBuffer* buf = *it; + if (buf->GetRefCount() == 0) { + m_list0x74.erase(it++); + FUN_100c7ce0(buf); + } + else { + it++; + } + } + + if (m_nextActionList.empty()) { + while (!m_list0x64.empty()) { + MxDSStreamingAction* action = (MxDSStreamingAction*) m_list0x64.front(); + m_list0x64.pop_front(); + FUN_100c7cb0(action); + } + } } // FUNCTION: LEGO1 0x100c8640 @@ -292,13 +448,20 @@ MxResult MxDiskStreamController::Tickle() return SUCCESS; } +// FUNCTION: LEGO1 0x100c8670 +void MxDiskStreamController::FUN_100c8670(MxDSStreamingAction* p_streamingAction) +{ + MxAutoLocker lock(&this->m_critical9c); + m_list0xb8.push_back(p_streamingAction); +} + // FUNCTION: LEGO1 0x100c8720 void MxDiskStreamController::FUN_100c8720() { MxAutoLocker lock(&this->m_critical9c); MxDSStreamingAction* action; - while (m_list0xb8.size() != 0) { + while (!m_list0xb8.empty()) { action = (MxDSStreamingAction*) m_list0xb8.front(); m_list0xb8.pop_front(); diff --git a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp new file mode 100644 index 00000000..88f70c7d --- /dev/null +++ b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp @@ -0,0 +1,414 @@ +#include "mxdiskstreamprovider.h" + +#include "mxautolocker.h" +#include "mxdiskstreamcontroller.h" +#include "mxdsbuffer.h" +#include "mxdsstreamingaction.h" +#include "mxomni.h" +#include "mxramstreamprovider.h" +#include "mxstreamcontroller.h" +#include "mxstring.h" +#include "mxthread.h" + +DECOMP_SIZE_ASSERT(MxDiskStreamProviderThread, 0x1c) +DECOMP_SIZE_ASSERT(MxDiskStreamProvider, 0x60); + +// GLOBAL: LEGO1 0x10102878 +MxU32 g_unk0x10102878 = 0; + +// FUNCTION: LEGO1 0x100d0f30 +MxResult MxDiskStreamProviderThread::Run() +{ + if (m_target) { + ((MxDiskStreamProvider*) m_target)->WaitForWorkToComplete(); + } + MxThread::Run(); + // They should probably have writen "return MxThread::Run()" but they didn't. + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100d0f50 +MxResult MxDiskStreamProviderThread::StartWithTarget(MxDiskStreamProvider* p_target) +{ + m_target = p_target; + return Start(0x1000, 0); +} + +// FUNCTION: LEGO1 0x100d0f70 +MxDiskStreamProvider::MxDiskStreamProvider() +{ + this->m_pFile = NULL; + this->m_remainingWork = FALSE; + this->m_unk0x35 = FALSE; +} + +// FUNCTION: LEGO1 0x100d1240 +MxDiskStreamProvider::~MxDiskStreamProvider() +{ + MxDSStreamingAction* action; + m_unk0x35 = FALSE; + + do { + action = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + m_list.PopFrontStreamingAction(action); + } + + if (!action) { + break; + } + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878--; + } + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + + if (m_remainingWork) { + m_remainingWork = FALSE; + m_busySemaphore.Release(1); + m_thread.Terminate(); + } + + if (m_pFile) { + delete m_pFile; + } + + m_pFile = NULL; +} + +// FUNCTION: LEGO1 0x100d13d0 +MxResult MxDiskStreamProvider::SetResourceToGet(MxStreamController* p_resource) +{ + MxResult result = FAILURE; + MxString path; + m_pLookup = p_resource; + + path = (MxString(MxOmni::GetHD()) + p_resource->GetAtom().GetInternal() + ".si"); + + m_pFile = new MxDSFile(path.GetData(), 0); + if (m_pFile != NULL) { + if (m_pFile->Open(0) != 0) { + path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si"; + m_pFile->SetFileName(path.GetData()); + + if (m_pFile->Open(0) != 0) { + goto done; + } + } + + m_remainingWork = TRUE; + m_busySemaphore.Init(0, 100); + + if (m_thread.StartWithTarget(this) == SUCCESS && p_resource != NULL) { + result = SUCCESS; + } + } + +done: + return result; +} + +// FUNCTION: LEGO1 0x100d15e0 +void MxDiskStreamProvider::VTable0x20(MxDSAction* p_action) +{ + MxDSStreamingAction* action; + + if (p_action->GetObjectId() == -1) { + m_unk0x35 = FALSE; + + do { + action = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + m_list.PopFrontStreamingAction(action); + } + + if (!action) { + return; + } + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878--; + } + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + } + else { + do { + { + MxAutoLocker lock(&m_criticalSection); + action = (MxDSStreamingAction*) m_list.Find(p_action, TRUE); + } + + if (!action) { + return; + } + + if (action->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878--; + } + + ((MxDiskStreamController*) m_pLookup)->FUN_100c8670(action); + } while (action); + } +} + +// FUNCTION: LEGO1 0x100d1750 +MxResult MxDiskStreamProvider::WaitForWorkToComplete() +{ + while (m_remainingWork) { + m_busySemaphore.Wait(INFINITE); + if (m_unk0x35) { + PerformWork(); + } + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100d1780 +MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action) +{ + if (!m_remainingWork) { + return FAILURE; + } + + if (p_action->GetUnknown9c() > 0 && !p_action->GetUnknowna0()) { + MxDSBuffer* buffer = new MxDSBuffer(); + + if (!buffer) { + return FAILURE; + } + + if (buffer->AllocateBuffer(GetFileSize(), MxDSBuffer::e_allocate) != SUCCESS) { + delete buffer; + return FAILURE; + } + + p_action->SetUnknowna0(buffer); + } + + if (p_action->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878++; + } + + { + MxAutoLocker lock(&m_criticalSection); + m_list.push_back(p_action); + } + + m_unk0x35 = TRUE; + m_busySemaphore.Release(1); + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100d18f0 +void MxDiskStreamProvider::PerformWork() +{ + MxDiskStreamController* controller = (MxDiskStreamController*) m_pLookup; + MxDSStreamingAction* streamingAction = NULL; + + { + MxAutoLocker lock(&m_criticalSection); + if (!m_list.empty()) { + streamingAction = (MxDSStreamingAction*) m_list.front(); + + if (streamingAction && !FUN_100d1af0(streamingAction)) { + m_thread.Sleep(500); + m_busySemaphore.Release(1); + return; + } + } + } + + MxDSBuffer* buffer; + + { + MxAutoLocker lock(&m_criticalSection); + + if (!m_list.PopFrontStreamingAction(streamingAction)) { + goto done; + } + } + + if (streamingAction->GetUnknowna0()->GetWriteOffset() < 0x20000) { + g_unk0x10102878--; + } + + buffer = streamingAction->GetUnknowna0(); + + if (m_pFile->GetPosition() == streamingAction->GetBufferOffset() || + m_pFile->Seek(streamingAction->GetBufferOffset(), 0) == 0) { + buffer->SetUnknown14(m_pFile->GetPosition()); + + if (m_pFile->ReadToBuffer(buffer) == SUCCESS) { + buffer->SetUnknown1c(m_pFile->GetPosition()); + + if (streamingAction->GetUnknown9c() > 0) { + FUN_100d1b20(streamingAction); + } + else { + if (m_pLookup == NULL || !((MxDiskStreamController*) m_pLookup)->GetUnk0xc4()) { + controller->FUN_100c8670(streamingAction); + } + else { + controller->FUN_100c7f40(streamingAction); + } + } + + streamingAction = NULL; + } + } + +done: + if (streamingAction) { + controller->FUN_100c8670(streamingAction); + } + + m_thread.Sleep(0); +} + +// FUNCTION: LEGO1 0x100d1af0 +MxBool MxDiskStreamProvider::FUN_100d1af0(MxDSStreamingAction* p_action) +{ + if (p_action->GetUnknowna0()->GetWriteOffset() == 0x20000) { + return g_unk0x10102878 == 0; + } + + return TRUE; +} + +// FUNCTION: LEGO1 0x100d1b20 +MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) +{ + 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 +MxU32 MxDiskStreamProvider::GetFileSize() +{ + return m_pFile->GetBufferSize(); +} + +// FUNCTION: LEGO1 0x100d1ea0 +MxS32 MxDiskStreamProvider::GetStreamBuffersNum() +{ + return m_pFile->GetStreamBuffersNum(); +} + +// FUNCTION: LEGO1 0x100d1eb0 +MxU32 MxDiskStreamProvider::GetLengthInDWords() +{ + return m_pFile->GetLengthInDWords(); +} + +// FUNCTION: LEGO1 0x100d1ec0 +MxU32* MxDiskStreamProvider::GetBufferForDWords() +{ + return m_pFile->GetBuffer(); +} diff --git a/LEGO1/omni/src/stream/mxdsbuffer.cpp b/LEGO1/omni/src/stream/mxdsbuffer.cpp new file mode 100644 index 00000000..106964b2 --- /dev/null +++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp @@ -0,0 +1,559 @@ +#include "mxdsbuffer.h" + +#include "mxdiskstreamcontroller.h" +#include "mxdschunk.h" +#include "mxdsstreamingaction.h" +#include "mxomni.h" +#include "mxstreamchunk.h" +#include "mxstreamcontroller.h" +#include "mxstreamer.h" + +DECOMP_SIZE_ASSERT(MxDSBuffer, 0x34); + +// FUNCTION: LEGO1 0x100c6470 +MxDSBuffer::MxDSBuffer() +{ + m_refcount = 0; + m_pBuffer = NULL; + m_pIntoBuffer = NULL; + m_pIntoBuffer2 = NULL; + m_unk0x14 = 0; + m_unk0x18 = 0; + m_unk0x1c = 0; + m_writeOffset = 0; + m_bytesRemaining = 0; + m_mode = e_preallocated; + m_unk0x30 = 0; +} + +// FUNCTION: LEGO1 0x100c6530 +MxDSBuffer::~MxDSBuffer() +{ + if (m_pBuffer != NULL) { + switch (m_mode) { + case e_allocate: + case e_unknown: + delete[] m_pBuffer; + break; + + case e_chunk: { + MxU32 offset = m_writeOffset / 1024; + MxStreamer* streamer = Streamer(); + + switch (offset) { + case 0x40: { + MxU32 a = + (m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10); + + MxU32 bit = 1 << ((MxU8) a & 0x1f); + MxU32 index = (a & ~0x18u) >> 3; + + if ((*(MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index])) & bit) { + MxU32* ptr = (MxU32*) (&streamer->GetSubclass1().GetUnk08Ref()[index]); + *ptr = *ptr ^ bit; + } + break; + } + case 0x80: { + MxU32 a = + (m_pBuffer - streamer->GetSubclass1().GetBuffer()) / (streamer->GetSubclass1().GetSize() << 10); + + MxU32 bit = 1 << ((MxU8) a & 0x1f); + MxU32 index = (a & ~0x18u) >> 3; + + if ((*(MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index])) & bit) { + MxU32* ptr = (MxU32*) (&streamer->GetSubclass2().GetUnk08Ref()[index]); + *ptr = *ptr ^ bit; + } + break; + } + } + } + } + } + + m_unk0x14 = 0; + m_unk0x1c = 0; +} + +// FUNCTION: LEGO1 0x100c6640 +MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, Type p_mode) +{ + MxResult result = FAILURE; + + switch (p_mode) { + case e_allocate: + m_pBuffer = new MxU8[p_bufferSize]; + break; + + case e_chunk: { + MxStreamer* streamer = Streamer(); + + switch (p_bufferSize / 1024) { + case 0x40: { + for (MxU32 i = 0; i < 22; i++) { + if (((1 << (i & 0x1f)) & (*(MxU32*) &streamer->GetSubclass1().GetUnk08Ref()[(i & ~0x18u) >> 3])) == 0) { + MxU32* ptr = (MxU32*) &streamer->GetSubclass1().GetUnk08Ref()[(i & 0xffffffe7) >> 3]; + + *ptr = *ptr ^ 1 << (i & 0x1f); + + m_pBuffer = + (MxU8*) (streamer->GetSubclass1().GetSize() * i * 0x400 + streamer->GetSubclass1().GetBuffer()); + goto done; + } + } + + m_pBuffer = NULL; + break; + } + case 0x80: { + for (MxU32 i = 0; i < 2; i++) { + if (((1 << (i & 0x1f)) & (*(MxU32*) &streamer->GetSubclass2().GetUnk08Ref()[(i & ~0x18u) >> 3])) == 0) { + MxU32* ptr = (MxU32*) &streamer->GetSubclass2().GetUnk08Ref()[(i & 0xffffffe7) >> 3]; + + *ptr = *ptr ^ 1 << (i & 0x1f); + + m_pBuffer = + (MxU8*) (streamer->GetSubclass2().GetSize() * i * 0x400 + streamer->GetSubclass2().GetBuffer()); + goto done; + } + } + + m_pBuffer = NULL; + break; + } + default: + m_pBuffer = NULL; + } + } + } + +done: + m_pIntoBuffer = m_pBuffer; + m_pIntoBuffer2 = m_pBuffer; + + if (m_pBuffer != NULL) { + m_mode = p_mode; + m_bytesRemaining = p_bufferSize; + m_writeOffset = p_bufferSize; + result = SUCCESS; + } + + return result; +} + +// FUNCTION: LEGO1 0x100c6780 +MxResult MxDSBuffer::SetBufferPointer(MxU8* p_buffer, MxU32 p_size) +{ + m_pBuffer = p_buffer; + m_pIntoBuffer = p_buffer; + m_pIntoBuffer2 = p_buffer; + m_bytesRemaining = p_size; + m_writeOffset = p_size; + m_mode = e_preallocated; + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100c67b0 +MxResult MxDSBuffer::FUN_100c67b0( + MxStreamController* p_controller, + MxDSAction* p_action, + MxDSStreamingAction** p_streamingAction +) +{ + MxResult result = FAILURE; + + m_unk0x30 = (MxDSStreamingAction*) p_controller->GetUnk0x3c().Find(p_action, FALSE); + if (m_unk0x30 == NULL) { + return FAILURE; + } + + MxU8* data; + while ((data = (MxU8*) SkipToData())) { + if (*p_streamingAction == NULL) { + result = CreateObject(p_controller, (MxU32*) data, p_action, p_streamingAction); + + if (result == FAILURE) { + return result; + } + // TODO: Not a MxResult value? + if (result == 1) { + break; + } + } + else { + MxDSBuffer* buffer = (*p_streamingAction)->GetUnknowna0(); + + if (buffer->CalcBytesRemaining(data) != SUCCESS) { + return result; + } + + if (buffer->GetBytesRemaining() == 0) { + buffer->SetUnk30(m_unk0x30); + + result = buffer->CreateObject(p_controller, (MxU32*) buffer->GetBuffer(), p_action, p_streamingAction); + if (result != SUCCESS) { + return result; + } + + if (buffer->GetRefCount() != 0) { + // Note: *p_streamingAction is always null in MxRamStreamProvider + ((MxDiskStreamController*) p_controller)->InsertToList74(buffer); + (*p_streamingAction)->SetUnknowna0(NULL); + } + + ((MxDiskStreamController*) p_controller)->FUN_100c7cb0(*p_streamingAction); + *p_streamingAction = NULL; + } + } + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100c68a0 +MxResult MxDSBuffer::CreateObject( + MxStreamController* p_controller, + MxU32* p_data, + MxDSAction* p_action, + MxDSStreamingAction** p_streamingAction +) +{ + if (p_data == NULL) { + return FAILURE; + } + + MxCore* header = ReadChunk(this, p_data, p_action->GetUnknown24()); + + if (header == NULL) { + return FAILURE; + } + + if (*p_data == FOURCC('M', 'x', 'O', 'b')) { + return StartPresenterFromAction(p_controller, p_action, (MxDSAction*) header); + } + else if (*p_data == FOURCC('M', 'x', 'C', 'h')) { + MxStreamChunk* chunk = (MxStreamChunk*) header; + if (!m_unk0x30->HasId((chunk)->GetObjectId())) { + delete header; + return SUCCESS; + } + + return ParseChunk(p_controller, p_data, p_action, p_streamingAction, chunk); + } + + delete header; + return FAILURE; +} + +// FUNCTION: LEGO1 0x100c6960 +MxResult MxDSBuffer::StartPresenterFromAction( + MxStreamController* p_controller, + MxDSAction* p_action1, + MxDSAction* p_objectheader +) +{ + if (!m_unk0x30->GetInternalAction()) { + p_objectheader->SetAtomId(p_action1->GetAtomId()); + p_objectheader->SetUnknown28(p_action1->GetUnknown28()); + p_objectheader->SetUnknown84(p_action1->GetUnknown84()); + p_objectheader->SetOrigin(p_action1->GetOrigin()); + p_objectheader->SetUnknown90(p_action1->GetUnknown90()); + p_objectheader->MergeFrom(*p_action1); + + m_unk0x30->SetInternalAction(p_objectheader->Clone()); + + p_controller->InsertActionToList54(p_objectheader); + + if (MxOmni::GetInstance()->CreatePresenter(p_controller, *p_objectheader) != SUCCESS) { + return FAILURE; + } + + m_unk0x30->SetLoopCount(p_objectheader->GetLoopCount()); + m_unk0x30->SetFlags(p_objectheader->GetFlags()); + m_unk0x30->SetDuration(p_objectheader->GetDuration()); + + if (m_unk0x30->GetInternalAction() == NULL) { + return FAILURE; + } + } + else if (p_objectheader) { + delete p_objectheader; + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100c6a50 +MxResult MxDSBuffer::ParseChunk( + MxStreamController* p_controller, + MxU32* p_data, + MxDSAction* p_action, + MxDSStreamingAction** p_streamingAction, + MxStreamChunk* p_header +) +{ + MxResult result = SUCCESS; + + 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::c_split) { + MxU32 length = p_header->GetLength() + MxDSChunk::GetHeaderSize() + 8; + MxDSBuffer* buffer = new MxDSBuffer(); + + 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::c_split; + + delete p_header; + (*p_streamingAction)->SetUnknowna0(buffer); + goto done; + } + } + + if (buffer) { + delete buffer; + } + + delete p_header; + return FAILURE; + } + else { + if (p_header->GetFlags() & MxDSChunk::c_end) { + if (m_unk0x30->HasId(p_header->GetObjectId())) { + if (m_unk0x30->GetFlags() & MxDSAction::c_bit3 && + (m_unk0x30->GetLoopCount() > 1 || m_unk0x30->GetDuration() == -1)) { + + if (p_action->GetObjectId() == p_header->GetObjectId()) { + MxU32 val = p_controller->GetProvider()->GetBufferForDWords()[m_unk0x30->GetObjectId()]; + + m_unk0x30->SetUnknown94(val); + m_unk0x30->SetBufferOffset(m_writeOffset * (val / m_writeOffset)); + + MxNextActionDataStart* data = + p_controller->FindNextActionDataStartFromStreamingAction(m_unk0x30); + + if (data) { + data->SetData(m_unk0x30->GetBufferOffset()); + } + + m_unk0x30->FUN_100cd2d0(); + } + + delete p_header; + p_header = NULL; + } + else { + if (p_action->GetObjectId() == p_header->GetObjectId() && + p_controller->VTable0x30(p_action) == SUCCESS) { + p_controller->GetProvider()->VTable0x20(p_action); + result = 1; + } + } + } + } + + if (p_header) { + if (p_header->SendChunk(p_controller->GetSubscriberList(), TRUE, p_action->GetUnknown24()) != SUCCESS) { + delete p_header; + } + } + } + +done: + return result; +} + +// FUNCTION: LEGO1 0x100c6d00 +MxCore* MxDSBuffer::ReadChunk(MxDSBuffer* p_buffer, MxU32* p_chunkData, MxU16 p_flags) +{ + // This function reads a chunk. If it is an object, this function returns an MxDSObject. If it is a chunk, + // returns a MxDSChunk. + MxCore* result = NULL; + MxU8* dataStart = (MxU8*) p_chunkData + 8; + + switch (*p_chunkData) { + case FOURCC('M', 'x', 'O', 'b'): + result = DeserializeDSObjectDispatch(&dataStart, p_flags); + break; + case FOURCC('M', 'x', 'C', 'h'): + result = new MxStreamChunk(); + if (result != NULL && ((MxStreamChunk*) result)->ReadChunk(p_buffer, (MxU8*) p_chunkData) != SUCCESS) { + delete result; + result = NULL; + } + return result; + } + + return result; +} + +// FUNCTION: LEGO1 0x100c6df0 +MxU8* MxDSBuffer::SkipToData() +{ + MxU8* result = NULL; + + if (m_pIntoBuffer != NULL) { + do { + MxU32* ptr = (MxU32*) m_pIntoBuffer; + switch (*ptr) { + case FOURCC('L', 'I', 'S', 'T'): + case FOURCC('R', 'I', 'F', 'F'): + m_pIntoBuffer = (MxU8*) (ptr + 3); + break; + case FOURCC('M', 'x', 'O', 'b'): + case FOURCC('M', 'x', 'C', 'h'): + result = m_pIntoBuffer; + m_pIntoBuffer = (MxU8*) ((ptr[1] & 1) + ptr[1] + (MxU32) ptr); + m_pIntoBuffer = (MxU8*) ((MxU32*) m_pIntoBuffer + 2); + if (m_pBuffer + (m_writeOffset - 8) < m_pIntoBuffer) { + m_pIntoBuffer2 = result; + m_pIntoBuffer = NULL; + return result; + } + goto done; + case FOURCC('M', 'x', 'D', 'a'): + case FOURCC('M', 'x', 'S', 't'): + m_pIntoBuffer = (MxU8*) (ptr + 2); + break; + case FOURCC('M', 'x', 'H', 'd'): + m_pIntoBuffer = (MxU8*) ((MxU32) ptr + ptr[1] + 8); + break; + default: + m_pIntoBuffer = NULL; + m_pIntoBuffer2 = NULL; + return NULL; + } + } while (m_pIntoBuffer <= m_pBuffer + (m_writeOffset - 8)); + } +done: + m_pIntoBuffer2 = result; + return result; +} + +// FUNCTION: LEGO1 0x100c6ec0 +MxU8 MxDSBuffer::ReleaseRef(MxDSChunk*) +{ + if (m_refcount != 0) { + m_refcount--; + } + return 0; +} + +// FUNCTION: LEGO1 0x100c6ee0 +void MxDSBuffer::AddRef(MxDSChunk* p_chunk) +{ + if (p_chunk) { + m_refcount++; + } +} + +// FUNCTION: LEGO1 0x100c6ef0 +MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) +{ + MxResult result = FAILURE; + + if (m_mode == e_allocate && m_bytesRemaining != 0) { + MxU32 bytesRead; + MxU8* ptr; + + if (m_writeOffset == m_bytesRemaining) { + bytesRead = *(MxU32*) (p_data + 4) + 8; + ptr = p_data; + } + else { + 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::GetHeaderSize(); + } + + m_bytesRemaining -= bytesRead; + result = SUCCESS; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x100c6f80 +void MxDSBuffer::FUN_100c6f80(MxU32 p_writeOffset) +{ + if (p_writeOffset < m_writeOffset) { + m_pIntoBuffer2 = m_pBuffer + 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/mxdschunk.cpp b/LEGO1/omni/src/stream/mxdschunk.cpp similarity index 72% rename from LEGO1/mxdschunk.cpp rename to LEGO1/omni/src/stream/mxdschunk.cpp index b44bc475..a964d0fa 100644 --- a/LEGO1/mxdschunk.cpp +++ b/LEGO1/omni/src/stream/mxdschunk.cpp @@ -15,7 +15,13 @@ 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::GetHeaderSize() +{ + return 0x0e; +} diff --git a/LEGO1/mxdsfile.cpp b/LEGO1/omni/src/stream/mxdsfile.cpp similarity index 96% rename from LEGO1/mxdsfile.cpp rename to LEGO1/omni/src/stream/mxdsfile.cpp index 3e03ad6e..b422f45e 100644 --- a/LEGO1/mxdsfile.cpp +++ b/LEGO1/omni/src/stream/mxdsfile.cpp @@ -62,7 +62,7 @@ MxLong MxDSFile::ReadChunks() return -1; } - m_io.Read(&m_header, 0xc); + m_io.Read(&m_header, 0x0c); if ((m_header.m_majorVersion == SI_MAJOR_VERSION) && (m_header.m_minorVersion == SI_MINOR_VERSION)) { childChunk.ckid = FOURCC('M', 'x', 'O', 'f'); if (m_io.Descend(&childChunk, &topChunk, 0) != 0) { @@ -98,8 +98,9 @@ MxLong MxDSFile::Close() // FUNCTION: LEGO1 0x100cc780 MxResult MxDSFile::Read(unsigned char* p_buf, MxULong p_nbytes) { - if (m_io.Read(p_buf, p_nbytes) != p_nbytes) + if (m_io.Read(p_buf, p_nbytes) != p_nbytes) { return FAILURE; + } m_position += p_nbytes; return SUCCESS; diff --git a/LEGO1/mxdssource.cpp b/LEGO1/omni/src/stream/mxdssource.cpp similarity index 62% rename from LEGO1/mxdssource.cpp rename to LEGO1/omni/src/stream/mxdssource.cpp index c38799d3..c2d86abb 100644 --- a/LEGO1/mxdssource.cpp +++ b/LEGO1/omni/src/stream/mxdssource.cpp @@ -2,10 +2,12 @@ #include "mxdsbuffer.h" +DECOMP_SIZE_ASSERT(MxDSSource, 0x14) + // FUNCTION: LEGO1 0x100bffd0 -void MxDSSource::ReadToBuffer(MxDSBuffer* p_buffer) +MxResult MxDSSource::ReadToBuffer(MxDSBuffer* p_buffer) { - Read(p_buffer->GetBuffer(), p_buffer->GetWriteOffset()); + return Read(p_buffer->GetBuffer(), p_buffer->GetWriteOffset()); } // FUNCTION: LEGO1 0x100bfff0 diff --git a/LEGO1/omni/src/stream/mxdssubscriber.cpp b/LEGO1/omni/src/stream/mxdssubscriber.cpp new file mode 100644 index 00000000..488ff02c --- /dev/null +++ b/LEGO1/omni/src/stream/mxdssubscriber.cpp @@ -0,0 +1,137 @@ +#include "mxdssubscriber.h" + +#include "mxstreamcontroller.h" + +DECOMP_SIZE_ASSERT(MxDSSubscriber, 0x4c); + +// FUNCTION: LEGO1 0x100b7bb0 +MxDSSubscriber::MxDSSubscriber() +{ + m_unk0x48 = -1; + m_objectId = -1; + m_pendingChunkCursor = NULL; + m_consumedChunkCursor = NULL; +} + +// FUNCTION: LEGO1 0x100b7e00 +MxDSSubscriber::~MxDSSubscriber() +{ + if (m_controller) { + m_controller->RemoveSubscriber(this); + } + + DeleteChunks(); + + if (m_pendingChunkCursor) { + delete m_pendingChunkCursor; + } + m_pendingChunkCursor = NULL; + + if (m_consumedChunkCursor) { + delete m_consumedChunkCursor; + } + m_consumedChunkCursor = NULL; +} + +// FUNCTION: LEGO1 0x100b7ed0 +MxResult MxDSSubscriber::Create(MxStreamController* p_controller, MxU32 p_objectId, MxS16 p_unk0x48) +{ + m_objectId = p_objectId; + m_unk0x48 = p_unk0x48; + + if (!p_controller) { + return FAILURE; + } + m_controller = p_controller; + + m_pendingChunkCursor = new MxStreamChunkListCursor(&m_pendingChunks); + if (!m_pendingChunkCursor) { + return FAILURE; + } + + m_consumedChunkCursor = new MxStreamChunkListCursor(&m_consumedChunks); + if (!m_consumedChunkCursor) { + return FAILURE; + } + + m_controller->AddSubscriber(this); + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100b8030 +void MxDSSubscriber::DeleteChunks() +{ + if (m_controller) { + MxStreamChunk* chunk = NULL; + + while (m_pendingChunkCursor->First(chunk)) { + m_pendingChunkCursor->Detach(); + delete chunk; + } + + while (m_consumedChunkCursor->First(chunk)) { + m_consumedChunkCursor->Detach(); + delete chunk; + } + } +} + +// FUNCTION: LEGO1 0x100b8150 +MxResult MxDSSubscriber::AddChunk(MxStreamChunk* p_chunk, MxBool p_append) +{ + if (m_pendingChunkCursor) { + if (p_append) { + m_pendingChunks.Append(p_chunk); + } + else { + m_pendingChunks.Prepend(p_chunk); + } + } + + return SUCCESS; +} + +// FUNCTION: LEGO1 0x100b8250 +MxStreamChunk* MxDSSubscriber::NextChunk() +{ + MxStreamChunk* chunk = NULL; + + if (m_pendingChunkCursor) { + m_pendingChunkCursor->First(chunk); + } + + if (chunk) { + m_pendingChunkCursor->Detach(); + m_consumedChunks.Append(chunk); + } + + return chunk; +} + +// FUNCTION: LEGO1 0x100b8360 +MxStreamChunk* MxDSSubscriber::CurrentChunk() +{ + MxStreamChunk* chunk = NULL; + + if (m_pendingChunkCursor) { + m_pendingChunkCursor->First(chunk); + } + + return chunk; +} + +// FUNCTION: LEGO1 0x100b8390 +void MxDSSubscriber::DestroyChunk(MxStreamChunk* p_chunk) +{ + if (p_chunk) { + if (m_consumedChunkCursor->Find(p_chunk)) { + m_consumedChunkCursor->Detach(); + if (p_chunk) { + delete p_chunk; + } + } + else if (p_chunk->GetFlags() & MxDSChunk::c_bit1 && p_chunk) { + delete p_chunk; + } + } +} diff --git a/LEGO1/mxioinfo.cpp b/LEGO1/omni/src/stream/mxioinfo.cpp similarity index 98% rename from LEGO1/mxioinfo.cpp rename to LEGO1/omni/src/stream/mxioinfo.cpp index 9951c174..a040bc41 100644 --- a/LEGO1/mxioinfo.cpp +++ b/LEGO1/omni/src/stream/mxioinfo.cpp @@ -72,8 +72,9 @@ MxU16 MXIOINFO::Close(MxLong p_unused) _lclose((HFILE) m_info.hmmio); m_info.hmmio = 0; - if (m_info.dwFlags & MMIO_ALLOCBUF) + if (m_info.dwFlags & MMIO_ALLOCBUF) { delete[] m_info.pchBuffer; + } m_info.pchEndWrite = 0; m_info.pchEndRead = 0; @@ -95,8 +96,9 @@ MxLong MXIOINFO::Read(void* p_buf, MxLong p_len) while (p_len > 0) { if (bytesLeft > 0) { - if (p_len < bytesLeft) + if (p_len < bytesLeft) { bytesLeft = p_len; + } memcpy(p_buf, m_info.pchNext, bytesLeft); p_len -= bytesLeft; @@ -105,12 +107,14 @@ MxLong MXIOINFO::Read(void* p_buf, MxLong p_len) bytesRead += bytesLeft; } - if (p_len <= 0 || Advance(0)) + if (p_len <= 0 || Advance(0)) { break; + } bytesLeft = m_info.pchEndRead - m_info.pchNext; - if (bytesLeft <= 0) + if (bytesLeft <= 0) { break; + } } } else if (m_info.hmmio && p_len > 0) { @@ -381,8 +385,9 @@ MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU { MxU16 result = 0; - if (!p_chunkInfo) + if (!p_chunkInfo) { return MMIOERR_BASE; // ? + } if (!p_descend) { p_chunkInfo->dwFlags = 0; @@ -406,8 +411,9 @@ MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU else { MxULong ofs = MAXLONG; - if (p_parentInfo) + if (p_parentInfo) { ofs = p_parentInfo->cksize + p_parentInfo->dwDataOffset; + } BOOL running = TRUE; BOOL readOk = FALSE; @@ -452,8 +458,9 @@ MxU16 MXIOINFO::Descend(MMCKINFO* p_chunkInfo, const MMCKINFO* p_parentInfo, MxU } } - if (!result) + if (!result) { memcpy(p_chunkInfo, &tmp, sizeof(MMCKINFO)); + } } return result; diff --git a/LEGO1/mxramstreamcontroller.cpp b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp similarity index 88% rename from LEGO1/mxramstreamcontroller.cpp rename to LEGO1/omni/src/stream/mxramstreamcontroller.cpp index 0a5e29cd..b480255c 100644 --- a/LEGO1/mxramstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxramstreamcontroller.cpp @@ -6,12 +6,10 @@ DECOMP_SIZE_ASSERT(MxRAMStreamController, 0x98); -undefined* __cdecl ReadData(MxU32* p_fileSizeBuffer, MxU32 p_fileSize); - // FUNCTION: LEGO1 0x100c6110 MxResult MxRAMStreamController::Open(const char* p_filename) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); if (MxStreamController::Open(p_filename) != SUCCESS) { return FAILURE; } @@ -39,7 +37,7 @@ MxResult MxRAMStreamController::Open(const char* p_filename) // FUNCTION: LEGO1 0x100c6210 MxResult MxRAMStreamController::VTable0x20(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxS32 unk0x24 = 0; MxResult result = FAILURE; @@ -83,7 +81,7 @@ MxResult MxRAMStreamController::VTable0x24(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c63c0 MxResult MxRAMStreamController::DeserializeObject(MxDSStreamingAction& p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result; MxDSStreamingAction* value = NULL; @@ -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/mxramstreamprovider.cpp b/LEGO1/omni/src/stream/mxramstreamprovider.cpp similarity index 50% rename from LEGO1/mxramstreamprovider.cpp rename to LEGO1/omni/src/stream/mxramstreamprovider.cpp index 9c52c20e..472930c7 100644 --- a/LEGO1/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; } @@ -70,21 +71,22 @@ MxResult MxRAMStreamProvider::SetResourceToGet(MxStreamController* p_resource) path = MxString(MxOmni::GetCD()) + p_resource->GetAtom().GetInternal() + ".si"; m_pFile->SetFileName(path.GetData()); - if (m_pFile->Open(0) != 0) + if (m_pFile->Open(0) != 0) { goto done; + } } m_fileSize = m_pFile->CalcFileSize(); if (m_fileSize != 0) { m_bufferSize = m_pFile->GetBufferSize(); - m_pBufferOfFileSize = new MxU32[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(); - m_bufferForDWords = new MxU32[m_lengthInDWords * sizeof(MxU32)]; + m_bufferForDWords = new MxU32[m_lengthInDWords]; if (m_bufferForDWords != NULL) { - memcpy(m_bufferForDWords, m_pFile->GetBuffer(), m_lengthInDWords); + memcpy(m_bufferForDWords, m_pFile->GetBuffer(), m_lengthInDWords * sizeof(MxU32)); result = SUCCESS; } } @@ -96,3 +98,64 @@ 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/mxstreamchunk.cpp b/LEGO1/omni/src/stream/mxstreamchunk.cpp similarity index 52% rename from LEGO1/mxstreamchunk.cpp rename to LEGO1/omni/src/stream/mxstreamchunk.cpp index 93e76a6c..ba833186 100644 --- a/LEGO1/mxstreamchunk.cpp +++ b/LEGO1/omni/src/stream/mxstreamchunk.cpp @@ -1,7 +1,8 @@ #include "mxstreamchunk.h" -#include "legoutil.h" #include "mxdsbuffer.h" +#include "mxstreamlist.h" +#include "mxutil.h" // FUNCTION: LEGO1 0x100c2fe0 MxStreamChunk::~MxStreamChunk() @@ -48,8 +49,51 @@ MxU32 MxStreamChunk::ReadChunkHeader(MxU8* p_chunkData) return headersize; } +// FUNCTION: LEGO1 0x100c30e0 +MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, MxBool p_append, MxS16 p_obj24val) +{ + 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::c_end && m_buffer) { + m_buffer->ReleaseRef(this); + m_buffer = NULL; + } + + (*it)->AddChunk(this, p_append); + + return SUCCESS; + } + } + + return FAILURE; +} + // FUNCTION: LEGO1 0x100c3170 void MxStreamChunk::SetBuffer(MxDSBuffer* p_buffer) { m_buffer = p_buffer; } + +// FUNCTION: LEGO1 0x100c3180 +MxU16* MxStreamChunk::IntoFlags(MxU8* p_buffer) +{ + return (MxU16*) (p_buffer + 0x08); +} + +// FUNCTION: LEGO1 0x100c3190 +MxU32* MxStreamChunk::IntoObjectId(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0x0a); +} + +// FUNCTION: LEGO1 0x100c31a0 +MxLong* MxStreamChunk::IntoTime(MxU8* p_buffer) +{ + return (MxLong*) (p_buffer + 0x0e); +} + +// FUNCTION: LEGO1 0x100c31b0 +MxU32* MxStreamChunk::IntoLength(MxU8* p_buffer) +{ + return (MxU32*) (p_buffer + 0x12); +} diff --git a/LEGO1/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp similarity index 65% rename from LEGO1/mxstreamcontroller.cpp rename to LEGO1/omni/src/stream/mxstreamcontroller.cpp index 92dcfb26..977db130 100644 --- a/LEGO1/mxstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp @@ -1,12 +1,14 @@ #include "mxstreamcontroller.h" -#include "legoomni.h" -#include "legoutil.h" #include "mxautolocker.h" +#include "mxdsmultiaction.h" #include "mxdsstreamingaction.h" #include "mxnextactiondatastart.h" +#include "mxomni.h" +#include "mxstl/stlcompat.h" #include "mxstreamchunk.h" #include "mxtimer.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxStreamController, 0x64) DECOMP_SIZE_ASSERT(MxNextActionDataStart, 0x14) @@ -43,17 +45,26 @@ MxStreamController::~MxStreamController() MxAutoLocker lock(&m_criticalSection); MxDSSubscriber* subscriber; - while (m_subscriberList.PopFront(subscriber)) + while (m_subscriberList.PopFront(subscriber)) { delete subscriber; + } MxDSAction* action; - while (m_unk0x3c.PopFront(action)) + while (m_unk0x3c.PopFront(action)) { delete action; + } if (m_provider) { MxStreamProvider* provider = m_provider; m_provider = NULL; +#ifdef COMPAT_MODE + { + MxDSAction action; + provider->VTable0x20(&action); + } +#else provider->VTable0x20(&MxDSAction()); +#endif delete provider; } @@ -62,37 +73,38 @@ MxStreamController::~MxStreamController() m_unk0x2c = NULL; } - while (m_unk0x54.PopFront(action)) + while (m_unk0x54.PopFront(action)) { delete action; + } } // FUNCTION: LEGO1 0x100c1520 MxResult MxStreamController::Open(const char* p_filename) { char sourceName[256]; - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MakeSourceName(sourceName, p_filename); - this->m_atom = MxAtomId(sourceName, LookupMode_LowerCase2); + this->m_atom = MxAtomId(sourceName, e_lowerCase2); return SUCCESS; } -// STUB: LEGO1 0x100c15d0 -void MxStreamController::FUN_100c15d0(MxDSSubscriber* p_subscriber) +// FUNCTION: LEGO1 0x100c15d0 +void MxStreamController::AddSubscriber(MxDSSubscriber* p_subscriber) { - // TODO + m_subscriberList.push_back(p_subscriber); } -// STUB: LEGO1 0x100c1620 -void MxStreamController::FUN_100c1620(MxDSSubscriber* p_subscriber) +// FUNCTION: LEGO1 0x100c1620 +void MxStreamController::RemoveSubscriber(MxDSSubscriber* p_subscriber) { - // TODO + m_subscriberList.remove(p_subscriber); } // FUNCTION: LEGO1 0x100c1690 MxResult MxStreamController::VTable0x20(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result; MxU32 offset = 0; @@ -100,13 +112,16 @@ MxResult MxStreamController::VTable0x20(MxDSAction* p_action) MxS32 objectId = p_action->GetObjectId(); MxStreamProvider* provider = m_provider; - if ((MxS32) provider->GetLengthInDWords() > objectId) + if ((MxS32) provider->GetLengthInDWords() > objectId) { offset = provider->GetBufferForDWords()[objectId]; + } - if (offset) + if (offset) { result = VTable0x2c(p_action, offset); - else + } + else { result = FAILURE; + } return result; } @@ -114,7 +129,7 @@ MxResult MxStreamController::VTable0x20(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1740 MxResult MxStreamController::VTable0x24(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); VTable0x30(p_action); m_action0x60 = m_unk0x54.Find(p_action, TRUE); if (m_action0x60 == NULL) { @@ -150,16 +165,18 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) for (MxStreamListMxDSAction::iterator it = m_unk0x54.begin(); it != m_unk0x54.end(); it++) { MxDSAction* action = *it; - if (action->GetObjectId() == p_action->GetObjectId()) + if (action->GetObjectId() == p_action->GetObjectId()) { newUnknown24 = Max(newUnknown24, action->GetUnknown24()); + } } if (newUnknown24 == -1) { for (MxStreamListMxDSAction::iterator it = m_unk0x3c.begin(); it != m_unk0x3c.end(); it++) { MxDSAction* action = *it; - if (action->GetObjectId() == p_action->GetObjectId()) + if (action->GetObjectId() == p_action->GetObjectId()) { newUnknown24 = Max(newUnknown24, action->GetUnknown24()); + } } if (newUnknown24 == -1) { @@ -167,8 +184,9 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) it++) { MxDSSubscriber* subscriber = *it; - if (subscriber->GetObjectId() == p_action->GetObjectId()) + if (subscriber->GetObjectId() == p_action->GetObjectId()) { newUnknown24 = Max(newUnknown24, subscriber->GetUnknown48()); + } } } } @@ -176,14 +194,16 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) p_action->SetUnknown24(newUnknown24 + 1); } else { - if (m_unk0x3c.Find(p_action, FALSE)) + if (m_unk0x3c.Find(p_action, FALSE)) { return FAILURE; + } } MxDSStreamingAction* streamingAction = new MxDSStreamingAction(*p_action, p_offset); - if (!streamingAction) + if (!streamingAction) { return FAILURE; + } MxU32 fileSize = m_provider->GetFileSize(); streamingAction->SetBufferOffset(fileSize * (p_offset / fileSize)); @@ -199,7 +219,7 @@ MxResult MxStreamController::FUN_100c1a00(MxDSAction* p_action, MxU32 p_offset) // FUNCTION: LEGO1 0x100c1c10 MxResult MxStreamController::VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); if (FUN_100c1a00(p_action, p_bufferval) != SUCCESS) { return FAILURE; } @@ -209,11 +229,11 @@ MxResult MxStreamController::VTable0x2c(MxDSAction* p_action, MxU32 p_bufferval) // FUNCTION: LEGO1 0x100c1ce0 MxResult MxStreamController::VTable0x30(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxResult result = FAILURE; MxDSAction* action = m_unk0x3c.Find(p_action, TRUE); if (action != NULL) { - MxNextActionDataStart* data = m_nextActionList.Find(action->GetObjectId(), action->GetUnknown24()); + MxNextActionDataStart* data = m_nextActionList.FindAndErase(action->GetObjectId(), action->GetUnknown24()); delete action; delete data; result = SUCCESS; @@ -224,7 +244,7 @@ MxResult MxStreamController::VTable0x30(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1da0 MxResult MxStreamController::InsertActionToList54(MxDSAction* p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxDSAction* action = p_action->Clone(); if (action == NULL) { @@ -239,7 +259,7 @@ MxResult MxStreamController::InsertActionToList54(MxDSAction* p_action) // FUNCTION: LEGO1 0x100c1e70 MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action) { - MxAutoLocker locker(&m_criticalSection); + MxAutoLocker lock(&m_criticalSection); MxPresenter* result = NULL; if (p_action.GetObjectId() != -1) { MxDSAction* action = m_unk0x3c.Find(&p_action, FALSE); @@ -251,16 +271,64 @@ MxPresenter* MxStreamController::FUN_100c1e70(MxDSAction& p_action) return result; } -// STUB: LEGO1 0x100c1f00 +// FUNCTION: LEGO1 0x100c1f00 MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) { - // TODO - return FAILURE; + MxAutoLocker lock(&m_criticalSection); + + MxU32 objectId = p_action->GetObjectId(); + MxStreamChunk* chunk = new MxStreamChunk; + + if (!chunk) { + return FAILURE; + } + + chunk->SetFlags(MxDSChunk::c_bit3); + chunk->SetObjectId(objectId); + + if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS) { + delete chunk; + } + + if (p_action->IsA("MxDSMultiAction")) { + MxDSActionList* actions = ((MxDSMultiAction*) p_action)->GetActionList(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + while (cursor.Next(action)) { + if (FUN_100c1f00(action) != SUCCESS) { + return FAILURE; + } + } + } + + return SUCCESS; } -// STUB: LEGO1 0x100c20d0 +// FUNCTION: LEGO1 0x100c20b0 +MxNextActionDataStart* MxStreamController::FindNextActionDataStartFromStreamingAction(MxDSStreamingAction* p_action) +{ + return m_nextActionList.Find(p_action->GetObjectId(), p_action->GetUnknown24()); +} + +// FUNCTION: LEGO1 0x100c20d0 MxBool MxStreamController::FUN_100c20d0(MxDSObject& p_obj) { - // TODO + if (m_subscriberList.Find(&p_obj)) { + return FALSE; + } + + if (p_obj.IsA("MxDSMultiAction")) { + MxDSActionList* actions = ((MxDSMultiAction&) p_obj).GetActionList(); + MxDSActionListCursor cursor(actions); + MxDSAction* action; + + while (cursor.Next(action)) { + if (!FUN_100c20d0(*action)) { + return FALSE; + } + } + } + return TRUE; } diff --git a/LEGO1/mxstreamer.cpp b/LEGO1/omni/src/stream/mxstreamer.cpp similarity index 72% rename from LEGO1/mxstreamer.cpp rename to LEGO1/omni/src/stream/mxstreamer.cpp index c35a4e8f..76aa7862 100644 --- a/LEGO1/mxstreamer.cpp +++ b/LEGO1/omni/src/stream/mxstreamer.cpp @@ -1,8 +1,8 @@ #include "mxstreamer.h" -#include "legoomni.h" #include "mxdiskstreamcontroller.h" #include "mxnotificationmanager.h" +#include "mxomni.h" #include "mxramstreamcontroller.h" #include @@ -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: @@ -79,13 +79,18 @@ MxLong MxStreamer::Close(const char* p_name) if (!p_name || !strcmp(p_name, c->GetAtom().GetInternal())) { m_openStreams.erase(it); - if (!c->FUN_100c20d0(ds)) { - MxStreamerNotification notif(MXSTREAMER_DELETE_NOTIFY, NULL, c); - - NotificationManager()->Send(this, ¬if); + if (c->FUN_100c20d0(ds)) { + delete c; } else { - delete c; +#ifdef COMPAT_MODE + { + MxStreamerNotification notification(c_notificationStreamer, NULL, c); + NotificationManager()->Send(this, ¬ification); + } +#else + NotificationManager()->Send(this, &MxStreamerNotification(c_notificationStreamer, NULL, c)); +#endif } return SUCCESS; @@ -117,6 +122,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) { @@ -142,7 +156,7 @@ MxResult MxStreamer::FUN_100b99b0(MxDSAction* p_action) return FAILURE; } -// STUB: LEGO1 0x100b99f0 +// FUNCTION: LEGO1 0x100b99f0 MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) { MxDSAction tempAction; @@ -156,48 +170,52 @@ MxResult MxStreamer::DeleteObject(MxDSAction* p_dsAction) tempAction.SetUnknown24(p_dsAction->GetUnknown24()); } - // TODO: remove action from list - return FAILURE; + MxResult result = FAILURE; + for (list::iterator it = m_openStreams.begin(); it != m_openStreams.end(); it++) { + const char* id = p_dsAction->GetAtomId().GetInternal(); + if (!id || id == (*it)->GetAtom().GetInternal()) { + tempAction.SetAtomId((*it)->GetAtom()); + result = (*it)->VTable0x24(&tempAction); + } + } + + return result; } // FUNCTION: LEGO1 0x100b9b30 MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject) { MxStreamController* controller = GetOpenStream(p_dsObject.GetAtomId().GetInternal()); - if (controller) + if (controller) { return controller->FUN_100c20d0(p_dsObject); + } return TRUE; } // 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); MxStreamController* c = static_cast(p_param).GetController(); - if (!c->FUN_100c20d0(ds)) { - MxStreamerNotification notif(MXSTREAMER_DELETE_NOTIFY, NULL, c); - NotificationManager()->Send(this, ¬if); + if (c->FUN_100c20d0(ds)) { + delete c; } else { - delete c; +#ifdef COMPAT_MODE + { + MxStreamerNotification notification(c_notificationStreamer, NULL, c); + NotificationManager()->Send(this, ¬ification); + } +#else + NotificationManager()->Send(this, &MxStreamerNotification(c_notificationStreamer, NULL, c)); +#endif } } return 0; } - -// No offset, function is always inlined -MxStreamerSubClass1::MxStreamerSubClass1(undefined4 p_size) -{ - m_buffer = NULL; - m_size = p_size; - undefined4* ptr = &m_unk0x08; - for (int i = 0; i >= 0; i--) { - ptr[i] = 0; - } -} diff --git a/LEGO1/mxstreamlist.cpp b/LEGO1/omni/src/stream/mxstreamlist.cpp similarity index 51% rename from LEGO1/mxstreamlist.cpp rename to LEGO1/omni/src/stream/mxstreamlist.cpp index 1fa4dd48..effa987a 100644 --- a/LEGO1/mxstreamlist.cpp +++ b/LEGO1/omni/src/stream/mxstreamlist.cpp @@ -1,9 +1,23 @@ #include "mxstreamlist.h" // Wrappers around STL list that are used by the MxStream* classes. -DECOMP_SIZE_ASSERT(MxStreamListMxDSAction, 0xc); -DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0xc); -DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0xc); +DECOMP_SIZE_ASSERT(MxStreamListMxDSAction, 0x0c); +DECOMP_SIZE_ASSERT(MxStreamListMxNextActionDataStart, 0x0c); +DECOMP_SIZE_ASSERT(MxStreamListMxDSSubscriber, 0x0c); + +// FUNCTION: LEGO1 0x100b8450 +MxDSSubscriber* MxStreamListMxDSSubscriber::Find(MxDSObject* p_object) +{ + for (iterator it = begin(); it != end(); it++) { + if (p_object->GetObjectId() == -1 || p_object->GetObjectId() == (*it)->GetObjectId()) { + if (p_object->GetUnknown24() == -2 || p_object->GetUnknown24() == (*it)->GetUnknown48()) { + return *it; + } + } + } + + return NULL; +} // FUNCTION: LEGO1 0x100bfa80 MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) @@ -12,13 +26,19 @@ MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) MxDSAction* found = NULL; +#ifdef COMPAT_MODE + iterator it; + for (it = begin(); it != end(); it++) { +#else for (iterator it = begin(); it != end(); it++) { +#endif if (p_action->GetObjectId() == -1 || p_action->GetObjectId() == (*it)->GetObjectId()) { if (p_action->GetUnknown24() == -2 || p_action->GetUnknown24() == -3 || p_action->GetUnknown24() == (*it)->GetUnknown24()) { found = *it; - if (p_action->GetUnknown24() != -3) + if (p_action->GetUnknown24() != -3) { break; + } } } } @@ -30,8 +50,20 @@ MxDSAction* MxStreamListMxDSAction::Find(MxDSAction* p_action, MxBool p_delete) return found; } -// FUNCTION: LEGO1 0x100c2240 +// FUNCTION: LEGO1 0x100c21e0 MxNextActionDataStart* MxStreamListMxNextActionDataStart::Find(MxU32 p_id, MxS16 p_value) +{ + for (iterator it = begin(); it != end(); it++) { + if (p_id == (*it)->GetObjectId() && p_value == (*it)->GetUnknown24()) { + return *it; + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x100c2240 +MxNextActionDataStart* MxStreamListMxNextActionDataStart::FindAndErase(MxU32 p_id, MxS16 p_value) { MxNextActionDataStart* match = NULL; diff --git a/LEGO1/mxstreamprovider.cpp b/LEGO1/omni/src/stream/mxstreamprovider.cpp similarity index 100% rename from LEGO1/mxstreamprovider.cpp rename to LEGO1/omni/src/stream/mxstreamprovider.cpp diff --git a/LEGO1/mxautolocker.cpp b/LEGO1/omni/src/system/mxautolocker.cpp similarity index 79% rename from LEGO1/mxautolocker.cpp rename to LEGO1/omni/src/system/mxautolocker.cpp index d5749ad5..3c5a2afb 100644 --- a/LEGO1/mxautolocker.cpp +++ b/LEGO1/omni/src/system/mxautolocker.cpp @@ -4,13 +4,15 @@ MxAutoLocker::MxAutoLocker(MxCriticalSection* p_criticalSection) { this->m_criticalSection = p_criticalSection; - if (this->m_criticalSection != 0) + if (this->m_criticalSection != 0) { this->m_criticalSection->Enter(); + } } // FUNCTION: LEGO1 0x100b8ef0 MxAutoLocker::~MxAutoLocker() { - if (this->m_criticalSection != 0) + if (this->m_criticalSection != 0) { this->m_criticalSection->Leave(); + } } diff --git a/LEGO1/mxcriticalsection.cpp b/LEGO1/omni/src/system/mxcriticalsection.cpp similarity index 100% rename from LEGO1/mxcriticalsection.cpp rename to LEGO1/omni/src/system/mxcriticalsection.cpp diff --git a/LEGO1/mxscheduler.cpp b/LEGO1/omni/src/system/mxscheduler.cpp similarity index 100% rename from LEGO1/mxscheduler.cpp rename to LEGO1/omni/src/system/mxscheduler.cpp diff --git a/LEGO1/mxsemaphore.cpp b/LEGO1/omni/src/system/mxsemaphore.cpp similarity index 78% rename from LEGO1/mxsemaphore.cpp rename to LEGO1/omni/src/system/mxsemaphore.cpp index 18637185..daba60f4 100644 --- a/LEGO1/mxsemaphore.cpp +++ b/LEGO1/omni/src/system/mxsemaphore.cpp @@ -1,6 +1,10 @@ #include "mxsemaphore.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxSemaphore, 0x08) + // FUNCTION: LEGO1 0x100c87d0 MxSemaphore::MxSemaphore() { @@ -11,8 +15,9 @@ MxSemaphore::MxSemaphore() MxResult MxSemaphore::Init(MxU32 p_initialCount, MxU32 p_maxCount) { MxResult result = FAILURE; - if (m_hSemaphore = CreateSemaphoreA(NULL, p_initialCount, p_maxCount, NULL)) + if ((m_hSemaphore = CreateSemaphoreA(NULL, p_initialCount, p_maxCount, NULL))) { result = SUCCESS; + } return result; } diff --git a/LEGO1/mxthread.cpp b/LEGO1/omni/src/system/mxthread.cpp similarity index 87% rename from LEGO1/mxthread.cpp rename to LEGO1/omni/src/system/mxthread.cpp index 899e959e..14c4ea82 100644 --- a/LEGO1/mxthread.cpp +++ b/LEGO1/omni/src/system/mxthread.cpp @@ -1,11 +1,14 @@ - #include "mxthread.h" +#include "decomp.h" #include "mxomni.h" #include "mxtimer.h" #include +DECOMP_SIZE_ASSERT(MxThread, 0x1c) +DECOMP_SIZE_ASSERT(MxTickleThread, 0x20) + // FUNCTION: LEGO1 0x100b8bb0 MxTickleThread::MxTickleThread(MxCore* p_target, MxS32 p_frequencyMS) { @@ -48,8 +51,9 @@ MxThread::MxThread() // FUNCTION: LEGO1 0x100bf5a0 MxThread::~MxThread() { - if (m_hThread) + if (m_hThread) { CloseHandle((HANDLE) m_hThread); + } } typedef unsigned(__stdcall* ThreadFunc)(void*); @@ -59,9 +63,10 @@ MxResult MxThread::Start(MxS32 p_stack, MxS32 p_flag) { MxResult result = FAILURE; if (m_semaphore.Init(0, 1) == SUCCESS) { - if (m_hThread = - _beginthreadex(NULL, p_stack << 2, (ThreadFunc) &MxThread::ThreadProc, this, p_flag, &m_threadId)) + if ((m_hThread = + _beginthreadex(NULL, p_stack << 2, (ThreadFunc) &MxThread::ThreadProc, this, p_flag, &m_threadId))) { result = SUCCESS; + } } return result; } diff --git a/LEGO1/mxbitmap.cpp b/LEGO1/omni/src/video/mxbitmap.cpp similarity index 70% rename from LEGO1/mxbitmap.cpp rename to LEGO1/omni/src/video/mxbitmap.cpp index 0aec1a6e..98f1f6b2 100644 --- a/LEGO1/mxbitmap.cpp +++ b/LEGO1/omni/src/video/mxbitmap.cpp @@ -1,6 +1,7 @@ #include "mxbitmap.h" #include "decomp.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxBitmap, 0x20); DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428); @@ -10,28 +11,6 @@ DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428); // (1998) GLOBAL: LEGO1 0x10102184 MxU16 g_bitmapSignature = TWOCC('B', 'M'); -// Bit mask trick to round up to the nearest multiple of four. -// Pixel data may be stored with padding. -// https://learn.microsoft.com/en-us/windows/win32/medfound/image-stride -inline MxLong AlignToFourByte(MxLong p_value) -{ - return (p_value + 3) & -4; -} - -// Same as the one from legoutil.h, but flipped the other way -// TODO: While it's not outside the realm of possibility that they -// reimplemented Abs for only this file, that seems odd, right? -inline MxLong AbsFlipped(MxLong p_value) -{ - return p_value > 0 ? p_value : -p_value; -} - -// FUNCTION: LEGO1 0x1004e0d0 -int MxBitmap::VTable0x28(int) -{ - return -1; -} - // FUNCTION: LEGO1 0x100bc980 MxBitmap::MxBitmap() { @@ -46,12 +25,15 @@ MxBitmap::MxBitmap() // FUNCTION: LEGO1 0x100bca10 MxBitmap::~MxBitmap() { - if (this->m_info) + if (this->m_info) { delete m_info; - if (this->m_data) + } + if (this->m_data) { delete m_data; - if (this->m_palette) + } + if (this->m_palette) { delete m_palette; + } } // FUNCTION: LEGO1 0x100bcaa0 @@ -125,7 +107,7 @@ MxResult MxBitmap::ImportBitmapInfo(MxBITMAPINFO* p_info) } if (this->m_data) { - delete this->m_data; + delete[] this->m_data; this->m_data = NULL; } } @@ -140,16 +122,14 @@ MxResult MxBitmap::ImportBitmap(MxBitmap* p_bitmap) this->m_info = new MxBITMAPINFO; if (this->m_info) { - MxLong height = AbsFlipped(p_bitmap->m_bmiHeader->biHeight); - this->m_data = new MxU8[AlignToFourByte(p_bitmap->m_bmiHeader->biWidth) * height]; + this->m_data = new MxU8[p_bitmap->GetDataSize()]; if (this->m_data) { - memcpy(this->m_info, p_bitmap->m_info, sizeof(*this->m_info)); - height = AbsFlipped(p_bitmap->m_bmiHeader->biHeight); - memcpy(this->m_data, p_bitmap->m_data, AlignToFourByte(p_bitmap->m_bmiHeader->biWidth) * height); + memcpy(this->m_info, p_bitmap->GetBitmapInfo(), MxBITMAPINFO::Size()); + memcpy(this->m_data, p_bitmap->GetBitmapData(), p_bitmap->GetDataSize()); - result = SUCCESS; this->m_bmiHeader = &this->m_info->m_bmiHeader; this->m_paletteData = this->m_info->m_bmiColors; + result = SUCCESS; } } @@ -175,11 +155,13 @@ MxLong MxBitmap::Read(const char* p_filename) HANDLE handle = CreateFileA(p_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (handle != INVALID_HANDLE_VALUE && !LoadFile(handle)) + if (handle != INVALID_HANDLE_VALUE && !LoadFile(handle)) { result = SUCCESS; + } - if (handle) + if (handle) { CloseHandle(handle); + } return result; } @@ -231,14 +213,89 @@ MxResult MxBitmap::LoadFile(HANDLE p_handle) return result; } -// STUB: LEGO1 0x100bce70 -void MxBitmap::VTable0x2c(int, int, int, int, int, int, int) +// FUNCTION: LEGO1 0x100bce70 +void MxBitmap::BitBlt( + MxBitmap* p_src, + MxS32 p_srcLeft, + MxS32 p_srcTop, + MxS32 p_dstLeft, + MxS32 p_dstTop, + MxS32 p_width, + MxS32 p_height +) { + MxLong dstHeight = GetBmiHeightAbs(); + MxLong srcHeight = p_src->GetBmiHeightAbs(); + + if (GetRectIntersection( + p_src->GetBmiWidth(), + srcHeight, + GetBmiWidth(), + dstHeight, + &p_srcLeft, + &p_srcTop, + &p_dstLeft, + &p_dstTop, + &p_width, + &p_height + )) { + MxU8* srcStart = p_src->GetStart(p_srcLeft, p_srcTop); + MxU8* dstStart = GetStart(p_dstLeft, p_dstTop); + MxLong srcStride = p_src->GetAdjustedStride(); + MxLong dstStride = GetAdjustedStride(); + + while (p_height--) { + memcpy(dstStart, srcStart, p_width); + dstStart += dstStride; + srcStart += srcStride; + } + } } -// STUB: LEGO1 0x100bd020 -void MxBitmap::VTable0x30(int, int, int, int, int, int, int) +// FUNCTION: LEGO1 0x100bd020 +void MxBitmap::BitBltTransparent( + MxBitmap* p_src, + MxS32 p_srcLeft, + MxS32 p_srcTop, + MxS32 p_dstLeft, + MxS32 p_dstTop, + MxS32 p_width, + MxS32 p_height +) { + MxLong dstHeight = GetBmiHeightAbs(); + MxLong srcHeight = p_src->GetBmiHeightAbs(); + + if (GetRectIntersection( + p_src->GetBmiWidth(), + srcHeight, + GetBmiWidth(), + dstHeight, + &p_srcLeft, + &p_srcTop, + &p_dstLeft, + &p_dstTop, + &p_width, + &p_height + )) { + MxU8* srcStart = p_src->GetStart(p_srcLeft, p_srcTop); + MxU8* dstStart = GetStart(p_dstLeft, p_dstTop); + MxLong srcStride = p_src->GetAdjustedStride() - p_width; + MxLong dstStride = GetAdjustedStride() - p_width; + + for (MxS32 h = 0; h < p_height; h++) { + for (MxS32 w = 0; w < p_width; w++) { + if (*srcStart) { + *dstStart = *srcStart; + } + srcStart++; + dstStart++; + } + + srcStart += srcStride; + dstStart += dstStride; + } + } } // FUNCTION: LEGO1 0x100bd1c0 @@ -250,17 +307,27 @@ MxPalette* MxBitmap::CreatePalette() switch (this->m_isHighColor) { case FALSE: palette = new MxPalette(this->m_paletteData); - if (palette) - success = TRUE; - break; + if (!palette) { + goto done; + } + + break; case TRUE: palette = this->m_palette->Clone(); - if (palette) - success = TRUE; + + if (!palette) { + goto done; + } + break; + default: + goto done; } + success = TRUE; + +done: if (!success && palette) { delete palette; palette = NULL; @@ -296,40 +363,48 @@ MxResult MxBitmap::SetBitDepth(MxBool p_isHighColor) if (m_isHighColor == p_isHighColor) { // no change: do nothing. ret = SUCCESS; + goto done; } - else { - switch (p_isHighColor) { - case FALSE: - ImportColorsToPalette(m_paletteData, m_palette); - if (m_palette) - delete m_palette; - m_palette = NULL; - break; - - case TRUE: - pal = NULL; - pal = new MxPalette(m_paletteData); - if (pal) { - m_palette = pal; - - // TODO: what is this? zeroing out top half of palette? - MxU16* buf = (MxU16*) m_paletteData; - for (MxU16 i = 0; i < 256; i++) { - buf[i] = i; - } - - m_isHighColor = p_isHighColor; - ret = SUCCESS; - } - break; + switch (p_isHighColor) { + case FALSE: + ImportColorsToPalette(m_paletteData, m_palette); + if (m_palette) { + delete m_palette; } + + m_palette = NULL; + break; + case TRUE: { + pal = NULL; + pal = new MxPalette(m_paletteData); + + if (!pal) { + goto done; + } + + m_palette = pal; + + // TODO: what is this? zeroing out top half of palette? + MxU16* buf = (MxU16*) m_paletteData; + for (MxU16 i = 0; i < 256; i++) { + buf[i] = i; + } + break; + } + default: + goto done; } + m_isHighColor = p_isHighColor; + ret = SUCCESS; + +done: // If we were unsuccessful overall but did manage to alloc // the MxPalette, free it. - if (ret && pal) + if (ret && pal) { delete pal; + } return ret; } @@ -374,13 +449,15 @@ MxResult MxBitmap::ImportColorsToPalette(RGBQUAD* p_rgbquad, MxPalette* p_palett PALETTEENTRY entries[256]; if (p_palette) { - if (p_palette->GetEntries(entries)) + if (p_palette->GetEntries(entries)) { goto done; + } } else { MxPalette palette; - if (palette.GetEntries(entries)) + if (palette.GetEntries(entries)) { goto done; + } } MxS32 i; diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp new file mode 100644 index 00000000..0cb88f6d --- /dev/null +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -0,0 +1,822 @@ +#include "mxdisplaysurface.h" + +#include "mxutil.h" +#include "mxvideomanager.h" + +#include + +DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); + +// GLOBAL: LEGO1 0x1010215c +MxU32 g_unk0x1010215c = 0; + +// FUNCTION: LEGO1 0x100ba500 +MxDisplaySurface::MxDisplaySurface() +{ + this->Init(); +} + +// FUNCTION: LEGO1 0x100ba5a0 +MxDisplaySurface::~MxDisplaySurface() +{ + this->Destroy(); +} + +// FUNCTION: LEGO1 0x100ba610 +void MxDisplaySurface::Init() +{ + this->m_ddSurface1 = NULL; + this->m_ddSurface2 = NULL; + this->m_ddClipper = NULL; + this->m_16bitPal = NULL; + this->m_initialized = FALSE; + memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); +} + +// FUNCTION: LEGO1 0x100ba640 +void MxDisplaySurface::ClearScreen() +{ + MxS32 backBuffers; + DDSURFACEDESC desc; + HRESULT hr; + + if (!m_videoParam.Flags().GetFlipSurfaces()) { + backBuffers = 1; + } + else { + backBuffers = m_videoParam.GetBackBuffers() + 1; + } + + for (MxS32 i = 0; i < backBuffers; i++) { + memset(&desc, 0, sizeof(DDSURFACEDESC)); + + desc.dwSize = sizeof(DDSURFACEDESC); + hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + m_ddSurface2->Restore(); + hr = m_ddSurface2->Lock(NULL, &desc, DDLOCK_WAIT, NULL); + } + + if (hr != DD_OK) { + return; + } + + MxU8* surface = (MxU8*) desc.lpSurface; + MxS32 height = m_videoParam.GetRect().GetHeight(); + + while (height--) { + memset(surface, 0, m_videoParam.GetRect().GetWidth() * desc.ddpfPixelFormat.dwRGBBitCount / 8); + surface += desc.lPitch; + } + + m_ddSurface2->Unlock(desc.lpSurface); + if (m_videoParam.Flags().GetFlipSurfaces()) { + m_ddSurface1->Flip(NULL, DDFLIP_WAIT); + } + } +} + +// FUNCTION: LEGO1 0x100ba750 +MxU8 MxDisplaySurface::CountTotalBitsSetTo1(MxU32 p_param) +{ + MxU8 count = 0; + + for (; p_param; p_param >>= 1) { + count += ((MxU8) p_param & 1); + } + + return count; +} + +// FUNCTION: LEGO1 0x100ba770 +MxU8 MxDisplaySurface::CountContiguousBitsSetTo1(MxU32 p_param) +{ + MxU8 count = 0; + + for (; (p_param & 1) == 0; p_param >>= 1) { + count++; + } + + return count; +} + +// FUNCTION: LEGO1 0x100ba790 +MxResult MxDisplaySurface::Init( + MxVideoParam& p_videoParam, + LPDIRECTDRAWSURFACE p_ddSurface1, + LPDIRECTDRAWSURFACE p_ddSurface2, + LPDIRECTDRAWCLIPPER p_ddClipper +) +{ + MxResult result = SUCCESS; + + this->m_videoParam = p_videoParam; + this->m_ddSurface1 = p_ddSurface1; + this->m_ddSurface2 = p_ddSurface2; + this->m_ddClipper = p_ddClipper; + this->m_initialized = FALSE; + + memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); + this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc); + + if (this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) { + result = FAILURE; + } + + return result; +} + +// FUNCTION: LEGO1 0x100ba7f0 +MxResult MxDisplaySurface::Create(MxVideoParam& p_videoParam) +{ + DDSURFACEDESC ddsd; + MxResult result = FAILURE; + LPDIRECTDRAW lpDirectDraw = MVideoManager()->GetDirectDraw(); + HWND hWnd = MxOmni::GetInstance()->GetWindowHandle(); + + this->m_initialized = TRUE; + this->m_videoParam = p_videoParam; + + if (!this->m_videoParam.Flags().GetFullScreen()) { + this->m_videoParam.Flags().SetFlipSurfaces(FALSE); + } + + if (!this->m_videoParam.Flags().GetFlipSurfaces()) { + this->m_videoParam.SetBackBuffers(1); + } + else { + MxU32 backBuffers = this->m_videoParam.GetBackBuffers(); + + if (backBuffers < 1) { + this->m_videoParam.SetBackBuffers(1); + } + else if (backBuffers > 2) { + this->m_videoParam.SetBackBuffers(2); + } + + this->m_videoParam.Flags().SetBackBuffers(TRUE); + } + + if (this->m_videoParam.Flags().GetFullScreen()) { + MxS32 width = this->m_videoParam.GetRect().GetWidth(); + MxS32 height = this->m_videoParam.GetRect().GetHeight(); + + if (lpDirectDraw->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN)) { + goto done; + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (lpDirectDraw->GetDisplayMode(&ddsd)) { + goto done; + } + + MxS32 bitdepth = !this->m_videoParam.Flags().Get16Bit() ? 8 : 16; + + if (ddsd.dwWidth != width || ddsd.dwHeight != height || ddsd.ddpfPixelFormat.dwRGBBitCount != bitdepth) { + if (lpDirectDraw->SetDisplayMode(width, height, bitdepth)) { + goto done; + } + } + } + + if (this->m_videoParam.Flags().GetFlipSurfaces()) { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwBackBufferCount = this->m_videoParam.GetBackBuffers(); + ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; + + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) { + goto done; + } + + ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; + + if (this->m_ddSurface1->GetAttachedSurface(&ddsd.ddsCaps, &this->m_ddSurface2)) { + goto done; + } + } + else { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface1, NULL)) { + goto done; + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_CAPS; + ddsd.dwWidth = this->m_videoParam.GetRect().GetWidth(); + ddsd.dwHeight = this->m_videoParam.GetRect().GetHeight(); + ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE | DDSCAPS_OFFSCREENPLAIN; + + if (!this->m_videoParam.Flags().GetBackBuffers()) { + ddsd.ddsCaps.dwCaps = DDSCAPS_3DDEVICE | DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + } + + if (lpDirectDraw->CreateSurface(&ddsd, &this->m_ddSurface2, NULL)) { + goto done; + } + } + + memset(&this->m_surfaceDesc, 0, sizeof(this->m_surfaceDesc)); + this->m_surfaceDesc.dwSize = sizeof(this->m_surfaceDesc); + + if (!this->m_ddSurface2->GetSurfaceDesc(&this->m_surfaceDesc)) { + if (!lpDirectDraw->CreateClipper(0, &this->m_ddClipper, NULL) && !this->m_ddClipper->SetHWnd(0, hWnd) && + !this->m_ddSurface1->SetClipper(this->m_ddClipper)) { + result = SUCCESS; + } + } + +done: + return result; +} + +// FUNCTION: LEGO1 0x100baa90 +void MxDisplaySurface::Destroy() +{ + if (this->m_initialized) { + if (this->m_ddSurface2) { + this->m_ddSurface2->Release(); + } + + if (this->m_ddSurface1) { + this->m_ddSurface1->Release(); + } + + if (this->m_ddClipper) { + this->m_ddClipper->Release(); + } + } + + if (this->m_16bitPal) { + delete[] this->m_16bitPal; + } + + this->Init(); +} + +// FUNCTION: LEGO1 0x100baae0 +void MxDisplaySurface::SetPalette(MxPalette* p_palette) +{ + if (m_surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) { + m_ddSurface1->SetPalette(p_palette->CreateNativePalette()); + m_ddSurface2->SetPalette(p_palette->CreateNativePalette()); + + if ((m_videoParam.Flags().GetFullScreen() & 1) == 0) { + struct { + WORD m_palVersion; + WORD m_palNumEntries; + PALETTEENTRY m_palPalEntry[256]; + } lpal; + + lpal.m_palVersion = 0x300; + lpal.m_palNumEntries = 256; + + memset(lpal.m_palPalEntry, 0, sizeof(lpal.m_palPalEntry)); + p_palette->GetEntries(lpal.m_palPalEntry); + + HPALETTE hpal = CreatePalette((LPLOGPALETTE) &lpal); + HDC hdc = ::GetDC(0); + SelectPalette(hdc, hpal, FALSE); + RealizePalette(hdc); + ::ReleaseDC(NULL, hdc); + DeleteObject(hpal); + } + } + + if (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount == 16) { + if (!m_16bitPal) { + m_16bitPal = new MxU16[256]; + } + + PALETTEENTRY palette[256]; + p_palette->GetEntries(palette); + + MxU8 contiguousBitsRed = CountContiguousBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwRBitMask); + MxU8 totalBitsRed = CountTotalBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwRBitMask); + MxU8 contiguousBitsGreen = CountContiguousBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwGBitMask); + MxU8 totalBitsGreen = CountTotalBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwGBitMask); + MxU8 contiguousBitsBlue = CountContiguousBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwBBitMask); + MxU8 totalBitsBlue = CountTotalBitsSetTo1(m_surfaceDesc.ddpfPixelFormat.dwBBitMask); + + for (MxS32 i = 0; i < 256; i++) { + m_16bitPal[i] = (((palette[i].peRed >> ((8 - totalBitsRed) & 0x1f)) << (contiguousBitsRed & 0x1f))) | + (((palette[i].peGreen >> ((8 - totalBitsGreen) & 0x1f)) << (contiguousBitsGreen & 0x1f))) | + (((palette[i].peBlue >> ((8 - totalBitsBlue) & 0x1f)) << (contiguousBitsBlue & 0x1f))); + } + } +} + +// FUNCTION: LEGO1 0x100bacc0 +void MxDisplaySurface::VTable0x28( + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height +) +{ + if (GetRectIntersection( + p_bitmap->GetBmiWidth(), + p_bitmap->GetBmiHeightAbs(), + m_videoParam.GetRect().GetWidth(), + m_videoParam.GetRect().GetHeight(), + &p_left, + &p_top, + &p_right, + &p_bottom, + &p_width, + &p_height + )) { + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + HRESULT hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); + if (hr == DDERR_SURFACELOST) { + m_ddSurface2->Restore(); + hr = m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL); + } + + if (hr == DD_OK) { + MxU8* data = p_bitmap->GetStart(p_left, p_top); + + if (m_videoParam.Flags().GetF1bit3()) { + p_bottom *= 2; + p_right *= 2; + + switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch); + MxLong stride = p_bitmap->GetAdjustedStride(); + + MxLong v22 = stride - p_width; + MxLong length = ddsd.lPitch - (2 * p_width); + while (p_height--) { + MxU8* surfaceBefore = surface; + + for (MxS32 i = 0; p_width > i; i++) { + MxU8 element = *data; + *surface++ = element; + data++; + *surface++ = *(data - 1); + } + + data += v22; + surface += length; + + memcpy(surface, surfaceBefore, 2 * p_width); + surface += ddsd.lPitch; + } + break; + } + case 16: { + MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch); + MxLong stride = p_bitmap->GetAdjustedStride(); + + // TODO: Match + stride -= p_width; + MxS32 length = p_width * 4; + MxLong v62 = ddsd.lPitch - length; + MxS32 height = p_height; + MxS32 width = p_width; + MxU16* p16BitPal = m_16bitPal; + + if (stride || v62) { + while (height--) { + MxU8* surfaceBefore = surface; + + for (MxS32 i = width; i > 0; i--) { + MxU16 element = p16BitPal[*data++]; + *(MxU16*) surface = element; + surface += 2; + *(MxU16*) surface = element; + surface += 2; + } + + data += stride; + surface += v62; + + // Odd expression for the length? + memcpy(surface, surfaceBefore, 4 * ((MxU32) (4 * p_width) / 4)); + surface += ddsd.lPitch; + } + } + else { + while (height--) { + MxU8* surfaceBefore = surface; + + for (MxS32 i = width; i > 0; i--) { + MxU16 element = p16BitPal[*data++]; + *(MxU16*) surface = element; + surface += 2; + *(MxU16*) surface = element; + surface += 2; + } + + memcpy(surface, surfaceBefore, length); + surface += ddsd.lPitch; + } + } + } + } + } + else { + switch (m_surfaceDesc.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + MxU8* surface = (MxU8*) ddsd.lpSurface + p_right + (p_bottom * ddsd.lPitch); + MxLong stride = p_bitmap->GetAdjustedStride(); + + MxLong length = ddsd.lPitch; + while (p_height--) { + memcpy(surface, data, p_width); + data += stride; + surface += length; + } + break; + } + case 16: { + MxU8* surface = (MxU8*) ddsd.lpSurface + (2 * p_right) + (p_bottom * ddsd.lPitch); + MxLong stride = p_bitmap->GetAdjustedStride(); + + MxLong v50 = stride - p_width; + MxLong length = ddsd.lPitch - (2 * p_width); + for (MxS32 i = 0; p_height > i; i++) { + for (MxS32 j = 0; p_width > j; j++) { + *(MxU16*) surface = m_16bitPal[*data++]; + surface += 2; + } + + data += v50; + surface += length; + } + } + } + } + + m_ddSurface2->Unlock(ddsd.lpSurface); + } + } +} + +// STUB: LEGO1 0x100bb1d0 +MxBool MxDisplaySurface::VTable0x30( + MxBitmap* p_bitmap, + MxS32 p_left, + MxS32 p_top, + MxS32 p_right, + MxS32 p_bottom, + MxS32 p_width, + MxS32 p_height, + MxBool +) +{ + return 0; +} + +// STUB: LEGO1 0x100bb850 +undefined4 MxDisplaySurface::VTable0x34(undefined4, undefined4, undefined4, undefined4, undefined4, undefined4) +{ + return 0; +} + +// FUNCTION: LEGO1 0x100bba50 +void MxDisplaySurface::Display(MxS32 p_left, MxS32 p_top, MxS32 p_left2, MxS32 p_top2, MxS32 p_width, MxS32 p_height) +{ + if (m_videoParam.Flags().GetF2bit1()) { + if (m_videoParam.Flags().GetFlipSurfaces()) { + if (g_unk0x1010215c < 2) { + g_unk0x1010215c++; + + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + if (m_ddSurface2->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) == DD_OK) { + MxU8* surface = (MxU8*) ddsd.lpSurface; + MxS32 height = m_videoParam.GetRect().GetHeight(); + + for (MxU32 i = 0; i < ddsd.dwHeight; i++) { + memset(surface, 0, ddsd.dwWidth * ddsd.ddpfPixelFormat.dwRGBBitCount / 8); + surface += ddsd.lPitch; + } + + m_ddSurface2->Unlock(ddsd.lpSurface); + } + else { + OutputDebugString("MxDisplaySurface::Display error\n"); + } + } + m_ddSurface1->Flip(NULL, DDFLIP_WAIT); + } + else { + POINT point = {0, 0}; + ClientToScreen(MxOmni::GetInstance()->GetWindowHandle(), &point); + + // TODO: Match + RECT rect1, rect2; + rect1.left = p_left2 + m_videoParam.GetRect().GetLeft() + point.x; + rect2.left = p_left; + rect1.top = p_top2 + m_videoParam.GetRect().GetTop() + point.y; + rect2.right = p_left + p_width; + rect2.top = p_top; + rect2.bottom = p_top + p_height; + rect1.right = rect1.left + p_width; + rect1.bottom = rect1.top + p_height; + + DDBLTFX data; + memset(&data, 0, sizeof(data)); + data.dwSize = sizeof(data); + data.dwDDFX = 8; + + if (m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data) == DDERR_SURFACELOST) { + m_ddSurface1->Restore(); + m_ddSurface1->Blt(&rect1, m_ddSurface2, &rect2, 0, &data); + } + } + } +} + +// FUNCTION: LEGO1 0x100bbc10 +void MxDisplaySurface::GetDC(HDC* p_hdc) +{ + if (this->m_ddSurface2 && !this->m_ddSurface2->GetDC(p_hdc)) { + return; + } + + *p_hdc = NULL; +} + +// FUNCTION: LEGO1 0x100bbc40 +void MxDisplaySurface::ReleaseDC(HDC p_hdc) +{ + if (this->m_ddSurface2 && p_hdc) { + this->m_ddSurface2->ReleaseDC(p_hdc); + } +} + +// FUNCTION: LEGO1 0x100bbc60 +LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( + MxBitmap* p_bitmap, + undefined4* p_ret, + undefined4 p_doNotWriteToSurface, + undefined4 p_transparent +) +{ + LPDIRECTDRAWSURFACE surface = NULL; + LPDIRECTDRAW draw = MVideoManager()->GetDirectDraw(); + MVideoManager(); + + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (draw->GetDisplayMode(&ddsd)) { + return NULL; + } + + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + ddsd.dwWidth = p_bitmap->GetBmiWidth(); + ddsd.dwHeight = p_bitmap->GetBmiHeightAbs(); + + *p_ret = 0; + ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; + + if (draw->CreateSurface(&ddsd, &surface, NULL) != DD_OK) { + if (*p_ret) { + *p_ret = 0; + + // Try creating bitmap surface in vram if system ram ran out + ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + + if (draw->CreateSurface(&ddsd, &surface, NULL) != DD_OK) { + surface = NULL; + } + } + else { + surface = NULL; + } + } + + if (surface) { + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (surface->Lock(NULL, &ddsd, DDLOCK_WAIT, 0) != DD_OK) { + surface->Release(); + surface = NULL; + goto done; + } + + if (p_doNotWriteToSurface) { + goto done; + } + + MxU8* bitmapSrcPtr = p_bitmap->GetStart(0, 0); + MxU16* surfaceData = (MxU16*) ddsd.lpSurface; + MxLong widthNormal = p_bitmap->GetBmiWidth(); + MxLong heightAbs = p_bitmap->GetBmiHeightAbs(); + + // TODO: Probably p_bitmap->GetAdjustedStride() + MxS32 rowSeek = p_bitmap->GetBmiStride(); + if (p_bitmap->GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap->GetBmiHeight() >= 0) { + rowSeek = -rowSeek; + } + + MxLong newPitch = ddsd.lPitch; + switch (ddsd.ddpfPixelFormat.dwRGBBitCount) { + case 8: { + for (MxS32 y = heightAbs; y > 0; y--) { + memcpy(surfaceData, bitmapSrcPtr, p_bitmap->GetBmiHeight()); + bitmapSrcPtr += rowSeek; + surfaceData = (MxU16*) ((MxU8*) surfaceData + newPitch); + } + + surface->Unlock(ddsd.lpSurface); + + if (p_transparent && surface) { + DDCOLORKEY key; + key.dwColorSpaceHighValue = 0; + key.dwColorSpaceLowValue = 0; + surface->SetColorKey(DDCKEY_SRCBLT, &key); + } + break; + } + case 16: + if (m_16bitPal == NULL) { + if (surface) { + surface->Release(); + } + return NULL; + } + else { + rowSeek -= p_bitmap->GetBmiWidth(); + newPitch -= 2 * p_bitmap->GetBmiWidth(); + + if (p_transparent) { + for (MxS32 y = heightAbs; y > 0; y--) { + for (MxS32 x = widthNormal; x > 0; x--) { + if (*bitmapSrcPtr) { + *surfaceData = m_16bitPal[*bitmapSrcPtr]; + } + else { + *surfaceData = 31775; + } + bitmapSrcPtr++; + surfaceData++; + } + + bitmapSrcPtr += rowSeek; + surfaceData = (MxU16*) ((MxU8*) surfaceData + newPitch); + } + + DDCOLORKEY key; + key.dwColorSpaceHighValue = 31775; + key.dwColorSpaceLowValue = 31775; + surface->SetColorKey(DDCKEY_SRCBLT, &key); + } + else { + for (MxS32 y = heightAbs; y > 0; y--) { + for (MxS32 x = widthNormal; x > 0; x--) { + *surfaceData++ = m_16bitPal[*bitmapSrcPtr++]; + } + + bitmapSrcPtr += rowSeek; + surfaceData = (MxU16*) ((MxU8*) surfaceData + newPitch); + } + } + + surface->Unlock(ddsd.lpSurface); + } + } + } + +done: + return surface; +} + +// STUB: LEGO1 0x100bbfb0 +LPDIRECTDRAWSURFACE MxDisplaySurface::FUN_100bbfb0(LPDIRECTDRAWSURFACE p_und) +{ + // TODO + return NULL; +} + +// FUNCTION: LEGO1 0x100bc070 +LPDIRECTDRAWSURFACE MxDisplaySurface::CreateCursorSurface() +{ + LPDIRECTDRAWSURFACE newSurface = NULL; + IDirectDraw* draw = MVideoManager()->GetDirectDraw(); + MVideoManager(); + + DDSURFACEDESC ddsd; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (draw->GetDisplayMode(&ddsd) != DD_OK) { + return NULL; + } + + if (ddsd.ddpfPixelFormat.dwRGBBitCount != 16) { + return NULL; + } + + ddsd.dwWidth = 16; + ddsd.dwHeight = 16; + ddsd.dwFlags = DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN; + + if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) { + ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY; + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + + if (draw->CreateSurface(&ddsd, &newSurface, NULL) != DD_OK) { + goto done; + } + } + + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + if (newSurface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK) { + goto done; + } + else { + MxU16* surface = (MxU16*) ddsd.lpSurface; + MxLong pitch = ddsd.lPitch; + + // draw a simple cursor to the surface + for (MxS32 x = 0; x < 16; x++) { + MxU16* surface2 = surface; + for (MxS32 y = 0; y < 16; y++) { + if ((y > 10 || x) && (x > 10 || y) && x + y != 10) { + if (x + y > 10) { + *surface2 = 31775; + } + else { + *surface2 = -1; + } + } + else { + *surface2 = 0; + } + surface2++; + } + surface = (MxU16*) ((MxU8*) surface + pitch); + } + + newSurface->Unlock(ddsd.lpSurface); + DDCOLORKEY colorkey; + colorkey.dwColorSpaceHighValue = 31775; + colorkey.dwColorSpaceLowValue = 31775; + newSurface->SetColorKey(DDCKEY_SRCBLT, &colorkey); + + return newSurface; + } + +done: + if (newSurface) { + newSurface->Release(); + } + + return NULL; +} + +// STUB: LEGO1 0x100bc200 +void MxDisplaySurface::VTable0x24( + LPDDSURFACEDESC, + MxBitmap*, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4 +) +{ +} + +// STUB: LEGO1 0x100bc630 +MxBool MxDisplaySurface::VTable0x2c( + LPDDSURFACEDESC, + MxBitmap*, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + undefined4, + MxBool +) +{ + return 0; +} diff --git a/LEGO1/omni/src/video/mxflcpresenter.cpp b/LEGO1/omni/src/video/mxflcpresenter.cpp new file mode 100644 index 00000000..5cc4ee6a --- /dev/null +++ b/LEGO1/omni/src/video/mxflcpresenter.cpp @@ -0,0 +1,83 @@ +#include "mxflcpresenter.h" + +#include "decomp.h" +#include "mxbitmap.h" +#include "mxdsmediaaction.h" +#include "mxomni.h" +#include "mxpalette.h" +#include "mxvideomanager.h" + +DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); + +// FUNCTION: LEGO1 0x100b3310 +MxFlcPresenter::MxFlcPresenter() +{ + m_flcHeader = NULL; + SetBit1(FALSE); + SetBit2(FALSE); +} + +// FUNCTION: LEGO1 0x100b3420 +MxFlcPresenter::~MxFlcPresenter() +{ + if (this->m_flcHeader) { + delete this->m_flcHeader; + } +} + +// FUNCTION: LEGO1 0x100b3490 +void MxFlcPresenter::LoadHeader(MxStreamChunk* p_chunk) +{ + m_flcHeader = (FLIC_HEADER*) new MxU8[p_chunk->GetLength()]; + memcpy(m_flcHeader, p_chunk->GetData(), p_chunk->GetLength()); +} + +// FUNCTION: LEGO1 0x100b34d0 +void MxFlcPresenter::CreateBitmap() +{ + if (m_bitmap) { + delete m_bitmap; + } + + m_bitmap = new MxBitmap; + m_bitmap->SetSize(m_flcHeader->width, m_flcHeader->height, NULL, FALSE); +} + +// FUNCTION: LEGO1 0x100b3570 +void MxFlcPresenter::LoadFrame(MxStreamChunk* p_chunk) +{ + MxU8* data = p_chunk->GetData(); + + MxS32 rectCount = *(MxS32*) data; + data += sizeof(MxS32); + + MxRect32* rects = (MxRect32*) data; + data += rectCount * sizeof(MxRect32); + + MxBool decodedColorMap; + DecodeFLCFrame( + &m_bitmap->GetBitmapInfo()->m_bmiHeader, + m_bitmap->GetBitmapData(), + m_flcHeader, + data, + &decodedColorMap + ); + + if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && decodedColorMap) { + RealizePalette(); + } + + for (MxS32 i = 0; i < rectCount; i++) { + MxRect32 rect(rects[i]); + rect.AddPoint(m_location); + MVideoManager()->InvalidateRect(rect); + } +} + +// FUNCTION: LEGO1 0x100b3620 +void MxFlcPresenter::RealizePalette() +{ + MxPalette* palette = m_bitmap->CreatePalette(); + MVideoManager()->RealizePalette(palette); + delete palette; +} diff --git a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp new file mode 100644 index 00000000..6d70842c --- /dev/null +++ b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp @@ -0,0 +1,134 @@ +#include "mxloopingflcpresenter.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxLoopingFlcPresenter, 0x6c); + +// FUNCTION: LEGO1 0x100b4310 +MxLoopingFlcPresenter::MxLoopingFlcPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x100b43b0 +MxLoopingFlcPresenter::~MxLoopingFlcPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x100b4410 +void MxLoopingFlcPresenter::Init() +{ + this->m_elapsedDuration = 0; + SetBit1(FALSE); + SetBit2(FALSE); +} + +// FUNCTION: LEGO1 0x100b4430 +void MxLoopingFlcPresenter::Destroy(MxBool p_fromDestructor) +{ + m_criticalSection.Enter(); + Init(); + m_criticalSection.Leave(); + + if (!p_fromDestructor) { + MxFlcPresenter::Destroy(FALSE); + } +} + +// FUNCTION: LEGO1 0x100b4470 +void MxLoopingFlcPresenter::NextFrame() +{ + MxStreamChunk* chunk = NextChunk(); + + if (chunk->GetFlags() & MxDSChunk::c_end) { + ProgressTickleState(e_repeating); + } + else { + LoadFrame(chunk); + LoopChunk(chunk); + m_elapsedDuration += m_flcHeader->speed; + } + + m_subscriber->DestroyChunk(chunk); +} + +// FUNCTION: LEGO1 0x100b44c0 +void MxLoopingFlcPresenter::VTable0x88() +{ + if (m_action->GetDuration() < m_elapsedDuration) { + ProgressTickleState(e_unk5); + } + else { + MxStreamChunk* chunk; + m_loopingChunkCursor->Current(chunk); + LoadFrame(chunk); + m_elapsedDuration += m_flcHeader->speed; + } +} + +// FUNCTION: LEGO1 0x100b4520 +void MxLoopingFlcPresenter::RepeatingTickle() +{ + for (MxS16 i = 0; i < m_unk0x5c; i++) { + if (!m_loopingChunkCursor->HasMatch()) { + MxStreamChunk* chunk; + MxStreamChunkListCursor cursor(m_loopingChunks); + + cursor.Last(chunk); + MxLong time = chunk->GetTime(); + + cursor.First(chunk); + + time -= chunk->GetTime(); + time += m_flcHeader->speed; + + cursor.Reset(); + while (cursor.Next(chunk)) { + chunk->SetTime(chunk->GetTime() + time); + } + + m_loopingChunkCursor->Next(); + } + + MxStreamChunk* chunk; + m_loopingChunkCursor->Current(chunk); + + if (m_action->GetElapsedTime() < chunk->GetTime()) { + break; + } + + VTable0x88(); + + m_loopingChunkCursor->Next(chunk); + + if (m_currentTickleState != e_repeating) { + break; + } + } +} + +// FUNCTION: LEGO1 0x100b4860 +MxResult MxLoopingFlcPresenter::AddToManager() +{ + MxResult result = FAILURE; + MxBool locked = FALSE; + + if (MxFlcPresenter::AddToManager() == SUCCESS) { + m_criticalSection.Enter(); + locked = TRUE; + result = SUCCESS; + } + + if (locked) { + m_criticalSection.Leave(); + } + + return result; +} + +// FUNCTION: LEGO1 0x100b48a0 +void MxLoopingFlcPresenter::Destroy() +{ + Destroy(FALSE); +} diff --git a/LEGO1/mxloopingsmkpresenter.cpp b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp similarity index 73% rename from LEGO1/mxloopingsmkpresenter.cpp rename to LEGO1/omni/src/video/mxloopingsmkpresenter.cpp index b000c835..2f4a5087 100644 --- a/LEGO1/mxloopingsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp @@ -20,9 +20,9 @@ MxLoopingSmkPresenter::~MxLoopingSmkPresenter() // FUNCTION: LEGO1 0x100b49b0 void MxLoopingSmkPresenter::Init() { - this->m_elapsedDuration = 0; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; + m_elapsedDuration = 0; + SetBit1(FALSE); + SetBit2(FALSE); } // FUNCTION: LEGO1 0x100b49d0 @@ -32,8 +32,9 @@ void MxLoopingSmkPresenter::Destroy(MxBool p_fromDestructor) Init(); m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxSmkPresenter::Destroy(); + } } // FUNCTION: LEGO1 0x100b4a00 @@ -51,29 +52,27 @@ void MxLoopingSmkPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + if (chunk->GetFlags() & MxDSChunk::c_end) { + ProgressTickleState(e_repeating); } else { LoadFrame(chunk); - AppendChunk(chunk); + LoopChunk(chunk); m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); } - m_subscriber->FUN_100b8390(chunk); + m_subscriber->DestroyChunk(chunk); } // FUNCTION: LEGO1 0x100b4a90 void MxLoopingSmkPresenter::VTable0x8c() { if (m_action->GetDuration() < m_elapsedDuration) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; + ProgressTickleState(e_unk5); } else { MxStreamChunk* chunk; - m_cursor->Current(chunk); + m_loopingChunkCursor->Current(chunk); LoadFrame(chunk); m_elapsedDuration += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); } @@ -83,9 +82,9 @@ void MxLoopingSmkPresenter::VTable0x8c() void MxLoopingSmkPresenter::RepeatingTickle() { for (MxS16 i = 0; i < m_unk0x5c; i++) { - if (!m_cursor->HasMatch()) { + if (!m_loopingChunkCursor->HasMatch()) { MxStreamChunk* chunk; - MxStreamChunkListCursor cursor(m_chunks); + MxStreamChunkListCursor cursor(m_loopingChunks); cursor.Last(chunk); MxLong time = chunk->GetTime(); @@ -96,24 +95,27 @@ void MxLoopingSmkPresenter::RepeatingTickle() time += 1000 / ((MxDSMediaAction*) m_action)->GetFramesPerSecond(); cursor.Reset(); - while (cursor.Next(chunk)) + while (cursor.Next(chunk)) { chunk->SetTime(chunk->GetTime() + time); + } - m_cursor->Advance(); + m_loopingChunkCursor->Next(); } MxStreamChunk* chunk; - m_cursor->Current(chunk); + m_loopingChunkCursor->Current(chunk); - if (m_action->GetElapsedTime() < chunk->GetTime()) + if (m_action->GetElapsedTime() < chunk->GetTime()) { break; + } VTable0x8c(); - m_cursor->Next(chunk); + m_loopingChunkCursor->Next(chunk); - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) { break; + } } } diff --git a/LEGO1/mxpalette.cpp b/LEGO1/omni/src/video/mxpalette.cpp similarity index 96% rename from LEGO1/mxpalette.cpp rename to LEGO1/omni/src/video/mxpalette.cpp index 6d4f0306..76b9a779 100644 --- a/LEGO1/mxpalette.cpp +++ b/LEGO1/omni/src/video/mxpalette.cpp @@ -4,7 +4,6 @@ #include "mxvideomanager.h" // GLOBAL: LEGO1 0x10102188 -// SIZE 0x400 PALETTEENTRY g_defaultPaletteEntries[256] = { {0u, 0u, 0u, 0u}, {128u, 0u, 0u, 0u}, {0u, 128u, 0u, 0u}, {128u, 128u, 0u, 0u}, {0u, 0u, 128u, 0u}, {128u, 0u, 128u, 0u}, {0u, 128u, 128u, 0u}, {128u, 128u, 128u, 0u}, @@ -111,18 +110,23 @@ LPDIRECTDRAWPALETTE MxPalette::CreateNativePalette() { MxS32 i; if (this->m_palette == NULL) { - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { this->m_entries[i].peFlags = 0x80; - for (i = 10; i < 136; i++) + } + for (i = 10; i < 136; i++) { this->m_entries[i].peFlags = 0x44; - for (i = 136; i < 140; i++) + } + for (i = 136; i < 140; i++) { this->m_entries[i].peFlags = 0x84; + } this->m_entries[140].peFlags = 0x84; this->m_entries[141].peFlags = 0x44; - for (i = 142; i < 246; i++) + for (i = 142; i < 246; i++) { this->m_entries[i].peFlags = 0x84; - for (i = 246; i < 256; i++) + } + for (i = 246; i < 256; i++) { this->m_entries[i].peFlags = 0x80; + } if (MVideoManager() && MVideoManager()->GetDirectDraw()) { MVideoManager()->GetDirectDraw()->CreatePalette(4, this->m_entries, &this->m_palette, NULL); @@ -155,8 +159,9 @@ MxResult MxPalette::SetEntries(LPPALETTEENTRY p_entries) MxResult status = SUCCESS; if (this->m_palette) { - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) { this->m_entries[i].peFlags = 0x80; + } for (i = 10; i < 136; i++) { this->m_entries[i].peFlags = 68; this->m_entries[i].peRed = p_entries[i].peRed; @@ -187,11 +192,13 @@ MxResult MxPalette::SetEntries(LPPALETTEENTRY p_entries) this->m_entries[i].peBlue = p_entries[i].peBlue; } - for (i = 246; i < 256; i++) + for (i = 246; i < 256; i++) { this->m_entries[i].peFlags = 0x80; + } - if (this->m_palette->SetEntries(0, 0, 256, this->m_entries)) + if (this->m_palette->SetEntries(0, 0, 256, this->m_entries)) { status = FAILURE; + } } return status; @@ -223,12 +230,15 @@ void MxPalette::Detach() MxBool MxPalette::operator==(MxPalette& p_other) { for (MxS32 i = 0; i < 256; i++) { - if (this->m_entries[i].peRed != p_other.m_entries[i].peRed) + if (this->m_entries[i].peRed != p_other.m_entries[i].peRed) { return FALSE; - if (this->m_entries[i].peGreen != p_other.m_entries[i].peGreen) + } + if (this->m_entries[i].peGreen != p_other.m_entries[i].peGreen) { return FALSE; - if (this->m_entries[i].peBlue != p_other.m_entries[i].peBlue) + } + if (this->m_entries[i].peBlue != p_other.m_entries[i].peBlue) { return FALSE; + } } return TRUE; } diff --git a/LEGO1/mxregion.cpp b/LEGO1/omni/src/video/mxregion.cpp similarity index 87% rename from LEGO1/mxregion.cpp rename to LEGO1/omni/src/video/mxregion.cpp index f003aceb..ca3698e9 100644 --- a/LEGO1/mxregion.cpp +++ b/LEGO1/omni/src/video/mxregion.cpp @@ -9,7 +9,7 @@ DECOMP_SIZE_ASSERT(MxRegionLeftRight, 0x08); // FUNCTION: LEGO1 0x100c31c0 MxRegion::MxRegion() { - m_list = new MxRegionList; + m_list = new MxRegionTopBottomList; m_rect = MxRect32(INT_MAX, INT_MAX, -1, -1); } @@ -22,8 +22,9 @@ MxBool MxRegion::VTable0x20() // FUNCTION: LEGO1 0x100c3690 MxRegion::~MxRegion() { - if (m_list) + if (m_list) { delete m_list; + } } // FUNCTION: LEGO1 0x100c3700 @@ -38,7 +39,7 @@ void MxRegion::VTable0x18(MxRect32& p_rect) { MxRect32 rect(p_rect); MxRect32 newRect; - MxRegionListCursor cursor(m_list); + MxRegionTopBottomListCursor cursor(m_list); MxRegionTopBottom* topBottom; while (rect.IsValid() && cursor.Next(topBottom)) { @@ -88,17 +89,20 @@ void MxRegion::VTable0x18(MxRect32& p_rect) // FUNCTION: LEGO1 0x100c3e20 MxBool MxRegion::VTable0x1c(MxRect32& p_rect) { - if (!m_rect.IntersectsWith(p_rect)) + if (!m_rect.IntersectsWith(p_rect)) { return FALSE; + } - MxRegionListCursor cursor(m_list); + MxRegionTopBottomListCursor cursor(m_list); MxRegionTopBottom* topBottom; while (cursor.Next(topBottom)) { - if (topBottom->GetTop() >= p_rect.GetBottom()) + if (topBottom->GetTop() >= p_rect.GetBottom()) { return FALSE; - if (topBottom->GetBottom() > p_rect.GetTop() && topBottom->FUN_100c57b0(p_rect)) + } + if (topBottom->GetBottom() > p_rect.GetTop() && topBottom->FUN_100c57b0(p_rect)) { return TRUE; + } } return FALSE; @@ -130,27 +134,31 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right) MxRegionLeftRightListCursor b(m_leftRightList); MxRegionLeftRight* leftRight; - while (a.Next(leftRight) && leftRight->GetRight() < p_left) + while (a.Next(leftRight) && leftRight->GetRight() < p_left) { ; + } if (!a.HasMatch()) { MxRegionLeftRight* copy = new MxRegionLeftRight(p_left, p_right); m_leftRightList->Append(copy); } else { - if (p_left > leftRight->GetLeft()) + if (p_left > leftRight->GetLeft()) { p_left = leftRight->GetLeft(); + } while (leftRight->GetLeft() < p_right) { - if (p_right < leftRight->GetRight()) + if (p_right < leftRight->GetRight()) { p_right = leftRight->GetRight(); + } b = a; - b.Advance(); + b.Next(); a.Destroy(); - if (!b.Current(leftRight)) + if (!b.Current(leftRight)) { break; + } a = b; } @@ -174,8 +182,9 @@ MxRegionTopBottom* MxRegionTopBottom::Clone() MxRegionLeftRightListCursor cursor(m_leftRightList); MxRegionLeftRight* leftRight; - while (cursor.Next(leftRight)) + while (cursor.Next(leftRight)) { clone->m_leftRightList->Append(leftRight->Clone()); + } return clone; } @@ -187,10 +196,12 @@ MxBool MxRegionTopBottom::FUN_100c57b0(MxRect32& p_rect) MxRegionLeftRight* leftRight; while (cursor.Next(leftRight)) { - if (p_rect.GetRight() <= leftRight->GetLeft()) + if (p_rect.GetRight() <= leftRight->GetLeft()) { return FALSE; - if (leftRight->GetRight() > p_rect.GetLeft()) + } + if (leftRight->GetRight() > p_rect.GetLeft()) { return TRUE; + } } return FALSE; diff --git a/LEGO1/omni/src/video/mxregioncursor.cpp b/LEGO1/omni/src/video/mxregioncursor.cpp new file mode 100644 index 00000000..6b74ee3f --- /dev/null +++ b/LEGO1/omni/src/video/mxregioncursor.cpp @@ -0,0 +1,297 @@ +#include "mxregioncursor.h" + +DECOMP_SIZE_ASSERT(MxRegionCursor, 0x18); + +// FUNCTION: LEGO1 0x100c3f70 +MxRegionCursor::MxRegionCursor(MxRegion* p_region) +{ + m_region = p_region; + m_rect = NULL; + m_topBottomCursor = new MxRegionTopBottomListCursor(m_region->m_list); + m_leftRightCursor = NULL; +} + +// FUNCTION: LEGO1 0x100c40b0 +MxRegionCursor::~MxRegionCursor() +{ + if (m_rect) { + delete m_rect; + } + + if (m_topBottomCursor) { + delete m_topBottomCursor; + } + + if (m_leftRightCursor) { + delete m_leftRightCursor; + } +} + +// FUNCTION: LEGO1 0x100c4140 +MxRect32* MxRegionCursor::VTable0x18() +{ + m_topBottomCursor->Head(); + + MxRegionTopBottom* topBottom; + if (m_topBottomCursor->Current(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + m_leftRightCursor->First(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + } + else { + Reset(); + } + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c41d0 +MxRect32* MxRegionCursor::VTable0x20() +{ + m_topBottomCursor->Tail(); + + MxRegionTopBottom* topBottom; + if (m_topBottomCursor->Current(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + m_leftRightCursor->Last(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + } + else { + Reset(); + } + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4260 +MxRect32* MxRegionCursor::VTable0x28() +{ + MxRegionLeftRight* leftRight; + MxRegionTopBottom* topBottom; + + if (m_leftRightCursor && m_leftRightCursor->Next(leftRight)) { + m_topBottomCursor->Current(topBottom); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + if (m_topBottomCursor->Next(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + m_leftRightCursor->First(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + Reset(); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4360 +MxRect32* MxRegionCursor::VTable0x30() +{ + MxRegionLeftRight* leftRight; + MxRegionTopBottom* topBottom; + + if (m_leftRightCursor && m_leftRightCursor->Prev(leftRight)) { + m_topBottomCursor->Current(topBottom); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + if (m_topBottomCursor->Prev(topBottom)) { + FUN_100c46c0(*topBottom->m_leftRightList); + m_leftRightCursor->Last(leftRight); + + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + return m_rect; + } + + Reset(); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4460 +MxRect32* MxRegionCursor::VTable0x14(MxRect32& p_rect) +{ + m_topBottomCursor->Reset(); + FUN_100c4a20(p_rect); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4480 +MxRect32* MxRegionCursor::VTable0x1c(MxRect32& p_rect) +{ + m_topBottomCursor->Reset(); + FUN_100c4b50(p_rect); + return m_rect; +} + +// FUNCTION: LEGO1 0x100c44a0 +MxRect32* MxRegionCursor::VTable0x24(MxRect32& p_rect) +{ + MxRegionLeftRight* leftRight; + + if (m_leftRightCursor && m_leftRightCursor->Next(leftRight)) { + MxRegionTopBottom* topBottom; + + m_topBottomCursor->Current(topBottom); + + if (topBottom->IntersectsWith(p_rect) && leftRight->IntersectsWith(p_rect)) { + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + m_rect->Intersect(p_rect); + } + else { + FUN_100c4a20(p_rect); + } + } + else { + FUN_100c4a20(p_rect); + } + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4590 +MxRect32* MxRegionCursor::VTable0x2c(MxRect32& p_rect) +{ + MxRegionLeftRight* leftRight; + + if (m_leftRightCursor && m_leftRightCursor->Prev(leftRight)) { + MxRegionTopBottom* topBottom; + + m_topBottomCursor->Current(topBottom); + + if (topBottom->IntersectsWith(p_rect) && leftRight->IntersectsWith(p_rect)) { + UpdateRect(leftRight->GetLeft(), topBottom->GetTop(), leftRight->GetRight(), topBottom->GetBottom()); + m_rect->Intersect(p_rect); + } + else { + FUN_100c4b50(p_rect); + } + } + else { + FUN_100c4b50(p_rect); + } + + return m_rect; +} + +// FUNCTION: LEGO1 0x100c4680 +void MxRegionCursor::Reset() +{ + if (m_rect) { + delete m_rect; + m_rect = NULL; + } + + m_topBottomCursor->Reset(); + + if (m_leftRightCursor) { + delete m_leftRightCursor; + m_leftRightCursor = NULL; + } +} + +// FUNCTION: LEGO1 0x100c46c0 +void MxRegionCursor::FUN_100c46c0(MxRegionLeftRightList& p_leftRightList) +{ + if (m_leftRightCursor) { + delete m_leftRightCursor; + } + + m_leftRightCursor = new MxRegionLeftRightListCursor(&p_leftRightList); +} + +// FUNCTION: LEGO1 0x100c4980 +void MxRegionCursor::UpdateRect(MxS32 p_left, MxS32 p_top, MxS32 p_right, MxS32 p_bottom) +{ + if (!m_rect) { + m_rect = new MxRect32; + } + + m_rect->SetLeft(p_left); + m_rect->SetTop(p_top); + m_rect->SetRight(p_right); + m_rect->SetBottom(p_bottom); +} + +// FUNCTION: LEGO1 0x100c4a20 +void MxRegionCursor::FUN_100c4a20(MxRect32& p_rect) +{ + MxRegionTopBottom* topBottom; + while (m_topBottomCursor->Next(topBottom)) { + if (p_rect.GetBottom() <= topBottom->GetTop()) { + Reset(); + return; + } + + if (p_rect.GetTop() < topBottom->GetBottom()) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + while (m_leftRightCursor->Next(leftRight)) { + if (p_rect.GetRight() <= leftRight->GetLeft()) { + break; + } + + if (p_rect.GetLeft() < leftRight->GetRight()) { + UpdateRect( + leftRight->GetLeft(), + topBottom->GetTop(), + leftRight->GetRight(), + topBottom->GetBottom() + ); + m_rect->Intersect(p_rect); + return; + } + } + } + } + + Reset(); +} + +// FUNCTION: LEGO1 0x100c4b50 +void MxRegionCursor::FUN_100c4b50(MxRect32& p_rect) +{ + MxRegionTopBottom* topBottom; + while (m_topBottomCursor->Prev(topBottom)) { + if (topBottom->GetBottom() <= p_rect.GetTop()) { + Reset(); + return; + } + + if (topBottom->GetTop() < p_rect.GetBottom()) { + FUN_100c46c0(*topBottom->m_leftRightList); + + MxRegionLeftRight* leftRight; + while (m_leftRightCursor->Prev(leftRight)) { + if (leftRight->GetRight() <= p_rect.GetLeft()) { + break; + } + + if (leftRight->GetLeft() < p_rect.GetRight()) { + UpdateRect( + leftRight->GetLeft(), + topBottom->GetTop(), + leftRight->GetRight(), + topBottom->GetBottom() + ); + m_rect->Intersect(p_rect); + return; + } + } + } + } + + Reset(); +} diff --git a/LEGO1/mxsmack.cpp b/LEGO1/omni/src/video/mxsmack.cpp similarity index 93% rename from LEGO1/mxsmack.cpp rename to LEGO1/omni/src/video/mxsmack.cpp index 551b87c9..8d1835fe 100644 --- a/LEGO1/mxsmack.cpp +++ b/LEGO1/omni/src/video/mxsmack.cpp @@ -40,8 +40,9 @@ MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack) // TODO for (MxU32 i = 0; i < FRAME_COUNT(p_mxSmack); i++) { - if (p_mxSmack->m_maxFrameSize < frameSizes[i]) + if (p_mxSmack->m_maxFrameSize < frameSizes[i]) { p_mxSmack->m_maxFrameSize = frameSizes[i]; + } } frameTypes = new MxU8[FRAME_COUNT(p_mxSmack)]; @@ -54,8 +55,9 @@ MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack) p_data += FRAME_COUNT(p_mxSmack); MxU32 treeSize = p_mxSmack->m_smackTag.tablesize + 0x1000; - if (treeSize <= 0x2000) + if (treeSize <= 0x2000) { treeSize = 0x2000; + } huffmanTrees = new MxU8[treeSize]; @@ -127,16 +129,21 @@ MxResult MxSmack::LoadHeader(MxU8* p_data, MxSmack* p_mxSmack) // FUNCTION: LEGO1 0x100c5d40 void MxSmack::Destroy(MxSmack* p_mxSmack) { - if (p_mxSmack->m_frameSizes) + if (p_mxSmack->m_frameSizes) { delete[] p_mxSmack->m_frameSizes; - if (p_mxSmack->m_frameTypes) + } + if (p_mxSmack->m_frameTypes) { delete[] p_mxSmack->m_frameTypes; - if (p_mxSmack->m_huffmanTrees) + } + if (p_mxSmack->m_huffmanTrees) { delete[] p_mxSmack->m_huffmanTrees; - if (p_mxSmack->m_huffmanTables) + } + if (p_mxSmack->m_huffmanTables) { delete[] p_mxSmack->m_huffmanTables; - if (p_mxSmack->m_unk0x6b4) + } + if (p_mxSmack->m_unk0x6b4) { delete[] p_mxSmack->m_unk0x6b4; + } } // This should be refactored to somewhere else @@ -223,12 +230,14 @@ MxBool MxSmack::GetRect(MxU8* p_unk0x6b4, MxU16* p_und, u32* p_smackRect, MxRect { u32 left, bottom, top, right; - if (!*p_und) + if (!*p_und) { return FALSE; + } if (*p_und == 1) { - if (!SmackGetRect(p_unk0x6b4, p_smackRect)) + if (!SmackGetRect(p_unk0x6b4, p_smackRect)) { return FALSE; + } *p_und = 2; } @@ -238,10 +247,12 @@ MxBool MxSmack::GetRect(MxU8* p_unk0x6b4, MxU16* p_und, u32* p_smackRect, MxRect bottom = p_smackRect[3] + p_smackRect[1]; while (SmackGetRect(p_unk0x6b4, p_smackRect)) { - if (left > p_smackRect[0]) + if (left > p_smackRect[0]) { left = p_smackRect[0]; - if (right < p_smackRect[0] + p_smackRect[2]) + } + if (right < p_smackRect[0] + p_smackRect[2]) { right = p_smackRect[0] + p_smackRect[2]; + } bottom = p_smackRect[1] + p_smackRect[3]; } diff --git a/LEGO1/mxsmkpresenter.cpp b/LEGO1/omni/src/video/mxsmkpresenter.cpp similarity index 95% rename from LEGO1/mxsmkpresenter.cpp rename to LEGO1/omni/src/video/mxsmkpresenter.cpp index 17985fdd..8bb2ed6f 100644 --- a/LEGO1/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; + SetBit1(FALSE); + SetBit2(FALSE); } // FUNCTION: LEGO1 0x100b3900 @@ -51,8 +51,9 @@ void MxSmkPresenter::LoadHeader(MxStreamChunk* p_chunk) // FUNCTION: LEGO1 0x100b3960 void MxSmkPresenter::CreateBitmap() { - if (m_bitmap) + if (m_bitmap) { delete m_bitmap; + } m_bitmap = new MxBitmap; m_bitmap->SetSize(m_mxSmack.m_smackTag.Width, m_mxSmack.m_smackTag.Height, NULL, FALSE); @@ -72,8 +73,9 @@ void MxSmkPresenter::LoadFrame(MxStreamChunk* p_chunk) MxRectList list(TRUE); MxSmack::LoadFrame(bitmapInfo, bitmapData, &m_mxSmack, chunkData, paletteChanged, &list); - if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && paletteChanged) + if (((MxDSMediaAction*) m_action)->GetPaletteManagement() && paletteChanged) { RealizePalette(); + } MxRect32 invalidateRect; MxRectListCursor cursor(&list); @@ -91,8 +93,9 @@ void MxSmkPresenter::VTable0x88() { if ((m_mxSmack.m_smackTag.SmackerType & 1) != 0) { MxU32 und = (m_currentFrame % m_mxSmack.m_smackTag.Frames); - if (1 < m_currentFrame && und == 1) + if (1 < m_currentFrame && und == 1) { m_currentFrame = 1; + } } else { if (m_mxSmack.m_smackTag.Frames == m_currentFrame) { diff --git a/LEGO1/mxstillpresenter.cpp b/LEGO1/omni/src/video/mxstillpresenter.cpp similarity index 64% rename from LEGO1/mxstillpresenter.cpp rename to LEGO1/omni/src/video/mxstillpresenter.cpp index 5474f8e3..ca749578 100644 --- a/LEGO1/mxstillpresenter.cpp +++ b/LEGO1/omni/src/video/mxstillpresenter.cpp @@ -2,43 +2,41 @@ #include "decomp.h" #include "define.h" -#include "legoomni.h" #include "mxcompositepresenter.h" #include "mxdsmediaaction.h" #include "mxomni.h" +#include "mxutil.h" #include "mxvideomanager.h" 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) { m_criticalSection.Enter(); - if (m_bitmapInfo) + if (m_bitmapInfo) { delete m_bitmapInfo; + } m_bitmapInfo = NULL; m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxVideoPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b9cc0 void MxStillPresenter::LoadHeader(MxStreamChunk* p_chunk) { - if (m_bitmapInfo) + if (m_bitmapInfo) { delete m_bitmapInfo; + } MxU8* data = new MxU8[p_chunk->GetLength()]; m_bitmapInfo = (MxBITMAPINFO*) data; @@ -48,8 +46,9 @@ void MxStillPresenter::LoadHeader(MxStreamChunk* p_chunk) // FUNCTION: LEGO1 0x100b9d10 void MxStillPresenter::CreateBitmap() { - if (m_bitmap) + if (m_bitmap) { delete m_bitmap; + } m_bitmap = new MxBitmap; m_bitmap->ImportBitmapInfo(m_bitmapInfo); @@ -63,7 +62,7 @@ void MxStillPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); LoadFrame(chunk); - m_subscriber->FUN_100b8390(chunk); + m_subscriber->DestroyChunk(chunk); } // FUNCTION: LEGO1 0x100b9dd0 @@ -71,6 +70,7 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) { memcpy(m_bitmap->GetBitmapData(), p_chunk->GetData(), p_chunk->GetLength()); + // MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); MxS32 height = GetHeight() - 1; MxS32 width = GetWidth() - 1; MxS32 x = m_location.GetX(); @@ -79,13 +79,13 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); - if (m_flags & Flag_Bit2) { + if (GetBit1()) { undefined4 und = 0; m_unk0x58 = MxOmni::GetInstance()->GetVideoManager()->GetDisplaySurface()->VTable0x44( m_bitmap, &und, - (m_flags & Flag_Bit4) / 8, - m_action->GetFlags() & MxDSAction::Flag_Bit4 + GetBit3(), + m_action->GetFlags() & MxDSAction::c_bit4 ); delete m_alpha; @@ -94,10 +94,12 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) delete m_bitmap; m_bitmap = NULL; - if (m_unk0x58 && und) - m_flags |= Flag_Bit3; - else - m_flags &= ~Flag_Bit3; + if (m_unk0x58 && und) { + SetBit2(TRUE); + } + else { + SetBit2(FALSE); + } } } @@ -114,23 +116,24 @@ void MxStillPresenter::StartingTickle() { MxVideoPresenter::StartingTickle(); - if (m_currentTickleState == TickleState_Streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) + if (m_currentTickleState == e_streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) { RealizePalette(); + } } // FUNCTION: LEGO1 0x100b9f90 void MxStillPresenter::StreamingTickle() { - MxStreamChunk* chunk = FUN_100b5650(); + MxStreamChunk* chunk = CurrentChunk(); 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) + if (m_action->GetDuration() == -1 && m_compositePresenter) { m_compositePresenter->VTable0x60(this); + } } } @@ -139,8 +142,7 @@ 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; + ProgressTickleState(e_unk5); } } } @@ -154,6 +156,7 @@ void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y) m_location.SetY(p_y); if (IsEnabled()) { + // Most likely needs to work with MxSize32 and MxPoint32 MxS32 height = GetHeight() - 1; MxS32 width = GetWidth() - 1; @@ -161,19 +164,20 @@ void MxStillPresenter::VTable0x88(MxS32 p_x, MxS32 p_y) MxRect32 rectB(m_location.GetX(), m_location.GetY(), width + m_location.GetX(), height + m_location.GetY()); MVideoManager()->InvalidateRect(rectA); - MVideoManager()->VTable0x34(rectA.GetLeft(), rectA.GetTop(), rectA.GetWidth(), rectA.GetHeight()); + MVideoManager()->UpdateView(rectA.GetLeft(), rectA.GetTop(), rectA.GetWidth(), rectA.GetHeight()); MVideoManager()->InvalidateRect(rectB); - MVideoManager()->VTable0x34(rectB.GetLeft(), rectB.GetTop(), rectB.GetWidth(), rectB.GetHeight()); + MVideoManager()->UpdateView(rectB.GetLeft(), rectB.GetTop(), rectB.GetWidth(), rectB.GetHeight()); } } // 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())); MxS32 height = GetHeight(); MxS32 width = GetWidth(); MxS32 x = m_location.GetX(); @@ -181,7 +185,7 @@ void MxStillPresenter::Enable(MxBool p_enable) MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); - MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); + MVideoManager()->UpdateView(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); } } @@ -190,13 +194,15 @@ void MxStillPresenter::ParseExtra() { MxPresenter::ParseExtra(); - if (m_action->GetFlags() & MxDSAction::Flag_Bit5) - m_flags |= Flag_Bit4; + if (m_action->GetFlags() & MxDSAction::c_bit5) { + SetBit3(TRUE); + } MxU32 len = m_action->GetExtraLength(); - if (len == 0) + if (len == 0) { return; + } len &= MAXWORD; @@ -212,15 +218,55 @@ void MxStillPresenter::ParseExtra() } if (KeyValueStringParse(output, g_strBmpIsmap, buf)) { - m_flags |= Flag_Bit5; - m_flags &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + SetBit4(TRUE); + SetBit1(FALSE); + SetBit2(FALSE); } } -// STUB: LEGO1 0x100ba2c0 +// FUNCTION: LEGO1 0x100ba2c0 MxStillPresenter* MxStillPresenter::Clone() { - // TODO - return NULL; + MxResult result = FAILURE; + MxStillPresenter* presenter = new MxStillPresenter; + + if (presenter) { + if (presenter->AddToManager() == SUCCESS) { + MxDSAction* action = presenter->GetAction()->Clone(); + + if (action && presenter->StartAction(NULL, action) == SUCCESS) { + presenter->SetBit0(GetBit0()); + presenter->SetBit1(GetBit1()); + presenter->SetBit2(GetBit2()); + presenter->SetBit3(GetBit3()); + presenter->SetBit4(GetBit4()); + + if (m_bitmap) { + presenter->m_bitmap = new MxBitmap; + + if (!presenter->m_bitmap || presenter->m_bitmap->ImportBitmap(m_bitmap) != SUCCESS) { + goto done; + } + } + + if (m_unk0x58) { + presenter->m_unk0x58 = MxDisplaySurface::FUN_100bbfb0(m_unk0x58); + } + + if (m_alpha) { + presenter->m_alpha = new MxVideoPresenter::AlphaMask(*m_alpha); + } + + result = SUCCESS; + } + } + } + +done: + if (result != SUCCESS) { + delete presenter; + presenter = NULL; + } + + return presenter; } diff --git a/LEGO1/mxvideomanager.cpp b/LEGO1/omni/src/video/mxvideomanager.cpp similarity index 83% rename from LEGO1/mxvideomanager.cpp rename to LEGO1/omni/src/video/mxvideomanager.cpp index aa2158f0..f2c9ddfa 100644 --- a/LEGO1/mxvideomanager.cpp +++ b/LEGO1/omni/src/video/mxvideomanager.cpp @@ -1,6 +1,5 @@ #include "mxvideomanager.h" -#include "legoomni.h" #include "mxautolocker.h" #include "mxpresenter.h" #include "mxticklemanager.h" @@ -14,7 +13,7 @@ MxVideoManager::MxVideoManager() } // FUNCTION: LEGO1 0x100be270 -void MxVideoManager::VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) +void MxVideoManager::UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) { } @@ -28,7 +27,7 @@ MxVideoManager::~MxVideoManager() MxResult MxVideoManager::Init() { this->m_pDirectDraw = NULL; - this->m_pDDSurface = NULL; + this->m_pDirect3D = NULL; this->m_displaySurface = NULL; this->m_region = NULL; this->m_videoParam.SetPalette(NULL); @@ -43,32 +42,39 @@ void MxVideoManager::Destroy(MxBool p_fromDestructor) m_thread->Terminate(); delete m_thread; } - else + else { TickleManager()->UnregisterClient(this); + } m_criticalSection.Enter(); - if (m_displaySurface) + if (m_displaySurface) { delete m_displaySurface; + } - if (m_region) + if (m_region) { delete m_region; + } - if (m_videoParam.GetPalette()) + if (m_videoParam.GetPalette()) { delete m_videoParam.GetPalette(); + } if (m_unk0x60) { - if (m_pDirectDraw) + if (m_pDirectDraw) { m_pDirectDraw->Release(); - if (m_pDDSurface) - m_pDDSurface->Release(); + } + if (m_pDirect3D) { + m_pDirect3D->Release(); + } } Init(); m_criticalSection.Leave(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaManager::Destroy(); + } } // FUNCTION: LEGO1 0x100be3e0 @@ -86,8 +92,9 @@ void MxVideoManager::UpdateRegion() // FUNCTION: LEGO1 0x100be440 void MxVideoManager::SortPresenterList() { - if (this->m_presenters->GetCount() <= 1) + if (this->m_presenters->GetCount() <= 1) { return; + } MxPresenterListCursor a(this->m_presenters); MxPresenterListCursor b(this->m_presenters); @@ -120,7 +127,7 @@ void MxVideoManager::SortPresenterList() MxResult MxVideoManager::VTable0x28( MxVideoParam& p_videoParam, LPDIRECTDRAW p_pDirectDraw, - LPDIRECTDRAWSURFACE p_pDDSurface, + LPDIRECT3D2 p_pDirect3D, LPDIRECTDRAWSURFACE p_ddSurface1, LPDIRECTDRAWSURFACE p_ddSurface2, LPDIRECTDRAWCLIPPER p_ddClipper, @@ -133,8 +140,9 @@ MxResult MxVideoManager::VTable0x28( m_unk0x60 = FALSE; - if (MxMediaManager::InitPresenters() != SUCCESS) + if (MxMediaManager::InitPresenters() != SUCCESS) { goto done; + } m_criticalSection.Enter(); locked = TRUE; @@ -142,26 +150,29 @@ MxResult MxVideoManager::VTable0x28( m_videoParam = p_videoParam; m_region = new MxRegion(); - if (!m_region) + if (!m_region) { goto done; + } m_pDirectDraw = p_pDirectDraw; - m_pDDSurface = p_pDDSurface; + m_pDirect3D = p_pDirect3D; MxPalette* palette; if (p_videoParam.GetPalette() == NULL) { palette = new MxPalette(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } else { palette = p_videoParam.GetPalette()->Clone(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } m_displaySurface = new MxDisplaySurface(); @@ -171,21 +182,25 @@ MxResult MxVideoManager::VTable0x28( if (p_createThread) { m_thread = new MxTickleThread(this, p_frequencyMS); - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; } done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return status; } @@ -198,8 +213,9 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, m_unk0x60 = TRUE; - if (MxMediaManager::InitPresenters() != SUCCESS) + if (MxMediaManager::InitPresenters() != SUCCESS) { goto done; + } m_criticalSection.Enter(); locked = TRUE; @@ -207,29 +223,34 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, m_videoParam = p_videoParam; m_region = new MxRegion(); - if (!m_region) + if (!m_region) { goto done; + } - if (DirectDrawCreate(NULL, &m_pDirectDraw, NULL) != DD_OK) + if (DirectDrawCreate(NULL, &m_pDirectDraw, NULL) != DD_OK) { goto done; + } - if (m_pDirectDraw->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DDSCL_NORMAL) != DD_OK) + if (m_pDirectDraw->SetCooperativeLevel(MxOmni::GetInstance()->GetWindowHandle(), DDSCL_NORMAL) != DD_OK) { goto done; + } MxPalette* palette; if (p_videoParam.GetPalette() == NULL) { palette = new MxPalette(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } else { palette = p_videoParam.GetPalette()->Clone(); m_videoParam.SetPalette(palette); - if (!palette) + if (!palette) { goto done; + } } m_displaySurface = new MxDisplaySurface(); @@ -239,21 +260,25 @@ MxResult MxVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, if (p_createThread) { m_thread = new MxTickleThread(this, p_frequencyMS); - if (!m_thread || m_thread->Start(0, 0) != SUCCESS) + if (!m_thread || m_thread->Start(0, 0) != SUCCESS) { goto done; + } } - else + else { TickleManager()->RegisterClient(this, p_frequencyMS); + } status = SUCCESS; } done: - if (status != SUCCESS) + if (status != SUCCESS) { Destroy(); + } - if (locked) + if (locked) { m_criticalSection.Leave(); + } return status; } @@ -269,8 +294,9 @@ void MxVideoManager::InvalidateRect(MxRect32& p_rect) { m_criticalSection.Enter(); - if (m_region) + if (m_region) { m_region->VTable0x18(p_rect); + } m_criticalSection.Leave(); } @@ -285,13 +311,15 @@ MxResult MxVideoManager::Tickle() MxPresenter* presenter; MxPresenterListCursor cursor(this->m_presenters); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->Tickle(); + } cursor.Reset(); - while (cursor.Next(presenter)) + while (cursor.Next(presenter)) { presenter->PutData(); + } UpdateRegion(); m_region->Reset(); diff --git a/LEGO1/mxvideoparam.cpp b/LEGO1/omni/src/video/mxvideoparam.cpp similarity index 89% rename from LEGO1/mxvideoparam.cpp rename to LEGO1/omni/src/video/mxvideoparam.cpp index c34e832c..8e48773f 100644 --- a/LEGO1/mxvideoparam.cpp +++ b/LEGO1/omni/src/video/mxvideoparam.cpp @@ -21,12 +21,7 @@ MxVideoParam::MxVideoParam() } // FUNCTION: LEGO1 0x100beca0 -MxVideoParam::MxVideoParam( - COMPAT_CONST MxRect32& p_rect, - MxPalette* p_palette, - MxULong p_backBuffers, - COMPAT_CONST MxVideoParamFlags& p_flags -) +MxVideoParam::MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_backBuffers, MxVideoParamFlags& p_flags) { this->m_rect = p_rect; this->m_palette = p_palette; @@ -51,15 +46,17 @@ MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam) // FUNCTION: LEGO1 0x100bed50 MxVideoParam::~MxVideoParam() { - if (this->m_deviceId != NULL) + if (this->m_deviceId != NULL) { delete[] this->m_deviceId; + } } // FUNCTION: LEGO1 0x100bed70 void MxVideoParam::SetDeviceName(char* p_deviceId) { - if (this->m_deviceId != NULL) + if (this->m_deviceId != NULL) { delete[] this->m_deviceId; + } if (p_deviceId != NULL) { this->m_deviceId = new char[strlen(p_deviceId) + 1]; diff --git a/LEGO1/mxvideoparamflags.cpp b/LEGO1/omni/src/video/mxvideoparamflags.cpp similarity index 100% rename from LEGO1/mxvideoparamflags.cpp rename to LEGO1/omni/src/video/mxvideoparamflags.cpp diff --git a/LEGO1/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp similarity index 53% rename from LEGO1/mxvideopresenter.cpp rename to LEGO1/omni/src/video/mxvideopresenter.cpp index b1beb08e..dcccf8f6 100644 --- a/LEGO1/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -2,70 +2,11 @@ #include "mxautolocker.h" #include "mxdsmediaaction.h" +#include "mxregioncursor.h" #include "mxvideomanager.h" 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->GetBmiHeader()->biWidth; -} - -// FUNCTION: LEGO1 0x1000c800 -MxS32 MxVideoPresenter::GetHeight() -{ - return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeader()->biHeight; -} +DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0x0c); // FUNCTION: LEGO1 0x100b24f0 MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) @@ -79,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; @@ -91,36 +31,29 @@ 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) { - rowsBeforeTop = 0; - } - else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs(); - rowsBeforeTop--; - } - - goto seek_to_last_row; - } - else if (biCompression == BI_RGB_TOPDOWN) { - // DECOMP: This is the only condition where we skip the - // calculation below. - bitmapSrcPtr = p_bitmap.GetBitmapData(); - } - else { + switch (p_bitmap.GetBmiHeader()->biCompression) { + case BI_RGB: { if (p_bitmap.GetBmiHeight() < 0) { rowsBeforeTop = 0; } else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs(); - rowsBeforeTop--; + rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; } - - // 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(); + bitmapSrcPtr = p_bitmap.GetBitmapData() + (p_bitmap.GetBmiStride() * rowsBeforeTop); + break; + } + case BI_RGB_TOPDOWN: + bitmapSrcPtr = p_bitmap.GetBitmapData(); + break; + default: { + if (p_bitmap.GetBmiHeight() < 0) { + rowsBeforeTop = 0; + } + 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? @@ -128,15 +61,16 @@ 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. @@ -166,15 +100,17 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxVideoPresenter::AlphaMask& p_alph // FUNCTION: LEGO1 0x100b26d0 MxVideoPresenter::AlphaMask::~AlphaMask() { - if (m_bitmask) + if (m_bitmask) { delete[] m_bitmask; + } } // FUNCTION: LEGO1 0x100b26f0 MxS32 MxVideoPresenter::AlphaMask::IsHit(MxU32 p_x, MxU32 p_y) { - if (p_x >= m_width || p_y >= m_height) + if (p_x >= m_width || p_y >= m_height) { return 0; + } MxS32 pos = p_y * m_width + p_x; return m_bitmask[pos / 8] & (1 << abs(abs(pos) & 7)) ? 1 : 0; @@ -188,41 +124,42 @@ void MxVideoPresenter::Init() m_unk0x5c = 1; m_unk0x58 = NULL; m_unk0x60 = -1; - m_flags &= ~Flag_Bit1; + SetBit0(FALSE); if (MVideoManager() != NULL) { MVideoManager(); - m_flags |= Flag_Bit2; - m_flags &= ~Flag_Bit3; + SetBit1(TRUE); + SetBit2(FALSE); } - m_flags &= ~Flag_Bit4; - m_flags &= ~Flag_Bit5; + SetBit3(FALSE); + SetBit4(FALSE); } // FUNCTION: LEGO1 0x100b27b0 void MxVideoPresenter::Destroy(MxBool p_fromDestructor) { - if (MVideoManager() != NULL) - MVideoManager()->RemovePresenter(*this); + if (MVideoManager() != NULL) { + MVideoManager()->UnregisterPresenter(*this); + } if (m_unk0x58) { m_unk0x58->Release(); m_unk0x58 = NULL; - m_flags &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + SetBit1(FALSE); + SetBit2(FALSE); } if (MVideoManager() && (m_alpha || m_bitmap)) { + // MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); MxS32 height = GetHeight(); MxS32 width = GetWidth(); - MxS32 x = m_location.GetX(); MxS32 y = m_location.GetY(); - MxRect32 rect(x, y, x + width, y + height); + MxRect32 rect(x, y, x + width, y + height); MVideoManager()->InvalidateRect(rect); - MVideoManager()->VTable0x34(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); + MVideoManager()->UpdateView(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight()); } delete m_bitmap; @@ -230,8 +167,9 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) Init(); - if (!p_fromDestructor) + if (!p_fromDestructor) { MxMediaPresenter::Destroy(FALSE); + } } // FUNCTION: LEGO1 0x100b28b0 @@ -239,14 +177,13 @@ void MxVideoPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxStreamChunk::Flag_Bit2) { - m_subscriber->FUN_100b8390(chunk); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + if (chunk->GetFlags() & MxDSChunk::c_end) { + m_subscriber->DestroyChunk(chunk); + ProgressTickleState(e_repeating); } else { LoadFrame(chunk); - m_subscriber->FUN_100b8390(chunk); + m_subscriber->DestroyChunk(chunk); } } @@ -254,12 +191,14 @@ 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()) || - (!m_bitmap && !m_alpha)) + if ((action == NULL) || (((action->GetFlags() & MxDSAction::c_bit11) == 0) && !IsEnabled()) || + (!m_bitmap && !m_alpha)) { return FALSE; + } - if (!m_bitmap) + if (!m_bitmap) { return m_alpha->IsHit(p_x - m_location.GetX(), p_y - m_location.GetY()); + } MxLong heightAbs = m_bitmap->GetBmiHeightAbs(); @@ -269,8 +208,9 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) MxLong maxY = minY + heightAbs; MxLong maxX = minX + m_bitmap->GetBmiWidth(); - if (p_x < minX || p_x >= maxX || p_y < minY || p_y >= maxY) + if (p_x < minX || p_x >= maxX || p_y < minY || p_y >= maxY) { return FALSE; + } MxU8* pixel; @@ -302,20 +242,163 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) pixel = m_bitmap->GetBmiStride() * height + m_bitmap->GetBitmapData(); } - // DECOMP: m_flags is 1 byte, so no enum here - if (m_flags & 0x10) + if (GetBit4()) { return (MxBool) *pixel; + } - if ((GetAction()->GetFlags() & MxDSAction::Flag_Bit4) && *pixel == 0) + if ((GetAction()->GetFlags() & MxDSAction::c_bit4) && *pixel == 0) { return FALSE; + } return TRUE; } -// STUB: LEGO1 0x100b2a70 -void MxVideoPresenter::VTable0x6c() +inline MxS32 MxVideoPresenter::PrepareRects(MxRect32& p_rectDest, MxRect32& p_rectSrc) { - // TODO + if (p_rectDest.GetTop() > 480 || p_rectDest.GetLeft() > 640 || p_rectSrc.GetTop() > 480 || + p_rectSrc.GetLeft() > 640) { + return -1; + } + + if (p_rectDest.GetBottom() > 480) { + p_rectDest.SetBottom(480); + } + + if (p_rectDest.GetRight() > 640) { + p_rectDest.SetRight(640); + } + + if (p_rectSrc.GetBottom() > 480) { + p_rectSrc.SetBottom(480); + } + + if (p_rectSrc.GetRight() > 640) { + p_rectSrc.SetRight(640); + } + + MxS32 height = p_rectDest.GetHeight(); + if (height <= 1) { + return -1; + } + + MxS32 width = p_rectDest.GetWidth(); + if (width <= 1) { + return -1; + } + + if (p_rectSrc.GetRight() - width - p_rectSrc.GetLeft() == -1 && + p_rectSrc.GetBottom() - height - p_rectSrc.GetTop() == -1) { + return 1; + } + + p_rectSrc.SetRight(p_rectSrc.GetLeft() + width - 1); + p_rectSrc.SetBottom(p_rectSrc.GetTop() + height - 1); + return 0; +} + +// FUNCTION: LEGO1 0x100b2a70 +void MxVideoPresenter::PutFrame() +{ + MxDisplaySurface* displaySurface = MVideoManager()->GetDisplaySurface(); + MxRegion* region = MVideoManager()->GetRegion(); + MxRect32 rect(m_location, MxSize32(GetWidth(), GetHeight())); + LPDIRECTDRAWSURFACE ddSurface = displaySurface->GetDirectDrawSurface2(); + + MxRect32 rectSrc, rectDest; + if (m_action->GetFlags() & MxDSAction::c_bit5) { + if (m_unk0x58) { + // TODO: Match + rectSrc.SetPoint(MxPoint32(0, 0)); + rectSrc.SetRight(GetWidth()); + rectSrc.SetBottom(GetHeight()); + + rectDest.SetPoint(m_location); + rectDest.SetRight(rectDest.GetLeft() + GetWidth()); + rectDest.SetBottom(rectDest.GetTop() + GetHeight()); + + switch (PrepareRects(rectDest, rectSrc)) { + case 0: + ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL); + break; + case 1: + ddSurface->BltFast( + rectDest.GetLeft(), + rectDest.GetTop(), + m_unk0x58, + (LPRECT) &rectSrc, + DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT + ); + } + } + else { + displaySurface->VTable0x30( + m_bitmap, + 0, + 0, + rect.GetLeft(), + rect.GetTop(), + m_bitmap->GetBmiWidth(), + m_bitmap->GetBmiHeightAbs(), + TRUE + ); + } + } + else { + MxRegionCursor cursor(region); + MxRect32* regionRect; + + while ((regionRect = cursor.VTable0x24(rect))) { + if (regionRect->GetWidth() >= 1 && regionRect->GetHeight() >= 1) { + if (m_unk0x58) { + rectSrc.SetLeft(regionRect->GetLeft() - m_location.GetX()); + rectSrc.SetTop(regionRect->GetTop() - m_location.GetY()); + rectSrc.SetRight(rectSrc.GetLeft() + regionRect->GetWidth()); + rectSrc.SetBottom(rectSrc.GetTop() + regionRect->GetHeight()); + + rectDest.SetLeft(regionRect->GetLeft()); + rectDest.SetTop(regionRect->GetTop()); + rectDest.SetRight(rectDest.GetLeft() + regionRect->GetWidth()); + rectDest.SetBottom(rectDest.GetTop() + regionRect->GetHeight()); + } + + 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); + } + } + else { + displaySurface->VTable0x30( + m_bitmap, + regionRect->GetLeft() - m_location.GetX(), + regionRect->GetTop() - m_location.GetY(), + regionRect->GetLeft(), + regionRect->GetTop(), + regionRect->GetWidth(), + regionRect->GetHeight(), + FALSE + ); + } + } + else if (m_unk0x58) { + if (PrepareRects(rectDest, rectSrc) >= 0) { + ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, 0, NULL); + } + } + else { + displaySurface->VTable0x28( + m_bitmap, + regionRect->GetLeft() - m_location.GetX(), + regionRect->GetTop() - m_location.GetY(), + regionRect->GetLeft(), + regionRect->GetTop(), + regionRect->GetWidth(), + regionRect->GetHeight() + ); + } + } + } + } } // FUNCTION: LEGO1 0x100b2f60 @@ -325,31 +408,30 @@ void MxVideoPresenter::ReadyTickle() if (chunk) { LoadHeader(chunk); - m_subscriber->FUN_100b8390(chunk); + m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } // FUNCTION: LEGO1 0x100b2fa0 void MxVideoPresenter::StartingTickle() { - MxStreamChunk* chunk = FUN_100b5650(); + MxStreamChunk* chunk = CurrentChunk(); 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_currentChunk) + if (m_action->GetFlags() & MxDSAction::c_bit10) { + if (!m_currentChunk) { MxMediaPresenter::StreamingTickle(); + } if (m_currentChunk) { LoadFrame(m_currentChunk); @@ -361,24 +443,28 @@ void MxVideoPresenter::StreamingTickle() if (!m_currentChunk) { MxMediaPresenter::StreamingTickle(); - if (!m_currentChunk) + if (!m_currentChunk) { break; + } } - if (m_action->GetElapsedTime() < m_currentChunk->GetTime()) + if (m_action->GetElapsedTime() < m_currentChunk->GetTime()) { break; + } LoadFrame(m_currentChunk); - m_subscriber->FUN_100b8390(m_currentChunk); + m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; - m_flags |= Flag_Bit1; + SetBit0(TRUE); - if (m_currentTickleState != TickleState_Streaming) + if (m_currentTickleState != e_streaming) { break; + } } - if (m_flags & Flag_Bit1) + if (GetBit0()) { m_unk0x5c = 5; + } } } @@ -386,9 +472,10 @@ void MxVideoPresenter::StreamingTickle() void MxVideoPresenter::RepeatingTickle() { if (IsEnabled()) { - if (m_action->GetFlags() & MxDSAction::Flag_Bit10) { - if (!m_currentChunk) + if (m_action->GetFlags() & MxDSAction::c_bit10) { + if (!m_currentChunk) { MxMediaPresenter::RepeatingTickle(); + } if (m_currentChunk) { LoadFrame(m_currentChunk); @@ -400,23 +487,27 @@ void MxVideoPresenter::RepeatingTickle() if (!m_currentChunk) { MxMediaPresenter::RepeatingTickle(); - if (!m_currentChunk) + if (!m_currentChunk) { break; + } } - if (m_action->GetElapsedTime() % m_action->GetLoopCount() < m_currentChunk->GetTime()) + if (m_action->GetElapsedTime() % m_action->GetLoopCount() < m_currentChunk->GetTime()) { break; + } LoadFrame(m_currentChunk); m_currentChunk = NULL; - m_flags |= Flag_Bit1; + SetBit0(TRUE); - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) { break; + } } - if (m_flags & Flag_Bit1) + if (GetBit0()) { m_unk0x5c = 5; + } } } } @@ -428,17 +519,16 @@ void MxVideoPresenter::Unk5Tickle() if (sustainTime != -1) { if (sustainTime) { - if (m_unk0x60 == -1) + if (m_unk0x60 == -1) { m_unk0x60 = m_action->GetElapsedTime(); + } if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } } else { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } } } @@ -450,7 +540,7 @@ MxResult MxVideoPresenter::AddToManager() if (MVideoManager()) { result = SUCCESS; - MVideoManager()->AddPresenter(*this); + MVideoManager()->RegisterPresenter(*this); } return result; @@ -481,8 +571,9 @@ MxResult MxVideoPresenter::PutData() { MxAutoLocker lock(&m_criticalSection); - if (IsEnabled() && m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_unk5) - VTable0x6c(); + if (IsEnabled() && m_currentTickleState >= e_streaming && m_currentTickleState <= e_unk5) { + PutFrame(); + } return SUCCESS; } diff --git a/LEGO1/pizzeria.cpp b/LEGO1/pizzeria.cpp deleted file mode 100644 index 3b6e8d41..00000000 --- a/LEGO1/pizzeria.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pizzeria.h" diff --git a/LEGO1/pizzeria.h b/LEGO1/pizzeria.h deleted file mode 100644 index 65a3b195..00000000 --- a/LEGO1/pizzeria.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef PIZZERIASTATE_H -#define PIZZERIASTATE_H - -#include "isleactor.h" - -// VTABLE: LEGO1 0x100d5520 -// SIZE 0x84 -class Pizzeria : public IsleActor { -public: - // FUNCTION: LEGO1 0x1000e780 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0380 - return "Pizzeria"; - } - - // FUNCTION: LEGO1 0x1000e790 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Pizzeria::ClassName()) || IsleActor::IsA(p_name); - } -}; - -#endif // PIZZERIASTATE_H diff --git a/LEGO1/pizzeriastate.cpp b/LEGO1/pizzeriastate.cpp deleted file mode 100644 index ea54a028..00000000 --- a/LEGO1/pizzeriastate.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "pizzeriastate.h" - -// STUB: LEGO1 0x10017af0 -PizzeriaState::PizzeriaState() -{ - // TODO -} diff --git a/LEGO1/police.cpp b/LEGO1/police.cpp deleted file mode 100644 index 67577ecc..00000000 --- a/LEGO1/police.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "police.h" - -// STUB: LEGO1 0x1005e130 -Police::Police() -{ - // TODO -} - -// STUB: LEGO1 0x1005e320 -Police::~Police() -{ - // TODO -} - -// STUB: LEGO1 0x1005e480 -MxLong Police::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/police.h b/LEGO1/police.h deleted file mode 100644 index 0da58828..00000000 --- a/LEGO1/police.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef POLICE_H -#define POLICE_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d8a80 -// SIZE 0x110 -// Radio at 0xf8 -class Police : public LegoWorld { -public: - Police(); - virtual ~Police() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x1005e1e0 - inline virtual const char* ClassName() const override // vtable+0xc - { - // GLOBAL: LEGO1 0x100f0450 - return "Police"; - } - - // FUNCTION: LEGO1 0x1005e1f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Police::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // POLICE_H diff --git a/LEGO1/policestate.cpp b/LEGO1/policestate.cpp deleted file mode 100644 index a2c66a45..00000000 --- a/LEGO1/policestate.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "policestate.h" - -// STUB: LEGO1 0x1005e7c0 -PoliceState::PoliceState() -{ - // TODO -} diff --git a/LEGO1/policestate.h b/LEGO1/policestate.h deleted file mode 100644 index b3a732c9..00000000 --- a/LEGO1/policestate.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef POLICESTATE_H -#define POLICESTATE_H - -#include "legostate.h" - -// VTABLE: LEGO1 0x100d8af0 -// SIZE 0x10 -class PoliceState : public LegoState { -public: - PoliceState(); - - // FUNCTION: LEGO1 0x1005e860 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0444 - return "PoliceState"; - } - - // FUNCTION: LEGO1 0x1005e870 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, PoliceState::ClassName()) || LegoState::IsA(p_name); - } -}; - -#endif // POLICESTATE_H diff --git a/LEGO1/racecar.cpp b/LEGO1/racecar.cpp deleted file mode 100644 index 0fbc97b9..00000000 --- a/LEGO1/racecar.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "racecar.h" - -DECOMP_SIZE_ASSERT(RaceCar, 0x164); - -// FUNCTION: LEGO1 0x10028200 -RaceCar::RaceCar() -{ - this->m_unk0x13c = 40.0; -} - -// STUB: LEGO1 0x10028420 -RaceCar::~RaceCar() -{ - // TODO -} diff --git a/LEGO1/racestandsentity.h b/LEGO1/racestandsentity.h deleted file mode 100644 index a7359df8..00000000 --- a/LEGO1/racestandsentity.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef RACESTANDSENTITY_H -#define RACESTANDSENTITY_H - -#include "buildingentity.h" - -// VTABLE: LEGO1 0x100d48a8 -// SIZE 0x68 -class RaceStandsEntity : public BuildingEntity {}; - -#endif // RACESTANDSENTITY_H diff --git a/LEGO1/radio.cpp b/LEGO1/radio.cpp deleted file mode 100644 index f1befefd..00000000 --- a/LEGO1/radio.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "radio.h" - -#include "legocontrolmanager.h" -#include "legogamestate.h" -#include "legoomni.h" -#include "mxnotificationmanager.h" - -DECOMP_SIZE_ASSERT(Radio, 0x10); - -// FUNCTION: LEGO1 0x1002c850 -Radio::Radio() -{ - NotificationManager()->Register(this); - ControlManager()->Register(this); - - m_unk0xc = TRUE; - CreateRadioState(); -} - -// STUB: LEGO1 0x1002c990 -Radio::~Radio() -{ - // TODO -} - -// FUNCTION: LEGO1 0x1002cde0 -void Radio::CreateRadioState() -{ - LegoGameState* gameState = GameState(); - RadioState* state = (RadioState*) gameState->GetState("RadioState"); - if (state == NULL) { - state = (RadioState*) gameState->CreateState("RadioState"); - } - - m_state = state; -} diff --git a/LEGO1/radio.h b/LEGO1/radio.h deleted file mode 100644 index 8d454483..00000000 --- a/LEGO1/radio.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef RADIO_H -#define RADIO_H - -#include "mxcore.h" -#include "radiostate.h" - -// VTABLE: LEGO1 0x100d6d10 -class Radio : public MxCore { -public: - Radio(); - virtual ~Radio() override; - - // FUNCTION: LEGO1 0x1002c8e0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f328c - return "Radio"; - } - - // FUNCTION: LEGO1 0x1002c8f0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Radio::ClassName()) || MxCore::IsA(p_name); - } - -private: - RadioState* m_state; // 0x08 - MxBool m_unk0xc; // 0x0c - - void CreateRadioState(); -}; - -#endif // RADIO_H diff --git a/LEGO1/radiostate.cpp b/LEGO1/radiostate.cpp deleted file mode 100644 index 012eea68..00000000 --- a/LEGO1/radiostate.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include "radiostate.h" - -// STUB: LEGO1 0x1002ce10 -RadioState::RadioState() -{ - // TODO -} diff --git a/LEGO1/radiostate.h b/LEGO1/radiostate.h deleted file mode 100644 index dc2c8b8f..00000000 --- a/LEGO1/radiostate.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RADIOSTATE_H -#define RADIOSTATE_H - -#include "legostate.h" - -// VTABLE: LEGO1 0x100d6d28 -// SIZE 0x30 -class RadioState : public LegoState { -public: - RadioState(); - - // FUNCTION: LEGO1 0x1002cf60 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f04f8 - return "RadioState"; - } - - // FUNCTION: LEGO1 0x1002cf70 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, RadioState::ClassName()) || LegoState::IsA(p_name); - } -}; - -#endif // RADIOSTATE_H diff --git a/LEGO1/realtime/matrix.cpp b/LEGO1/realtime/matrix.cpp index 852e14d0..c1de1535 100644 --- a/LEGO1/realtime/matrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -1,186 +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 0x10002370 -void Matrix4Impl::SetData(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, 0x08); diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index 58db7a9f..266b2fa6 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -3,89 +3,167 @@ #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 { +// SIZE 0x08 +class Matrix4 { public: - inline Matrix4Impl(Matrix4& p_data) : m_data(&p_data) {} + inline Matrix4(float (*p_data)[4]) { SetData(p_data); } - // vtable + 0x00 - virtual void EqualsMatrixImpl(const Matrix4Impl* p_other); - virtual void EqualsMatrixData(const Matrix4& p_matrix); - virtual void SetData(Matrix4& p_data); - virtual void AnotherSetData(Matrix4& p_data); + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. - // 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 0x10002320 + virtual void Equals(float (*p_data)[4]) { memcpy(m_data, p_data, sizeof(float) * 4 * 4); } // vtable+0x04 - // vtable + 0x20 - virtual void Clear(); - virtual void SetIdentity(); - virtual void operator=(const Matrix4Impl& p_other); - virtual Matrix4Impl* operator+=(const Matrix4& p_matrix); + // FUNCTION: LEGO1 0x10002340 + virtual void Equals(const Matrix4& p_matrix) + { + memcpy(m_data, p_matrix.m_data, sizeof(float) * 4 * 4); + } // vtable+0x00 - // 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 0x10002360 + virtual void SetData(float (*p_data)[4]) { m_data = p_data; } // vtable+0x0c - // vtable + 0x40 - virtual void ToQuaternion(Vector4Impl* p_resultQuat); - virtual int FromQuaternion(const Vector4Impl& p_vec); + // FUNCTION: LEGO1 0x10002370 + virtual void SetData(UnknownMatrixType& p_matrix) { m_data = p_matrix.m_data; } // vtable+0x08 - inline float& operator[](size_t idx) { return ((float*) m_data)[idx]; } + // FUNCTION: LEGO1 0x10002380 + virtual float (*GetData())[4] { return m_data; } // vtable+0x14 + + // FUNCTION: LEGO1 0x10002390 + virtual float (*GetData() const)[4] { return m_data; } // vtable+0x10 + + // FUNCTION: LEGO1 0x100023a0 + virtual float* Element(int p_row, int p_col) { return &m_data[p_row][p_col]; } // vtable+0x1c + + // FUNCTION: LEGO1 0x100023c0 + virtual const float* Element(int p_row, int p_col) const { return &m_data[p_row][p_col]; } // vtable+0x18 + + // 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 0x10002420 + 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..4a2c979b 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,36 +28,37 @@ 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(); // iterate over comps - if (m_comp) + if (m_comp) { for (CompoundObject::iterator iter = m_comp->begin(); !(iter == m_comp->end()); iter++) { ROI* child = *iter; static_cast(child)->UpdateWorldData(p_transform); } + } } // FUNCTION: LEGO1 0x100a5a50 @@ -50,9 +67,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..005ec4dc 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -1,47 +1,60 @@ #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 - virtual const BoundingBox& GetWorldBoundingBox() const override; // vtable+0xc - virtual const BoundingSphere& GetWorldBoundingSphere() const override; // vtable+0x10 + OrientableROI(); + + const float* GetWorldVelocity() const override; // vtable+0x08 + const BoundingBox& GetWorldBoundingBox() const override; // vtable+0x0c + const BoundingSphere& GetWorldBoundingSphere() const override; // vtable+0x10 // FUNCTION: LEGO1 0x100a5db0 - virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 - virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 - 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]; } + OrientableROI* GetUnknown0xd4() const { return m_unk0xd4; } 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 + OrientableROI* 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/realtimeview.h b/LEGO1/realtime/realtimeview.h index 22183ced..f732c480 100644 --- a/LEGO1/realtime/realtimeview.h +++ b/LEGO1/realtime/realtimeview.h @@ -3,11 +3,11 @@ class RealtimeView { public: - __declspec(dllexport) static float GetPartsThreshold(); - __declspec(dllexport) static float GetUserMaxLOD(); - __declspec(dllexport) static void SetPartsThreshold(float); + static float GetPartsThreshold(); + static float GetUserMaxLOD(); + static void SetPartsThreshold(float); static void UpdateMaxLOD(); - __declspec(dllexport) static void SetUserMaxLOD(float); + static void SetUserMaxLOD(float); }; #endif // REALTIMEVIEW_H diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index 287407ac..6f367c48 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -3,41 +3,41 @@ // ROI stands for Real-time Object Instance. -#include "../mxstl/stlcompat.h" -#include "../realtime/realtime.h" #include "compat.h" #include "lodlist.h" -#include "vector.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxstl/stlcompat.h" +#include "realtime/realtime.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; }; @@ -49,9 +49,9 @@ class LODObject { public: // LODObject(); virtual ~LODObject() {} - virtual float Cost(float pixels_covered) const = 0; // vtable+0x4 - virtual float AveragePolyArea() const = 0; // vtable+0x8 - virtual int NVerts() const = 0; // vtable+0xc + virtual float Cost(float pixels_covered) const = 0; // vtable+0x04 + virtual float AveragePolyArea() const = 0; // vtable+0x08 + virtual int NVerts() const = 0; // vtable+0x0c }; /* @@ -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_unk0x0c = 1; } virtual ~ROI() { @@ -88,9 +89,9 @@ class ROI { assert(!m_comp); assert(!m_lods); } - virtual float IntrinsicImportance() const = 0; // vtable+0x4 - virtual const Vector3& GetWorldVelocity() const = 0; // vtable+0x8 - virtual const BoundingBox& GetWorldBoundingBox() const = 0; // vtable+0xc + virtual float IntrinsicImportance() const = 0; // vtable+0x04 + virtual const float* GetWorldVelocity() const = 0; // vtable+0x08 + virtual const BoundingBox& GetWorldBoundingBox() const = 0; // vtable+0x0c virtual const BoundingSphere& GetWorldBoundingSphere() const = 0; // vtable+0x10 const LODListBase* GetLODs() const { return m_lods; } @@ -102,8 +103,18 @@ class ROI { int GetLODCount() const { return m_lods ? m_lods->Size() : 0; } const CompoundObject* GetComp() const { return m_comp; } + inline undefined GetUnk0x0c() { return m_unk0x0c; } + + // SYNTHETIC: LEGO1 0x100a5d60 + // ROI::`scalar deleting destructor' + protected: - CompoundObject* m_comp; // 0x4 - LODListBase* m_lods; // 0x8 + CompoundObject* m_comp; // 0x04 + LODListBase* m_lods; // 0x08 + undefined m_unk0x0c; // 0x0c }; + +// SYNTHETIC: LEGO1 0x100a5d50 +// ROI::~ROI + #endif // ROI_H diff --git a/LEGO1/realtime/vector.cpp b/LEGO1/realtime/vector.cpp index 390cfdd9..ad09b0b0 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, 0x08); +DECOMP_SIZE_ASSERT(Vector3, 0x08); +DECOMP_SIZE_ASSERT(Vector4, 0x08); diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 5c31f24e..a28a9874 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) { this->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) { this->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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 3); } // vtable+0x20 + + // FUNCTION: LEGO1 0x10003bc0 + void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10003bd0 + 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 { +// SIZE 0x08 +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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 4); } // vtable+0x20 + + // FUNCTION: LEGO1 0x10002b00 + void Clear() override { memset(m_data, 0, sizeof(float) * 4); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10002b20 + 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 + 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/registrationbook.cpp b/LEGO1/registrationbook.cpp deleted file mode 100644 index eb7e099a..00000000 --- a/LEGO1/registrationbook.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "registrationbook.h" - -// STUB: LEGO1 0x10076d20 -RegistrationBook::RegistrationBook() -{ - // TODO -} - -// STUB: LEGO1 0x10076f50 -RegistrationBook::~RegistrationBook() -{ - // TODO -} - -// STUB: LEGO1 0x100770e0 -MxLong RegistrationBook::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/registrationbook.h b/LEGO1/registrationbook.h deleted file mode 100644 index 4f19a8dc..00000000 --- a/LEGO1/registrationbook.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef REGISTRATIONBOOK_H -#define REGISTRATIONBOOK_H - -#include "legoworld.h" - -// VTABLE: LEGO1 0x100d9928 -// SIZE 0x2d0 -class RegistrationBook : public LegoWorld { -public: - RegistrationBook(); - virtual ~RegistrationBook() override; // vtable+0x0 - - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x10076e10 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f04c8 - return "RegistrationBook"; - } - - // FUNCTION: LEGO1 0x10076e20 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, RegistrationBook::ClassName()) || LegoWorld::IsA(p_name); - } -}; - -#endif // REGISTRATIONBOOK_H diff --git a/LEGO1/res/arrow.cur b/LEGO1/res/arrow.cur new file mode 100644 index 00000000..15f687a1 Binary files /dev/null and b/LEGO1/res/arrow.cur differ diff --git a/LEGO1/res/busy.cur b/LEGO1/res/busy.cur new file mode 100644 index 00000000..2a63b536 Binary files /dev/null and b/LEGO1/res/busy.cur differ diff --git a/LEGO1/res/leaf_0.cur b/LEGO1/res/leaf_0.cur new file mode 100644 index 00000000..e8735671 Binary files /dev/null and b/LEGO1/res/leaf_0.cur differ diff --git a/LEGO1/res/leaf_1.cur b/LEGO1/res/leaf_1.cur new file mode 100644 index 00000000..e7e0cde9 Binary files /dev/null and b/LEGO1/res/leaf_1.cur differ diff --git a/LEGO1/res/leaf_2.cur b/LEGO1/res/leaf_2.cur new file mode 100644 index 00000000..1abce39b Binary files /dev/null and b/LEGO1/res/leaf_2.cur differ diff --git a/LEGO1/res/leaf_3.cur b/LEGO1/res/leaf_3.cur new file mode 100644 index 00000000..25e6935f Binary files /dev/null and b/LEGO1/res/leaf_3.cur differ diff --git a/LEGO1/res/leaf_4.cur b/LEGO1/res/leaf_4.cur new file mode 100644 index 00000000..73ec0799 Binary files /dev/null and b/LEGO1/res/leaf_4.cur differ diff --git a/LEGO1/res/leaf_5.cur b/LEGO1/res/leaf_5.cur new file mode 100644 index 00000000..8d8df94e Binary files /dev/null and b/LEGO1/res/leaf_5.cur differ diff --git a/LEGO1/res/leaf_6.cur b/LEGO1/res/leaf_6.cur new file mode 100644 index 00000000..04615d16 Binary files /dev/null and b/LEGO1/res/leaf_6.cur differ diff --git a/LEGO1/res/leaf_7.cur b/LEGO1/res/leaf_7.cur new file mode 100644 index 00000000..9795b1df Binary files /dev/null and b/LEGO1/res/leaf_7.cur differ diff --git a/LEGO1/res/lego1.rc b/LEGO1/res/lego1.rc new file mode 100644 index 00000000..44e07d7c --- /dev/null +++ b/LEGO1/res/lego1.rc @@ -0,0 +1,39 @@ +#include "resource.h" + +LEGO1_LEAF4 CURSOR "leaf_4.cur" +LEGO1_LEAF7 CURSOR "leaf_7.cur" +LEGO1_LEAF1 CURSOR "leaf_1.cur" +LEGO1_LEAF2 CURSOR "leaf_2.cur" +LEGO1_LEAF6 CURSOR "leaf_6.cur" +LEGO1_LEAF0 CURSOR "leaf_0.cur" +LEGO1_LEAF5 CURSOR "leaf_5.cur" +LEGO1_LEAF3 CURSOR "leaf_3.cur" +LEGO1_ARROW CURSOR "arrow.cur" +LEGO1_BUSY CURSOR "busy.cur" + +1 VERSIONINFO +FILEVERSION 1,1,0,0 +PRODUCTVERSION 1,1,0,0 +FILEOS 0x40004 +FILETYPE 0x2 +{ +BLOCK "StringFileInfo" +{ + BLOCK "040904b0" + { + VALUE "CompanyName", "Mindscape, Inc." + VALUE "FileDescription", "LegoOmni Library" + VALUE "FileVersion", "1, 1, 0, 0" + VALUE "InternalName", "LegoOmni Library" + VALUE "LegalCopyright", "Copyright \xA9 1997" + VALUE "OriginalFilename", "LegoOmni Library" + VALUE "ProductName", "LegoOmni Library" + VALUE "ProductVersion", "1, 1, 0, 0" + } +} + +BLOCK "VarFileInfo" +{ + VALUE "Translation", 0x0409, 0x04B0 +} +} diff --git a/LEGO1/res/resource.h b/LEGO1/res/resource.h new file mode 100644 index 00000000..2402acad --- /dev/null +++ b/LEGO1/res/resource.h @@ -0,0 +1,10 @@ +#define LEGO1_ARROW 101 +#define LEGO1_LEAF4 102 +#define LEGO1_LEAF7 103 +#define LEGO1_LEAF1 104 +#define LEGO1_LEAF2 105 +#define LEGO1_LEAF6 106 +#define LEGO1_LEAF0 107 +#define LEGO1_LEAF5 108 +#define LEGO1_LEAF3 109 +#define LEGO1_BUSY 111 diff --git a/LEGO1/score.h b/LEGO1/score.h deleted file mode 100644 index 89d9608d..00000000 --- a/LEGO1/score.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef SCORE_H -#define SCORE_H - -#include "legoeventnotificationparam.h" -#include "legoworld.h" -#include "mxactionnotificationparam.h" -#include "mxtype17notificationparam.h" -#include "scorestate.h" - -// VTABLE: LEGO1 0x100d4018 -// SIZE 0x104 -class Score : public LegoWorld { -public: - Score(); - virtual ~Score() override; // vtable+0x0 - virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 - - // FUNCTION: LEGO1 0x100010c0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f0050 - return "Score"; - } - - // FUNCTION: LEGO1 0x100010d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, Score::ClassName()) || LegoWorld::IsA(p_name); - } - - // SYNTHETIC: LEGO1 0x100011e0 - // Score::`scalar deleting destructor' - - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+18 - virtual void Stop() override; // vtable+50 - virtual MxBool VTable0x5c() override; // vtable+5c - virtual MxBool VTable0x64() override; // vtable+64 - virtual void VTable0x68(MxBool p_add) override; // vtable+68 - - void Paint(); - MxLong FUN_10001510(MxEndActionNotificationParam& p_param); - MxLong FUN_100016d0(MxType17NotificationParam& p_param); - void FillArea(MxU32 p_x, MxU32 p_y, MxS16 p_color); - -protected: - undefined4 m_unk0xf8; - ScoreState* m_state; - MxU8* m_surface; - -private: - void DeleteScript(); -}; - -#endif // SCORE_H diff --git a/LEGO1/skateboard.cpp b/LEGO1/skateboard.cpp deleted file mode 100644 index 96a26bcd..00000000 --- a/LEGO1/skateboard.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "skateboard.h" - -#include "decomp.h" -#include "mxnotificationmanager.h" -#include "mxomni.h" - -DECOMP_SIZE_ASSERT(SkateBoard, 0x168); - -// FUNCTION: LEGO1 0x1000fd40 -SkateBoard::SkateBoard() -{ - this->m_unk0x160 = 0; - this->m_unk0x13c = 15.0; - this->m_unk0x150 = 3.5; - this->m_unk0x148 = 1; - - NotificationManager()->Register(this); -} diff --git a/LEGO1/skateboard.h b/LEGO1/skateboard.h deleted file mode 100644 index 671c7f86..00000000 --- a/LEGO1/skateboard.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SKATEBOARD_H -#define SKATEBOARD_H - -#include "decomp.h" -#include "islepathactor.h" - -// VTABLE: LEGO1 0x100d55f0 -// SIZE 0x168 -class SkateBoard : public IslePathActor { -public: - SkateBoard(); - - // FUNCTION: LEGO1 0x1000fdd0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f041c - return "SkateBoard"; - } - - // FUNCTION: LEGO1 0x1000fde0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, SkateBoard::ClassName()) || IslePathActor::IsA(p_name); - } - -private: - // TODO: SkateBoard types - undefined m_unk0x160; - undefined m_unk0x161[0x7]; -}; - -#endif // SKATEBOARD_H diff --git a/LEGO1/tgl/d3drm/camera.cpp b/LEGO1/tgl/d3drm/camera.cpp index 5084c2ca..c7bc06f9 100644 --- a/LEGO1/tgl/d3drm/camera.cpp +++ b/LEGO1/tgl/d3drm/camera.cpp @@ -2,8 +2,8 @@ using namespace TglImpl; -DECOMP_SIZE_ASSERT(Camera, 0x4); -DECOMP_SIZE_ASSERT(CameraImpl, 0x8); +DECOMP_SIZE_ASSERT(Camera, 0x04); +DECOMP_SIZE_ASSERT(CameraImpl, 0x08); // FUNCTION: LEGO1 0x100a36f0 void* CameraImpl::ImplementationDataPtr() @@ -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..bc7da727 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); @@ -112,7 +112,7 @@ Result GroupImpl::RemoveAll() return Error; } -// STUB: LEGO1 0x100a34c0 +// STUB: LEGO1 0x100a3540 Result GroupImpl::Unknown() { return Error; diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index 5ba877bb..d1e2e7fc 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -1,14 +1,15 @@ -#include "../tgl.h" +#include "compat.h" #include "decomp.h" +#include "tgl/tgl.h" #include // Forward declare D3D types -struct IDirect3DRM; -struct IDirect3DRMDevice; +struct IDirect3DRM2; +struct IDirect3DRMDevice2; struct IDirect3DRMViewport; -struct IDirect3DRMFrame; +struct IDirect3DRMFrame2; struct IDirect3DRMMesh; struct IDirect3DRMMeshBuilder; struct IDirect3DRMTexture; @@ -35,35 +36,34 @@ class MeshImpl; class TextureImpl; class UnkImpl; -// VTABLE 0x100db910 +// VTABLE: LEGO1 0x100db910 class RendererImpl : public Renderer { public: RendererImpl() : m_data(0) {} - ~RendererImpl() { Destroy(); }; + ~RendererImpl() override { Destroy(); } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Device* CreateDevice(const DeviceDirect3DCreateData&); - virtual Device* CreateDevice(const DeviceDirectDrawCreateData&); + Device* CreateDevice(const DeviceDirectDrawCreateData&) override; + Device* CreateDevice(const DeviceDirect3DCreateData&) override; // vtable+0x10 - virtual View* CreateView( + View* CreateView( const Device*, const Camera*, unsigned long x, unsigned long y, unsigned long width, unsigned long height - ); - virtual Camera* CreateCamera(); - virtual Light* CreateLight(LightType, float r, float g, float b); - virtual Group* CreateGroup(const Group* pParent); + ) override; + Camera* CreateCamera() override; + Light* CreateLight(LightType, float r, float g, float b) override; + Group* CreateGroup(const Group* pParent) override; // vtable+0x20 - virtual Unk* CreateUnk(); - virtual Texture* CreateTexture(); - virtual Texture* CreateTexture( + Unk* CreateUnk() override; + Texture* CreateTexture( int width, int height, int bitsPerTexel, @@ -71,25 +71,46 @@ class RendererImpl : public Renderer { int pTexelsArePersistent, int paletteEntryCount, const PaletteEntry* pEntries - ); - virtual Result SetTextureDefaultShadeCount(unsigned long); + ) override; + Texture* CreateTexture() override; + + Result SetTextureDefaultShadeCount(unsigned long) override; // vtable+0x30 - virtual Result SetTextureDefaultColorCount(unsigned long); + Result SetTextureDefaultColorCount(unsigned long) override; public: inline Result Create(); inline void Destroy(); private: - IDirect3DRM* m_data; + IDirect3DRM2* m_data; }; -// VTABLE 0x100db988 +extern IDirect3DRM2* g_pD3DRM; + +inline void RendererDestroy(IDirect3DRM2* pRenderer) +{ + int refCount = pRenderer->Release(); + if (refCount <= 0) { + g_pD3DRM = NULL; + } +} + +// Inlined only +void RendererImpl::Destroy() +{ + if (m_data) { + RendererDestroy(m_data); + m_data = NULL; + } +} + +// VTABLE: LEGO1 0x100db988 class DeviceImpl : public Device { public: DeviceImpl() : m_data(0) {} - ~DeviceImpl() + ~DeviceImpl() override { if (m_data) { m_data->Release(); @@ -97,36 +118,36 @@ class DeviceImpl : public Device { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual unsigned long GetWidth(); - virtual unsigned long GetHeight(); + unsigned long GetWidth() override; + unsigned long GetHeight() override; // vtable+0x10 - virtual Result SetColorModel(ColorModel); - virtual Result SetShadingModel(ShadingModel); - virtual Result SetShadeCount(unsigned long); - virtual Result SetDither(int); + Result SetColorModel(ColorModel) override; + Result SetShadingModel(ShadingModel) override; + Result SetShadeCount(unsigned long) override; + Result SetDither(int) override; // vtable+0x20 - virtual Result Update(); - virtual void InitFromD3DDevice(Device*); - virtual void InitFromWindowsDevice(Device*); + Result Update() override; + void InitFromD3DDevice(Device*) override; + void InitFromWindowsDevice(Device*) override; - inline IDirect3DRMDevice* ImplementationData() const { return m_data; } + inline IDirect3DRMDevice2* ImplementationData() const { return m_data; } friend class RendererImpl; private: - IDirect3DRMDevice* m_data; + IDirect3DRMDevice2* m_data; }; -// VTABLE 0x100db9e8 +// VTABLE: LEGO1 0x100db9e8 class ViewImpl : public View { public: ViewImpl() : m_data(0) {} - ~ViewImpl() + ~ViewImpl() override { if (m_data) { m_data->Release(); @@ -134,39 +155,39 @@ class ViewImpl : public View { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result Add(const Light*); - virtual Result Remove(const Light*); + Result Add(const Light*) override; + Result Remove(const Light*) override; // vtable+0x10 - virtual Result SetCamera(const Camera*); - virtual Result SetProjection(ProjectionType); - virtual Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees); - virtual Result SetBackgroundColor(float r, float g, float b); + Result SetCamera(const Camera*) override; + Result SetProjection(ProjectionType) override; + Result SetFrustrum(float frontClippingDistance, float backClippingDistance, float degrees) override; + Result SetBackgroundColor(float r, float g, float b) override; // vtable+0x20 - virtual Result GetBackgroundColor(float* r, float* g, float* b); - virtual Result Clear(); - virtual Result Render(const Light*); - virtual Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height); + Result GetBackgroundColor(float* r, float* g, float* b) override; + Result Clear() override; + Result Render(const Light*) override; + Result ForceUpdate(unsigned long x, unsigned long y, unsigned long width, unsigned long height) override; // vtable+0x30 - virtual Result TransformWorldToScreen(const float world[3], float screen[4]); - virtual Result TransformScreenToWorld(const float screen[4], float world[3]); - virtual Result Pick( + Result TransformWorldToScreen(const float world[3], float screen[4]) override; + Result TransformScreenToWorld(const float screen[4], float world[3]) override; + Result Pick( unsigned long x, unsigned long y, const Group** ppGroupsToPickFrom, int groupsToPickFromCount, const Group**& rppPickedGroups, int& rPickedGroupCount - ); + ) override; inline IDirect3DRMViewport* ImplementationData() const { return m_data; } - static Result ViewportCreateAppData(IDirect3DRM*, IDirect3DRMViewport*, IDirect3DRMFrame*); + static Result ViewportCreateAppData(IDirect3DRM2*, IDirect3DRMViewport*, IDirect3DRMFrame2*); friend class RendererImpl; @@ -174,11 +195,11 @@ class ViewImpl : public View { IDirect3DRMViewport* m_data; }; -// VTABLE 0x100dbad8 +// VTABLE: LEGO1 0x100dbad8 class CameraImpl : public Camera { public: CameraImpl() : m_data(0) {} - ~CameraImpl() + ~CameraImpl() override { if (m_data) { m_data->Release(); @@ -186,24 +207,24 @@ class CameraImpl : public Camera { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + Result SetTransformation(FloatMatrix4&) override; - inline IDirect3DRMFrame* ImplementationData() const { return m_data; } + inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } friend class RendererImpl; private: - IDirect3DRMFrame* m_data; + IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbaf8 +// VTABLE: LEGO1 0x100dbaf8 class LightImpl : public Light { public: LightImpl() : m_data(0) {} - ~LightImpl() + ~LightImpl() override { if (m_data) { m_data->Release(); @@ -211,25 +232,25 @@ class LightImpl : public Light { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); - virtual Result SetColor(float r, float g, float b); + Result SetTransformation(FloatMatrix4&) override; + Result SetColor(float r, float g, float b) override; - inline IDirect3DRMFrame* ImplementationData() const { return m_data; } + inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } friend class RendererImpl; private: - IDirect3DRMFrame* m_data; + IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbb88 +// VTABLE: LEGO1 0x100dbb88 class MeshImpl : public Mesh { public: MeshImpl() : m_data(0) {} - ~MeshImpl() + ~MeshImpl() override { if (m_data) { delete m_data; @@ -237,20 +258,20 @@ class MeshImpl : public Mesh { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetColor(float r, float g, float b, float a); - virtual Result SetTexture(const Texture*); + Result SetColor(float r, float g, float b, float a) override; + Result SetTexture(const Texture*) override; // vtable+0x10 - virtual Result GetTexture(Texture*&); - virtual Result SetTextureMappingMode(ProjectionType); - virtual Result SetShadingModel(ShadingModel); - virtual Mesh* DeepClone(Unk*); + Result GetTexture(Texture*&) override; + Result SetTextureMappingMode(ProjectionType) override; + Result SetShadingModel(ShadingModel) override; + Mesh* DeepClone(Unk*) override; // vtable+0x20 - virtual Mesh* ShallowClone(Unk*); + Mesh* ShallowClone(Unk*) override; struct MeshData { IDirect3DRMMesh* groupMesh; @@ -265,11 +286,11 @@ class MeshImpl : public Mesh { MeshData* m_data; }; -// VTABLE 0x100dba68 +// VTABLE: LEGO1 0x100dba68 class GroupImpl : public Group { public: GroupImpl() : m_data(0) {} - ~GroupImpl() + ~GroupImpl() override { if (m_data) { m_data->Release(); @@ -277,38 +298,38 @@ class GroupImpl : public Group { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); - virtual Result SetColor(float r, float g, float b, float a); + Result SetTransformation(FloatMatrix4&) override; + Result SetColor(float r, float g, float b, float a) override; // vtable+0x10 - virtual Result SetTexture(const Texture*); - virtual Result GetTexture(Texture*&); - virtual Result SetMaterialMode(MaterialMode); - virtual Result Add(const Group*); + Result SetTexture(const Texture*) override; + Result GetTexture(Texture*&) override; + Result SetMaterialMode(MaterialMode) override; + Result Add(const Mesh*) override; // vtable+0x20 - virtual Result Add(const Mesh*); - virtual Result Remove(const Group*); - virtual Result Remove(const Mesh*); - virtual Result RemoveAll(); + Result Add(const Group*) override; + Result Remove(const Mesh*) override; + Result Remove(const Group*) override; + Result RemoveAll() override; // vtable+0x30 - virtual Result Unknown(); + Result Unknown() override; friend class RendererImpl; private: - IDirect3DRMFrame* m_data; + IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbb18 +// VTABLE: LEGO1 0x100dbb18 class UnkImpl : public Unk { public: UnkImpl() : m_data(0) {} - ~UnkImpl() + ~UnkImpl() override { if (m_data) { m_data->Release(); @@ -316,10 +337,10 @@ class UnkImpl : public Unk { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetMeshData( + Result SetMeshData( unsigned long faceCount, unsigned long vertexCount, const float (*pPositions)[3], @@ -327,11 +348,11 @@ class UnkImpl : public Unk { const float (*pTextureCoordinates)[2], unsigned long vertexPerFaceCount, unsigned long* pFaceData - ); - virtual Result GetBoundingBox(float min[3], float max[3]); + ) override; + Result GetBoundingBox(float min[3], float max[3]) override; // vtable+0x10 - virtual Unk* Clone(); + Unk* Clone() override; inline IDirect3DRMMesh* ImplementationData() const { return m_data; } @@ -364,11 +385,11 @@ class TglD3DRMIMAGE { int m_texelsAllocatedByClient; }; -// VTABLE 0x100dbb48 +// VTABLE: LEGO1 0x100dbb48 class TextureImpl : public Texture { public: TextureImpl() : m_data(0) {} - ~TextureImpl() + ~TextureImpl() override { if (m_data) { m_data->Release(); @@ -376,23 +397,23 @@ class TextureImpl : public Texture { } } - virtual void* ImplementationDataPtr(); + void* ImplementationDataPtr() override; // vtable+0x08 - virtual Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels); - virtual void FillRowsOfTexture(int y, int height, void* pBuffer); + Result SetTexels(int width, int height, int bitsPerTexel, void* pTexels) override; + void FillRowsOfTexture(int y, int height, void* pBuffer) override; // vtable+0x10 - virtual Result Changed(int texelsChanged, int paletteChanged); - virtual Result GetBufferAndPalette( + Result Changed(int texelsChanged, int paletteChanged) override; + Result GetBufferAndPalette( int* pWidth, int* pHeight, int* pDepth, void** ppBuffer, int* ppPaletteSize, PaletteEntry** ppPalette - ); - virtual Result SetPalette(int entryCount, PaletteEntry* entries); + ) override; + Result SetPalette(int entryCount, PaletteEntry* entries) override; inline IDirect3DRMTexture* ImplementationData() const { return m_data; } inline void SetImplementation(IDirect3DRMTexture* pData) { m_data = pData; } @@ -454,7 +475,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..0fe66bfb 100644 --- a/LEGO1/tgl/d3drm/light.cpp +++ b/LEGO1/tgl/d3drm/light.cpp @@ -2,8 +2,8 @@ using namespace TglImpl; -DECOMP_SIZE_ASSERT(Light, 0x4); -DECOMP_SIZE_ASSERT(LightImpl, 0x8); +DECOMP_SIZE_ASSERT(Light, 0x04); +DECOMP_SIZE_ASSERT(LightImpl, 0x08); // FUNCTION: LEGO1 0x100a3770 void* LightImpl::ImplementationDataPtr() @@ -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/d3drm/mesh.cpp b/LEGO1/tgl/d3drm/mesh.cpp index f044d512..ceaf7079 100644 --- a/LEGO1/tgl/d3drm/mesh.cpp +++ b/LEGO1/tgl/d3drm/mesh.cpp @@ -4,8 +4,8 @@ using namespace TglImpl; DECOMP_SIZE_ASSERT(D3DRMVERTEX, 0x24); -DECOMP_SIZE_ASSERT(Mesh, 0x4); -DECOMP_SIZE_ASSERT(MeshImpl, 0x8); +DECOMP_SIZE_ASSERT(Mesh, 0x04); +DECOMP_SIZE_ASSERT(MeshImpl, 0x08); // FUNCTION: LEGO1 0x100a3ed0 void* MeshImpl::ImplementationDataPtr() diff --git a/LEGO1/tgl/d3drm/renderer.cpp b/LEGO1/tgl/d3drm/renderer.cpp index d098f7ff..c3669e05 100644 --- a/LEGO1/tgl/d3drm/renderer.cpp +++ b/LEGO1/tgl/d3drm/renderer.cpp @@ -13,8 +13,11 @@ Renderer* Tgl::CreateRenderer() return renderer; } +namespace TglImpl +{ // GLOBAL: LEGO1 0x1010103c -IDirect3DRM* g_pD3DRM = NULL; +IDirect3DRM2* g_pD3DRM = NULL; +} // namespace TglImpl // Inlined only Result RendererImpl::Create() @@ -31,24 +34,7 @@ Result RendererImpl::Create() return (m_data != NULL) ? Success : Error; } -inline void RendererDestroy(IDirect3DRM* pRenderer) -{ - int refCount = pRenderer->Release(); - if (refCount <= 0) { - g_pD3DRM = NULL; - } -} - -// Inlined only -void RendererImpl::Destroy() -{ - if (m_data) { - RendererDestroy(m_data); - m_data = NULL; - } -} - -// FUNCTION: LEGO1 0x100a1894 +// FUNCTION: LEGO1 0x100a1830 Device* RendererImpl::CreateDevice(const DeviceDirect3DCreateData& data) { DeviceImpl* device = new DeviceImpl(); @@ -61,7 +47,7 @@ Device* RendererImpl::CreateDevice(const DeviceDirect3DCreateData& data) } // GLOBAL: LEGO1 0x10101040 -static int gSetBufferCount = 1; +static int g_SetBufferCount = 1; // FUNCTION: LEGO1 0x100a1900 Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) @@ -73,7 +59,7 @@ Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) data.m_pBackBuffer, &device->m_data ); - if (SUCCEEDED(result) && data.m_pBackBuffer && gSetBufferCount) { + if (SUCCEEDED(result) && data.m_pBackBuffer && g_SetBufferCount) { device->m_data->SetBufferCount(2); } if (!SUCCEEDED(result)) { @@ -84,9 +70,9 @@ Device* RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& data) } inline Result RendererCreateView( - IDirect3DRM* pRenderer, - IDirect3DRMDevice* pDevice, - IDirect3DRMFrame* pCamera, + IDirect3DRM2* pRenderer, + IDirect3DRMDevice2* pDevice, + IDirect3DRMFrame2* pCamera, IDirect3DRMViewport*& rpView, unsigned long x, unsigned long y, @@ -133,7 +119,7 @@ View* RendererImpl::CreateView( return view; } -inline Result RendererCreateGroup(IDirect3DRM* pRenderer, IDirect3DRMFrame* pParent, IDirect3DRMFrame*& rpGroup) +inline Result RendererCreateGroup(IDirect3DRM2* pRenderer, IDirect3DRMFrame2* pParent, IDirect3DRMFrame2*& rpGroup) { Result result = ResultVal(pRenderer->CreateFrame(NULL, &rpGroup)); if (Succeeded(result) && pParent) { @@ -195,7 +181,7 @@ Light* RendererImpl::CreateLight(LightType type, float r, float g, float b) translatedType = D3DRMLIGHT_AMBIENT; } - LPDIRECT3DRMFRAME frame; + LPDIRECT3DRMFRAME2 frame; Result result = ResultVal(m_data->CreateFrame(NULL, &frame)); if (Succeeded(result)) { LPDIRECT3DRMLIGHT d3dLight; @@ -240,7 +226,7 @@ Unk* RendererImpl::CreateUnk() } inline Result RendererCreateTexture( - IDirect3DRM* renderer, + IDirect3DRM2* renderer, IDirect3DRMTexture*& texture, int width, int height, @@ -255,7 +241,8 @@ inline Result RendererCreateTexture( Result result; image = new TglD3DRMIMAGE(width, height, bytesPerPixel, pBuffer, useBuffer, paletteSize, pEntries); - result = ResultVal(renderer->CreateTexture(&image->m_image, &texture)); + // TODO: LPDIRECT3DRMTEXTURE2? + result = ResultVal(renderer->CreateTexture(&image->m_image, (LPDIRECT3DRMTEXTURE2*) &texture)); if (Succeeded(result)) { result = TextureImpl::SetImage(texture, image); if (!Succeeded(result)) { diff --git a/LEGO1/tgl/d3drm/texture.cpp b/LEGO1/tgl/d3drm/texture.cpp index 2b2c3eb0..b0ee3813 100644 --- a/LEGO1/tgl/d3drm/texture.cpp +++ b/LEGO1/tgl/d3drm/texture.cpp @@ -150,7 +150,7 @@ Result TextureImpl::Changed(int texelsChanged, int paletteChanged) return ResultVal(m_data->Changed(texelsChanged, paletteChanged)); } -// FUNCTION: LEGO1 0x100a3d00 +// FUNCTION: LEGO1 0x100a3cc0 Result TextureImpl::GetBufferAndPalette( int* width, int* height, diff --git a/LEGO1/tgl/d3drm/unk.cpp b/LEGO1/tgl/d3drm/unk.cpp index debc1484..038b0e9d 100644 --- a/LEGO1/tgl/d3drm/unk.cpp +++ b/LEGO1/tgl/d3drm/unk.cpp @@ -2,8 +2,8 @@ using namespace TglImpl; -DECOMP_SIZE_ASSERT(Unk, 0x4); -DECOMP_SIZE_ASSERT(UnkImpl, 0x8); +DECOMP_SIZE_ASSERT(Unk, 0x04); +DECOMP_SIZE_ASSERT(UnkImpl, 0x08); // FUNCTION: LEGO1 0x100a3830 void* UnkImpl::ImplementationDataPtr() diff --git a/LEGO1/tgl/d3drm/view.cpp b/LEGO1/tgl/d3drm/view.cpp index f8302bc2..dcaa21ae 100644 --- a/LEGO1/tgl/d3drm/view.cpp +++ b/LEGO1/tgl/d3drm/view.cpp @@ -3,12 +3,12 @@ using namespace TglImpl; struct ViewportAppData { - ViewportAppData(IDirect3DRM* pRenderer); + ViewportAppData(IDirect3DRM2* pRenderer); ~ViewportAppData(); - IDirect3DRMFrame* m_pLightFrame; - IDirect3DRMFrame* m_pCamera; - IDirect3DRMFrame* m_pLastRenderedFrame; + IDirect3DRMFrame2* m_pLightFrame; + IDirect3DRMFrame2* m_pCamera; + IDirect3DRMFrame2* m_pLastRenderedFrame; float m_backgroundColorRed; float m_backgroundColorGreen; float m_backgroundColorBlue; @@ -17,7 +17,7 @@ struct ViewportAppData { DECOMP_SIZE_ASSERT(ViewportAppData, 0x18); // FUNCTION: LEGO1 0x100a10b0 -ViewportAppData::ViewportAppData(IDirect3DRM* pRenderer) +ViewportAppData::ViewportAppData(IDirect3DRM2* pRenderer) { pRenderer->CreateFrame(NULL, &m_pLightFrame); m_pCamera = NULL; @@ -46,7 +46,7 @@ ViewportAppData::~ViewportAppData() void ViewportDestroyCallback(IDirect3DRMObject* pObject, void* pArg); // FUNCTION: LEGO1 0x100a1160 -Result ViewImpl::ViewportCreateAppData(IDirect3DRM* pDevice, IDirect3DRMViewport* pView, IDirect3DRMFrame* pCamera) +Result ViewImpl::ViewportCreateAppData(IDirect3DRM2* pDevice, IDirect3DRMViewport* pView, IDirect3DRMFrame2* pCamera) { ViewportAppData* data = new ViewportAppData(pDevice); data->m_pCamera = pCamera; @@ -145,7 +145,7 @@ Result ViewImpl::Remove(const Light* pLight) Result ViewImpl::SetCamera(const Camera* pCamera) { const CameraImpl* camera = static_cast(pCamera); - IDirect3DRMFrame* frame = camera->ImplementationData(); + IDirect3DRMFrame2* frame = camera->ImplementationData(); ViewportAppData* pViewportAppData; Result result; @@ -249,9 +249,9 @@ Result ViewImpl::Render(const Light* pCamera) { ViewportAppData* appdata = ViewportGetData(m_data); - IDirect3DRMFrame* light = static_cast(pCamera)->ImplementationData(); + IDirect3DRMFrame2* light = static_cast(pCamera)->ImplementationData(); - IDirect3DRMFrame* lastRendered = appdata->m_pLastRenderedFrame; + IDirect3DRMFrame2* lastRendered = appdata->m_pLastRenderedFrame; if (light != lastRendered) { if (lastRendered) { lastRendered->DeleteChild(appdata->m_pCamera); diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index 9bf4ce3a..630510b9 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -57,8 +57,8 @@ struct PaletteEntry { }; struct DeviceDirect3DCreateData { - IDirect3D* m_pDirect3D; - IDirect3DDevice* m_pDirect3DDevice; + IDirect3D2* m_pDirect3D; + IDirect3DDevice2* m_pDirect3DDevice; }; struct DeviceDirectDrawCreateData { @@ -98,20 +98,23 @@ class Mesh; class Texture; class Unk; -// VTABLE 0x100db980 +// VTABLE: LEGO1 0x100db980 class Object { public: virtual ~Object() {} virtual void* ImplementationDataPtr() = 0; + + // SYNTHETIC: LEGO1 0x100a2250 + // Tgl::Object::`scalar deleting destructor' }; -// VTABLE 0x100db948 +// VTABLE: LEGO1 0x100db948 class Renderer : public Object { public: // vtable+0x08 - virtual Device* CreateDevice(const DeviceDirect3DCreateData&) = 0; virtual Device* CreateDevice(const DeviceDirectDrawCreateData&) = 0; + virtual Device* CreateDevice(const DeviceDirect3DCreateData&) = 0; // vtable+0x10 virtual View* CreateView( @@ -128,7 +131,6 @@ class Renderer : public Object { // vtable+0x20 virtual Unk* CreateUnk() = 0; - virtual Texture* CreateTexture() = 0; virtual Texture* CreateTexture( int width, int height, @@ -138,15 +140,19 @@ class Renderer : public Object { int paletteEntryCount, const PaletteEntry* pEntries ) = 0; + virtual Texture* CreateTexture() = 0; virtual Result SetTextureDefaultShadeCount(unsigned long) = 0; // vtable+0x30 virtual Result SetTextureDefaultColorCount(unsigned long) = 0; + + // SYNTHETIC: LEGO1 0x100a17c0 + // Tgl::Renderer::`scalar deleting destructor' }; Renderer* CreateRenderer(); -// VTABLE 0x100db9b8 +// VTABLE: LEGO1 0x100db9b8 class Device : public Object { public: // vtable+0x08 @@ -163,9 +169,12 @@ class Device : public Object { virtual Result Update() = 0; virtual void InitFromD3DDevice(Device*) = 0; virtual void InitFromWindowsDevice(Device*) = 0; + + // SYNTHETIC: LEGO1 0x100a28e0 + // Tgl::Device::`scalar deleting destructor' }; -// VTABLE 0x100dba28 +// VTABLE: LEGO1 0x100dba28 class View : public Object { public: virtual Result Add(const Light*) = 0; @@ -217,22 +226,31 @@ class View : public Object { const Group**& rppPickedGroups, int& rPickedGroupCount ) = 0; + + // SYNTHETIC: LEGO1 0x100a2950 + // Tgl::View::`scalar deleting destructor' }; -// VTABLE 0x100dbae8 +// VTABLE: LEGO1 0x100dbae8 class Camera : public Object { public: - virtual Result SetTransformation(const FloatMatrix4&) = 0; + virtual Result SetTransformation(FloatMatrix4&) = 0; + + // SYNTHETIC: LEGO1 0x100a2a30 + // Tgl::Camera::`scalar deleting destructor' }; -// 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; + + // SYNTHETIC: LEGO1 0x100a2aa0 + // Tgl::Light::`scalar deleting destructor' }; -// VTABLE 0x100dbbb0 +// VTABLE: LEGO1 0x100dbbb0 class Mesh : public Object { public: virtual Result SetColor(float r, float g, float b, float a) = 0; @@ -247,31 +265,37 @@ class Mesh : public Object { // Just get another Group pointing to the same underlying data virtual Mesh* ShallowClone(Unk*) = 0; + + // SYNTHETIC: LEGO1 0x100a3e60 + // Tgl::Mesh::`scalar deleting destructor' }; -// 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; virtual Result SetMaterialMode(MaterialMode) = 0; - virtual Result Add(const Group*) = 0; virtual Result Add(const Mesh*) = 0; - virtual Result Remove(const Group*) = 0; + virtual Result Add(const Group*) = 0; virtual Result Remove(const Mesh*) = 0; + virtual Result Remove(const Group*) = 0; virtual Result RemoveAll() = 0; // This is TransformLocalToWorld in the leak, however it seems // to have been replaced by something else in the shipped code. virtual Result Unknown() = 0; + + // SYNTHETIC: LEGO1 0x100a29c0 + // Tgl::Group::`scalar deleting destructor' }; // 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( @@ -285,9 +309,12 @@ class Unk : public Object { ) = 0; virtual Result GetBoundingBox(float min[3], float max[3]) = 0; virtual Unk* Clone() = 0; + + // SYNTHETIC: LEGO1 0x100a2b10 + // Tgl::Unk::`scalar deleting destructor' }; -// VTABLE 0x100dbb68 +// VTABLE: LEGO1 0x100dbb68 class Texture : public Object { public: // vtable+0x08 @@ -305,6 +332,9 @@ class Texture : public Object { PaletteEntry** ppPalette ) = 0; virtual Result SetPalette(int entryCount, PaletteEntry* pEntries) = 0; + + // SYNTHETIC: LEGO1 0x100a2b80 + // Tgl::Texture::`scalar deleting destructor' }; } // namespace Tgl 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/towtrack.cpp b/LEGO1/towtrack.cpp deleted file mode 100644 index 3fd0d84d..00000000 --- a/LEGO1/towtrack.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "towtrack.h" - -DECOMP_SIZE_ASSERT(TowTrack, 0x180); - -// FUNCTION: LEGO1 0x1004c720 -TowTrack::TowTrack() -{ - this->m_unk0x168 = 0; - this->m_unk0x16a = -1; - this->m_unk0x164 = 0; - this->m_unk0x16c = 0; - this->m_unk0x170 = -1; - this->m_unk0x16e = 0; - this->m_unk0x174 = -1; - this->m_unk0x13c = 40.0; - this->m_unk0x178 = 1.0; -} diff --git a/LEGO1/towtrack.h b/LEGO1/towtrack.h deleted file mode 100644 index 2243f9a2..00000000 --- a/LEGO1/towtrack.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef TOWTRACK_H -#define TOWTRACK_H - -#include "decomp.h" -#include "islepathactor.h" - -// VTABLE: LEGO1 0x100d7ee0 -// SIZE 0x180 -class TowTrack : public IslePathActor { -public: - TowTrack(); - - // FUNCTION: LEGO1 0x1004c7c0 - inline virtual const char* ClassName() const override // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f03b8 - return "TowTrack"; - } - - // FUNCTION: LEGO1 0x1004c7d0 - inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, TowTrack::ClassName()) || IslePathActor::IsA(p_name); - } - -private: - // TODO: TowTrack field types - undefined m_unk0x154[4]; - MxS32 m_unk0x164; - MxS16 m_unk0x168; - MxS16 m_unk0x16a; - MxS16 m_unk0x16c; - MxS16 m_unk0x16e; - MxS32 m_unk0x170; - MxS32 m_unk0x174; - MxFloat m_unk0x178; - undefined4 m_unk0x17c; -}; - -#endif // TOWTRACK_H diff --git a/LEGO1/towtrackmissionstate.cpp b/LEGO1/towtrackmissionstate.cpp deleted file mode 100644 index cdef8a88..00000000 --- a/LEGO1/towtrackmissionstate.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "towtrackmissionstate.h" - -DECOMP_SIZE_ASSERT(TowTrackMissionState, 0x28) - -// STUB: LEGO1 0x1004dd30 -TowTrackMissionState::TowTrackMissionState() -{ - // TODO -} diff --git a/LEGO1/towtrackmissionstate.h b/LEGO1/towtrackmissionstate.h deleted file mode 100644 index 7537cb94..00000000 --- a/LEGO1/towtrackmissionstate.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef TOWTRACKMISSIONSTATE_H -#define TOWTRACKMISSIONSTATE_H - -#include "legostate.h" - -// VTABLE: LEGO1 0x100d7fd8 -// SIZE 0x28 -class TowTrackMissionState : public LegoState { -public: - TowTrackMissionState(); - - // FUNCTION: LEGO1 0x1004dfa0 - inline virtual const char* ClassName() const // vtable+0x0c - { - // GLOBAL: LEGO1 0x100f00bc - return "TowTrackMissionState"; - } - - // FUNCTION: LEGO1 0x1004dfb0 - inline virtual MxBool IsA(const char* p_name) const // vtable+0x10 - { - return !strcmp(p_name, TowTrackMissionState::ClassName()) || LegoState::IsA(p_name); - } - - inline MxU16 GetColor(MxU8 p_id) - { - switch (p_id) { - case 1: - return m_color1; - case 2: - return m_color2; - case 3: - return m_color3; - case 4: - return m_color4; - case 5: - return m_color5; - default: - return 0; - } - } - -protected: - undefined m_unk0x8[0x14]; - MxU16 m_color1; - MxU16 m_color2; - MxU16 m_color3; - MxU16 m_color4; - MxU16 m_color5; -}; - -#endif // TOWTRACKMISSIONSTATE_H diff --git a/LEGO1/viewmanager/viewlodlist.cpp b/LEGO1/viewmanager/viewlodlist.cpp new file mode 100644 index 00000000..1cd0783e --- /dev/null +++ b/LEGO1/viewmanager/viewlodlist.cpp @@ -0,0 +1,54 @@ +#include "viewlodlist.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(ViewLODListManager, 0x14); + +// FUNCTION: LEGO1 0x100a6fd0 +ViewLODListManager::ViewLODListManager() +{ +} + +// STUB: LEGO1 0x100a7130 +ViewLODListManager::~ViewLODListManager() +{ + // TODO +} + +// STUB: LEGO1 0x100a72c0 +ViewLODList* ViewLODListManager::Create(const ROIName& rROIName, int lodCount) +{ + // returned ViewLODList has a refCount of 1, i.e. caller must call Release() + // when it no longer holds on to the list + + ViewLODList* pLODList; + int refCount; + char* pROIName; + + assert(!Lookup(rROIName)); + + pLODList = new ViewLODList(lodCount); + refCount = pLODList->AddRef(); + assert(refCount == 1); + + pROIName = new char[strlen(rROIName) + 1]; + strcpy(pROIName, rROIName); + + m_map[pROIName] = pLODList; + + // NOTE: Lookup() adds a refCount + assert((Lookup(rROIName) == pLODList) && (pLODList->Release() == 1)); + + return pLODList; +} + +// STUB: LEGO1 0x100a75b0 +ViewLODList* ViewLODListManager::Lookup(const ROIName&) const +{ + return NULL; +} + +// STUB: LEGO1 0x100a7680 +void ViewLODListManager::Destroy(ViewLODList* lodList) +{ +} diff --git a/LEGO1/viewmanager/viewlodlist.h b/LEGO1/viewmanager/viewlodlist.h index 5fa31454..d8516955 100644 --- a/LEGO1/viewmanager/viewlodlist.h +++ b/LEGO1/viewmanager/viewlodlist.h @@ -1,9 +1,12 @@ #ifndef VIEWLODLIST_H #define VIEWLODLIST_H -#include "../realtime/lodlist.h" #include "assert.h" #include "compat.h" +#include "mxstl/stlcompat.h" +#include "realtime/lodlist.h" + +#include #pragma warning(disable : 4237) #pragma warning(disable : 4786) @@ -24,7 +27,7 @@ class ViewLODList : public LODList { protected: ViewLODList(size_t capacity); - ~ViewLODList(); + ~ViewLODList() override; public: inline int AddRef(); @@ -59,6 +62,8 @@ struct ROINameComparator { // It stores ViewLODLists under a name, the name of the ROI where // the ViewLODList belongs. +// VTABLE: LEGO1 0x100dbdbc +// SIZE 0x14 class ViewLODListManager { typedef map ViewLODListMap; @@ -72,7 +77,7 @@ class ViewLODListManager { // creates an LODList with room for lodCount LODs for a named ROI // returned LODList has a refCount of 1, i.e. caller must call Release() // when it no longer holds on to the list - ViewLODList* Create(const ROIName&, int lodCount); + ViewLODList* Create(const ROIName& rROIName, int lodCount); // returns an LODList for a named ROI // returned LODList's refCount is increased, i.e. caller must call Release() @@ -84,10 +89,29 @@ class ViewLODListManager { void Dump(void (*pTracer)(const char*, ...)) const; #endif + // SYNTHETIC: LEGO1 0x100a70c0 + // ViewLODListManager::`scalar deleting destructor' + private: 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 @@ -109,9 +133,17 @@ inline int ViewLODList::AddRef() inline int ViewLODList::Release() { assert(m_refCount > 0); - if (!--m_refCount) + if (!--m_refCount) { m_owner->Destroy(this); + } return m_refCount; } +#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..3e68f78e 100644 --- a/LEGO1/viewmanager/viewmanager.cpp +++ b/LEGO1/viewmanager/viewmanager.cpp @@ -1,7 +1,41 @@ #include "viewmanager.h" +#include "decomp.h" + +DECOMP_SIZE_ASSERT(ViewManager, 0x1bc) + +// STUB: LEGO1 0x100a5eb0 +ViewManager::ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view) +{ +} + +// STUB: LEGO1 0x100a60c0 +ViewManager::~ViewManager() +{ +} + // STUB: LEGO1 0x100a64d0 void ViewManager::RemoveAll(ViewROI*) { // TODO } + +// STUB: LEGO1 0x100a6930 +void ViewManager::Update(float p_previousRenderTime, float p_und2) +{ +} + +// 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..625722b5 100644 --- a/LEGO1/viewmanager/viewmanager.h +++ b/LEGO1/viewmanager/viewmanager.h @@ -1,11 +1,34 @@ #ifndef VIEWMANAGER_H #define VIEWMANAGER_H -class ViewROI; +#include "viewroi.h" +// VTABLE: LEGO1 0x100dbd88 +// SIZE 0x1bc class ViewManager { public: - __declspec(dllexport) void RemoveAll(ViewROI*); + ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view); + virtual ~ViewManager(); + + void RemoveAll(ViewROI*); + + void SetPOVSource(const OrientableROI* point_of_view); + void SetResolution(int width, int height); + void SetFrustrum(float fov, float front, float back); + void Update(float p_previousRenderTime, float p_und2); + + // SYNTHETIC: LEGO1 0x100a6000 + // ViewManager::`scalar deleting destructor' + + inline void AddToUnknown0x08(ViewROI* p_roi) { m_unk0x08.push_back(p_roi); } + +private: + undefined4 m_unk0x04; // 0x04 + CompoundObject m_unk0x08; // 0x08 + undefined m_pad[0x1c8]; // 0x14 }; +// TEMPLATE: LEGO1 0x10022030 +// list >::insert + #endif // VIEWMANAGER_H diff --git a/LEGO1/viewmanager/viewroi.cpp b/LEGO1/viewmanager/viewroi.cpp index bb5dcaab..37b299b5 100644 --- a/LEGO1/viewmanager/viewroi.cpp +++ b/LEGO1/viewmanager/viewroi.cpp @@ -2,8 +2,13 @@ #include "decomp.h" +#include + DECOMP_SIZE_ASSERT(ViewROI, 0xe0) +// GLOBAL: LEGO1 0x101013d8 +undefined g_unk101013d8 = 0; + // FUNCTION: LEGO1 0x100a9eb0 float ViewROI::IntrinsicImportance() const { @@ -23,20 +28,41 @@ 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)); } } -inline ViewROI::~ViewROI() +// STUB: LEGO1 0x100a9fc0 +void ViewROI::VTable0x24(const MxMatrix& p_transform) { - // SetLODList() will decrease refCount of LODList - SetLODList(0); - delete geometry; + // TODO +} + +// STUB: LEGO1 0x100aa0a0 +void ViewROI::SetLocalTransform(const Matrix4& p_transform) +{ + // TODO +} + +// STUB: LEGO1 0x100aa180 +void ViewROI::VTable0x1c() +{ + // TODO +} + +// FUNCTION: LEGO1 0x100aa500 +undefined ViewROI::SetUnk101013d8(undefined p_flag) +{ + undefined oldFlag = g_unk101013d8; + g_unk101013d8 = p_flag; + return oldFlag; } diff --git a/LEGO1/viewmanager/viewroi.h b/LEGO1/viewmanager/viewroi.h index e54e6113..cec1ba0e 100644 --- a/LEGO1/viewmanager/viewroi.h +++ b/LEGO1/viewmanager/viewroi.h @@ -1,8 +1,9 @@ #ifndef VIEWROI_H #define VIEWROI_H -#include "../realtime/orientableroi.h" -#include "../tgl/tgl.h" +#include "decomp.h" +#include "realtime/orientableroi.h" +#include "tgl/tgl.h" #include "viewlodlist.h" /* @@ -10,6 +11,9 @@ etc. Basically, anything which can be placed in a scene and manipilated by the view manager is a ViewROI. */ + +// VTABLE: LEGO1 0x100dbe70 +// SIZE 0xe0 class ViewROI : public OrientableROI { public: inline ViewROI(Tgl::Renderer* pRenderer, ViewLODList* lodList) @@ -17,7 +21,12 @@ class ViewROI : public OrientableROI { SetLODList(lodList); geometry = pRenderer->CreateGroup(); } - inline ~ViewROI(); + inline ~ViewROI() override + { + // SetLODList() will decrease refCount of LODList + SetLODList(0); + delete geometry; + } inline void SetLODList(ViewLODList* lodList) { // ??? inherently type unsafe - kind of... because, now, ROI @@ -35,13 +44,18 @@ class ViewROI : public OrientableROI { reinterpret_cast(m_lods)->AddRef(); } } - virtual float IntrinsicImportance() const; - virtual Tgl::Group* GetGeometry(); - virtual const Tgl::Group* GetGeometry() const; + float IntrinsicImportance() const override; // vtable+0x04 + void VTable0x1c() override; // vtable+0x1c + void SetLocalTransform(const Matrix4& p_transform) override; // vtable+0x20 + void VTable0x24(const MxMatrix& p_transform) override; // vtable+0x24 + virtual const Tgl::Group* GetGeometry() const; // vtable+0x34 + virtual Tgl::Group* GetGeometry(); // vtable+0x30 + + static undefined SetUnk101013d8(undefined p_flag); protected: Tgl::Group* geometry; - void UpdateWorldData(const Matrix4Data& parent2world); + void UpdateWorldData(const MxMatrix& parent2world) override; }; // SYNTHETIC: LEGO1 0x100aa250 diff --git a/README.md b/README.md index 2e2ea906..0f7edf0b 100644 --- a/README.md +++ b/README.md @@ -2,29 +2,29 @@ [Development Vlog](https://www.youtube.com/playlist?list=PLbpl-gZkNl2COf_bB6cfgTapD5WduAfPz) | [Contributing](/CONTRIBUTING.md) | [Matrix](https://matrix.to/#/#isledecomp:matrix.org) | [Forums](https://forum.mattkc.com/viewforum.php?f=1) | [Patreon](https://www.patreon.com/mattkc) -This is a **work-in-progress** decompilation of LEGO Island version 1.1. It aims to be as accurate as possible, matching the recompiled instructions to the original machine code as much as possible. The goal is to provide a workable codebase that can be modified, improved, and ported to other platforms later on. +This is a **work-in-progress** decompilation of LEGO Island (Version 1.1, English). It aims to be as accurate as possible, matching the recompiled instructions to the original machine code as much as possible. The goal is to provide a workable codebase that can be modified, improved, and ported to other platforms later on. ## Status -Currently `ISLE.EXE` is completely decompiled and behaves identically to the original. A handful of stubborn instructions are not yet matching, however we anticipate they will as more of the overall codebase is implemented. +Currently, `ISLE.EXE` is completely decompiled and behaves identically to the original. A handful of stubborn instructions are not yet matching; however, we anticipate they will as more of the overall codebase is implemented. -`LEGO1.DLL` is still very much incomplete and cannot be used at this time. Instead, if you want to test this, it is recommended to pair the recompiled `ISLE.EXE` with the `LEGO1.DLL` from the original game. +`LEGO1.DLL` is still incomplete and cannot be used for gameplay at this time. If you would like to use this, it is instead recommended to pair the recompiled `ISLE.EXE` with the `LEGO1.DLL` from the original game. ## Building -This projects uses the [CMake](https://cmake.org/) build system, which allows for a high degree of versatility regarding compilers and development environments. For the most accurate results, it is recommended to use Microsoft Visual C++ 4.20 (the same compiler used to build the original game). Since we're trying to match this to the original executable as closely as possible, all contributions will be graded with the output of this compiler. +This project uses the [CMake](https://cmake.org/) build system, which allows for a high degree of versatility regarding compilers and development environments. For the most accurate results, it is recommended to use Microsoft Visual C++ 4.20 (the same compiler used to build the original game). Since we're trying to match the output of this code to the original executables as closely as possible, all contributions will be graded with the output of this compiler. -These instructions will outline how to compile this repository into an accurate instruction-matching binary with Visual C++ 4.2. If you wish, you can try using other compilers, but this is at your own risk and won't be covered in this guide. +These instructions will outline how to compile this repository into accurate instruction-matching binaries with Visual C++ 4.2. If you wish, you can try using other compilers, but this is at your own risk and won't be covered in this guide. #### Prerequisites You will need the following software installed: -- Microsoft Visual C++ 4.2. This can be found on many abandonware sites, but the installer can be a little iffy on modern versions of Windows. For convenience, I made a [portable version](https://github.com/itsmattkc/msvc420) that can be downloaded and used quickly instead. -- [CMake](https://cmake.org/). A copy is often included with the "Desktop development with C++" workload in newer versions of Visual Studio, however it can also be installed as a standalone app. +- Microsoft Visual C++ 4.2. This can be found on many abandonware sites, but the installer can be a little iffy on modern versions of Windows. For convenience, a [portable version](https://github.com/itsmattkc/msvc420) is available that can be downloaded and used quickly instead. +- [CMake](https://cmake.org/). A copy is often included with the "Desktop development with C++" workload in newer versions of Visual Studio; however, it can also be installed as a standalone app. #### Compiling @@ -37,8 +37,8 @@ You will need the following software installed: cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo ``` - **Visual C++ 4.2 has issues with paths containing spaces**. If you get configure or build errors, make sure neither CMake, the repository, nor Visual C++ 4.2 is in a path that contains spaces. - - Replace `` with the source repository. Can be `..` if your build folder is inside the source repository. - - `RelWithDebInfo` is recommended because it will produce debug symbols useful for further decompilation work. However, you can change this to `Release` if you don't need them. `Debug` builds are not recommended because they are unlikely to be compatible with the retail `LEGO1.DLL`, which is currently the only way to really use this decomp. + - Replace `` with the source repository. This can be `..` if your build folder is inside the source repository. + - `RelWithDebInfo` is recommended because it will produce debug symbols useful for further decompilation work. However, you can change this to `Release` if you don't need them. `Debug` builds are not recommended because they are unlikely to be compatible with the retail `LEGO1.DLL`, which is currently the only way to use this decompilation for gameplay. - `NMake Makefiles` is most recommended because it will be immediately compatible with Visual C++ 4.2. For faster builds, you can use `Ninja` (if you have it installed), however due to limitations in Visual C++ 4.2, you can only build `Release` builds this way (debug symbols cannot be generated with `Ninja`). 1. Build the project by running `nmake` or `cmake --build ` 1. When this is done, there should a recompiled `ISLE.EXE` and `LEGO1.DLL` in the build folder. @@ -47,14 +47,17 @@ If you have a CMake-compatible IDE, it should be pretty straightforward to use t ## Usage -Simply place the compiled `ISLE.EXE` into LEGO Island's install folder (usually `C:\Program Files\LEGO Island` or `C:\Program Files (x86)\LEGO Island`). Unless you're a developer, disregard the compiled `LEGO1.DLL` for now as it is too incomplete to be usable. Alternatively, LEGO Island can run from any directory as long as `ISLE.EXE` and `LEGO1.DLL` are in the same directory, and the registry keys point to the correct location for the asset files. +Simply place the compiled `ISLE.EXE` into LEGO Island's install folder (usually `C:\Program Files\LEGO Island` or `C:\Program Files (x86)\LEGO Island`). Unless you're a developer, disregard the compiled `LEGO1.DLL` for now as it is too incomplete to be usable. Alternatively, LEGO Island can run from any directory as long as `ISLE.EXE` and `LEGO1.DLL` are in the same directory, and the registry keys (usually `HKEY_LOCAL_MACHINE\Software\Mindscape\LEGO Island` or `HKEY_LOCAL_MACHINE\Software\Wow6432Node\Mindscape\LEGO Island`) point to the correct location for the asset files. ## Contributing -If you're interested in helping/contributing to this project, check out the [CONTRIBUTING](/CONTRIBUTING.md) page. +If you're interested in helping or contributing to this project, check out the [CONTRIBUTING](/CONTRIBUTING.md) page. ## Additional Information ### Which version of LEGO Island do I have? -Right click on `LEGO1.DLL`, select `Properties`, and switch to the `Details` tab. Under `Version` you should either see `1.0.0.0` (1.0) or `1.1.0.0` (1.1). Additionally, you can look at the game disc files; 1.0's files will all say August 8, 1997, and 1.1's files will all say September 8, 1997. Version 1.1 is by far the most common, especially if you're not using the English or Japanese versions, so that's most likely the version you have. +Right click on `LEGO1.DLL`, select `Properties`, and switch to the `Details` tab. Under `Version` you should either see `1.0.0.0` (1.0) or `1.1.0.0` (1.1). Additionally, you can look at the game disc files; 1.0's files will all say August 8, 1997, and 1.1's files will all say September 8, 1997. Version 1.1 is by far the most common, especially if you're not using the English or Japanese versions, so that's most likely the version you have. Please note that some localized versions of LEGO Island were recompiled with small changes despite maintaining a version number parallel with other versions; this decompilation is specifically targeting the English release of version 1.1 of LEGO Island. You can verify you have the correct version using the checksums below: + +* ISLE.EXE `md5: f6da12249e03eed1c74810cd23beb9f5` +* LEGO1.DLL `md5: 4e2f6d969ea2ef8655ba3fc221a0c8fe` diff --git a/tools/README.md b/tools/README.md index da23d84c..6e6b046f 100644 --- a/tools/README.md +++ b/tools/README.md @@ -58,7 +58,7 @@ Templated functions should be annotated with `TEMPLATE`. Since the goal is to ev ### `SYNTHETIC` -Synthetic functions should be annotated with `SYNTHETIC`. A synthetic function is generated by the compiler; for the time being, the only case is the "scalar deleting destructor" found in virtual tables. Note: `SYNTHETIC` takes precedence over `TEMPLATE`. +Synthetic functions should be annotated with `SYNTHETIC`. A synthetic function is generated by the compiler; most common is the "scalar deleting destructor" found in virtual tables. Other cases include default destructors and assignment operators. Note: `SYNTHETIC` takes precedence over `TEMPLATE`. ``` // SYNTHETIC: LEGO1 0x10003210 @@ -71,7 +71,22 @@ Synthetic functions should be annotated with `SYNTHETIC`. A synthetic function i // MxList::`scalar deleting destructor' ``` -## Virtual tables (**WIP**) +### `LIBRARY` + +Functions located in 3rd party libraries should be annotated with `LIBRARY`. Since the goal is to eventually have a full accounting of all the functions present in the binaries, please make an effort to find and annotate every function of every statically linked library, including the MSVC standard libraries. + +``` +// LIBRARY: ISLE 0x4061b0 +// _MemPoolInit@4 + +// LIBRARY: ISLE 0x406520 +// _MemPoolSetPageSize@8 + +// LIBRARY: ISLE 0x406630 +// _MemPoolSetBlockSizeFS@8 +``` + +## Virtual tables Classes with a virtual table should be annotated using the `VTABLE` marker, which includes the module name and address of the virtual table. Additionally, virtual function declarations should be annotated with a comment indicating their relative offset. Please use the following example as a reference. @@ -94,9 +109,9 @@ Classes should be annotated using the `SIZE` marker to indicate their size. If y // SIZE 0x1c class MxCriticalSection { public: - __declspec(dllexport) MxCriticalSection(); - __declspec(dllexport) ~MxCriticalSection(); - __declspec(dllexport) static void SetDoMutex(); + MxCriticalSection(); + ~MxCriticalSection(); + static void SetDoMutex(); ``` ## Member variables (**WIP**) @@ -112,7 +127,7 @@ private: undefined4 m_unk0x14; // 0x14 ``` -## Global variables (**WIP**) +## Global variables Global variables should be annotated using the `GLOBAL` marker, which includes the module name and address of the variable. @@ -127,6 +142,18 @@ MxAtomId* g_pz5Script = NULL; MxAtomId* g_introScript = NULL; ``` +## Strings + +String values should be annotated using the `STRING` marker, which includes the module name and address of the string. + +``` +inline virtual const char* ClassName() const override // vtable+0x0c +{ + // STRING: LEGO1 0x100f03fc + return "Act2PoliceStation"; +} +``` + # Tooling Use `pip` to install the required packages to be able to use the Python tools found in this folder: diff --git a/tools/isledecomp/.gitignore b/tools/isledecomp/.gitignore index 00aa29cb..a7c50887 100644 --- a/tools/isledecomp/.gitignore +++ b/tools/isledecomp/.gitignore @@ -1 +1,2 @@ -isledecomp.egg-info/ \ No newline at end of file +isledecomp.egg-info/ +build \ No newline at end of file diff --git a/tools/isledecomp/isledecomp/__init__.py b/tools/isledecomp/isledecomp/__init__.py index a95f1869..59c55869 100644 --- a/tools/isledecomp/isledecomp/__init__.py +++ b/tools/isledecomp/isledecomp/__init__.py @@ -1,5 +1,4 @@ from .bin import * from .dir import * from .parser import * -from .syminfo import * from .utils import * diff --git a/tools/isledecomp/isledecomp/bin.py b/tools/isledecomp/isledecomp/bin.py index 1aec9330..dc04bb53 100644 --- a/tools/isledecomp/isledecomp/bin.py +++ b/tools/isledecomp/isledecomp/bin.py @@ -1,4 +1,7 @@ +import logging import struct +from typing import List, Optional, Tuple +from dataclasses import dataclass from collections import namedtuple @@ -33,49 +36,72 @@ class InvalidVirtualAddressError(IndexError): ], ) -ImageSectionHeader = namedtuple( - "ImageSectionHeader", - [ - "Name", - "Misc", - "VirtualAddress", - "SizeOfRawData", - "PointerToRawData", - "PointerToRelocations", - "PointerToLineNumbers", - "NumberOfRelocations", - "NumberOfLineNumbers", - "Characteristics", - ], -) + +@dataclass +class ImageSectionHeader: + # pylint: disable=too-many-instance-attributes + # Most attributes are unused, but this is the struct format + name: bytes + virtual_size: int + virtual_address: int + size_of_raw_data: int + pointer_to_raw_data: int + pointer_to_relocations: int + pointer_to_line_numbers: int + number_of_relocations: int + number_of_line_numbers: int + characteristics: int + + @property + def extent(self): + """Get the highest possible offset of this section""" + return max(self.size_of_raw_data, self.virtual_size) + + def match_name(self, name: str) -> bool: + return self.name == struct.pack("8s", name.encode("ascii")) + + def contains_vaddr(self, vaddr: int) -> bool: + ofs = vaddr - self.virtual_address + return 0 <= ofs < self.extent + + def addr_is_uninitialized(self, vaddr: int) -> bool: + """We cannot rely on the IMAGE_SCN_CNT_UNINITIALIZED_DATA flag (0x80) in + the characteristics field so instead we determine it this way.""" + if not self.contains_vaddr(vaddr): + return False + + # Should include the case where size_of_raw_data == 0, + # meaning the entire section is uninitialized + return (self.virtual_size > self.size_of_raw_data) and ( + vaddr - self.virtual_address >= self.size_of_raw_data + ) -def section_name_match(section, name): - return section.Name == struct.pack("8s", name.encode("ascii")) - - -def section_contains_vaddr(section, imagebase, vaddr) -> bool: - debased = vaddr - imagebase - ofs = debased - section.VirtualAddress - return 0 <= ofs < section.SizeOfRawData +logger = logging.getLogger(__name__) class Bin: """Parses a PE format EXE and allows reading data from a virtual address. Reference: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format""" - def __init__(self, filename, logger=None): - self.logger = logger - self._debuglog(f'Parsing headers of "{filename}"... ') + # pylint: disable=too-many-instance-attributes + + def __init__(self, filename: str, find_str: bool = False) -> None: + logger.debug('Parsing headers of "%s"... ', filename) self.filename = filename self.file = None self.imagebase = None - self.sections = [] + self.entry = None + self.sections: List[ImageSectionHeader] = [] self.last_section = None + self.find_str = find_str + self._potential_strings = {} self._relocated_addrs = set() + self.imports = [] + self.thunks = [] def __enter__(self): - self._debuglog(f"Bin {self.filename} Enter") + logger.debug("Bin %s Enter", self.filename) self.file = open(self.filename, "rb") (mz_str,) = struct.unpack("2s", self.file.read(2)) @@ -95,36 +121,87 @@ def __enter__(self): optional_hdr = self.file.read(pe_hdr.SizeOfOptionalHeader) (self.imagebase,) = struct.unpack(" List[int]: return sorted(self._relocated_addrs) + def find_string(self, target: str) -> Optional[int]: + # Pad with null terminator to make sure we don't + # match on a subset of the full string + if not target.endswith(b"\x00"): + target += b"\x00" + + c = target[0] + if c not in self._potential_strings: + return None + + for addr in self._potential_strings[c]: + if target == self.read(addr, len(target)): + return addr + + return None + def is_relocated_addr(self, vaddr) -> bool: return vaddr in self._relocated_addrs + def _prepare_string_search(self): + """We are intersted in deduplicated string constants found in the + .rdata and .data sections. For each relocated address in these sections, + read the first byte and save the address if that byte is an ASCII character. + When we search for an arbitrary string later, we can narrow down the list + of potential locations by a lot.""" + + def is_ascii(b): + return b" " <= b < b"\x7f" + + sect_data = self._get_section_by_name(".data") + sect_rdata = self._get_section_by_name(".rdata") + potentials = filter( + lambda a: sect_data.contains_vaddr(a) or sect_rdata.contains_vaddr(a), + self.get_relocated_addresses(), + ) + + for addr in potentials: + c = self.read(addr, 1) + if c is not None and is_ascii(c): + k = ord(c) + if k not in self._potential_strings: + self._potential_strings[k] = set() + + self._potential_strings[k].add(addr) + def _populate_relocations(self): """The relocation table in .reloc gives each virtual address where the next four bytes are, itself, another virtual address. During loading, these values will be @@ -165,27 +242,97 @@ def _populate_relocations(self): (relocated_addr,) = struct.unpack(" int: + def get_section_extent_by_index(self, index: int) -> int: + return self.sections[index - 1].extent + + def get_section_offset_by_index(self, index: int) -> int: """The symbols output from cvdump gives addresses in this format: AAAA.BBBBBBBB where A is the index (1-based) into the section table and B is the local offset. This will return the virtual address for the start of the section at the given index @@ -202,29 +352,50 @@ def get_section_offset_by_index(self, index) -> int: """ section = self.sections[index - 1] - return self.imagebase + section.VirtualAddress + return section.virtual_address - def get_section_offset_by_name(self, name) -> int: + def get_section_offset_by_name(self, name: str) -> int: """Same as above, but use the section name as the lookup""" section = self._get_section_by_name(name) - return self.imagebase + section.VirtualAddress + return section.virtual_address - def get_raw_addr(self, vaddr) -> int: + def get_abs_addr(self, section: int, offset: int) -> int: + """Convenience function for converting section:offset pairs from cvdump + into an absolute vaddr.""" + return self.get_section_offset_by_index(section) + offset + + def get_relative_addr(self, addr: int) -> Tuple[int, int]: + """Convert an absolute address back into a (section, offset) pair.""" + for i, section in enumerate(self.sections): + if section.contains_vaddr(addr): + return (i + 1, addr - section.virtual_address) + + return (0, 0) + + def get_raw_addr(self, vaddr: int) -> int: """Returns the raw offset in the PE binary for the given virtual address.""" self._set_section_for_vaddr(vaddr) return ( vaddr - - self.imagebase - - self.last_section.VirtualAddress - + self.last_section.PointerToRawData + - self.last_section.virtual_address + + self.last_section.pointer_to_raw_data ) - def is_valid_vaddr(self, vaddr) -> bool: + def is_valid_section(self, section: int) -> bool: + """The PDB will refer to sections that are not listed in the headers + and so should ignore these references.""" + try: + _ = self.sections[section - 1] + return True + except IndexError: + return False + + def is_valid_vaddr(self, vaddr: int) -> bool: """Does this virtual address point to anything in the exe?""" section = next( filter( - lambda section: section_contains_vaddr(section, self.imagebase, vaddr), + lambda section: section.contains_vaddr(vaddr), self.sections, ), None, @@ -232,9 +403,26 @@ def is_valid_vaddr(self, vaddr) -> bool: return section is not None - def read(self, offset, size): + 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.""" self._set_section_for_vaddr(offset) + if self.last_section.addr_is_uninitialized(offset): + return None + raw_addr = self.get_raw_addr(offset) self.file.seek(raw_addr) @@ -242,8 +430,8 @@ def read(self, offset, size): # Reading off the end will most likely misrepresent the virtual addressing. _size = min( size, - self.last_section.PointerToRawData - + self.last_section.SizeOfRawData + self.last_section.pointer_to_raw_data + + self.last_section.size_of_raw_data - raw_addr, ) return self.file.read(_size) diff --git a/tools/isledecomp/isledecomp/compare/__init__.py b/tools/isledecomp/isledecomp/compare/__init__.py new file mode 100644 index 00000000..f8d18500 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/__init__.py @@ -0,0 +1 @@ +from .core import Compare 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..f8323165 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/asm/parse.py @@ -0,0 +1,198 @@ +"""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 isledecomp.bin import InvalidVirtualAddressError +from capstone import Cs, CS_ARCH_X86, CS_MODE_32 + +disassembler = Cs(CS_ARCH_X86, CS_MODE_32) + +ptr_replace_regex = re.compile(r"(?P\w+) ptr \[(?P0x[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 + + +def get_float_size(size_str: str) -> int: + return 8 if size_str == "qword" else 4 + + +class ParseAsm: + def __init__( + self, + relocate_lookup: Optional[Callable[[int], bool]] = None, + name_lookup: Optional[Callable[[int], str]] = None, + float_lookup: Optional[Callable[[int, int], Optional[str]]] = None, + ) -> None: + self.relocate_lookup = relocate_lookup + self.name_lookup = name_lookup + self.float_lookup = float_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 float_replace(self, addr: int, data_size: int) -> Optional[str]: + if callable(self.float_lookup): + try: + float_str = self.float_lookup(addr, data_size) + except InvalidVirtualAddressError: + # probably caused by reading an invalid instruction + return None + if float_str is not None: + return f"{float_str} (FLOAT)" + + return None + + 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("addr")) + + if offset is not None: + # We assume this is always an address to replace + placeholder = self.replace(offset) + return f'{match.group("data_size")} 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) + + def float_ptr_replace(match): + offset = from_hex(match.group("addr")) + + if offset is not None: + # If we can find a variable name for this pointer, use it. + placeholder = self.lookup(offset) + + # Read what's under the pointer and show the decimal value. + if placeholder is None: + placeholder = self.float_replace( + offset, get_float_size(match.group("data_size")) + ) + + # If we can't read the float, use a regular placeholder. + if placeholder is None: + placeholder = self.replace(offset) + + return f'{match.group("data_size")} 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) + + if inst.mnemonic.startswith("f"): + # If floating point instruction + op_str = ptr_replace_regex.sub(float_ptr_replace, inst.op_str) + else: + 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 new file mode 100644 index 00000000..4e1a1f70 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -0,0 +1,449 @@ +import os +import logging +import difflib +import struct +from dataclasses import dataclass +from typing import Callable, Iterable, List, Optional +from isledecomp.bin import Bin as IsleBin +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 + + +logger = logging.getLogger(__name__) + + +@dataclass +class DiffReport: + match_type: SymbolType + 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 ''}" + + +def create_reloc_lookup(bin_file: IsleBin) -> Callable[[int], bool]: + """Function generator for relocation table lookup""" + + def lookup(addr: int) -> bool: + return addr > bin_file.imagebase and bin_file.is_relocated_addr(addr) + + return lookup + + +def create_float_lookup(bin_file: IsleBin) -> Callable[[int, int], Optional[str]]: + """Function generator for floating point lookup""" + + def lookup(addr: int, size: int) -> Optional[str]: + data = bin_file.read(addr, size) + # If this is a float constant, it should be initialized data. + if data is None: + return None + + struct_str = " DiffReport: + if match.size == 0: + # Report a failed match to make the user aware of the empty function. + return DiffReport( + match_type=SymbolType.FUNCTION, + orig_addr=match.orig_addr, + recomp_addr=match.recomp_addr, + name=match.name, + ) + + orig_raw = self.orig_bin.read(match.orig_addr, match.size) + recomp_raw = self.recomp_bin.read(match.recomp_addr, match.size) + + 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_should_replace = create_reloc_lookup(self.orig_bin) + recomp_should_replace = create_reloc_lookup(self.recomp_bin) + + orig_float = create_float_lookup(self.orig_bin) + recomp_float = create_float_lookup(self.recomp_bin) + + orig_parse = ParseAsm( + relocate_lookup=orig_should_replace, + name_lookup=orig_lookup, + float_lookup=orig_float, + ) + recomp_parse = ParseAsm( + relocate_lookup=recomp_should_replace, + name_lookup=recomp_lookup, + float_lookup=recomp_float, + ) + + orig_asm = orig_parse.parse_asm(orig_raw, match.orig_addr) + recomp_asm = recomp_parse.parse_asm(recomp_raw, match.recomp_addr) + + 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( + match_type=SymbolType.FUNCTION, + 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_vtable(self, match: MatchInfo) -> DiffReport: + vtable_size = match.size + + # The vtable size should always be a multiple of 4 because that + # is the pointer size. If it is not (for whatever reason) + # it would cause iter_unpack to blow up so let's just fix it. + if vtable_size % 4 != 0: + logger.warning( + "Vtable for class %s has irregular size %d", match.name, vtable_size + ) + vtable_size = 4 * (vtable_size // 4) + + orig_table = self.orig_bin.read(match.orig_addr, vtable_size) + recomp_table = self.recomp_bin.read(match.recomp_addr, vtable_size) + + raw_addrs = zip( + [t for (t,) in struct.iter_unpack(" str: + """Format the function reference at this vtable index as text. + If we have not identified this function, we have the option to + display the raw address. This is only worth doing for the original addr + because we should always be able to identify the recomp function. + If the original function is missing then this probably means that the class + should override the given function from the superclass, but we have not + implemented this yet. + """ + index = f"vtable0x{i*4:02x}" + + if m is not None: + orig = hex(m.orig_addr) if m.orig_addr is not None else "no orig" + recomp = ( + hex(m.recomp_addr) if m.recomp_addr is not None else "no recomp" + ) + return f"{index:>12} : ({orig:10} / {recomp:10}) : {m.name}" + + if raw_addr is not None: + return f"{index:>12} : 0x{raw_addr:x} from orig not annotated." + + return f"{index:>12} : (no match)" + + orig_text = [] + recomp_text = [] + ratio = 0 + n_entries = 0 + + # Now compare each pointer from the two vtables. + for i, (raw_orig, raw_recomp) in enumerate(raw_addrs): + orig = self._db.get_by_orig(raw_orig) + recomp = self._db.get_by_recomp(raw_recomp) + + if ( + orig is not None + and recomp is not None + and orig.recomp_addr == recomp.recomp_addr + ): + ratio += 1 + + n_entries += 1 + orig_text.append(match_text(i, orig, raw_orig)) + recomp_text.append(match_text(i, recomp)) + + ratio = ratio / float(n_entries) if n_entries > 0 else 0 + + # n=100: Show the entire table if there is a diff to display. + # Otherwise it would be confusing if the table got cut off. + unified_diff = difflib.unified_diff(orig_text, recomp_text, n=100) + + return DiffReport( + match_type=SymbolType.VTABLE, + orig_addr=match.orig_addr, + recomp_addr=match.recomp_addr, + name=f"{match.name}::`vftable'", + udiff=unified_diff, + ratio=ratio, + ) + + def _compare_match(self, match: MatchInfo) -> Optional[DiffReport]: + """Router for comparison type""" + if match.compare_type == SymbolType.FUNCTION: + return self._compare_function(match) + + if match.compare_type == SymbolType.VTABLE: + return self._compare_vtable(match) + + return None + + ## Public API + + def get_all(self) -> List[MatchInfo]: + return self._db.get_all() + + def get_functions(self) -> List[MatchInfo]: + return self._db.get_matches_by_type(SymbolType.FUNCTION) + + def get_vtables(self) -> List[MatchInfo]: + return self._db.get_matches_by_type(SymbolType.VTABLE) + + def compare_address(self, addr: int) -> Optional[DiffReport]: + match = self._db.get_one_match(addr) + if match is None: + return None + + return self._compare_match(match) + + def compare_all(self) -> Iterable[DiffReport]: + for match in self._db.get_matches(): + diff = self._compare_match(match) + if diff is not None: + yield diff + + def compare_functions(self) -> Iterable[DiffReport]: + for match in self.get_functions(): + yield self._compare_match(match) + + def compare_variables(self): + pass + + def compare_pointers(self): + pass + + def compare_strings(self): + pass + + def compare_vtables(self) -> Iterable[DiffReport]: + for match in self.get_vtables(): + yield self._compare_match(match) diff --git a/tools/isledecomp/isledecomp/compare/db.py b/tools/isledecomp/isledecomp/compare/db.py new file mode 100644 index 00000000..96ab3e10 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/db.py @@ -0,0 +1,231 @@ +"""Wrapper for database (here an in-memory sqlite database) that collects the +addresses/symbols that we want to compare between the original and recompiled binaries.""" +import sqlite3 +import logging +from typing import List, Optional +from isledecomp.types import SymbolType + +_SETUP_SQL = """ + DROP TABLE IF EXISTS `symbols`; + CREATE TABLE `symbols` ( + compare_type int, + orig_addr int, + recomp_addr int, + name text, + size int, + should_skip int default(FALSE) + ); + CREATE INDEX `symbols_or` ON `symbols` (orig_addr); + CREATE INDEX `symbols_re` ON `symbols` (recomp_addr); +""" + + +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): + return MatchInfo(*row) + + +logger = logging.getLogger(__name__) + + +class CompareDb: + def __init__(self): + self._db = sqlite3.connect(":memory:") + self._db.executescript(_SETUP_SQL) + + def set_recomp_symbol( + self, + addr: int, + compare_type: Optional[SymbolType], + name: Optional[str], + size: Optional[int], + ): + compare_value = compare_type.value if compare_type is not None else None + self._db.execute( + "INSERT INTO `symbols` (recomp_addr, compare_type, name, size) VALUES (?,?,?,?)", + (addr, compare_value, name, size), + ) + + def get_unmatched_strings(self) -> List[str]: + """Return any strings not already identified by STRING markers.""" + + cur = self._db.execute( + "SELECT name FROM `symbols` WHERE compare_type = ? AND orig_addr IS NULL", + (SymbolType.STRING.value,), + ) + + return [string for (string,) in cur.fetchall()] + + def get_all(self) -> List[MatchInfo]: + cur = self._db.execute( + """SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + ORDER BY orig_addr NULLS LAST + """, + ) + cur.row_factory = matchinfo_factory + + return cur.fetchall() + + def get_matches(self) -> Optional[MatchInfo]: + cur = self._db.execute( + """SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + WHERE orig_addr IS NOT NULL + AND recomp_addr IS NOT NULL + AND should_skip IS FALSE + ORDER BY orig_addr + """, + ) + cur.row_factory = matchinfo_factory + + return cur.fetchall() + + def get_one_match(self, addr: int) -> Optional[MatchInfo]: + cur = self._db.execute( + """SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + WHERE orig_addr = ? + AND recomp_addr IS NOT NULL + AND should_skip IS FALSE + """, + (addr,), + ) + 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_by_type(self, compare_type: SymbolType) -> List[MatchInfo]: + cur = self._db.execute( + """SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + WHERE compare_type = ? + AND orig_addr IS NOT NULL + AND recomp_addr IS NOT NULL + AND should_skip IS FALSE + ORDER BY orig_addr + """, + (compare_type.value,), + ) + cur.row_factory = matchinfo_factory + + return cur.fetchall() + + 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, 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): + self._db.execute( + "UPDATE `symbols` SET should_skip = TRUE WHERE orig_addr = ?", (orig,) + ) + + def _match_on(self, compare_type: SymbolType, addr: int, name: str) -> bool: + # Update the compare_type here too since the marker tells us what we should do + + # Truncate the name to 255 characters. It will not be possible to match a name + # longer than that because MSVC truncates the debug symbols to this length. + # See also: warning C4786. + name = name[:255] + + logger.debug("Looking for %s %s", compare_type.name.lower(), name) + cur = self._db.execute( + """UPDATE `symbols` + SET orig_addr = ?, compare_type = ? + WHERE name = ? + AND orig_addr IS NULL + AND (compare_type = ? OR compare_type IS NULL)""", + (addr, compare_type.value, name, compare_type.value), + ) + + return cur.rowcount > 0 + + def match_function(self, addr: int, name: str) -> bool: + did_match = self._match_on(SymbolType.FUNCTION, addr, name) + if not did_match: + logger.error("Failed to find function symbol with name: %s", name) + + return did_match + + def match_vtable(self, addr: int, name: str) -> bool: + did_match = self._match_on(SymbolType.VTABLE, addr, name) + if not did_match: + logger.error("Failed to find vtable for class: %s", name) + + return did_match + + def match_variable(self, addr: int, name: str) -> bool: + did_match = self._match_on(SymbolType.DATA, addr, name) or self._match_on( + SymbolType.POINTER, addr, name + ) + if not did_match: + logger.error("Failed to find variable: %s", name) + + return did_match + + def match_string(self, addr: int, value: str) -> bool: + did_match = self._match_on(SymbolType.STRING, addr, value) + if not did_match: + escaped = repr(value) + logger.error("Failed to find string: %s", escaped) + + return did_match diff --git a/tools/isledecomp/isledecomp/compare/lines.py b/tools/isledecomp/isledecomp/compare/lines.py new file mode 100644 index 00000000..ced3c117 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/lines.py @@ -0,0 +1,58 @@ +"""Database used to match (filename, line_number) pairs +between FUNCTION markers and PDB analysis.""" +import sqlite3 +import logging +from typing import Optional +from pathlib import Path +from isledecomp.dir import PathResolver + + +_SETUP_SQL = """ + DROP TABLE IF EXISTS `lineref`; + CREATE TABLE `lineref` ( + path text not null, + filename text not null, + line int not null, + addr int not null + ); + CREATE INDEX `file_line` ON `lineref` (filename, line); +""" + + +logger = logging.getLogger(__name__) + + +class LinesDb: + def __init__(self, code_dir) -> None: + self._db = sqlite3.connect(":memory:") + self._db.executescript(_SETUP_SQL) + self._path_resolver = PathResolver(code_dir) + + def add_line(self, path: str, line_no: int, addr: int): + """To be added from the LINES section of cvdump.""" + sourcepath = self._path_resolver.resolve_cvdump(path) + filename = Path(sourcepath).name.lower() + + self._db.execute( + "INSERT INTO `lineref` (path, filename, line, addr) VALUES (?,?,?,?)", + (sourcepath, filename, line_no, addr), + ) + + def search_line(self, path: str, line_no: int) -> Optional[int]: + """Using path and line number from FUNCTION marker, + get the address of this function in the recomp.""" + filename = Path(path).name.lower() + cur = self._db.execute( + "SELECT path, addr FROM `lineref` WHERE filename = ? AND line = ?", + (filename, line_no), + ) + for source_path, addr in cur.fetchall(): + if Path(path).samefile(source_path): + return addr + + logger.error( + "Failed to find function symbol with filename and line: %s:%d", + path, + line_no, + ) + return None diff --git a/tools/isledecomp/isledecomp/cvdump/__init__.py b/tools/isledecomp/isledecomp/cvdump/__init__.py new file mode 100644 index 00000000..635ef5cd --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/__init__.py @@ -0,0 +1,3 @@ +from .analysis import CvdumpAnalysis +from .parser import CvdumpParser +from .runner import Cvdump diff --git a/tools/isledecomp/isledecomp/cvdump/analysis.py b/tools/isledecomp/isledecomp/cvdump/analysis.py new file mode 100644 index 00000000..330429dd --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/analysis.py @@ -0,0 +1,188 @@ +"""For collating the results from parsing cvdump.exe into a more directly useful format.""" +from typing import List, Optional, Tuple +from isledecomp.types import SymbolType +from .parser import CvdumpParser +from .demangler import demangle_string_const, demangle_vtable + + +def data_type_info(type_name: str) -> Optional[Tuple[int, bool]]: + """cvdump type aliases are listed here: + https://github.com/microsoft/microsoft-pdb/blob/master/include/cvinfo.h + For the given type, return tuple(size, is_pointer) if possible.""" + # pylint: disable=too-many-return-statements + # TODO: refactor to be as simple as possble + + # Ignore complex types. We can get the size of those from the TYPES section. + if not type_name.startswith("T"): + return None + + # if 32-bit pointer + if type_name.startswith("T_32P"): + return (4, True) + + if type_name.endswith("QUAD") or type_name.endswith("64"): + return (8, False) + + if ( + type_name.endswith("LONG") + or type_name.endswith("INT4") + or type_name.endswith("32") + ): + return (4, False) + + if type_name.endswith("SHORT") or type_name.endswith("WCHAR"): + return (2, False) + + if "CHAR" in type_name: + return (1, False) + + if type_name in ("T_NOTYPE", "T_VOID"): + return (0, False) + + return None + + +class CvdumpNode: + # pylint: disable=too-many-instance-attributes + # These two are required and allow us to identify the symbol + section: int + offset: int + # aka the mangled name from the PUBLICS section + decorated_name: Optional[str] = None + # optional "nicer" name (e.g. of a function from SYMBOLS section) + friendly_name: Optional[str] = None + # To be determined by context after inserting data, unless the decorated + # name makes this obvious. (i.e. string constants or vtables) + # We choose not to assume that section 1 (probably ".text") contains only + # functions. Smacker functions are linked to their own section "_UNSTEXT" + node_type: Optional[SymbolType] = None + # Function size can be read from the LINES section so use this over any + # other value if we have it. + # TYPES section can tell us the size of structs and other complex types. + confirmed_size: Optional[int] = None + # Estimated by reading the distance between this symbol and the one that + # follows in the same section. + # If this is the last symbol in the section, we cannot estimate a size. + estimated_size: Optional[int] = None + # Size as reported by SECTION CONTRIBUTIONS section. Not guaranteed to be + # accurate. + section_contribution: Optional[int] = None + + def __init__(self, section: int, offset: int) -> None: + self.section = section + self.offset = offset + + def set_decorated(self, name: str): + self.decorated_name = name + + if self.decorated_name.startswith("??_7"): + self.node_type = SymbolType.VTABLE + self.friendly_name = demangle_vtable(self.decorated_name) + + elif self.decorated_name.startswith("??_C@"): + self.node_type = SymbolType.STRING + (strlen, _) = demangle_string_const(self.decorated_name) + self.confirmed_size = strlen + + elif not self.decorated_name.startswith("?") and "@" in self.decorated_name: + # C mangled symbol. The trailing at-sign with number tells the number of bytes + # in the parameter list for __stdcall, __fastcall, or __vectorcall + # For __cdecl it is more ambiguous and we would have to know which section we are in. + # https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170#FormatC + self.node_type = SymbolType.FUNCTION + + 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 + if self.friendly_name is not None + else self.decorated_name + ) + + def size(self) -> Optional[int]: + if self.confirmed_size is not None: + return self.confirmed_size + + # Better to undershoot the size because we can identify a comparison gap easily + if self.estimated_size is not None and self.section_contribution is not None: + return min(self.estimated_size, self.section_contribution) + + # Return whichever one we have, or neither + return self.estimated_size or self.section_contribution + + +class CvdumpAnalysis: + """Collects the results from CvdumpParser into a list of nodes (i.e. symbols). + These can then be analyzed by a downstream tool.""" + + nodes = List[CvdumpNode] + + def __init__(self, parser: CvdumpParser): + """Read in as much information as we have from the parser. + The more sections we have, the better our information will be.""" + node_dict = {} + + # PUBLICS is our roadmap for everything that follows. + for pub in parser.publics: + key = (pub.section, pub.offset) + if key not in node_dict: + node_dict[key] = CvdumpNode(*key) + + node_dict[key].set_decorated(pub.name) + + for sizeref in parser.sizerefs: + key = (sizeref.section, sizeref.offset) + if key not in node_dict: + node_dict[key] = CvdumpNode(*key) + + node_dict[key].section_contribution = sizeref.size + + for glo in parser.globals: + key = (glo.section, glo.offset) + if key not in node_dict: + node_dict[key] = CvdumpNode(*key) + + node_dict[key].node_type = SymbolType.DATA + node_dict[key].friendly_name = glo.name + + if (g_info := data_type_info(glo.type)) is not None: + (size, is_pointer) = g_info + node_dict[key].confirmed_size = size + if is_pointer: + node_dict[key].node_type = SymbolType.POINTER + + for lin in parser.lines: + key = (lin.section, lin.offset) + # Here we only set if the section:offset already exists + # because our values include offsets inside of the function. + if key in node_dict: + node_dict[key].node_type = SymbolType.FUNCTION + + for sym in parser.symbols: + key = (sym.section, sym.offset) + if key not in node_dict: + node_dict[key] = CvdumpNode(*key) + + if sym.type == "S_GPROC32": + node_dict[key].friendly_name = sym.name + node_dict[key].confirmed_size = sym.size + node_dict[key].node_type = SymbolType.FUNCTION + + self.nodes = [v for _, v in dict(sorted(node_dict.items())).items()] + self._estimate_size() + + def _estimate_size(self): + """Get the distance between one section:offset value and the next one + in the same section. This gives a rough estimate of the size of the symbol. + If we have information from SECTION CONTRIBUTIONS, take whichever one is + less to get the best approximate size.""" + for i in range(len(self.nodes) - 1): + this_node = self.nodes[i] + next_node = self.nodes[i + 1] + + # If they are in different sections, we can't compare them + if this_node.section != next_node.section: + continue + + this_node.estimated_size = next_node.offset - this_node.offset diff --git a/tools/isledecomp/isledecomp/cvdump/demangler.py b/tools/isledecomp/isledecomp/cvdump/demangler.py new file mode 100644 index 00000000..10984bff --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/demangler.py @@ -0,0 +1,76 @@ +"""For demangling a subset of MSVC mangled symbols. +Some unofficial information about the mangling scheme is here: +https://en.wikiversity.org/wiki/Visual_C%2B%2B_name_mangling +""" +import re +from collections import namedtuple +from typing import Optional + + +class InvalidEncodedNumberError(Exception): + pass + + +_encoded_number_translate = str.maketrans("ABCDEFGHIJKLMNOP", "0123456789ABCDEF") + + +def parse_encoded_number(string: str) -> int: + # TODO: assert string ends in "@"? + if string.endswith("@"): + string = string[:-1] + + try: + return int(string.translate(_encoded_number_translate), 16) + except ValueError as e: + raise InvalidEncodedNumberError(string) from e + + +string_const_regex = re.compile( + r"\?\?_C@\_(?P[0-1])(?P\d|[A-P]+@)(?P\w+)@(?P.+)@" +) +StringConstInfo = namedtuple("StringConstInfo", "len is_utf16") + + +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: + return None + + try: + strlen = ( + parse_encoded_number(match.group("len")) + if "@" in match.group("len") + else int(match.group("len")) + ) + except (ValueError, InvalidEncodedNumberError): + return None + + is_utf16 = match.group("is_utf16") == "1" + return StringConstInfo(len=strlen, is_utf16=is_utf16) + + +def demangle_vtable(symbol: str) -> str: + """Get the class name referenced in the vtable symbol.""" + + # Seek ahead 4 chars to strip off "??_7" prefix + t = symbol[4:].split("@") + # "?$" indicates a template class + if t[0].startswith("?$"): + class_name = t[0][2:] + # PA = Pointer/reference + # V or U = class or struct + if t[1].startswith("PA"): + generic = f"{t[1][3:]} *" + else: + generic = t[1][1:] + + return f"{class_name}<{generic}>" + + # If we have two classes listed, it is a namespace hierarchy. + # @@6B@ is a common generic suffix for these vtable symbols. + if t[1] != "" and t[1] != "6B": + return t[1] + "::" + t[0] + + return t[0] diff --git a/tools/isledecomp/isledecomp/cvdump/parser.py b/tools/isledecomp/isledecomp/cvdump/parser.py new file mode 100644 index 00000000..8d1c71bb --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/parser.py @@ -0,0 +1,203 @@ +import re +from typing import Iterable, Tuple +from collections import namedtuple + +# e.g. `*** PUBLICS` +_section_change_regex = re.compile(r"^\*\*\* (?P
[A-Z/ ]+)") + +# e.g. ` 27 00034EC0 28 00034EE2 29 00034EE7 30 00034EF4` +_line_addr_pairs_findall = re.compile(r"\s+(?P\d+) (?P[A-F0-9]{8})") + +# We assume no spaces in the file name +# e.g. ` Z:\lego-island\isle\LEGO1\viewmanager\viewroi.cpp (None), 0001:00034E90-00034E97, line/addr pairs = 2` +_lines_subsection_header = re.compile( + r"^\s*(?P\S+).*?, (?P
[A-F0-9]{4}):(?P[A-F0-9]{8})-(?P[A-F0-9]{8}), line/addr pairs = (?P\d+)" +) + +# e.g. `S_PUB32: [0001:0003FF60], Flags: 00000000, __read` +_publics_line_regex = re.compile( + r"^(?P\w+): \[(?P
\w{4}):(?P\w{8})], Flags: (?P\w{8}), (?P\S+)" +) + +# e.g. `(00008C) S_GPROC32: [0001:00034E90], Cb: 00000007, Type: 0x1024, ViewROI::IntrinsicImportance` +_symbol_line_regex = re.compile( + r"\(\w+\) (?P\S+): \[(?P
\w{4}):(?P\w{8})\], Cb: (?P\w+), Type:\s+\S+, (?P.+)" +) + +# e.g. ` Debug start: 00000008, Debug end: 0000016E` +_gproc_debug_regex = re.compile( + r"\s*Debug start: (?P\w{8}), Debug end: (?P\w{8})" +) + +# e.g. ` 00DA 0001:00000000 00000073 60501020` +_section_contrib_regex = re.compile( + r"\s*(?P\w{4}) (?P
\w{4}):(?P\w{8}) (?P\w{8}) (?P\w{8})" +) + +# 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.+)" +) + +# e.g. 0003 "CMakeFiles/isle.dir/ISLE/res/isle.rc.res" +# e.g. 0004 "C:\work\lego-island\isle\3rdparty\smartheap\SHLW32MT.LIB" "check.obj" +_module_regex = re.compile(r"(?P\w{4})(?: \"(?P.+?)\")?(?: \"(?P.+?)\")") + +# User functions only +LinesEntry = namedtuple("LinesEntry", "filename line_no section offset") + +# Strings, vtables, functions +# superset of everything else +# only place you can find the C symbols (library functions, smacker, etc) +PublicsEntry = namedtuple("PublicsEntry", "type section offset flags name") + +# S_GPROC32 = functions +SymbolsEntry = namedtuple("SymbolsEntry", "type section offset size name") + +# (Estimated) size of any symbol +SizeRefEntry = namedtuple("SizeRefEntry", "module section offset size") + +# global variables +GdataEntry = namedtuple("GdataEntry", "section offset type name") + +ModuleEntry = namedtuple("ModuleEntry", "id lib obj") + + +class CvdumpParser: + # pylint: disable=too-many-instance-attributes + def __init__(self) -> None: + self._section: str = "" + self._lines_function: Tuple[str, int] = ("", 0) + + self.lines = [] + self.publics = [] + self.symbols = [] + self.sizerefs = [] + self.globals = [] + self.modules = [] + + def _lines_section(self, line: str): + """Parsing entries from the LINES section. We only care about the pairs of + line_number and address and the subsection header to indicate which code file + we are in.""" + + # Subheader indicates a new function and possibly a new code filename. + # Save the section here because it is not given on the lines that follow. + if (match := _lines_subsection_header.match(line)) is not None: + self._lines_function = ( + match.group("filename"), + int(match.group("section"), 16), + ) + return + + # Match any pairs as we find them + for line_no, offset in _line_addr_pairs_findall.findall(line): + self.lines.append( + LinesEntry( + filename=self._lines_function[0], + line_no=int(line_no), + section=self._lines_function[1], + offset=int(offset, 16), + ) + ) + + def _publics_section(self, line: str): + """Match each line from PUBLICS and pull out the symbol information. + These are MSVC mangled symbol names. String constants and vtable + addresses can only be found here.""" + if (match := _publics_line_regex.match(line)) is not None: + self.publics.append( + PublicsEntry( + type=match.group("type"), + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + flags=int(match.group("flags"), 16), + name=match.group("name"), + ) + ) + + def _globals_section(self, line: str): + """S_PROCREF may be useful later. + Right now we just want S_GDATA32 symbols because it is the simplest + way to access global variables.""" + if (match := _gdata32_regex.match(line)) is not None: + self.globals.append( + GdataEntry( + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + type=match.group("type"), + name=match.group("name"), + ) + ) + + def _symbols_section(self, line: str): + """We are interested in S_GPROC32 symbols only.""" + if (match := _symbol_line_regex.match(line)) is not None: + if match.group("type") == "S_GPROC32": + self.symbols.append( + SymbolsEntry( + type=match.group("type"), + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + size=int(match.group("size"), 16), + name=match.group("name"), + ) + ) + + def _section_contributions(self, line: str): + """Gives the size of elements across all sections of the binary. + This is the easiest way to get the data size for .data and .rdata + members that do not have a primitive data type.""" + if (match := _section_contrib_regex.match(line)) is not None: + self.sizerefs.append( + SizeRefEntry( + module=int(match.group("module"), 16), + section=int(match.group("section"), 16), + offset=int(match.group("offset"), 16), + size=int(match.group("size"), 16), + ) + ) + + def _modules_section(self, line: str): + """Record the object file (and lib file, if used) linked into the binary. + The auto-incrementing id is cross-referenced in SECTION CONTRIBUTIONS + (and perhaps other locations)""" + if (match := _module_regex.match(line)) is not None: + self.modules.append( + ModuleEntry( + id=int(match.group("id"), 16), + lib=match.group("lib"), + obj=match.group("obj"), + ) + ) + + def read_line(self, line: str): + # Blank lines are there to help the reader; they have no context significance + if line.strip() == "": + return + + if (match := _section_change_regex.match(line)) is not None: + self._section = match.group(1) + return + + if self._section == "LINES": + self._lines_section(line) + + elif self._section == "PUBLICS": + self._publics_section(line) + + elif self._section == "SYMBOLS": + self._symbols_section(line) + + elif self._section == "SECTION CONTRIBUTIONS": + self._section_contributions(line) + + elif self._section == "GLOBALS": + self._globals_section(line) + + elif self._section == "MODULES": + self._modules_section(line) + + def read_lines(self, lines: Iterable[str]): + for line in lines: + self.read_line(line) diff --git a/tools/isledecomp/isledecomp/cvdump/runner.py b/tools/isledecomp/isledecomp/cvdump/runner.py new file mode 100644 index 00000000..6b2c2ff4 --- /dev/null +++ b/tools/isledecomp/isledecomp/cvdump/runner.py @@ -0,0 +1,72 @@ +from os import name as os_name +from enum import Enum +from typing import List +import subprocess +from isledecomp.lib import lib_path_join +from isledecomp.dir import winepath_unix_to_win +from .parser import CvdumpParser + + +class DumpOpt(Enum): + LINES = 0 + SYMBOLS = 1 + GLOBALS = 2 + PUBLICS = 3 + SECTION_CONTRIB = 4 + MODULES = 5 + + +cvdump_opt_map = { + DumpOpt.LINES: "-l", + DumpOpt.SYMBOLS: "-s", + DumpOpt.GLOBALS: "-g", + DumpOpt.PUBLICS: "-p", + DumpOpt.SECTION_CONTRIB: "-seccontrib", + DumpOpt.MODULES: "-m", +} + + +class Cvdump: + def __init__(self, pdb: str) -> None: + self._pdb: str = pdb + self._options = set() + + def lines(self): + self._options.add(DumpOpt.LINES) + return self + + def symbols(self): + self._options.add(DumpOpt.SYMBOLS) + return self + + def globals(self): + self._options.add(DumpOpt.GLOBALS) + return self + + def publics(self): + self._options.add(DumpOpt.PUBLICS) + return self + + def section_contributions(self): + self._options.add(DumpOpt.SECTION_CONTRIB) + return self + + def modules(self): + self._options.add(DumpOpt.MODULES) + return self + + def cmd_line(self) -> List[str]: + cvdump_exe = lib_path_join("cvdump.exe") + flags = [cvdump_opt_map[opt] for opt in self._options] + + if os_name == "nt": + return [cvdump_exe, *flags, self._pdb] + + return ["wine", cvdump_exe, *flags, winepath_unix_to_win(self._pdb)] + + def run(self) -> CvdumpParser: + p = CvdumpParser() + call = self.cmd_line() + lines = subprocess.check_output(call).decode("utf-8").split("\r\n") + p.read_lines(lines) + return p diff --git a/tools/isledecomp/isledecomp/parser/__init__.py b/tools/isledecomp/isledecomp/parser/__init__.py index 3034a562..14549700 100644 --- a/tools/isledecomp/isledecomp/parser/__init__.py +++ b/tools/isledecomp/isledecomp/parser/__init__.py @@ -1,2 +1,3 @@ +from .codebase import DecompCodebase from .parser import DecompParser from .linter import DecompLinter diff --git a/tools/isledecomp/isledecomp/parser/codebase.py b/tools/isledecomp/isledecomp/parser/codebase.py new file mode 100644 index 00000000..184b1256 --- /dev/null +++ b/tools/isledecomp/isledecomp/parser/codebase.py @@ -0,0 +1,48 @@ +"""For aggregating decomp markers read from an entire directory and for a single module.""" +from typing import Iterable, Iterator, List +from .parser import DecompParser +from .node import ( + ParserSymbol, + ParserFunction, + ParserVtable, + ParserVariable, + ParserString, +) + + +class DecompCodebase: + def __init__(self, filenames: Iterable[str], module: str) -> None: + self._symbols: List[ParserSymbol] = [] + + parser = DecompParser() + for filename in filenames: + parser.reset() + with open(filename, "r", encoding="utf-8") as f: + parser.read_lines(f) + + for sym in parser.iter_symbols(module): + sym.filename = filename + self._symbols.append(sym) + + def iter_line_functions(self) -> Iterator[ParserFunction]: + """Return lineref functions separately from nameref. Assuming the PDB matches + the state of the source code, a line reference is a guaranteed match, even if + multiple functions share the same name. (i.e. polymorphism)""" + return filter( + lambda s: isinstance(s, ParserFunction) and not s.is_nameref(), + self._symbols, + ) + + def iter_name_functions(self) -> Iterator[ParserFunction]: + return filter( + lambda s: isinstance(s, ParserFunction) and s.is_nameref(), self._symbols + ) + + def iter_vtables(self) -> Iterator[ParserVtable]: + return filter(lambda s: isinstance(s, ParserVtable), self._symbols) + + 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 638a806e..81123381 100644 --- a/tools/isledecomp/isledecomp/parser/error.py +++ b/tools/isledecomp/isledecomp/parser/error.py @@ -39,6 +39,14 @@ class ParserError(Enum): # WARN: We found a marker to be referenced by name outside of a header file. BYNAME_FUNCTION_IN_CPP = 109 + # WARN: A GLOBAL marker appeared over a variable without the g_ prefix + GLOBAL_MISSING_PREFIX = 110 + + # WARN: GLOBAL marker points at something other than variable declaration. + # We can't match global variables based on position, but the goal here is + # to ignore things like string literal that are not variables. + GLOBAL_NOT_VARIABLE = 111 + # This code or higher is an error, not a warning DECOMP_ERROR_START = 200 @@ -50,13 +58,22 @@ class ParserError(Enum): # For example, a GLOBAL cannot follow FUNCTION/STUB INCOMPATIBLE_MARKER = 201 - # ERROR: The line following a synthetic marker was not a comment - BAD_SYNTHETIC = 202 + # ERROR: The line following an explicit by-name marker was not a comment + # We assume a syntax error here rather than try to use the next line + BAD_NAMEREF = 202 # ERROR: This function offset comes before the previous offset from the same module # This hopefully gives some hint about which functions need to be rearranged. FUNCTION_OUT_OF_ORDER = 203 + # ERROR: The line following an explicit by-name marker that does _not_ expect + # 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 new file mode 100644 index 00000000..de8c6f05 --- /dev/null +++ b/tools/isledecomp/isledecomp/parser/marker.py @@ -0,0 +1,133 @@ +import re +from typing import Optional +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 + STUB = 2 + SYNTHETIC = 3 + TEMPLATE = 4 + GLOBAL = 5 + VTABLE = 6 + STRING = 7 + LIBRARY = 8 + + +markerRegex = re.compile( + r"\s*//\s*(?P\w+):\s*(?P\w+)\s+(?P0x[a-f0-9]+)", + flags=re.I, +) + + +markerExactRegex = re.compile( + r"\s*// (?P[A-Z]+): (?P[A-Z0-9]+) (?P0x[a-f0-9]+)$" +) + + +class DecompMarker: + def __init__(self, marker_type: str, module: str, offset: int) -> None: + try: + self._type = MarkerType[marker_type.upper()] + except KeyError: + self._type = MarkerType.UNKNOWN + + # Convert to upper here. A lot of other analysis depends on this name + # being consistent and predictable. If the name is _not_ capitalized + # we will emit a syntax error. + self._module: str = module.upper() + self._offset: int = offset + + @property + def type(self) -> MarkerType: + return self._type + + @property + def module(self) -> str: + return self._module + + @property + 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. + FUNCTION and STUB markers are (currently) the only heterogenous marker types that + can be lumped together, although the reasons for doing so are a little vague.""" + return self._type in (MarkerType.FUNCTION, MarkerType.STUB) + + def is_explicit_byname(self) -> bool: + return self._type in ( + MarkerType.SYNTHETIC, + MarkerType.TEMPLATE, + MarkerType.LIBRARY, + ) + + def is_variable(self) -> bool: + return self._type == MarkerType.GLOBAL + + def is_synthetic(self) -> bool: + return self._type == MarkerType.SYNTHETIC + + def is_template(self) -> bool: + return self._type == MarkerType.TEMPLATE + + def is_vtable(self) -> bool: + return self._type == MarkerType.VTABLE + + def is_library(self) -> bool: + return self._type == MarkerType.LIBRARY + + def is_string(self) -> bool: + return self._type == MarkerType.STRING + + def allowed_in_func(self) -> bool: + return self._type in (MarkerType.GLOBAL, MarkerType.STRING) + + +def match_marker(line: str) -> Optional[DecompMarker]: + match = markerRegex.match(line) + if match is None: + return None + + return DecompMarker( + marker_type=match.group("type"), + module=match.group("module"), + offset=int(match.group("offset"), 16), + ) + + +def is_marker_exact(line: str) -> bool: + return markerExactRegex.match(line) is not None diff --git a/tools/isledecomp/isledecomp/parser/node.py b/tools/isledecomp/isledecomp/parser/node.py index 721a24b9..71d4ebdd 100644 --- a/tools/isledecomp/isledecomp/parser/node.py +++ b/tools/isledecomp/isledecomp/parser/node.py @@ -1,35 +1,62 @@ +from typing import Optional from dataclasses import dataclass +from .marker import MarkerType @dataclass -class ParserNode: +class ParserSymbol: + """Exported decomp marker with all information (except the code filename) required to + cross-reference with cvdump data.""" + + type: MarkerType line_number: int - - -@dataclass -class ParserSymbol(ParserNode): module: str offset: int + name: str + + # The parser doesn't (currently) know about the code filename, but if you + # wanted to set it here after the fact, here's the spot. + filename: Optional[str] = None + + def should_skip(self) -> bool: + """The default is to compare any symbols we have""" + return False + + def is_nameref(self) -> bool: + """All symbols default to name lookup""" + return True @dataclass class ParserFunction(ParserSymbol): - name: str + # We are able to detect the closing line of a function with some reliability. + # This isn't used for anything right now, but perhaps later it will be. + end_line: Optional[int] = None + + # All marker types are referenced by name except FUNCTION/STUB. These can also be + # referenced by name, but only if this flag is true. lookup_by_name: bool = False - is_stub: bool = False - is_synthetic: bool = False - is_template: bool = False - end_line: int = -1 + + def should_skip(self) -> bool: + return self.type == MarkerType.STUB + + def is_nameref(self) -> bool: + return ( + self.type in (MarkerType.SYNTHETIC, MarkerType.TEMPLATE, MarkerType.LIBRARY) + or self.lookup_by_name + ) @dataclass class ParserVariable(ParserSymbol): - name: str - size: int = -1 is_static: bool = False @dataclass class ParserVtable(ParserSymbol): - class_name: str - num_entries: int = -1 + pass + + +@dataclass +class ParserString(ParserSymbol): + pass diff --git a/tools/isledecomp/isledecomp/parser/parser.py b/tools/isledecomp/isledecomp/parser/parser.py index 336d4b0c..4d8beace 100644 --- a/tools/isledecomp/isledecomp/parser/parser.py +++ b/tools/isledecomp/isledecomp/parser/parser.py @@ -1,20 +1,27 @@ # C++ file parser -from typing import List, Iterable, Iterator +from typing import List, Iterable, Iterator, Optional from enum import Enum from .util import ( - DecompMarker, - is_blank_or_comment, - match_marker, - is_marker_exact, get_class_name, + get_variable_name, get_synthetic_name, remove_trailing_comment, + get_string_contents, + sanitize_code_line, + scopeDetectRegex, +) +from .marker import ( + DecompMarker, + match_marker, + is_marker_exact, ) from .node import ( + ParserSymbol, ParserFunction, ParserVariable, ParserVtable, + ParserString, ) from .error import ParserAlert, ParserError @@ -28,63 +35,90 @@ class ReaderState(Enum): IN_GLOBAL = 5 IN_FUNC_GLOBAL = 6 IN_VTABLE = 7 + IN_SYNTHETIC = 8 + IN_LIBRARY = 9 DONE = 100 -def marker_is_stub(marker: DecompMarker) -> bool: - return marker.type.upper() == "STUB" - - -def marker_is_variable(marker: DecompMarker) -> bool: - return marker.type.upper() == "GLOBAL" - - -def marker_is_synthetic(marker: DecompMarker) -> bool: - return marker.type.upper() in ("SYNTHETIC", "TEMPLATE") - - -def marker_is_template(marker: DecompMarker) -> bool: - return marker.type.upper() == "TEMPLATE" - - -def marker_is_function(marker: DecompMarker) -> bool: - return marker.type.upper() in ("FUNCTION", "STUB") - - -def marker_is_vtable(marker: DecompMarker) -> bool: - return marker.type.upper() == "VTABLE" - - class MarkerDict: def __init__(self) -> None: self.markers: dict = {} def insert(self, marker: DecompMarker) -> bool: """Return True if this insert would overwrite""" - module = marker.module.upper() - if module in self.markers: + key = (marker.category, marker.module) + if key in self.markers: return True - self.markers[module] = (marker.type, 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 = {} +class CurlyManager: + """Overly simplified scope manager""" + + def __init__(self): + self._stack = [] + + def reset(self): + self._stack = [] + + def _pop(self): + """Pop stack safely""" + try: + self._stack.pop() + except IndexError: + pass + + def get_prefix(self, name: Optional[str] = None) -> str: + """Return the prefix for where we are.""" + + scopes = [t for t in self._stack if t != "{"] + if len(scopes) == 0: + return name if name is not None else "" + + if name is not None and name not in scopes: + scopes.append(name) + + return "::".join(scopes) + + def read_line(self, raw_line: str): + """Read a line of code and update the stack.""" + line = sanitize_code_line(raw_line) + if (match := scopeDetectRegex.match(line)) is not None: + if not line.endswith(";"): + self._stack.append(match.group("name")) + + change = line.count("{") - line.count("}") + if change > 0: + for _ in range(change): + self._stack.append("{") + elif change < 0: + for _ in range(-change): + self._pop() + + if len(self._stack) == 0: + return + + last = self._stack[-1] + if last != "{": + self._pop() + + class DecompParser: # pylint: disable=too-many-instance-attributes # Could combine output lists into a single list to get under the limit, # but not right now def __init__(self) -> None: # The lists to be populated as we parse - self.functions: List[ParserFunction] = [] - self.vtables: List[ParserVtable] = [] - self.variables: List[ParserVariable] = [] + self._symbols: List[ParserSymbol] = [] self.alerts: List[ParserAlert] = [] self.line_number: int = 0 @@ -92,6 +126,8 @@ def __init__(self) -> None: self.last_line: str = "" + self.curly = CurlyManager() + # To allow for multiple markers where code is shared across different # modules, save lists of compatible markers that appear in sequence self.fun_markers = MarkerDict() @@ -113,9 +149,7 @@ def __init__(self) -> None: self.function_sig: str = "" def reset(self): - self.functions = [] - self.vtables = [] - self.variables = [] + self._symbols = [] self.alerts = [] self.line_number = 0 @@ -131,6 +165,29 @@ def reset(self): self.function_start = 0 self.function_sig = "" + self.curly.reset() + + @property + def functions(self) -> List[ParserFunction]: + return [s for s in self._symbols if isinstance(s, ParserFunction)] + + @property + def vtables(self) -> List[ParserVtable]: + return [s for s in self._symbols if isinstance(s, ParserVtable)] + + @property + 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: + yield s + def _recover(self): """We hit a syntax error and need to reset temp structures""" self.state = ReaderState.SEARCH @@ -159,10 +216,17 @@ def _function_marker(self, marker: DecompMarker): self._syntax_warning(ParserError.DUPLICATE_MODULE) self.state = ReaderState.WANT_SIG - def _synthetic_marker(self, marker: DecompMarker): + def _nameref_marker(self, marker: DecompMarker): + """Functions explicitly referenced by name are set here""" if self.fun_markers.insert(marker): self._syntax_warning(ParserError.DUPLICATE_MODULE) - self.state = ReaderState.IN_TEMPLATE + + if marker.is_template(): + self.state = ReaderState.IN_TEMPLATE + elif marker.is_synthetic(): + self.state = ReaderState.IN_SYNTHETIC + else: + self.state = ReaderState.IN_LIBRARY def _function_done(self, lookup_by_name: bool = False, unexpected: bool = False): end_line = self.line_number @@ -173,16 +237,14 @@ def _function_done(self, lookup_by_name: bool = False, unexpected: bool = False) end_line -= 1 for marker in self.fun_markers.iter(): - self.functions.append( + self._symbols.append( ParserFunction( + type=marker.type, line_number=self.function_start, module=marker.module, offset=marker.offset, - lookup_by_name=lookup_by_name, - is_stub=marker_is_stub(marker), - is_synthetic=marker_is_synthetic(marker), - is_template=marker_is_template(marker), name=self.function_sig, + lookup_by_name=lookup_by_name, end_line=end_line, ) ) @@ -202,12 +264,13 @@ def _vtable_done(self, class_name: str = None): class_name = self.last_line.strip() for marker in self.tbl_markers.iter(): - self.vtables.append( + self._symbols.append( ParserVtable( + type=marker.type, line_number=self.line_number, module=marker.module, offset=marker.offset, - class_name=class_name, + name=self.curly.get_prefix(class_name), ) ) @@ -223,16 +286,35 @@ def _variable_marker(self, marker: DecompMarker): else: self.state = ReaderState.IN_GLOBAL - def _variable_done(self): + 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.variables.append( - ParserVariable( - line_number=self.line_number, - module=marker.module, - offset=marker.offset, - name=self.last_line.strip(), + 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=self.curly.get_prefix(variable_name), + is_static=self.state == ReaderState.IN_FUNC_GLOBAL, + ) ) - ) self.var_markers.empty() if self.state == ReaderState.IN_FUNC_GLOBAL: @@ -246,12 +328,23 @@ def _handle_marker(self, marker: DecompMarker): self._syntax_error(ParserError.UNEXPECTED_MARKER) return + # If we are inside a function, the only markers we accept are: + # GLOBAL, indicating a static variable + # STRING, indicating a literal string. + # Otherwise we assume that the parser missed the end of the function + # and we have moved on to something else. + # This is unlikely to occur with well-formed code, but + # we can recover easily by just ending the function here. + if self.state == ReaderState.IN_FUNC and not marker.allowed_in_func(): + self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) + self._function_done(unexpected=True) + # TODO: How uncertain are we of detecting the end of a function # in a clang-formatted file? For now we assume we have missed the # end if we detect a non-GLOBAL marker while state is IN_FUNC. # Maybe these cases should be syntax errors instead - if marker_is_function(marker): + if marker.is_regular_function(): if self.state in ( ReaderState.SEARCH, ReaderState.WANT_SIG, @@ -259,29 +352,29 @@ def _handle_marker(self, marker: DecompMarker): # We will allow multiple offsets if we have just begun # the code block, but not after we hit the curly brace. self._function_marker(marker) - elif self.state == ReaderState.IN_FUNC: - # We hit another offset unexpectedly. - # We can recover easily by just ending the function here. - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(unexpected=True) - - # Start the next function right after so we can - # read the next line. - self._function_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_synthetic(marker): + elif marker.is_template(): if self.state in (ReaderState.SEARCH, ReaderState.IN_TEMPLATE): - self._synthetic_marker(marker) - elif self.state == ReaderState.IN_FUNC: - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(lookup_by_name=True, unexpected=True) - self._synthetic_marker(marker) + self._nameref_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_variable(marker): + elif marker.is_synthetic(): + if self.state in (ReaderState.SEARCH, ReaderState.IN_SYNTHETIC): + self._nameref_marker(marker) + else: + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + elif marker.is_library(): + if self.state in (ReaderState.SEARCH, ReaderState.IN_LIBRARY): + self._nameref_marker(marker) + else: + self._syntax_error(ParserError.INCOMPATIBLE_MARKER) + + # 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, @@ -292,13 +385,9 @@ def _handle_marker(self, marker: DecompMarker): else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker_is_vtable(marker): + elif marker.is_vtable(): if self.state in (ReaderState.SEARCH, ReaderState.IN_VTABLE): self._vtable_marker(marker) - elif self.state == ReaderState.IN_FUNC: - self._syntax_warning(ParserError.MISSED_END_OF_FUNCTION) - self._function_done(unexpected=True) - self._vtable_marker(marker) else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) @@ -321,13 +410,19 @@ def read_line(self, line: str): self._handle_marker(marker) return + self.curly.read_line(line) + line_strip = line.strip() - if self.state == ReaderState.IN_TEMPLATE: - # TEMPLATE functions are a special case. The signature is - # given on the next line (in a // comment) + if self.state in ( + ReaderState.IN_SYNTHETIC, + ReaderState.IN_TEMPLATE, + ReaderState.IN_LIBRARY, + ): + # Explicit nameref functions provide the function name + # on the next line (in a // comment) name = get_synthetic_name(line) if name is None: - self._syntax_error(ParserError.BAD_SYNTHETIC) + self._syntax_error(ParserError.BAD_NAMEREF) else: self.function_sig = name self._function_starts_here() @@ -384,8 +479,46 @@ def read_line(self, line: str): self._function_done() elif self.state in (ReaderState.IN_GLOBAL, ReaderState.IN_FUNC_GLOBAL): - if not is_blank_or_comment(line): - self._variable_done() + # TODO: Known problem that an error here will cause us to abandon a + # 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. + 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 + + 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: + # Before checking for the prefix, remove the + # namespace chain if there is one. + if not variable_name.split("::")[-1].startswith("g_"): + self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) + + string_name = get_string_contents(line) + + 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 99ab1c56..bfe3803c 100644 --- a/tools/isledecomp/isledecomp/parser/util.py +++ b/tools/isledecomp/isledecomp/parser/util.py @@ -1,29 +1,33 @@ # C++ Parser utility functions and data structures -from __future__ import annotations # python <3.10 compatibility import re -from collections import namedtuple - -DecompMarker = namedtuple("DecompMarker", ["type", "module", "offset"]) - - -markerRegex = re.compile( - r"\s*//\s*(\w+):\s*(\w+)\s+(0x[a-f0-9]+)", - flags=re.I, -) - -markerExactRegex = re.compile(r"\s*// ([A-Z]+): ([A-Z0-9]+) (0x[a-f0-9]+)$") +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 templateCommentRegex = re.compile(r"\s*//\s+(.*)") - # To remove any comment (//) or block comment (/*) and its leading spaces # from the end of a code line trailingCommentRegex = re.compile(r"(\s*(?://|/\*).*)$") +# Get char contents, ignore escape characters +singleQuoteRegex = re.compile(r"('(?:[^\'\\]|\\.)')") -def get_synthetic_name(line: str) -> str | None: +# Match contents of block comment on one line +blockCommentRegex = re.compile(r"(/\*.*?\*/)") + +# Match contents of single comment on one line +regularCommentRegex = re.compile(r"(//.*)") + +# Get string contents, ignore escape characters that might interfere +doubleQuoteRegex = re.compile(r"(\"(?:[^\"\\]|\\.)*\")") + +# Detect a line that would cause us to enter a new scope +scopeDetectRegex = re.compile(r"(?:class|struct|namespace) (?P\w+).*(?:{)?") + + +def get_synthetic_name(line: str) -> Optional[str]: """Synthetic names appear on a single line comment on the line after the marker. If that's not what we have, return None""" template_match = templateCommentRegex.match(line) @@ -34,6 +38,20 @@ def get_synthetic_name(line: str) -> str | None: return None +def sanitize_code_line(line: str) -> str: + """Helper for scope manager. Removes sections from a code line + that would cause us to incorrectly detect curly brackets. + This is a very naive implementation and fails entirely on multi-line + strings or comments.""" + + line = singleQuoteRegex.sub("''", line) + line = doubleQuoteRegex.sub('""', line) + line = blockCommentRegex.sub("", line) + line = regularCommentRegex.sub("", line) + + return line.strip() + + def remove_trailing_comment(line: str) -> str: return trailingCommentRegex.sub("", line) @@ -51,20 +69,6 @@ def is_blank_or_comment(line: str) -> bool: ) -def match_marker(line: str) -> DecompMarker | None: - match = markerRegex.match(line) - if match is None: - return None - - return DecompMarker( - type=match.group(1), module=match.group(2), offset=int(match.group(3), 16) - ) - - -def is_marker_exact(line: str) -> bool: - return markerExactRegex.match(line) is not None - - template_class_decl_regex = re.compile( r"\s*(?:\/\/)?\s*(?:class|struct) (\w+)<([\w]+)\s*(\*+)?\s*>" ) @@ -73,7 +77,7 @@ def is_marker_exact(line: str) -> bool: class_decl_regex = re.compile(r"\s*(?:\/\/)?\s*(?:class|struct) (\w+)") -def get_class_name(line: str) -> str | None: +def get_class_name(line: str) -> Optional[str]: """For VTABLE markers, extract the class name from the code line or comment where it appears.""" @@ -93,3 +97,38 @@ def get_class_name(line: str) -> str | None: return match.group(1) return None + + +global_regex = re.compile(r"(?P(?:\w+::)*g_\w+)") +less_strict_global_regex = re.compile(r"(?P(?:\w+::)*\w+)(?:\)\(|\[.*|\s*=.*|;)") + + +def get_variable_name(line: str) -> Optional[str]: + """Grab the name of the variable annotated with the GLOBAL marker. + Correct syntax would have the variable start with the prefix "g_" + but we will try to match regardless.""" + + if (match := global_regex.search(line)) is not None: + return match.group("name") + + if (match := less_strict_global_regex.search(line)) is not None: + 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/syminfo.py b/tools/isledecomp/isledecomp/syminfo.py deleted file mode 100644 index e7ab0df4..00000000 --- a/tools/isledecomp/isledecomp/syminfo.py +++ /dev/null @@ -1,138 +0,0 @@ -import os -import subprocess -from isledecomp.lib import lib_path_join -from isledecomp.dir import PathResolver, winepath_unix_to_win - - -class RecompiledInfo: - addr = None - size = None - name = None - start = None - - -# Declare a class that parses the output of cvdump for fast access later -class SymInfo: - funcs = {} - lines = {} - names = {} - - def __init__(self, pdb, sym_recompfile, sym_logger, base_dir): - self.logger = sym_logger - path_resolver = PathResolver(base_dir) - call = [lib_path_join("cvdump.exe"), "-l", "-s"] - - if os.name != "nt": - # Run cvdump through wine and convert path to Windows-friendly wine path - call.insert(0, "wine") - call.append(winepath_unix_to_win(pdb)) - else: - call.append(pdb) - - self.logger.info("Parsing %s ...", pdb) - self.logger.debug("Command = %s", call) - line_dump = subprocess.check_output(call).decode("utf-8").split("\r\n") - - current_section = None - - self.logger.debug("Parsing output of cvdump.exe ...") - - for i, line in enumerate(line_dump): - if line.startswith("***"): - current_section = line[4:] - - if current_section == "SYMBOLS" and "S_GPROC32" in line: - sym_section = int(line[21:25], 16) - sym_addr = int(line[26:34], 16) - - info = RecompiledInfo() - info.addr = sym_addr + sym_recompfile.get_section_offset_by_index( - sym_section - ) - - use_dbg_offs = False - if use_dbg_offs: - debug_offs = line_dump[i + 2] - debug_start = int(debug_offs[22:30], 16) - debug_end = int(debug_offs[43:], 16) - - info.start = debug_start - info.size = debug_end - debug_start - else: - info.start = 0 - info.size = int(line[41:49], 16) - - info.name = line[77:] - - self.names[info.name] = info - self.funcs[sym_addr] = info - elif ( - current_section == "LINES" - and line.startswith(" ") - and not line.startswith(" ") - ): - sourcepath = line.split()[0] - sourcepath = path_resolver.resolve_cvdump(sourcepath) - - if sourcepath not in self.lines: - self.lines[sourcepath] = {} - - j = i + 2 - while True: - ll = line_dump[j].split() - if len(ll) == 0: - break - - k = 0 - while k < len(ll): - linenum = int(ll[k + 0]) - address = int(ll[k + 1], 16) - if linenum not in self.lines[sourcepath]: - self.lines[sourcepath][linenum] = address - k += 2 - - j += 1 - - self.logger.debug("... Parsing output of cvdump.exe finished") - - def get_recompiled_address(self, filename, line): - recompiled_addr = None - - self.logger.debug("Looking for %s:%s", filename, line) - filename_basename = os.path.basename(filename).lower() - - for fn in self.lines: - # Sometimes a PDB is compiled with a relative path while we always have - # an absolute path. Therefore we must - try: - if os.path.basename( - fn - ).lower() == filename_basename and os.path.samefile(fn, filename): - filename = fn - break - except FileNotFoundError: - continue - - if filename in self.lines and line in self.lines[filename]: - recompiled_addr = self.lines[filename][line] - - if recompiled_addr in self.funcs: - return self.funcs[recompiled_addr] - self.logger.error( - "Failed to find function symbol with address: %x", recompiled_addr - ) - return None - self.logger.error( - "Failed to find function symbol with filename and line: %s:%s", - filename, - line, - ) - return None - - def get_recompiled_address_from_name(self, name): - self.logger.debug("Looking for %s", name) - - if name in self.names: - return self.names[name] - self.logger.error("Failed to find function symbol with name: %s", name) - return None diff --git a/tools/isledecomp/isledecomp/types.py b/tools/isledecomp/isledecomp/types.py new file mode 100644 index 00000000..4d518dd3 --- /dev/null +++ b/tools/isledecomp/isledecomp/types.py @@ -0,0 +1,12 @@ +"""Types shared by other modules""" +from enum import Enum + + +class SymbolType(Enum): + """Broadly tells us what kind of comparison is required for this symbol.""" + + FUNCTION = 1 + DATA = 2 + POINTER = 3 + STRING = 4 + VTABLE = 5 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_curly.py b/tools/isledecomp/tests/test_curly.py new file mode 100644 index 00000000..8328f5e9 --- /dev/null +++ b/tools/isledecomp/tests/test_curly.py @@ -0,0 +1,73 @@ +# nyuk nyuk nyuk +import pytest +from isledecomp.parser.parser import CurlyManager +from isledecomp.parser.util import sanitize_code_line + + +@pytest.fixture(name="curly") +def fixture_curly(): + return CurlyManager() + + +def test_simple(curly): + curly.read_line("namespace Test {") + assert curly.get_prefix() == "Test" + curly.read_line("}") + assert curly.get_prefix() == "" + + +def test_oneliner(curly): + """Should not go down into a scope for a class forward reference""" + curly.read_line("class LegoEntity;") + assert curly.get_prefix() == "" + # Now make sure that we still would not consider that class name + # even after reading the opening curly brace + curly.read_line("if (true) {") + assert curly.get_prefix() == "" + + +def test_ignore_comments(curly): + curly.read_line("namespace Test {") + curly.read_line("// }") + assert curly.get_prefix() == "Test" + + +@pytest.mark.xfail(reason="todo: need a real lexer") +def test_ignore_multiline_comments(curly): + curly.read_line("namespace Test {") + curly.read_line("/*") + curly.read_line("}") + curly.read_line("*/") + assert curly.get_prefix() == "Test" + curly.read_line("}") + assert curly.get_prefix() == "" + + +def test_nested(curly): + curly.read_line("namespace Test {") + curly.read_line("namespace Foo {") + assert curly.get_prefix() == "Test::Foo" + curly.read_line("}") + assert curly.get_prefix() == "Test" + + +sanitize_cases = [ + ("", ""), + (" ", ""), + ("{", "{"), + ("// comments {", ""), + ("{ // why comment here", "{"), + ("/* comments */ {", "{"), + ('"curly in a string {"', '""'), + ('if (!strcmp("hello { there }", g_test)) {', 'if (!strcmp("", g_test)) {'), + ("'{'", "''"), + ("weird_function('\"', hello, '\"')", "weird_function('', hello, '')"), +] + + +@pytest.mark.parametrize("start, end", sanitize_cases) +def test_sanitize(start: str, end: str): + """Make sure that we can remove curly braces in places where they should + not be considered as part of the semantic structure of the file. + i.e. inside strings or chars, and inside comments""" + assert sanitize_code_line(start) == end diff --git a/tools/isledecomp/tests/test_cvdump.py b/tools/isledecomp/tests/test_cvdump.py new file mode 100644 index 00000000..cfaff7a9 --- /dev/null +++ b/tools/isledecomp/tests/test_cvdump.py @@ -0,0 +1,39 @@ +import pytest +from isledecomp.cvdump.analysis import data_type_info + +# fmt: off +type_check_cases = [ + ("T_32PINT4", 4, True), + ("T_32PLONG", 4, True), + ("T_32PRCHAR", 4, True), + ("T_32PREAL32", 4, True), + ("T_32PUCHAR", 4, True), + ("T_32PUINT4", 4, True), + ("T_32PULONG", 4, True), + ("T_32PUSHORT", 4, True), + ("T_32PVOID", 4, True), + ("T_CHAR", 1, False), + ("T_INT4", 4, False), + ("T_LONG", 4, False), + ("T_NOTYPE", 0, False), # ? + ("T_QUAD", 8, False), + ("T_RCHAR", 1, False), + ("T_REAL32", 4, False), + ("T_REAL64", 8, False), + ("T_SHORT", 2, False), + ("T_UCHAR", 1, False), + ("T_UINT4", 4, False), + ("T_ULONG", 4, False), + ("T_UQUAD", 8, False), + ("T_USHORT", 2, False), + ("T_VOID", 0, False), # ? + ("T_WCHAR", 2, False), +] +# fmt: on + + +@pytest.mark.parametrize("type_name, size, is_pointer", type_check_cases) +def test_type_check(type_name: str, size: int, is_pointer: bool): + assert (info := data_type_info(type_name)) is not None + assert info[0] == size + assert info[1] == is_pointer diff --git a/tools/isledecomp/tests/test_demangler.py b/tools/isledecomp/tests/test_demangler.py new file mode 100644 index 00000000..9d0b5203 --- /dev/null +++ b/tools/isledecomp/tests/test_demangler.py @@ -0,0 +1,57 @@ +import pytest +from isledecomp.cvdump.demangler import ( + demangle_string_const, + demangle_vtable, + parse_encoded_number, + InvalidEncodedNumberError, +) + +string_demangle_cases = [ + ("??_C@_08LIDF@December?$AA@", 8, False), + ("??_C@_0L@EGPP@english?9nz?$AA@", 11, False), + ( + "??_C@_1O@POHA@?$AA?$CI?$AAn?$AAu?$AAl?$AAl?$AA?$CJ?$AA?$AA?$AA?$AA?$AA?$AH?$AA?$AA?$AA?$AA?$AA?$AA?$AA?$9A?$AE?$;I@", + 14, + True, + ), + ("??_C@_00A@?$AA@", 0, False), +] + + +@pytest.mark.parametrize("symbol, strlen, is_utf16", string_demangle_cases) +def test_strings(symbol, is_utf16, strlen): + s = demangle_string_const(symbol) + assert s.len == strlen + assert s.is_utf16 == is_utf16 + + +encoded_numbers = [ + ("A@", 0), + ("AA@", 0), # would never happen? + ("P@", 15), + ("BA@", 16), + ("BCD@", 291), +] + + +@pytest.mark.parametrize("string, value", encoded_numbers) +def test_encoded_numbers(string, value): + assert parse_encoded_number(string) == value + + +def test_invalid_encoded_number(): + with pytest.raises(InvalidEncodedNumberError): + parse_encoded_number("Hello") + + +vtable_cases = [ + ("??_7LegoCarBuildAnimPresenter@@6B@", "LegoCarBuildAnimPresenter"), + ("??_7?$MxCollection@PAVLegoWorld@@@@6B@", "MxCollection"), + ("??_7?$MxPtrList@VLegoPathController@@@@6B@", "MxPtrList"), + ("??_7Renderer@Tgl@@6B@", "Tgl::Renderer"), +] + + +@pytest.mark.parametrize("symbol, class_name", vtable_cases) +def test_vtable(symbol, class_name): + assert demangle_vtable(symbol) == class_name 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 c31602f1..7dcc24b1 100644 --- a/tools/isledecomp/tests/test_parser.py +++ b/tools/isledecomp/tests/test_parser.py @@ -115,7 +115,7 @@ def test_different_markers_same_module(parser): # Use first marker declaration, don't replace assert len(parser.functions) == 1 - assert parser.functions[0].is_stub is False + assert parser.functions[0].should_skip() is False # Should alert to this assert len(parser.alerts) == 1 @@ -193,7 +193,7 @@ def test_multiple_vtables(parser): ) assert len(parser.alerts) == 0 assert len(parser.vtables) == 2 - assert parser.vtables[0].class_name == "MxString" + assert parser.vtables[0].name == "MxString" def test_multiple_vtables_same_module(parser): @@ -247,7 +247,7 @@ def test_synthetic_no_comment(parser): ) assert len(parser.functions) == 0 assert len(parser.alerts) == 1 - assert parser.alerts[0].code == ParserError.BAD_SYNTHETIC + assert parser.alerts[0].code == ParserError.BAD_NAMEREF assert parser.state == ReaderState.SEARCH @@ -375,3 +375,257 @@ def test_unexpected_eof(parser): assert len(parser.functions) == 1 assert len(parser.alerts) == 1 assert parser.alerts[0].code == ParserError.UNEXPECTED_END_OF_FILE + + +def test_global_variable_prefix(parser): + """Global and static variables should have the g_ prefix.""" + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + 'const char* g_msg = "hello";', + ] + ) + assert len(parser.variables) == 1 + assert len(parser.alerts) == 0 + + parser.read_lines( + [ + "// GLOBAL: TEXT 0x5555", + "int test = 5;", + ] + ) + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.GLOBAL_MISSING_PREFIX + # In spite of that, we should still grab the variable name. + assert parser.variables[1].name == "test" + + +def test_global_nomatch(parser): + """We do our best to grab the variable name, even without the g_ prefix + but this (by design) will not match everything.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "FunctionCall();", + ] + ) + assert len(parser.variables) == 0 + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.NO_SUITABLE_NAME + + +def test_static_variable(parser): + """We can detect whether a variable is a static function variable + based on the parser's state when we detect it. + Checking for the word `static` alone is not a good test. + Static class variables are filed as S_GDATA32, same as regular globals. + Only function statics are filed as S_LDATA32.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "int g_test = 1234;", + ] + ) + assert len(parser.variables) == 1 + assert parser.variables[0].is_static is False + + parser.read_lines( + [ + "// FUNCTION: TEST 0x5555", + "void test_function() {", + "// GLOBAL: TEST 0x8888", + "int g_internal = 0;", + "}", + ] + ) + 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 + + +def test_class_variable(parser): + """We should accurately name static variables that are class members.""" + + parser.read_lines( + [ + "class Test {", + "protected:", + " // GLOBAL: TEST 0x1234", + " static int g_test;", + "};", + ] + ) + + assert len(parser.variables) == 1 + assert parser.variables[0].name == "Test::g_test" + + +def test_namespace_variable(parser): + """We should identify a namespace surrounding any global variables""" + + parser.read_lines( + [ + "namespace Test {", + "// GLOBAL: TEST 0x1234", + "int g_test = 1234;", + "}", + "// GLOBAL: TEST 0x5555", + "int g_second = 2;", + ] + ) + + assert len(parser.variables) == 2 + assert parser.variables[0].name == "Test::g_test" + assert parser.variables[1].name == "g_second" + + +def test_namespace_vtable(parser): + parser.read_lines( + [ + "namespace Tgl {", + "// VTABLE: TEST 0x1234", + "class Renderer {", + "};", + "}", + "// VTABLE: TEST 0x5555", + "class Hello { };", + ] + ) + + assert len(parser.vtables) == 2 + assert parser.vtables[0].name == "Tgl::Renderer" + assert parser.vtables[1].name == "Hello" + + +def test_global_prefix_namespace(parser): + """Should correctly identify namespaces before checking for the g_ prefix""" + + parser.read_lines( + [ + "class Test {", + " // GLOBAL: TEST 0x1234", + " static int g_count = 0;", + " // GLOBAL: TEST 0x5555", + " static int count = 0;", + "};", + ] + ) + + assert len(parser.variables) == 2 + assert parser.variables[0].name == "Test::g_count" + assert parser.variables[1].name == "Test::count" + + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.GLOBAL_MISSING_PREFIX + + +def test_nested_namespace(parser): + parser.read_lines( + [ + "namespace Tgl {", + "class Renderer {", + " // GLOBAL: TEST 0x1234", + " static int g_count = 0;", + "};", + "};", + ] + ) + + assert len(parser.variables) == 1 + assert parser.variables[0].name == "Tgl::Renderer::g_count" + + +def test_match_qualified_variable(parser): + """If a variable belongs to a scope and we use a fully qualified reference + below a GLOBAL marker, make sure we capture the full name.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "int MxTest::g_count = 0;", + ] + ) + + assert len(parser.variables) == 1 + assert parser.variables[0].name == "MxTest::g_count" + assert len(parser.alerts) == 0 diff --git a/tools/isledecomp/tests/test_parser_statechange.py b/tools/isledecomp/tests/test_parser_statechange.py index 8d18d547..be37e3c8 100644 --- a/tools/isledecomp/tests/test_parser_statechange.py +++ b/tools/isledecomp/tests/test_parser_statechange.py @@ -11,9 +11,11 @@ (_rs.SEARCH, "FUNCTION", _rs.WANT_SIG, None), (_rs.SEARCH, "GLOBAL", _rs.IN_GLOBAL, None), (_rs.SEARCH, "STUB", _rs.WANT_SIG, None), - (_rs.SEARCH, "SYNTHETIC", _rs.IN_TEMPLATE, None), + (_rs.SEARCH, "SYNTHETIC", _rs.IN_SYNTHETIC, None), (_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.IN_GLOBAL, None), (_rs.WANT_SIG, "FUNCTION", _rs.WANT_SIG, None), (_rs.WANT_SIG, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -21,20 +23,26 @@ (_rs.WANT_SIG, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_SIG, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_SIG, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.WANT_SIG, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.WANT_SIG, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC, "FUNCTION", _rs.WANT_SIG, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), (_rs.IN_FUNC, "STUB", _rs.WANT_SIG, _pe.MISSED_END_OF_FUNCTION), - (_rs.IN_FUNC, "SYNTHETIC", _rs.IN_TEMPLATE, _pe.MISSED_END_OF_FUNCTION), + (_rs.IN_FUNC, "SYNTHETIC", _rs.IN_SYNTHETIC, _pe.MISSED_END_OF_FUNCTION), (_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_GLOBAL, None), (_rs.IN_TEMPLATE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), - (_rs.IN_TEMPLATE, "SYNTHETIC", _rs.IN_TEMPLATE, None), + (_rs.IN_TEMPLATE, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "TEMPLATE", _rs.IN_TEMPLATE, None), (_rs.IN_TEMPLATE, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_TEMPLATE, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_TEMPLATE, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.WANT_CURLY, "FUNCTION", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "GLOBAL", _rs.SEARCH, _pe.UNEXPECTED_MARKER), @@ -42,6 +50,8 @@ (_rs.WANT_CURLY, "SYNTHETIC", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "TEMPLATE", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.WANT_CURLY, "VTABLE", _rs.SEARCH, _pe.UNEXPECTED_MARKER), + (_rs.WANT_CURLY, "LIBRARY", _rs.SEARCH, _pe.UNEXPECTED_MARKER), + (_rs.WANT_CURLY, "STRING", _rs.SEARCH, _pe.UNEXPECTED_MARKER), (_rs.IN_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "GLOBAL", _rs.IN_GLOBAL, None), @@ -49,6 +59,8 @@ (_rs.IN_GLOBAL, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_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.IN_GLOBAL, None), (_rs.IN_FUNC_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), @@ -56,6 +68,8 @@ (_rs.IN_FUNC_GLOBAL, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_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.IN_FUNC_GLOBAL, None), (_rs.IN_VTABLE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -63,6 +77,26 @@ (_rs.IN_VTABLE, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "VTABLE", _rs.IN_VTABLE, None), + (_rs.IN_VTABLE, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_VTABLE, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + + (_rs.IN_SYNTHETIC, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "SYNTHETIC", _rs.IN_SYNTHETIC, None), + (_rs.IN_SYNTHETIC, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_SYNTHETIC, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + + (_rs.IN_LIBRARY, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "STUB", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "SYNTHETIC", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_LIBRARY, "LIBRARY", _rs.IN_LIBRARY, None), + (_rs.IN_LIBRARY, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), ] # fmt: on @@ -105,47 +139,3 @@ def test_state_search_line(line: str): p.read_line(line) assert p.state == _rs.SEARCH assert len(p.alerts) == 0 - - -global_lines = [ - ("// A comment", _rs.IN_GLOBAL), - ("", _rs.IN_GLOBAL), - ("\t", _rs.IN_GLOBAL), - (" ", _rs.IN_GLOBAL), - # TODO: no check for "likely" variable declaration so these all count - ("void function()", _rs.SEARCH), - ("int x = 123;", _rs.SEARCH), - ("just some text", _rs.SEARCH), -] - - -@pytest.mark.parametrize("line, new_state", global_lines) -def test_state_global_line(line: str, new_state: _rs): - p = DecompParser() - p.read_line("// GLOBAL: TEST 0x1234") - assert p.state == _rs.IN_GLOBAL - p.read_line(line) - assert p.state == new_state - - -# mostly same as above -in_func_global_lines = [ - ("// A comment", _rs.IN_FUNC_GLOBAL), - ("", _rs.IN_FUNC_GLOBAL), - ("\t", _rs.IN_FUNC_GLOBAL), - (" ", _rs.IN_FUNC_GLOBAL), - # TODO: no check for "likely" variable declaration so these all count - ("void function()", _rs.IN_FUNC), - ("int x = 123;", _rs.IN_FUNC), - ("just some text", _rs.IN_FUNC), -] - - -@pytest.mark.parametrize("line, new_state", in_func_global_lines) -def test_state_in_func_global_line(line: str, new_state: _rs): - p = DecompParser() - p.state = _rs.IN_FUNC - p.read_line("// GLOBAL: TEST 0x1234") - assert p.state == _rs.IN_FUNC_GLOBAL - p.read_line(line) - assert p.state == new_state diff --git a/tools/isledecomp/tests/test_parser_util.py b/tools/isledecomp/tests/test_parser_util.py index 643abf3e..8a403710 100644 --- a/tools/isledecomp/tests/test_parser_util.py +++ b/tools/isledecomp/tests/test_parser_util.py @@ -1,11 +1,16 @@ import pytest from isledecomp.parser.parser import MarkerDict -from isledecomp.parser.util import ( +from isledecomp.parser.marker import ( DecompMarker, - is_blank_or_comment, + MarkerType, match_marker, is_marker_exact, +) +from isledecomp.parser.util import ( + is_blank_or_comment, get_class_name, + get_variable_name, + get_string_contents, ) @@ -96,7 +101,7 @@ def test_marker_dict_type_replace(): d.insert(DecompMarker("STUB", "TEST", 0x1234)) markers = list(d.iter()) assert len(markers) == 1 - assert markers[0].type == "FUNCTION" + assert markers[0].type == MarkerType.FUNCTION class_name_match_cases = [ @@ -131,3 +136,41 @@ def test_get_class_name(line: str, class_name: str): @pytest.mark.parametrize("line", class_name_no_match_cases) def test_get_class_name_none(line: str): assert get_class_name(line) is None + + +variable_name_cases = [ + # with prefix for easy access + ("char* g_test;", "g_test"), + ("g_test;", "g_test"), + ("void (*g_test)(int);", "g_test"), + ("char g_test[50];", "g_test"), + ("char g_test[50] = {1234,", "g_test"), + ("int g_test = 500;", "g_test"), + # no prefix + ("char* hello;", "hello"), + ("hello;", "hello"), + ("void (*hello)(int);", "hello"), + ("char hello[50];", "hello"), + ("char hello[50] = {1234,", "hello"), + ("int hello = 500;", "hello"), +] + + +@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..be0da30f --- /dev/null +++ b/tools/isledecomp/tests/test_sanitize.py @@ -0,0 +1,213 @@ +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" + + +def test_float_replacement(): + """Floating point constants often appear as pointers to data. + A good example is ViewROI::IntrinsicImportance and the subclass override + LegoROI::IntrinsicImportance. Both return 0.5, but this is done via the + FLD instruction and a dword value at 0x100dbdec. In this case it is more + valuable to just read the constant value rather than use a placeholder. + The float constants don't appear to be deduplicated (like strings are) + because there is another 0.5 at 0x100d40b0.""" + + def substitute_float(addr: int, _: int) -> str: + return "zero-point-five" if addr == 0x1234 else None + + p = ParseAsm(float_lookup=substitute_float) + inst = DisasmLiteInst(0x1000, 6, "fld", "dword ptr [0x1234]") + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr [zero-point-five (FLOAT)]" + + +def test_float_variable(): + """If there is a variable at the address referenced by a float instruction, + use the name instead of calling into the float replacement handler.""" + + def name_lookup(addr: int) -> Optional[str]: + return "g_myFloatVariable" if addr == 0x1234 else None + + def substitute_float(_: int, __: int) -> str: + return "" + + p = ParseAsm(name_lookup=name_lookup, float_lookup=substitute_float) + inst = DisasmLiteInst(0x1000, 6, "fld", "dword ptr [0x1234]") + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr [g_myFloatVariable]" 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 75a186ca..f6d2de8e 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -2,12 +2,17 @@ configureLegoAnimationManager(MxS32): 'DLL exported function' configureLegoBuildingManager(MxS32): 'DLL exported function' configureLegoModelPresenter(MxS32): 'DLL exported function' configureLegoPartPresenter(MxS32, MxS32): 'DLL exported function' -configureLegoROI(MxS32): 'DLL exported function' +configureLegoROI(int): 'DLL exported function' configureLegoWorldPresenter(MxS32): 'DLL exported function' GetNoCD_SourceName(): 'DLL exported function' m_3dView: 'Allow this variable name' m_3dManager: 'Allow this variable name' m_16bitPal: 'Allow this variable name' +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 913154f5..69783cb2 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -2,169 +2,21 @@ import argparse import base64 -import difflib import json import logging import os -import re from isledecomp import ( Bin, - DecompParser, get_file_in_script_dir, - OffsetPlaceholderGenerator, print_diff, - SymInfo, - walk_source_dir, ) - -from capstone import Cs, CS_ARCH_X86, CS_MODE_32 -import colorama +from isledecomp.compare import Compare as IsleCompare +from isledecomp.types import SymbolType 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): @@ -199,9 +51,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.", @@ -228,6 +159,7 @@ def main(): "--verbose", "-v", metavar="", + type=virtual_address, help="Print assembly diff for specific function (original file's offset)", ) parser.add_argument( @@ -260,225 +192,104 @@ 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") - logger = logging.getLogger(__name__) - colorama.init() + 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) - 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, logger) as origfile, Bin(recomp, logger) as recompfile: - syminfo = SymInfo(syms, recompfile, logger, 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_address(args.verbose) + if match is None: + print(f"Failed to find a match at 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 = [] - # Generate basename of original file, used in locating OFFSET lines - basename = os.path.basename(os.path.splitext(original)[0]) - - parser = DecompParser() - for srcfilename in walk_source_dir(source): - parser.reset() - with open(srcfilename, "r", encoding="utf-8") as srcfile: - parser.read_lines(srcfile) - - for fun in parser.functions: - if fun.is_stub: - continue - - if fun.module != basename: - continue - - addr = fun.offset - # Verbose flag handling - if verbose: - if addr == verbose: - found_verbose_target = True - else: - continue - - if fun.lookup_by_name: - recinfo = syminfo.get_recompiled_address_from_name(fun.name) - if not recinfo: - continue - else: - recinfo = syminfo.get_recompiled_address( - srcfilename, fun.line_number - ) - if not recinfo: - continue - - # 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 recinfo.size: - origasm = parse_asm( - capstone_disassembler, - origfile, - addr + recinfo.start, - recinfo.size, - ) - recompasm = parse_asm( - capstone_disassembler, - recompfile, - recinfo.addr + recinfo.start, - recinfo.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{addr:x} / 0x{recinfo.addr:x}" - else: - addrs = hex(addr) - - if not verbose: - print( - f" {recinfo.name} ({addrs}) is {percenttext} similar to the original" - ) + for match in isle_compare.compare_all(): + print_match_oneline( + match, show_both_addrs=args.print_rec_addr, is_plain=args.no_color + ) + if match.match_type == SymbolType.FUNCTION: function_count += 1 - total_accuracy += ratio - total_effective_accuracy += effective_ratio + total_accuracy += match.ratio + total_effective_accuracy += match.effective_ratio - if recinfo.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}: {recinfo.name} 100% match.\n\n{ok_text}\n\n" - ) - else: - print( - f"{addrs}: {recinfo.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{recinfo.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{addr:x}", - "name": recinfo.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/tools/roadmap/roadmap.py b/tools/roadmap/roadmap.py new file mode 100644 index 00000000..97a4f894 --- /dev/null +++ b/tools/roadmap/roadmap.py @@ -0,0 +1,482 @@ +"""For all addresses matched by code annotations or recomp pdb, +report how "far off" the recomp symbol is from its proper place +in the original binary.""" + +import os +import argparse +import logging +import statistics +import bisect +from typing import Iterator, List, Optional, Tuple +from collections import namedtuple +from isledecomp import Bin as IsleBin +from isledecomp.cvdump import Cvdump +from isledecomp.compare import Compare as IsleCompare +from isledecomp.types import SymbolType + +# Ignore all compare-db messages. +logging.getLogger("isledecomp.compare").addHandler(logging.NullHandler()) + + +def or_blank(value) -> str: + """Helper for dealing with potential None values in text output.""" + return "" if value is None else str(value) + + +class ModuleMap: + """Load a subset of sections from the pdb to allow you to look up the + module number based on the recomp address.""" + + def __init__(self, pdb, binfile) -> None: + cvdump = Cvdump(pdb).section_contributions().modules().run() + self.module_lookup = {m.id: (m.lib, m.obj) for m in cvdump.modules} + self.library_lookup = {m.obj: m.lib for m in cvdump.modules} + self.section_contrib = [ + ( + binfile.get_abs_addr(sizeref.section, sizeref.offset), + sizeref.size, + sizeref.module, + ) + for sizeref in cvdump.sizerefs + if binfile.is_valid_section(sizeref.section) + ] + + # For bisect performance enhancement + self.contrib_starts = [start for (start, _, __) in self.section_contrib] + + def get_lib_for_module(self, module: str) -> Optional[str]: + return self.library_lookup.get(module) + + def get_all_cmake_modules(self) -> List[str]: + return [ + obj + for (_, (__, obj)) in self.module_lookup.items() + if obj.startswith("CMakeFiles") + ] + + def get_module(self, addr: int) -> Optional[str]: + i = bisect.bisect_left(self.contrib_starts, addr) + # If the addr matches the section contribution start, we are in the + # right spot. Otherwise, we need to subtract one here. + # We don't want the insertion point given by bisect, but the + # section contribution that contains the address. + + (potential_start, _, __) = self.section_contrib[i] + if potential_start != addr: + i -= 1 + + # Safety catch: clamp to range of indices from section_contrib. + i = max(0, min(i, len(self.section_contrib) - 1)) + + (start, size, module_id) = self.section_contrib[i] + if start <= addr < start + size: + if (module := self.module_lookup.get(module_id)) is not None: + return module + + return None + + +def print_sections(sections): + print(" name | start | v.size | raw size") + print("---------|----------|----------|----------") + for sect in sections: + name = sect.name.decode("ascii").rstrip("\x00") + print( + f"{name:>8} | {sect.virtual_address:8x} | {sect.virtual_size:8x} | {sect.size_of_raw_data:8x}" + ) + print() + + +ALLOWED_TYPE_ABBREVIATIONS = ["fun", "dat", "poi", "str", "vta"] + + +def match_type_abbreviation(mtype: Optional[SymbolType]) -> str: + """Return abbreviation of the given SymbolType name""" + if mtype is None: + return "" + + return mtype.name.lower()[:3] + + +def get_cmakefiles_prefix(module: str) -> str: + """For the given .obj, get the "CMakeFiles/something.dir/" prefix. + For lack of a better option, this is the library for this module.""" + if module.startswith("CMakeFiles"): + return "/".join(module.split("/", 2)[:2]) + "/" + + return module + + +def truncate_module_name(prefix: str, module: str) -> str: + """Remove the CMakeFiles prefix and the .obj suffix for the given module. + Input: CMakeFiles/lego1.dir/, CMakeFiles/lego1.dir/LEGO1/define.cpp.obj + Output: LEGO1/define.cpp""" + + if module.startswith(prefix): + module = module[len(prefix) :] + + if module.endswith(".obj"): + module = module[:-4] + + return module + + +def avg_remove_outliers(entries: List[int]) -> int: + """Compute the average from this list of entries (addresses) + after removing outlier values.""" + + if len(entries) == 1: + return entries[0] + + avg = statistics.mean(entries) + sd = statistics.pstdev(entries) + + return int(statistics.mean([e for e in entries if abs(e - avg) <= 2 * sd])) + + +RoadmapRow = namedtuple( + "RoadmapRow", + [ + "orig_sect_ofs", + "recomp_sect_ofs", + "orig_addr", + "recomp_addr", + "displacement", + "sym_type", + "size", + "name", + "module", + ], +) + + +class DeltaCollector: + """Reads each row of the results and aggregates information about the + placement of each module.""" + + def __init__(self, match_type: str = "fun") -> None: + # The displacement for each symbol from each module + self.disp_map = {} + + # Each address for each module + self.addresses = {} + + # The earliest address for each module + self.earliest = {} + + # String abbreviation for which symbol type we are checking + self.match_type = "fun" + + match_type = str(match_type).strip().lower()[:3] + if match_type in ALLOWED_TYPE_ABBREVIATIONS: + self.match_type = match_type + + def read_row(self, row: RoadmapRow): + if row.module is None: + return + + if row.sym_type != self.match_type: + return + + if row.orig_addr is not None: + if row.module not in self.addresses: + self.addresses[row.module] = [] + + self.addresses[row.module].append(row.orig_addr) + + if row.orig_addr < self.earliest.get(row.module, 0xFFFFFFFFF): + self.earliest[row.module] = row.orig_addr + + if row.displacement is not None: + if row.module not in self.disp_map: + self.disp_map[row.module] = [] + + self.disp_map[row.module].append(row.displacement) + + def iter_sorted(self) -> Iterator[Tuple[int, int]]: + """Compute the average address for each module, then generate them + in ascending order.""" + avg_address = { + mod: avg_remove_outliers(values) for mod, values in self.addresses.items() + } + for mod, avg in sorted(avg_address.items(), key=lambda x: x[1]): + yield (avg, mod) + + +def suggest_order(results: List[RoadmapRow], module_map: ModuleMap, match_type: str): + """Suggest the order of modules for CMakeLists.txt""" + + dc = DeltaCollector(match_type) + for row in results: + dc.read_row(row) + + # First, show the order of .obj files for the "CMake Modules" + # Meaning: the modules where the .obj file begins with "CMakeFiles". + # These are the libraries where we directly control the order. + # The library name (from cvdump) doesn't make it obvious that these are + # our libraries so we derive the name based on the CMakeFiles prefix. + leftover_modules = set(module_map.get_all_cmake_modules()) + + # A little convoluted, but we want to take the first two tokens + # of the string with '/' as the delimiter. + # i.e. CMakeFiles/isle.dir/ + # The idea is to print exactly what appears in CMakeLists.txt. + cmake_prefixes = sorted(set(get_cmakefiles_prefix(mod) for mod in leftover_modules)) + + # Save this off because we'll use it again later. + computed_order = list(dc.iter_sorted()) + + for prefix in cmake_prefixes: + print(prefix) + + last_earliest = 0 + # Show modules ordered by the computed average of addresses + for _, module in computed_order: + if not module.startswith(prefix): + continue + + leftover_modules.remove(module) + + avg_displacement = None + displacements = dc.disp_map.get(module) + if displacements is not None and len(displacements) > 0: + avg_displacement = int(statistics.mean(displacements)) + + # Call attention to any modules where ordering by earliest + # address is different from the computed order we display. + earliest = dc.earliest.get(module) + ooo_mark = "*" if earliest < last_earliest else " " + last_earliest = earliest + + code_file = truncate_module_name(prefix, module) + print(f"0x{earliest:08x}{ooo_mark} {avg_displacement:10} {code_file}") + + # These modules are included in the final binary (in some form) but + # don't contribute any symbols of the type we are checking. + # n.b. There could still be other modules that are part of + # CMakeLists.txt but are not included in the pdb for whatever reason. + # In other words: don't take the list we provide as the final word on + # what should or should not be included. + # This is merely a suggestion of the order. + for module in leftover_modules: + if not module.startswith(prefix): + continue + + # aligned with previous print + code_file = truncate_module_name(prefix, module) + print(f" no suggestion {code_file}") + + print() + + # Now display the order of all libaries in the final file. + library_order = {} + + for start, module in computed_order: + lib = module_map.get_lib_for_module(module) + if lib is None: + lib = get_cmakefiles_prefix(module) + + if start < library_order.get(lib, 0xFFFFFFFFF): + library_order[lib] = start + + print("Library order (average address shown):") + for lib, start in sorted(library_order.items(), key=lambda x: x[1]): + # Strip off any OS path for brevity + if not lib.startswith("CMakeFiles"): + lib = os.path.basename(lib) + + print(f"{lib:40} {start:08x}") + + +def print_text_report(results: List[RoadmapRow]): + """Print the result with original and recomp addresses.""" + for row in results: + print( + " ".join( + [ + f"{or_blank(row.orig_sect_ofs):14}", + f"{or_blank(row.recomp_sect_ofs):14}", + f"{or_blank(row.displacement):>8}", + f"{row.sym_type:3}", + f"{or_blank(row.size):6}", + or_blank(row.name), + ] + ) + ) + + +def print_diff_report(results: List[RoadmapRow]): + """Print only entries where we have the recomp address. + This is intended for generating a file to diff against. + The recomp addresses are always changing so we hide those.""" + for row in results: + if row.orig_addr is None or row.recomp_addr is None: + continue + + print( + " ".join( + [ + f"{or_blank(row.orig_sect_ofs):14}", + f"{or_blank(row.displacement):>8}", + f"{row.sym_type:3}", + f"{or_blank(row.size):6}", + or_blank(row.name), + ] + ) + ) + + +def export_to_csv(csv_file: str, results: List[RoadmapRow]): + with open(csv_file, "w+", encoding="utf-8") as f: + f.write( + "orig_sect_ofs,recomp_sect_ofs,orig_addr,recomp_addr,displacement,row_type,size,name,module\n" + ) + for row in results: + f.write(",".join(map(or_blank, row))) + f.write("\n") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Show all addresses from original and recomp." + ) + parser.add_argument( + "original", metavar="original-binary", help="The original binary" + ) + parser.add_argument( + "recompiled", metavar="recompiled-binary", help="The recompiled binary" + ) + parser.add_argument( + "pdb", metavar="recompiled-pdb", help="The PDB of the recompiled binary" + ) + parser.add_argument( + "decomp_dir", metavar="decomp-dir", help="The decompiled source tree" + ) + parser.add_argument("--csv", metavar="", help="If set, export to CSV") + parser.add_argument( + "--verbose", "-v", action="store_true", help="Show recomp addresses in output" + ) + parser.add_argument( + "--order", + const="fun", + nargs="?", + type=str, + help="Show suggested order of modules (using the specified symbol type)", + ) + + (args, _) = parser.parse_known_args() + + if not os.path.isfile(args.original): + parser.error(f"Original binary {args.original} does not exist") + + if not os.path.isfile(args.recompiled): + parser.error(f"Recompiled binary {args.recompiled} does not exist") + + if not os.path.isfile(args.pdb): + parser.error(f"Symbols PDB {args.pdb} does not exist") + + if not os.path.isdir(args.decomp_dir): + parser.error(f"Source directory {args.decomp_dir} does not exist") + + return args + + +def main(): + args = parse_args() + + with IsleBin(args.original, find_str=True) as orig_bin, IsleBin( + args.recompiled + ) as recomp_bin: + engine = IsleCompare(orig_bin, recomp_bin, args.pdb, args.decomp_dir) + + module_map = ModuleMap(args.pdb, recomp_bin) + + def is_same_section(orig: int, recomp: int) -> bool: + """Compare the section name instead of the index. + LEGO1.dll adds extra sections for some reason. (Smacker library?)""" + + try: + orig_name = orig_bin.sections[orig - 1].name + recomp_name = recomp_bin.sections[recomp - 1].name + return orig_name == recomp_name + except IndexError: + return False + + def to_roadmap_row(match): + orig_sect = None + orig_ofs = None + orig_sect_ofs = None + recomp_sect = None + recomp_ofs = None + recomp_sect_ofs = None + orig_addr = None + recomp_addr = None + displacement = None + module_name = None + + if match.recomp_addr is not None: + if (module_ref := module_map.get_module(match.recomp_addr)) is not None: + (_, module_name) = module_ref + + row_type = match_type_abbreviation(match.compare_type) + name = ( + repr(match.name) + if match.compare_type == SymbolType.STRING + else match.name + ) + + if match.orig_addr is not None: + orig_addr = match.orig_addr + (orig_sect, orig_ofs) = orig_bin.get_relative_addr(match.orig_addr) + orig_sect_ofs = f"{orig_sect:04}:{orig_ofs:08x}" + + if match.recomp_addr is not None: + recomp_addr = match.recomp_addr + (recomp_sect, recomp_ofs) = recomp_bin.get_relative_addr( + match.recomp_addr + ) + recomp_sect_ofs = f"{recomp_sect:04}:{recomp_ofs:08x}" + + if ( + orig_sect is not None + and recomp_sect is not None + and is_same_section(orig_sect, recomp_sect) + ): + displacement = recomp_ofs - orig_ofs + + return RoadmapRow( + orig_sect_ofs, + recomp_sect_ofs, + orig_addr, + recomp_addr, + displacement, + row_type, + match.size, + name, + module_name, + ) + + results = list(map(to_roadmap_row, engine.get_all())) + + if args.order is not None: + suggest_order(results, module_map, args.order) + return + + if args.csv is None: + if args.verbose: + print("ORIG sections:") + print_sections(orig_bin.sections) + + print("RECOMP sections:") + print_sections(recomp_bin.sections) + + print_text_report(results) + else: + print_diff_report(results) + + if args.csv is not None: + export_to_csv(args.csv, results) + + +if __name__ == "__main__": + main() diff --git a/tools/vtable/vtable.py b/tools/vtable/vtable.py new file mode 100644 index 00000000..bdee080b --- /dev/null +++ b/tools/vtable/vtable.py @@ -0,0 +1,99 @@ +import os +import argparse +import logging +from typing import List +import colorama +from isledecomp.bin import Bin as IsleBin +from isledecomp.compare import Compare as IsleCompare +from isledecomp.utils import print_diff + +# Ignore all compare-db messages. +logging.getLogger("isledecomp.compare").addHandler(logging.NullHandler()) + +colorama.init() + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Comparing vtables.") + parser.add_argument( + "original", metavar="original-binary", help="The original binary" + ) + parser.add_argument( + "recompiled", metavar="recompiled-binary", help="The recompiled binary" + ) + parser.add_argument( + "pdb", metavar="recompiled-pdb", help="The PDB of the recompiled binary" + ) + parser.add_argument( + "decomp_dir", metavar="decomp-dir", help="The decompiled source tree" + ) + parser.add_argument( + "--verbose", "-v", action="store_true", help="Show more detailed information" + ) + parser.add_argument( + "--no-color", "-n", action="store_true", help="Do not color the output" + ) + + (args, _) = parser.parse_known_args() + + if not os.path.isfile(args.original): + parser.error(f"Original binary {args.original} does not exist") + + if not os.path.isfile(args.recompiled): + parser.error(f"Recompiled binary {args.recompiled} does not exist") + + if not os.path.isfile(args.pdb): + parser.error(f"Symbols PDB {args.pdb} does not exist") + + if not os.path.isdir(args.decomp_dir): + parser.error(f"Source directory {args.decomp_dir} does not exist") + + return args + + +def show_vtable_diff(udiff: List[str], verbose: bool = False, plain: bool = False): + lines = [ + line + for line in udiff + if verbose or line.startswith("+") or line.startswith("-") + ] + print_diff(lines, plain) + + +def print_summary(vtable_count: int, problem_count: int): + if problem_count == 0: + print(f"Vtables found: {vtable_count}.\n100% match.") + return + + print(f"Vtables found: {vtable_count}.\nVtables not matching: {problem_count}.") + + +def main(): + args = parse_args() + vtable_count = 0 + problem_count = 0 + + with IsleBin(args.original) as orig_bin, IsleBin(args.recompiled) as recomp_bin: + engine = IsleCompare(orig_bin, recomp_bin, args.pdb, args.decomp_dir) + + for tbl_match in engine.compare_vtables(): + vtable_count += 1 + if tbl_match.ratio < 1: + problem_count += 1 + + udiff = list(tbl_match.udiff) + + print( + tbl_match.name, + f": orig 0x{tbl_match.orig_addr:x}, recomp 0x{tbl_match.recomp_addr:x}", + ) + show_vtable_diff(udiff, args.verbose, args.no_color) + print() + + print_summary(vtable_count, problem_count) + + return 1 if problem_count > 0 else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/util/compat.h b/util/compat.h index c1175cd2..ea2a6507 100644 --- a/util/compat.h +++ b/util/compat.h @@ -3,12 +3,8 @@ // Various macros to enable compiling with other/newer compilers. -// 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__ -#define COMPAT_CONST const -#else -#define COMPAT_CONST +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1100) +#define COMPAT_MODE #endif // Disable "identifier was truncated to '255' characters" warning. @@ -21,8 +17,9 @@ // We use `override` so newer compilers can tell us our vtables are valid, // however this keyword was added in C++11, so we define it as empty for // compatibility with older compilers. -#if defined(_MSC_VER) && _MSC_VER <= 1200 // 1200 corresponds to VC6.0 but "override" was probably added even later +#if __cplusplus < 201103L #define override +#define static_assert(expr, msg) #endif #endif // COMPAT_H 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 \ { \