diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml index e139b8bf..01b85f47 100644 --- a/.github/workflows/analyze.yml +++ b/.github/workflows/analyze.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: decomplint-isle: + name: 'ISLE annotations' runs-on: ubuntu-latest steps: @@ -18,6 +19,7 @@ jobs: python3 tools/decomplint/decomplint.py ISLE --module ISLE --warnfail decomplint-lego1: + name: 'LEGO1 annotations' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2c285836..419033cc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,7 +3,53 @@ name: Build on: [push, pull_request] jobs: + build-current-toolchain: + name: 'Current ${{ matrix.toolchain.name }}' + runs-on: windows-latest + defaults: + run: + shell: ${{ matrix.toolchain.shell }} + strategy: + fail-fast: false + matrix: + toolchain: + - { name: 'MSVC', shell: 'sh', setup-cmake: true, setup-ninja: true, setup-msvc: true } + - { name: 'msys2 mingw32', shell: 'msys2 {0}', setup-msys2: true } + + steps: + - name: Set up MSYS2 + if: matrix.toolchain.setup-msys2 + uses: msys2/setup-msys2@v2 + with: + msystem: mingw32 + install: >- + mingw-w64-i686-cc + mingw-w64-i686-cmake + mingw-w64-i686-ninja + + - name: Setup cmake + if: matrix.toolchain.setup-cmake + uses: jwlawson/actions-setup-cmake@v1.13 + + - name: Setup ninja + if: matrix.toolchain.setup-ninja + uses: ashutoshvarma/setup-ninja@master + + - name: Setup vcvars + if: matrix.toolchain.setup-msvc + uses: ilammy/msvc-dev-cmd@v1 + with: + arch: amd64_x86 # Use the 64-bit x64-native cross tools to build 32-bit x86 code + + - uses: actions/checkout@v3 + + - name: Build + run: | + cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -GNinja -Werror=dev + cmake --build build + build: + name: 'MSVC 4.20' runs-on: windows-latest steps: @@ -28,10 +74,8 @@ jobs: shell: cmd run: | call .\msvc420\bin\VCVARS32.BAT x86 - mkdir build - cd build - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "NMake Makefiles" - cmake --build . + cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "NMake Makefiles" + cmake --build build - name: Upload Artifact uses: actions/upload-artifact@master @@ -44,6 +88,7 @@ jobs: build/LEGO1.PDB compare: + name: 'Compare with master' needs: build runs-on: windows-latest steps: @@ -109,6 +154,7 @@ jobs: LEGO1PROGRESS.* upload: + name: 'Upload artifacts' needs: [build, compare] runs-on: ubuntu-latest if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'isledecomp/isle' }} diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 07b646fb..ccec2b50 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: clang-format: + name: 'C++' runs-on: ubuntu-latest steps: @@ -19,6 +20,7 @@ jobs: -i python-format: + name: 'Python' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/naming.yml b/.github/workflows/naming.yml index 163354d5..a23275e1 100644 --- a/.github/workflows/naming.yml +++ b/.github/workflows/naming.yml @@ -4,6 +4,7 @@ on: [push, pull_request] jobs: ncc: + name: 'C++' runs-on: ubuntu-latest steps: diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index 06446888..612ae3ae 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -1,9 +1,10 @@ -name: Unit Tests +name: Test on: [push, pull_request] jobs: pytest-win: + name: 'Python Windows' runs-on: windows-latest steps: @@ -20,6 +21,7 @@ jobs: pytest tools/isledecomp pytest-ubuntu: + name: 'Python Linux' runs-on: ubuntu-latest steps: diff --git a/3rdparty/flic/flic.asm b/3rdparty/flic/flic.asm new file mode 100644 index 00000000..44f42086 --- /dev/null +++ b/3rdparty/flic/flic.asm @@ -0,0 +1,851 @@ +.486 +.387 +option dotname +.model flat, c +assume fs:nothing + +public DecodeFLCFrame + +; This is so reccmp can detect the end of DecodeFLCFrame +public EndOfSection + +.text SEGMENT BYTE PUBLIC 'CODE' + +?_25162 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 + +?_25164 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 ?_25168 ; 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 + +?_25168 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 + +?_25173 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 ?_25168 ; 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 + +?_25176 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 ?_25168 ; 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 + +?_25180 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 ?_25194 ; 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 ?_25220 ; 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 ?_25202 ; 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 ?_25213 ; 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 ?_25227 ; 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 ?_25203 ; 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 ?_25231 ; 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 _ ........ + +?_25194 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 ?_25195 ; 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 + +?_25195 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 ?_25199 ; 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 + +?_25199 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 + +?_25202 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 ?_25195 ; 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 + +?_25203 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 + +?_25213 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 ?_25173 ; 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 ?_25164 ; 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 + +?_25220 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 ?_25162 ; 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 ?_25164 ; 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 ?_25176 ; 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 + +?_25227 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 ?_25176 ; 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 ?_25162 ; 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 + +?_25231 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 ?_25164 ; 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 ?_25180 ; 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 42969e5c..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; +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..fea46a25 Binary files /dev/null and b/3rdparty/flic/flic.lib differ diff --git a/CMakeLists.txt b/CMakeLists.txt index 483ba9db..34b67e0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,8 +2,24 @@ cmake_minimum_required(VERSION 3.13 FATAL_ERROR) project(isle CXX) +math(EXPR bits "8 * ${CMAKE_SIZEOF_VOID_P}") +message(STATUS "Building ${bits}-bit LEGO Island") +if (NOT bits EQUAL 32) + message(WARNING "Only 32-bit executables are supported") +endif() + +set(MSVC_FOR_DECOMP FALSE) +if (MSVC) + # Visual C++ 4.2 -> cl version 10.2.0 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "11.0") + set(MSVC_FOR_DECOMP TRUE) + endif() +endif() + +message(STATUS "MSVC for decompilation: ${MSVC_FOR_DECOMP}") + option(ISLE_BUILD_APP "Build ISLE.EXE application" ON) -option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC}) +option(ISLE_USE_SMARTHEAP "Build with SmartHeap" ${MSVC_FOR_DECOMP}) option(ISLE_USE_DX5 "Build with internal DirectX 5 SDK" ON) add_library(lego1 SHARED @@ -42,7 +58,9 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/common/legoutil.cpp LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp + LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp LEGO1/lego/legoomni/src/entity/legoactor.cpp + LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp LEGO1/lego/legoomni/src/entity/legoanimactor.cpp LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -81,7 +99,7 @@ add_library(lego1 SHARED LEGO1/lego/legoomni/src/isle/jukebox.cpp LEGO1/lego/legoomni/src/isle/jukeboxentity.cpp LEGO1/lego/legoomni/src/isle/jukeboxstate.cpp - LEGO1/lego/legoomni/src/isle/motorcycle.cpp + LEGO1/lego/legoomni/src/isle/motocycle.cpp LEGO1/lego/legoomni/src/isle/radio.cpp LEGO1/lego/legoomni/src/isle/radiostate.cpp LEGO1/lego/legoomni/src/isle/skateboard.cpp @@ -123,8 +141,11 @@ add_library(lego1 SHARED LEGO1/lego/sources/3dmanager/legoview1.cpp LEGO1/lego/sources/3dmanager/tglsurface.cpp LEGO1/lego/sources/roi/legoroi.cpp + LEGO1/main.cpp LEGO1/mxdirectx/mxdirect3d.cpp LEGO1/mxdirectx/mxdirectdraw.cpp + LEGO1/mxgeometry/mxgeometry3d.cpp + LEGO1/mxgeometry/mxmatrix.cpp LEGO1/omni/src/action/mxdsaction.cpp LEGO1/omni/src/action/mxdsanim.cpp LEGO1/omni/src/action/mxdsevent.cpp @@ -161,11 +182,9 @@ add_library(lego1 SHARED LEGO1/omni/src/common/mxutil.cpp LEGO1/omni/src/common/mxvariable.cpp LEGO1/omni/src/common/mxvariabletable.cpp - LEGO1/omni/src/control/mxcontrolpresenter.cpp LEGO1/omni/src/entity/mxentity.cpp LEGO1/omni/src/event/mxeventmanager.cpp LEGO1/omni/src/event/mxeventpresenter.cpp - LEGO1/omni/src/main/mxmain.cpp LEGO1/omni/src/main/mxomni.cpp LEGO1/omni/src/main/mxomnicreateflags.cpp LEGO1/omni/src/main/mxomnicreateparam.cpp @@ -259,9 +278,10 @@ if (ISLE_USE_DX5) endif() target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/smacker") +target_link_directories(lego1 PRIVATE "${CMAKE_SOURCE_DIR}/3rdparty/flic") # Link libraries -target_link_libraries(lego1 PRIVATE ddraw dsound dinput dxguid winmm d3drm smack) +target_link_libraries(lego1 PRIVATE ddraw dsound dinput dxguid winmm d3drm smack flic) # Make sure filenames are ALL CAPS set_property(TARGET lego1 PROPERTY OUTPUT_NAME LEGO1) @@ -275,6 +295,8 @@ if (ISLE_BUILD_APP) ISLE/define.cpp ) + target_compile_definitions(isle PRIVATE ISLE_APP) + target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/util") target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1") target_include_directories(isle PRIVATE "${CMAKE_SOURCE_DIR}/LEGO1/omni/include") @@ -300,6 +322,29 @@ if (ISLE_BUILD_APP) endif() if (MSVC) + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "15") + target_compile_definitions(lego1 PRIVATE _CRT_SECURE_NO_WARNINGS) + if (ISLE_BUILD_APP) + target_compile_definitions(isle PRIVATE "_CRT_SECURE_NO_WARNINGS") + endif() + endif() + # Visual Studio 2017 version 15.7 needs "/Zc:__cplusplus" for __cplusplus + if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.14.26428") + target_compile_options(lego1 PRIVATE "-Zc:__cplusplus") + if (ISLE_BUILD_APP) + target_compile_options(isle PRIVATE "-Zc:__cplusplus") + endif() + endif() +endif() + +if (MSVC_FOR_DECOMP) + target_compile_definitions(lego1 PRIVATE "ENABLE_DECOMP_ASSERTS") + if (ISLE_BUILD_APP) + target_compile_definitions(isle PRIVATE "ENABLE_DECOMP_ASSERTS") + endif() +endif() + +if (MSVC_FOR_DECOMP) # These flags have been taken from the defaults for a Visual C++ 4.20 project (the compiler the # game was originally built with) and tweaked slightly to produce more debugging info for reccmp. # They ensure a recompilation that can be byte/instruction accurate to the original binaries. diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index d6f9c293..4a2a840b 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -614,8 +614,8 @@ MxResult IsleApp::SetupWindow(HINSTANCE hInstance, LPSTR lpCmdLine) LegoAnimationManager::configureLegoAnimationManager(m_islandQuality); if (LegoOmni::GetInstance()) { if (LegoOmni::GetInstance()->GetInputManager()) { - LegoOmni::GetInstance()->GetInputManager()->m_useJoystick = m_useJoystick; - LegoOmni::GetInstance()->GetInputManager()->m_joystickIndex = m_joystickIndex; + LegoOmni::GetInstance()->GetInputManager()->SetUseJoystick(m_useJoystick); + LegoOmni::GetInstance()->GetInputManager()->SetJoystickIndex(m_joystickIndex); } } if (m_fullScreen) { @@ -792,11 +792,11 @@ inline void IsleApp::Tick(BOOL sleepIfNotNextFrame) LegoOmni::GetInstance()->CreateBackgroundAudio(); BackgroundAudioManager()->Enable(this->m_useMusic); - MxStreamController* stream = Streamer()->Open("\\lego\\scripts\\isle\\isle", MxStreamer::e_DiskStream); + MxStreamController* stream = Streamer()->Open("\\lego\\scripts\\isle\\isle", MxStreamer::e_diskStream); MxDSAction ds; if (!stream) { - stream = Streamer()->Open("\\lego\\scripts\\nocd", MxStreamer::e_DiskStream); + stream = Streamer()->Open("\\lego\\scripts\\nocd", MxStreamer::e_diskStream); if (!stream) { return; } diff --git a/ISLE/library_msvc.h b/ISLE/library_msvc.h new file mode 100644 index 00000000..a837fd3b --- /dev/null +++ b/ISLE/library_msvc.h @@ -0,0 +1,63 @@ +#ifdef 0 +// For ISLE symbols only + +// aka `operator new` +// LIBRARY: ISLE 0x402f80 +// ??2@YAPAXI@Z + +// aka `operator delete` +// LIBRARY: ISLE 0x402fa0 +// ??3@YAXPAX@Z + +// LIBRARY: ISLE 0x406dd0 +// _malloc + +// LIBRARY: ISLE 0x406f00 +// _free + +// LIBRARY: ISLE 0x407ec0 +// ___CxxFrameHandler + +// LIBRARY: ISLE 0x4081e0 +// _srand + +// LIBRARY: ISLE 0x4081f0 +// _rand + +// LIBRARY: ISLE 0x408220 +// _atol + +// LIBRARY: ISLE 0x4082d0 +// _atoi + +// LIBRARY: ISLE 0x4084c0 +// ?_query_new_handler@@YAP6AHI@ZXZ + +// LIBRARY: ISLE 0x4084d0 +// ?_query_new_mode@@YAHXZ + +// LIBRARY: ISLE 0x4085c0 +// _sprintf + +// LIBRARY: ISLE 0x408630 +// _abort + +// LIBRARY: ISLE 0x409110 +// __mtinit + +// LIBRARY: ISLE 0x409190 +// __getptd + +// GLOBAL: ISLE 0x4108e8 +// __osver + +// GLOBAL: ISLE 0x4108f0 +// __winmajor + +// GLOBAL: ISLE 0x4108f4 +// __winminor + +// GLOBAL: ISLE 0x410d50 +// __newmode + +#endif diff --git a/ISLE/library_smartheap.h b/ISLE/library_smartheap.h new file mode 100644 index 00000000..53ef5f0d --- /dev/null +++ b/ISLE/library_smartheap.h @@ -0,0 +1,312 @@ +#ifdef 0 + +// LIBRARY: ISLE 0x402f10 +// ?shi_New@@YAPAXKIPAU_SHI_Pool@@@Z + +// LIBRARY: ISLE 0x402fb0 +// _MemInitDefaultPool@0 + +// LIBRARY: ISLE 0x403020 +// _shi_call_new_handler_msc + +// LIBRARY: ISLE 0x403050 +// _MemPoolShrink@4 + +// LIBRARY: ISLE 0x403180 +// _MemPoolPreAllocate@12 + +// LIBRARY: ISLE 0x403300 +// @_shi_initPageHeaders@4 + +// LIBRARY: ISLE 0x403570 +// @shi_allocPageHeader@4 + +// LIBRARY: ISLE 0x4035a0 +// @shi_freePageHeader@8 + +// LIBRARY: ISLE 0x403750 +// @_shi_deletePage@8 + +// LIBRARY: ISLE 0x403830 +// @_shi_allocExternal@12 + +// LIBRARY: ISLE 0x403a50 +// @_shi_initPageVariable@8 + +// LIBRARY: ISLE 0x403b00 +// _MemAllocPtr@12 + +// LIBRARY: ISLE 0x403d60 +// @_shi_allocVar@12 + +// LIBRARY: ISLE 0x403ef0 +// @_shi_allocBlock@12 + +// LIBRARY: ISLE 0x4040c0 +// _MemFreePtr@4 + +// LIBRARY: ISLE 0x404170 +// @_shi_freeVar@4 + +// LIBRARY: ISLE 0x404260 +// _MemReAllocPtr@12 + +// LIBRARY: ISLE 0x4043b0 +// @_shi_resizeAny@16 + +// LIBRARY: ISLE 0x404650 +// @_shi_resizeVar@8 + +// LIBRARY: ISLE 0x404820 +// _MemSizePtr@4 + +// LIBRARY: ISLE 0x4048d0 +// @shi_findAllocAddress@4 + +// LIBRARY: ISLE 0x404910 +// @_shi_sysAlloc@8 + +// LIBRARY: ISLE 0x4049a0 +// @_shi_sysFree@4 + +// LIBRARY: ISLE 0x404a00 +// @_shi_sysRealloc@12 + +// LIBRARY: ISLE 0x404ab0 +// @_shi_sysResize@12 + +// LIBRARY: ISLE 0x404b90 +// @_shi_sysSize@4 + +// LIBRARY: ISLE 0x404bd0 +// @_shi_sysAllocNear@4 + +// LIBRARY: ISLE 0x404bf0 +// @_shi_sysFreeNear@4 + +// LIBRARY: ISLE 0x404c10 +// @_shi_sysValidatePtr@12 + +// LIBRARY: ISLE 0x404d10 +// @_shi_sysValidateFunction@4 + +// LIBRARY: ISLE 0x405300 +// @_shi_sysAllocPool@12 + +// LIBRARY: ISLE 0x405520 +// @_shi_sysResizePool@16 + +// LIBRARY: ISLE 0x405690 +// @_shi_sysFreePage@4 + +// LIBRARY: ISLE 0x4057b0 +// @_shi_sysSizePage@4 + +// LIBRARY: ISLE 0x4057e0 +// @_shi_sysSizePool@8 + +// LIBRARY: ISLE 0x405800 +// @_shi_registerShared@16 + +// LIBRARY: ISLE 0x405a00 +// @_shi_unregisterShared@8 + +// LIBRARY: ISLE 0x405b20 +// @_shi_getNextPool@4 + +// LIBRARY: ISLE 0x405b30 +// @shi_delNextPool@4 + +// LIBRARY: ISLE 0x405d30 +// @shi_createAndEnterMutexShr@12 + +// LIBRARY: ISLE 0x405e20 +// @shi_termPoolMutexShr@4 + +// LIBRARY: ISLE 0x405e40 +// @shi_enterPoolMutexShr@4 + +// LIBRARY: ISLE 0x405e60 +// @shi_leavePoolMutexShr@4 + +// LIBRARY: ISLE 0x405e80 +// __shi_enterCriticalSection@0 + +// LIBRARY: ISLE 0x405ea0 +// __shi_leaveCriticalSection@0 + +// LIBRARY: ISLE 0x405ec0 +// __shi_createAndEnterMutex + +// LIBRARY: ISLE 0x405ef0 +// _shi_enterPoolMutexSafely + +// LIBRARY: ISLE 0x405fd0 +// _shi_enterPoolInitMutexReader + +// LIBRARY: ISLE 0x406060 +// _shi_leavePoolInitMutexReader + +// LIBRARY: ISLE 0x406090 +// _shi_enterPoolInitMutexWriter + +// LIBRARY: ISLE 0x406160 +// _shi_leavePoolInitMutexWriter + +// LIBRARY: ISLE 0x406180 +// _shi_isNT + +// LIBRARY: ISLE 0x4061b0 +// _MemPoolInit@4 + +// LIBRARY: ISLE 0x406520 +// _MemPoolSetPageSize@8 + +// LIBRARY: ISLE 0x406630 +// _MemPoolSetBlockSizeFS@8 + +// LIBRARY: ISLE 0x406710 +// @_shi_poolFree@8 + +// LIBRARY: ISLE 0x4068c0 +// @_shi_invokeErrorHandler1@8 + +// LIBRARY: ISLE 0x406be0 +// _MemErrorUnwind@0 + +// LIBRARY: ISLE 0x406c30 +// _MemDefaultErrorHandler@4 + +// LIBRARY: ISLE 0x406cb0 +// @_shi_taskRemovePool@4 + +// LIBRARY: ISLE 0x406d50 +// @_shi_getCurrentThreadContext@8 + +// LIBRARY: ISLE 0x406db0 +// @_shi_deleteThreadContext@8 + +// LIBRARY: ISLE 0x406e40 +// _calloc + +// LIBRARY: ISLE 0x406ea0 +// _realloc + +// LIBRARY: ISLE 0x406f10 +// __expand + +// LIBRARY: ISLE 0x406f50 +// __heapadd + +// LIBRARY: ISLE 0x406f60 +// __heapwalk + +// LIBRARY: ISLE 0x406ff0 +// __heapused + +// LIBRARY: ISLE 0x407020 +// __heapmin + +// LIBRARY: ISLE 0x407040 +// __msize + +// LIBRARY: ISLE 0x407050 +// __heapchk + +// LIBRARY: ISLE 0x407080 +// __heapset + +// LIBRARY: ISLE 0x407090 +// @_shi_sysReportError@16 + +// LIBRARY: ISLE 0x407110 +// _MemPoolSize@4 + +// LIBRARY: ISLE 0x4071a0 +// _MemPoolWalk@8 + +// LIBRARY: ISLE 0x407240 +// @_shi_walkPool@16 + +// LIBRARY: ISLE 0x407540 +// @shi_isBlockInUseSmall@8 + +// LIBRARY: ISLE 0x407800 +// @_shi_isBlockInUseFS@12 + +// LIBRARY: ISLE 0x407880 +// _MemPoolCheck@4 + +// LIBRARY: ISLE 0x407b20 +// _MemCheckPtr@8 + +// LIBRARY: ISLE 0x4084e0 +// __except_handler3 + +// GLOBAL: ISLE 0x40f0a0 +// _szLibName + +// GLOBAL: ISLE 0x4102f4 +// ?_new_handler@@3P6AXXZA + +// GLOBAL: ISLE 0x4102fc +// _MemDefaultPool + +// GLOBAL: ISLE 0x41031c +// __shi_compactPoolFn + +// GLOBAL: ISLE 0x410320 +// __shi_compactPageFn + +// GLOBAL: ISLE 0x410324 +// _MemDefaultPoolFlags + +// GLOBAL: ISLE 0x41032c +// __shi_mutexGlobalInit + +// GLOBAL: ISLE 0x410330 +// __shi_mutexMovInit + +// GLOBAL: ISLE 0x410334 +// __shi_mutexMovLockCount + +// GLOBAL: ISLE 0x410338 +// _shi_initPoolReaders + +// GLOBAL: ISLE 0x41033c +// _shi_eventInitPool + +// GLOBAL: ISLE 0x410340 +// _shi_mutexMovShr + +// GLOBAL: ISLE 0x410368 +// _shi_deferFreePools + +// GLOBAL: ISLE 0x410378 +// __shi_poolTerminating + +// GLOBAL: ISLE 0x41037c +// _MemDefaultPoolBlockSizeFS + +// GLOBAL: ISLE 0x410380 +// _MemDefaultPoolPageSize + +// GLOBAL: ISLE 0x410384 +// _SmartHeap_malloc + +// GLOBAL: ISLE 0x4105b0 +// __shi_TaskRecord + +// GLOBAL: ISLE 0x4125f8 +// ?_pnhHeap@@3P6AHI@ZA + +// GLOBAL: ISLE 0x412830 +// __shi_mutexMov + +// GLOBAL: ISLE 0x412850 +// _shi_mutexPoolSynch + +// GLOBAL: ISLE 0x412870 +// __shi_mutexGlobal + +#endif diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 3f3f70ac..1e403a50 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -10,20 +10,26 @@ MxS32 g_mxcoreCount[101] = {0, -6643, -5643, -5058, -4643, -4321, -4058, -38 -358, -340, -321, -304, -286, -268, -251, -234, -217, -200, -184, -168, -152, -136, -120, -104, -89, -74, -58, -43, -29, -14, 0}; -// GLOBAL: LEGO1 0x10101eac -const char* g_parseExtraTokens = ":;"; - -// GLOBAL: LEGO1 0x10101edc -const char* g_strWORLD = "WORLD"; - -// GLOBAL: LEGO1 0x10101f20 -const char* g_strSOUND = "SOUND"; - -// GLOBAL: LEGO1 0x10101f58 -const char* g_strOBJECT = "OBJECT"; - -// GLOBAL: LEGO1 0x10102040 +// GLOBAL: LEGO1 0x10102048 +// STRING: LEGO1 0x10102040 const char* g_strACTION = "ACTION"; +// GLOBAL: LEGO1 0x1010209c +// STRING: LEGO1 0x10101f58 +const char* g_strOBJECT = "OBJECT"; + +// GLOBAL: LEGO1 0x101020b0 +// STRING: LEGO1 0x10101f20 +const char* g_strSOUND = "SOUND"; + // GLOBAL: LEGO1 0x101020cc +// STRING: LEGO1 0x100f3808 const char* g_strVISIBILITY = "VISIBILITY"; + +// GLOBAL: LEGO1 0x101020d0 +// STRING: LEGO1 0x10101edc +const char* g_strWORLD = "WORLD"; + +// GLOBAL: LEGO1 0x101020e4 +// STRING: LEGO1 0x10101eac +const char* g_parseExtraTokens = ":;"; diff --git a/LEGO1/lego/legoomni/include/act1state.h b/LEGO1/lego/legoomni/include/act1state.h index d0daec7d..82e95f63 100644 --- a/LEGO1/lego/legoomni/include/act1state.h +++ b/LEGO1/lego/legoomni/include/act1state.h @@ -24,10 +24,24 @@ class Act1State : public LegoState { inline void SetUnknown18(MxU32 p_unk0x18) { m_unk0x18 = p_unk0x18; } inline MxU32 GetUnknown18() { return m_unk0x18; } + inline void SetUnknown21(MxS16 p_unk0x21) { m_unk0x21 = p_unk0x21; } + inline MxS16 GetUnknown21() { return m_unk0x21; } + + void FUN_10034d00(); + + // SYNTHETIC: LEGO1 0x10033960 + // Act1State::`scalar deleting destructor' protected: undefined m_unk0x8[0x10]; // 0x8 MxU32 m_unk0x18; // 0x18 + undefined2 m_unk0x1c; // 0x1c + undefined m_unk0x1e; // 0x1e + undefined m_unk0x1f; // 0x1f + undefined m_unk0x20; // 0x20 + MxBool m_unk0x21; // 0x21 + undefined m_unk0x22; // 0x22 + // TODO }; #endif // ACT1STATE_H diff --git a/LEGO1/lego/legoomni/include/act2brick.h b/LEGO1/lego/legoomni/include/act2brick.h index 10665c40..5eb697ed 100644 --- a/LEGO1/lego/legoomni/include/act2brick.h +++ b/LEGO1/lego/legoomni/include/act2brick.h @@ -25,6 +25,9 @@ class Act2Brick : public LegoPathActor { { return !strcmp(p_name, Act2Brick::ClassName()) || LegoEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1007a450 + // Act2Brick::`scalar deleting destructor' }; #endif // ACT2BRICK_H diff --git a/LEGO1/lego/legoomni/include/act2policestation.h b/LEGO1/lego/legoomni/include/act2policestation.h index 887ab542..4746236f 100644 --- a/LEGO1/lego/legoomni/include/act2policestation.h +++ b/LEGO1/lego/legoomni/include/act2policestation.h @@ -21,6 +21,9 @@ class Act2PoliceStation : public LegoEntity { { 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 index 76c9722b..053bde82 100644 --- a/LEGO1/lego/legoomni/include/act3.h +++ b/LEGO1/lego/legoomni/include/act3.h @@ -27,6 +27,9 @@ class Act3 : public LegoWorld { 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' + protected: undefined m_unk0xf8[0x4114]; // 0xf8 MxEntity* m_unk0x420c; // 0x420c diff --git a/LEGO1/lego/legoomni/include/act3shark.h b/LEGO1/lego/legoomni/include/act3shark.h index 611cbc38..e6910cdb 100644 --- a/LEGO1/lego/legoomni/include/act3shark.h +++ b/LEGO1/lego/legoomni/include/act3shark.h @@ -12,6 +12,9 @@ class Act3Shark : public LegoAnimActor { // STRING: LEGO1 0x100f03a0 return "Act3Shark"; } + + // SYNTHETIC: LEGO1 0x10043020 + // Act3Shark::`scalar deleting destructor' }; #endif // ACT3SHARK_H diff --git a/LEGO1/lego/legoomni/include/act3state.h b/LEGO1/lego/legoomni/include/act3state.h index dca6c3ea..c88c4620 100644 --- a/LEGO1/lego/legoomni/include/act3state.h +++ b/LEGO1/lego/legoomni/include/act3state.h @@ -24,6 +24,9 @@ class Act3State : public LegoState { virtual MxBool VTable0x14() override; + // SYNTHETIC: LEGO1 0x1000e3c0 + // Act3State::`scalar deleting destructor' + private: // FIXME: May be part of LegoState? Uncertain... MxU32 m_unk0x08; diff --git a/LEGO1/lego/legoomni/include/ambulance.h b/LEGO1/lego/legoomni/include/ambulance.h index 3bc80212..7c54561a 100644 --- a/LEGO1/lego/legoomni/include/ambulance.h +++ b/LEGO1/lego/legoomni/include/ambulance.h @@ -22,6 +22,9 @@ class Ambulance : public IslePathActor { return !strcmp(p_name, Ambulance::ClassName()) || IslePathActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x10036130 + // Ambulance::`scalar deleting destructor' + private: // TODO: Ambulance fields undefined m_unk0x160[4]; diff --git a/LEGO1/lego/legoomni/include/ambulancemissionstate.h b/LEGO1/lego/legoomni/include/ambulancemissionstate.h index a09bf117..cdfa608b 100644 --- a/LEGO1/lego/legoomni/include/ambulancemissionstate.h +++ b/LEGO1/lego/legoomni/include/ambulancemissionstate.h @@ -40,6 +40,9 @@ class AmbulanceMissionState : public LegoState { } } + // SYNTHETIC: LEGO1 0x100376c0 + // AmbulanceMissionState::`scalar deleting destructor' + protected: undefined4 m_unk0x8; // 0x08 undefined4 m_unk0xc; // 0x0c diff --git a/LEGO1/lego/legoomni/include/animstate.h b/LEGO1/lego/legoomni/include/animstate.h index c1098b6a..fe39ccc7 100644 --- a/LEGO1/lego/legoomni/include/animstate.h +++ b/LEGO1/lego/legoomni/include/animstate.h @@ -26,6 +26,9 @@ class AnimState : public LegoState { virtual MxBool SetFlag() override; // vtable+0x18 virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream) override; // vtable+0x1C + // SYNTHETIC: LEGO1 0x10065130 + // AnimState::`scalar deleting destructor' + private: undefined4 m_unk0x8; undefined4 m_unk0xc; diff --git a/LEGO1/lego/legoomni/include/beachhouseentity.h b/LEGO1/lego/legoomni/include/beachhouseentity.h index 58aa3c68..1c92fc17 100644 --- a/LEGO1/lego/legoomni/include/beachhouseentity.h +++ b/LEGO1/lego/legoomni/include/beachhouseentity.h @@ -7,8 +7,6 @@ // 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 { @@ -21,6 +19,9 @@ class BeachHouseEntity : public BuildingEntity { { 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 index 899cfd21..29aa6063 100644 --- a/LEGO1/lego/legoomni/include/bike.h +++ b/LEGO1/lego/legoomni/include/bike.h @@ -23,6 +23,9 @@ class Bike : public IslePathActor { return !strcmp(p_name, Bike::ClassName()) || IslePathActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x10076880 + // Bike::`scalar deleting destructor' + private: // TODO: Bike fields undefined m_unk0x160[4]; diff --git a/LEGO1/lego/legoomni/include/buildingentity.h b/LEGO1/lego/legoomni/include/buildingentity.h index 7f2abe07..0e9a9d45 100644 --- a/LEGO1/lego/legoomni/include/buildingentity.h +++ b/LEGO1/lego/legoomni/include/buildingentity.h @@ -10,6 +10,8 @@ class BuildingEntity : public LegoEntity { BuildingEntity(); virtual ~BuildingEntity() override; // vtable+0x0 + virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + // FUNCTION: LEGO1 0x10014f20 inline virtual const char* ClassName() const override // vtable+0x0c { @@ -22,6 +24,9 @@ class BuildingEntity : public LegoEntity { { 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 index a56526e4..a423ca3e 100644 --- a/LEGO1/lego/legoomni/include/bumpbouy.h +++ b/LEGO1/lego/legoomni/include/bumpbouy.h @@ -19,6 +19,9 @@ class BumpBouy : public LegoAnimActor { { return !strcmp(p_name, BumpBouy::ClassName()) || LegoAnimActor::IsA(p_name); } + + // 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 index 767fa567..3a3b238a 100644 --- a/LEGO1/lego/legoomni/include/carrace.h +++ b/LEGO1/lego/legoomni/include/carrace.h @@ -23,6 +23,9 @@ class CarRace : public LegoRace { return !strcmp(p_name, CarRace::ClassName()) || LegoRace::IsA(p_name); } + // SYNTHETIC: LEGO1 0x10016c70 + // CarRace::`scalar deleting destructor' + private: undefined m_unk0x144[12]; // 0x144 undefined4 m_unk0x150; // 0x150 diff --git a/LEGO1/lego/legoomni/include/carracestate.h b/LEGO1/lego/legoomni/include/carracestate.h index 561f277b..490900dd 100644 --- a/LEGO1/lego/legoomni/include/carracestate.h +++ b/LEGO1/lego/legoomni/include/carracestate.h @@ -19,6 +19,9 @@ class CarRaceState : public RaceState { { 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 index feea0460..321fdf61 100644 --- a/LEGO1/lego/legoomni/include/doors.h +++ b/LEGO1/lego/legoomni/include/doors.h @@ -19,6 +19,9 @@ class Doors : public LegoPathActor { { return !strcmp(p_name, Doors::ClassName()) || LegoPathActor::IsA(p_name); } + + // 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 index e45fe8fe..918a8b1a 100644 --- a/LEGO1/lego/legoomni/include/dunebuggy.h +++ b/LEGO1/lego/legoomni/include/dunebuggy.h @@ -23,6 +23,9 @@ class DuneBuggy : public IslePathActor { return !strcmp(p_name, DuneBuggy::ClassName()) || IslePathActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x10067dc0 + // DuneBuggy::`scalar deleting destructor' + private: // TODO: Double check DuneBuggy field types undefined4 m_unk0x160; diff --git a/LEGO1/lego/legoomni/include/elevatorbottom.h b/LEGO1/lego/legoomni/include/elevatorbottom.h index 64b3f221..1f02d28f 100644 --- a/LEGO1/lego/legoomni/include/elevatorbottom.h +++ b/LEGO1/lego/legoomni/include/elevatorbottom.h @@ -1,9 +1,11 @@ #ifndef ELEVATORBOTTOM_H #define ELEVATORBOTTOM_H +#include "decomp.h" #include "legoworld.h" // VTABLE: LEGO1 0x100d5f20 +// SIZE: 0xfc (from inlined ctor at 0x1000a8aa) class ElevatorBottom : public LegoWorld { public: ElevatorBottom(); @@ -23,6 +25,23 @@ class ElevatorBottom : public LegoWorld { { return !strcmp(p_name, ElevatorBottom::ClassName()) || LegoWorld::IsA(p_name); } + + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void VTable0x50() override; // vtable+0x50 + + // FUNCTION: LEGO1 0x10017f10 + virtual MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + + virtual MxBool VTable0x64() override; // vtable+0x64 + virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x10018040 + // ElevatorBottom::`scalar deleting destructor' + +private: + undefined4 m_unk0xf8; // 0xf8 + + MxLong HandleNotification17(MxParam& p_param); }; #endif // ELEVATORBOTTOM_H diff --git a/LEGO1/lego/legoomni/include/extra.h b/LEGO1/lego/legoomni/include/extra.h index e8aed106..35f08033 100644 --- a/LEGO1/lego/legoomni/include/extra.h +++ b/LEGO1/lego/legoomni/include/extra.h @@ -3,19 +3,21 @@ // Items related to the Extra string of key-value pairs found in MxOb -enum ExtraActionType { - ExtraActionType_none = 0, - ExtraActionType_opendisk = 1, - ExtraActionType_openram = 2, - ExtraActionType_close = 3, - ExtraActionType_start = 4, - ExtraActionType_stop = 5, - ExtraActionType_run = 6, - ExtraActionType_exit = 7, - ExtraActionType_enable = 8, - ExtraActionType_disable = 9, - ExtraActionType_notify = 10, - ExtraActionType_unknown = 11, +struct Extra { + enum ActionType { + e_none = 0, + e_opendisk, + e_openram, + e_close, + e_start, + e_stop, + e_run, + e_exit, + e_enable, + e_disable, + e_notify, + e_unknown, + }; }; #endif // EXTRA_H diff --git a/LEGO1/lego/legoomni/include/gasstation.h b/LEGO1/lego/legoomni/include/gasstation.h index 0617e161..2c979d72 100644 --- a/LEGO1/lego/legoomni/include/gasstation.h +++ b/LEGO1/lego/legoomni/include/gasstation.h @@ -1,7 +1,9 @@ #ifndef GASSTATION_H #define GASSTATION_H +#include "decomp.h" #include "legoworld.h" +#include "radio.h" // VTABLE: LEGO1 0x100d4650 // SIZE 0x128 @@ -26,6 +28,23 @@ class GasStation : public LegoWorld { { return !strcmp(p_name, GasStation::ClassName()) || LegoWorld::IsA(p_name); } + + // 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/lego/legoomni/include/gasstationentity.h b/LEGO1/lego/legoomni/include/gasstationentity.h index b4a27942..7ab807cd 100644 --- a/LEGO1/lego/legoomni/include/gasstationentity.h +++ b/LEGO1/lego/legoomni/include/gasstationentity.h @@ -19,6 +19,9 @@ class GasStationEntity : public BuildingEntity { { 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 index e2768a98..0cdf7bf1 100644 --- a/LEGO1/lego/legoomni/include/gasstationstate.h +++ b/LEGO1/lego/legoomni/include/gasstationstate.h @@ -22,6 +22,9 @@ class GasStationState : public LegoState { return !strcmp(p_name, GasStationState::ClassName()) || LegoState::IsA(p_name); } + // SYNTHETIC: LEGO1 0x10006290 + // GasStationState::`scalar deleting destructor' + private: undefined4 m_unk0x08[3]; undefined4 m_unk0x14; diff --git a/LEGO1/lego/legoomni/include/gifmanager.h b/LEGO1/lego/legoomni/include/gifmanager.h index 3226b4b0..898ab1fb 100644 --- a/LEGO1/lego/legoomni/include/gifmanager.h +++ b/LEGO1/lego/legoomni/include/gifmanager.h @@ -1,69 +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: - const char* m_name; - LPDIRECTDRAWSURFACE m_surface; - LPDIRECTDRAWPALETTE m_palette; - LPDIRECT3DRMTEXTURE2 m_texture; - MxU8* m_data; + char* m_name; // 0x00 + LPDIRECTDRAWSURFACE m_surface; // 0x04 + LPDIRECTDRAWPALETTE m_palette; // 0x08 + LPDIRECT3DRMTEXTURE2 m_texture; // 0x0c + MxU8* m_data; // 0x10 + + ~GifData(); }; -struct GifMapEntry { -public: - GifMapEntry* m_right; - GifMapEntry* m_parent; - GifMapEntry* m_left; - const char* m_key; - GifData* m_value; +struct GifMapComparator { + bool operator()(const char* const& p_key0, const char* const& p_key1) const { return strcmp(p_key0, p_key1) > 0; } }; -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; +// SIZE 0x10 +class GifMap : public map { + // SYNTHETIC: LEGO1 0x1005a400 + // GifMap::~GifMap }; +typedef list GifList; + // VTABLE: LEGO1 0x100d86d4 +// SIZE 0x18 class GifManagerBase { public: - // STUB: LEGO1 0x1005a310 - virtual ~GifManagerBase() {} // vtable+00 + // 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); - inline GifData* Get(const char* p_name) { return m_unk0x8.Get(p_name); } + 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: - undefined4 m_unk0x0; - undefined4 m_unk0x4; - GifMap m_unk0x8; + MxBool m_ownership; // 0x04 + GifMap m_map; // 0x08 }; // VTABLE: LEGO1 0x100d86fc +// SIZE 0x24 class GifManager : public GifManagerBase { public: - // STUB: LEGO1 0x1005a580 - virtual ~GifManager() {} // vtable+00 + GifManager() { m_ownership = TRUE; }; + virtual ~GifManager() override; + + // SYNTHETIC: LEGO1 0x1005a580 + // GifManager::`scalar deleting destructor' + + void FUN_10099cc0(GifData* p_data); protected: - undefined m_unk0x14[0x1c]; + GifList m_list; // 0x18 }; +// TEMPLATE: LEGO1 0x10059c50 +// allocator::_Charalloc + +// clang-format off +// TEMPLATE: LEGO1 0x10001cc0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Lbound + +// TEMPLATE: LEGO1 0x1004f9b0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Insert + +// TEMPLATE: LEGO1 0x10059c70 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Color + +// TEMPLATE: LEGO1 0x10059c80 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Left + +// TEMPLATE: LEGO1 0x10059c90 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Parent + +// TEMPLATE: LEGO1 0x10059ca0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Right + +// TEMPLATE: LEGO1 0x10059cb0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::~_Tree,map >::_Kfn,GifMapComparator,allocator > + +// TEMPLATE: LEGO1 0x10059d80 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::iterator::_Inc + +// TEMPLATE: LEGO1 0x10059dc0 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::erase + +// TEMPLATE: LEGO1 0x1005a210 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Erase + +// TEMPLATE: LEGO1 0x1005a250 +// list >::~list > + +// TEMPLATE: LEGO1 0x1005a2c0 +// map >::~map > + +// TEMPLATE: LEGO1 0x1005a450 +// Map::~Map + +// TEMPLATE: LEGO1 0x1005a5a0 +// List::~List + +// GLOBAL: LEGO1 0x100f0100 +// _Tree,map >::_Kfn,GifMapComparator,allocator >::_Nil +// clang-format on + #endif // GIFMANAGER_H diff --git a/LEGO1/lego/legoomni/include/helicopter.h b/LEGO1/lego/legoomni/include/helicopter.h index 7c5be4ea..ec4faa59 100644 --- a/LEGO1/lego/legoomni/include/helicopter.h +++ b/LEGO1/lego/legoomni/include/helicopter.h @@ -9,12 +9,12 @@ class HelicopterSubclass { public: inline HelicopterSubclass() : m_unk0x30(0) {} - MxResult FUN_100040a0(Vector4Impl& p_v, float p_f); + MxResult FUN_100040a0(Vector4& p_v, float p_f); private: - Vector4Data m_unk0x0; // 0x0 - Vector4Data m_unk0x18; // 0x18 - undefined4 m_unk0x30; // 0x30 + Mx4DPointFloat m_unk0x0; // 0x0 + Mx4DPointFloat m_unk0x18; // 0x18 + undefined4 m_unk0x30; // 0x30 }; // VTABLE: LEGO1 0x100d40f8 @@ -37,9 +37,9 @@ class Helicopter : public IslePathActor { return !strcmp(p_name, Helicopter::ClassName()) || IslePathActor::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 void VTable0x70(float p_float) override; // vtable+0x70 - void VTable0x74(Matrix4Impl& p_transform) override; // vtable+0x74 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 virtual MxU32 VTable0xcc() override; // vtable+0xcc virtual MxU32 VTable0xd4(MxType17NotificationParam& p_param) override; // vtable+0xd4 virtual MxU32 VTable0xd8(MxType18NotificationParam& p_param) override; // vtable+0xd8 @@ -49,8 +49,8 @@ class Helicopter : public IslePathActor { // Helicopter::`scalar deleting destructor' protected: - Matrix4Data m_unk0x160; // 0x160 - Matrix4Data m_unk0x1a8; // 0x1a8 + MxMatrix m_unk0x160; // 0x160 + MxMatrix m_unk0x1a8; // 0x1a8 float m_unk0x1f0; // 0x1f0 HelicopterSubclass m_unk0x1f4; // 0x1f4 HelicopterState* m_state; // 0x228 diff --git a/LEGO1/lego/legoomni/include/helicopterstate.h b/LEGO1/lego/legoomni/include/helicopterstate.h index 2cb3b747..41dcf84b 100644 --- a/LEGO1/lego/legoomni/include/helicopterstate.h +++ b/LEGO1/lego/legoomni/include/helicopterstate.h @@ -24,6 +24,9 @@ class HelicopterState : public LegoState { inline void SetUnknown8(MxU32 p_unk0x8) { m_unk0x8 = p_unk0x8; } inline MxU32 GetUnkown8() { return m_unk0x8; } + // SYNTHETIC: LEGO1 0x1000e190 + // HelicopterState::`scalar deleting destructor' + protected: MxU32 m_unk0x8; // 0x8 }; diff --git a/LEGO1/lego/legoomni/include/historybook.h b/LEGO1/lego/legoomni/include/historybook.h index 80cc78b5..101e45a6 100644 --- a/LEGO1/lego/legoomni/include/historybook.h +++ b/LEGO1/lego/legoomni/include/historybook.h @@ -24,6 +24,9 @@ class HistoryBook : public LegoWorld { { return !strcmp(p_name, HistoryBook::ClassName()) || LegoWorld::IsA(p_name); } + + // 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 index 29ff1177..bbaa3e74 100644 --- a/LEGO1/lego/legoomni/include/hospital.h +++ b/LEGO1/lego/legoomni/include/hospital.h @@ -26,6 +26,9 @@ class Hospital : public LegoWorld { return !strcmp(p_name, Hospital::ClassName()) || LegoWorld::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100747d0 + // Hospital::`scalar deleting destructor' + private: undefined2 m_unk0xf8; // 0xf8 undefined4 m_unk0xfc; // 0xfc diff --git a/LEGO1/lego/legoomni/include/hospitalentity.h b/LEGO1/lego/legoomni/include/hospitalentity.h index f4f14b70..fea461d8 100644 --- a/LEGO1/lego/legoomni/include/hospitalentity.h +++ b/LEGO1/lego/legoomni/include/hospitalentity.h @@ -19,6 +19,9 @@ class HospitalEntity : public BuildingEntity { { 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 index 25c23d96..7fabe10a 100644 --- a/LEGO1/lego/legoomni/include/hospitalstate.h +++ b/LEGO1/lego/legoomni/include/hospitalstate.h @@ -23,6 +23,9 @@ class HospitalState : public LegoState { return !strcmp(p_name, HospitalState::ClassName()) || LegoState::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100764c0 + // HospitalState::`scalar deleting destructor' + private: undefined m_unk0x8[4]; // 0x8 undefined2 m_unk0xc; // 0xc diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index ec0be745..7de6ec45 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -2,11 +2,111 @@ #define INFOCENTER_H #include "legoworld.h" +#include "radio.h" + +class InfocenterState; + +// SIZE 0x18 +struct InfocenterUnkDataEntry { + // FUNCTION: LEGO1 0x1006ec80 + InfocenterUnkDataEntry() {} + + undefined m_pad[0x18]; +}; // VTABLE: LEGO1 0x100d9338 // SIZE 0x1d8 class Infocenter : public LegoWorld { public: + enum Cutscene { + e_noIntro = -1, + e_legoMovie, + e_mindscapeMovie, + e_introMovie, + e_outroMovie, + e_badEndMovie, + e_goodEndMovie + }; + + enum InfomainScript { + c_noInfomain = -1, + + c_welcomeDialogue = 500, + c_goodJobDialogue = 501, + + c_clickOnInfomanDialogue = 502, + c_tickleInfomanDialogue = 503, + + c_letsGetStartedDialogue = 504, + + c_clickOnObjectsGuidanceDialogue = 505, + c_arrowNavigationGuidanceDialogue = 506, + c_elevatorGuidanceDialogue = 507, + c_radioGuidanceDialogue = 508, + c_exitGuidanceDialogue1 = 509, + c_exitGuidanceDialogue2 = 510, + c_goOutsideGuidanceDialogue = 511, + c_experimentGuidanceDialogue = 512, + c_returnBackGuidanceDialogue1 = 513, + c_returnBackGuidanceDialogue2 = 514, + c_bricksterWarningDialogue = 515, + c_newGameGuidanceDialogue = 516, + c_returnBackGuidanceDialogue3 = 517, + + c_reenterInfoCenterDialogue1 = 518, + c_reenterInfoCenterDialogue2 = 519, + c_reenterInfoCenterDialogue3 = 520, + c_reenterInfoCenterDialogue4 = 521, + + c_exitConfirmationDialogue = 522, + c_saveGameOptionsDialogueUnused = 523, + c_exitGameDialogue = 524, + + c_bricksterEscapedDialogue1 = 525, + c_bricksterEscapedDialogue2 = 526, + c_bricksterEscapedDialogue3 = 527, + c_bricksterEscapedDialogue4 = 528, + c_bricksterEscapedDialogue5 = 529, + c_bricksterEscapedDialogue6 = 530, + c_bricksterEscapedDialogue7 = 531, + + c_infomanHiccup = 532, + c_infomanWalkOffScreenLeftUnused = 533, + c_infomanSneeze = 534, + c_infomanWalkOffScreenRightUnused = 535, + c_infomanLaughs = 536, + c_infomanLooksBehindAtScreenUnused = 537, + c_infomanReturnsFromScreenUnused = 538, + + c_goodEndingDialogue = 539, + c_badEndingDialogue = 540, + + c_pepperCharacterSelect = 541, + c_mamaCharacterSelect = 542, + c_papaCharacterSelect = 543, + c_nickCharacterSelect = 544, + c_lauraCharacterSelect = 545, + + c_creditsDialogue = 551, + + c_noCDDialogueUnused1 = 552, + c_noCDDialogueUnused2 = 553, + + c_leaveInfoCenterDialogue1 = 562, + c_leaveInfoCenterDialogue2 = 563, + c_leaveInfoCenterDialogue3 = 564, + c_leaveInfoCenterDialogue4 = 565, + + c_registerToContinueDialogue = 573, + + c_bricksterDialogue = 574, + c_bricksterLaughs = 575, + }; + + enum SndAmimScript { + c_bookWig = 400 + }; + Infocenter(); virtual ~Infocenter() override; @@ -26,11 +126,54 @@ class Infocenter : public LegoWorld { return !strcmp(p_name, Infocenter::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 - virtual void Stop() override; // vtable+0x50 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void VTable0x50() override; // vtable+0x50 virtual MxBool VTable0x5c() override; // vtable+0x5c virtual MxBool VTable0x64() override; // vtable+0x64 virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + + // 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 HandleNotification17(MxParam&); + MxLong HandleEndAction(MxParam& p_param); + MxLong HandleNotification0(MxParam&); + + void FUN_10070dc0(MxBool); + void FUN_10070e90(); + + void PlayCutscene(Cutscene p_entityId, MxBool p_scale); + void StopCutscene(); + + void StartCredits(); + void StopCredits(); + + void PlayAction(InfomainScript p_objectId); + void StopCurrentAction(); + + void PlayBookAnimation(); + void StopBookAnimation(); + + InfomainScript m_currentInfomainScript; // 0xf8 + MxS16 m_unk0xfc; // 0xfc + InfocenterState* m_infocenterState; // 0x100 + undefined4 m_unk0x104; // 0x104 + Cutscene m_currentCutscene; // 0x108 + Radio m_radio; // 0x10c + undefined4 m_unk0x11c; // 0x11c + InfocenterUnkDataEntry m_entries[7]; // 0x120 + MxS16 m_unk0x1c8; // 0x1c8 + undefined4 m_unk0x1cc; // 0x1cc + MxS16 m_infoManDialogueTimer; // 0x1d0 + MxS16 m_bookAnimationTimer; // 0x1d2 + MxU16 m_unk0x1d4; // 0x1d4 + MxS16 m_unk0x1d6; // 0x1d6 }; #endif // INFOCENTER_H diff --git a/LEGO1/lego/legoomni/include/infocenterdoor.h b/LEGO1/lego/legoomni/include/infocenterdoor.h index 5bc5e407..1890f0b1 100644 --- a/LEGO1/lego/legoomni/include/infocenterdoor.h +++ b/LEGO1/lego/legoomni/include/infocenterdoor.h @@ -24,6 +24,21 @@ class InfocenterDoor : public LegoWorld { { return !strcmp(p_name, InfocenterDoor::ClassName()) || LegoWorld::IsA(p_name); } + + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void VTable0x50() override; // vtable+0x50 + + // FUNCTION: LEGO1 0x100377a0 + virtual MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + + virtual MxBool VTable0x64() override; // vtable+0x64 + virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + + // SYNTHETIC: LEGO1 0x100378d0 + // InfocenterDoor::`scalar deleting destructor' + +private: + MxS32 m_unk0xf8; // 0xf8 }; #endif // INFOCENTERDOOR_H diff --git a/LEGO1/lego/legoomni/include/infocenterentity.h b/LEGO1/lego/legoomni/include/infocenterentity.h index e011aeb8..91fe03ff 100644 --- a/LEGO1/lego/legoomni/include/infocenterentity.h +++ b/LEGO1/lego/legoomni/include/infocenterentity.h @@ -19,6 +19,9 @@ class InfoCenterEntity : public BuildingEntity { { 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 index b1bce306..8314529f 100644 --- a/LEGO1/lego/legoomni/include/infocenterstate.h +++ b/LEGO1/lego/legoomni/include/infocenterstate.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "legostate.h" +#include "mxstillpresenter.h" // VTABLE: LEGO1 0x100d93a8 // SIZE 0x94 @@ -24,7 +25,17 @@ class InfocenterState : public LegoState { return !strcmp(p_name, InfocenterState::ClassName()) || LegoState::IsA(p_name); } - inline MxU32 GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } + // FUNCTION: LEGO1 0x10071830 + virtual 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 MxU32 GetUnknown0x74() { return m_unk0x74; } + + inline void SetUnknown0x74(MxU32 p_unk0x74) { m_unk0x74 = p_unk0x74; } + + // SYNTHETIC: LEGO1 0x10071900 + // InfocenterState::`scalar deleting destructor' private: // Members should be renamed with their offsets before use @@ -55,8 +66,9 @@ class InfocenterState : public LegoState { undefined4 unk13; */ - undefined m_pad[0x70]; - MxU32 m_buffer[7]; // 0x78 + undefined m_pad[0x6c]; + MxU32 m_unk0x74; // 0x74 + MxStillPresenter* m_buffer[7]; // 0x78 }; #endif // INFOCENTERSTATE_H diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index c3579aec..681e0337 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -12,7 +12,7 @@ class JukeBoxEntity; class Helicopter; class Bike; class DuneBuggy; -class Motorcycle; +class Motocycle; class SkateBoard; class RaceCar; class Jetski; @@ -40,8 +40,8 @@ class Isle : public LegoWorld { return !strcmp(p_name, Isle::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 - virtual void Stop() override; // vtable+50 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void VTable0x50() override; // vtable+50 virtual void VTable0x58(MxCore* p_object) override; // vtable+58 // FUNCTION: LEGO1 0x10030900 virtual MxBool VTable0x5c() override { return TRUE; } // vtable+5c @@ -57,6 +57,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 +72,7 @@ class Isle : public LegoWorld { Helicopter* m_helicopter; // 0x110 Bike* m_bike; // 0x114 DuneBuggy* m_dunebuggy; // 0x118 - Motorcycle* m_motorcycle; // 0x11c + Motocycle* m_motocycle; // 0x11c SkateBoard* m_skateboard; // 0x120 RaceCar* m_racecar; // 0x124 Jetski* m_jetski; // 0x128 diff --git a/LEGO1/lego/legoomni/include/isleactor.h b/LEGO1/lego/legoomni/include/isleactor.h index 8fd7d039..1c2ddc5c 100644 --- a/LEGO1/lego/legoomni/include/isleactor.h +++ b/LEGO1/lego/legoomni/include/isleactor.h @@ -20,4 +20,10 @@ class IsleActor : public LegoActor { } }; +// SYNTHETIC: LEGO1 0x1000e940 +// IsleActor::~IsleActor + +// SYNTHETIC: LEGO1 0x1000e990 +// IsleActor::`scalar deleting destructor' + #endif // ISLEACTOR_H diff --git a/LEGO1/lego/legoomni/include/islepathactor.h b/LEGO1/lego/legoomni/include/islepathactor.h index d7a8ff60..96a3dce7 100644 --- a/LEGO1/lego/legoomni/include/islepathactor.h +++ b/LEGO1/lego/legoomni/include/islepathactor.h @@ -13,6 +13,8 @@ class IslePathActor : public LegoPathActor { public: IslePathActor(); + + // FUNCTION: LEGO1 0x10002e10 inline virtual ~IslePathActor() override { IslePathActor::Destroy(TRUE); } // vtable+0x0 // FUNCTION: LEGO1 0x10002ea0 @@ -28,7 +30,8 @@ class IslePathActor : public LegoPathActor { return !strcmp(p_name, IslePathActor::ClassName()) || LegoPathActor::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c // FUNCTION: LEGO1 0x10002e70 virtual MxU32 VTable0xcc() { return 0; } // vtable+0xcc // FUNCTION: LEGO1 0x10002df0 diff --git a/LEGO1/lego/legoomni/include/jetski.h b/LEGO1/lego/legoomni/include/jetski.h index 1a64a4b6..c0129dbd 100644 --- a/LEGO1/lego/legoomni/include/jetski.h +++ b/LEGO1/lego/legoomni/include/jetski.h @@ -23,6 +23,9 @@ class Jetski : public IslePathActor { return !strcmp(p_name, Jetski::ClassName()) || IslePathActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x1007e5c0 + // Jetski::`scalar deleting destructor' + private: // TODO: Jetski fields undefined m_unk0x160[4]; diff --git a/LEGO1/lego/legoomni/include/jetskiracestate.h b/LEGO1/lego/legoomni/include/jetskiracestate.h index 5610ac32..ccb60112 100644 --- a/LEGO1/lego/legoomni/include/jetskiracestate.h +++ b/LEGO1/lego/legoomni/include/jetskiracestate.h @@ -19,6 +19,9 @@ class JetskiRaceState : public RaceState { { 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 index 59aee194..0bef74fa 100644 --- a/LEGO1/lego/legoomni/include/jukebox.h +++ b/LEGO1/lego/legoomni/include/jukebox.h @@ -23,6 +23,92 @@ class JukeBox : public LegoWorld { return !strcmp(p_name, JukeBox::ClassName()) || LegoWorld::IsA(p_name); } + // 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 diff --git a/LEGO1/lego/legoomni/include/jukeboxentity.h b/LEGO1/lego/legoomni/include/jukeboxentity.h index c451787d..81a47ef9 100644 --- a/LEGO1/lego/legoomni/include/jukeboxentity.h +++ b/LEGO1/lego/legoomni/include/jukeboxentity.h @@ -22,6 +22,9 @@ class JukeBoxEntity : public LegoEntity { { return !strcmp(p_name, JukeBoxEntity::ClassName()) || LegoEntity::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x10085db0 + // JukeBoxEntity::`scalar deleting destructor' }; #endif // JUKEBOXENTITY_H diff --git a/LEGO1/lego/legoomni/include/jukeboxstate.h b/LEGO1/lego/legoomni/include/jukeboxstate.h index 7a517bb0..8263e97c 100644 --- a/LEGO1/lego/legoomni/include/jukeboxstate.h +++ b/LEGO1/lego/legoomni/include/jukeboxstate.h @@ -21,6 +21,9 @@ class JukeBoxState : public LegoState { } virtual 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 index ed1942da..c08e777f 100644 --- a/LEGO1/lego/legoomni/include/lego3dwavepresenter.h +++ b/LEGO1/lego/legoomni/include/lego3dwavepresenter.h @@ -19,6 +19,9 @@ class Lego3DWavePresenter : public MxWavePresenter { { return !strcmp(p_name, Lego3DWavePresenter::ClassName()) || MxWavePresenter::IsA(p_name); } + + // 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 index 79983416..1f0138ce 100644 --- a/LEGO1/lego/legoomni/include/legoact2.h +++ b/LEGO1/lego/legoomni/include/legoact2.h @@ -6,6 +6,9 @@ // VTABLE: LEGO1 0x100d82e0 // SIZE 0x1154 -class LegoAct2 : public LegoWorld {}; +class LegoAct2 : public LegoWorld { + // SYNTHETIC: LEGO1 0x1004fe20 + // LegoAct2::`scalar deleting destructor' +}; #endif // LEGOACT2_H diff --git a/LEGO1/lego/legoomni/include/legoact2state.h b/LEGO1/lego/legoomni/include/legoact2state.h index 38584769..2f8a2e79 100644 --- a/LEGO1/lego/legoomni/include/legoact2state.h +++ b/LEGO1/lego/legoomni/include/legoact2state.h @@ -19,6 +19,9 @@ class LegoAct2State : public LegoState { { return !strcmp(p_name, LegoAct2State::ClassName()) || LegoState::IsA(p_name); } + + // 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 index 746300a6..0cc18935 100644 --- a/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/legoactioncontrolpresenter.h @@ -9,7 +9,7 @@ // SIZE 0x68 class LegoActionControlPresenter : public MxMediaPresenter { public: - inline LegoActionControlPresenter() { m_unk0x50 = ExtraActionType_none; } + inline LegoActionControlPresenter() { m_unk0x50 = Extra::ActionType::e_none; } virtual ~LegoActionControlPresenter() override { Destroy(TRUE); }; // vtable+0x00 // FUNCTION: LEGO1 0x1000d0e0 @@ -32,9 +32,9 @@ class LegoActionControlPresenter : public MxMediaPresenter { virtual void Destroy(MxBool p_fromDestructor); // vtable+0x5c private: - ExtraActionType m_unk0x50; // 0x50 - MxString m_unk0x54; // 0x54 - undefined4 m_unk0x64; // 0x64 + Extra::ActionType m_unk0x50; // 0x50 + MxString m_unk0x54; // 0x54 + undefined4 m_unk0x64; // 0x64 }; // SYNTHETIC: LEGO1 0x1000d1d0 diff --git a/LEGO1/lego/legoomni/include/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h index 95c991df..a183a249 100644 --- a/LEGO1/lego/legoomni/include/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -9,6 +9,7 @@ class LegoActor : public LegoEntity { public: LegoActor(); + virtual ~LegoActor() override; // FUNCTION: LEGO1 0x1002d210 inline virtual const char* ClassName() const override // vtable+0x0c @@ -43,4 +44,7 @@ class LegoActor : public LegoEntity { MxU8 m_unk0x74; // 0x74 }; +// SYNTHETIC: LEGO1 0x1002d300 +// LegoActor::`scalar deleting destructor' + #endif // LEGOACTOR_H diff --git a/LEGO1/lego/legoomni/include/legoactorpresenter.h b/LEGO1/lego/legoomni/include/legoactorpresenter.h index a9709686..a9b8ae7e 100644 --- a/LEGO1/lego/legoomni/include/legoactorpresenter.h +++ b/LEGO1/lego/legoomni/include/legoactorpresenter.h @@ -7,6 +7,8 @@ // SIZE 0x50 class LegoActorPresenter : public LegoEntityPresenter { public: + virtual ~LegoActorPresenter() override{}; + // FUNCTION: LEGO1 0x1000cb10 inline virtual const char* ClassName() const override // vtable+0x0c { @@ -19,6 +21,13 @@ class LegoActorPresenter : public LegoEntityPresenter { { return !strcmp(p_name, LegoActorPresenter::ClassName()) || LegoEntityPresenter::IsA(p_name); } + + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void ParseExtra() override; // vtable+0x30 }; +// SYNTHETIC: LEGO1 0x1000cc30 +// LegoActorPresenter::`scalar deleting destructor' + #endif // LEGOACTORPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index f943b062..b81f2c72 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -1,6 +1,7 @@ #ifndef LEGOANIMATIONMANAGER_H #define LEGOANIMATIONMANAGER_H +#include "decomp.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d8c18 @@ -26,11 +27,16 @@ class LegoAnimationManager : public MxCore { return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); } + void FUN_1005ef10(); void FUN_1005f6d0(MxBool); + void FUN_1005f720(undefined4); void FUN_10064670(MxBool); __declspec(dllexport) static void configureLegoAnimationManager(MxS32 p_legoAnimationManagerConfig); + // SYNTHETIC: LEGO1 0x1005ed10 + // LegoAnimationManager::`scalar deleting destructor' + private: void Init(); }; diff --git a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h index 2e1ab918..520f3c09 100644 --- a/LEGO1/lego/legoomni/include/legoanimmmpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimmmpresenter.h @@ -21,6 +21,9 @@ class LegoAnimMMPresenter : public MxCompositePresenter { { return !strcmp(p_name, LegoAnimMMPresenter::ClassName()) || MxCompositePresenter::IsA(p_name); } + + // 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 index de8e91d9..5ff2f0c3 100644 --- a/LEGO1/lego/legoomni/include/legoanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoanimpresenter.h @@ -1,12 +1,19 @@ #ifndef LEGOANIMPRESENTER_H #define LEGOANIMPRESENTER_H +#include "mxgeometry/mxgeometry3d.h" #include "mxvideopresenter.h" +class LegoWorld; +class LegoMemoryStream; +class LegoAnimClass; + // VTABLE: LEGO1 0x100d90c8 +// SIZE 0xc0 class LegoAnimPresenter : public MxVideoPresenter { public: LegoAnimPresenter(); + virtual ~LegoAnimPresenter() override; // FUNCTION: LEGO1 0x10068530 inline virtual const char* ClassName() const override // vtable+0x0c @@ -21,8 +28,84 @@ class LegoAnimPresenter : public MxVideoPresenter { return !strcmp(p_name, LegoAnimPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); } + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void ParseExtra() override; // vtable+0x30 + virtual void Destroy() override; // vtable+0x38 + virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c + virtual void EndAction() override; // vtable+0x40 + virtual void PutFrame() override; // vtable+0x6c + virtual MxResult VTable0x88(MxStreamChunk* p_chunk); // vtable+0x88 + + // 6 more virtual functions here + private: void Init(); + void Destroy(MxBool p_fromDestructor); + + LegoAnimClass* m_unk0x64; // 0x64 + undefined4 m_unk0x68; // 0x68 + undefined4 m_unk0x6c; // 0x6c + undefined4 m_unk0x70; // 0x70 + undefined4 m_unk0x74; // 0x74 + undefined4 m_unk0x78; // 0x78 + undefined4 m_unk0x7c; // 0x7c + LegoWorld* m_currentWorld; // 0x80 + MxAtomId m_animAtom; // 0x84 + undefined4 m_unk0x88; // 0x88 + undefined4 m_unk0x8c; // 0x8c + undefined4 m_unk0x90; // 0x90 + undefined m_unk0x94; // 0x94 + undefined m_unk0x95; // 0x95 + undefined m_unk0x96; // 0x96 + undefined m_unk0x97; // 0x97 + undefined4 m_unk0x98; // 0x98 + MxS16 m_unk0x9c; // 0x9c + undefined4 m_unk0xa0; // 0xa0 + undefined4 m_unk0xa4; // 0xa4 + Mx3DPointFloat m_unk0xa8; // 0xa8 + undefined4 m_unk0xbc; // 0xbc }; +// SYNTHETIC: LEGO1 0x10068650 +// LegoAnimPresenter::`scalar deleting destructor' + +// VTABLE: LEGO1 0x100db768 +// SIZE 0x08 +class LegoAnimClassBase { +public: + LegoAnimClassBase(); + virtual ~LegoAnimClassBase(); + + virtual void VTable0x4(); // vtable+0x04 + virtual void VTable0x8(); // vtable+0x08 + virtual void VTable0xc(); // vtable+0x0c + + undefined4 m_unk0x4; // 0x04 +}; + +// SYNTHETIC: LEGO1 0x10099de0 +// LegoAnimClassBase::`scalar deleting destructor' + +// VTABLE: LEGO1 0x100db8d8 +// SIZE 0x18 +class LegoAnimClass : public LegoAnimClassBase { +public: + LegoAnimClass(); + virtual ~LegoAnimClass() override; + + virtual void VTable0x8() override; // vtable+0x08 + virtual void VTable0xc() override; // vtable+0x0c + virtual MxResult VTable0x10(LegoMemoryStream* p_stream, MxS32); // vtable+0x10 + + MxLong m_unk0x8; // 0x08 + undefined4 m_unk0xc; // 0x0c + undefined4 m_unk0x10; // 0x10 + undefined4 m_unk0x14; // 0x14 +}; + +// SYNTHETIC: LEGO1 0x100a0ba0 +// LegoAnimClass::`scalar deleting destructor' + #endif // LEGOANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index bb9c96bb..5c0061d3 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -19,6 +19,11 @@ class LegoBuildingManager : public MxCore { __declspec(dllexport) static void configureLegoBuildingManager(MxS32); + void FUN_1002fa00(); + + // SYNTHETIC: LEGO1 0x1002f940 + // LegoBuildingManager::`scalar deleting destructor' + private: void Init(); }; diff --git a/LEGO1/lego/legoomni/include/legocachesound.h b/LEGO1/lego/legoomni/include/legocachesound.h index 6398c04e..5d587835 100644 --- a/LEGO1/lego/legoomni/include/legocachesound.h +++ b/LEGO1/lego/legoomni/include/legocachesound.h @@ -23,6 +23,9 @@ class LegoCacheSound : public MxCore { return !strcmp(p_name, LegoCacheSound::ClassName()) || MxCore::IsA(p_name); } + // SYNTHETIC: LEGO1 0x10006610 + // LegoCacheSound::`scalar deleting destructor' + private: void Init(); }; diff --git a/LEGO1/lego/legoomni/include/legocameracontroller.h b/LEGO1/lego/legoomni/include/legocameracontroller.h index 05c974a3..7d038d02 100644 --- a/LEGO1/lego/legoomni/include/legocameracontroller.h +++ b/LEGO1/lego/legoomni/include/legocameracontroller.h @@ -3,9 +3,9 @@ #include "legopointofviewcontroller.h" #include "mxcore.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" #include "mxpoint32.h" -#include "realtime/matrix.h" -#include "realtime/vector.h" // VTABLE: LEGO1 0x100d57b0 // SIZE 0xc8 @@ -29,22 +29,22 @@ class LegoCameraController : public LegoPointOfViewController { return !strcmp(p_name, ClassName()) || MxCore::IsA(p_name); } - virtual void OnLButtonDown(MxPoint32 p_point) override; // vtable+0x30 - virtual void OnLButtonUp(MxPoint32 p_point) override; // vtable+0x34 - virtual void OnRButtonDown(MxPoint32 p_point) override; // vtable+0x38 - virtual void OnRButtonUp(MxPoint32 p_point) override; // vtable+0x3c - virtual void OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) override; // vtable+0x40 - virtual MxResult Create(); // vtable+0x44 + virtual void OnLButtonDown(MxPoint32 p_point); // vtable+0x30 + virtual void OnLButtonUp(MxPoint32 p_point); // vtable+0x34 + virtual void OnRButtonDown(MxPoint32 p_point); // vtable+0x38 + virtual void OnRButtonUp(MxPoint32 p_point); // vtable+0x3c + virtual void OnMouseMove(MxU8 p_modifier, MxPoint32 p_point); // vtable+0x40 + virtual MxResult Create(); // vtable+0x44 - void SetWorldTransform(Vector3Impl& p_at, Vector3Impl& p_dir, Vector3Impl& p_up); - void FUN_100123e0(Matrix4Data& p_transform, MxU32); - Vector3Data& FUN_10012740(); - Vector3Data& FUN_100127f0(); - Vector3Data& FUN_100128a0(); + void SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up); + void FUN_100123e0(const MxMatrix& p_transform, MxU32); + Mx3DPointFloat GetWorldUp(); + Mx3DPointFloat GetWorldLocation(); + Mx3DPointFloat GetWorldDirection(); private: - Matrix4Data m_matrix1; // 0x38 - Matrix4Data m_matrix2; // 0x80 + MxMatrix m_matrix1; // 0x38 + MxMatrix m_matrix2; // 0x80 }; // SYNTHETIC: LEGO1 0x10011f50 diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 74d850d4..c3b1b1f6 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -25,6 +25,9 @@ class LegoCarBuild : public LegoWorld { { return !strcmp(p_name, LegoCarBuild::ClassName()) || LegoWorld::IsA(p_name); } + + // 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 index 0440a0f3..8bd5ba75 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildanimpresenter.h @@ -22,6 +22,9 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { { return !strcmp(p_name, LegoCarBuildAnimPresenter::ClassName()) || LegoAnimPresenter::IsA(p_name); } + + // 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 index f00d900e..d88da3f7 100644 --- a/LEGO1/lego/legoomni/include/legocarraceactor.h +++ b/LEGO1/lego/legoomni/include/legocarraceactor.h @@ -18,6 +18,9 @@ class LegoCarRaceActor : public LegoRaceActor { { return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name); } + + // 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 index 7bc8dc0f..385ee92b 100644 --- a/LEGO1/lego/legoomni/include/legocontrolmanager.h +++ b/LEGO1/lego/legoomni/include/legocontrolmanager.h @@ -2,6 +2,7 @@ #define LEGOCONTROLMANAGER_H #include "mxcore.h" +#include "mxpresenterlist.h" // VTABLE: LEGO1 0x100d6a80 class LegoControlManager : public MxCore { @@ -24,8 +25,13 @@ class LegoControlManager : public MxCore { return !strcmp(p_name, LegoControlManager::ClassName()) || MxCore::IsA(p_name); } + void FUN_10028df0(MxPresenterList* p_presenterList); void Register(MxCore* p_listener); void Unregister(MxCore* p_listener); + void FUN_100293c0(undefined4, const char*, undefined2); + + // SYNTHETIC: LEGO1 0x10028d40 + // LegoControlManager::`scalar deleting destructor' }; #endif // LEGOCONTROLMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index ba0e1a7b..b775f840 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -3,7 +3,7 @@ #include "decomp.h" #include "extra.h" -#include "mxdsobject.h" +#include "mxdsaction.h" #include "mxentity.h" #include "realtime/vector.h" #include "roi/legoroi.h" @@ -12,10 +12,19 @@ // SIZE 0x68 (probably) class LegoEntity : public MxEntity { public: + enum { + c_bit1 = 0x01 + }; + // Inlined at 0x100853f7 inline LegoEntity() { Init(); } - __declspec(dllexport) virtual ~LegoEntity() override; // vtable+0x0 +#ifdef ISLE_APP + __declspec(dllexport) virtual ~LegoEntity() override; +#else + // FUNCTION: LEGO1 0x1000c290 + __declspec(dllexport) virtual ~LegoEntity() override { Destroy(TRUE); } +#endif virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 @@ -32,12 +41,13 @@ class LegoEntity : public MxEntity { return !strcmp(p_name, LegoEntity::ClassName()) || MxEntity::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject); // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c - virtual void ParseAction(char*); // vtable+0x20 - virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 - virtual void SetWorldTransform(Vector3Impl& p_loc, Vector3Impl& p_dir, Vector3Impl& p_up); // vtable+0x28 - virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c + virtual MxResult Create(MxDSAction& p_dsAction); // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c + virtual void ParseAction(char*); // vtable+0x20 + virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 + virtual void SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, + const Vector3& p_up); // vtable+0x28 + virtual void ResetWorldTransform(MxBool p_inVehicle); // vtable+0x2c // FUNCTION: LEGO1 0x10001090 virtual void SetWorldSpeed(MxFloat p_worldSpeed) { m_worldSpeed = p_worldSpeed; } // vtable+0x30 virtual void VTable0x34(); // vtable+0x34 @@ -49,26 +59,31 @@ class LegoEntity : public MxEntity { virtual void VTable0x4c(); // vtable+0x4c void FUN_10010c30(); - void SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool); + void SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool); + + inline LegoROI* GetROI() { return m_roi; } protected: void Init(); void SetWorld(); - undefined m_unk0x10; - undefined m_unk0x11; - Vector3Data m_worldLocation; // 0x14 - Vector3Data m_worldDirection; // 0x28 - Vector3Data m_worldUp; // 0x3c - MxFloat m_worldSpeed; // 0x50 - LegoROI* m_roi; // 0x54 - MxBool m_cameraFlag; // 0x58 - undefined m_unk0x59; + undefined m_unk0x10; // 0x10 + MxU8 m_flags; // 0x11 + Mx3DPointFloat m_worldLocation; // 0x14 + Mx3DPointFloat m_worldDirection; // 0x28 + Mx3DPointFloat m_worldUp; // 0x3c + MxFloat m_worldSpeed; // 0x50 + LegoROI* m_roi; // 0x54 + MxBool m_cameraFlag; // 0x58 + undefined m_unk0x59; // 0x59 // For tokens from the extra string that look like this: // "Action:openram;\lego\scripts\Race\CarRaceR;0" - ExtraActionType m_actionType; // 0x5c - char* m_actionArgString; // 0x60 - MxS32 m_actionArgNumber; // 0x64 + Extra::ActionType m_actionType; // 0x5c + char* m_actionArgString; // 0x60 + MxS32 m_actionArgNumber; // 0x64 }; +// SYNTHETIC: LEGO1 0x1000c3b0 +// LegoEntity::`scalar deleting destructor' + #endif // LEGOENTITY_H diff --git a/LEGO1/lego/legoomni/include/legoentitylist.h b/LEGO1/lego/legoomni/include/legoentitylist.h new file mode 100644 index 00000000..1d29e65d --- /dev/null +++ b/LEGO1/lego/legoomni/include/legoentitylist.h @@ -0,0 +1,92 @@ +#ifndef LEGOENTITYLIST_H +#define LEGOENTITYLIST_H + +#include "mxlist.h" +#include "mxtypes.h" + +class LegoEntity; + +// VTABLE: LEGO1 0x100d6410 +// class MxCollection + +// VTABLE: LEGO1 0x100d6428 +// class MxList + +// VTABLE: LEGO1 0x100d6440 +// class MxPtrList + +// VTABLE: LEGO1 0x100d6458 +// SIZE 0x18 +class LegoEntityList : public MxPtrList { +public: + LegoEntityList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} + + // FUNCTION: LEGO1 0x1001e2d0 + virtual MxS8 Compare(LegoEntity* p_a, LegoEntity* p_b) override + { + return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; + }; // vtable+0x14 +}; + +// VTABLE: LEGO1 0x100d64e8 +// class MxListCursor + +// VTABLE: LEGO1 0x100d64b8 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d64d0 +// SIZE 0x10 +class LegoEntityListCursor : public MxPtrListCursor { +public: + LegoEntityListCursor(LegoEntityList* p_list) : MxPtrListCursor(p_list){}; +}; + +// TEMPLATE: LEGO1 0x1001e2f0 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1001e300 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1001e350 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1001e360 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x1001e3f0 +// MxPtrList::Destroy + +// SYNTHETIC: LEGO1 0x1001e400 +// LegoEntityList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001e470 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x1001e4c0 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e530 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e5e0 +// MxPtrList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f110 +// LegoEntityListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1001f180 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f1d0 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f240 +// MxPtrListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1001f2b0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001edc6 +// LegoEntityListCursor::~LegoEntityListCursor + +#endif // LEGOENTITYLIST_H diff --git a/LEGO1/lego/legoomni/include/legoentitypresenter.h b/LEGO1/lego/legoomni/include/legoentitypresenter.h index 72af0498..249e8b5c 100644 --- a/LEGO1/lego/legoomni/include/legoentitypresenter.h +++ b/LEGO1/lego/legoomni/include/legoentitypresenter.h @@ -26,20 +26,23 @@ class LegoEntityPresenter : public MxCompositePresenter { } virtual void ReadyTickle() override; // vtable+0x18 - virtual void RepeatingTickle(); // vtable+0x24 - virtual void ParseExtra(); // vtable+0x30 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void ParseExtra() override; // vtable+0x30 virtual void Destroy() override; // vtable+0x38 virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c virtual void Init(); // vtable+0x68 - virtual undefined4 SetBackend(LegoEntity* p_unk0x4c); // vtable+0x6c + virtual undefined4 SetEntity(LegoEntity* p_entity); // vtable+0x6c - void SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up); + void SetEntityLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up); + + // SYNTHETIC: LEGO1 0x100535a0 + // LegoEntityPresenter::`scalar deleting destructor' private: void Destroy(MxBool p_fromDestructor); protected: - LegoEntity* m_objectBackend; // 0x4c + LegoEntity* m_entity; // 0x4c }; #endif // LEGOENTITYPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h index c9087909..8805d9cd 100644 --- a/LEGO1/lego/legoomni/include/legoeventnotificationparam.h +++ b/LEGO1/lego/legoomni/include/legoeventnotificationparam.h @@ -7,9 +7,10 @@ #include // VTABLE: LEGO1 0x100d6aa0 +// SIZE 0x20 class LegoEventNotificationParam : public MxNotificationParam { public: - inline LegoEventNotificationParam() : MxNotificationParam(PARAM_NONE, NULL) {} + inline LegoEventNotificationParam() : MxNotificationParam(c_notificationType0, NULL) {} inline LegoEventNotificationParam( NotificationId p_type, MxCore* p_sender, @@ -22,8 +23,9 @@ class LegoEventNotificationParam : public MxNotificationParam { { } - virtual ~LegoEventNotificationParam() override {} // vtable+0x0 (scalar deleting destructor) inline MxU8 GetKey() const { return m_key; } + inline MxS32 GetX() const { return m_x; } + inline MxS32 GetY() const { return m_y; } protected: MxU8 m_modifier; // 0x0c @@ -33,4 +35,10 @@ class LegoEventNotificationParam : public MxNotificationParam { MxU32 m_unk0x1c; // 0x1c }; +// SYNTHETIC: LEGO1 0x10028770 +// LegoEventNotificationParam::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100287e0 +// LegoEventNotificationParam::~LegoEventNotificationParam + #endif // LEGOEVENTNOTIFICATIONPARAM_H diff --git a/LEGO1/lego/legoomni/include/legoflctexturepresenter.h b/LEGO1/lego/legoomni/include/legoflctexturepresenter.h index 36d1fefc..f5ea7420 100644 --- a/LEGO1/lego/legoomni/include/legoflctexturepresenter.h +++ b/LEGO1/lego/legoomni/include/legoflctexturepresenter.h @@ -17,6 +17,9 @@ class LegoFlcTexturePresenter : public MxFlcPresenter { return "LegoFlcTexturePresenter"; } + // SYNTHETIC: LEGO1 0x1005df00 + // LegoFlcTexturePresenter::`scalar deleting destructor' + private: void Init(); diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 5f62b107..ae39654c 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -43,6 +43,7 @@ class LegoGameState { void SetSomeEnumState(undefined4 p_state); void FUN_1003ceb0(); + void FUN_10039780(MxU8); struct ScoreStruct { void WriteScoreHistory(); @@ -72,7 +73,7 @@ class LegoGameState { undefined m_unk0x41a[8]; // 0x41a - might be part of the structure at 0xa6 MxBool m_isDirty; // 0x420 undefined4 m_unk0x424; // 0x424 - undefined4 m_unk0x428; // 0x428 + undefined4 m_prevArea; // 0x428 undefined4 m_unk0x42c; // 0x42c }; diff --git a/LEGO1/lego/legoomni/include/legohideanimpresenter.h b/LEGO1/lego/legoomni/include/legohideanimpresenter.h index f6e86c2e..59449283 100644 --- a/LEGO1/lego/legoomni/include/legohideanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legohideanimpresenter.h @@ -1,6 +1,7 @@ #ifndef LEGOHIDEANIMPRESENTER_H #define LEGOHIDEANIMPRESENTER_H +#include "decomp.h" #include "legoloopinganimpresenter.h" // VTABLE: LEGO1 0x100d9278 @@ -8,6 +9,7 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { public: LegoHideAnimPresenter(); + virtual ~LegoHideAnimPresenter() override; // FUNCTION: LEGO1 0x1006d880 inline const char* ClassName() const override // vtable+0xc @@ -22,8 +24,16 @@ class LegoHideAnimPresenter : public LegoLoopingAnimPresenter { return !strcmp(p_name, ClassName()) || LegoAnimPresenter::IsA(p_name); } + virtual void Destroy() override; // vtable+0x38 + private: void Init(); + void Destroy(MxBool p_fromDestructor); + + undefined4* m_unk0xc0; // 0xc0 }; +// SYNTHETIC: LEGO1 0x1006d9d0 +// LegoHideAnimPresenter::`scalar deleting destructor' + #endif // LEGOHIDEANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 961d8ffc..0f068a90 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -46,13 +46,23 @@ class LegoInputManager : public MxPresenter { MxResult GetJoystickState(MxU32* p_joystickX, MxU32* p_joystickY, DWORD* p_buttonsState, MxU32* p_povPosition); void SetTimer(); void KillTimer(); + 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; } @@ -61,7 +71,10 @@ class LegoInputManager : public MxPresenter { void ProcessEvents(); MxBool ProcessOneEvent(LegoEventNotificationParam& p_param); - // private: + // SYNTHETIC: LEGO1 0x1005b8d0 + // LegoInputManager::`scalar deleting destructor' + +private: MxCriticalSection m_criticalSection; MxList* m_unk0x5c; // list or hash table LegoCameraController* m_camera; @@ -94,6 +107,9 @@ class LegoInputManager : public MxPresenter { // TEMPLATE: LEGO1 0x1005bb80 // MxCollection::Compare +// TEMPLATE: LEGO1 0x1005bbe0 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x1005bc30 // MxCollection::Destroy @@ -109,6 +125,9 @@ class LegoInputManager : public MxPresenter { // SYNTHETIC: LEGO1 0x1005beb0 // LegoEventQueue::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x1005bf20 +// MxQueue::~MxQueue + // SYNTHETIC: LEGO1 0x1005bf70 // MxQueue::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legojetski.h b/LEGO1/lego/legoomni/include/legojetski.h index 09a9f8d1..e4f876a3 100644 --- a/LEGO1/lego/legoomni/include/legojetski.h +++ b/LEGO1/lego/legoomni/include/legojetski.h @@ -18,6 +18,9 @@ class LegoJetski : public LegoJetskiRaceActor { { return !strcmp(p_name, LegoJetski::ClassName()) || LegoJetskiRaceActor::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x10013e20 + // LegoJetski::`scalar deleting destructor' }; #endif // LEGOJETSKI_H diff --git a/LEGO1/lego/legoomni/include/legojetskiraceactor.h b/LEGO1/lego/legoomni/include/legojetskiraceactor.h index 28d151e8..cd497525 100644 --- a/LEGO1/lego/legoomni/include/legojetskiraceactor.h +++ b/LEGO1/lego/legoomni/include/legojetskiraceactor.h @@ -18,6 +18,9 @@ class LegoJetskiRaceActor : public LegoCarRaceActor { { return !strcmp(p_name, LegoJetskiRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x10081d40 + // LegoJetskiRaceActor::`scalar deleting destructor' }; #endif // LEGOJETSKIRACEACTOR_H diff --git a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h index 36facd1d..09370d0f 100644 --- a/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h +++ b/LEGO1/lego/legoomni/include/legolocomotionanimpresenter.h @@ -21,6 +21,9 @@ class LegoLocomotionAnimPresenter : public LegoLoopingAnimPresenter { return !strcmp(p_name, ClassName()) || LegoLoopingAnimPresenter::IsA(p_name); } + // SYNTHETIC: LEGO1 0x1006cfe0 + // LegoLocomotionAnimPresenter::`scalar deleting destructor' + private: void Init(); }; diff --git a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h index a17c671c..844d1586 100644 --- a/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h +++ b/LEGO1/lego/legoomni/include/legoloopinganimpresenter.h @@ -21,4 +21,10 @@ class LegoLoopingAnimPresenter : public LegoAnimPresenter { } }; +// SYNTHETIC: LEGO1 0x1006d000 +// LegoLoopingAnimPresenter::~LegoLoopingAnimPresenter + +// SYNTHETIC: LEGO1 0x1000f440 +// LegoLoopingAnimPresenter::`scalar deleting destructor' + #endif // LEGOLOOPINGANIMPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legometerpresenter.h b/LEGO1/lego/legoomni/include/legometerpresenter.h index 023a7bfa..33c7aa37 100644 --- a/LEGO1/lego/legoomni/include/legometerpresenter.h +++ b/LEGO1/lego/legoomni/include/legometerpresenter.h @@ -7,7 +7,30 @@ // SIZE 0x94 (from 0x1000a163) class LegoMeterPresenter : public MxStillPresenter { public: + LegoMeterPresenter(); + virtual ~LegoMeterPresenter() override; + // MxStillPresenter's `::ClassName` and `::IsA` are used. + + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void ParseExtra() override; // vtable+0x30 + +private: + void FUN_10043a50(); + + MxU8* m_unk0x6c; // 0x6c + MxU16 m_type; // 0x70 + MxString m_variable; // 0x74 + MxFloat m_unk0x84; // 0x84 + MxU16 m_unk0x88; // 0x88 + MxU16 m_unk0x8a; // 0x8a + MxU16 m_unk0x8c; // 0x8c + MxU16 m_unk0x8e; // 0x8e + MxU16 m_layout; // 0x90 }; +// SYNTHETIC: LEGO1 0x10043760 +// LegoMeterPresenter::`scalar deleting destructor' + #endif // LEGOMETERPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legomodelpresenter.h b/LEGO1/lego/legoomni/include/legomodelpresenter.h index ca3e216f..7803187a 100644 --- a/LEGO1/lego/legoomni/include/legomodelpresenter.h +++ b/LEGO1/lego/legoomni/include/legomodelpresenter.h @@ -26,8 +26,15 @@ class LegoModelPresenter : public MxVideoPresenter { virtual void ParseExtra() override; // vtable+0x30 virtual void Destroy() override; // vtable+0x38 + // SYNTHETIC: LEGO1 0x1000cdd0 + // LegoModelPresenter::`scalar deleting destructor' + protected: void Destroy(MxBool p_fromDestructor); + +private: + undefined4 m_unk0x64; // 0x64 + MxBool m_addedToView; // 0x68 }; #endif // LEGOMODELPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h index 97882566..2ae35245 100644 --- a/LEGO1/lego/legoomni/include/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -61,6 +61,9 @@ class LegoNavController : public MxCore { 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/legoobjectfactory.h b/LEGO1/lego/legoomni/include/legoobjectfactory.h index 3a575c52..9357ce34 100644 --- a/LEGO1/lego/legoomni/include/legoobjectfactory.h +++ b/LEGO1/lego/legoomni/include/legoobjectfactory.h @@ -70,7 +70,7 @@ X(RaceCar) \ X(Jetski) \ X(Bike) \ - X(Motorcycle) \ + X(Motocycle) \ X(Ambulance) \ X(AmbulanceMissionState) \ X(TowTrack) \ @@ -108,6 +108,9 @@ class LegoObjectFactory : public MxObjectFactory { virtual MxCore* Create(const char* p_name) override; // vtable 0x14 virtual 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) diff --git a/LEGO1/lego/legoomni/include/legoomni.h b/LEGO1/lego/legoomni/include/legoomni.h index fc9ba1c2..d7d9a2d4 100644 --- a/LEGO1/lego/legoomni/include/legoomni.h +++ b/LEGO1/lego/legoomni/include/legoomni.h @@ -62,6 +62,12 @@ extern MxAtomId* g_nocdSourceName; // SIZE 0x140 class LegoOmni : public MxOmni { public: + enum { + c_disableInput = 0x01, + c_disable3d = 0x02, + c_clearScreen = 0x04 + }; + __declspec(dllexport) void CreateBackgroundAudio(); __declspec(dllexport) void RemoveWorld(const MxAtomId&, MxLong); __declspec(dllexport) static int GetCurrPathInfo(LegoPathBoundary**, MxS32&); @@ -99,6 +105,7 @@ class LegoOmni : public MxOmni { LegoEntity* FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid); void AddWorld(LegoWorld* p_world); + void FUN_1005b4f0(MxBool p_disable, MxU16 p_flags); LegoVideoManager* GetVideoManager() { return (LegoVideoManager*) m_videoManager; } LegoSoundManager* GetSoundManager() { return (LegoSoundManager*) m_soundManager; } @@ -114,11 +121,17 @@ class LegoOmni : public MxOmni { MxBackgroundAudioManager* GetBackgroundAudioManager() { return m_bkgAudioManager; } MxTransitionManager* GetTransitionManager() { return m_transitionManager; } MxDSAction& GetCurrentAction() { return m_action; } + LegoUnkSaveDataWriter* GetUnkSaveDataWriter() { return m_saveDataWriter; } inline void SetNavController(LegoNavController* p_navController) { m_navController = p_navController; } - + inline void SetWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } inline void SetExit(MxBool p_exit) { m_exit = p_exit; }; + inline void CloseMainWindow() { PostMessageA(m_windowHandle, WM_CLOSE, 0, 0); } + + // SYNTHETIC: LEGO1 0x10058b30 + // LegoOmni::`scalar deleting destructor' + private: undefined4* m_unk0x68; // 0x68 ViewLODListManager* m_viewLODListManager; // 0x6c @@ -148,7 +161,6 @@ __declspec(dllexport) LegoOmni* Lego(); __declspec(dllexport) LegoEntity* PickEntity(MxLong, MxLong); __declspec(dllexport) LegoROI* PickROI(MxLong, MxLong); __declspec(dllexport) LegoSoundManager* SoundManager(); -__declspec(dllexport) MxResult Start(MxDSAction*); __declspec(dllexport) MxTransitionManager* TransitionManager(); __declspec(dllexport) LegoVideoManager* VideoManager(); @@ -158,14 +170,18 @@ LegoControlManager* ControlManager(); IslePathActor* GetCurrentVehicle(); LegoPlantManager* PlantManager(); LegoWorld* GetCurrentWorld(); +LegoUnkSaveDataWriter* GetUnkSaveDataWriter(); GifManager* GetGifManager(); -void FUN_10015820(MxU32, MxU32); +void FUN_10015820(MxBool p_disable, MxU16 p_flags); +void FUN_10015860(const char*, MxU8); LegoEntity* FindEntityByAtomIdOrEntityId(const MxAtomId& p_atom, MxS32 p_entityid); MxDSAction& GetCurrentAction(); void PlayMusic(MxU32 p_index); void SetIsWorldActive(MxBool p_isWorldActive); +void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last); void RegisterScripts(); void UnregisterScripts(); +void SetCurrentWorld(LegoWorld* p_world); #endif // LEGOOMNI_H diff --git a/LEGO1/lego/legoomni/include/legopalettepresenter.h b/LEGO1/lego/legoomni/include/legopalettepresenter.h index 858e1097..242c7bc0 100644 --- a/LEGO1/lego/legoomni/include/legopalettepresenter.h +++ b/LEGO1/lego/legoomni/include/legopalettepresenter.h @@ -30,6 +30,9 @@ class LegoPalettePresenter : public MxVideoPresenter { MxResult ParsePalette(MxStreamChunk* p_chunk); + // SYNTHETIC: LEGO1 0x1007a050 + // LegoPalettePresenter::`scalar deleting destructor' + private: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/lego/legoomni/include/legopartpresenter.h b/LEGO1/lego/legoomni/include/legopartpresenter.h index 6695a70b..e847d39b 100644 --- a/LEGO1/lego/legoomni/include/legopartpresenter.h +++ b/LEGO1/lego/legoomni/include/legopartpresenter.h @@ -21,6 +21,9 @@ class LegoPartPresenter : public MxMediaPresenter { } __declspec(dllexport) static void configureLegoPartPresenter(MxS32, MxS32); + + // SYNTHETIC: LEGO1 0x1000d060 + // LegoPartPresenter::`scalar deleting destructor' }; #endif // LEGOPARTPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index a3f5756c..be2c87e3 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -25,10 +25,10 @@ class LegoPathActor : public LegoActor { return !strcmp(p_name, LegoPathActor::ClassName()) || LegoActor::IsA(p_name); } - virtual void VTable0x68(); // vtable+0x68 - virtual void VTable0x6c(); // vtable+0x6c - virtual void VTable0x70(float p_float); // vtable+0x70 - virtual void VTable0x74(Matrix4Impl& p_transform); // vtable+0x74 + virtual void VTable0x68(); // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(float p_float); // vtable+0x70 + virtual void VTable0x74(Matrix4& p_transform); // vtable+0x74 // FUNCTION: LEGO1 0x10002d20 virtual void VTable0x78(MxU8 p_unk0xea) { m_unk0xea = p_unk0xea; } // vtable+0x78 // FUNCTION: LEGO1 0x10002d30 @@ -66,6 +66,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/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index f7278ca8..ada96e7e 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -8,7 +8,7 @@ class LegoPathController : public MxCore { public: LegoPathController(); - virtual ~LegoPathController() override; + virtual ~LegoPathController() override { Destroy(); }; virtual MxResult Tickle() override; // vtable+08 @@ -24,6 +24,12 @@ 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 }; #endif // LEGOPATHCONTROLLER_H diff --git a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h index db31c2c4..ead40f48 100644 --- a/LEGO1/lego/legoomni/include/legopathcontrollerlist.h +++ b/LEGO1/lego/legoomni/include/legopathcontrollerlist.h @@ -19,6 +19,9 @@ class LegoPathControllerList : public MxPtrList { { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; } // vtable+0x14 + + // SYNTHETIC: LEGO1 0x1001d3d0 + // LegoPathControllerList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100d6380 diff --git a/LEGO1/lego/legoomni/include/legopathpresenter.h b/LEGO1/lego/legoomni/include/legopathpresenter.h index de7b14d1..792b99eb 100644 --- a/LEGO1/lego/legoomni/include/legopathpresenter.h +++ b/LEGO1/lego/legoomni/include/legopathpresenter.h @@ -8,6 +8,7 @@ class LegoPathPresenter : public MxMediaPresenter { public: LegoPathPresenter(); + virtual ~LegoPathPresenter() override; // FUNCTION: LEGO1 0x100449a0 inline const char* ClassName() const override // vtable+0xc @@ -22,11 +23,16 @@ class LegoPathPresenter : public MxMediaPresenter { return !strcmp(p_name, LegoPathPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StreamingTickle() override; // vtable+0x20 virtual void RepeatingTickle() override; // vtable+0x24 virtual void ParseExtra() override; // vtable+0x30 virtual MxResult AddToManager() override; // vtable+0x34 virtual void Destroy() override; // vtable+0x38 + // SYNTHETIC: LEGO1 0x10044a90 + // LegoPathPresenter::`scalar deleting destructor' + private: void Init(); diff --git a/LEGO1/lego/legoomni/include/legophonemepresenter.h b/LEGO1/lego/legoomni/include/legophonemepresenter.h index 330b1c7a..c643f261 100644 --- a/LEGO1/lego/legoomni/include/legophonemepresenter.h +++ b/LEGO1/lego/legoomni/include/legophonemepresenter.h @@ -20,6 +20,9 @@ class LegoPhonemePresenter : public MxFlcPresenter { return "LegoPhonemePresenter"; } + // 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 index 7fd20746..e199f11b 100644 --- a/LEGO1/lego/legoomni/include/legoplantmanager.h +++ b/LEGO1/lego/legoomni/include/legoplantmanager.h @@ -1,6 +1,7 @@ #ifndef LEGOPLANTMANAGER_H #define LEGOPLANTMANAGER_H +#include "decomp.h" #include "mxcore.h" // VTABLE: LEGO1 0x100d6758 @@ -19,6 +20,11 @@ class LegoPlantManager : public MxCore { return "LegoPlantManager"; } + void FUN_10026360(undefined4 p_world); + + // SYNTHETIC: LEGO1 0x100262a0 + // LegoPlantManager::`scalar deleting destructor' + private: void Init(); }; diff --git a/LEGO1/lego/legoomni/include/legopointofviewcontroller.h b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h index a7e92e97..99c213e2 100644 --- a/LEGO1/lego/legoomni/include/legopointofviewcontroller.h +++ b/LEGO1/lego/legoomni/include/legopointofviewcontroller.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "mxcore.h" +#include "mxpoint32.h" #include @@ -82,6 +83,7 @@ class LegoPointOfViewController : public LegoMouseController { virtual void SetEntity(LegoEntity* p_entity); // vtable+0x2c MxResult Create(Lego3DView* p_lego3DView); + void OnViewSize(int p_width, int p_height); inline LegoEntity* GetEntity() { return m_entity; } diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index 530c289c..e3f9df88 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -28,7 +28,7 @@ class LegoRace : public LegoWorld { return !strcmp(p_name, LegoRace::ClassName()) || LegoWorld::IsA(p_name); } - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+0x18 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 virtual MxBool VTable0x5c() override; // vtable+0x5c virtual MxBool VTable0x64() override; // vtable+0x64 virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 @@ -38,6 +38,9 @@ class LegoRace : public LegoWorld { 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 diff --git a/LEGO1/lego/legoomni/include/legoraceactor.h b/LEGO1/lego/legoomni/include/legoraceactor.h index eb459e81..6df40e43 100644 --- a/LEGO1/lego/legoomni/include/legoraceactor.h +++ b/LEGO1/lego/legoomni/include/legoraceactor.h @@ -18,6 +18,9 @@ class LegoRaceActor : public LegoAnimActor { { return !strcmp(p_name, LegoRaceActor::ClassName()) || LegoAnimActor::IsA(p_name); } + + // 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 index a2a54afb..7e200ff6 100644 --- a/LEGO1/lego/legoomni/include/legoracecar.h +++ b/LEGO1/lego/legoomni/include/legoracecar.h @@ -20,6 +20,9 @@ class LegoRaceCar : public LegoCarRaceActor { { return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoCarRaceActor::IsA(p_name); } + + // 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 index 2caef869..0e4bbbbd 100644 --- a/LEGO1/lego/legoomni/include/legosoundmanager.h +++ b/LEGO1/lego/legoomni/include/legosoundmanager.h @@ -14,6 +14,9 @@ class LegoSoundManager : public MxSoundManager { virtual void Destroy() override; // vtable+18 virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x30 + // SYNTHETIC: LEGO1 0x10029920 + // LegoSoundManager::`scalar deleting destructor' + private: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index ba4403de..215d64d4 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -27,6 +27,9 @@ class LegoState : public MxCore { virtual MxBool VTable0x14(); // vtable+0x14 virtual MxBool SetFlag(); // vtable+0x18 virtual MxResult VTable0x1c(LegoFileStream* p_legoFileStream); // vtable+0x1C + + // SYNTHETIC: LEGO1 0x10006160 + // LegoState::`scalar deleting destructor' }; #endif // LEGOSTATE_H diff --git a/LEGO1/lego/legoomni/include/legostream.h b/LEGO1/lego/legoomni/include/legostream.h index 8b0a57c1..601e94e2 100644 --- a/LEGO1/lego/legoomni/include/legostream.h +++ b/LEGO1/lego/legoomni/include/legostream.h @@ -18,7 +18,8 @@ class MxVariableTable; class LegoStream { public: LegoStream() : m_mode(0) {} - inline virtual ~LegoStream(){}; + // FUNCTION: LEGO1 0x10045ad0 + inline virtual ~LegoStream() {} virtual MxResult Read(void* p_buffer, MxU32 p_size) = 0; virtual MxResult Write(const void* p_buffer, MxU32 p_size) = 0; @@ -29,9 +30,9 @@ class LegoStream { virtual MxBool IsReadMode(); enum OpenFlags { - ReadBit = 1, - WriteBit = 2, - BinaryBit = 4, + c_readBit = 1, + c_writeBit = 2, + c_binaryBit = 4, }; static MxResult __stdcall WriteVariable(LegoStream* p_stream, MxVariableTable* p_from, const char* p_variableName); @@ -41,11 +42,14 @@ class LegoStream { MxU8 m_mode; }; +// SYNTHETIC: LEGO1 0x10045b00 +// LegoStream::`scalar deleting destructor' + // VTABLE: LEGO1 0x100db730 class LegoFileStream : public LegoStream { public: LegoFileStream(); - virtual ~LegoFileStream(); + virtual ~LegoFileStream() override; MxResult Read(void* p_buffer, MxU32 p_size) override; MxResult Write(const void* p_buffer, MxU32 p_size) override; @@ -60,11 +64,13 @@ class LegoFileStream : public LegoStream { FILE* m_hFile; }; +// SYNTHETIC: LEGO1 0x10099230 +// LegoFileStream::`scalar deleting destructor' + // VTABLE: LEGO1 0x100db710 class LegoMemoryStream : public LegoStream { public: LegoMemoryStream(char* p_buffer); - ~LegoMemoryStream() {} MxResult Read(void* p_buffer, MxU32 p_size) override; MxResult Write(const void* p_buffer, MxU32 p_size) override; @@ -76,4 +82,10 @@ class LegoMemoryStream : public LegoStream { MxU32 m_offset; }; +// SYNTHETIC: LEGO1 0x10045a80 +// LegoMemoryStream::~LegoMemoryStream + +// SYNTHETIC: LEGO1 0x100990f0 +// LegoMemoryStream::`scalar deleting destructor' + #endif // LEGOSTREAM_H diff --git a/LEGO1/lego/legoomni/include/legotexturepresenter.h b/LEGO1/lego/legoomni/include/legotexturepresenter.h index 0ac13926..ca6541df 100644 --- a/LEGO1/lego/legoomni/include/legotexturepresenter.h +++ b/LEGO1/lego/legoomni/include/legotexturepresenter.h @@ -25,6 +25,9 @@ class LegoTexturePresenter : public MxMediaPresenter { virtual void DoneTickle() override; // vtable+0x2c virtual MxResult AddToManager() override; // vtable+0x34 virtual MxResult PutData() override; // vtable+0x4c + + // SYNTHETIC: LEGO1 0x1000cf40 + // LegoTexturePresenter::`scalar deleting destructor' }; #endif // LEGOTEXTUREPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legounknown100d7c88.h b/LEGO1/lego/legoomni/include/legounknown100d7c88.h index a6004053..2fa960c8 100644 --- a/LEGO1/lego/legoomni/include/legounknown100d7c88.h +++ b/LEGO1/lego/legoomni/include/legounknown100d7c88.h @@ -4,6 +4,7 @@ #include "decomp.h" #include "mxstring.h" +// VTABLE: LEGO1 0x100d7c88 class LegoUnknown100d7c88 { public: ~LegoUnknown100d7c88(); diff --git a/LEGO1/lego/legoomni/include/legounknown100d9d00.h b/LEGO1/lego/legoomni/include/legounknown100d9d00.h index d31634fe..394ffbbd 100644 --- a/LEGO1/lego/legoomni/include/legounknown100d9d00.h +++ b/LEGO1/lego/legoomni/include/legounknown100d9d00.h @@ -27,9 +27,15 @@ class LegoUnknown100d9d00 : public MxList { // TEMPLATE: LEGO1 0x1007b300 // MxCollection::Compare +// TEMPLATE: LEGO1 0x1007b310 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x1007b360 // MxCollection::Destroy +// TEMPLATE: LEGO1 0x1007b370 +// MxList::~MxList + // SYNTHETIC: LEGO1 0x1007b400 // LegoUnknown100d9d00::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legounksavedatawriter.h b/LEGO1/lego/legoomni/include/legounksavedatawriter.h index 039058e6..240bef11 100644 --- a/LEGO1/lego/legoomni/include/legounksavedatawriter.h +++ b/LEGO1/lego/legoomni/include/legounksavedatawriter.h @@ -4,6 +4,7 @@ #include "decomp.h" #include "mxtypes.h" +class LegoROI; class LegoStream; struct LegoSaveDataEntry3 { @@ -32,7 +33,9 @@ struct LegoSaveDataEntry3 { }; class LegoUnkSaveDataWriter { +public: MxResult WriteSaveData3(LegoStream* p_stream); + void FUN_10083db0(LegoROI* p_roi); }; #endif // LEGOUNKSAVEDATAWRITER_H diff --git a/LEGO1/lego/legoomni/include/legoutil.h b/LEGO1/lego/legoomni/include/legoutil.h index 1539f28f..6e9bb5ee 100644 --- a/LEGO1/lego/legoomni/include/legoutil.h +++ b/LEGO1/lego/legoomni/include/legoutil.h @@ -10,8 +10,8 @@ class MxAtomId; class LegoEntity; -ExtraActionType MatchActionString(const char*); -void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender); +Extra::ActionType MatchActionString(const char*); +void InvokeAction(Extra::ActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender); void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut); MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); void FUN_1003ef00(MxBool); diff --git a/LEGO1/lego/legoomni/include/legovehiclebuildstate.h b/LEGO1/lego/legoomni/include/legovehiclebuildstate.h index a39740bb..f441dfad 100644 --- a/LEGO1/lego/legoomni/include/legovehiclebuildstate.h +++ b/LEGO1/lego/legoomni/include/legovehiclebuildstate.h @@ -23,6 +23,9 @@ class LegoVehicleBuildState : public LegoState { return !strcmp(p_name, this->m_className.GetData()) || LegoState::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100260a0 + // LegoVehicleBuildState::`scalar deleting destructor' + public: struct UnkStruct { undefined4 m_unk0x00; diff --git a/LEGO1/lego/legoomni/include/legovideomanager.h b/LEGO1/lego/legoomni/include/legovideomanager.h index 898204da..a9532e87 100644 --- a/LEGO1/lego/legoomni/include/legovideomanager.h +++ b/LEGO1/lego/legoomni/include/legovideomanager.h @@ -30,7 +30,7 @@ class LegoVideoManager : public MxVideoManager { virtual MxResult Create(MxVideoParam& p_videoParam, MxU32 p_frequencyMS, MxBool p_createThread) override; // vtable+0x2c virtual MxResult RealizePalette(MxPalette*) override; // vtable+0x30 - virtual void VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) override; // vtable+0x34 + virtual void UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) override; // vtable+0x34 virtual void VTable0x38(undefined4, undefined4); // vtable+0x38 // FUNCTION: LGEO1 0x1007ab10 virtual LegoUnknown100d9d00* VTable0x3c() { return m_unk0x100d9d00; } // vtable+0x3c @@ -41,6 +41,7 @@ class LegoVideoManager : public MxVideoManager { 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(); diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index c4f53913..31b60f84 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -3,7 +3,9 @@ #include "legocameracontroller.h" #include "legoentity.h" +#include "legoentitylist.h" #include "legopathcontrollerlist.h" +#include "mxcorelist.h" #include "mxpresenter.h" #include "mxpresenterlist.h" @@ -33,37 +35,49 @@ class LegoWorld : public LegoEntity { return !strcmp(p_name, LegoWorld::ClassName()) || LegoEntity::IsA(p_name); } - virtual void Stop(); // vtable+50 - virtual void VTable0x54(); // vtable+54 - virtual void VTable0x58(MxCore* p_object); // vtable+58 - virtual MxBool VTable0x5c(); // vtable+5c - // FUNCTION: LEGO1 0x100010a0 - virtual void VTable0x60() {} // vtable+60 - virtual MxBool VTable0x64(); // vtable+64 - virtual void VTable0x68(MxBool p_add); // vtable+68 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + virtual void VTable0x50(); // vtable+0x50 + virtual LegoCameraController* VTable0x54(); // vtable+0x54 + virtual void VTable0x58(MxCore* p_object); // vtable+0x58 + virtual MxBool VTable0x5c(); // vtable+0x5c - inline LegoCameraController* GetCamera() { return m_camera; } + // FUNCTION: LEGO1 0x100010a0 + virtual void VTable0x60() {} // vtable+0x60 + + virtual MxBool VTable0x64(); // vtable+0x64 + virtual void VTable0x68(MxBool p_add); // vtable+0x68 + + inline LegoCameraController* GetCamera() { return m_cameraController; } + inline undefined4 GetUnknown0xec() { return m_unk0xec; } undefined FUN_100220e0(); - MxResult SetAsCurrentWorld(MxDSObject& p_dsObject); void EndAction(MxCore* p_object); void FUN_1001fc80(IslePathActor* p_actor); - MxBool FUN_100727e0(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up); - MxBool FUN_10072980(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up); + MxBool FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); + MxBool FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up); void FUN_10073400(); void FUN_10073430(); MxS32 GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); + MxPresenter* FindPresenter(const char* p_presenter, const char* p_name); + + // SYNTHETIC: LEGO1 0x1001dee0 + // LegoWorld::`scalar deleting destructor' protected: - LegoPathControllerList m_list0x68; // 0x68 - MxPresenterList m_list0x80; // 0x80 - LegoCameraController* m_camera; // 0x98 - undefined m_unk0x9c[0x1c]; // 0x9c - MxPresenterList m_list0xb8; // 0xb8 - undefined m_unk0xd0[0x24]; // 0xd0 - MxS16 m_unk0xf4; // 0xf4 - MxBool m_unk0xf6; // 0xf6 - undefined m_unk0xf7; // 0xf7 + LegoPathControllerList m_list0x68; // 0x68 + MxPresenterList m_list0x80; // 0x80 + LegoCameraController* m_cameraController; // 0x98 + LegoEntityList* m_entityList; // 0x9c + MxCoreList* m_coreList; // 0xa0 + undefined m_unk0xa4[0x14]; // 0xa4 + MxPresenterList m_list0xb8; // 0xb8 + undefined m_unk0xd0[0x1c]; // 0xd0 + undefined4 m_unk0xec; // 0xec + undefined4 m_unk0xf0; // 0xf0 + MxS16 m_unk0xf4; // 0xf4 + MxBool m_worldStarted; // 0xf6 + undefined m_unk0xf7; // 0xf7 }; // SYNTHETIC: LEGO1 0x1001eed0 diff --git a/LEGO1/lego/legoomni/include/legoworldlist.h b/LEGO1/lego/legoomni/include/legoworldlist.h index 22cf5838..339f5393 100644 --- a/LEGO1/lego/legoomni/include/legoworldlist.h +++ b/LEGO1/lego/legoomni/include/legoworldlist.h @@ -26,8 +26,42 @@ class LegoWorldList : public MxPtrList { { 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 diff --git a/LEGO1/lego/legoomni/include/legoworldpresenter.h b/LEGO1/lego/legoomni/include/legoworldpresenter.h index be18baca..f3dbba30 100644 --- a/LEGO1/lego/legoomni/include/legoworldpresenter.h +++ b/LEGO1/lego/legoomni/include/legoworldpresenter.h @@ -31,6 +31,9 @@ class LegoWorldPresenter : public LegoEntityPresenter { virtual MxResult StartAction(MxStreamController* p_controller, MxDSAction* p_action) override; // vtable+0x3c virtual void VTable0x60(MxPresenter* p_presenter) override; // vtable+0x60 + // SYNTHETIC: LEGO1 0x10066750 + // LegoWorldPresenter::`scalar deleting destructor' + private: undefined4 m_unk0x50; }; diff --git a/LEGO1/lego/legoomni/include/motorcycle.h b/LEGO1/lego/legoomni/include/motocycle.h similarity index 62% rename from LEGO1/lego/legoomni/include/motorcycle.h rename to LEGO1/lego/legoomni/include/motocycle.h index af04b4ad..b4ccafd3 100644 --- a/LEGO1/lego/legoomni/include/motorcycle.h +++ b/LEGO1/lego/legoomni/include/motocycle.h @@ -1,14 +1,14 @@ -#ifndef MOTORCYCLE_H -#define MOTORCYCLE_H +#ifndef MOTOCYCLE_H +#define MOTOCYCLE_H #include "decomp.h" #include "islepathactor.h" // VTABLE: LEGO1 0x100d7090 // SIZE 0x16c -class Motorcycle : public IslePathActor { +class Motocycle : public IslePathActor { public: - Motorcycle(); + Motocycle(); // FUNCTION: LEGO1 0x10035840 inline virtual const char* ClassName() const override // vtable+0x0c @@ -20,13 +20,16 @@ class Motorcycle : public IslePathActor { // FUNCTION: LEGO1 0x10035850 inline virtual MxBool IsA(const char* p_name) const override // vtable+0x10 { - return !strcmp(p_name, Motorcycle::ClassName()) || IslePathActor::IsA(p_name); + return !strcmp(p_name, Motocycle::ClassName()) || IslePathActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100359d0 + // Motocycle::`scalar deleting destructor' + private: undefined m_unk0x160[4]; MxFloat m_unk0x164; undefined m_unk0x168[4]; }; -#endif // MOTORCYCLE_H +#endif // MOTOCYCLE_H diff --git a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h index 9d47947f..e0e64ae9 100644 --- a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h +++ b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h @@ -46,6 +46,9 @@ class MxBackgroundAudioManager : public MxCore { void LowerVolume(); void RaiseVolume(); + // SYNTHETIC: LEGO1 0x1007ec00 + // MxBackgroundAudioManager::`scalar deleting destructor' + private: void Init(); MxResult OpenMusic(MxAtomId& p_script); diff --git a/LEGO1/omni/include/mxcontrolpresenter.h b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h similarity index 92% rename from LEGO1/omni/include/mxcontrolpresenter.h rename to LEGO1/lego/legoomni/include/mxcontrolpresenter.h index 9779e45f..2db0a2e4 100644 --- a/LEGO1/omni/include/mxcontrolpresenter.h +++ b/LEGO1/lego/legoomni/include/mxcontrolpresenter.h @@ -33,7 +33,8 @@ class MxControlPresenter : public MxCompositePresenter { virtual MxBool HasTickleStatePassed(TickleState p_tickleState) override; // vtable+0x48 virtual void Enable(MxBool p_enable) override; // vtable+0x54 virtual MxBool VTable0x64(undefined4 p_undefined) override; // vtable+0x64 - virtual void VTable0x68(MxBool p_undefined); // vtable+0x68 + virtual void VTable0x68(MxBool p_unk0x50); // vtable+0x68 + virtual void VTable0x6c(undefined4); // vtable+0x6c private: MxBool FUN_10044270(undefined4, undefined4, undefined4*); diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h index ac87ffcc..fdfbf674 100644 --- a/LEGO1/lego/legoomni/include/mxtransitionmanager.h +++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h @@ -32,19 +32,22 @@ class MxTransitionManager : public MxCore { virtual MxResult GetDDrawSurfaceFromVideoManager(); // vtable+0x14 enum TransitionType { - NOT_TRANSITIONING, - NO_ANIMATION, - DISSOLVE, - PIXELATION, - SCREEN_WIPE, - WINDOWS, - BROKEN // Unknown what this is supposed to be, it locks the game up + e_notTransitioning = 0, + e_noAnimation, + e_dissolve, + e_pixelation, + e_screenWipe, + e_windows, + e_broken // Unknown what this is supposed to be, it locks the game up }; MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim); inline TransitionType GetTransitionType() { return m_transitionType; } + // SYNTHETIC: LEGO1 0x1004b9e0 + // MxTransitionManager::`scalar deleting destructor' + private: void EndTransition(MxBool p_notifyWorld); void TransitionNone(); diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 11bf6814..835a5b2e 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -30,6 +30,9 @@ class Pizza : public IsleActor { return !strcmp(p_name, Pizza::ClassName()) || IsleActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100380e0 + // Pizza::`scalar deleting destructor' + private: undefined4 m_unk0x78; undefined4 m_unk0x7c; diff --git a/LEGO1/lego/legoomni/include/pizzamissionstate.h b/LEGO1/lego/legoomni/include/pizzamissionstate.h index 85b8e4bb..76690a99 100644 --- a/LEGO1/lego/legoomni/include/pizzamissionstate.h +++ b/LEGO1/lego/legoomni/include/pizzamissionstate.h @@ -30,6 +30,9 @@ class PizzaMissionState : public LegoState { 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); diff --git a/LEGO1/lego/legoomni/include/pizzeria.h b/LEGO1/lego/legoomni/include/pizzeria.h index 0196d616..1c73ca58 100644 --- a/LEGO1/lego/legoomni/include/pizzeria.h +++ b/LEGO1/lego/legoomni/include/pizzeria.h @@ -19,6 +19,9 @@ class Pizzeria : public IsleActor { { return !strcmp(p_name, Pizzeria::ClassName()) || IsleActor::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1000e8d0 + // Pizzeria::`scalar deleting destructor' }; #endif // PIZZERIA_H diff --git a/LEGO1/lego/legoomni/include/pizzeriastate.h b/LEGO1/lego/legoomni/include/pizzeriastate.h index c27fcef0..188ee624 100644 --- a/LEGO1/lego/legoomni/include/pizzeriastate.h +++ b/LEGO1/lego/legoomni/include/pizzeriastate.h @@ -21,6 +21,9 @@ class PizzeriaState : public LegoState { { return !strcmp(p_name, PizzeriaState::ClassName()) || LegoState::IsA(p_name); } + + // 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 index 829c7e66..9d6bc1c7 100644 --- a/LEGO1/lego/legoomni/include/police.h +++ b/LEGO1/lego/legoomni/include/police.h @@ -25,6 +25,9 @@ class Police : public LegoWorld { { return !strcmp(p_name, Police::ClassName()) || LegoWorld::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1005e300 + // Police::`scalar deleting destructor' }; #endif // POLICE_H diff --git a/LEGO1/lego/legoomni/include/policeentity.h b/LEGO1/lego/legoomni/include/policeentity.h index 735cf0bc..cdb89af6 100644 --- a/LEGO1/lego/legoomni/include/policeentity.h +++ b/LEGO1/lego/legoomni/include/policeentity.h @@ -19,6 +19,9 @@ class PoliceEntity : public BuildingEntity { { 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 index 2638a393..be55ecae 100644 --- a/LEGO1/lego/legoomni/include/policestate.h +++ b/LEGO1/lego/legoomni/include/policestate.h @@ -1,6 +1,7 @@ #ifndef POLICESTATE_H #define POLICESTATE_H +#include "decomp.h" #include "legostate.h" // VTABLE: LEGO1 0x100d8af0 @@ -21,6 +22,13 @@ class PoliceState : public LegoState { { return !strcmp(p_name, PoliceState::ClassName()) || LegoState::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1005e920 + // PoliceState::`scalar deleting destructor' + +private: + undefined4 m_unk0x8; // 0x8 + undefined4 m_unk0xc; // 0xc }; #endif // POLICESTATE_H diff --git a/LEGO1/lego/legoomni/include/racecar.h b/LEGO1/lego/legoomni/include/racecar.h index b4a210e6..39005831 100644 --- a/LEGO1/lego/legoomni/include/racecar.h +++ b/LEGO1/lego/legoomni/include/racecar.h @@ -24,6 +24,9 @@ class RaceCar : public IslePathActor { return !strcmp(p_name, RaceCar::ClassName()) || IslePathActor::IsA(p_name); } + // 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 index a7359df8..20b1b4a6 100644 --- a/LEGO1/lego/legoomni/include/racestandsentity.h +++ b/LEGO1/lego/legoomni/include/racestandsentity.h @@ -5,6 +5,9 @@ // VTABLE: LEGO1 0x100d48a8 // SIZE 0x68 -class RaceStandsEntity : public BuildingEntity {}; +class RaceStandsEntity : public BuildingEntity { + // SYNTHETIC: LEGO1 0x1000f9e0 + // RaceStandsEntity::`scalar deleting destructor' +}; #endif // RACESTANDSENTITY_H diff --git a/LEGO1/lego/legoomni/include/racestate.h b/LEGO1/lego/legoomni/include/racestate.h index ef3cfa63..05760e32 100644 --- a/LEGO1/lego/legoomni/include/racestate.h +++ b/LEGO1/lego/legoomni/include/racestate.h @@ -32,6 +32,9 @@ class RaceState : public LegoState { 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); diff --git a/LEGO1/lego/legoomni/include/radio.h b/LEGO1/lego/legoomni/include/radio.h index 54aef25b..3d8da44b 100644 --- a/LEGO1/lego/legoomni/include/radio.h +++ b/LEGO1/lego/legoomni/include/radio.h @@ -23,6 +23,9 @@ class Radio : public MxCore { return !strcmp(p_name, Radio::ClassName()) || MxCore::IsA(p_name); } + // SYNTHETIC: LEGO1 0x1002c970 + // Radio::`scalar deleting destructor' + private: RadioState* m_state; // 0x08 MxBool m_unk0xc; // 0x0c diff --git a/LEGO1/lego/legoomni/include/radiostate.h b/LEGO1/lego/legoomni/include/radiostate.h index a5ea6035..1035a659 100644 --- a/LEGO1/lego/legoomni/include/radiostate.h +++ b/LEGO1/lego/legoomni/include/radiostate.h @@ -21,6 +21,9 @@ class RadioState : public LegoState { { return !strcmp(p_name, RadioState::ClassName()) || LegoState::IsA(p_name); } + + // SYNTHETIC: LEGO1 0x1002d020 + // RadioState::`scalar deleting destructor' }; #endif // RADIOSTATE_H diff --git a/LEGO1/lego/legoomni/include/registrationbook.h b/LEGO1/lego/legoomni/include/registrationbook.h index 3ae904c9..25e4b2d8 100644 --- a/LEGO1/lego/legoomni/include/registrationbook.h +++ b/LEGO1/lego/legoomni/include/registrationbook.h @@ -11,6 +11,7 @@ class RegistrationBook : public LegoWorld { virtual ~RegistrationBook() override; // vtable+0x0 virtual MxLong Notify(MxParam& p_param) override; // vtable+0x4 + virtual MxResult Tickle() override; // vtable+0x8 // FUNCTION: LEGO1 0x10076e10 inline virtual const char* ClassName() const override // vtable+0x0c @@ -24,6 +25,14 @@ class RegistrationBook : public LegoWorld { { return !strcmp(p_name, RegistrationBook::ClassName()) || LegoWorld::IsA(p_name); } + + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + virtual void VTable0x50() override; // vtable+0x50 + virtual MxBool VTable0x64() override; // vtable+0x64 + virtual void VTable0x68(MxBool p_add) override; // vtable+0x68 + + // 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 index c927863f..1e801aa3 100644 --- a/LEGO1/lego/legoomni/include/score.h +++ b/LEGO1/lego/legoomni/include/score.h @@ -31,8 +31,8 @@ class Score : public LegoWorld { // SYNTHETIC: LEGO1 0x100011e0 // Score::`scalar deleting destructor' - virtual MxResult Create(MxDSObject& p_dsObject) override; // vtable+18 - virtual void Stop() override; // vtable+50 + virtual MxResult Create(MxDSAction& p_dsAction) override; // vtable+18 + virtual void VTable0x50() override; // vtable+50 virtual MxBool VTable0x5c() override; // vtable+5c virtual MxBool VTable0x64() override; // vtable+64 virtual void VTable0x68(MxBool p_add) override; // vtable+68 diff --git a/LEGO1/lego/legoomni/include/scorestate.h b/LEGO1/lego/legoomni/include/scorestate.h index 21be3493..fde33e1a 100644 --- a/LEGO1/lego/legoomni/include/scorestate.h +++ b/LEGO1/lego/legoomni/include/scorestate.h @@ -26,6 +26,9 @@ class ScoreState : public LegoState { 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; }; diff --git a/LEGO1/lego/legoomni/include/skateboard.h b/LEGO1/lego/legoomni/include/skateboard.h index 171705c4..06adc8cb 100644 --- a/LEGO1/lego/legoomni/include/skateboard.h +++ b/LEGO1/lego/legoomni/include/skateboard.h @@ -23,6 +23,9 @@ class SkateBoard : public IslePathActor { return !strcmp(p_name, SkateBoard::ClassName()) || IslePathActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x1000ff60 + // SkateBoard::`scalar deleting destructor' + private: // TODO: SkateBoard types undefined m_unk0x160; diff --git a/LEGO1/lego/legoomni/include/towtrack.h b/LEGO1/lego/legoomni/include/towtrack.h index 1cc7e6af..39c4f630 100644 --- a/LEGO1/lego/legoomni/include/towtrack.h +++ b/LEGO1/lego/legoomni/include/towtrack.h @@ -23,6 +23,9 @@ class TowTrack : public IslePathActor { return !strcmp(p_name, TowTrack::ClassName()) || IslePathActor::IsA(p_name); } + // SYNTHETIC: LEGO1 0x1004c950 + // TowTrack::`scalar deleting destructor' + private: // TODO: TowTrack field types undefined m_unk0x154[4]; diff --git a/LEGO1/lego/legoomni/include/towtrackmissionstate.h b/LEGO1/lego/legoomni/include/towtrackmissionstate.h index c0ad3145..be2e2689 100644 --- a/LEGO1/lego/legoomni/include/towtrackmissionstate.h +++ b/LEGO1/lego/legoomni/include/towtrackmissionstate.h @@ -41,6 +41,9 @@ class TowTrackMissionState : public LegoState { } } + // SYNTHETIC: LEGO1 0x1004e060 + // TowTrackMissionState::`scalar deleting destructor' + protected: undefined4 m_unk0x08; // 0x08 undefined4 m_unk0x0c; // 0x0c diff --git a/LEGO1/lego/legoomni/src/act1/act1state.cpp b/LEGO1/lego/legoomni/src/act1/act1state.cpp index c013b502..17f09277 100644 --- a/LEGO1/lego/legoomni/src/act1/act1state.cpp +++ b/LEGO1/lego/legoomni/src/act1/act1state.cpp @@ -2,6 +2,19 @@ // STUB: LEGO1 0x100334b0 Act1State::Act1State() +{ + // TODO + m_unk0x1e = 0; + m_unk0x18 = 1; + m_unk0x20 = 0; + m_unk0x1f = 0; + m_unk0x21 = TRUE; + m_unk0x22 = 0; + m_unk0x1c = 1; +} + +// STUB: LEGO1 0x10034d00 +void Act1State::FUN_10034d00() { // TODO } diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index 9fe20941..74f8c146 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -77,13 +77,13 @@ void MxBackgroundAudioManager::DestroyMusic() MxResult MxBackgroundAudioManager::Tickle() { switch (m_unk0x13c) { - case MxPresenter::TickleState_Starting: + case MxPresenter::e_starting: FadeInOrFadeOut(); return SUCCESS; - case MxPresenter::TickleState_Streaming: + case MxPresenter::e_streaming: FUN_1007ee70(); return SUCCESS; - case MxPresenter::TickleState_Repeating: + case MxPresenter::e_repeating: FUN_1007ef40(); return SUCCESS; default: diff --git a/LEGO1/lego/legoomni/src/build/buildingentity.cpp b/LEGO1/lego/legoomni/src/build/buildingentity.cpp index 37a09f2f..37b0a8d9 100644 --- a/LEGO1/lego/legoomni/src/build/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/helicopter.cpp b/LEGO1/lego/legoomni/src/build/helicopter.cpp index f4220183..9f5cc843 100644 --- a/LEGO1/lego/legoomni/src/build/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" @@ -27,9 +28,9 @@ Helicopter::~Helicopter() } // FUNCTION: LEGO1 0x100032c0 -MxResult Helicopter::Create(MxDSObject& p_dsObject) +MxResult Helicopter::Create(MxDSAction& p_dsAction) { - MxResult result = IslePathActor::Create(p_dsObject); + MxResult result = IslePathActor::Create(p_dsAction); LegoWorld* world = GetCurrentWorld(); SetWorld(world); if (world->IsA("Act3")) { @@ -99,10 +100,10 @@ MxU32 Helicopter::VTable0xcc() AnimationManager()->FUN_10064670(FALSE); VTable0xe8(0x29, TRUE, 7); ((Isle*) GetCurrentWorld())->SetUnknown13c(0x3c); - FUN_10015820(1, 0); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, TRUE); + 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,7 +113,7 @@ MxU32 Helicopter::VTable0xcc() break; } VTable0xe0(); - InvokeAction(ExtraActionType_start, m_script, 0x15, NULL); + InvokeAction(Extra::ActionType::e_start, m_script, 0x15, NULL); GetCurrentAction().SetObjectId(-1); ControlManager()->Register(this); return 1; @@ -139,7 +140,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) case 0x17: if (*g_act3Script == script) { ((Act3*) GetCurrentWorld())->SetUnkown4270(2); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, FALSE); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); } else if (m_state->GetUnkown8() != 0) break; @@ -155,7 +156,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) state->SetUnknown18(4); m_state->SetUnknown8(1); m_world->FUN_1001fc80(this); - InvokeAction(ExtraActionType_start, script, 0x20, NULL); + InvokeAction(Extra::ActionType::e_start, script, 0x20, NULL); SetUnknownDC(0); } ret = 1; @@ -167,7 +168,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) if (m_state->GetUnkown8() == 2) { m_state->SetUnknown8(3); m_world->FUN_1001fc80(this); - InvokeAction(ExtraActionType_start, script, 0x21, NULL); + InvokeAction(Extra::ActionType::e_start, script, 0x21, NULL); SetUnknownDC(4); } ret = 1; @@ -181,15 +182,15 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) if (*g_act3Script != script) break; if (m_world && m_world->GetCamera()) { - Vector3Data loc, dir, lookat; - loc.CopyFrom(m_world->GetCamera()->FUN_100127f0()); - dir.CopyFrom(m_world->GetCamera()->FUN_100128a0()); + Mx3DPointFloat loc, dir, lookat; + loc.CopyFrom(m_world->GetCamera()->GetWorldLocation()); + dir.CopyFrom(m_world->GetCamera()->GetWorldDirection()); lookat = dir; float scale = 3; lookat.Mul(scale); lookat.Add(&loc); - Vector3Data v68, v7c, v90(0, 1, 0), va4; - v68.CopyFrom(m_world->GetCamera()->FUN_10012740()); + Mx3DPointFloat v68, v7c, v90(0, 1, 0), va4; + v68.CopyFrom(m_world->GetCamera()->GetWorldUp()); va4.EqualsCross(v68, dir); v7c.EqualsCross(va4, v90); if (ret) @@ -203,7 +204,7 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) case 0x1c: if (GameState()->GetUnknown10() == 0) { ((Isle*) GetCurrentWorld())->SetUnknown13c(2); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 50, FALSE, FALSE); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); VTable0xe4(); } ret = 1; @@ -219,6 +220,8 @@ MxU32 Helicopter::VTable0xd4(MxType17NotificationParam& p_param) // FUNCTION: LEGO1 0x10003c20 MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) { + MxU32 ret = 0; + switch (m_state->GetUnkown8()) { case 1: { if (GameState()->GetUnknown10() == 0) { @@ -227,44 +230,54 @@ MxU32 Helicopter::VTable0xd8(MxType18NotificationParam& p_param) } else VTable0xe8(0x31, TRUE, 7); + m_state->SetUnknown8(2); - Matrix4Data mat; - mat.SetIdentity(); - Matrix4 mat2 = mat.GetMatrix(); + + MxMatrix matrix; + matrix.SetIdentity(); + float s = sin(0.5235987901687622); // PI / 6, 30 deg float c = cos(0.5235987901687622); // PI / 6, 30 deg + + float matrixCopy[4][4]; + memcpy(matrixCopy, matrix.GetData(), sizeof(matrixCopy)); for (MxS32 i = 0; i < 4; i++) { - mat.GetMatrix()[i][1] = mat2[i][1] * c - mat2[i][2] * s; - mat.GetMatrix()[i][2] = mat2[i][2] * c + mat2[i][1] * s; + matrix.GetData()[i][1] = matrixCopy[i][1] * c - matrixCopy[i][2] * s; + matrix.GetData()[i][2] = matrixCopy[i][2] * c + matrixCopy[i][1] * s; } - Vector3Impl at(mat.GetMatrix()[3]), dir(mat.GetMatrix()[2]), up(mat.GetMatrix()[1]); + + Vector3 at(matrix[3]), dir(matrix[2]), up(matrix[1]); m_world->GetCamera()->SetWorldTransform(at, dir, up); FUN_10010c30(); + ret = 1; break; } case 3: { - Matrix4Data mat; - mat.SetIdentity(); - Vector3Impl at(mat.GetMatrix()[3]), dir(mat.GetMatrix()[2]), up(mat.GetMatrix()[1]); + MxMatrix matrix; + matrix.SetIdentity(); + + Vector3 at(matrix[3]), dir(matrix[2]), up(matrix[1]); at[1] = 1.25; m_world->GetCamera()->SetWorldTransform(at, dir, up); + if (GameState()->GetUnknown10() == 0) { ((Act1State*) GameState()->GetState("Act1State"))->SetUnknown18(0); VTable0xe8(0x29, TRUE, 7); } else VTable0xe8(0x30, TRUE, 7); + m_state->SetUnknown8(0); + ret = 1; break; } - default: - return 0; } - return 1; + + return ret; } // FUNCTION: LEGO1 0x10003e90 -void Helicopter::VTable0x74(Matrix4Impl& p_transform) +void Helicopter::VTable0x74(Matrix4& p_transform) { if (m_unk0xea != 0) { m_roi->FUN_100a46b0(p_transform); @@ -295,13 +308,13 @@ void Helicopter::VTable0x70(float p_float) f2 = 0; if (1.0f < f2) f2 = 1.0f; - Vector3Impl v(m_unk0x160.GetMatrix()[3]); - Matrix4Data mat; - Vector3Impl v2(m_unk0x1a8.GetMatrix()[3]); - float* loc = m_unk0x1a8.GetMatrix()[3]; + Vector3 v(m_unk0x160[3]); + MxMatrix mat; + Vector3 v2(m_unk0x1a8[3]); + float* loc = m_unk0x1a8[3]; mat.SetIdentity(); float fa[4]; - Vector4Impl v3(fa); + Vector4 v3(fa); if (m_unk0x1f4.FUN_100040a0(v3, f2) == SUCCESS) { mat.FromQuaternion(v3); } @@ -322,18 +335,17 @@ void Helicopter::VTable0x70(float p_float) } // FUNCTION: LEGO1 0x100040a0 -MxResult HelicopterSubclass::FUN_100040a0(Vector4Impl& p_v, float p_f) +MxResult HelicopterSubclass::FUN_100040a0(Vector4& p_v, float p_f) { MxU32 state = m_unk0x30; if (state == 1) { - p_v.EqualsImpl(m_unk0x0.GetVector().elements); + p_v.EqualsImpl(m_unk0x0.GetData()); p_v[3] = acos(p_v[3]) * (1 - p_f) * 2.0; return p_v.NormalizeQuaternion(); } else if (state == 2) { - p_v.EqualsImpl(m_unk0x18.GetVector().elements); + p_v.EqualsImpl(m_unk0x18.GetData()); p_v[3] = acos(p_v[3]) * p_f * 2.0; - p_v.NormalizeQuaternion(); return p_v.NormalizeQuaternion(); } else if (state == 3) { diff --git a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index 34652509..3e6c4d7b 100644 --- a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -26,3 +26,9 @@ void LegoBuildingManager::Init() { // TODO } + +// STUB: LEGO1 0x1002fa00 +void LegoBuildingManager::FUN_1002fa00() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/common/gifmanager.cpp b/LEGO1/lego/legoomni/src/common/gifmanager.cpp index 0fc25b96..cd485b11 100644 --- a/LEGO1/lego/legoomni/src/common/gifmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/gifmanager.cpp @@ -1,25 +1,61 @@ #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); +DECOMP_SIZE_ASSERT(GifMap, 0x10); +DECOMP_SIZE_ASSERT(GifManagerBase, 0x18); +DECOMP_SIZE_ASSERT(GifManager, 0x24); -GifMapEntry* g_unk0x100f0100; - -// FUNCTION: LEGO1 0x10001cc0 -GifMapEntry* GifMap::FindNode(const char*& p_string) +// FUNCTION: LEGO1 0x10065c00 +GifData::~GifData() { - 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; + if (m_name) { + delete[] m_name; + m_name = NULL; + } + + if (m_palette) { + m_palette->Release(); + m_palette = NULL; + } + + if (m_surface) { + m_surface->Release(); + m_surface = NULL; + } + + if (m_texture) { + m_texture->Release(); + m_texture = NULL; + } +} + +// FUNCTION: LEGO1 0x10099870 +GifManager::~GifManager() +{ +} + +// FUNCTION: LEGO1 0x10099cc0 +void GifManager::FUN_10099cc0(GifData* p_data) +{ + if (p_data == NULL) + return; + +#ifdef COMPAT_MODE + GifList::iterator it; + for (it = m_list.begin(); it != m_list.end(); it++) { +#else + for (GifList::iterator it = m_list.begin(); it != m_list.end(); it++) { +#endif + if (*it == p_data) { + // TODO: This is wrong, but what is at +0xc on the iterator? + *it = NULL; + + if (p_data->m_texture->Release() == TRUE) { + delete p_data; + m_list.erase(it); + } + + return; + } } - return ret; } diff --git a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp index 953aef36..1407de1b 100644 --- a/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/legoactioncontrolpresenter.cpp @@ -19,8 +19,7 @@ void LegoActionControlPresenter::ReadyTickle() if (chunk) { ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); m_subscriber->DestroyChunk(chunk); if (m_compositePresenter) { @@ -39,9 +38,15 @@ void LegoActionControlPresenter::RepeatingTickle() ParseExtra(); } - InvokeAction(m_unk0x50, MxAtomId(m_unk0x54.GetData(), LookupMode_LowerCase2), m_unk0x64, NULL); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; +#ifdef COMPAT_MODE + { + MxAtomId atom(m_unk0x54.GetData(), e_lowerCase2); + InvokeAction(m_unk0x50, atom, m_unk0x64, NULL); + } +#else + InvokeAction(m_unk0x50, MxAtomId(m_unk0x54.GetData(), e_lowerCase2), m_unk0x64, NULL); +#endif + ProgressTickleState(e_done); } } @@ -87,11 +92,11 @@ void LegoActionControlPresenter::ParseExtra() char output[1024]; if (KeyValueStringParse(output, g_strACTION, buf)) { m_unk0x50 = MatchActionString(strtok(output, g_parseExtraTokens)); - if (m_unk0x50 != ExtraActionType_exit) { + if (m_unk0x50 != Extra::ActionType::e_exit) { MakeSourceName(buf, strtok(NULL, g_parseExtraTokens)); m_unk0x54 = buf; m_unk0x54.ToLowerCase(); - if (m_unk0x50 != ExtraActionType_run) { + if (m_unk0x50 != Extra::ActionType::e_run) { m_unk0x64 = atoi(strtok(NULL, g_parseExtraTokens)); } } diff --git a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp index e682356b..5d594eaa 100644 --- a/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp +++ b/LEGO1/lego/legoomni/src/common/legobackgroundcolor.cpp @@ -7,8 +7,16 @@ DECOMP_SIZE_ASSERT(LegoBackgroundColor, 0x30) -const char* g_delimiter = "\t"; +// GLOBAL: LEGO1 0x100f3fb0 +// STRING: LEGO1 0x100f3a18 +const char* g_delimiter = " \t"; + +// GLOBAL: LEGO1 0x100f3fb4 +// STRING: LEGO1 0x100f3bf0 const char* g_set = "set"; + +// GLOBAL: LEGO1 0x100f3fb8 +// STRING: LEGO1 0x100f0cdc const char* g_reset = "reset"; // FUNCTION: LEGO1 0x1003bfb0 diff --git a/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp b/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp index 110a88d0..b10b285f 100644 --- a/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp +++ b/LEGO1/lego/legoomni/src/common/legofullscreenmovie.cpp @@ -7,10 +7,12 @@ DECOMP_SIZE_ASSERT(LegoFullScreenMovie, 0x24) -// GLOBAL: LEGO1 0x100f3be8 +// GLOBAL: LEGO1 0x100f3fbc +// STRING: LEGO1 0x100f3be8 const char* g_strEnable = "enable"; -// GLOBAL: LEGO1 0x100f3bf4 +// GLOBAL: LEGO1 0x100f3fc0 +// STRING: LEGO1 0x100f3bf4 const char* g_strDisable = "disable"; // FUNCTION: LEGO1 0x1003c500 @@ -29,7 +31,6 @@ void LegoFullScreenMovie::SetValue(const char* p_option) LegoVideoManager* videomanager = VideoManager(); if (videomanager) { - if (!strcmp(m_value.GetData(), g_strEnable)) { videomanager->EnableFullScreenMovie(TRUE); return; diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index a081248c..0bb0b066 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -1,9 +1,13 @@ #include "legogamestate.h" #include "infocenterstate.h" +#include "legoanimationmanager.h" #include "legoomni.h" #include "legostate.h" #include "legostream.h" +#include "legoutil.h" +#include "legovideomanager.h" +#include "mxbackgroundaudiomanager.h" #include "mxobjectfactory.h" #include "mxstring.h" #include "mxvariabletable.h" @@ -15,14 +19,17 @@ // There may be other members that come after. DECOMP_SIZE_ASSERT(LegoGameState, 0x430) -// GLOBAL: LEGO1 0x100f3e24 -const char* g_historyGSI = "History.gsi"; +// GLOBAL: LEGO1 0x100f3e40 +// STRING: LEGO1 0x100f3e3c +const char* g_fileExtensionGS = ".GS"; -// GLOBAL: LEGO1 0x100f3e30 +// GLOBAL: LEGO1 0x100f3e44 +// STRING: LEGO1 0x100f3e30 const char* g_playersGSI = "Players.gsi"; -// GLOBAL: LEGO1 0x100f3e40 -const char* g_fileExtensionGS = ".GS"; +// GLOBAL: LEGO1 0x100f3e48 +// STRING: LEGO1 0x100f3e24 +const char* g_historyGSI = "History.gsi"; // GLOBAL: LEGO1 0x100f3e58 ColorStringStruct g_colorSaveData[43] = { @@ -53,7 +60,15 @@ LegoGameState::LegoGameState() // TODO SetROIHandlerFunction(); - m_stateCount = 0; + this->m_stateCount = 0; + this->m_unk0xc = 0; + this->m_savePath = NULL; + this->m_unk0x424 = 0; + this->m_prevArea = 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); @@ -85,12 +100,19 @@ LegoGameState::~LegoGameState() delete[] m_savePath; } +// STUB: LEGO1 0x10039780 +void LegoGameState::FUN_10039780(MxU8) +{ + // TODO +} + // FUNCTION: LEGO1 0x10039980 MxResult LegoGameState::Save(MxULong p_slot) { MxResult result; InfocenterState* infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); - if (!infocenterState || infocenterState->GetInfocenterBufferElement(0) == 0) + + if (!infocenterState || infocenterState->GetInfocenterBufferElement(0) == NULL) result = SUCCESS; else { result = FAILURE; @@ -98,7 +120,7 @@ MxResult LegoGameState::Save(MxULong p_slot) MxString savePath; GetFileSavePath(&savePath, p_slot); LegoFileStream fileStream; - if (fileStream.Open(savePath.GetData(), LegoStream::WriteBit) != FAILURE) { + if (fileStream.Open(savePath.GetData(), LegoStream::c_writeBit) != FAILURE) { MxU32 maybeVersion = 0x1000C; fileStream.Write(&maybeVersion, 4); fileStream.Write(&m_unk0x24, 2); @@ -164,7 +186,7 @@ void LegoGameState::GetFileSavePath(MxString* p_outPath, MxULong p_slotn) strcpy(path, m_savePath); // Slot: "G0", "G1", ... - strcat(path, "G"); + strcat(path, "\\G"); baseForSlot[0] += p_slotn; strcat(path, baseForSlot); @@ -186,9 +208,30 @@ void LegoGameState::FUN_1003a720(MxU32) } // STUB: LEGO1 0x1003b060 -void LegoGameState::HandleAction(MxU32) +void LegoGameState::HandleAction(MxU32 p_area) { - // TODO + m_prevArea = p_area; + BackgroundAudioManager()->Stop(); + AnimationManager()->FUN_1005ef10(); + VideoManager()->SetUnk0x554(0); + + MxAtomId* script = g_isleScript; + switch (p_area) { + case 1: + break; + case 2: + VideoManager()->SetUnk0x554(1); + script = g_infomainScript; + break; + case 3: + VideoManager()->SetUnk0x554(1); + script = g_infodoorScript; + break; + + // TODO: implement other cases + } + + InvokeAction(Extra::ActionType::e_opendisk, *script, 0, NULL); } // FUNCTION: LEGO1 0x1003bac0 @@ -282,7 +325,7 @@ void LegoGameState::SerializeScoreHistory(MxS16 p_flags) savePath += "\\"; savePath += g_historyGSI; - if (p_flags == LegoStream::WriteBit) { + if (p_flags == LegoStream::c_writeBit) { m_unk0xa6.WriteScoreHistory(); } diff --git a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp index ff52bad1..8e3d7526 100644 --- a/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp +++ b/LEGO1/lego/legoomni/src/common/legoobjectfactory.cpp @@ -68,7 +68,7 @@ #include "doors.h" #include "jetski.h" #include "legoanimmmpresenter.h" -#include "motorcycle.h" +#include "motocycle.h" #include "racecar.h" #include "towtrack.h" #include "towtrackmissionstate.h" @@ -106,7 +106,7 @@ // FUNCTION: LEGO1 0x10006e40 LegoObjectFactory::LegoObjectFactory() { -#define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact); +#define X(V) this->m_id##V = MxAtomId(#V, e_exact); FOR_LEGOOBJECTFACTORY_OBJECTS(X) #undef X } @@ -114,7 +114,7 @@ LegoObjectFactory::LegoObjectFactory() // FUNCTION: LEGO1 0x10009a90 MxCore* LegoObjectFactory::Create(const char* p_name) { - MxAtomId atom(p_name, LookupMode_Exact); + MxAtomId atom(p_name, e_exact); #define X(V) \ if (this->m_id##V == atom) { \ diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 4b93d8d7..193f5c8a 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -18,6 +18,12 @@ void LegoPlantManager::Init() // TODO } +// STUB: LEGO1 0x10026360 +void LegoPlantManager::FUN_10026360(undefined4 p_world) +{ + // TODO +} + // STUB: LEGO1 0x10026e00 MxResult LegoPlantManager::Tickle() { diff --git a/LEGO1/lego/legoomni/src/common/legostream.cpp b/LEGO1/lego/legoomni/src/common/legostream.cpp index 0cfe0a51..f54d5982 100644 --- a/LEGO1/lego/legoomni/src/common/legostream.cpp +++ b/LEGO1/lego/legoomni/src/common/legostream.cpp @@ -10,6 +10,7 @@ // the text "END_OF_VARIABLES" in it. // TODO: make g_endOfVariables reference the actual end of the variable array. // GLOBAL: LEGO1 0x100f3e50 +// STRING: LEGO1 0x100f3e00 const char* g_endOfVariables = "END_OF_VARIABLES"; // Very likely but not certain sizes. @@ -166,18 +167,18 @@ MxResult LegoFileStream::Open(const char* p_filename, OpenFlags p_mode) fclose(m_hFile); modeString[0] = '\0'; - if (p_mode & ReadBit) { + if (p_mode & c_readBit) { m_mode = LEGOSTREAM_MODE_READ; strcat(modeString, "r"); } - if (p_mode & WriteBit) { + if (p_mode & c_writeBit) { if (m_mode != LEGOSTREAM_MODE_READ) m_mode = LEGOSTREAM_MODE_WRITE; strcat(modeString, "w"); } - if ((p_mode & 4) != 0) + if ((p_mode & c_binaryBit) != 0) strcat(modeString, "b"); else strcat(modeString, "t"); diff --git a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp index 2e4d1804..a6e7e135 100644 --- a/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp +++ b/LEGO1/lego/legoomni/src/common/legounksavedatawriter.cpp @@ -47,3 +47,9 @@ MxResult LegoUnkSaveDataWriter::WriteSaveData3(LegoStream* p_stream) } return result; } + +// STUB: LEGO1 0x10083db0 +void LegoUnkSaveDataWriter::FUN_10083db0(LegoROI* p_roi) +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/common/legoutil.cpp b/LEGO1/lego/legoomni/src/common/legoutil.cpp index 4941d968..fb207f50 100644 --- a/LEGO1/lego/legoomni/src/common/legoutil.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutil.cpp @@ -11,30 +11,30 @@ #include // FUNCTION: LEGO1 0x1003e300 -ExtraActionType MatchActionString(const char* p_str) +Extra::ActionType MatchActionString(const char* p_str) { - ExtraActionType result = ExtraActionType_unknown; + Extra::ActionType result = Extra::ActionType::e_unknown; if (!strcmpi("openram", p_str)) - result = ExtraActionType_openram; + result = Extra::ActionType::e_openram; else if (!strcmpi("opendisk", p_str)) - result = ExtraActionType_opendisk; + result = Extra::ActionType::e_opendisk; else if (!strcmpi("close", p_str)) - result = ExtraActionType_close; + result = Extra::ActionType::e_close; else if (!strcmpi("start", p_str)) - result = ExtraActionType_start; + result = Extra::ActionType::e_start; else if (!strcmpi("stop", p_str)) - result = ExtraActionType_stop; + result = Extra::ActionType::e_stop; else if (!strcmpi("run", p_str)) - result = ExtraActionType_run; + result = Extra::ActionType::e_run; else if (!strcmpi("exit", p_str)) - result = ExtraActionType_exit; + result = Extra::ActionType::e_exit; else if (!strcmpi("enable", p_str)) - result = ExtraActionType_enable; + result = Extra::ActionType::e_enable; else if (!strcmpi("disable", p_str)) - result = ExtraActionType_disable; + result = Extra::ActionType::e_disable; else if (!strcmpi("notify", p_str)) - result = ExtraActionType_notify; + result = Extra::ActionType::e_notify; return result; } @@ -43,54 +43,54 @@ MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_enti void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender); // FUNCTION: LEGO1 0x1003e430 -void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender) +void InvokeAction(Extra::ActionType p_actionId, MxAtomId& p_pAtom, int p_targetEntityId, LegoEntity* p_sender) { MxDSAction action; action.SetAtomId(p_pAtom); action.SetObjectId(p_targetEntityId); switch (p_actionId) { - case ExtraActionType_opendisk: + case Extra::ActionType::e_opendisk: if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { - Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_DiskStream); + Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_diskStream); Start(&action); } break; - case ExtraActionType_openram: + case Extra::ActionType::e_openram: if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_RAMStream); Start(&action); } break; - case ExtraActionType_close: + case Extra::ActionType::e_close: action.SetUnknown24(-2); DeleteObject(action); Streamer()->Close(p_pAtom.GetInternal()); break; - case ExtraActionType_start: + case Extra::ActionType::e_start: if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { Start(&action); } break; - case ExtraActionType_stop: + case Extra::ActionType::e_stop: action.SetUnknown24(-2); if (!FUN_1003ee00(p_pAtom, p_targetEntityId)) { DeleteObject(action); } break; - case ExtraActionType_run: + case Extra::ActionType::e_run: _spawnl(0, "\\lego\\sources\\main\\main.exe", "\\lego\\sources\\main\\main.exe", "/script", &p_pAtom, 0); break; - case ExtraActionType_exit: + case Extra::ActionType::e_exit: Lego()->SetExit(TRUE); break; - case ExtraActionType_enable: + case Extra::ActionType::e_enable: CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId); break; - case ExtraActionType_disable: + case Extra::ActionType::e_disable: CheckIfEntityExists(FALSE, p_pAtom.GetInternal(), p_targetEntityId); break; - case ExtraActionType_notify: + case Extra::ActionType::e_notify: NotifyEntity(p_pAtom.GetInternal(), p_targetEntityId, p_sender); break; } @@ -99,8 +99,7 @@ void InvokeAction(ExtraActionType p_actionId, MxAtomId& p_pAtom, int p_targetEnt // FUNCTION: LEGO1 0x1003e670 MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId) { - LegoWorld* world = - (LegoWorld*) FindEntityByAtomIdOrEntityId(MxAtomId(p_filename, LookupMode_LowerCase2), p_entityId); + LegoWorld* world = (LegoWorld*) FindEntityByAtomIdOrEntityId(MxAtomId(p_filename, e_lowerCase2), p_entityId); if (world) { world->VTable0x68(p_enable); return TRUE; diff --git a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp index 2a15d445..d3971150 100644 --- a/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp +++ b/LEGO1/lego/legoomni/src/common/mxcompositemediapresenter.cpp @@ -16,13 +16,13 @@ MxCompositeMediaPresenter::MxCompositeMediaPresenter() { m_unk0x4c = 0; m_unk0x4e = FALSE; - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); } // FUNCTION: LEGO1 0x10074020 MxCompositeMediaPresenter::~MxCompositeMediaPresenter() { - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); } // FUNCTION: LEGO1 0x10074090 @@ -55,12 +55,12 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller if (presenter && presenter->AddToManager() == SUCCESS) { presenter->SetCompositePresenter(this); if (presenter->StartAction(p_controller, action) == SUCCESS) { - presenter->SetTickleState(TickleState_Idle); + presenter->SetTickleState(e_idle); if (presenter->IsA("MxVideoPresenter")) - VideoManager()->RemovePresenter(*presenter); + VideoManager()->UnregisterPresenter(*presenter); else if (presenter->IsA("MxAudioPresenter")) - SoundManager()->RemovePresenter(*presenter); + SoundManager()->UnregisterPresenter(*presenter); success = TRUE; } @@ -75,7 +75,7 @@ MxResult MxCompositeMediaPresenter::StartAction(MxStreamController* p_controller } if (!m_compositePresenter) { - SetTickleState(TickleState_Ready); + SetTickleState(e_ready); MxLong time = Timer()->GetTime(); m_action->SetUnknown90(time); } @@ -93,10 +93,10 @@ void MxCompositeMediaPresenter::StartingTickle() if (!m_unk0x4e) { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { - if ((*it)->GetCurrentTickleState() < TickleState_Streaming) { + if ((*it)->GetCurrentTickleState() < e_streaming) { (*it)->Tickle(); - if ((*it)->GetCurrentTickleState() == TickleState_Streaming || + if ((*it)->GetCurrentTickleState() == e_streaming || ((*it)->GetAction() && (*it)->GetAction()->GetStartTime())) m_unk0x4c++; } @@ -115,16 +115,15 @@ void MxCompositeMediaPresenter::StartingTickle() else { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { if (!(*it)->GetAction()->GetStartTime() && ((MxMediaPresenter*) *it)->CurrentChunk() && - !((*it)->GetAction()->GetFlags() & MxDSAction::Flag_Bit9)) { + !((*it)->GetAction()->GetFlags() & MxDSAction::c_bit9)) { (*it)->Tickle(); - (*it)->GetAction()->SetFlags((*it)->GetAction()->GetFlags() | MxDSAction::Flag_Bit9); + (*it)->GetAction()->SetFlags((*it)->GetAction()->GetFlags() | MxDSAction::c_bit9); m_unk0x4c--; } } if (!m_unk0x4c) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); MxLong time = Timer()->GetTime(); m_action->SetUnknown90(time); } @@ -137,16 +136,15 @@ MxResult MxCompositeMediaPresenter::Tickle() MxAutoLocker lock(&m_criticalSection); switch (m_currentTickleState) { - case TickleState_Ready: - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; - case TickleState_Starting: + case e_ready: + ProgressTickleState(e_starting); + case e_starting: StartingTickle(); break; - case TickleState_Streaming: - case TickleState_Repeating: - case TickleState_unk5: - case TickleState_Done: { + case e_streaming: + case e_repeating: + case e_unk5: + case e_done: { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) (*it)->Tickle(); break; @@ -163,7 +161,7 @@ MxResult MxCompositeMediaPresenter::PutData() { MxAutoLocker lock(&m_criticalSection); - if (m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_Done) { + if (m_currentTickleState >= e_streaming && m_currentTickleState <= e_done) { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) (*it)->PutData(); } diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index f3c70c50..481bd9c5 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -12,6 +12,12 @@ LegoControlManager::~LegoControlManager() // TODO } +// STUB: LEGO1 0x10028df0 +void LegoControlManager::FUN_10028df0(MxPresenterList* p_presenterList) +{ + // TODO +} + // STUB: LEGO1 0x10028e10 void LegoControlManager::Register(MxCore* p_listener) { @@ -24,6 +30,11 @@ void LegoControlManager::Unregister(MxCore* p_listener) // TODO } +// STUB: LEGO1 0x100293c0 +void LegoControlManager::FUN_100293c0(undefined4, const char*, undefined2) +{ +} + // STUB: LEGO1 0x10029600 MxResult LegoControlManager::Tickle() { diff --git a/LEGO1/omni/src/control/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp similarity index 52% rename from LEGO1/omni/src/control/mxcontrolpresenter.cpp rename to LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp index 2c7fb81d..7a204a78 100644 --- a/LEGO1/omni/src/control/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp @@ -1,6 +1,7 @@ #include "mxcontrolpresenter.h" #include "mxticklemanager.h" +#include "mxutil.h" DECOMP_SIZE_ASSERT(MxControlPresenter, 0x5c) @@ -28,9 +29,9 @@ MxBool MxControlPresenter::VTable0x64(undefined4 p_undefined) } // FUNCTION: LEGO1 0x10043ff0 -void MxControlPresenter::VTable0x68(MxBool p_undefined) +void MxControlPresenter::VTable0x68(MxBool p_unk0x50) { - m_unk0x50 = p_undefined; + m_unk0x50 = p_unk0x50; } // FUNCTION: LEGO1 0x10044110 @@ -47,11 +48,28 @@ MxResult MxControlPresenter::AddToManager() return SUCCESS; } -// STUB: LEGO1 0x10044190 -MxResult MxControlPresenter::StartAction(MxStreamController*, MxDSAction*) +// FUNCTION: LEGO1 0x10044190 +MxResult MxControlPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) { - // TODO - return SUCCESS; + MxResult result = MxCompositePresenter::StartAction(p_controller, p_action); + + FUN_100b7220(m_action, MxDSAction::c_world | MxDSAction::c_looping, TRUE); + ParseExtra(); + + MxS16 i = 0; + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + (*it)->Enable((m_unk0x4c != 3 || m_unk0x4e) && IsEnabled() ? m_unk0x4e == i : FALSE); + i++; + } + + if (m_unk0x4c == 3) { + MxDSAction* action = (*m_list.begin())->GetAction(); + action->SetFlags(action->GetFlags() | MxDSAction::c_bit11); + } + + TickleManager()->RegisterClient(this, 200); + + return result; } // FUNCTION: LEGO1 0x10044260 @@ -78,7 +96,7 @@ MxBool MxControlPresenter::FUN_10044480(undefined4, undefined4*) } // STUB: LEGO1 0x10044540 -void MxControlPresenter::FUN_10044540(undefined2) +void MxControlPresenter::VTable0x6c(undefined4) { // TODO } @@ -88,9 +106,7 @@ void MxControlPresenter::ReadyTickle() { MxPresenter::ParseExtra(); TickleManager()->UnregisterClient(this); - - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); } // STUB: LEGO1 0x10044640 @@ -99,15 +115,34 @@ void MxControlPresenter::ParseExtra() // TODO } -// STUB: LEGO1 0x10044820 +// FUNCTION: LEGO1 0x10044820 void MxControlPresenter::Enable(MxBool p_enable) { - // TODO + if (MxPresenter::IsEnabled() != p_enable) { + MxPresenter::Enable(p_enable); + + MxS16 i = 0; + for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { + if (i == m_unk0x4e) { + (*it)->Enable((m_unk0x4c != 3 || i != 0) ? p_enable : 0); + break; + } + + i++; + } + + if (!p_enable) { + m_unk0x4e = 0; + } + } } -// STUB: LEGO1 0x100448a0 +// FUNCTION: LEGO1 0x100448a0 MxBool MxControlPresenter::HasTickleStatePassed(TickleState p_tickleState) { - // TODO - return TRUE; + MxCompositePresenterList::iterator it = m_list.begin(); + for (MxS16 i = m_unk0x4e; i > 0; i--, it++) + ; + + return (*it)->HasTickleStatePassed(p_tickleState); } diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index 46f59a77..e9010ef4 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -11,3 +11,9 @@ LegoActor::LegoActor() m_unk0x10 = 0; m_unk0x74 = 0; } + +// STUB: LEGO1 0x1002d320 +LegoActor::~LegoActor() +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp new file mode 100644 index 00000000..927677fe --- /dev/null +++ b/LEGO1/lego/legoomni/src/entity/legoactorpresenter.cpp @@ -0,0 +1,39 @@ +#include "legoactorpresenter.h" + +#include "legoentity.h" +#include "legoomni.h" + +// FUNCTION: LEGO1 0x10076c30 +void LegoActorPresenter::ReadyTickle() +{ + if (GetCurrentWorld()) { + m_entity = (LegoEntity*) CreateEntity("LegoActor"); + if (m_entity) { + SetEntityLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); + m_entity->Create(*m_action); + } + ProgressTickleState(e_starting); + } +} + +// FUNCTION: LEGO1 0x10076c90 +void LegoActorPresenter::StartingTickle() +{ + if (m_entity->GetROI()) { + ProgressTickleState(e_streaming); + ParseExtra(); + } +} + +// FUNCTION: LEGO1 0x10076cc0 +void LegoActorPresenter::ParseExtra() +{ + char buffer[512]; + char* extraData = m_action->GetExtraData(); + if (m_action->GetExtraLength()) { + memcpy(buffer, extraData, m_action->GetExtraLength()); + buffer[m_action->GetExtraLength()] = 0; + + m_entity->ParseAction(buffer); + } +} diff --git a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp index 34afaac0..d48d22ff 100644 --- a/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legocameracontroller.cpp @@ -10,7 +10,7 @@ DECOMP_SIZE_ASSERT(LegoCameraController, 0xc8); // FUNCTION: LEGO1 0x10011d50 LegoCameraController::LegoCameraController() { - SetWorldTransform(Vector3Data(0, 0, 0), Vector3Data(0, 0, 1), Vector3Data(0, 1, 0)); + SetWorldTransform(Mx3DPointFloat(0, 0, 0), Mx3DPointFloat(0, 0, 1), Mx3DPointFloat(0, 1, 0)); } // FUNCTION: LEGO1 0x10011f70 @@ -71,37 +71,49 @@ void LegoCameraController::OnMouseMove(MxU8 p_modifier, MxPoint32 p_point) } // FUNCTION: LEGO1 0x10012260 -void LegoCameraController::SetWorldTransform(Vector3Impl& p_at, Vector3Impl& p_dir, Vector3Impl& p_up) +void LegoCameraController::SetWorldTransform(const Vector3& p_at, const Vector3& p_dir, const Vector3& p_up) { CalcLocalTransform(p_at, p_dir, p_up, m_matrix1); m_matrix2 = m_matrix1; } // STUB: LEGO1 0x100123e0 -void LegoCameraController::FUN_100123e0(Matrix4Data& p_transform, MxU32) +void LegoCameraController::FUN_100123e0(const MxMatrix& p_transform, MxU32) { } -// STUB: LEGO1 0x10012740 -Vector3Data& LegoCameraController::FUN_10012740() +// FUNCTION: LEGO1 0x10012740 +Mx3DPointFloat LegoCameraController::GetWorldUp() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldUp(); + return Mx3DPointFloat(vec[0], vec[1], vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } -// STUB: LEGO1 0x100127f0 -Vector3Data& LegoCameraController::FUN_100127f0() +// FUNCTION: LEGO1 0x100127f0 +Mx3DPointFloat LegoCameraController::GetWorldLocation() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldPosition(); + return Mx3DPointFloat(vec[0], vec[1] - m_entityOffsetUp, vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } -// STUB: LEGO1 0x100128a0 -Vector3Data& LegoCameraController::FUN_100128a0() +// FUNCTION: LEGO1 0x100128a0 +Mx3DPointFloat LegoCameraController::GetWorldDirection() { - // Actually returns reference to a member - static Vector3Data g_v; - return g_v; + if (m_lego3DView && m_lego3DView->GetPointOfView()) { + Mx3DPointFloat vec; + vec = m_lego3DView->GetPointOfView()->GetWorldDirection(); + return Mx3DPointFloat(vec[0], vec[1], vec[2]); + } + else + return Mx3DPointFloat(0, 0, 0); } diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index 0f813029..2c482715 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -2,17 +2,13 @@ #include "define.h" #include "legoomni.h" +#include "legounksavedatawriter.h" #include "legoutil.h" +#include "legovideomanager.h" #include "legoworld.h" DECOMP_SIZE_ASSERT(LegoEntity, 0x68) -// FUNCTION: LEGO1 0x1000c290 -LegoEntity::~LegoEntity() -{ - Destroy(TRUE); -} - // FUNCTION: LEGO1 0x100105f0 void LegoEntity::Init() { @@ -20,11 +16,11 @@ void LegoEntity::Init() m_worldDirection.Fill(0); m_worldSpeed = 0; m_roi = NULL; - m_cameraFlag = 0; + m_cameraFlag = FALSE; m_actionArgString = NULL; m_unk0x10 = 0; - m_unk0x11 = 0; - m_actionType = ExtraActionType_unknown; + m_flags = 0; + m_actionType = Extra::ActionType::e_unknown; m_actionArgNumber = -1; m_unk0x59 = 4; } @@ -36,25 +32,34 @@ void LegoEntity::ResetWorldTransform(MxBool p_inVehicle) } // STUB: LEGO1 0x10010790 -void LegoEntity::SetWorldTransform(Vector3Impl& p_loc, Vector3Impl& p_dir, Vector3Impl& p_up) +void LegoEntity::SetWorldTransform(const Vector3& p_loc, const Vector3& p_dir, const Vector3& p_up) { // TODO } // FUNCTION: LEGO1 0x100107e0 -MxResult LegoEntity::Create(MxDSObject& p_dsObject) +MxResult LegoEntity::Create(MxDSAction& p_dsAction) { - m_mxEntityId = p_dsObject.GetObjectId(); - m_atom = p_dsObject.GetAtomId(); - Init(); + m_mxEntityId = p_dsAction.GetObjectId(); + m_atom = p_dsAction.GetAtomId(); + SetWorld(); return SUCCESS; } -// STUB: LEGO1 0x10010810 +// FUNCTION: LEGO1 0x10010810 void LegoEntity::Destroy(MxBool p_fromDestructor) { if (m_roi) { - // TODO + if (m_flags & c_bit1) { + if (m_roi->GetUnknown0x104() == this) + m_roi->SetUnknown0x104(NULL); + + GetUnkSaveDataWriter()->FUN_10083db0(m_roi); + } + else { + VideoManager()->Get3DManager()->GetLego3DView()->Remove(*m_roi); + delete m_roi; + } } delete[] m_actionArgString; @@ -77,14 +82,18 @@ void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) } // STUB: LEGO1 0x100109b0 -void LegoEntity::SetLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up, MxBool) +void LegoEntity::SetLocation(Mx3DPointFloat& p_location, Mx3DPointFloat& p_direction, Mx3DPointFloat& p_up, MxBool) { // TODO } -// STUB: LEGO1 0x10010c30 +// FUNCTION: LEGO1 0x10010c30 void LegoEntity::FUN_10010c30() { + LegoWorld* world = GetCurrentWorld(); + + if (m_cameraFlag && world && world->GetCamera() && m_roi) + world->GetCamera()->FUN_100123e0(m_roi->GetLocal2World(), 1); } // FUNCTION: LEGO1 0x10010e10 @@ -97,13 +106,13 @@ void LegoEntity::ParseAction(char* p_extra) if (KeyValueStringParse(actionValue, g_strACTION, copy)) { m_actionType = MatchActionString(strtok(actionValue, g_parseExtraTokens)); - if (m_actionType != ExtraActionType_exit) { + if (m_actionType != Extra::ActionType::e_exit) { char* token = strtok(NULL, g_parseExtraTokens); m_actionArgString = new char[strlen(token) + 1]; strcpy(m_actionArgString, token); - if (m_actionType != ExtraActionType_run) { + if (m_actionType != Extra::ActionType::e_run) { m_actionArgNumber = atoi(strtok(NULL, g_parseExtraTokens)); } } diff --git a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp index 7a586c80..0da082cd 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentitypresenter.cpp @@ -15,7 +15,7 @@ LegoEntityPresenter::LegoEntityPresenter() // FUNCTION: LEGO1 0x100535c0 void LegoEntityPresenter::Init() { - m_objectBackend = 0; + m_entity = NULL; } // FUNCTION: LEGO1 0x100535d0 @@ -25,9 +25,9 @@ LegoEntityPresenter::~LegoEntityPresenter() } // FUNCTION: LEGO1 0x10053630 -undefined4 LegoEntityPresenter::SetBackend(LegoEntity* p_backend) +undefined4 LegoEntityPresenter::SetEntity(LegoEntity* p_entity) { - m_objectBackend = p_backend; + m_entity = p_entity; return 0; } @@ -35,7 +35,7 @@ undefined4 LegoEntityPresenter::SetBackend(LegoEntity* p_backend) void LegoEntityPresenter::Destroy(MxBool p_fromDestructor) { if (VideoManager()) { - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); } Init(); @@ -53,7 +53,7 @@ MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDS MxResult result = MxCompositePresenter::StartAction(p_controller, p_action); if (VideoManager()) { - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); } return result; @@ -63,14 +63,13 @@ MxResult LegoEntityPresenter::StartAction(MxStreamController* p_controller, MxDS void LegoEntityPresenter::ReadyTickle() { if (GetCurrentWorld()) { - m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoEntity"); - if (m_objectBackend) { - m_objectBackend->Create(*m_action); - m_objectBackend->SetLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), TRUE); + m_entity = (LegoEntity*) MxPresenter::CreateEntity("LegoEntity"); + if (m_entity) { + m_entity->Create(*m_action); + m_entity->SetLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp(), TRUE); ParseExtra(); } - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -83,10 +82,14 @@ void LegoEntityPresenter::RepeatingTickle() } // FUNCTION: LEGO1 0x10053730 -void LegoEntityPresenter::SetBackendLocation(Vector3Data& p_location, Vector3Data& p_direction, Vector3Data& p_up) +void LegoEntityPresenter::SetEntityLocation( + Mx3DPointFloat& p_location, + Mx3DPointFloat& p_direction, + Mx3DPointFloat& p_up +) { - if (m_objectBackend) { - m_objectBackend->SetLocation(p_location, p_direction, p_up, TRUE); + if (m_entity) { + m_entity->SetLocation(p_location, p_direction, p_up, TRUE); } } @@ -100,6 +103,6 @@ void LegoEntityPresenter::ParseExtra() data[len] = 0; len &= MAXWORD; - m_objectBackend->ParseAction(data); + m_entity->ParseAction(data); } } diff --git a/LEGO1/lego/legoomni/src/entity/legopathactor.cpp b/LEGO1/lego/legoomni/src/entity/legopathactor.cpp index f6d0a10d..472f2e4b 100644 --- a/LEGO1/lego/legoomni/src/entity/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legopathactor.cpp @@ -39,7 +39,7 @@ void LegoPathActor::VTable0x8c() } // STUB: LEGO1 0x1002e740 -void LegoPathActor::VTable0x74(Matrix4Impl& p_transform) +void LegoPathActor::VTable0x74(Matrix4& p_transform) { // TODO } diff --git a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp index a2e1bb04..f656022d 100644 --- a/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp +++ b/LEGO1/lego/legoomni/src/entity/legopovcontroller.cpp @@ -100,6 +100,12 @@ MxResult LegoPointOfViewController::Create(Lego3DView* p_lego3DView) return SUCCESS; } +// FUNCTION: LEGO1 0x100658a0 +void LegoPointOfViewController::OnViewSize(int p_width, int p_height) +{ + m_nav->SetControlMax(p_width, p_height); +} + // FUNCTION: LEGO1 0x100658c0 void LegoPointOfViewController::LeftDown(int p_x, int p_y) { diff --git a/LEGO1/lego/legoomni/src/entity/legorace.cpp b/LEGO1/lego/legoomni/src/entity/legorace.cpp index d5eefbd5..79565966 100644 --- a/LEGO1/lego/legoomni/src/entity/legorace.cpp +++ b/LEGO1/lego/legoomni/src/entity/legorace.cpp @@ -62,7 +62,7 @@ MxBool LegoRace::VTable0x64() } // STUB: LEGO1 0x10015ce0 -MxResult LegoRace::Create(MxDSObject& p_dsObject) +MxResult LegoRace::Create(MxDSAction& p_dsAction) { // TODO return SUCCESS; diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index ff3969bd..8e5c7465 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -1,21 +1,27 @@ #include "legoworld.h" +#include "legocontrolmanager.h" #include "legoinputmanager.h" #include "legoomni.h" #include "legoutil.h" +#include "legovideomanager.h" #include "mxactionnotificationparam.h" #include "mxnotificationmanager.h" #include "mxnotificationparam.h" #include "mxomni.h" #include "mxticklemanager.h" -DECOMP_SIZE_ASSERT(LegoWorld, 0xf8); +DECOMP_SIZE_ASSERT(LegoWorld, 0xf8) +DECOMP_SIZE_ASSERT(LegoEntityList, 0x18) +DECOMP_SIZE_ASSERT(LegoEntityListCursor, 0x10) +DECOMP_SIZE_ASSERT(MxCoreList, 0x18) +DECOMP_SIZE_ASSERT(MxCoreListCursor, 0x10) // STUB: LEGO1 0x1001ca40 LegoWorld::LegoWorld() : m_list0x68(TRUE) { // TODO - m_unk0xf6 = FALSE; + m_worldStarted = FALSE; m_unk0xf4 = 4; NotificationManager()->Register(this); } @@ -38,11 +44,43 @@ LegoWorld::~LegoWorld() // TODO } -// STUB: LEGO1 0x1001e0b0 -MxResult LegoWorld::SetAsCurrentWorld(MxDSObject& p_dsObject) +// FUNCTION: LEGO1 0x1001e0b0 +MxResult LegoWorld::Create(MxDSAction& p_dsAction) +{ + MxEntity::Create(p_dsAction); + + m_entityList = new LegoEntityList(TRUE); + + if (!m_entityList) + return FAILURE; + + m_coreList = new MxCoreList(TRUE); + + if (!m_coreList) + return FAILURE; + + if (!VTable0x54()) + return FAILURE; + + if (p_dsAction.GetFlags() & MxDSAction::c_enabled) { + if (GetCurrentWorld()) { + GetCurrentWorld()->VTable0x68(0); + } + + SetCurrentWorld(this); + ControlManager()->FUN_10028df0(&m_list0xb8); + } + + SetIsWorldActive(TRUE); + m_unk0xec = -1; + + return SUCCESS; +} + +// STUB: LEGO1 0x1001e9d0 +void LegoWorld::Destroy(MxBool p_fromDestructor) { // TODO - return SUCCESS; } // FUNCTION: LEGO1 0x1001f5e0 @@ -63,10 +101,37 @@ MxLong LegoWorld::Notify(MxParam& p_param) return ret; } -// STUB: LEGO1 0x1001f630 -void LegoWorld::VTable0x54() +// FUNCTION: LEGO1 0x1001f630 +LegoCameraController* LegoWorld::VTable0x54() { - // TODO + MxBool success = FALSE; + + if (!VideoManager()) { + goto done; + } + if (!(m_cameraController = new LegoCameraController())) { + goto done; + } + if (m_cameraController->Create() != SUCCESS) { + goto done; + } + + m_cameraController->OnViewSize( + VideoManager()->GetVideoParam().GetRect().GetWidth(), + VideoManager()->GetVideoParam().GetRect().GetHeight() + ); + + success = TRUE; + +done: + if (!success) { + if (m_cameraController) { + delete m_cameraController; + m_cameraController = NULL; + } + } + + return m_cameraController; } // STUB: LEGO1 0x1001fc80 @@ -92,6 +157,12 @@ void LegoWorld::EndAction(MxCore* p_object) { } +// STUB: LEGO1 0x100213a0 +MxPresenter* LegoWorld::FindPresenter(const char* p_presenter, const char* p_name) +{ + return NULL; +} + // STUB: LEGO1 0x10021a70 void LegoWorld::VTable0x68(MxBool p_add) { @@ -101,12 +172,12 @@ void LegoWorld::VTable0x68(MxBool p_add) // FUNCTION: LEGO1 0x10022080 MxResult LegoWorld::Tickle() { - if (!m_unk0xf6) { + if (!m_worldStarted) { switch (m_unk0xf4) { case 0: - m_unk0xf6 = TRUE; + m_worldStarted = TRUE; SetAppCursor(0); - Stop(); + VTable0x50(); return TRUE; case 2: if (FUN_100220e0() == 1) @@ -121,23 +192,23 @@ MxResult LegoWorld::Tickle() // STUB: LEGO1 0x100220e0 undefined LegoWorld::FUN_100220e0() { - return TRUE; + return 0; } // FUNCTION: LEGO1 0x10022340 -void LegoWorld::Stop() +void LegoWorld::VTable0x50() { TickleManager()->UnregisterClient(this); } // STUB: LEGO1 0x100727e0 -MxBool LegoWorld::FUN_100727e0(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) +MxBool LegoWorld::FUN_100727e0(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) { return FALSE; } // STUB: LEGO1 0x10072980 -MxBool LegoWorld::FUN_10072980(MxU32, Vector3Data& p_loc, Vector3Data& p_dir, Vector3Data& p_up) +MxBool LegoWorld::FUN_10072980(MxU32, Mx3DPointFloat& p_loc, Mx3DPointFloat& p_dir, Mx3DPointFloat& p_up) { return FALSE; } diff --git a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp index 02578675..55f908bd 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworldpresenter.cpp @@ -1,12 +1,18 @@ #include "legoworldpresenter.h" +#include "legoanimationmanager.h" +#include "legobuildingmanager.h" #include "legoentity.h" #include "legoomni.h" +#include "legoplantmanager.h" #include "legovideomanager.h" +#include "legoworld.h" #include "mxactionnotificationparam.h" #include "mxautolocker.h" #include "mxdsactionlist.h" +#include "mxdsmediaaction.h" #include "mxdsmultiaction.h" +#include "mxnotificationmanager.h" #include "mxobjectfactory.h" #include "mxpresenter.h" #include "mxstl/stlcompat.h" @@ -26,10 +32,32 @@ LegoWorldPresenter::LegoWorldPresenter() m_unk0x50 = 50000; } -// STUB: LEGO1 0x10066770 +// FUNCTION: LEGO1 0x10066770 LegoWorldPresenter::~LegoWorldPresenter() { - // TODO + MxBool result = FALSE; + if (m_entity) { + undefined4 world = ((LegoWorld*) m_entity)->GetUnknown0xec(); + PlantManager()->FUN_10026360(world); + AnimationManager()->FUN_1005f720(world); + BuildingManager()->FUN_1002fa00(); + result = ((LegoWorld*) m_entity)->VTable0x5c(); + } + + if (result == FALSE) { + FUN_10015820(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 @@ -63,7 +91,7 @@ MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSA if (presenter && presenter->AddToManager() == SUCCESS) { presenter->SetCompositePresenter(this); if (presenter->StartAction(p_controller, action) == SUCCESS) { - presenter->SetTickleState(TickleState_Idle); + presenter->SetTickleState(e_idle); success = TRUE; } } @@ -76,7 +104,7 @@ MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSA delete presenter; } - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); result = SUCCESS; } @@ -87,16 +115,15 @@ MxResult LegoWorldPresenter::StartAction(MxStreamController* p_controller, MxDSA // FUNCTION: LEGO1 0x10066a50 void LegoWorldPresenter::ReadyTickle() { - m_objectBackend = (LegoEntity*) MxPresenter::CreateEntityBackend("LegoWorld"); - if (m_objectBackend) { - m_objectBackend->Create(*m_action); - Lego()->AddWorld((LegoWorld*) m_objectBackend); - SetBackendLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); + m_entity = (LegoEntity*) MxPresenter::CreateEntity("LegoWorld"); + if (m_entity) { + m_entity->Create(*m_action); + Lego()->AddWorld((LegoWorld*) m_entity); + SetEntityLocation(m_action->GetLocation(), m_action->GetDirection(), m_action->GetUp()); } ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } // FUNCTION: LEGO1 0x10066ac0 @@ -104,25 +131,42 @@ void LegoWorldPresenter::StartingTickle() { if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *m_list.begin(); - if (presenter->GetCurrentTickleState() == TickleState_Idle) { - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) { + presenter->SetTickleState(e_ready); } } else { for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { - if ((*it)->GetCurrentTickleState() == TickleState_Idle) { - (*it)->SetTickleState(TickleState_Ready); + if ((*it)->GetCurrentTickleState() == e_idle) { + (*it)->SetTickleState(e_ready); } } } - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); } -// STUB: LEGO1 0x10067a70 +// FUNCTION: LEGO1 0x10067a70 void LegoWorldPresenter::VTable0x60(MxPresenter* p_presenter) { + MxCompositePresenter::VTable0x60(p_presenter); + MxDSAction* action = p_presenter->GetAction(); + + if (action->GetDuration() != -1 && (action->GetFlags() & MxDSAction::c_looping) == 0) { + if (!action->IsA("MxDSMediaAction")) { + return; + } + + if (((MxDSMediaAction*) action)->GetSustainTime() != -1) { + return; + } + } + + if (!p_presenter->IsA("LegoAnimPresenter") && !p_presenter->IsA("MxControlPresenter") && + !p_presenter->IsA("MxCompositePresenter")) { + p_presenter->SendToCompositePresenter(Lego()); + ((LegoWorld*) m_entity)->VTable0x58(p_presenter); + } } // STUB: LEGO1 0x10067b00 diff --git a/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp index 24325511..7f7aff11 100644 --- a/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/gasstation/gasstation.cpp @@ -1,9 +1,22 @@ #include "gasstation.h" -// STUB: LEGO1 0x100046a0 +#include "mxnotificationmanager.h" + +// FUNCTION: LEGO1 0x100046a0 GasStation::GasStation() { - // TODO + this->m_unk0xf8 = 0; + this->m_unk0x100 = 0; + this->m_unk0xfc = 0; + this->m_unk0x108 = 0; + this->m_unk0x104 = 0; + this->m_unk0x114 = 0; + this->m_unk0x106 = 0; + this->m_unk0x10c = 0; + this->m_unk0x115 = 0; + this->m_unk0x110 = 0; + + NotificationManager()->Register(this); } // STUB: LEGO1 0x100048c0 diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp index 247defb0..ab4d3cff 100644 --- a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -1,21 +1,103 @@ #include "elevatorbottom.h" -// STUB: LEGO1 0x10017e90 +#include "jukebox.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "mxnotificationmanager.h" +#include "mxomni.h" + +DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) + +// FUNCTION: LEGO1 0x10017e90 ElevatorBottom::ElevatorBottom() { - // TODO + NotificationManager()->Register(this); + this->m_unk0xf8 = 0; } -// STUB: LEGO1 0x10018060 +// FUNCTION: LEGO1 0x10018060 ElevatorBottom::~ElevatorBottom() { - // TODO + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x10018150 +// 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()->SetUnknown424(5); + GameState()->FUN_1003a720(0); + + return result; +} + +// FUNCTION: LEGO1 0x10018150 MxLong ElevatorBottom::Notify(MxParam& p_param) { - // TODO + MxLong ret = 0; + LegoWorld::Notify(p_param); + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationType17: + ret = HandleNotification17(p_param); + break; + case c_notificationTransitioned: + GameState()->HandleAction(m_unk0xf8); + break; + } + } + + return ret; +} + +// FUNCTION: LEGO1 0x100181b0 +void ElevatorBottom::VTable0x50() +{ + LegoWorld::VTable0x50(); + PlayMusic(JukeBox::e_informationCenter); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); +} + +// STUB: LEGO1 0x100181d0 +MxLong ElevatorBottom::HandleNotification17(MxParam& p_param) +{ return 0; } + +// FUNCTION: LEGO1 0x100182c0 +void ElevatorBottom::VTable0x68(MxBool p_add) +{ + LegoWorld::VTable0x68(p_add); + + if (p_add) { + 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 index 8c6bcb8d..170147d0 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -1,47 +1,528 @@ #include "infocenter.h" -// STUB: LEGO1 0x1006ea20 +#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 "mxnotificationmanager.h" +#include "mxstillpresenter.h" +#include "mxticklemanager.h" +#include "mxtransitionmanager.h" + +DECOMP_SIZE_ASSERT(Infocenter, 0x1d8) +DECOMP_SIZE_ASSERT(InfocenterUnkDataEntry, 0x18) + +// GLOBAL: LEGO1 0x100f76a0 +const char* g_object2x4red = "2x4red"; + +// GLOBAL: LEGO1 0x100f76a4 +const char* g_object2x4grn = "2x4grn"; + +// FUNCTION: LEGO1 0x1006ea20 Infocenter::Infocenter() { - // TODO + m_unk0xfc = 0; + m_unk0x11c = 0; + m_infocenterState = NULL; + m_unk0x1cc = 0; + m_unk0x11c = 0; + m_unk0x104 = 0; + m_currentInfomainScript = c_noInfomain; + m_currentCutscene = e_noIntro; + + memset(&m_entries, 0, sizeof(m_entries)); + + m_unk0x1c8 = -1; + SetAppCursor(1); + NotificationManager()->Register(this); + + m_infoManDialogueTimer = 0; + m_bookAnimationTimer = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; } -// STUB: LEGO1 0x1006ec90 +// FUNCTION: LEGO1 0x1006ec90 Infocenter::~Infocenter() { - // TODO + 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); } // STUB: LEGO1 0x1006ed90 -MxResult Infocenter::Create(MxDSObject& p_dsObject) +MxResult Infocenter::Create(MxDSAction& p_dsAction) { - return FAILURE; + if (LegoWorld::Create(p_dsAction) == SUCCESS) { + InputManager()->SetWorld(this); + ControlManager()->Register(this); + } + + LegoGameState* gs = GameState(); + m_infocenterState = (InfocenterState*) gs->GetState("InfocenterState"); + if (!m_infocenterState) { + m_infocenterState = (InfocenterState*) gs->CreateState("InfocenterState"); + m_infocenterState->SetUnknown0x74(3); + } + else { + // TODO + } + + // TODO + InputManager()->Register(this); + SetIsWorldActive(FALSE); + return SUCCESS; } -// STUB: LEGO1 0x1006ef10 +// FUNCTION: LEGO1 0x1006ef10 MxLong Infocenter::Notify(MxParam& p_param) { - // TODO - return 0; + MxLong result = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationType0: + result = HandleNotification0(p_param); + break; + case c_notificationEndAction: + result = HandleEndAction(p_param); + break; + case c_notificationKeyPress: + result = HandleKeyPress(((LegoEventNotificationParam&) p_param).GetKey()); + break; + case c_notificationButtonUp: + result = HandleButtonUp( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ); + break; + case c_notificationMouseMove: + result = HandleMouseMove( + ((LegoEventNotificationParam&) p_param).GetX(), + ((LegoEventNotificationParam&) p_param).GetY() + ); + break; + case c_notificationType17: + result = HandleNotification17(p_param); + break; + case c_notificationTransitioned: + StopBookAnimation(); + m_bookAnimationTimer = 0; + + if (m_infocenterState->GetUnknown0x74() == 0xc) { + StartCredits(); + m_infocenterState->SetUnknown0x74(0xd); + } + else if (m_unk0x104 != 0) { + BackgroundAudioManager()->RaiseVolume(); + GameState()->HandleAction(m_unk0x104); + m_unk0x104 = 0; + } + break; + } + } + + return result; +} + +// FUNCTION: LEGO1 0x1006f080 +MxLong Infocenter::HandleEndAction(MxParam& p_param) +{ + MxDSAction* action = ((MxEndActionNotificationParam&) p_param).GetAction(); + if (action->GetAtomId() == *g_creditsScript && action->GetObjectId() == 499) { + Lego()->CloseMainWindow(); + return 1; + } + + if (action->GetAtomId() == m_atom && + (action->GetObjectId() == 40 || action->GetObjectId() == 41 || action->GetObjectId() == 42 || + action->GetObjectId() == 43 || action->GetObjectId() == 44)) { + if (m_unk0x1d4) { + m_unk0x1d4--; + } + + if (!m_unk0x1d4) { + PlayMusic(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; + } + + FUN_10070dc0(TRUE); + } + } + + MxLong result = m_radio.Notify(p_param); + + if (result || (action->GetAtomId() != m_atom && action->GetAtomId() != *g_introScript)) + return result; + + if (action->GetObjectId() == c_returnBackGuidanceDialogue2) { + ControlManager()->FUN_100293c0(0x10, action->GetAtomId().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() == 70 || action->GetObjectId() == 71) { + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_infocenterState->SetUnknown0x74(14); + return 1; + } + break; + case 5: + if (action->GetObjectId() == m_currentInfomainScript) { + if (GameState()->GetUnknown10() != 2 && m_unk0xfc != 0) { + GameState()->FUN_10039780(m_unk0xfc); + } + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_infocenterState->SetUnknown0x74(14); + return 1; + } + break; + case 11: + if (m_infocenterState->GetInfocenterBufferElement(0) == 0 && m_currentInfomainScript != 40 && + m_currentInfomainScript != 41 && m_currentInfomainScript != 42 && m_currentInfomainScript != 43 && + m_currentInfomainScript != 44) { + m_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::Stop() +void Infocenter::VTable0x50() { - // TODO + m_infoManDialogueTimer = 0; + m_bookAnimationTimer = 0; + m_unk0x1d4 = 0; + m_unk0x1d6 = 0; + + MxStillPresenter* bg = (MxStillPresenter*) FindPresenter("MxStillPresenter", "Background_Bitmap"); + MxStillPresenter* bgRed = (MxStillPresenter*) FindPresenter("MxStillPresenter", "BackgroundRed_Bitmap"); + + switch (GameState()->GetUnknown10()) { + case 0: + // bg->Enable(1); // TODO: Uncomment once LegoWorld::FindPresenter and LegoWorld::VTable0x58 are implemented. + InitializeBitmaps(); + switch (m_infocenterState->GetUnknown0x74()) { + case 3: + PlayCutscene(e_legoMovie, TRUE); + m_infocenterState->SetUnknown0x74(0); + return; + case 4: + m_infocenterState->SetUnknown0x74(2); + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_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; + } } -// STUB: LEGO1 0x10070aa0 +// STUB: LEGO1 0x1006f9a0 +void Infocenter::InitializeBitmaps() +{ + // TODO: Infocenter class size is wrong +} + +// STUB: LEGO1 0x1006fd00 +MxU8 Infocenter::HandleMouseMove(MxS32 p_x, MxS32 p_y) +{ + return 1; +} + +// FUNCTION: LEGO1 0x1006fda0 +MxLong Infocenter::HandleKeyPress(MxS8 p_key) +{ + MxLong result = 0; + + if (p_key == ' ' && m_worldStarted) { + switch (m_infocenterState->GetUnknown0x74()) { + case 0: + StopCutscene(); + m_infocenterState->SetUnknown0x74(1); + + if (m_infocenterState->GetInfocenterBufferElement(0) == 0) { + m_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; +} + +// STUB: LEGO1 0x1006feb0 +MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) +{ + return 1; +} + +// STUB: LEGO1 0x10070370 +MxU8 Infocenter::HandleNotification17(MxParam&) +{ + return 1; +} + +// STUB: LEGO1 0x10070870 +MxLong Infocenter::HandleNotification0(MxParam&) +{ + return 1; +} + +// FUNCTION: LEGO1 0x10070aa0 void Infocenter::VTable0x68(MxBool p_add) { - // TODO + LegoWorld::VTable0x68(p_add); + + if (p_add) { + InputManager()->SetWorld(this); + SetIsWorldActive(FALSE); + } + else { + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + } } -// STUB: LEGO1 0x10070af0 +// FUNCTION: LEGO1 0x10070af0 MxResult Infocenter::Tickle() { - // TODO - return 0; + 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 @@ -50,8 +531,79 @@ MxBool Infocenter::VTable0x5c() return TRUE; } +// STUB: LEGO1 0x10070dc0 +void Infocenter::FUN_10070dc0(MxBool) +{ +} + +// STUB: LEGO1 0x10070e90 +void Infocenter::FUN_10070e90() +{ +} + // STUB: LEGO1 0x10070f60 MxBool Infocenter::VTable0x64() { return FALSE; } + +// STUB: LEGO1 0x10071030 +void Infocenter::StartCredits() +{ + // TODO +} + +// FUNCTION: LEGO1 0x10071250 +void Infocenter::StopCredits() +{ + MxDSAction action; + action.SetObjectId(499); + action.SetAtomId(*g_creditsScript); + action.SetUnknown24(-2); + DeleteObject(action); +} + +// FUNCTION: LEGO1 0x10071300 +void Infocenter::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 index c6d85394..79e88a99 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp @@ -1,21 +1,85 @@ #include "infocenterdoor.h" -// STUB: LEGO1 0x10037730 +#include "jukebox.h" +#include "legocontrolmanager.h" +#include "legogamestate.h" +#include "legoinputmanager.h" +#include "legoomni.h" +#include "mxnotificationmanager.h" + +DECOMP_SIZE_ASSERT(InfocenterDoor, 0xfc) + +// FUNCTION: LEGO1 0x10037730 InfocenterDoor::InfocenterDoor() { - // TODO + m_unk0xf8 = 0; + + NotificationManager()->Register(this); } -// STUB: LEGO1 0x100378f0 +// FUNCTION: LEGO1 0x100378f0 InfocenterDoor::~InfocenterDoor() { - // TODO + 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()->SetUnknown424(3); + GameState()->FUN_1003a720(0); + + return result; } // STUB: LEGO1 0x100379e0 MxLong InfocenterDoor::Notify(MxParam& p_param) { // TODO - - return 0; + return LegoWorld::Notify(p_param); +} + +// FUNCTION: LEGO1 0x10037a70 +void InfocenterDoor::VTable0x50() +{ + LegoWorld::VTable0x50(); + PlayMusic(JukeBox::e_informationCenter); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); +} + +// FUNCTION: LEGO1 0x10037c80 +void InfocenterDoor::VTable0x68(MxBool p_add) +{ + LegoWorld::VTable0x68(p_add); + + if (p_add) { + 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/lego/legoomni/src/infocenter/infocenterstate.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp index 47a31fbb..76ffd3ea 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterstate.cpp @@ -2,14 +2,22 @@ DECOMP_SIZE_ASSERT(InfocenterState, 0x94); -// STUB: LEGO1 0x10071600 +// FUNCTION: LEGO1 0x10071600 InfocenterState::InfocenterState() { // TODO + memset(m_buffer, 0, sizeof(m_buffer)); } -// STUB: LEGO1 0x10071920 +// FUNCTION: LEGO1 0x10071920 InfocenterState::~InfocenterState() { - // TODO + 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 index eb7e099a..f68bc29e 100644 --- a/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/registrationbook.cpp @@ -1,5 +1,7 @@ #include "registrationbook.h" +#include "legoomni.h" + // STUB: LEGO1 0x10076d20 RegistrationBook::RegistrationBook() { @@ -12,6 +14,12 @@ RegistrationBook::~RegistrationBook() // TODO } +// STUB: LEGO1 0x10077060 +MxResult RegistrationBook::Create(MxDSAction& p_dsAction) +{ + return SUCCESS; +} + // STUB: LEGO1 0x100770e0 MxLong RegistrationBook::Notify(MxParam& p_param) { @@ -19,3 +27,29 @@ MxLong RegistrationBook::Notify(MxParam& p_param) return 0; } + +// STUB: LEGO1 0x10077cc0 +void RegistrationBook::VTable0x50() +{ + // TODO +} + +// STUB: LEGO1 0x10077fd0 +MxResult RegistrationBook::Tickle() +{ + // TODO + return SUCCESS; +} + +// STUB: LEGO1 0x10078180 +void RegistrationBook::VTable0x68(MxBool p_add) +{ + // TODO +} + +// FUNCTION: LEGO1 0x100783e0 +MxBool RegistrationBook::VTable0x64() +{ + DeleteObjects(&m_atom, 500, 506); + return TRUE; +} diff --git a/LEGO1/lego/legoomni/src/infocenter/score.cpp b/LEGO1/lego/legoomni/src/infocenter/score.cpp index dcc39f02..2d7d8c05 100644 --- a/LEGO1/lego/legoomni/src/infocenter/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" @@ -39,9 +40,9 @@ Score::~Score() } // FUNCTION: LEGO1 0x100012a0 -MxResult Score::Create(MxDSObject& p_dsObject) +MxResult Score::Create(MxDSAction& p_dsAction) { - MxResult result = SetAsCurrentWorld(p_dsObject); + MxResult result = LegoWorld::Create(p_dsAction); if (result == SUCCESS) { InputManager()->SetWorld(this); @@ -76,7 +77,7 @@ MxLong Score::Notify(MxParam& p_param) { MxLong ret = 0; LegoWorld::Notify(p_param); - if (m_unk0xf6) { + if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationStartAction: ret = 1; @@ -90,10 +91,10 @@ MxLong Score::Notify(MxParam& p_param) DeleteScript(); // Shutting down ret = 1; break; - case TYPE17: + case c_notificationType17: ret = FUN_100016d0((MxType17NotificationParam&) p_param); break; - case MXTRANSITIONMANAGER_TRANSITIONENDED: + case c_notificationTransitioned: DeleteObjects(g_infoscorScript, 7, 9); if (m_unk0xf8) GameState()->HandleAction(m_unk0xf8); @@ -116,10 +117,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 +129,9 @@ MxLong Score::FUN_10001510(MxEndActionNotificationParam& p_param) } // FUNCTION: LEGO1 0x10001580 -void Score::Stop() +void Score::VTable0x50() { - LegoWorld::Stop(); + LegoWorld::VTable0x50(); MxDSAction action; action.SetObjectId(0x1f4); @@ -145,9 +146,9 @@ void Score::Stop() Start(&action); } else - PlayMusic(11); + PlayMusic(JukeBox::e_informationCenter); - FUN_10015820(0, 7); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x100016d0 @@ -160,12 +161,12 @@ MxLong Score::FUN_100016d0(MxType17NotificationParam& p_param) case 1: m_unk0xf8 = 2; DeleteScript(); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 0x32, 0, 0); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; case 2: m_unk0xf8 = 3; DeleteScript(); - TransitionManager()->StartTransition(MxTransitionManager::PIXELATION, 0x32, 0, 0); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 0x32, 0, 0); break; case 3: { LegoInputManager* im = InputManager(); @@ -227,8 +228,7 @@ void Score::VTable0x68(MxBool p_add) // 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"); diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index cdfd4bb3..87c72a63 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -7,6 +7,12 @@ DECOMP_SIZE_ASSERT(LegoInputManager, 0x338); DECOMP_SIZE_ASSERT(LegoEventQueue, 0x18); +// GLOBAL: LEGO1 0x100f31b0 +MxS32 g_unk0x100f31b0 = -1; + +// GLOBAL: LEGO1 0x100f31b4 +MxS32 g_unk0x100f31b4 = 0; + // FUNCTION: LEGO1 0x1005b790 LegoInputManager::LegoInputManager() { @@ -271,3 +277,11 @@ void LegoInputManager::KillTimer() ::KillTimer(omni->GetWindowHandle(), m_timer); } } + +// FUNCTION: LEGO1 0x1005cff0 +void LegoInputManager::EnableInputProcessing() +{ + m_unk0x88 = FALSE; + g_unk0x100f31b0 = -1; + g_unk0x100f31b4 = 0; +} diff --git a/LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp b/LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp index 66b07f60..f243b92a 100644 --- a/LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp +++ b/LEGO1/lego/legoomni/src/isle/beachhouseentity.cpp @@ -1,9 +1 @@ #include "beachhouseentity.h" - -// STUB: LEGO1 0x100150a0 -MxLong BeachHouseEntity::Notify(MxParam& p_param) -{ - // TODO - - return 0; -} diff --git a/LEGO1/lego/legoomni/src/isle/isle.cpp b/LEGO1/lego/legoomni/src/isle/isle.cpp index 2d1d856a..7172a7a6 100644 --- a/LEGO1/lego/legoomni/src/isle/isle.cpp +++ b/LEGO1/lego/legoomni/src/isle/isle.cpp @@ -26,7 +26,7 @@ Isle::Isle() m_helicopter = NULL; m_bike = NULL; m_dunebuggy = NULL; - m_motorcycle = NULL; + m_motocycle = NULL; m_skateboard = NULL; m_racecar = NULL; m_jetski = NULL; @@ -54,11 +54,11 @@ Isle::~Isle() } // FUNCTION: LEGO1 0x10030b20 -MxResult Isle::Create(MxDSObject& p_dsObject) +MxResult Isle::Create(MxDSAction& p_dsAction) { GameState()->FUN_1003ceb0(); - MxResult result = LegoWorld::SetAsCurrentWorld(p_dsObject); + MxResult result = LegoWorld::Create(p_dsAction); if (result == SUCCESS) { ControlManager()->Register(this); InputManager()->SetWorld(this); @@ -99,7 +99,7 @@ MxLong Isle::Notify(MxParam& p_param) MxLong result = 0; LegoWorld::Notify(p_param); - if (m_unk0xf6) { + if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationEndAction: result = StopAction(p_param); @@ -115,10 +115,10 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case TYPE17: + case c_notificationType17: result = HandleType17Notification(p_param); break; - case TYPE18: + case c_notificationType18: switch (m_act1state->GetUnknown18()) { case 4: result = GetCurrentVehicle()->Notify(p_param); @@ -131,13 +131,13 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case TYPE19: + case c_notificationType19: result = HandleType19Notification(p_param); break; - case TYPE20: + case c_notificationType20: VTable0x68(TRUE); break; - case MXTRANSITIONMANAGER_TRANSITIONENDED: + case c_notificationTransitioned: result = HandleTransitionEnd(); break; } @@ -152,10 +152,22 @@ MxLong Isle::StopAction(MxParam& p_param) return 0; } -// STUB: LEGO1 0x10030fc0 -void Isle::Stop() +// FUNCTION: LEGO1 0x10030fc0 +void Isle::VTable0x50() { - // TODO + LegoWorld::VTable0x50(); + + if (m_act1state->GetUnknown21()) { + GameState()->HandleAction(2); + m_act1state->SetUnknown18(0); + m_act1state->SetUnknown21(0); + } + else if (GameState()->GetCurrentAct()) { + FUN_1003ef00(TRUE); + FUN_10032620(); + m_act1state->FUN_10034d00(); + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + } } // STUB: LGEO1 0x10031030 @@ -176,6 +188,12 @@ void Isle::VTable0x68(MxBool p_add) // TODO } +// STUB: LEGO1 0x10032620 +void Isle::FUN_10032620() +{ + // TODO +} + // STUB: LEGO1 0x100327a0 MxLong Isle::HandleTransitionEnd() { @@ -212,7 +230,7 @@ void Isle::VTable0x58(MxCore* p_object) m_dunebuggy = (DuneBuggy*) p_object; } else if (p_object->IsA("Motorcycle")) { - m_motorcycle = (Motorcycle*) p_object; + m_motocycle = (Motocycle*) p_object; } else if (p_object->IsA("SkateBoard")) { m_skateboard = (SkateBoard*) p_object; diff --git a/LEGO1/lego/legoomni/src/isle/islepathactor.cpp b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp index 528bbde8..76ec41bd 100644 --- a/LEGO1/lego/legoomni/src/isle/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/isle/islepathactor.cpp @@ -12,9 +12,16 @@ IslePathActor::IslePathActor() } // FUNCTION: LEGO1 0x1001a280 -MxResult IslePathActor::Create(MxDSObject& p_dsObject) +MxResult IslePathActor::Create(MxDSAction& p_dsAction) { - return MxEntity::Create(p_dsObject); + return MxEntity::Create(p_dsAction); +} + +// FUNCTION: LEGO1 0x1001a2a0 +void IslePathActor::Destroy(MxBool p_fromDestructor) +{ + if (!p_fromDestructor) + LegoPathActor::Destroy(FALSE); } // STUB: LEGO1 0x1001a350 diff --git a/LEGO1/lego/legoomni/src/isle/motorcycle.cpp b/LEGO1/lego/legoomni/src/isle/motocycle.cpp similarity index 60% rename from LEGO1/lego/legoomni/src/isle/motorcycle.cpp rename to LEGO1/lego/legoomni/src/isle/motocycle.cpp index 18fabd8a..2628d7ce 100644 --- a/LEGO1/lego/legoomni/src/isle/motorcycle.cpp +++ b/LEGO1/lego/legoomni/src/isle/motocycle.cpp @@ -1,9 +1,9 @@ -#include "motorcycle.h" +#include "motocycle.h" -DECOMP_SIZE_ASSERT(Motorcycle, 0x16c); +DECOMP_SIZE_ASSERT(Motocycle, 0x16c); // FUNCTION: LEGO1 0x100357b0 -Motorcycle::Motorcycle() +Motocycle::Motocycle() { this->m_unk0x13c = 40.0; this->m_unk0x150 = 1.75; diff --git a/LEGO1/lego/legoomni/src/main/legoomni.cpp b/LEGO1/lego/legoomni/src/main/legoomni.cpp index 9f27a980..a8d06b89 100644 --- a/LEGO1/lego/legoomni/src/main/legoomni.cpp +++ b/LEGO1/lego/legoomni/src/main/legoomni.cpp @@ -23,6 +23,7 @@ #include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(LegoWorldList, 0x18); +DECOMP_SIZE_ASSERT(LegoWorldListCursor, 0x10); // GLOBAL: LEGO1 0x100f451c MxAtomId* g_copterScript = NULL; @@ -99,7 +100,7 @@ MxAtomId* g_testScript = NULL; // GLOBAL: LEGO1 0x100f457c MxAtomId* g_jukeboxwScript = NULL; -// GLOBAL: LEGO1 0x100f4580c +// GLOBAL: LEGO1 0x100f4580 MxAtomId* g_sndAnimScript = NULL; // GLOBAL: LEGO1 0x100f4584 @@ -109,6 +110,7 @@ MxAtomId* g_creditsScript = NULL; MxAtomId* g_nocdSourceName = NULL; // GLOBAL: LEGO1 0x100f6718 +// STRING: LEGO1 0x100f6710 const char* g_current = "current"; // GLOBAL: LEGO1 0x100f4c58 @@ -117,7 +119,7 @@ MxBool g_isWorldActive = TRUE; // FUNCTION: LEGO1 0x10015700 LegoOmni* Lego() { - return (LegoOmni*) MxOmni::GetInstance(); + return LegoOmni::GetInstance(); } // FUNCTION: LEGO1 0x10015710 @@ -180,6 +182,12 @@ LegoWorld* GetCurrentWorld() return LegoOmni::GetInstance()->GetCurrentOmniWorld(); } +// FUNCTION: LEGO1 0x100157b0 +LegoUnkSaveDataWriter* GetUnkSaveDataWriter() +{ + return LegoOmni::GetInstance()->GetUnkSaveDataWriter(); +} + // FUNCTION: LEGO1 0x100157e0 LegoPlantManager* PlantManager() { @@ -198,8 +206,14 @@ 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 } @@ -216,6 +230,12 @@ MxDSAction& GetCurrentAction() return LegoOmni::GetInstance()->GetCurrentAction(); } +// FUNCTION: LEGO1 0x100158f0 +void SetCurrentWorld(LegoWorld* p_world) +{ + LegoOmni::GetInstance()->SetWorld(p_world); +} + // FUNCTION: LEGO1 0x10015900 MxTransitionManager* TransitionManager() { @@ -241,6 +261,20 @@ void SetIsWorldActive(MxBool p_isWorldActive) g_isWorldActive = p_isWorldActive; } +// FUNCTION: LEGO1 0x100159e0 +void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last) +{ + MxDSAction action; + + action.SetAtomId(*p_id); + action.SetUnknown24(-2); + + for (MxS32 first = p_first, last = p_last; first <= last; first++) { + action.SetObjectId(first); + DeleteObject(action); + } +} + // STUB: LEGO1 0x1001a700 void FUN_1001a700() { @@ -265,34 +299,34 @@ LegoEntity* PickEntity(MxLong, MxLong) // FUNCTION: LEGO1 0x100528e0 void RegisterScripts() { - g_copterScript = new MxAtomId("\\lego\\scripts\\build\\copter", LookupMode_LowerCase2); - g_dunecarScript = new MxAtomId("\\lego\\scripts\\build\\dunecar", LookupMode_LowerCase2); - g_jetskiScript = new MxAtomId("\\lego\\scripts\\build\\jetski", LookupMode_LowerCase2); - g_racecarScript = new MxAtomId("\\lego\\scripts\\build\\racecar", LookupMode_LowerCase2); - g_carraceScript = new MxAtomId("\\lego\\scripts\\race\\carrace", LookupMode_LowerCase2); - g_carracerScript = new MxAtomId("\\lego\\scripts\\race\\carracer", LookupMode_LowerCase2); - g_jetraceScript = new MxAtomId("\\lego\\scripts\\race\\jetrace", LookupMode_LowerCase2); - g_jetracerScript = new MxAtomId("\\lego\\scripts\\race\\jetracer", LookupMode_LowerCase2); - g_isleScript = new MxAtomId("\\lego\\scripts\\isle\\isle", LookupMode_LowerCase2); - g_elevbottScript = new MxAtomId("\\lego\\scripts\\infocntr\\elevbott", LookupMode_LowerCase2); - g_infodoorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infodoor", LookupMode_LowerCase2); - g_infomainScript = new MxAtomId("\\lego\\scripts\\infocntr\\infomain", LookupMode_LowerCase2); - g_infoscorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infoscor", LookupMode_LowerCase2); - g_regbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\regbook", LookupMode_LowerCase2); - g_histbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\histbook", LookupMode_LowerCase2); - g_hospitalScript = new MxAtomId("\\lego\\scripts\\hospital\\hospital", LookupMode_LowerCase2); - g_policeScript = new MxAtomId("\\lego\\scripts\\police\\police", LookupMode_LowerCase2); - g_garageScript = new MxAtomId("\\lego\\scripts\\garage\\garage", LookupMode_LowerCase2); - g_act2mainScript = new MxAtomId("\\lego\\scripts\\act2\\act2main", LookupMode_LowerCase2); - g_act3Script = new MxAtomId("\\lego\\scripts\\act3\\act3", LookupMode_LowerCase2); - g_jukeboxScript = new MxAtomId("\\lego\\scripts\\isle\\jukebox", LookupMode_LowerCase2); - g_pz5Script = new MxAtomId("\\lego\\scripts\\isle\\pz5", LookupMode_LowerCase2); - g_introScript = new MxAtomId("\\lego\\scripts\\intro", LookupMode_LowerCase2); - g_testScript = new MxAtomId("\\lego\\scripts\\test\\test", LookupMode_LowerCase2); - g_jukeboxwScript = new MxAtomId("\\lego\\scripts\\isle\\jukeboxw", LookupMode_LowerCase2); - g_sndAnimScript = new MxAtomId("\\lego\\scripts\\sndanim", LookupMode_LowerCase2); - g_creditsScript = new MxAtomId("\\lego\\scripts\\credits", LookupMode_LowerCase2); - g_nocdSourceName = new MxAtomId("\\lego\\scripts\\nocd", LookupMode_LowerCase2); + g_copterScript = new MxAtomId("\\lego\\scripts\\build\\copter", e_lowerCase2); + g_dunecarScript = new MxAtomId("\\lego\\scripts\\build\\dunecar", e_lowerCase2); + g_jetskiScript = new MxAtomId("\\lego\\scripts\\build\\jetski", e_lowerCase2); + g_racecarScript = new MxAtomId("\\lego\\scripts\\build\\racecar", e_lowerCase2); + g_carraceScript = new MxAtomId("\\lego\\scripts\\race\\carrace", e_lowerCase2); + g_carracerScript = new MxAtomId("\\lego\\scripts\\race\\carracer", e_lowerCase2); + g_jetraceScript = new MxAtomId("\\lego\\scripts\\race\\jetrace", e_lowerCase2); + g_jetracerScript = new MxAtomId("\\lego\\scripts\\race\\jetracer", e_lowerCase2); + g_isleScript = new MxAtomId("\\lego\\scripts\\isle\\isle", e_lowerCase2); + g_elevbottScript = new MxAtomId("\\lego\\scripts\\infocntr\\elevbott", e_lowerCase2); + g_infodoorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infodoor", e_lowerCase2); + g_infomainScript = new MxAtomId("\\lego\\scripts\\infocntr\\infomain", e_lowerCase2); + g_infoscorScript = new MxAtomId("\\lego\\scripts\\infocntr\\infoscor", e_lowerCase2); + g_regbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\regbook", e_lowerCase2); + g_histbookScript = new MxAtomId("\\lego\\scripts\\infocntr\\histbook", e_lowerCase2); + g_hospitalScript = new MxAtomId("\\lego\\scripts\\hospital\\hospital", e_lowerCase2); + g_policeScript = new MxAtomId("\\lego\\scripts\\police\\police", e_lowerCase2); + g_garageScript = new MxAtomId("\\lego\\scripts\\garage\\garage", e_lowerCase2); + g_act2mainScript = new MxAtomId("\\lego\\scripts\\act2\\act2main", e_lowerCase2); + g_act3Script = new MxAtomId("\\lego\\scripts\\act3\\act3", e_lowerCase2); + g_jukeboxScript = new MxAtomId("\\lego\\scripts\\isle\\jukebox", e_lowerCase2); + g_pz5Script = new MxAtomId("\\lego\\scripts\\isle\\pz5", e_lowerCase2); + g_introScript = new MxAtomId("\\lego\\scripts\\intro", e_lowerCase2); + g_testScript = new MxAtomId("\\lego\\scripts\\test\\test", e_lowerCase2); + g_jukeboxwScript = new MxAtomId("\\lego\\scripts\\isle\\jukeboxw", e_lowerCase2); + g_sndAnimScript = new MxAtomId("\\lego\\scripts\\sndanim", e_lowerCase2); + g_creditsScript = new MxAtomId("\\lego\\scripts\\credits", e_lowerCase2); + g_nocdSourceName = new MxAtomId("\\lego\\scripts\\nocd", e_lowerCase2); } // FUNCTION: LEGO1 0x100530c0 @@ -577,10 +611,20 @@ void LegoOmni::RemoveWorld(const MxAtomId&, MxLong) // TODO } -// STUB: LEGO1 0x1005b0c0 +// FUNCTION: LEGO1 0x1005b0c0 LegoEntity* LegoOmni::FindByEntityIdOrAtomId(const MxAtomId& p_atom, MxS32 p_entityid) { - // TODO + if (m_worldList) { + LegoWorld* world; + LegoWorldListCursor cursor(m_worldList); + + while (cursor.Next(world)) { + if ((p_entityid == -1 || world->GetEntityId() == p_entityid) && + (!p_atom.GetInternal() || world->GetAtom() == p_atom)) + return world; + } + } + return NULL; } @@ -595,7 +639,7 @@ MxEntity* LegoOmni::FindWorld(const char* p_id, MxS32 p_entityId, MxPresenter* p { LegoWorld* foundEntity = NULL; if (strcmpi(p_id, g_current)) { - foundEntity = (LegoWorld*) FindByEntityIdOrAtomId(MxAtomId(p_id, LookupMode_LowerCase2), p_entityId); + foundEntity = (LegoWorld*) FindByEntityIdOrAtomId(MxAtomId(p_id, e_lowerCase2), p_entityId); } else { foundEntity = this->m_currentWorld; @@ -636,6 +680,29 @@ MxS32 LegoOmni::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) return GetCurrentWorld()->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() { @@ -666,7 +733,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; @@ -685,9 +752,3 @@ void LegoOmni::StopTimer() MxOmni::StopTimer(); SetAppCursor(0); } - -// FUNCTION: LEGO1 0x100acf50 -MxResult Start(MxDSAction* p_dsAction) -{ - return MxOmni::GetInstance()->Start(p_dsAction); -} diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index a636253a..c187344c 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -6,8 +6,14 @@ LegoPathController::LegoPathController() // TODO } -// STUB: LEGO1 0x10045740 -LegoPathController::~LegoPathController() +// STUB: LEGO1 0x10045880 +void LegoPathController::VTable0x14() +{ + // TODO +} + +// STUB: LEGO1 0x10045b20 +void LegoPathController::Destroy() { // TODO } diff --git a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp index b8ab8faf..48d592a3 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathpresenter.cpp @@ -17,13 +17,19 @@ void LegoPathPresenter::Init() { } +// FUNCTION: LEGO1 0x10044ac0 +LegoPathPresenter::~LegoPathPresenter() +{ + Destroy(TRUE); +} + // FUNCTION: LEGO1 0x10044b40 MxResult LegoPathPresenter::AddToManager() { MxResult status = FAILURE; if (VideoManager()) { - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); status = SUCCESS; } @@ -34,7 +40,7 @@ MxResult LegoPathPresenter::AddToManager() void LegoPathPresenter::Destroy(MxBool p_fromDestructor) { if (VideoManager()) - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); { MxAutoLocker lock(&this->m_criticalSection); @@ -51,6 +57,27 @@ void LegoPathPresenter::Destroy() Destroy(FALSE); } +// STUB: LEGO1 0x10044c20 +void LegoPathPresenter::ReadyTickle() +{ + // TODO + ProgressTickleState(e_starting); // Allow initialization process to continue +} + +// FUNCTION: LEGO1 0x10044d00 +void LegoPathPresenter::StreamingTickle() +{ + MxStreamChunk* chunk = m_subscriber->NextChunk(); + + if (chunk) { + if (chunk->GetFlags() & MxStreamChunk::c_end) { + ProgressTickleState(e_repeating); + } + + m_subscriber->DestroyChunk(chunk); + } +} + // FUNCTION: LEGO1 0x10044d40 void LegoPathPresenter::RepeatingTickle() { diff --git a/LEGO1/lego/legoomni/src/police/policestate.cpp b/LEGO1/lego/legoomni/src/police/policestate.cpp index a2c66a45..4965a36f 100644 --- a/LEGO1/lego/legoomni/src/police/policestate.cpp +++ b/LEGO1/lego/legoomni/src/police/policestate.cpp @@ -1,7 +1,12 @@ #include "policestate.h" -// STUB: LEGO1 0x1005e7c0 +#include + +DECOMP_SIZE_ASSERT(PoliceState, 0x10) + +// FUNCTION: LEGO1 0x1005e7c0 PoliceState::PoliceState() { - // TODO + m_unk0xc = 0; + m_unk0x8 = (rand() % 2 == 0) ? 501 : 500; } diff --git a/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp index 444eeccf..476c6291 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimationmanager.cpp @@ -21,6 +21,11 @@ LegoAnimationManager::~LegoAnimationManager() // TODO } +// STUB: LEGO1 0x1005ef10 +void LegoAnimationManager::FUN_1005ef10() +{ +} + // STUB: LEGO1 0x1005f130 void LegoAnimationManager::Init() { @@ -33,6 +38,12 @@ void LegoAnimationManager::FUN_1005f6d0(MxBool) // TODO } +// STUB: LEGO1 0x1005f720 +void LegoAnimationManager::FUN_1005f720(undefined4) +{ + // TODO +} + // STUB: LEGO1 0x100619f0 MxLong LegoAnimationManager::Notify(MxParam& p_param) { diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp index 2bdd7475..31fe68b3 100644 --- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp @@ -1,13 +1,243 @@ #include "legoanimpresenter.h" -// STUB: LEGO1 0x10068420 +#include "legoomni.h" +#include "legostream.h" +#include "legoworld.h" +#include "mxcompositepresenter.h" +#include "mxdsanim.h" +#include "mxstreamchunk.h" + +DECOMP_SIZE_ASSERT(LegoAnimPresenter, 0xc0) +DECOMP_SIZE_ASSERT(LegoAnimClassBase, 0x08) +DECOMP_SIZE_ASSERT(LegoAnimClass, 0x18) + +// FUNCTION: LEGO1 0x10068420 LegoAnimPresenter::LegoAnimPresenter() +{ + Init(); +} + +// FUNCTION: LEGO1 0x10068670 +LegoAnimPresenter::~LegoAnimPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x100686f0 +void LegoAnimPresenter::Init() +{ + m_unk0x64 = NULL; + m_unk0x68 = 0; + m_unk0x6c = 0; + m_unk0x74 = 0; + m_unk0x70 = 0; + m_unk0x78 = 0; + m_unk0x7c = 0; + m_unk0xa8.Clear(); + m_unk0xa4 = 0; + m_currentWorld = NULL; + m_unk0x95 = 0; + m_unk0x88 = -1; + m_unk0x98 = 0; + m_animAtom.Clear(); + m_unk0x9c = 0; + m_unk0x8c = 0; + m_unk0x90 = 0; + m_unk0x94 = 0; + m_unk0x96 = 1; + m_unk0xa0 = 0; +} + +// STUB: LEGO1 0x10068770 +void LegoAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + // TODO + MxVideoPresenter::Destroy(p_fromDestructor); +} + +// FUNCTION: LEGO1 0x10068fb0 +MxResult LegoAnimPresenter::VTable0x88(MxStreamChunk* p_chunk) +{ + MxResult result = FAILURE; + LegoMemoryStream stream((char*) p_chunk->GetData()); + + MxS32 magicSig; + MxS32 val2 = 0; + MxS32 val3; + + if (stream.Read(&magicSig, sizeof(MxS32)) == SUCCESS && magicSig == 0x11) { + if (stream.Read(&m_unk0xa4, sizeof(MxU32)) == SUCCESS) { + if (stream.Read(&m_unk0xa8[0], sizeof(float)) == SUCCESS) { + if (stream.Read(&m_unk0xa8[1], sizeof(float)) == SUCCESS) { + if (stream.Read(&m_unk0xa8[2], sizeof(float)) == SUCCESS) { + if (stream.Read(&val2, sizeof(MxS32)) == SUCCESS) { + if (stream.Read(&val3, sizeof(MxS32)) == SUCCESS) { + m_unk0x64 = new LegoAnimClass(); + if (m_unk0x64) { + if (m_unk0x64->VTable0x10(&stream, val2) == SUCCESS) { + result = SUCCESS; + } + } + } + } + } + } + } + } + } + + if (result != SUCCESS) { + delete m_unk0x64; + Init(); + } + + return result; +} + +// STUB: LEGO1 0x1006ad30 +void LegoAnimPresenter::PutFrame() { // TODO } -// STUB: LEGO1 0x100686f0 -void LegoAnimPresenter::Init() +// FUNCTION: LEGO1 0x1006b550 +void LegoAnimPresenter::ReadyTickle() +{ + m_currentWorld = GetCurrentWorld(); + + if (m_currentWorld) { + MxStreamChunk* chunk = m_subscriber->CurrentChunk(); + + if (chunk && chunk->GetTime() + m_action->GetStartTime() <= m_action->GetElapsedTime()) { + chunk = m_subscriber->NextChunk(); + MxResult result = VTable0x88(chunk); + m_subscriber->DestroyChunk(chunk); + + if (result == SUCCESS) { + ProgressTickleState(e_starting); + ParseExtra(); + } + else { + EndAction(); + } + } + } +} + +// STUB: LEGO1 0x1006b5e0 +void LegoAnimPresenter::StartingTickle() +{ + // TODO + ProgressTickleState(e_streaming); + EndAction(); // Allow game to start +} + +// FUNCTION: LEGO1 0x1006b840 +void LegoAnimPresenter::StreamingTickle() +{ + if (m_subscriber->CurrentChunk()) { + MxStreamChunk* chunk = m_subscriber->NextChunk(); + m_subscriber->DestroyChunk(chunk); + } + + if (m_unk0x95 == 0) { + if (m_unk0x64->m_unk0x8 + m_action->GetStartTime() < m_action->GetElapsedTime()) { + m_unk0x95 = 1; + } + } + else { + ProgressTickleState(e_done); + if (m_compositePresenter) { + if (m_compositePresenter->IsA("LegoAnimMMPresenter")) { + m_compositePresenter->VTable0x60(this); + } + } + } +} + +// FUNCTION: LEGO1 0x1006b8e0 +void LegoAnimPresenter::Destroy() +{ + Destroy(FALSE); +} + +// STUB: LEGO1 0x1006bac0 +void LegoAnimPresenter::ParseExtra() +{ + // TODO +} + +// FUNCTION: LEGO1 0x1006c620 +MxResult LegoAnimPresenter::StartAction(MxStreamController* p_controller, MxDSAction* p_action) +{ + MxResult result = MxVideoPresenter::StartAction(p_controller, p_action); + m_displayZ = 0; + return result; +} + +// STUB: LEGO1 0x1006c640 +void LegoAnimPresenter::EndAction() +{ + // TODO + MxVideoPresenter::EndAction(); +} + +// FUNCTION: LEGO1 0x10099dd0 +LegoAnimClassBase::LegoAnimClassBase() +{ + m_unk0x4 = 0; +} + +// STUB: LEGO1 0x10099e00 +LegoAnimClassBase::~LegoAnimClassBase() +{ + // TODO +} + +// STUB: LEGO1 0x10099e20 +void LegoAnimClassBase::VTable0x4() +{ +} + +// STUB: LEGO1 0x10099e40 +void LegoAnimClassBase::VTable0x8() +{ +} + +// STUB: LEGO1 0x10099f70 +void LegoAnimClassBase::VTable0xc() +{ +} + +// FUNCTION: LEGO1 0x100a0b30 +LegoAnimClass::LegoAnimClass() +{ + m_unk0x8 = 0; + m_unk0xc = 0; + m_unk0x10 = 0; + m_unk0x14 = 0; +} + +// STUB: LEGO1 0x100a0bc0 +LegoAnimClass::~LegoAnimClass() +{ + // TODO +} + +// STUB: LEGO1 0x100a0c70 +MxResult LegoAnimClass::VTable0x10(LegoMemoryStream* p_stream, MxS32) +{ + return SUCCESS; +} + +// STUB: LEGO1 0x100a0e30 +void LegoAnimClass::VTable0x8() +{ + // TODO +} + +// STUB: LEGO1 0x100a1040 +void LegoAnimClass::VTable0xc() { // TODO } diff --git a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp index f13165cc..00718629 100644 --- a/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legohideanimpresenter.cpp @@ -1,12 +1,43 @@ #include "legohideanimpresenter.h" +DECOMP_SIZE_ASSERT(LegoHideAnimPresenter, 0xc4) + // FUNCTION: LEGO1 0x1006d7e0 LegoHideAnimPresenter::LegoHideAnimPresenter() { Init(); } -// STUB: LEGO1 0x1006da50 +// FUNCTION: LEGO1 0x1006d9f0 +LegoHideAnimPresenter::~LegoHideAnimPresenter() +{ + Destroy(TRUE); +} + +// FUNCTION: LEGO1 0x1006da50 void LegoHideAnimPresenter::Init() { + m_unk0xc0 = NULL; +} + +// FUNCTION: LEGO1 0x1006da60 +void LegoHideAnimPresenter::Destroy(MxBool p_fromDestructor) +{ + m_criticalSection.Enter(); + + if (m_unk0xc0) + delete m_unk0xc0; + Init(); + + m_criticalSection.Leave(); + + // This appears to be a bug, since it results in an endless loop + if (!p_fromDestructor) + LegoHideAnimPresenter::Destroy(); +} + +// FUNCTION: LEGO1 0x1006dac0 +void LegoHideAnimPresenter::Destroy() +{ + Destroy(FALSE); } diff --git a/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp index 6314a4fd..f347545d 100644 --- a/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legometerpresenter.cpp @@ -1,6 +1,126 @@ #include "legometerpresenter.h" #include "decomp.h" +#include "mxbitmap.h" +#include "mxutil.h" -// Uncomment when member class variables are fleshed out. -// DECOMP_SIZE_ASSERT(LegoMeterPresenter, 0x94); // 0x1000a163 +DECOMP_SIZE_ASSERT(LegoMeterPresenter, 0x94) + +// GLOBAL: LEGO1 0x1010207c +// STRING: LEGO1 0x10101fb4 +const char* g_filterIndex = "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; + m_flags &= ~c_bit2; +} + +// FUNCTION: LEGO1 0x10043780 +LegoMeterPresenter::~LegoMeterPresenter() +{ + delete m_unk0x6c; +} + +// FUNCTION: LEGO1 0x10043800 +void LegoMeterPresenter::ParseExtra() +{ + char buffer[256]; + + MxStillPresenter::ParseExtra(); + *((MxU16*) &buffer[0]) = m_action->GetExtraLength(); + char* extraData = m_action->GetExtraData(); + + if (*((MxU16*) &buffer[0])) { + MxU16 len = *((MxU16*) &buffer[0]); + memcpy(buffer, extraData, len); + buffer[len] = '\0'; + + char result[256]; + if (KeyValueStringParse(buffer, g_type, result)) { + if (!strcmpi(result, g_leftToRight)) { + m_layout = 0; + } + else if (!strcmpi(result, g_rightToLeft)) { + m_layout = 1; + } + else if (!strcmpi(result, g_bottomToTop)) { + m_layout = 2; + } + else if (!strcmpi(result, g_topToBottom)) { + m_layout = 3; + } + } + + if (KeyValueStringParse(buffer, g_filterIndex, result)) { + m_type = atoi(result); + } + + if (KeyValueStringParse(buffer, g_variable, result)) { + m_variable = result; + } + else { + EndAction(); + } + } + else { + EndAction(); + } +} + +// FUNCTION: LEGO1 0x10043990 +void LegoMeterPresenter::StreamingTickle() +{ + MxStillPresenter::StreamingTickle(); + m_unk0x6c = new MxU8[m_bitmap->GetBmiStride() * m_bitmap->GetBmiHeightAbs()]; + if (m_unk0x6c == NULL) { + EndAction(); + } + + memcpy(m_unk0x6c, m_bitmap->GetBitmapData(), m_bitmap->GetBmiStride() * m_bitmap->GetBmiHeightAbs()); + + m_unk0x88 = 0; + m_unk0x8a = 0; + m_unk0x8c = m_bitmap->GetBmiWidth() - 1; + m_unk0x8e = m_bitmap->GetBmiHeightAbs() - 1; +} + +// FUNCTION: LEGO1 0x10043a30 +void LegoMeterPresenter::RepeatingTickle() +{ + FUN_10043a50(); + MxStillPresenter::RepeatingTickle(); +} + +// STUB: LEGO1 0x10043a50 +void LegoMeterPresenter::FUN_10043a50() +{ +} diff --git a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp index d9608461..4f835212 100644 --- a/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legomodelpresenter.cpp @@ -15,16 +15,23 @@ void LegoModelPresenter::configureLegoModelPresenter(MxS32 p_modelPresenterConfi g_modelPresenterConfig = p_modelPresenterConfig; } -// STUB: LEGO1 0x1007f670 +// FUNCTION: LEGO1 0x1007f670 void LegoModelPresenter::Destroy(MxBool p_fromDestructor) { - // TODO + m_criticalSection.Enter(); + m_unk0x64 = 0; + m_addedToView = FALSE; + m_criticalSection.Leave(); + if (!p_fromDestructor) { + MxVideoPresenter::Destroy(FALSE); + } } // STUB: LEGO1 0x10080050 void LegoModelPresenter::ReadyTickle() { // TODO + SetTickleState(e_starting); } // STUB: LEGO1 0x100801b0 diff --git a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp index 821942b9..ce352f7e 100644 --- a/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legopalettepresenter.cpp @@ -49,12 +49,13 @@ void LegoPalettePresenter::Destroy() MxResult LegoPalettePresenter::ParsePalette(MxStreamChunk* p_chunk) { MxU8 buffer[40]; - RGBQUAD palleteData[256]; + RGBQUAD palette[256]; MxResult result = FAILURE; + LegoMemoryStream stream((char*) p_chunk->GetData()); - if (stream.Read(buffer, 40) == SUCCESS) { - if (stream.Read(palleteData, sizeof(RGBQUAD) * 256) == SUCCESS) { - m_palette = new MxPalette(palleteData); + if (stream.Read(buffer, sizeof(buffer)) == SUCCESS) { + if (stream.Read(palette, sizeof(palette)) == SUCCESS) { + m_palette = new MxPalette(palette); if (m_palette) { result = SUCCESS; } @@ -76,8 +77,8 @@ void LegoPalettePresenter::ReadyTickle() if (chunk) { if (chunk->GetTime() <= m_action->GetElapsedTime()) { ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); + chunk = m_subscriber->NextChunk(); MxResult result = ParsePalette(chunk); m_subscriber->DestroyChunk(chunk); diff --git a/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp index 6d0cbe8c..e376966f 100644 --- a/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp +++ b/LEGO1/lego/legoomni/src/video/legotexturepresenter.cpp @@ -7,13 +7,13 @@ // FUNCTION: LEGO1 0x1004eb40 LegoTexturePresenter::~LegoTexturePresenter() { - VideoManager()->RemovePresenter(*this); + VideoManager()->UnregisterPresenter(*this); } // FUNCTION: LEGO1 0x1004ebb0 MxResult LegoTexturePresenter::AddToManager() { - VideoManager()->AddPresenter(*this); + VideoManager()->RegisterPresenter(*this); return SUCCESS; } @@ -28,7 +28,7 @@ MxResult LegoTexturePresenter::PutData() void LegoTexturePresenter::DoneTickle() { if (this->m_compositePresenter && !this->m_compositePresenter->VTable0x64(2)) { - SetTickleState(TickleState_Idle); + SetTickleState(e_idle); return; } diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 1db16c2c..2a5d1643 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -10,6 +10,7 @@ DECOMP_SIZE_ASSERT(LegoVideoManager, 0x590); DECOMP_SIZE_ASSERT(MxStopWatch, 0x18); +DECOMP_SIZE_ASSERT(MxFrequencyMeter, 0x20); // FUNCTION: LEGO1 0x1007aa20 LegoVideoManager::LegoVideoManager() @@ -64,10 +65,10 @@ MxResult LegoVideoManager::Create(MxVideoParam& p_videoParam, MxU32 p_frequencyM MxResult result = FAILURE; MxDeviceEnumerate100d9cc8 deviceEnumerate; - Vector3Data posVec(0.0, 1.25, -50.0); - Vector3Data dirVec(0.0, 0.0, 1.0); - Vector3Data upVec(0.0, 1.0, 0.0); - Matrix4Data outMatrix; + Mx3DPointFloat posVec(0.0, 1.25, -50.0); + Mx3DPointFloat dirVec(0.0, 0.0, 1.0); + Mx3DPointFloat upVec(0.0, 1.0, 0.0); + MxMatrix outMatrix; HWND hwnd = MxOmni::GetInstance()->GetWindowHandle(); MxS32 bits = p_videoParam.Flags().Get16Bit() ? 16 : 8; MxS32 deviceNum = -1; @@ -229,7 +230,7 @@ void LegoVideoManager::MoveCursor(MxS32 p_cursorX, MxS32 p_cursorY) MxResult LegoVideoManager::Tickle() { if (m_unk0x554 && !m_videoParam.Flags().GetFlipSurfaces() && - TransitionManager()->GetTransitionType() == MxTransitionManager::NOT_TRANSITIONING) + TransitionManager()->GetTransitionType() == MxTransitionManager::e_notTransitioning) Sleep(30); m_stopWatch->Stop(); @@ -368,7 +369,7 @@ void LegoVideoManager::EnableFullScreenMovie(MxBool p_enable, MxBool p_scale) m_fullScreenMovie = TRUE; } else { - m_displaySurface->FUN_100ba640(); + m_displaySurface->ClearScreen(); m_displaySurface->GetVideoParam().Flags().SetF1bit3(FALSE); // restore previous pallete @@ -422,7 +423,7 @@ void LegoVideoManager::OverrideSkyColor(MxBool p_shouldOverride) } // FUNCTION: LEGO1 0x1007c4d0 -void LegoVideoManager::VTable0x34(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height) +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(); @@ -461,7 +462,7 @@ MxResult LegoVideoManager::ConfigureD3DRM() MxAssignedDevice* assignedDevice = m_direct3d->GetAssignedDevice(); - if (assignedDevice && assignedDevice->GetFlags() & MxAssignedDevice::Flag_HardwareMode) { + if (assignedDevice && assignedDevice->GetFlags() & MxAssignedDevice::c_hardwareMode) { if (assignedDevice->GetDesc().dpcTriCaps.dwTextureFilterCaps & D3DPTFILTERCAPS_LINEAR) d3drm->SetTextureQuality(D3DRMTEXTURE_LINEAR); diff --git a/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp index 734b4eae..677837bf 100644 --- a/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/video/mxtransitionmanager.cpp @@ -17,7 +17,7 @@ RECT g_fullScreenRect = {0, 0, 640, 480}; MxTransitionManager::MxTransitionManager() { m_animationTimer = 0; - m_transitionType = NOT_TRANSITIONING; + m_transitionType = e_notTransitioning; m_ddSurface = NULL; m_waitIndicator = NULL; m_copyBuffer = NULL; @@ -57,22 +57,22 @@ MxResult MxTransitionManager::Tickle() this->m_systemTime = timeGetTime(); switch (this->m_transitionType) { - case NO_ANIMATION: + case e_noAnimation: TransitionNone(); break; - case DISSOLVE: + case e_dissolve: TransitionDissolve(); break; - case PIXELATION: + case e_pixelation: TransitionPixelation(); break; - case SCREEN_WIPE: + case e_screenWipe: TransitionWipe(); break; - case WINDOWS: + case e_windows: TransitionWindows(); break; - case BROKEN: + case e_broken: TransitionBroken(); break; } @@ -87,7 +87,7 @@ MxResult MxTransitionManager::StartTransition( MxBool p_playMusicInAnim ) { - if (this->m_transitionType == NOT_TRANSITIONING) { + if (this->m_transitionType == e_notTransitioning) { if (!p_playMusicInAnim) { MxBackgroundAudioManager* backgroundAudioManager = BackgroundAudioManager(); backgroundAudioManager->Stop(); @@ -102,7 +102,7 @@ MxResult MxTransitionManager::StartTransition( MxDSAction* action = m_waitIndicator->GetAction(); action->SetLoopCount(10000); - action->SetFlags(action->GetFlags() | MxDSAction::Flag_Bit10); + action->SetFlags(action->GetFlags() | MxDSAction::c_bit10); } MxU32 time = timeGetTime(); @@ -114,8 +114,8 @@ 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->SetRender3D(FALSE); @@ -129,8 +129,8 @@ MxResult MxTransitionManager::StartTransition( // FUNCTION: LEGO1 0x1004bc30 void MxTransitionManager::EndTransition(MxBool p_notifyWorld) { - if (m_transitionType != NOT_TRANSITIONING) { - m_transitionType = NOT_TRANSITIONING; + if (m_transitionType != e_notTransitioning) { + m_transitionType = e_notTransitioning; m_copyFlags.m_bit0 = FALSE; @@ -142,11 +142,11 @@ void MxTransitionManager::EndTransition(MxBool p_notifyWorld) if (world) { #ifdef COMPAT_MODE { - MxNotificationParam param(MXTRANSITIONMANAGER_TRANSITIONENDED, this); + MxNotificationParam param(c_notificationTransitioned, this); world->Notify(param); } #else - world->Notify(MxNotificationParam(MXTRANSITIONMANAGER_TRANSITIONENDED, this)); + world->Notify(MxNotificationParam(c_notificationTransitioned, this)); #endif } } @@ -157,7 +157,7 @@ void MxTransitionManager::EndTransition(MxBool p_notifyWorld) void MxTransitionManager::TransitionNone() { LegoVideoManager* videoManager = VideoManager(); - videoManager->GetDisplaySurface()->FUN_100ba640(); + videoManager->GetDisplaySurface()->ClearScreen(); EndTransition(TRUE); } @@ -475,7 +475,7 @@ void MxTransitionManager::SetWaitIndicator(MxVideoPresenter* p_waitIndicator) { // End current wait indicator if (m_waitIndicator != NULL) { - m_waitIndicator->GetAction()->SetFlags(m_waitIndicator->GetAction()->GetFlags() & ~MxDSAction::Flag_World); + m_waitIndicator->GetAction()->SetFlags(m_waitIndicator->GetAction()->GetFlags() & ~MxDSAction::c_world); m_waitIndicator->EndAction(); m_waitIndicator = NULL; } @@ -486,9 +486,9 @@ void MxTransitionManager::SetWaitIndicator(MxVideoPresenter* p_waitIndicator) m_waitIndicator = p_waitIndicator; LegoVideoManager* videoManager = VideoManager(); - videoManager->RemovePresenter(*m_waitIndicator); + videoManager->UnregisterPresenter(*m_waitIndicator); - if (m_waitIndicator->GetCurrentTickleState() < MxPresenter::TickleState_Streaming) { + if (m_waitIndicator->GetCurrentTickleState() < MxPresenter::e_streaming) { m_waitIndicator->Tickle(); } } @@ -542,7 +542,7 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) m_waitIndicator->Tickle(); // Check if wait indicator has started - if (m_waitIndicator->GetCurrentTickleState() >= MxPresenter::TickleState_Streaming) { + if (m_waitIndicator->GetCurrentTickleState() >= MxPresenter::e_streaming) { // Setup the copy rect MxU32 copyPitch = (p_ddsc->ddpfPixelFormat.dwRGBBitCount / 8) * (m_copyRect.right - m_copyRect.left + 1); // This uses m_copyRect, seemingly erroneously @@ -576,7 +576,7 @@ void MxTransitionManager::SetupCopyRect(LPDDSURFACEDESC p_ddsc) } // Setup display surface - if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::Flag_Bit5) != 0) { + if ((m_waitIndicator->GetAction()->GetFlags() & MxDSAction::c_bit5) != 0) { MxDisplaySurface* displaySurface = VideoManager()->GetDisplaySurface(); MxBool und = FALSE; displaySurface->VTable0x2c( diff --git a/LEGO1/lego/sources/3dmanager/lego3dmanager.h b/LEGO1/lego/sources/3dmanager/lego3dmanager.h index 8445800b..9d993f26 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dmanager.h +++ b/LEGO1/lego/sources/3dmanager/lego3dmanager.h @@ -4,8 +4,12 @@ #include "assert.h" #include "lego3dview.h" -class Tgl::Renderer; -class Tgl::Group; +namespace Tgl +{ +class Renderer; +class Group; +} // namespace Tgl + class ViewROI; // ??? for now @@ -53,6 +57,9 @@ class Lego3DManager { // ??? for now ViewLODListManager* GetViewLODListManager(); + // SYNTHETIC: LEGO1 0x100ab340 + // Lego3DManager::`scalar deleting destructor' + private: Tgl::Renderer* m_pRenderer; // 0x04 diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.cpp b/LEGO1/lego/sources/3dmanager/lego3dview.cpp index 04c9ea22..37b8215e 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.cpp +++ b/LEGO1/lego/sources/3dmanager/lego3dview.cpp @@ -10,11 +10,12 @@ DECOMP_SIZE_ASSERT(Lego3DView, 0xa8) ///////////////////////////////////////////////////////////////////////////// // Lego3DView -// STUB: LEGO1 0x100aae90 +// FUNCTION: LEGO1 0x100aae90 Lego3DView::Lego3DView() { m_pViewManager = 0; m_previousRenderTime = 0; + m_unk0x98 = 0; m_pPointOfView = 0; } @@ -24,27 +25,31 @@ Lego3DView::~Lego3DView() Destroy(); } -// STUB: LEGO1 0x100aaf90 +// FUNCTION: LEGO1 0x100aaf90 BOOL Lego3DView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) { double viewAngle = 45; - double frontClippingDistance = 1; - double backClippingDistance = 5000; + if (rCreateStruct.m_isWideViewAngle) + viewAngle = 90; + + float frontClippingDistance = 0.1; + float backClippingDistance = 500; if (!LegoView1::Create(rCreateStruct, pRenderer)) { return FALSE; } - // assert(GetView()); - // GetView()->SetFrustrum(frontClippingDistance, backClippingDistance, viewAngle); + assert(GetView()); + GetView()->SetFrustrum(frontClippingDistance, backClippingDistance, viewAngle); - // assert(GetScene()); - // assert(!m_pViewManager); + assert(GetScene()); + assert(!m_pViewManager); - // m_pViewManager = new ViewManager(GetScene(), 0); - // m_pViewManager->SetResolution(GetWidth(), GetHeight()); - // m_pViewManager->SetFrustrum(viewAngle, -frontClippingDistance, -backClippingDistance); - // m_previousRenderTime = 0; + m_pViewManager = new ViewManager(pRenderer, GetScene(), 0); + m_pViewManager->SetResolution(GetWidth(), GetHeight()); + m_pViewManager->SetFrustrum(viewAngle, frontClippingDistance, backClippingDistance); + m_previousRenderTime = 0; + m_unk0x98 = 0; // // NOTE: a derived class must inform view manager when it configures // // its (Tgl) view: calling Tgl::View::SetFrustrum() should be @@ -53,12 +58,12 @@ BOOL Lego3DView::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Rend return TRUE; } -// STUB: LEGO1 0x100ab0b0 +// FUNCTION: LEGO1 0x100ab0b0 void Lego3DView::Destroy() { if (m_pPointOfView) { m_pPointOfView = 0; - // m_pViewManager->SetPOVSource(0); + m_pViewManager->SetPOVSource(0); } delete m_pViewManager; diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.h b/LEGO1/lego/sources/3dmanager/lego3dview.h index 986d652c..7e68bdcb 100644 --- a/LEGO1/lego/sources/3dmanager/lego3dview.h +++ b/LEGO1/lego/sources/3dmanager/lego3dview.h @@ -3,9 +3,7 @@ #include "decomp.h" #include "legoview1.h" - -class ViewROI; -class ViewManager; +#include "viewmanager/viewmanager.h" ///////////////////////////////////////////////////////////////////////////// // Lego3DView @@ -35,11 +33,9 @@ class Lego3DView : public LegoView1 { private: ViewManager* m_pViewManager; // 0x88 - double m_previousRenderTime; // 0x8c - - ViewROI* m_pPointOfView; // 0x90 - - undefined m_unk0x94[0x0c]; // 0x94 + double m_previousRenderTime; // 0x90 + double m_unk0x98; // 0x98 + ViewROI* m_pPointOfView; // 0xa0 }; // SYNTHETIC: LEGO1 0x100aaf10 diff --git a/LEGO1/lego/sources/3dmanager/legoview1.cpp b/LEGO1/lego/sources/3dmanager/legoview1.cpp index 3705eb33..97114469 100644 --- a/LEGO1/lego/sources/3dmanager/legoview1.cpp +++ b/LEGO1/lego/sources/3dmanager/legoview1.cpp @@ -4,13 +4,24 @@ #include "legoview1.h" #include "decomp.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" #include "realtime/realtime.h" -#include // SETMAT4 +#include DECOMP_SIZE_ASSERT(LegoView, 0x78); DECOMP_SIZE_ASSERT(LegoView1, 0x88); +// GLOBAL: LEGO1 0x101013e4 +float g_sunLightRGB = 1.0; + +// GLOBAL: LEGO1 0x101013e8 +float g_directionalLightRGB = 1.0; + +// GLOBAL: LEGO1 0x101013ec +float g_ambientLightRGB = 0.3; + ///////////////////////////////////////////////////////////////////////////// // LegoView @@ -112,51 +123,39 @@ BOOL LegoView1::AddLightsToViewport() return TRUE; } -// STUB: LEGO1 0x100ab860 +// FUNCTION: LEGO1 0x100ab860 BOOL LegoView1::Create(const TglSurface::CreateStruct& rCreateStruct, Tgl::Renderer* pRenderer) { - double position[3] = {0, 0, 0}; - double direction[3]; - double up[3] = {0, 1, 0}; - if (!LegoView::Create(rCreateStruct, pRenderer)) { return FALSE; } // lights - m_pSunLight = pRenderer->CreateLight(Tgl::Directional, .9, .9, .9); - m_pDirectionalLight = pRenderer->CreateLight(Tgl::Directional, .4, .4, .4); - m_pAmbientLight = pRenderer->CreateLight(Tgl::Ambient, .3, .3, .3); + m_pSunLight = pRenderer->CreateLight(Tgl::Point, g_sunLightRGB, g_sunLightRGB, g_sunLightRGB); + m_pDirectionalLight = + pRenderer->CreateLight(Tgl::Directional, g_directionalLightRGB, g_directionalLightRGB, g_directionalLightRGB); + m_pAmbientLight = pRenderer->CreateLight(Tgl::Ambient, g_ambientLightRGB, g_ambientLightRGB, g_ambientLightRGB); -#if 0 - direction[0] = 1, direction[1] = -1, direction[2] = 2; - m_pSunLight->SetOrientation(direction, up); - direction[0] = -1, direction[1] = -2, direction[2] = -1; - m_pDirectionalLight->SetOrientation(direction, up); -#else - { - // Change everything to float and proper Matrix types - /* - Tgl::FloatMatrix4 transformation; - Matrix4Data transform; + Mx3DPointFloat direction(0.0, -1.0, 0.0); + Mx3DPointFloat position(0.0, 0.0, 0.0); + Mx3DPointFloat up(1.0, 0.0, 0.0); - direction[0] = 1, direction[1] = -1, direction[2] = 2; - CalcLocalTransform(position, direction, up, transform); - SETMAT4(transformation, transform); - m_pSunLight->SetTransformation(transformation); + Tgl::FloatMatrix4 matrix; + Matrix4 in(matrix); + MxMatrix transform; - direction[0] = -1, direction[1] = -2, direction[2] = -1; - CalcLocalTransform(position, direction, up, transform); - SETMAT4(transformation, transform); - m_pDirectionalLight->SetTransformation(transformation); - */ - } -#endif + CalcLocalTransform(position, direction, up, transform); + SETMAT4(in, transform); + m_pDirectionalLight->SetTransformation(matrix); + + direction[0] = 0, direction[1] = 150, direction[2] = -150; + CalcLocalTransform(position, direction, up, transform); + SETMAT4(in, transform); + m_pSunLight->SetTransformation(matrix); assert(GetView()); - AddLightsToViewport(); - return TRUE; + return AddLightsToViewport(); } // FUNCTION: LEGO1 0x100abad0 diff --git a/LEGO1/lego/sources/3dmanager/legoview1.h b/LEGO1/lego/sources/3dmanager/legoview1.h index 20ccadfa..4060e54f 100644 --- a/LEGO1/lego/sources/3dmanager/legoview1.h +++ b/LEGO1/lego/sources/3dmanager/legoview1.h @@ -2,14 +2,18 @@ #define _LegoView1_h #include "compat.h" +#include "decomp.h" #include "tglsurface.h" -class Tgl::Camera; +namespace Tgl +{ +class Camera; +} ///////////////////////////////////////////////////////////////////////////// // LegoView -// VTABLE: 0x100dc000 +// VTABLE: LEGO1 0x100dc000 // SIZE 0x78 class LegoView : public TglSurface { public: diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.cpp b/LEGO1/lego/sources/3dmanager/tglsurface.cpp index 2493e00c..394e03e5 100644 --- a/LEGO1/lego/sources/3dmanager/tglsurface.cpp +++ b/LEGO1/lego/sources/3dmanager/tglsurface.cpp @@ -195,7 +195,12 @@ double TglSurface::Render() #ifdef _DEBUG { +#if 0 + // FIXME: Tgl::Device::GetDrawnTriangleCount does not exist unsigned long triangleCount = m_pDevice->GetDrawnTriangleCount(); +#else + unsigned long triangleCount = 0; +#endif m_triangleRateMeter.IncreaseOperationCount(triangleCount - m_triangleCount - 1); m_triangleCount = triangleCount; diff --git a/LEGO1/lego/sources/3dmanager/tglsurface.h b/LEGO1/lego/sources/3dmanager/tglsurface.h index 2ea4cf12..2b97db50 100644 --- a/LEGO1/lego/sources/3dmanager/tglsurface.h +++ b/LEGO1/lego/sources/3dmanager/tglsurface.h @@ -4,10 +4,13 @@ #include "mxdirectx/mxstopwatch.h" #include "tgl/tgl.h" -class Tgl::Renderer; -class Tgl::Device; -class Tgl::View; -class Tgl::Group; +namespace Tgl +{ +class Renderer; +class Device; +class View; +class Group; +} // namespace Tgl ///////////////////////////////////////////////////////////////////////////// // TglSurface diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index dab06a1a..9d530b16 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -38,18 +38,18 @@ MxS32 g_roiConfig = 100; ROIHandler g_someHandlerFunction = NULL; // FUNCTION: LEGO1 0x100a46a0 -void LegoROI::WrappedSetLocalTransform(Matrix4Impl& p_transform) +void LegoROI::WrappedSetLocalTransform(Matrix4& p_transform) { SetLocalTransform(p_transform); } // STUB: LEGO1 0x100a46b0 -void LegoROI::FUN_100a46b0(Matrix4Impl& p_transform) +void LegoROI::FUN_100a46b0(Matrix4& p_transform) { } // STUB: LEGO1 0x100a58f0 -void LegoROI::FUN_100a58f0(Matrix4Impl& p_transform) +void LegoROI::FUN_100a58f0(Matrix4& p_transform) { } diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index d84e8df4..302a0bd8 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -6,6 +6,8 @@ typedef MxBool (*ROIHandler)(char*, char*, MxU32); +class LegoEntity; + // Note: There is an extra class between LegoROI and ViewROI, // maybe called "AutoROI". VTABLE 0x100dbe38 @@ -15,6 +17,9 @@ class LegoROI : public ViewROI { public: LegoROI(Tgl::Renderer* p_renderer, ViewLODList* p_lodList, MxTime p_time); + // Note: Actually part of parent class (doesn't exist yet) + virtual void UpdateWorldBoundingVolumes() override; // vtable+0x18 + __declspec(dllexport) void SetDisplayBB(MxS32 p_displayBB); __declspec(dllexport) static void configureLegoROI(MxS32 p_roi); @@ -28,16 +33,20 @@ class LegoROI : public ViewROI { ); static MxBool ColorAliasLookup(char* p_param, MxFloat& p_red, MxFloat& p_green, MxFloat& p_blue, MxFloat& p_other); - void WrappedSetLocalTransform(Matrix4Impl& p_transform); - void FUN_100a46b0(Matrix4Impl& p_transform); - void FUN_100a58f0(Matrix4Impl& p_transform); + void WrappedSetLocalTransform(Matrix4& p_transform); + void FUN_100a46b0(Matrix4& p_transform); + void FUN_100a58f0(Matrix4& p_transform); - // Note: Actually part of parent class (doesn't exist yet) - virtual void UpdateWorldBoundingVolumes() override; // vtable+0x18 + inline LegoEntity* GetUnknown0x104() { return m_unk0x104; } + inline void SetUnknown0x104(LegoEntity* p_unk0x104) { m_unk0x104 = p_unk0x104; } + + // SYNTHETIC: LEGO1 0x100a9ad0 + // LegoROI::`scalar deleting destructor' private: - undefined m_pad[0x28]; // 0xe0 - MxTime m_time; // 0x108 + undefined m_pad[0x24]; // 0xe0 + LegoEntity* m_unk0x104; // 0x104 + MxTime m_time; // 0x108 }; #endif // LEGOROI_H diff --git a/LEGO1/library_flic.h b/LEGO1/library_flic.h new file mode 100644 index 00000000..1c6a6d8b --- /dev/null +++ b/LEGO1/library_flic.h @@ -0,0 +1,6 @@ +#ifdef 0 + +// LIBRARY: LEGO1 0x100bdce0 +// _DecodeFLCFrame + +#endif diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 20ae06ef..259ed919 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -1,49 +1,111 @@ #ifdef 0 +// For LEGO1 symbols only // aka `operator new` -// LIBRARY: ISLE 0x402f80 // LIBRARY: LEGO1 0x10086240 // ??2@YAPAXI@Z // aka `operator delete` -// LIBRARY: ISLE 0x402fa0 // LIBRARY: LEGO1 0x10086260 // ??3@YAXPAX@Z -// LIBRARY: ISLE 0x406dd0 // LIBRARY: LEGO1 0x1008a090 // _malloc -// LIBRARY: ISLE 0x406f00 // LIBRARY: LEGO1 0x1008a1c0 // _free -// LIBRARY: ISLE 0x408220 +// LIBRARY: LEGO1 0x1008b020 +// ___CxxFrameHandler + // LIBRARY: LEGO1 0x1008b400 // _atol -// LIBRARY: ISLE 0x4082d0 // LIBRARY: LEGO1 0x1008b4b0 // _atoi // LIBRARY: LEGO1 0x1008b4c0 // _strtok -// LIBRARY: ISLE 0x4085c0 // LIBRARY: LEGO1 0x1008b5a0 // _sprintf -// LIBRARY: ISLE 0x4081e0 +// LIBRARY: LEGO1 0x1008b608 +// __ftol + +// LIBRARY: LEGO1 0x1008b630 // _srand -// LIBRARY: ISLE 0x4081f0 // LIBRARY: LEGO1 0x1008b640 // _rand -// LIBRARY: ISLE 0x409110 -// __mtinit +// LIBRARY: LEGO1 0x1008b680 +// _strncmp -// LIBRARY: ISLE 0x409190 -// __getptd +// LIBRARY: LEGO1 0x1008b730 +// _fprintf + +// LIBRARY: LEGO1 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/omni/src/main/mxmain.cpp b/LEGO1/main.cpp similarity index 100% rename from LEGO1/omni/src/main/mxmain.cpp rename to LEGO1/main.cpp diff --git a/LEGO1/mxdirectx/mxdirect3d.cpp b/LEGO1/mxdirectx/mxdirect3d.cpp index c97ad0a9..b2166ca1 100644 --- a/LEGO1/mxdirectx/mxdirect3d.cpp +++ b/LEGO1/mxdirectx/mxdirect3d.cpp @@ -113,7 +113,7 @@ BOOL MxDirect3D::CreateIDirect3D() // FUNCTION: LEGO1 0x1009b310 BOOL MxDirect3D::D3DSetMode() { - if (m_assignedDevice->m_flags & MxAssignedDevice::Flag_HardwareMode) { + if (m_assignedDevice->m_flags & MxAssignedDevice::c_hardwareMode) { if (m_bOnlySoftRender) { Error("Failed to place vital surfaces in video memory for hardware driver", DDERR_GENERIC); return FALSE; @@ -265,7 +265,7 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri ); if (i == 0) - assignedDevice->m_flags |= MxAssignedDevice::Flag_PrimaryDevice; + assignedDevice->m_flags |= MxAssignedDevice::c_primaryDevice; for (list::iterator it2 = driver.m_devices.begin(); it2 != driver.m_devices.end(); it2++) { MxDevice& device = *it2; @@ -276,7 +276,7 @@ BOOL MxDirect3D::SetDevice(MxDeviceEnumerate& p_deviceEnumerate, MxDriver* p_dri D3DDEVICEDESC* desc; if (device.m_HWDesc.dcmColorModel) { - assignedDevice->m_flags |= MxAssignedDevice::Flag_HardwareMode; + assignedDevice->m_flags |= MxAssignedDevice::c_hardwareMode; desc = &device.m_HWDesc; } else diff --git a/LEGO1/mxdirectx/mxdirect3d.h b/LEGO1/mxdirectx/mxdirect3d.h index f0c87c69..2d89ad39 100644 --- a/LEGO1/mxdirectx/mxdirect3d.h +++ b/LEGO1/mxdirectx/mxdirect3d.h @@ -13,8 +13,8 @@ class MxDirect3D; class MxAssignedDevice { public: enum { - Flag_HardwareMode = 0x01, - Flag_PrimaryDevice = 0x02 + c_hardwareMode = 0x01, + c_primaryDevice = 0x02 }; MxAssignedDevice(); @@ -66,6 +66,9 @@ class MxDirect3D : public MxDirectDraw { 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 @@ -158,11 +161,15 @@ struct MxDriver { // List::~List // Compiler-generated copy ctor -// Part of this function are two more synthetic sub-routines, -// LEGO1 0x1009c400 and LEGO1 0x1009c460 // SYNTHETIC: LEGO1 0x1009c290 // MxDriver::MxDriver +// SYNTHETIC: LEGO1 0x1009c400 +// list >::insert + +// SYNTHETIC: LEGO1 0x1009c460 +// list >::insert + // SYNTHETIC: LEGO1 0x1009d450 // MxDriver::`scalar deleting destructor' @@ -223,4 +230,7 @@ class MxDeviceEnumerate { // SIZE 0x14 class MxDeviceEnumerate100d9cc8 : public MxDeviceEnumerate {}; +// SYNTHETIC: LEGO1 0x1007b590 +// MxDeviceEnumerate100d9cc8::~MxDeviceEnumerate100d9cc8 + #endif // MXDIRECT3D_H diff --git a/LEGO1/mxdirectx/mxdirectdraw.h b/LEGO1/mxdirectx/mxdirectdraw.h index 490233b5..b8f5f551 100644 --- a/LEGO1/mxdirectx/mxdirectdraw.h +++ b/LEGO1/mxdirectx/mxdirectdraw.h @@ -83,6 +83,9 @@ class MxDirectDraw { 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 diff --git a/LEGO1/mxdirectx/mxstopwatch.h b/LEGO1/mxdirectx/mxstopwatch.h index 7e7fcc38..0630d2f6 100644 --- a/LEGO1/mxdirectx/mxstopwatch.h +++ b/LEGO1/mxdirectx/mxstopwatch.h @@ -97,6 +97,9 @@ inline double MxStopWatch::ElapsedSeconds() const return m_elapsedSeconds; } +// SYNTHETIC: LEGO1 0x100a6fc0 +// MxStopWatch::~MxStopWatch + ////////////////////////////////////////////////////////////////////////////// // // MxFrequencyMeter @@ -182,4 +185,7 @@ inline double MxFrequencyMeter::ElapsedSeconds() const return m_stopWatch.ElapsedSeconds(); } +// SYNTHETIC: LEGO1 0x100abd10 +// MxFrequencyMeter::~MxFrequencyMeter + #endif /* _MxStopWatch_h */ diff --git a/LEGO1/mxgeometry/mxgeometry3d.cpp b/LEGO1/mxgeometry/mxgeometry3d.cpp new file mode 100644 index 00000000..03ce60eb --- /dev/null +++ b/LEGO1/mxgeometry/mxgeometry3d.cpp @@ -0,0 +1,6 @@ +#include "mxgeometry3d.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(Mx3DPointFloat, 0x14); +DECOMP_SIZE_ASSERT(Mx4DPointFloat, 0x18); diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h new file mode 100644 index 00000000..13781722 --- /dev/null +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -0,0 +1,48 @@ +#ifndef MXGEOMETRY3D_H +#define MXGEOMETRY3D_H + +#include "realtime/vector.h" + +// VTABLE: LEGO1 0x100d4488 +// SIZE 0x14 +class Mx3DPointFloat : public Vector3 { +public: + inline Mx3DPointFloat() : Vector3(m_elements) {} + inline Mx3DPointFloat(float p_x, float p_y, float p_z) : Vector3(m_elements) + { + m_elements[0] = p_x; + m_elements[1] = p_y; + m_elements[2] = p_z; + } + + // FUNCTION: LEGO1 0x10003c10 + virtual void operator=(const Vector3& p_impl) { EqualsImpl(p_impl.m_data); } // vtable+0x88 + + inline void CopyFrom(const Mx3DPointFloat& p_other) + { + // ALPHA: 0x10010860, multiple indirections to this call + EqualsImpl(p_other.m_data); + + float* dest = m_elements; + const float* src = p_other.m_elements; + for (size_t i = sizeof(m_elements) / sizeof(float); i > 0; --i) + *dest++ = *src++; + } + + inline void EqualsCross(Mx3DPointFloat& p_a, Mx3DPointFloat& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } + +private: + float m_elements[3]; +}; + +// VTABLE: LEGO1 0x100d41e8 +// SIZE 0x18 +class Mx4DPointFloat : public Vector4 { +public: + inline Mx4DPointFloat() : Vector4(m_elements) {} + +private: + float m_elements[4]; +}; + +#endif // MXGEOMETRY3D_H diff --git a/LEGO1/mxgeometry/mxmatrix.cpp b/LEGO1/mxgeometry/mxmatrix.cpp new file mode 100644 index 00000000..fc768f38 --- /dev/null +++ b/LEGO1/mxgeometry/mxmatrix.cpp @@ -0,0 +1,5 @@ +#include "mxmatrix.h" + +#include "decomp.h" + +DECOMP_SIZE_ASSERT(MxMatrix, 0x48); diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h new file mode 100644 index 00000000..2db07671 --- /dev/null +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -0,0 +1,22 @@ +#ifndef MXMATRIX_H +#define MXMATRIX_H + +#include "realtime/matrix.h" + +// VTABLE: LEGO1 0x100d4300 +// SIZE 0x48 +class MxMatrix : public Matrix4 { +public: + inline MxMatrix() : Matrix4(m_elements) {} + inline MxMatrix(const MxMatrix& p_matrix) : Matrix4(m_elements) { Equals(p_matrix); } + + // No idea why there's another equals. Maybe to some other type like the + // DirectX Retained Mode Matrix type which is also a float* alias? + // FUNCTION: LEGO1 0x10002860 + virtual void operator=(const MxMatrix& p_matrix) { Equals(p_matrix); } // vtable+0x48 + +private: + float m_elements[4][4]; +}; + +#endif // MXMATRIX_H diff --git a/LEGO1/omni/include/mxactionnotificationparam.h b/LEGO1/omni/include/mxactionnotificationparam.h index 24d9e5e1..5628cf7b 100644 --- a/LEGO1/omni/include/mxactionnotificationparam.h +++ b/LEGO1/omni/include/mxactionnotificationparam.h @@ -43,7 +43,11 @@ class MxActionNotificationParam : public MxNotificationParam { delete this->m_action; } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + // FUNCTION: LEGO1 0x100510c0 + virtual MxNotificationParam* Clone() override + { + return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc); + }; // vtable+0x4 inline MxDSAction* GetAction() { return m_action; } @@ -83,7 +87,16 @@ class MxEndActionNotificationParam : public MxActionNotificationParam { { } - virtual MxNotificationParam* Clone() override; // vtable+0x4 + // FUNCTION: LEGO1 0x10051270 + virtual MxNotificationParam* Clone() override + { + return new MxEndActionNotificationParam( + c_notificationEndAction, + this->m_sender, + this->m_action, + this->m_realloc + ); + }; // vtable+0x4 }; // VTABLE: LEGO1 0x100dc208 @@ -91,7 +104,7 @@ class MxEndActionNotificationParam : public MxActionNotificationParam { class MxType4NotificationParam : public MxActionNotificationParam { public: inline MxType4NotificationParam(MxCore* p_sender, MxDSAction* p_action, MxPresenter* p_unk0x14) - : MxActionNotificationParam(TYPE4, p_sender, p_action, FALSE) + : MxActionNotificationParam(c_notificationType4, p_sender, p_action, FALSE) { m_unk0x14 = p_unk0x14; } @@ -102,13 +115,25 @@ class MxType4NotificationParam : public MxActionNotificationParam { MxPresenter* m_unk0x14; // 0x14 }; +// SYNTHETIC: LEGO1 0x100511e0 +// MxActionNotificationParam::`scalar deleting destructor' + // SYNTHETIC: LEGO1 0x100513a0 // MxEndActionNotificationParam::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x10051410 +// MxEndActionNotificationParam::~MxEndActionNotificationParam + // SYNTHETIC: LEGO1 0x100b0430 // MxStartActionNotificationParam::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x100b04a0 +// MxStartActionNotificationParam::~MxStartActionNotificationParam + // SYNTHETIC: LEGO1 0x100b05c0 // MxType4NotificationParam::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x100b0630 +// MxType4NotificationParam::~MxType4NotificationParam + #endif diff --git a/LEGO1/omni/include/mxatomid.h b/LEGO1/omni/include/mxatomid.h index 3abe6479..388ffce3 100644 --- a/LEGO1/omni/include/mxatomid.h +++ b/LEGO1/omni/include/mxatomid.h @@ -5,12 +5,13 @@ #include "mxtypes.h" enum LookupMode { - LookupMode_Exact = 0, - LookupMode_LowerCase = 1, - LookupMode_UpperCase = 2, - LookupMode_LowerCase2 = 3 + e_exact = 0, + e_lowerCase, + e_upperCase, + e_lowerCase2, }; +// SIZE 0x04 class MxAtomId { public: __declspec(dllexport) MxAtomId(const char*, LookupMode); @@ -30,7 +31,7 @@ class MxAtomId { MxAtomIdCounter* GetCounter(const char*, LookupMode); void Destroy(); - const char* m_internal; + const char* m_internal; // 0x00 }; #endif // MXATOMID_H diff --git a/LEGO1/omni/include/mxatomidcounter.h b/LEGO1/omni/include/mxatomidcounter.h index f2c4fb3f..79a98f34 100644 --- a/LEGO1/omni/include/mxatomidcounter.h +++ b/LEGO1/omni/include/mxatomidcounter.h @@ -43,4 +43,50 @@ struct MxAtomIdCounterCompare { class MxAtomIdCounterSet : public set {}; +// SYNTHETIC: LEGO1 0x100ad170 +// MxAtomIdCounter::~MxAtomIdCounter + +// clang-format off +// TEMPLATE: LEGO1 0x100ad480 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::iterator::_Dec +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100ad780 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::_Lbound +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100ad4d0 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::_Insert +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100af6d0 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::~_Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::iterator::_Inc +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100af7e0 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::erase +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100afc40 +// _Tree >::_Kfn,MxAtomIdCounterCompare,allocator >::_Erase +// clang-format on + +// clang-format off +// TEMPLATE: LEGO1 0x100afc80 +// set >::~set > +// clang-format on + +// TEMPLATE: LEGO1 0x100afe40 +// Set::~Set + #endif // MXATOMIDCOUNTER_H diff --git a/LEGO1/omni/include/mxaudiomanager.h b/LEGO1/omni/include/mxaudiomanager.h index c910a493..94b5c4c9 100644 --- a/LEGO1/omni/include/mxaudiomanager.h +++ b/LEGO1/omni/include/mxaudiomanager.h @@ -5,6 +5,7 @@ #include "mxmediamanager.h" // VTABLE: LEGO1 0x100dc6e0 +// SIZE 0x30 class MxAudioManager : public MxMediaManager { public: MxAudioManager(); @@ -12,8 +13,14 @@ class MxAudioManager : public MxMediaManager { virtual MxResult InitPresenters() override; // vtable+14 virtual void Destroy() override; // vtable+18 - virtual MxS32 GetVolume(); // vtable+28 - virtual void SetVolume(MxS32 p_volume); // vtable+2c + + // FUNCTION: LEGO1 0x10029910 + virtual MxS32 GetVolume() { return this->m_volume; }; // vtable+28 + + virtual void SetVolume(MxS32 p_volume); // vtable+2c + + // SYNTHETIC: LEGO1 0x100b8d70 + // MxAudioManager::`scalar deleting destructor' private: void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxaudiopresenter.h b/LEGO1/omni/include/mxaudiopresenter.h index 73024aac..82e4b48a 100644 --- a/LEGO1/omni/include/mxaudiopresenter.h +++ b/LEGO1/omni/include/mxaudiopresenter.h @@ -23,11 +23,20 @@ class MxAudioPresenter : public MxMediaPresenter { return !strcmp(p_name, MxAudioPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual MxS32 GetVolume(); // vtable+0x5c - virtual void SetVolume(MxS32 p_volume); // vtable+0x60 + // FUNCTION: LEGO1 0x1000d260 + virtual MxS32 GetVolume() { return m_volume; }; // vtable+0x5c + + // FUNCTION: LEGO1 0x1000d270 + virtual void SetVolume(MxS32 p_volume) { m_volume = p_volume; }; // vtable+0x60 protected: MxS32 m_volume; }; +// SYNTHETIC: LEGO1 0x1000d370 +// MxAudioPresenter::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1000d3e0 +// MxAudioPresenter::~MxAudioPresenter + #endif // MXAUDIOPRESENTER_H diff --git a/LEGO1/omni/include/mxbitmap.h b/LEGO1/omni/include/mxbitmap.h index d9fda78d..f17ddb4b 100644 --- a/LEGO1/omni/include/mxbitmap.h +++ b/LEGO1/omni/include/mxbitmap.h @@ -42,9 +42,28 @@ class MxBitmap : public MxCore { virtual MxResult SetSize(MxS32 p_width, MxS32 p_height, MxPalette* p_palette, MxBool); // vtable+1c virtual MxResult LoadFile(HANDLE p_handle); // vtable+20 __declspec(dllexport) virtual MxLong Read(const char* p_filename); // vtable+24 - virtual int VTable0x28(int); - virtual void VTable0x2c(int, int, int, int, int, int, int); - virtual void VTable0x30(int, int, int, int, int, int, int); + + // 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 __declspec(dllexport) virtual MxPalette* CreatePalette(); // vtable+34 virtual void ImportPalette(MxPalette* p_palette); // vtable+38 virtual MxResult SetBitDepth(MxBool); // vtable+3c @@ -89,6 +108,29 @@ class MxBitmap : public MxCore { 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*); diff --git a/LEGO1/omni/include/mxcompositepresenter.h b/LEGO1/omni/include/mxcompositepresenter.h index 6f14e615..33d00dc8 100644 --- a/LEGO1/omni/include/mxcompositepresenter.h +++ b/LEGO1/omni/include/mxcompositepresenter.h @@ -37,7 +37,14 @@ class MxCompositePresenter : public MxPresenter { virtual void VTable0x58(MxEndActionNotificationParam& p_param); // vtable+0x58 virtual void VTable0x5c(MxNotificationParam& p_param); // vtable+0x5c virtual void VTable0x60(MxPresenter* p_presenter); // vtable+0x60 - virtual MxBool VTable0x64(undefined4 p_undefined); // vtable+0x64 + + // FUNCTION: LEGO1 0x1000caf0 + virtual MxBool VTable0x64(undefined4 p_undefined) + { + if (m_compositePresenter) + return m_compositePresenter->VTable0x64(p_undefined); + return TRUE; + }; // vtable+0x64 protected: MxCompositePresenterList m_list; // 0x40 diff --git a/LEGO1/omni/include/mxcore.h b/LEGO1/omni/include/mxcore.h index db812bba..cae7020e 100644 --- a/LEGO1/omni/include/mxcore.h +++ b/LEGO1/omni/include/mxcore.h @@ -15,7 +15,9 @@ class MxCore { __declspec(dllexport) MxCore(); __declspec(dllexport) virtual ~MxCore(); // vtable+00 __declspec(dllexport) virtual MxLong Notify(MxParam& p_param); // vtable+04 - virtual MxResult Tickle(); // vtable+08 + + // FUNCTION: LEGO1 0x10001f70 + virtual MxResult Tickle() { return SUCCESS; }; // vtable+08 // FUNCTION: LEGO1 0x100144c0 inline virtual const char* ClassName() const // vtable+0c @@ -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/omni/include/mxcorelist.h b/LEGO1/omni/include/mxcorelist.h new file mode 100644 index 00000000..15ae7c9b --- /dev/null +++ b/LEGO1/omni/include/mxcorelist.h @@ -0,0 +1,95 @@ +#ifndef MXCORELIST_H +#define MXCORELIST_H + +#include "mxlist.h" +#include "mxtypes.h" + +class MxCore; + +// VTABLE: LEGO1 0x100d63b0 +// class MxCollection + +// VTABLE: LEGO1 0x100d63c8 +// class MxList + +// VTABLE: LEGO1 0x100d63e0 +// class MxPtrList + +// VTABLE: LEGO1 0x100d63f8 +// SIZE 0x18 +class MxCoreList : public MxPtrList { +public: + MxCoreList(MxBool p_ownership = FALSE) : MxPtrList(p_ownership) {} + + // FUNCTION: LEGO1 0x1001e650 + virtual MxS8 Compare(MxCore* p_a, MxCore* p_b) override + { + return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; + }; // vtable+0x14 +}; + +// VTABLE: LEGO1 0x100d64a0 +// class MxListCursor + +// VTABLE: LEGO1 0x100d6500 +// class MxPtrListCursor + +// VTABLE: LEGO1 0x100d6518 +// SIZE 0x10 +class MxCoreListCursor : public MxPtrListCursor { +public: + MxCoreListCursor(MxCoreList* p_list) : MxPtrListCursor(p_list){}; +}; + +// TEMPLATE: LEGO1 0x1001e670 +// MxCollection::Compare + +// TEMPLATE: LEGO1 0x1001e680 +// MxCollection::~MxCollection + +// TEMPLATE: LEGO1 0x1001e6d0 +// MxCollection::Destroy + +// TEMPLATE: LEGO1 0x1001e6e0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x1001e770 +// MxPtrList::Destroy + +// SYNTHETIC: LEGO1 0x1001e780 +// MxCoreList::`scalar deleting destructor' + +// TEMPLATE: LEGO1 0x1001e7f0 +// MxPtrList::~MxPtrList + +// SYNTHETIC: LEGO1 0x1001e840 +// MxCollection::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e8b0 +// MxList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001e960 +// MxPtrList::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f350 +// MxCoreListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1001f3c0 +// MxPtrListCursor::~MxPtrListCursor + +// SYNTHETIC: LEGO1 0x1001f410 +// MxListCursor::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x1001f480 +// MxPtrListCursor::`scalar deleting destructor' + +// FUNCTION: LEGO1 0x1001f4f0 +// MxListCursor::~MxListCursor + +// FUNCTION: LEGO1 0x1001f540 +// MxCoreListCursor::~MxCoreListCursor + +// TEMPLATE: LEGO1 0x10020840 +// MxListCursor::MxListCursor + +#endif // MXCORELIST_H diff --git a/LEGO1/omni/include/mxdiskstreamcontroller.h b/LEGO1/omni/include/mxdiskstreamcontroller.h index 01ddc78a..52c0d8b4 100644 --- a/LEGO1/omni/include/mxdiskstreamcontroller.h +++ b/LEGO1/omni/include/mxdiskstreamcontroller.h @@ -42,10 +42,12 @@ class MxDiskStreamController : public MxStreamController { inline MxBool GetUnk0xc4() const { return m_unk0xc4; } - void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); - void FUN_100c8670(MxDSStreamingAction* p_streamingAction); - void InsertToList74(MxDSBuffer* p_buffer); + MxResult FUN_100c7890(MxDSStreamingAction* p_action); void FUN_100c7cb0(MxDSStreamingAction* p_action); + void FUN_100c7f40(MxDSStreamingAction* p_streamingaction); + void FUN_100c8120(MxDSAction* p_action); + void InsertToList74(MxDSBuffer* p_buffer); + void FUN_100c8670(MxDSStreamingAction* p_streamingAction); private: MxStreamListMxDSAction m_list0x64; // 0x64 @@ -58,7 +60,6 @@ class MxDiskStreamController : public MxStreamController { MxStreamListMxDSAction m_list0xb8; // 0xb8 MxBool m_unk0xc4; // 0xc4 - MxResult FUN_100c7890(MxDSStreamingAction* p_action); void FUN_100c7970(); void FUN_100c7ce0(MxDSBuffer* p_buffer); MxResult FUN_100c7d10(); @@ -69,6 +70,9 @@ class MxDiskStreamController : public MxStreamController { void FUN_100c8720(); }; +// TEMPLATE: LEGO1 0x100c14d0 +// list >::erase + // TEMPLATE: LEGO1 0x100c7330 // list >::_Buynode @@ -84,4 +88,7 @@ class MxDiskStreamController : public MxStreamController { // TEMPLATE: LEGO1 0x100c74e0 // List::~List +// TEMPLATE: LEGO1 0x100c7ef0 +// list::insert + #endif // MXDISKSTREAMCONTROLLER_H diff --git a/LEGO1/omni/include/mxdiskstreamprovider.h b/LEGO1/omni/include/mxdiskstreamprovider.h index 6df049da..517fa463 100644 --- a/LEGO1/omni/include/mxdiskstreamprovider.h +++ b/LEGO1/omni/include/mxdiskstreamprovider.h @@ -20,9 +20,6 @@ class MxDiskStreamProviderThread : public MxThread { MxResult Run() override; MxResult StartWithTarget(MxDiskStreamProvider* p_target); - - // SYNTHETIC: LEGO1 0x100d10a0 - // MxDiskStreamProviderThread::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dd138 @@ -58,9 +55,6 @@ class MxDiskStreamProvider : public MxStreamProvider { virtual MxU32 GetLengthInDWords() override; // vtable+0x24 virtual MxU32* GetBufferForDWords() override; // vtable+0x28 - // SYNTHETIC: LEGO1 0x100d1220 - // MxDiskStreamProvider::`scalar deleting destructor' - private: MxDiskStreamProviderThread m_thread; // 0x10 MxSemaphore m_busySemaphore; // 0x2c @@ -70,4 +64,13 @@ class MxDiskStreamProvider : public MxStreamProvider { MxStreamListMxDSAction m_list; // 0x54 }; +// SYNTHETIC: LEGO1 0x100d10a0 +// MxDiskStreamProviderThread::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100d1110 +// MxDiskStreamProviderThread::~MxDiskStreamProviderThread + +// SYNTHETIC: LEGO1 0x100d1220 +// MxDiskStreamProvider::`scalar deleting destructor' + #endif // MXDISKSTREAMPROVIDER_H diff --git a/LEGO1/omni/include/mxdisplaysurface.h b/LEGO1/omni/include/mxdisplaysurface.h index 25fe95aa..dde3d086 100644 --- a/LEGO1/omni/include/mxdisplaysurface.h +++ b/LEGO1/omni/include/mxdisplaysurface.h @@ -80,12 +80,17 @@ class MxDisplaySurface : public MxCore { 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*, undefined4*, undefined4, undefined4); // vtable+0x44 + ); // 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 FUN_100ba640(); + void ClearScreen(); static LPDIRECTDRAWSURFACE FUN_100bc070(); inline LPDIRECTDRAWSURFACE GetDirectDrawSurface1() { return this->m_ddSurface1; } diff --git a/LEGO1/omni/include/mxdsaction.h b/LEGO1/omni/include/mxdsaction.h index c32dd4aa..67449868 100644 --- a/LEGO1/omni/include/mxdsaction.h +++ b/LEGO1/omni/include/mxdsaction.h @@ -2,8 +2,8 @@ #define MXDSACTION_H #include "mxdsobject.h" +#include "mxgeometry/mxgeometry3d.h" #include "mxtypes.h" -#include "realtime/vector.h" class MxOmni; @@ -12,16 +12,16 @@ class MxOmni; class MxDSAction : public MxDSObject { public: enum { - Flag_Looping = 0x01, - Flag_Bit3 = 0x04, - Flag_Bit4 = 0x08, - Flag_Bit5 = 0x10, - Flag_Enabled = 0x20, - Flag_Bit7 = 0x40, - Flag_World = 0x80, - Flag_Bit9 = 0x100, - Flag_Bit10 = 0x200, - Flag_Bit11 = 0x400, + c_looping = 0x01, + c_bit3 = 0x04, + c_bit4 = 0x08, + c_bit5 = 0x10, + c_enabled = 0x20, + c_bit7 = 0x40, + c_world = 0x80, + c_bit9 = 0x100, + c_bit10 = 0x200, + c_bit11 = 0x400, }; __declspec(dllexport) MxDSAction(); @@ -43,6 +43,7 @@ class MxDSAction : public MxDSObject { return !strcmp(p_name, MxDSAction::ClassName()) || MxDSObject::IsA(p_name); } + virtual undefined4 VTable0x14() override; // vtable+14; virtual MxU32 GetSizeOnDisk() override; // vtable+18; virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; virtual MxLong GetDuration(); // vtable+24; @@ -63,40 +64,43 @@ class MxDSAction : public MxDSObject { inline MxLong GetStartTime() const { return m_startTime; } inline MxS32 GetLoopCount() { return m_loopCount; } inline void SetLoopCount(MxS32 p_loopCount) { m_loopCount = p_loopCount; } - inline Vector3Data& GetLocation() { return m_location; } - inline Vector3Data& GetDirection() { return m_direction; } - inline Vector3Data& GetUp() { return m_up; } + inline Mx3DPointFloat& GetLocation() { return m_location; } + inline Mx3DPointFloat& GetDirection() { return m_direction; } + inline Mx3DPointFloat& GetUp() { return m_up; } inline MxCore* GetUnknown84() { return m_unk0x84; } inline void SetUnknown84(MxCore* p_unk0x84) { m_unk0x84 = p_unk0x84; } inline MxCore* GetOrigin() { return m_origin; } inline void SetOrigin(MxCore* p_origin) { m_origin = p_origin; } - inline MxBool IsLooping() const { return m_flags & Flag_Looping; } - inline MxBool IsBit3() const { return m_flags & Flag_Bit3; } + inline MxBool IsLooping() const { return m_flags & c_looping; } + inline MxBool IsBit3() const { return m_flags & c_bit3; } inline void CopyFlags(MxU32 p_flags) { - if (p_flags & MxDSAction::Flag_Looping) - SetFlags(GetFlags() | MxDSAction::Flag_Looping); - else if (p_flags & MxDSAction::Flag_Bit3) - SetFlags(GetFlags() | MxDSAction::Flag_Bit3); + if (p_flags & MxDSAction::c_looping) + SetFlags(GetFlags() | MxDSAction::c_looping); + else if (p_flags & MxDSAction::c_bit3) + SetFlags(GetFlags() | MxDSAction::c_bit3); } + // 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 - Vector3Data m_location; // 0x40 - Vector3Data m_direction; // 0x54 - Vector3Data m_up; // 0x68 - char* m_extraData; // 0x7c - MxU16 m_extraLength; // 0x80 - MxCore* m_unk0x84; // 0x84 - undefined4 m_unk0x88; // 0x88 - MxCore* m_origin; // 0x8c - MxLong m_unk0x90; // 0x90 + MxU32 m_sizeOnDisk; // 0x2c + MxU32 m_flags; // 0x30 + MxLong m_startTime; // 0x34 + MxLong m_duration; // 0x38 + MxS32 m_loopCount; // 0x3c + Mx3DPointFloat m_location; // 0x40 + Mx3DPointFloat m_direction; // 0x54 + Mx3DPointFloat m_up; // 0x68 + char* m_extraData; // 0x7c + MxU16 m_extraLength; // 0x80 + MxCore* m_unk0x84; // 0x84 + undefined4 m_unk0x88; // 0x88 + MxCore* m_origin; // 0x8c + MxLong m_unk0x90; // 0x90 }; #endif // MXDSACTION_H diff --git a/LEGO1/omni/include/mxdsactionlist.h b/LEGO1/omni/include/mxdsactionlist.h index fbccd5cf..75d96842 100644 --- a/LEGO1/omni/include/mxdsactionlist.h +++ b/LEGO1/omni/include/mxdsactionlist.h @@ -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/omni/include/mxdsanim.h b/LEGO1/omni/include/mxdsanim.h index 213fcf87..0e5b9a0c 100644 --- a/LEGO1/omni/include/mxdsanim.h +++ b/LEGO1/omni/include/mxdsanim.h @@ -27,6 +27,9 @@ class MxDSAnim : public MxDSMediaAction { } virtual MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100c9180 + // MxDSAnim::`scalar deleting destructor' }; #endif // MXDSANIM_H diff --git a/LEGO1/omni/include/mxdsbuffer.h b/LEGO1/omni/include/mxdsbuffer.h index 3a336af7..01696471 100644 --- a/LEGO1/omni/include/mxdsbuffer.h +++ b/LEGO1/omni/include/mxdsbuffer.h @@ -10,17 +10,17 @@ class MxDSStreamingAction; class MxStreamChunk; class MxDSChunk; -enum MxDSBufferType { - MxDSBufferType_Chunk = 0, - MxDSBufferType_Allocate = 1, - MxDSBufferType_Preallocated = 2, - MxDSBufferType_Unknown = 3, -}; - // VTABLE: LEGO1 0x100dcca0 // SIZE 0x34 class MxDSBuffer : public MxCore { public: + enum Type { + e_chunk = 0, + e_allocate = 1, + e_preallocated = 2, + e_unknown = 3, + }; + MxDSBuffer(); virtual ~MxDSBuffer() override; @@ -31,7 +31,7 @@ class MxDSBuffer : public MxCore { return "MxDSBuffer"; } - MxResult AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode); + MxResult AllocateBuffer(MxU32 p_bufferSize, Type p_mode); MxResult SetBufferPointer(MxU8* p_buffer, MxU32 p_size); MxResult FUN_100c67b0( MxStreamController* p_controller, @@ -67,14 +67,17 @@ class MxDSBuffer : public MxCore { 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(MxDSBufferType p_mode) { m_mode = p_mode; } + 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 MxU8* m_pIntoBuffer; // 0x0c @@ -83,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/omni/include/mxdschunk.h b/LEGO1/omni/include/mxdschunk.h index 3cd60b27..52806580 100644 --- a/LEGO1/omni/include/mxdschunk.h +++ b/LEGO1/omni/include/mxdschunk.h @@ -10,11 +10,11 @@ class MxDSChunk : public MxCore { public: enum { - Flag_Bit1 = 0x01, - Flag_End = 0x02, - Flag_Bit3 = 0x04, - Flag_Split = 0x10, - Flag_Bit16 = 0x8000 + c_bit1 = 0x01, + c_end = 0x02, + c_bit3 = 0x04, + c_split = 0x10, + c_bit16 = 0x8000 }; MxDSChunk(); @@ -57,6 +57,9 @@ class MxDSChunk : public MxCore { delete[] m_data; } + // SYNTHETIC: LEGO1 0x100be150 + // MxDSChunk::`scalar deleting destructor' + protected: MxU16 m_flags; // 0x8 MxU32 m_objectId; // 0xc diff --git a/LEGO1/omni/include/mxdsevent.h b/LEGO1/omni/include/mxdsevent.h index 01cf1fa4..1a197496 100644 --- a/LEGO1/omni/include/mxdsevent.h +++ b/LEGO1/omni/include/mxdsevent.h @@ -3,6 +3,7 @@ #include "mxdsmediaaction.h" +// VTABLE: LEGO1 0x100dce18 class MxDSEvent : public MxDSMediaAction { public: MxDSEvent(); @@ -25,6 +26,9 @@ class MxDSEvent : public MxDSMediaAction { } virtual MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100c9780 + // MxDSEvent::`scalar deleting destructor' }; #endif // MXDSEVENT_H diff --git a/LEGO1/omni/include/mxdsfile.h b/LEGO1/omni/include/mxdsfile.h index 34afeccb..473b9741 100644 --- a/LEGO1/omni/include/mxdsfile.h +++ b/LEGO1/omni/include/mxdsfile.h @@ -38,6 +38,9 @@ class MxDSFile : public MxDSSource { 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/omni/include/mxdsmediaaction.h b/LEGO1/omni/include/mxdsmediaaction.h index 1f1b97d5..7422ec2d 100644 --- a/LEGO1/omni/include/mxdsmediaaction.h +++ b/LEGO1/omni/include/mxdsmediaaction.h @@ -28,8 +28,13 @@ class MxDSMediaAction : public MxDSAction { return !strcmp(p_name, MxDSMediaAction::ClassName()) || MxDSAction::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100c8cd0 + // MxDSMediaAction::`scalar deleting destructor' + + virtual undefined4 VTable0x14(); // vtable+14; virtual MxU32 GetSizeOnDisk() override; // vtable+18; virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; + virtual MxDSAction* Clone() override; // vtable+2c; void CopyMediaSrcPath(const char* p_mediaSrcPath); diff --git a/LEGO1/omni/include/mxdsmultiaction.h b/LEGO1/omni/include/mxdsmultiaction.h index a600b787..efc1a11d 100644 --- a/LEGO1/omni/include/mxdsmultiaction.h +++ b/LEGO1/omni/include/mxdsmultiaction.h @@ -38,6 +38,9 @@ class MxDSMultiAction : public MxDSAction { inline MxDSActionList* GetActionList() const { return m_actions; }; + // SYNTHETIC: LEGO1 0x100ca040 + // MxDSMultiAction::`scalar deleting destructor' + protected: MxU32 m_sizeOnDisk; // 0x94 MxDSActionList* m_actions; // 0x98 diff --git a/LEGO1/omni/include/mxdsobject.h b/LEGO1/omni/include/mxdsobject.h index a05d319b..ad1cae40 100644 --- a/LEGO1/omni/include/mxdsobject.h +++ b/LEGO1/omni/include/mxdsobject.h @@ -4,7 +4,6 @@ #include "decomp.h" #include "mxatomid.h" #include "mxcore.h" -#include "mxdstypes.h" class MxPresenter; @@ -12,6 +11,21 @@ class MxPresenter; // SIZE 0x2c class MxDSObject : public MxCore { public: + enum Type { + e_object = 0, + e_action, + e_mediaAction, + e_anim, + e_sound, + e_multiAction, + e_serialAction, + e_parallelAction, + e_event, + e_selectAction, + e_still, + e_objectAction, + }; + MxDSObject(); virtual ~MxDSObject() override; @@ -35,20 +49,23 @@ class MxDSObject : public MxCore { virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24); // vtable+1c; inline virtual void SetAtomId(MxAtomId p_atomId) { this->m_atomId = p_atomId; } // vtable+20; - inline MxDSType GetType() const { return (MxDSType) this->m_type; } + inline Type GetType() const { return (Type) this->m_type; } inline const char* GetSourceName() const { return this->m_sourceName; } inline MxU32 GetObjectId() { return this->m_objectId; } inline const MxAtomId& GetAtomId() { return this->m_atomId; } inline MxS16 GetUnknown24() { return this->m_unk0x24; } inline MxPresenter* GetUnknown28() { return this->m_unk0x28; } - inline void SetType(MxDSType p_type) { this->m_type = p_type; } + inline void SetType(Type p_type) { this->m_type = p_type; } inline void SetObjectId(MxU32 p_objectId) { this->m_objectId = p_objectId; } inline void SetUnknown24(MxS16 p_unk0x24) { this->m_unk0x24 = p_unk0x24; } inline void SetUnknown28(MxPresenter* p_unk0x28) { this->m_unk0x28 = p_unk0x28; } inline void ClearAtom() { m_atomId.Clear(); } + // SYNTHETIC: LEGO1 0x100bf7c0 + // MxDSObject::`scalar deleting destructor' + private: MxU32 m_sizeOnDisk; // 0x8 MxU16 m_type; // 0xc diff --git a/LEGO1/omni/include/mxdsobjectaction.h b/LEGO1/omni/include/mxdsobjectaction.h index a31f6d6b..77480452 100644 --- a/LEGO1/omni/include/mxdsobjectaction.h +++ b/LEGO1/omni/include/mxdsobjectaction.h @@ -27,6 +27,9 @@ class MxDSObjectAction : public MxDSMediaAction { virtual 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/omni/include/mxdsparallelaction.h b/LEGO1/omni/include/mxdsparallelaction.h index 89fc1df0..0386de7f 100644 --- a/LEGO1/omni/include/mxdsparallelaction.h +++ b/LEGO1/omni/include/mxdsparallelaction.h @@ -26,8 +26,15 @@ class MxDSParallelAction : public MxDSMultiAction { return !strcmp(p_name, MxDSParallelAction::ClassName()) || MxDSMultiAction::IsA(p_name); } + // SYNTHETIC: LEGO1 0x100cb020 + // MxDSParallelAction::`scalar deleting destructor' + virtual MxLong GetDuration() override; // vtable+24; - virtual MxDSAction* Clone() override; // vtable+2c; + + // FUNCTION: LEGO1 0x100caef0 + virtual void SetDuration(MxLong p_duration) override { m_duration = p_duration; } // vtable+0x28 + + virtual MxDSAction* Clone() override; // vtable+2c; }; #endif // MXDSPARALLELACTION_H diff --git a/LEGO1/omni/include/mxdsselectaction.h b/LEGO1/omni/include/mxdsselectaction.h index 6b68bfc9..f7c6a148 100644 --- a/LEGO1/omni/include/mxdsselectaction.h +++ b/LEGO1/omni/include/mxdsselectaction.h @@ -32,6 +32,9 @@ class MxDSSelectAction : public MxDSParallelAction { virtual void Deserialize(MxU8** p_source, MxS16 p_unk0x24) override; // vtable+1c; virtual MxDSAction* Clone() override; // vtable+2c; + // SYNTHETIC: LEGO1 0x100cb840 + // MxDSSelectAction::`scalar deleting destructor' + private: MxString m_unk0x9c; MxStringList* m_unk0xac; diff --git a/LEGO1/omni/include/mxdsserialaction.h b/LEGO1/omni/include/mxdsserialaction.h index c4fa18b3..694c9afa 100644 --- a/LEGO1/omni/include/mxdsserialaction.h +++ b/LEGO1/omni/include/mxdsserialaction.h @@ -31,6 +31,9 @@ class MxDSSerialAction : public MxDSMultiAction { virtual void SetDuration(MxLong p_duration) override; // vtable+28; virtual MxDSAction* Clone() override; // vtable+2c; + // SYNTHETIC: LEGO1 0x100cabf0 + // MxDSSerialAction::`scalar deleting destructor' + private: MxDSActionListCursor* m_cursor; undefined4 m_unk0xa0; diff --git a/LEGO1/omni/include/mxdssound.h b/LEGO1/omni/include/mxdssound.h index 5dc6bbd7..3d1fa31d 100644 --- a/LEGO1/omni/include/mxdssound.h +++ b/LEGO1/omni/include/mxdssound.h @@ -32,6 +32,9 @@ class MxDSSound : public MxDSMediaAction { 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 index db009fb4..143b9c78 100644 --- a/LEGO1/omni/include/mxdssource.h +++ b/LEGO1/omni/include/mxdssource.h @@ -11,6 +11,9 @@ class MxDSSource : public MxCore { public: MxDSSource() : m_lengthInDWords(0), m_pBuffer(NULL), m_position(-1) {} + // FUNCTION: LEGO1 0x100bff60 + virtual ~MxDSSource() override { delete[] m_pBuffer; } + // FUNCTION: LEGO1 0x100c0010 inline virtual const char* ClassName() const override // vtable+0x0c { @@ -41,4 +44,7 @@ class MxDSSource : public MxCore { MxLong m_position; // 0x10 }; +// SYNTHETIC: LEGO1 0x100c00a0 +// MxDSSource::`scalar deleting destructor' + #endif // MXDSSOURCE_H diff --git a/LEGO1/omni/include/mxdsstill.h b/LEGO1/omni/include/mxdsstill.h index 268fe79f..4de69475 100644 --- a/LEGO1/omni/include/mxdsstill.h +++ b/LEGO1/omni/include/mxdsstill.h @@ -27,6 +27,9 @@ class MxDSStill : public MxDSMediaAction { } virtual MxDSAction* Clone() override; // vtable+2c; + + // SYNTHETIC: LEGO1 0x100c9a50 + // MxDSStill::`scalar deleting destructor' }; #endif // MXDSSTILL_H diff --git a/LEGO1/omni/include/mxdsstreamingaction.h b/LEGO1/omni/include/mxdsstreamingaction.h index ab21bac2..074bd5ed 100644 --- a/LEGO1/omni/include/mxdsstreamingaction.h +++ b/LEGO1/omni/include/mxdsstreamingaction.h @@ -44,6 +44,9 @@ class MxDSStreamingAction : public MxDSAction { 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/omni/include/mxdstypes.h b/LEGO1/omni/include/mxdstypes.h deleted file mode 100644 index f43742b9..00000000 --- a/LEGO1/omni/include/mxdstypes.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MXDSTYPES_H -#define MXDSTYPES_H - -enum MxDSType { - MxDSType_Object = 0, - MxDSType_Action = 1, - MxDSType_MediaAction = 2, - MxDSType_Anim = 3, - MxDSType_Sound = 4, - MxDSType_MultiAction = 5, - MxDSType_SerialAction = 6, - MxDSType_ParallelAction = 7, - MxDSType_Event = 8, - MxDSType_SelectAction = 9, - MxDSType_Still = 10, - MxDSType_ObjectAction = 11, -}; - -#endif // MXDSTYPES_H diff --git a/LEGO1/omni/include/mxentity.h b/LEGO1/omni/include/mxentity.h index 64a003ee..e78d3b2b 100644 --- a/LEGO1/omni/include/mxentity.h +++ b/LEGO1/omni/include/mxentity.h @@ -4,15 +4,18 @@ #include "decomp.h" #include "mxatomid.h" #include "mxcore.h" -#include "mxdsobject.h" +#include "mxdsaction.h" #include "mxtypes.h" // VTABLE: LEGO1 0x100d5390 // SIZE 0x10 class MxEntity : public MxCore { public: - MxEntity(); - virtual ~MxEntity() override; + // FUNCTION: LEGO1 0x1001d190 + MxEntity() { this->m_mxEntityId = -1; } + + // FUNCTION: LEGO1 0x1000c110 + virtual ~MxEntity() override{}; // FUNCTION: LEGO1 0x1000c180 inline virtual const char* ClassName() const override // vtable+0xc @@ -27,14 +30,27 @@ class MxEntity : public MxCore { return !strcmp(p_name, MxEntity::ClassName()) || MxCore::IsA(p_name); } - virtual MxResult Create(MxS32 p_id, const MxAtomId& p_atom); // vtable+0x14 - inline MxResult Create(MxDSObject& p_dsObject) + // FUNCTION: LEGO1 0x10001070 + virtual MxResult Create(MxS32 p_id, const MxAtomId& p_atom) { - m_mxEntityId = p_dsObject.GetObjectId(); - m_atom = p_dsObject.GetAtomId(); + this->m_mxEntityId = p_id; + this->m_atom = p_atom; + return SUCCESS; + }; // vtable+0x14 + + inline MxResult Create(MxDSAction& p_dsAction) + { + m_mxEntityId = p_dsAction.GetObjectId(); + m_atom = p_dsAction.GetAtomId(); return SUCCESS; } + inline MxS32 GetEntityId() { return m_mxEntityId; } + inline MxAtomId& GetAtom() { return m_atom; } + + // SYNTHETIC: LEGO1 0x1000c210 + // MxEntity::`scalar deleting destructor' + protected: MxS32 m_mxEntityId; // 0x8 MxAtomId m_atom; // 0xc diff --git a/LEGO1/omni/include/mxeventmanager.h b/LEGO1/omni/include/mxeventmanager.h index e7f41a6d..c21e92bc 100644 --- a/LEGO1/omni/include/mxeventmanager.h +++ b/LEGO1/omni/include/mxeventmanager.h @@ -14,6 +14,9 @@ class MxEventManager : public MxMediaManager { virtual 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 index 201b15e5..52d503df 100644 --- a/LEGO1/omni/include/mxeventpresenter.h +++ b/LEGO1/omni/include/mxeventpresenter.h @@ -31,6 +31,9 @@ class MxEventPresenter : public MxMediaPresenter { virtual MxResult PutData() override; // vtable+0x4c virtual void CopyData(MxStreamChunk* p_chunk); // vtable+0x5c + // SYNTHETIC: LEGO1 0x100c2d20 + // MxEventPresenter::`scalar deleting destructor' + private: void Init(); diff --git a/LEGO1/omni/include/mxflcpresenter.h b/LEGO1/omni/include/mxflcpresenter.h index 0ad44de3..c8f9854d 100644 --- a/LEGO1/omni/include/mxflcpresenter.h +++ b/LEGO1/omni/include/mxflcpresenter.h @@ -28,10 +28,14 @@ class MxFlcPresenter : public MxVideoPresenter { 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 + // SYNTHETIC: LEGO1 0x100b3400 + // MxFlcPresenter::`scalar deleting destructor' + protected: - FLIC_HEADER* m_flicHeader; + FLIC_HEADER* m_flcHeader; // 0x64 }; #endif // MXFLCPRESENTER_H diff --git a/LEGO1/omni/include/mxhashtable.h b/LEGO1/omni/include/mxhashtable.h index 8d6be0cf..056ff402 100644 --- a/LEGO1/omni/include/mxhashtable.h +++ b/LEGO1/omni/include/mxhashtable.h @@ -32,10 +32,10 @@ class MxHashTableNode { template class MxHashTable : protected MxCollection { public: - enum HashTableOpt { - HashTableOpt_NoExpand = 0, - HashTableOpt_ExpandAdd = 1, - HashTableOpt_ExpandMultiply = 2, + enum Option { + e_noExpand = 0, + e_expandAll, + e_expandMultiply, }; MxHashTable() @@ -43,7 +43,7 @@ class MxHashTable : protected MxCollection { m_numSlots = HASH_TABLE_INIT_SIZE; m_slots = new MxHashTableNode*[HASH_TABLE_INIT_SIZE]; memset(m_slots, 0, sizeof(MxHashTableNode*) * m_numSlots); - m_resizeOption = HashTableOpt_NoExpand; + m_resizeOption = e_noExpand; } virtual ~MxHashTable() override; @@ -62,7 +62,7 @@ class MxHashTable : protected MxCollection { MxHashTableNode** m_slots; // 0x10 MxU32 m_numSlots; // 0x14 MxU32 m_autoResizeRatio; // 0x18 - HashTableOpt m_resizeOption; // 0x1c + Option m_resizeOption; // 0x1c // FIXME: or FIXME? This qword is used as an integer or double depending // on the value of m_resizeOption. Hard to say whether this is how the devs // did it, but a simple cast in either direction doesn't match. @@ -177,10 +177,10 @@ inline void MxHashTable::Resize() MxHashTableNode** oldTable = m_slots; switch (m_resizeOption) { - case HashTableOpt_ExpandAdd: + case e_expandAll: m_numSlots += m_increaseAmount; break; - case HashTableOpt_ExpandMultiply: + case e_expandMultiply: m_numSlots *= m_increaseFactor; break; } diff --git a/LEGO1/omni/include/mxlist.h b/LEGO1/omni/include/mxlist.h index 911d5a36..99330975 100644 --- a/LEGO1/omni/include/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -69,6 +69,7 @@ class MxList : protected MxCollection { MxListEntry* InsertEntry(T, MxListEntry*, MxListEntry*); }; +// SIZE 0x18 template class MxPtrList : public MxList { public: @@ -82,6 +83,7 @@ class MxPtrList : public MxList { } }; +// SIZE 0x10 template class MxListCursor : public MxCore { public: @@ -128,6 +130,7 @@ class MxListCursor : public MxCore { MxListEntry* m_match; // 0x0c }; +// SIZE 0x10 template class MxPtrListCursor : public MxListCursor { public: diff --git a/LEGO1/omni/include/mxloopingflcpresenter.h b/LEGO1/omni/include/mxloopingflcpresenter.h index c05c3657..7075332d 100644 --- a/LEGO1/omni/include/mxloopingflcpresenter.h +++ b/LEGO1/omni/include/mxloopingflcpresenter.h @@ -18,13 +18,20 @@ class MxLoopingFlcPresenter : public MxFlcPresenter { return "MxLoopingFlcPresenter"; } - virtual void NextFrame() override; // vtable+0x64 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual MxResult AddToManager() override; // vtable+0x34 + virtual void Destroy() override; // vtable+0x38 + virtual void NextFrame() override; // vtable+0x64 + virtual void VTable0x88(); // vtable+0x88 + + // SYNTHETIC: LEGO1 0x100b4390 + // MxLoopingFlcPresenter::`scalar deleting destructor' private: void Init(); void Destroy(MxBool p_fromDestructor); - undefined4 m_unk0x68; + MxLong m_elapsedDuration; // 0x68 }; #endif // MXLOOPINGFLCPRESENTER_H diff --git a/LEGO1/omni/include/mxmediamanager.h b/LEGO1/omni/include/mxmediamanager.h index 47f7f0d1..25853adf 100644 --- a/LEGO1/omni/include/mxmediamanager.h +++ b/LEGO1/omni/include/mxmediamanager.h @@ -14,17 +14,20 @@ class MxMediaManager : public MxCore { MxMediaManager(); virtual ~MxMediaManager() override; - virtual MxResult Tickle() override; // vtable+08 - virtual MxResult InitPresenters(); // vtable+14 - virtual void Destroy(); // vtable+18 - virtual void AddPresenter(MxPresenter& p_presenter); // vtable+1c - virtual void RemovePresenter(MxPresenter& p_presenter); // vtable+20 - virtual void StopPresenters(); // vtable+24 + virtual MxResult Tickle() override; // vtable+08 + virtual MxResult InitPresenters(); // vtable+14 + virtual void Destroy(); // vtable+18 + virtual void RegisterPresenter(MxPresenter& p_presenter); // vtable+1c + virtual void UnregisterPresenter(MxPresenter& p_presenter); // vtable+20 + virtual void StopPresenters(); // vtable+24 MxResult Init(); + // SYNTHETIC: LEGO1 0x100b8540 + // MxMediaManager::`scalar deleting destructor' + protected: - MxPresenterList* m_presenters; + MxPresenterList* m_presenters; // 0x8 MxThread* m_thread; // 0xc MxCriticalSection m_criticalSection; // 0x10 }; diff --git a/LEGO1/omni/include/mxmediapresenter.h b/LEGO1/omni/include/mxmediapresenter.h index 64baa409..954a2dcc 100644 --- a/LEGO1/omni/include/mxmediapresenter.h +++ b/LEGO1/omni/include/mxmediapresenter.h @@ -11,7 +11,9 @@ class MxMediaPresenter : public MxPresenter { public: inline MxMediaPresenter() { Init(); } - virtual ~MxMediaPresenter() override; + + // FUNCTION: LEGO1 0x1000c550 + virtual ~MxMediaPresenter() override { Destroy(TRUE); }; virtual MxResult Tickle() override; // vtable+0x8 @@ -28,15 +30,21 @@ class MxMediaPresenter : public MxPresenter { return !strcmp(p_name, MxMediaPresenter::ClassName()) || MxPresenter::IsA(p_name); } - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void DoneTickle() override; // vtable+0x2c - virtual void Destroy() override; // vtable+0x38 + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void DoneTickle() override; // vtable+0x2c + + // FUNCTION: LEGO1 0x1000c5b0 + virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + virtual MxResult StartAction(MxStreamController*, MxDSAction*) override; // vtable+0x3c virtual void EndAction() override; // vtable+0x40 virtual void Enable(MxBool p_enable) override; // vtable+0x54 virtual void LoopChunk(MxStreamChunk* p_chunk); // vtable+0x58 + // SYNTHETIC: LEGO1 0x1000c680 + // MxMediaPresenter::`scalar deleting destructor' + protected: MxDSSubscriber* m_subscriber; // 0x40 MxStreamChunkList* m_loopingChunks; // 0x44 diff --git a/LEGO1/omni/include/mxmidipresenter.h b/LEGO1/omni/include/mxmidipresenter.h index 2ec11b0b..0bde447c 100644 --- a/LEGO1/omni/include/mxmidipresenter.h +++ b/LEGO1/omni/include/mxmidipresenter.h @@ -33,6 +33,9 @@ class MxMIDIPresenter : public MxMusicPresenter { virtual MxResult PutData() override; // vtable+0x4c virtual void SetVolume(MxS32 p_volume) override; // vtable+0x60 + // SYNTHETIC: LEGO1 0x100c27a0 + // MxMIDIPresenter::`scalar deleting destructor' + private: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxmusicmanager.h b/LEGO1/omni/include/mxmusicmanager.h index d9f6d46d..2a8b30e5 100644 --- a/LEGO1/omni/include/mxmusicmanager.h +++ b/LEGO1/omni/include/mxmusicmanager.h @@ -4,6 +4,8 @@ #include "decomp.h" #include "mxaudiomanager.h" +#include + // VTABLE: LEGO1 0x100dc930 // SIZE 0x58 class MxMusicManager : public MxAudioManager { @@ -16,9 +18,17 @@ class MxMusicManager : public MxAudioManager { 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(); - undefined4 FUN_100c09c0(MxU8* p_data, MxS32 p_loopCount); void SetMultiplier(MxS32 p_multiplier); private: @@ -27,16 +37,21 @@ class MxMusicManager : public MxAudioManager { 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 + 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(); diff --git a/LEGO1/omni/include/mxmusicpresenter.h b/LEGO1/omni/include/mxmusicpresenter.h index bba2afb0..88be5c7f 100644 --- a/LEGO1/omni/include/mxmusicpresenter.h +++ b/LEGO1/omni/include/mxmusicpresenter.h @@ -26,6 +26,9 @@ class MxMusicPresenter : public MxAudioPresenter { virtual MxResult AddToManager() override; // vtable+0x34 virtual void Destroy() override; // vtable+0x38 + // SYNTHETIC: LEGO1 0x100c24c0 + // MxMusicPresenter::`scalar deleting destructor' + private: void Init(); void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/include/mxnextactiondatastart.h b/LEGO1/omni/include/mxnextactiondatastart.h index 15e35b00..3b58a338 100644 --- a/LEGO1/omni/include/mxnextactiondatastart.h +++ b/LEGO1/omni/include/mxnextactiondatastart.h @@ -33,6 +33,9 @@ class MxNextActionDataStart : public MxCore { 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; // 0x08 MxS16 m_unk0x24; // 0x0c diff --git a/LEGO1/omni/include/mxnotificationmanager.h b/LEGO1/omni/include/mxnotificationmanager.h index 4a3d8726..4ed58f62 100644 --- a/LEGO1/omni/include/mxnotificationmanager.h +++ b/LEGO1/omni/include/mxnotificationmanager.h @@ -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/omni/include/mxnotificationparam.h b/LEGO1/omni/include/mxnotificationparam.h index 66f9dd95..e990abe6 100644 --- a/LEGO1/omni/include/mxnotificationparam.h +++ b/LEGO1/omni/include/mxnotificationparam.h @@ -8,48 +8,55 @@ class MxCore; enum NotificationId { - PARAM_NONE = 0, + c_notificationType0 = 0, c_notificationStartAction = 1, // 100dc210:100d8350 c_notificationEndAction = 2, // 100d8358:100d8350 - TYPE4 = 4, // 100dc208:100d8350 - MXPRESENTER_NOTIFICATION = 5, - MXSTREAMER_DELETE_NOTIFY = 6, // 100dc760 + c_notificationType4 = 4, // 100dc208:100d8350 + c_notificationPresenter = 5, + c_notificationStreamer = 6, // 100dc760 c_notificationKeyPress = 7, // 100d6aa0 c_notificationButtonUp = 8, // 100d6aa0 c_notificationButtonDown = 9, // 100d6aa0 c_notificationMouseMove = 10, // 100d6aa0 - TYPE11 = 11, // 100d6aa0 + c_notificationType11 = 11, // 100d6aa0 c_notificationDragEnd = 12, c_notificationDragStart = 13, c_notificationDrag = 14, c_notificationTimer = 15, // 100d6aa0 - TYPE17 = 17, - TYPE18 = 18, // 100d7e80 - TYPE19 = 19, // 100d6230 - TYPE20 = 20, + c_notificationType17 = 17, + c_notificationType18 = 18, // 100d7e80 + c_notificationType19 = 19, // 100d6230 + c_notificationType20 = 20, c_notificationNewPresenter = 21, - TYPE22 = 22, - TYPE23 = 23, - MXTRANSITIONMANAGER_TRANSITIONENDED = 24 + c_notificationType22 = 22, + c_notificationType23 = 23, + c_notificationTransitioned = 24 }; // VTABLE: LEGO1 0x100d56e0 +// SIZE 0x0c class MxNotificationParam : public MxParam { public: inline MxNotificationParam(NotificationId p_type, MxCore* p_sender) : MxParam(), m_type(p_type), m_sender(p_sender) { } - virtual ~MxNotificationParam() override {} // vtable+0x0 (scalar deleting destructor) - virtual MxNotificationParam* Clone(); // vtable+0x4 + // FUNCTION: LEGO1 0x10010390 + virtual MxNotificationParam* Clone() { return new MxNotificationParam(m_type, m_sender); }; // vtable+0x4 inline NotificationId GetNotification() const { return m_type; } inline MxCore* GetSender() const { return m_sender; } inline NotificationId GetType() const { return m_type; } protected: - NotificationId m_type; // 0x4 - MxCore* m_sender; // 0x8 + NotificationId m_type; // 0x04 + MxCore* m_sender; // 0x08 }; +// SYNTHETIC: LEGO1 0x10010430 +// MxNotificationParam::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100104a0 +// MxNotificationParam::~MxNotificationParam + #endif // MXNOTIFICATIONPARAM_H diff --git a/LEGO1/omni/include/mxobjectfactory.h b/LEGO1/omni/include/mxobjectfactory.h index 3741bfa3..4ae3e348 100644 --- a/LEGO1/omni/include/mxobjectfactory.h +++ b/LEGO1/omni/include/mxobjectfactory.h @@ -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/omni/include/mxomni.h b/LEGO1/omni/include/mxomni.h index 7bac0723..9ade97b3 100644 --- a/LEGO1/omni/include/mxomni.h +++ b/LEGO1/omni/include/mxomni.h @@ -52,10 +52,12 @@ class MxOmni : public MxCore { virtual void NotifyCurrentEntity(MxNotificationParam* p_param); // vtable+34 virtual void StartTimer(); // vtable+38 virtual void StopTimer(); // vtable+3c - virtual MxBool IsTimerRunning(); // vtable+40 + + // FUNCTION: LEGO1 0x10058a90 + virtual MxBool IsTimerRunning() { return m_timerRunning; }; // vtable+40 static void SetInstance(MxOmni* p_instance); - static MxBool FUN_100b06b0(MxDSAction* p_action, const char* p_name); + 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,6 +73,9 @@ 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; @@ -98,12 +103,12 @@ __declspec(dllexport) MxSoundManager* MSoundManager(); __declspec(dllexport) MxVariableTable* VariableTable(); __declspec(dllexport) MxMusicManager* MusicManager(); __declspec(dllexport) MxEventManager* EventManager(); +__declspec(dllexport) MxResult Start(MxDSAction*); __declspec(dllexport) MxNotificationManager* NotificationManager(); MxVideoManager* MVideoManager(); MxAtomIdCounterSet* AtomIdCounterSet(); MxObjectFactory* ObjectFactory(); void DeleteObject(MxDSAction& p_dsAction); -void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last); #endif // MXOMNI_H diff --git a/LEGO1/omni/include/mxomnicreateflags.h b/LEGO1/omni/include/mxomnicreateflags.h index a94ed45a..24b1e942 100644 --- a/LEGO1/omni/include/mxomnicreateflags.h +++ b/LEGO1/omni/include/mxomnicreateflags.h @@ -6,84 +6,76 @@ class MxOmniCreateFlags { public: enum LowFlags { - Flag_CreateObjectFactory = 0x01, - Flag_CreateVariableTable = 0x02, - Flag_CreateTickleManager = 0x04, - Flag_CreateNotificationManager = 0x08, - Flag_CreateVideoManager = 0x10, - Flag_CreateSoundManager = 0x20, - Flag_CreateMusicManager = 0x40, - Flag_CreateEventManager = 0x80 + c_createObjectFactory = 0x01, + c_createVariableTable = 0x02, + c_createTickleManager = 0x04, + c_createNotificationManager = 0x08, + c_createVideoManager = 0x10, + c_createSoundManager = 0x20, + c_createMusicManager = 0x40, + c_createEventManager = 0x80 }; enum HighFlags { - Flag_CreateTimer = 0x02, - Flag_CreateStreamer = 0x04 + c_createTimer = 0x02, + c_createStreamer = 0x04 }; __declspec(dllexport) MxOmniCreateFlags(); - inline const MxBool CreateObjectFactory() const { return this->m_flags1 & Flag_CreateObjectFactory; } - inline const MxBool CreateVariableTable() const { return this->m_flags1 & Flag_CreateVariableTable; } - inline const MxBool CreateTickleManager() const { return this->m_flags1 & Flag_CreateTickleManager; } - inline const MxBool CreateNotificationManager() const { return this->m_flags1 & Flag_CreateNotificationManager; } - inline const MxBool CreateVideoManager() const { return this->m_flags1 & Flag_CreateVideoManager; } - inline const MxBool CreateSoundManager() const { return this->m_flags1 & Flag_CreateSoundManager; } - inline const MxBool CreateMusicManager() const { return this->m_flags1 & Flag_CreateMusicManager; } - inline const MxBool CreateEventManager() const { return this->m_flags1 & Flag_CreateEventManager; } + inline const MxBool CreateObjectFactory() const { return this->m_flags1 & c_createObjectFactory; } + inline const MxBool CreateVariableTable() const { return this->m_flags1 & c_createVariableTable; } + inline const MxBool CreateTickleManager() const { return this->m_flags1 & c_createTickleManager; } + inline const MxBool CreateNotificationManager() const { return this->m_flags1 & c_createNotificationManager; } + inline const MxBool CreateVideoManager() const { return this->m_flags1 & c_createVideoManager; } + inline const MxBool CreateSoundManager() const { return this->m_flags1 & c_createSoundManager; } + inline const MxBool CreateMusicManager() const { return this->m_flags1 & c_createMusicManager; } + inline const MxBool CreateEventManager() const { return this->m_flags1 & c_createEventManager; } - inline const MxBool CreateTimer() const { return this->m_flags2 & Flag_CreateTimer; } - inline const MxBool CreateStreamer() const { return this->m_flags2 & Flag_CreateStreamer; } + inline const MxBool CreateTimer() const { return this->m_flags2 & c_createTimer; } + inline const MxBool CreateStreamer() const { return this->m_flags2 & c_createStreamer; } inline void CreateObjectFactory(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateObjectFactory : this->m_flags1 & ~Flag_CreateObjectFactory); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createObjectFactory : this->m_flags1 & ~c_createObjectFactory); } inline void CreateVariableTable(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateVariableTable : this->m_flags1 & ~Flag_CreateVariableTable); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createVariableTable : this->m_flags1 & ~c_createVariableTable); } inline void CreateTickleManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateTickleManager : this->m_flags1 & ~Flag_CreateTickleManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createTickleManager : this->m_flags1 & ~c_createTickleManager); } inline void CreateNotificationManager(MxBool p_enable) { this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateNotificationManager - : this->m_flags1 & ~Flag_CreateNotificationManager); + (p_enable ? this->m_flags1 | c_createNotificationManager : this->m_flags1 & ~c_createNotificationManager); } inline void CreateVideoManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateVideoManager : this->m_flags1 & ~Flag_CreateVideoManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createVideoManager : this->m_flags1 & ~c_createVideoManager); } inline void CreateSoundManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateSoundManager : this->m_flags1 & ~Flag_CreateSoundManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createSoundManager : this->m_flags1 & ~c_createSoundManager); } inline void CreateMusicManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateMusicManager : this->m_flags1 & ~Flag_CreateMusicManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createMusicManager : this->m_flags1 & ~c_createMusicManager); } inline void CreateEventManager(MxBool p_enable) { - this->m_flags1 = - (p_enable ? this->m_flags1 | Flag_CreateEventManager : this->m_flags1 & ~Flag_CreateEventManager); + this->m_flags1 = (p_enable ? this->m_flags1 | c_createEventManager : this->m_flags1 & ~c_createEventManager); } inline void CreateTimer(MxBool p_enable) { - this->m_flags2 = (p_enable ? this->m_flags2 | Flag_CreateTimer : this->m_flags2 & ~Flag_CreateTimer); + this->m_flags2 = (p_enable ? this->m_flags2 | c_createTimer : this->m_flags2 & ~c_createTimer); } inline void CreateStreamer(MxBool p_enable) { - this->m_flags2 = (p_enable ? this->m_flags2 | Flag_CreateStreamer : this->m_flags2 & ~Flag_CreateStreamer); + this->m_flags2 = (p_enable ? this->m_flags2 | c_createStreamer : this->m_flags2 & ~c_createStreamer); } private: diff --git a/LEGO1/omni/include/mxomnicreateparam.h b/LEGO1/omni/include/mxomnicreateparam.h index 825b5053..53539bc6 100644 --- a/LEGO1/omni/include/mxomnicreateparam.h +++ b/LEGO1/omni/include/mxomnicreateparam.h @@ -8,6 +8,7 @@ #include +// VTABLE: LEGO1 0x100dc218 class MxOmniCreateParam : public MxParam { public: __declspec(dllexport) MxOmniCreateParam( @@ -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/omni/include/mxpalette.h b/LEGO1/omni/include/mxpalette.h index 90ffa605..5ed5e80f 100644 --- a/LEGO1/omni/include/mxpalette.h +++ b/LEGO1/omni/include/mxpalette.h @@ -28,6 +28,9 @@ 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 diff --git a/LEGO1/omni/include/mxparam.h b/LEGO1/omni/include/mxparam.h index 19e92e0e..a266b12b 100644 --- a/LEGO1/omni/include/mxparam.h +++ b/LEGO1/omni/include/mxparam.h @@ -1,9 +1,18 @@ #ifndef MXPARAM_H #define MXPARAM_H +// VTABLE: ISLE 0x40f018 +// VTABLE: LEGO1 0x100d56e8 +// SIZE 0x04 class MxParam { public: + // FUNCTION: ISLE 0x401530 + // FUNCTION: LEGO1 0x10010360 virtual ~MxParam() {} }; +// SYNTHETIC: ISLE 0x401540 +// SYNTHETIC: LEGO1 0x10010370 +// MxParam::`scalar deleting destructor' + #endif // MXPARAM_H diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h index bc327c1f..a6b3eca8 100644 --- a/LEGO1/omni/include/mxpresenter.h +++ b/LEGO1/omni/include/mxpresenter.h @@ -17,19 +17,25 @@ class MxEntity; class MxPresenter : public MxCore { public: enum TickleState { - TickleState_Idle = 0, - TickleState_Ready, - TickleState_Starting, - TickleState_Streaming, - TickleState_Repeating, - TickleState_unk5, - TickleState_Done, + e_idle = 0, + e_ready, + e_starting, + e_streaming, + e_repeating, + e_unk5, + e_done, }; MxPresenter() { Init(); } - __declspec(dllexport) virtual ~MxPresenter(); // vtable+0x0 - __declspec(dllexport) virtual MxResult Tickle() override; // vtable+0x8 +#ifdef ISLE_APP + __declspec(dllexport) virtual ~MxPresenter() override; // vtable+0x00 +#else + // FUNCTION: LEGO1 0x1000bf00 + __declspec(dllexport) virtual ~MxPresenter() override{}; // vtable+0x00 +#endif + + __declspec(dllexport) virtual MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1000bfe0 inline virtual const char* ClassName() const override // vtable+0xc @@ -44,29 +50,73 @@ class MxPresenter : public MxCore { return !strcmp(p_name, MxPresenter::ClassName()) || MxCore::IsA(p_name); } - virtual void VTable0x14(); // vtable+0x14 - virtual void ReadyTickle(); // vtable+0x18 - virtual void StartingTickle(); // vtable+0x1c - virtual void StreamingTickle(); // vtable+0x20 - virtual void RepeatingTickle(); // vtable+0x24 - virtual void Unk5Tickle(); // vtable+0x28 + // FUNCTION: LEGO1 0x1000be30 + virtual void VTable0x14() {} // vtable+0x14 + + // FUNCTION: LEGO1 0x1000be40 + virtual void ReadyTickle() + { + ParseExtra(); + ProgressTickleState(e_starting); + } // vtable+0x18 + + // FUNCTION: LEGO1 0x1000be60 + virtual void StartingTickle() { ProgressTickleState(e_streaming); } // vtable+0x1c + + // FUNCTION: LEGO1 0x1000be80 + virtual void StreamingTickle() { ProgressTickleState(e_repeating); }; // vtable+0x20 + + // FUNCTION: LEGO1 0x1000bea0 + virtual void RepeatingTickle() { ProgressTickleState(e_unk5); }; // vtable+0x24 + + // FUNCTION: LEGO1 0x1000bec0 + virtual void Unk5Tickle() { ProgressTickleState(e_done); }; // vtable+0x28 protected: +#ifdef ISLE_APP __declspec(dllexport) virtual void DoneTickle(); // vtable+0x2c +#else + // FUNCTION: LEGO1 0x1000bee0 + __declspec(dllexport) virtual void DoneTickle() { ProgressTickleState(e_idle); }; // vtable+0x2c +#endif + __declspec(dllexport) virtual void ParseExtra(); // vtable+0x30 + inline void ProgressTickleState(TickleState p_tickleState) + { + m_previousTickleStates |= 1 << (MxU8) m_currentTickleState; + m_currentTickleState = p_tickleState; + } + public: - virtual MxResult AddToManager(); // vtable+0x34 - virtual void Destroy(); // vtable+0x38 + // FUNCTION: LEGO1 0x1000bf70 + virtual MxResult AddToManager() { return SUCCESS; }; // vtable+0x34 + + // FUNCTION: LEGO1 0x1000bf80 + virtual void Destroy() { Init(); }; // vtable+0x38 + __declspec(dllexport) virtual MxResult StartAction(MxStreamController*, MxDSAction*); // vtable+0x3c __declspec(dllexport) virtual void EndAction(); // vtable+0x40 - virtual void SetTickleState(TickleState p_tickleState); // vtable+0x44 - virtual MxBool HasTickleStatePassed(TickleState p_tickleState); // vtable+0x48 - virtual MxResult PutData(); // vtable+0x4c - virtual MxBool IsHit(MxS32 p_x, MxS32 p_y); // vtable+0x50 - __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 - MxEntity* CreateEntityBackend(const char* p_name); + // FUNCTION: LEGO1 0x1000bf90 + virtual void SetTickleState(TickleState p_tickleState) { ProgressTickleState(p_tickleState); } // vtable+0x44 + + // FUNCTION: LEGO1 0x1000bfb0 + virtual MxBool HasTickleStatePassed(TickleState p_tickleState) + { + return m_previousTickleStates & (1 << (MxU8) p_tickleState); + }; // vtable+0x48 + + // FUNCTION: LEGO1 0x1000bfc0 + virtual MxResult PutData() { return SUCCESS; }; // vtable+0x4c + + // FUNCTION: LEGO1 0x1000bfd0 + virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) { return FALSE; }; // vtable+0x50 + + __declspec(dllexport) virtual void Enable(MxBool p_enable); // vtable+0x54 + + MxEntity* CreateEntity(const char* p_name); + void SendToCompositePresenter(MxOmni*); MxBool IsEnabled(); inline MxS32 GetCurrentTickleState() const { return this->m_currentTickleState; } @@ -79,9 +129,11 @@ class MxPresenter : public MxCore { m_compositePresenter = p_compositePresenter; } + // SYNTHETIC: LEGO1 0x1000c070 + // MxPresenter::`scalar deleting destructor' + protected: __declspec(dllexport) void Init(); - void SendToCompositePresenter(MxOmni*); TickleState m_currentTickleState; // 0x8 MxU32 m_previousTickleStates; // 0x0c diff --git a/LEGO1/omni/include/mxpresenterlist.h b/LEGO1/omni/include/mxpresenterlist.h index d8b74a3f..257d0996 100644 --- a/LEGO1/omni/include/mxpresenterlist.h +++ b/LEGO1/omni/include/mxpresenterlist.h @@ -18,6 +18,9 @@ class MxPresenterList : public MxPtrList { { return p_a == p_b ? 0 : p_a < p_b ? -1 : 1; }; // 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' diff --git a/LEGO1/omni/include/mxrectlist.h b/LEGO1/omni/include/mxrectlist.h index e19c4994..c25c2483 100644 --- a/LEGO1/omni/include/mxrectlist.h +++ b/LEGO1/omni/include/mxrectlist.h @@ -53,6 +53,9 @@ class MxRectListCursor : public MxPtrListCursor { // SYNTHETIC: LEGO1 0x100b3d80 // MxRectList::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x100b3df0 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x100b3e40 // MxCollection::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxregion.h b/LEGO1/omni/include/mxregion.h index 646866a6..5659ba81 100644 --- a/LEGO1/omni/include/mxregion.h +++ b/LEGO1/omni/include/mxregion.h @@ -23,6 +23,9 @@ class MxRegion : public MxCore { friend class MxRegionCursor; + // SYNTHETIC: LEGO1 0x100c3670 + // MxRegion::`scalar deleting destructor' + private: MxRegionTopBottomList* m_list; // 0x08 MxRect32 m_rect; // 0x0c diff --git a/LEGO1/omni/include/mxregionlist.h b/LEGO1/omni/include/mxregionlist.h index 7c6da5c2..9dfd78bd 100644 --- a/LEGO1/omni/include/mxregionlist.h +++ b/LEGO1/omni/include/mxregionlist.h @@ -40,6 +40,9 @@ struct MxRegionLeftRight { class MxRegionLeftRightList : public MxPtrList { public: MxRegionLeftRightList() : MxPtrList(TRUE) {} + + // SYNTHETIC: LEGO1 0x100c4e90 + // MxRegionLeftRightList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dcbf8 @@ -95,6 +98,9 @@ struct MxRegionTopBottom { class MxRegionTopBottomList : public MxPtrList { public: MxRegionTopBottomList() : MxPtrList(TRUE) {} + + // SYNTHETIC: LEGO1 0x100c3410 + // MxRegionTopBottomList::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100dcb70 @@ -116,12 +122,21 @@ class MxRegionTopBottomListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x100c32e0 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100c32f0 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100c3340 // MxCollection::Destroy +// TEMPLATE: LEGO1 0x100c3350 +// MxList::~MxList + // TEMPLATE: LEGO1 0x100c33e0 // MxPtrList::Destroy +// TEMPLATE: LEGO1 0x100c3480 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x100c34d0 // MxCollection::`scalar deleting destructor' @@ -167,9 +182,18 @@ class MxRegionTopBottomListCursor : public MxPtrListCursor { // TEMPLATE: LEGO1 0x100c4d80 // MxCollection::Compare +// TEMPLATE: LEGO1 0x100c4d90 +// MxCollection::~MxCollection + // TEMPLATE: LEGO1 0x100c4de0 // MxCollection::Destroy +// TEMPLATE: LEGO1 0x100c4df0 +// MxList::~MxList + +// TEMPLATE: LEGO1 0x100c4f00 +// MxPtrList::~MxPtrList + // SYNTHETIC: LEGO1 0x100c4f50 // MxCollection::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxsemaphore.h b/LEGO1/omni/include/mxsemaphore.h index ecb6509c..4e692395 100644 --- a/LEGO1/omni/include/mxsemaphore.h +++ b/LEGO1/omni/include/mxsemaphore.h @@ -5,12 +5,13 @@ #include +// VTABLE: LEGO1 0x100dccf0 // SIZE 0x08 class MxSemaphore { public: MxSemaphore(); - // Inlined only, no offset + // FUNCTION: LEGO1 0x100c87e0 ~MxSemaphore() { CloseHandle(m_hSemaphore); } virtual MxResult Init(MxU32 p_initialCount, MxU32 p_maxCount); diff --git a/LEGO1/omni/include/mxsmack.h b/LEGO1/omni/include/mxsmack.h index e0f8c76e..227dbd6d 100644 --- a/LEGO1/omni/include/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 index 4c3913cc..eeb12945 100644 --- a/LEGO1/omni/include/mxsmkpresenter.h +++ b/LEGO1/omni/include/mxsmkpresenter.h @@ -33,6 +33,9 @@ class MxSmkPresenter : public MxVideoPresenter { virtual 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); diff --git a/LEGO1/omni/include/mxsoundpresenter.h b/LEGO1/omni/include/mxsoundpresenter.h index d61d8088..1949617f 100644 --- a/LEGO1/omni/include/mxsoundpresenter.h +++ b/LEGO1/omni/include/mxsoundpresenter.h @@ -8,7 +8,8 @@ // SIZE 0x54 class MxSoundPresenter : public MxAudioPresenter { public: - virtual ~MxSoundPresenter() override; + // FUNCTION: LEGO1 0x1000d430 + virtual ~MxSoundPresenter() override { Destroy(TRUE); }; // FUNCTION: LEGO1 0x1000d4a0 inline virtual const char* ClassName() const // vtable+0x0c @@ -24,7 +25,12 @@ class MxSoundPresenter : public MxAudioPresenter { }; virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + + // FUNCTION: LEGO1 0x1000d490 + virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + + // 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 index 828f58b7..0fa48bf3 100644 --- a/LEGO1/omni/include/mxstillpresenter.h +++ b/LEGO1/omni/include/mxstillpresenter.h @@ -25,11 +25,14 @@ class MxStillPresenter : public MxVideoPresenter { return !strcmp(p_name, MxStillPresenter::ClassName()) || MxVideoPresenter::IsA(p_name); } - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void ParseExtra() override; // vtable+0x30 - virtual void Destroy() override; // vtable+0x38 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void ParseExtra() override; // vtable+0x30 + + // FUNCTION: LEGO1 0x100435b0 + virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + virtual void Enable(MxBool p_enable) override; // vtable+0x54 virtual void LoadHeader(MxStreamChunk* p_chunk) override; // vtable+0x5c virtual void CreateBitmap() override; // vtable+0x60 diff --git a/LEGO1/omni/include/mxstreamchunklist.h b/LEGO1/omni/include/mxstreamchunklist.h index 02dcd2d9..9d8aec0e 100644 --- a/LEGO1/omni/include/mxstreamchunklist.h +++ b/LEGO1/omni/include/mxstreamchunklist.h @@ -26,9 +26,13 @@ class MxStreamChunkList : public MxList { // 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/omni/include/mxstreamcontroller.h b/LEGO1/omni/include/mxstreamcontroller.h index 790856c1..57caae8e 100644 --- a/LEGO1/omni/include/mxstreamcontroller.h +++ b/LEGO1/omni/include/mxstreamcontroller.h @@ -118,4 +118,7 @@ class MxStreamController : public MxCore { // TEMPLATE: LEGO1 0x100c1240 // List::~List +// TEMPLATE: LEGO1 0x100c1bc0 +// list >::insert + #endif // MXSTREAMCONTROLLER_H diff --git a/LEGO1/omni/include/mxstreamer.h b/LEGO1/omni/include/mxstreamer.h index 02f97d12..f22e343f 100644 --- a/LEGO1/omni/include/mxstreamer.h +++ b/LEGO1/omni/include/mxstreamer.h @@ -24,6 +24,7 @@ class MxStreamerSubClass1 { } } + // FUNCTION: LEGO1 0x100b9110 ~MxStreamerSubClass1() { delete[] m_buffer; } undefined4 GetSize() const { return m_size; } @@ -48,6 +49,7 @@ class MxStreamerSubClass3 : public MxStreamerSubClass1 { inline MxStreamerSubClass3() : MxStreamerSubClass1(0x80) {} }; +// VTABLE: LEGO1 0x100dc760 class MxStreamerNotification : public MxNotificationParam { public: inline MxStreamerNotification(NotificationId p_type, MxCore* p_sender, MxStreamController* p_ctrlr) @@ -56,8 +58,6 @@ class MxStreamerNotification : public MxNotificationParam { m_controller = p_ctrlr; } - virtual ~MxStreamerNotification() override {} - virtual MxNotificationParam* Clone() override; MxStreamController* GetController() { return m_controller; } @@ -71,7 +71,7 @@ class MxStreamerNotification : public MxNotificationParam { class MxStreamer : public MxCore { public: enum OpenMode { - e_DiskStream, + e_diskStream = 0, e_RAMStream }; @@ -100,6 +100,7 @@ class MxStreamer : public MxCore { MxBool FUN_100b9b30(MxDSObject& p_dsObject); MxStreamController* GetOpenStream(const char* p_name); + void FUN_100b98f0(MxDSAction* p_action); MxResult AddStreamControllerToOpenList(MxStreamController* p_stream); MxResult FUN_100b99b0(MxDSAction* p_action); MxResult DeleteObject(MxDSAction* p_dsAction); @@ -113,7 +114,21 @@ class MxStreamer : public MxCore { MxStreamerSubClass3 m_subclass2; // 0x20 }; +// clang-format off +// TEMPLATE: LEGO1 0x100b9090 +// list >::~list > +// clang-format on + // SYNTHETIC: LEGO1 0x100b9120 // MxStreamer::`scalar deleting destructor' +// TEMPLATE: LEGO1 0x100b9140 +// List::~List + +// SYNTHETIC: LEGO1 0x100b97b0 +// MxStreamerNotification::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100b9820 +// MxStreamerNotification::~MxStreamerNotification + #endif // MXSTREAMER_H diff --git a/LEGO1/omni/include/mxstreamprovider.h b/LEGO1/omni/include/mxstreamprovider.h index 17bba38d..803038e3 100644 --- a/LEGO1/omni/include/mxstreamprovider.h +++ b/LEGO1/omni/include/mxstreamprovider.h @@ -41,4 +41,7 @@ class MxStreamProvider : public MxCore { // SYNTHETIC: LEGO1 0x100d0870 // MxStreamProvider::`scalar deleting destructor' +// SYNTHETIC: LEGO1 0x100d08e0 +// MxStreamProvider::~MxStreamProvider + #endif // MXSTREAMPROVIDER_H diff --git a/LEGO1/omni/include/mxstring.h b/LEGO1/omni/include/mxstring.h index 6d8a9936..65c15d3e 100644 --- a/LEGO1/omni/include/mxstring.h +++ b/LEGO1/omni/include/mxstring.h @@ -22,6 +22,9 @@ 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; // 0x08 MxU16 m_length; // 0x0c diff --git a/LEGO1/omni/include/mxstringlist.h b/LEGO1/omni/include/mxstringlist.h index 6e75683d..6d07584f 100644 --- a/LEGO1/omni/include/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/omni/include/mxthread.h b/LEGO1/omni/include/mxthread.h index e3af186d..5ab80041 100644 --- a/LEGO1/omni/include/mxthread.h +++ b/LEGO1/omni/include/mxthread.h @@ -21,6 +21,9 @@ class MxThread { inline MxBool IsRunning() { return m_running; } + // SYNTHETIC: LEGO1 0x100bf580 + // MxThread::`scalar deleting destructor' + protected: MxThread(); @@ -48,6 +51,9 @@ class MxTickleThread : public MxThread { MxResult Run() override; + // SYNTHETIC: LEGO1 0x100b8c20 + // MxTickleThread::`scalar deleting destructor' + private: MxS32 m_frequencyMS; // 0x1c }; diff --git a/LEGO1/omni/include/mxticklemanager.h b/LEGO1/omni/include/mxticklemanager.h index 44694a61..6ebd655b 100644 --- a/LEGO1/omni/include/mxticklemanager.h +++ b/LEGO1/omni/include/mxticklemanager.h @@ -44,10 +44,19 @@ class MxTickleManager : public MxCore { 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 }; #define TICKLE_MANAGER_NOT_FOUND 0x80000000 +// TEMPLATE: LEGO1 0x1005a4a0 +// list >::~list > + +// TEMPLATE: LEGO1 0x1005a530 +// List::~List + #endif // MXTICKLEMANAGER_H diff --git a/LEGO1/omni/include/mxtimer.h b/LEGO1/omni/include/mxtimer.h index 70d52d79..63b597ac 100644 --- a/LEGO1/omni/include/mxtimer.h +++ b/LEGO1/omni/include/mxtimer.h @@ -22,6 +22,9 @@ class MxTimer : public MxCore { return g_lastTimeCalculated - this->m_startTime; } + // SYNTHETIC: LEGO1 0x100ae0d0 + // MxTimer::`scalar deleting destructor' + private: MxLong m_startTime; MxBool m_isRunning; diff --git a/LEGO1/omni/include/mxutil.h b/LEGO1/omni/include/mxutil.h index f9febef1..5eb0a984 100644 --- a/LEGO1/omni/include/mxutil.h +++ b/LEGO1/omni/include/mxutil.h @@ -3,8 +3,11 @@ #include "mxtypes.h" +#include + class MxDSFile; class MxDSObject; +class MxDSAction; template inline T Abs(T p_t) @@ -53,21 +56,22 @@ inline void GetString(MxU8** p_source, char** p_dest, T* p_obj, void (T::*p_sett *p_source += strlen(*p_dest) + 1; } -MxBool FUN_100b6e10( - MxS32 p_bitmapWidth, - MxS32 p_bitmapHeight, - MxS32 p_videoParamWidth, - MxS32 p_videoParamHeight, - MxS32* p_left, - MxS32* p_top, - MxS32* p_right, - MxS32* p_bottom, +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 ); __declspec(dllexport) void MakeSourceName(char*, const char*); __declspec(dllexport) void SetOmniUserMessage(void (*)(const char*, int)); +void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags); __declspec(dllexport) MxDSObject* CreateStreamObject(MxDSFile*, MxS16); MxBool KeyValueStringParse(char*, const char*, const char*); diff --git a/LEGO1/omni/include/mxvariable.h b/LEGO1/omni/include/mxvariable.h index d1434467..e09d449c 100644 --- a/LEGO1/omni/include/mxvariable.h +++ b/LEGO1/omni/include/mxvariable.h @@ -20,15 +20,24 @@ class MxVariable { m_key.ToUpperCase(); m_value = p_value; } - virtual MxString* GetValue(); - virtual void SetValue(const char* p_value); - virtual void Destroy(); + + // FUNCTION: LEGO1 0x1003bea0 + virtual MxString* GetValue() { return &m_value; }; + + // FUNCTION: LEGO1 0x1003beb0 + virtual void SetValue(const char* p_value) { m_value = p_value; }; + + // FUNCTION: LEGO1 0x1003bec0 + virtual void Destroy() { delete this; }; inline const MxString* GetKey() const { return &m_key; } protected: - MxString m_key; - MxString m_value; + MxString m_key; // 0x04 + MxString m_value; // 0x14 }; +// SYNTHETIC: LEGO1 0x1003bf40 +// MxVariable::~MxVariable + #endif // MXVARIABLE_H diff --git a/LEGO1/omni/include/mxvariabletable.h b/LEGO1/omni/include/mxvariabletable.h index 7821311e..fd5cdea2 100644 --- a/LEGO1/omni/include/mxvariabletable.h +++ b/LEGO1/omni/include/mxvariabletable.h @@ -18,6 +18,9 @@ class MxVariableTable : public MxHashTable { virtual MxS8 Compare(MxVariable*, MxVariable*) override; // vtable+0x14 virtual 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/omni/include/mxvideomanager.h b/LEGO1/omni/include/mxvideomanager.h index 41a7ce93..57919da3 100644 --- a/LEGO1/omni/include/mxvideomanager.h +++ b/LEGO1/omni/include/mxvideomanager.h @@ -32,7 +32,7 @@ class MxVideoManager : public MxMediaManager { __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 + virtual void UpdateView(MxU32 p_x, MxU32 p_y, MxU32 p_width, MxU32 p_height); // vtable+0x34 MxResult Init(); void Destroy(MxBool p_fromDestructor); @@ -44,6 +44,9 @@ class MxVideoManager : public MxMediaManager { 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 diff --git a/LEGO1/omni/include/mxvideopresenter.h b/LEGO1/omni/include/mxvideopresenter.h index f02f3f08..f338b972 100644 --- a/LEGO1/omni/include/mxvideopresenter.h +++ b/LEGO1/omni/include/mxvideopresenter.h @@ -11,15 +11,17 @@ class MxVideoPresenter : public MxMediaPresenter { public: enum { - Flag_Bit1 = 0x01, - Flag_Bit2 = 0x02, - Flag_Bit3 = 0x04, - Flag_Bit4 = 0x08, - Flag_Bit5 = 0x10, + c_bit1 = 0x01, + c_bit2 = 0x02, + c_bit3 = 0x04, + c_bit4 = 0x08, + c_bit5 = 0x10, }; MxVideoPresenter() { Init(); } - virtual ~MxVideoPresenter() override; // vtable+0x0 + + // FUNCTION: LEGO1 0x1000c740 + virtual ~MxVideoPresenter() override { Destroy(TRUE); }; // vtable+0x0 // FUNCTION: LEGO1 0x1000c820 inline virtual const char* ClassName() const override // vtable+0x0c @@ -34,28 +36,51 @@ class MxVideoPresenter : public MxMediaPresenter { return !strcmp(p_name, MxVideoPresenter::ClassName()) || MxMediaPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void RepeatingTickle() override; // vtable+0x24 - virtual void Unk5Tickle() override; // vtable+0x28 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void RepeatingTickle() override; // vtable+0x24 + virtual void Unk5Tickle() override; // vtable+0x28 + virtual MxResult AddToManager() override; // vtable+0x34 + + // FUNCTION: LEGO1 0x1000c7a0 + virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + virtual void EndAction() override; // vtable+0x40 virtual MxResult PutData() override; // vtable+0x4c virtual MxBool IsHit(MxS32 p_x, MxS32 p_y) override; // vtable+0x50 - virtual void LoadHeader(MxStreamChunk* p_chunk); // vtable+0x5c - virtual void CreateBitmap(); // vtable+0x60 - virtual void NextFrame(); // vtable+0x64 - virtual void LoadFrame(MxStreamChunk* p_chunk); // vtable+0x68 - virtual void PutFrame(); // vtable+0x6c - virtual void RealizePalette(); // vtable+0x70 - virtual undefined VTable0x74(); // vtable+0x74 - virtual LPDIRECTDRAWSURFACE VTable0x78(); // vtable+0x78 - virtual MxBool VTable0x7c(); // vtable+0x7c - virtual MxS32 GetWidth(); // vtable+0x80 - virtual MxS32 GetHeight(); // vtable+0x84 + // FUNCTION: LEGO1 0x1000c700 + virtual void LoadHeader(MxStreamChunk* p_chunk){}; // vtable+0x5c + + // FUNCTION: LEGO1 0x1000c710 + virtual void CreateBitmap(){}; // vtable+0x60 + + virtual void NextFrame(); // vtable+0x64 + + // FUNCTION: LEGO1 0x1000c720 + virtual void LoadFrame(MxStreamChunk* p_chunk){}; // vtable+0x68 + + virtual void PutFrame(); // vtable+0x6c + + // FUNCTION: LEGO1 0x1000c730 + virtual void RealizePalette(){}; // vtable+0x70 + + virtual undefined VTable0x74(); // vtable+0x74 + + // FUNCTION: LEGO1 0x1000c7b0 + virtual LPDIRECTDRAWSURFACE VTable0x78() { return m_unk0x58; }; // vtable+0x78 + + // FUNCTION: LEGO1 0x1000c7c0 + virtual MxBool VTable0x7c() { return (m_bitmap != NULL) || (m_alpha != NULL); }; // vtable+0x7c + + // FUNCTION: LEGO1 0x1000c7e0 + virtual MxS32 GetWidth() { return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiWidth(); }; // vtable+0x80 + + // FUNCTION: LEGO1 0x1000c800 + virtual MxS32 GetHeight() { return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs(); }; // vtable+0x84 + + // VTABLE: LEGO1 0x100dc2bc // SIZE 0xc struct AlphaMask { MxU8* m_bitmask; @@ -67,11 +92,17 @@ class MxVideoPresenter : public MxMediaPresenter { 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; } + // SYNTHETIC: LEGO1 0x1000c910 + // MxVideoPresenter::`scalar deleting destructor' + private: void Init(); diff --git a/LEGO1/omni/include/mxwavepresenter.h b/LEGO1/omni/include/mxwavepresenter.h index 383659ab..bffefe15 100644 --- a/LEGO1/omni/include/mxwavepresenter.h +++ b/LEGO1/omni/include/mxwavepresenter.h @@ -11,7 +11,9 @@ class MxWavePresenter : public MxSoundPresenter { public: MxWavePresenter() { Init(); } - virtual ~MxWavePresenter() override; // vtable+0x00 + + // FUNCTION: LEGO1 0x1000d640 + virtual ~MxWavePresenter() override { Destroy(TRUE); }; // vtable+0x00 // FUNCTION: LEGO1 0x1000d6c0 inline virtual const char* ClassName() const override // vtable+0x0c @@ -26,13 +28,16 @@ class MxWavePresenter : public MxSoundPresenter { return !strcmp(p_name, MxWavePresenter::ClassName()) || MxSoundPresenter::IsA(p_name); } - virtual void ReadyTickle() override; // vtable+0x18 - virtual void StartingTickle() override; // vtable+0x1c - virtual void StreamingTickle() override; // vtable+0x20 - virtual void DoneTickle() override; // vtable+0x2c - virtual void ParseExtra() override; // vtable+0x30 - virtual MxResult AddToManager() override; // vtable+0x34 - virtual void Destroy() override; // vtable+0x38 + virtual void ReadyTickle() override; // vtable+0x18 + virtual void StartingTickle() override; // vtable+0x1c + virtual void StreamingTickle() override; // vtable+0x20 + virtual void DoneTickle() override; // vtable+0x2c + virtual void ParseExtra() override; // vtable+0x30 + virtual MxResult AddToManager() override; // vtable+0x34 + + // FUNCTION: LEGO1 0x1000d6a0 + virtual void Destroy() override { Destroy(FALSE); }; // vtable+0x38 + virtual void EndAction() override; // vtable+0x40 virtual MxResult PutData() override; // vtable+0x4c virtual void Enable(MxBool p_enable) override; // vtable+0x54 @@ -40,7 +45,9 @@ class MxWavePresenter : public MxSoundPresenter { virtual void SetVolume(MxS32 p_volume) override; // vtable+0x60 virtual void Pause(); // vtable+0x64 virtual void Resume(); // vtable+0x68 - virtual MxBool IsPaused(); // vtable+0x6c + + // FUNCTION: LEGO1 0x1000d6b0 + virtual MxBool IsPaused() { return m_paused; }; // vtable+0x6c // Reference: https://github.com/itsmattkc/SIEdit/blob/master/lib/othertypes.h // SIZE 0x1c @@ -50,6 +57,9 @@ class MxWavePresenter : public MxSoundPresenter { MxU32 m_flags; }; + // SYNTHETIC: LEGO1 0x1000d810 + // MxWavePresenter::`scalar deleting destructor' + protected: void Destroy(MxBool p_fromDestructor); diff --git a/LEGO1/omni/src/action/mxdsaction.cpp b/LEGO1/omni/src/action/mxdsaction.cpp index b24ff347..cea02696 100644 --- a/LEGO1/omni/src/action/mxdsaction.cpp +++ b/LEGO1/omni/src/action/mxdsaction.cpp @@ -15,14 +15,14 @@ MxU16 g_sep = TWOCC(',', ' '); // FUNCTION: LEGO1 0x100ad810 MxDSAction::MxDSAction() { - this->m_flags = MxDSAction::Flag_Enabled; + this->m_flags = MxDSAction::c_enabled; this->m_startTime = INT_MIN; this->m_extraData = NULL; this->m_extraLength = 0; this->m_duration = INT_MIN; this->m_loopCount = -1; - this->SetType(MxDSType_Action); + this->SetType(e_action); this->m_location.Fill(FLT_MAX); this->m_direction.Fill(FLT_MAX); this->m_up.Fill(FLT_MAX); @@ -88,6 +88,12 @@ void MxDSAction::CopyFrom(MxDSAction& p_dsAction) this->m_unk0x90 = p_dsAction.m_unk0x90; } +// FUNCTION: LEGO1 0x100adbd0 +undefined4 MxDSAction::VTable0x14() +{ + return MxDSObject::VTable0x14(); +} + // FUNCTION: LEGO1 0x100adbe0 MxU32 MxDSAction::GetSizeOnDisk() { diff --git a/LEGO1/omni/src/action/mxdsanim.cpp b/LEGO1/omni/src/action/mxdsanim.cpp index c62be34c..cef2321c 100644 --- a/LEGO1/omni/src/action/mxdsanim.cpp +++ b/LEGO1/omni/src/action/mxdsanim.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSAnim, 0xb8) // FUNCTION: LEGO1 0x100c8ff0 MxDSAnim::MxDSAnim() { - this->SetType(MxDSType_Anim); + this->SetType(e_anim); } // FUNCTION: LEGO1 0x100c91a0 diff --git a/LEGO1/omni/src/action/mxdsevent.cpp b/LEGO1/omni/src/action/mxdsevent.cpp index 198c9ca0..bc925369 100644 --- a/LEGO1/omni/src/action/mxdsevent.cpp +++ b/LEGO1/omni/src/action/mxdsevent.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSEvent, 0xb8) // FUNCTION: LEGO1 0x100c95f0 MxDSEvent::MxDSEvent() { - this->SetType(MxDSType_Event); + this->SetType(e_event); } // FUNCTION: LEGO1 0x100c97a0 diff --git a/LEGO1/omni/src/action/mxdsmediaaction.cpp b/LEGO1/omni/src/action/mxdsmediaaction.cpp index c631dec8..fda2721a 100644 --- a/LEGO1/omni/src/action/mxdsmediaaction.cpp +++ b/LEGO1/omni/src/action/mxdsmediaaction.cpp @@ -15,7 +15,7 @@ MxDSMediaAction::MxDSMediaAction() this->m_paletteManagement = 1; this->m_unk0xb4 = -1; this->m_sustainTime = 0; - this->SetType(MxDSType_MediaAction); + this->SetType(e_mediaAction); } // FUNCTION: LEGO1 0x100c8cf0 @@ -47,6 +47,17 @@ MxDSMediaAction& MxDSMediaAction::operator=(MxDSMediaAction& p_dsMediaAction) return *this; } +// FUNCTION: LEGO1 0x100c8df0 +MxDSAction* MxDSMediaAction::Clone() +{ + MxDSMediaAction* clone = new MxDSMediaAction(); + + if (clone) + *clone = *this; + + return clone; +} + // FUNCTION: LEGO1 0x100c8e80 void MxDSMediaAction::CopyMediaSrcPath(const char* p_mediaSrcPath) { @@ -64,6 +75,12 @@ void MxDSMediaAction::CopyMediaSrcPath(const char* p_mediaSrcPath) this->m_mediaSrcPath = NULL; } +// FUNCTION: LEGO1 0x100c8f00 +undefined4 MxDSMediaAction::VTable0x14() +{ + return MxDSAction::VTable0x14(); +} + // FUNCTION: LEGO1 0x100c8f10 MxU32 MxDSMediaAction::GetSizeOnDisk() { diff --git a/LEGO1/omni/src/action/mxdsmultiaction.cpp b/LEGO1/omni/src/action/mxdsmultiaction.cpp index b986c23d..64e20a55 100644 --- a/LEGO1/omni/src/action/mxdsmultiaction.cpp +++ b/LEGO1/omni/src/action/mxdsmultiaction.cpp @@ -7,7 +7,7 @@ DECOMP_SIZE_ASSERT(MxDSActionListCursor, 0x10); // FUNCTION: LEGO1 0x100c9b90 MxDSMultiAction::MxDSMultiAction() { - this->SetType(MxDSType_MultiAction); + this->SetType(e_multiAction); this->m_actions = new MxDSActionList; this->m_actions->SetDestroy(MxDSActionList::Destroy); } diff --git a/LEGO1/omni/src/action/mxdsobject.cpp b/LEGO1/omni/src/action/mxdsobject.cpp index 7ee92937..6d11476d 100644 --- a/LEGO1/omni/src/action/mxdsobject.cpp +++ b/LEGO1/omni/src/action/mxdsobject.cpp @@ -11,7 +11,6 @@ #include "mxdsserialaction.h" #include "mxdssound.h" #include "mxdsstill.h" -#include "mxdstypes.h" #include "mxutil.h" #include @@ -22,7 +21,7 @@ DECOMP_SIZE_ASSERT(MxDSObject, 0x2c); // FUNCTION: LEGO1 0x100bf6a0 MxDSObject::MxDSObject() { - this->SetType(MxDSType_Object); + this->SetType(e_object); this->m_sourceName = NULL; this->m_unk0x14 = 0; this->m_objectName = NULL; @@ -148,40 +147,40 @@ MxDSObject* DeserializeDSObjectDispatch(MxU8** p_source, MxS16 p_flags) switch (type) { default: return NULL; - case MxDSType_Object: + case MxDSObject::e_object: obj = new MxDSObject(); break; - case MxDSType_Action: + case MxDSObject::e_action: obj = new MxDSAction(); break; - case MxDSType_MediaAction: + case MxDSObject::e_mediaAction: obj = new MxDSMediaAction(); break; - case MxDSType_Anim: + case MxDSObject::e_anim: obj = new MxDSAnim(); break; - case MxDSType_Sound: + case MxDSObject::e_sound: obj = new MxDSSound(); break; - case MxDSType_MultiAction: + case MxDSObject::e_multiAction: obj = new MxDSMultiAction(); break; - case MxDSType_SerialAction: + case MxDSObject::e_serialAction: obj = new MxDSSerialAction(); break; - case MxDSType_ParallelAction: + case MxDSObject::e_parallelAction: obj = new MxDSParallelAction(); break; - case MxDSType_Event: + case MxDSObject::e_event: obj = new MxDSEvent(); break; - case MxDSType_SelectAction: + case MxDSObject::e_selectAction: obj = new MxDSSelectAction(); break; - case MxDSType_Still: + case MxDSObject::e_still: obj = new MxDSStill(); break; - case MxDSType_ObjectAction: + case MxDSObject::e_objectAction: obj = new MxDSObjectAction(); break; } diff --git a/LEGO1/omni/src/action/mxdsobjectaction.cpp b/LEGO1/omni/src/action/mxdsobjectaction.cpp index 1155d3a5..db8b149f 100644 --- a/LEGO1/omni/src/action/mxdsobjectaction.cpp +++ b/LEGO1/omni/src/action/mxdsobjectaction.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSObjectAction, 0xb8) // FUNCTION: LEGO1 0x100c8870 MxDSObjectAction::MxDSObjectAction() { - this->SetType(MxDSType_ObjectAction); + this->SetType(e_objectAction); } // FUNCTION: LEGO1 0x100c8a20 diff --git a/LEGO1/omni/src/action/mxdsparallelaction.cpp b/LEGO1/omni/src/action/mxdsparallelaction.cpp index 07b0fef2..a14a326f 100644 --- a/LEGO1/omni/src/action/mxdsparallelaction.cpp +++ b/LEGO1/omni/src/action/mxdsparallelaction.cpp @@ -7,7 +7,7 @@ DECOMP_SIZE_ASSERT(MxDSParallelAction, 0x9c) // FUNCTION: LEGO1 0x100cae80 MxDSParallelAction::MxDSParallelAction() { - this->SetType(MxDSType_ParallelAction); + this->SetType(e_parallelAction); } // FUNCTION: LEGO1 0x100cb040 diff --git a/LEGO1/omni/src/action/mxdsselectaction.cpp b/LEGO1/omni/src/action/mxdsselectaction.cpp index 27f3a9cf..ddadde84 100644 --- a/LEGO1/omni/src/action/mxdsselectaction.cpp +++ b/LEGO1/omni/src/action/mxdsselectaction.cpp @@ -5,12 +5,14 @@ #include "mxvariabletable.h" DECOMP_SIZE_ASSERT(MxDSSelectAction, 0xb0) +DECOMP_SIZE_ASSERT(MxStringList, 0x18) +DECOMP_SIZE_ASSERT(MxStringListCursor, 0x10) DECOMP_SIZE_ASSERT(MxListEntry, 0x18) // FUNCTION: LEGO1 0x100cb2b0 MxDSSelectAction::MxDSSelectAction() { - this->SetType(MxDSType_SelectAction); + this->SetType(e_selectAction); this->m_unk0xac = new MxStringList; } diff --git a/LEGO1/omni/src/action/mxdsserialaction.cpp b/LEGO1/omni/src/action/mxdsserialaction.cpp index 59cda938..24513f48 100644 --- a/LEGO1/omni/src/action/mxdsserialaction.cpp +++ b/LEGO1/omni/src/action/mxdsserialaction.cpp @@ -7,7 +7,7 @@ DECOMP_SIZE_ASSERT(MxDSSerialAction, 0xa8) // FUNCTION: LEGO1 0x100ca9d0 MxDSSerialAction::MxDSSerialAction() { - this->SetType(MxDSType_SerialAction); + this->SetType(e_serialAction); this->m_cursor = new MxDSActionListCursor(this->m_actions); this->m_unk0xa0 = 0; } diff --git a/LEGO1/omni/src/action/mxdssound.cpp b/LEGO1/omni/src/action/mxdssound.cpp index 49806ce0..61022cab 100644 --- a/LEGO1/omni/src/action/mxdssound.cpp +++ b/LEGO1/omni/src/action/mxdssound.cpp @@ -8,7 +8,7 @@ DECOMP_SIZE_ASSERT(MxDSSound, 0xc0) MxDSSound::MxDSSound() { this->m_volume = 0x4f; - this->SetType(MxDSType_Sound); + this->SetType(e_sound); } // FUNCTION: LEGO1 0x100c9470 diff --git a/LEGO1/omni/src/action/mxdsstill.cpp b/LEGO1/omni/src/action/mxdsstill.cpp index 6ee1ede3..59a78ffc 100644 --- a/LEGO1/omni/src/action/mxdsstill.cpp +++ b/LEGO1/omni/src/action/mxdsstill.cpp @@ -5,7 +5,7 @@ DECOMP_SIZE_ASSERT(MxDSStill, 0xb8) // FUNCTION: LEGO1 0x100c98c0 MxDSStill::MxDSStill() { - this->SetType(MxDSType_Still); + this->SetType(e_still); } // FUNCTION: LEGO1 0x100c9a70 diff --git a/LEGO1/omni/src/audio/mxaudiomanager.cpp b/LEGO1/omni/src/audio/mxaudiomanager.cpp index 318a8446..a2d6072a 100644 --- a/LEGO1/omni/src/audio/mxaudiomanager.cpp +++ b/LEGO1/omni/src/audio/mxaudiomanager.cpp @@ -5,12 +5,6 @@ DECOMP_SIZE_ASSERT(MxAudioManager, 0x30); // GLOBAL: LEGO1 0x10102108 MxS32 MxAudioManager::g_count = 0; -// FUNCTION: LEGO1 0x10029910 -MxS32 MxAudioManager::GetVolume() -{ - return this->m_volume; -} - // FUNCTION: LEGO1 0x100b8d00 MxAudioManager::MxAudioManager() { diff --git a/LEGO1/omni/src/audio/mxaudiopresenter.cpp b/LEGO1/omni/src/audio/mxaudiopresenter.cpp index 1ef74dea..ac634362 100644 --- a/LEGO1/omni/src/audio/mxaudiopresenter.cpp +++ b/LEGO1/omni/src/audio/mxaudiopresenter.cpp @@ -3,15 +3,3 @@ #include "decomp.h" DECOMP_SIZE_ASSERT(MxAudioPresenter, 0x54); - -// FUNCTION: LEGO1 0x1000d260 -MxS32 MxAudioPresenter::GetVolume() -{ - return m_volume; -} - -// FUNCTION: LEGO1 0x1000d270 -void MxAudioPresenter::SetVolume(MxS32 p_volume) -{ - m_volume = p_volume; -} diff --git a/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp index 84b33229..77b32506 100644 --- a/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxloopingmidipresenter.cpp @@ -20,10 +20,8 @@ void MxLoopingMIDIPresenter::StreamingTickle() return; } - if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; - } + if (m_chunk->GetTime() + m_action->GetDuration() <= m_action->GetElapsedTime()) + ProgressTickleState(e_done); } // FUNCTION: LEGO1 0x100c2ae0 @@ -40,9 +38,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/omni/src/audio/mxmidipresenter.cpp b/LEGO1/omni/src/audio/mxmidipresenter.cpp index 95add150..5796fb67 100644 --- a/LEGO1/omni/src/audio/mxmidipresenter.cpp +++ b/LEGO1/omni/src/audio/mxmidipresenter.cpp @@ -52,8 +52,7 @@ void MxMIDIPresenter::ReadyTickle() if (chunk) { m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -62,19 +61,15 @@ void MxMIDIPresenter::StartingTickle() { MxStreamChunk* chunk = CurrentChunk(); - if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; - } + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) + ProgressTickleState(e_streaming); } // FUNCTION: LEGO1 0x100c2910 void MxMIDIPresenter::StreamingTickle() { - if (m_chunk) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; - } + if (m_chunk) + ProgressTickleState(e_done); else m_chunk = NextChunk(); } @@ -97,10 +92,10 @@ 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(); } diff --git a/LEGO1/omni/src/audio/mxmusicmanager.cpp b/LEGO1/omni/src/audio/mxmusicmanager.cpp index 244e3861..7a0684f8 100644 --- a/LEGO1/omni/src/audio/mxmusicmanager.cpp +++ b/LEGO1/omni/src/audio/mxmusicmanager.cpp @@ -31,11 +31,11 @@ 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_bufferSize = 0; + m_bufferCurrentSize = 0; + m_bufferOffset = 0; + m_bufferCurrentOffset = 0; + m_loopCount = 0; m_midiHdrP = NULL; } @@ -62,6 +62,60 @@ void MxMusicManager::Destroy(MxBool p_fromDestructor) } } +// 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() { @@ -74,6 +128,13 @@ void MxMusicManager::SetMIDIVolume() } } +// FUNCTION: LEGO1 0x100c0820 +void CALLBACK MxMusicManager::MidiCallbackProc(HDRVR p_hdrvr, UINT p_uMsg, DWORD p_dwUser, DWORD p_dw1, DWORD p_dw2) +{ + if (p_uMsg == MOM_DONE) + ((MxMusicManager*) p_dwUser)->ResetStream(); +} + // FUNCTION: LEGO1 0x100c0840 MxResult MxMusicManager::Create(MxU32 p_frequencyMS, MxBool p_createThread) { @@ -136,11 +197,68 @@ MxS32 MxMusicManager::CalculateVolume(MxS32 p_volume) return (result << 0x10) | result; } -// STUB: LEGO1 0x100c09c0 -undefined4 MxMusicManager::FUN_100c09c0(MxU8* p_data, MxS32 p_loopCount) +// FUNCTION: LEGO1 0x100c09c0 +MxResult MxMusicManager::InitializeMIDI(MxU8* p_data, MxS32 p_loopCount) { - // TODO - return 0; + 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 diff --git a/LEGO1/omni/src/audio/mxmusicpresenter.cpp b/LEGO1/omni/src/audio/mxmusicpresenter.cpp index dc2f4b7f..437cd52d 100644 --- a/LEGO1/omni/src/audio/mxmusicpresenter.cpp +++ b/LEGO1/omni/src/audio/mxmusicpresenter.cpp @@ -27,7 +27,7 @@ void MxMusicPresenter::Init() void MxMusicPresenter::Destroy(MxBool p_fromDestructor) { if (MusicManager()) { - MusicManager()->RemovePresenter(*this); + MusicManager()->UnregisterPresenter(*this); } m_criticalSection.Enter(); @@ -46,7 +46,7 @@ MxResult MxMusicPresenter::AddToManager() if (MusicManager()) { result = SUCCESS; - MusicManager()->AddPresenter(*this); + MusicManager()->RegisterPresenter(*this); } return result; diff --git a/LEGO1/omni/src/audio/mxsoundpresenter.cpp b/LEGO1/omni/src/audio/mxsoundpresenter.cpp index 1065fc99..b0376331 100644 --- a/LEGO1/omni/src/audio/mxsoundpresenter.cpp +++ b/LEGO1/omni/src/audio/mxsoundpresenter.cpp @@ -5,23 +5,11 @@ DECOMP_SIZE_ASSERT(MxSoundPresenter, 0x54) -// FUNCTION: LEGO1 0x1000d430 -MxSoundPresenter::~MxSoundPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000d490 -void MxSoundPresenter::Destroy() -{ - Destroy(FALSE); -} - // FUNCTION: LEGO1 0x100b1a50 void MxSoundPresenter::Destroy(MxBool p_fromDestructor) { if (MSoundManager()) - MSoundManager()->RemovePresenter(*this); + MSoundManager()->UnregisterPresenter(*this); this->m_criticalSection.Enter(); MxMediaPresenter::Init(); @@ -38,7 +26,7 @@ MxResult MxSoundPresenter::AddToManager() if (MSoundManager()) { ret = SUCCESS; - MSoundManager()->AddPresenter(*this); + MSoundManager()->RegisterPresenter(*this); } return ret; diff --git a/LEGO1/omni/src/audio/mxwavepresenter.cpp b/LEGO1/omni/src/audio/mxwavepresenter.cpp index d77ccac2..831e0043 100644 --- a/LEGO1/omni/src/audio/mxwavepresenter.cpp +++ b/LEGO1/omni/src/audio/mxwavepresenter.cpp @@ -11,24 +11,6 @@ DECOMP_SIZE_ASSERT(MxWavePresenter, 0x6c); DECOMP_SIZE_ASSERT(MxWavePresenter::WaveFormat, 0x1c); -// FUNCTION: LEGO1 0x1000d640 -MxWavePresenter::~MxWavePresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000d6a0 -void MxWavePresenter::Destroy() -{ - Destroy(FALSE); -} - -// FUNCTION: LEGO1 0x1000d6b0 -MxBool MxWavePresenter::IsPaused() -{ - return m_paused; -} - // FUNCTION: LEGO1 0x100b1ad0 void MxWavePresenter::Init() { @@ -104,7 +86,7 @@ void MxWavePresenter::WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length) } if (dwStatus != DSBSTATUS_BUFFERLOST) { - if (m_action->GetFlags() & MxDSAction::Flag_Looping) { + if (m_action->GetFlags() & MxDSAction::c_looping) { m_writtenChunks++; m_lockSize = p_length; } @@ -117,7 +99,7 @@ void MxWavePresenter::WriteToSoundBuffer(void* p_audioPtr, MxU32 p_length) DS_OK) { memcpy(pvAudioPtr1, p_audioPtr, p_length); - if (m_lockSize > p_length && !(m_action->GetFlags() & MxDSAction::Flag_Looping)) { + if (m_lockSize > p_length && !(m_action->GetFlags() & MxDSAction::c_looping)) { memset((MxU8*) pvAudioPtr1 + p_length, m_silenceData, m_lockSize - p_length); } @@ -136,8 +118,7 @@ void MxWavePresenter::ReadyTickle() memcpy(m_waveFormat, chunk->GetData(), chunk->GetLength()); m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -175,7 +156,7 @@ void MxWavePresenter::StartingTickle() else desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME; - if (m_action->GetFlags() & MxDSAction::Flag_Looping) + if (m_action->GetFlags() & MxDSAction::c_looping) desc.dwBufferBytes = m_waveFormat->m_waveFormatEx.nAvgBytesPerSec * (m_action->GetDuration() / m_action->GetLoopCount()) / 1000; else @@ -188,8 +169,7 @@ void MxWavePresenter::StartingTickle() } else { SetVolume(((MxDSSound*) m_action)->GetVolume()); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); } } } @@ -198,11 +178,11 @@ void MxWavePresenter::StartingTickle() void MxWavePresenter::StreamingTickle() { if (!m_currentChunk) { - if (!(m_action->GetFlags() & MxDSAction::Flag_Looping)) { + if (!(m_action->GetFlags() & MxDSAction::c_looping)) { MxStreamChunk* chunk = CurrentChunk(); - if (chunk && chunk->GetFlags() & MxDSChunk::Flag_End && !(chunk->GetFlags() & MxDSChunk::Flag_Bit16)) { - chunk->SetFlags(chunk->GetFlags() | MxDSChunk::Flag_Bit16); + if (chunk && chunk->GetFlags() & MxDSChunk::c_end && !(chunk->GetFlags() & MxDSChunk::c_bit16)) { + chunk->SetFlags(chunk->GetFlags() | MxDSChunk::c_bit16); m_currentChunk = new MxStreamChunk; MxU8* data = new MxU8[m_chunkLength]; @@ -212,7 +192,7 @@ void MxWavePresenter::StreamingTickle() m_currentChunk->SetLength(m_chunkLength); m_currentChunk->SetData(data); m_currentChunk->SetTime(chunk->GetTime() + 1000); - m_currentChunk->SetFlags(MxDSChunk::Flag_Bit1); + m_currentChunk->SetFlags(MxDSChunk::c_bit1); } } @@ -228,7 +208,7 @@ void MxWavePresenter::DoneTickle() m_dsBuffer->GetCurrentPosition(&dwCurrentPlayCursor, &dwCurrentWriteCursor); MxS8 playedChunks = dwCurrentPlayCursor / m_chunkLength; - if (m_action->GetFlags() & MxDSAction::Flag_Bit7 || m_action->GetFlags() & MxDSAction::Flag_Looping || + if (m_action->GetFlags() & MxDSAction::c_bit7 || m_action->GetFlags() & MxDSAction::c_looping || m_writtenChunks != playedChunks || m_lockSize + (m_chunkLength * playedChunks) <= dwCurrentPlayCursor) MxMediaPresenter::DoneTickle(); } @@ -251,7 +231,7 @@ MxResult MxWavePresenter::PutData() if (IsEnabled()) { switch (m_currentTickleState) { - case TickleState_Streaming: + case e_streaming: if (m_currentChunk && FUN_100b1ba0()) { WriteToSoundBuffer(m_currentChunk->GetData(), m_currentChunk->GetLength()); m_subscriber->DestroyChunk(m_currentChunk); @@ -265,7 +245,7 @@ MxResult MxWavePresenter::PutData() m_started = TRUE; } break; - case TickleState_Repeating: + case e_repeating: if (m_started) break; @@ -359,13 +339,13 @@ void MxWavePresenter::Resume() if (m_paused) { if (m_dsBuffer && m_started) { switch (m_currentTickleState) { - case TickleState_Streaming: + case e_streaming: m_dsBuffer->Play(0, 0, DSBPLAY_LOOPING); break; - case TickleState_Repeating: + case e_repeating: m_dsBuffer->Play(0, 0, m_action->GetLoopCount() > 1); break; - case TickleState_Done: + case e_done: m_dsBuffer->Play(0, 0, 0); } } diff --git a/LEGO1/omni/src/common/mxatomid.cpp b/LEGO1/omni/src/common/mxatomid.cpp index ae57c820..6c400eed 100644 --- a/LEGO1/omni/src/common/mxatomid.cpp +++ b/LEGO1/omni/src/common/mxatomid.cpp @@ -55,7 +55,7 @@ MxAtomId& MxAtomId::operator=(const MxAtomId& p_atomId) Destroy(); if (p_atomId.m_internal && MxOmni::GetInstance() && AtomIdCounterSet()) { - MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, LookupMode_Exact); + MxAtomIdCounter* counter = GetCounter(p_atomId.m_internal, e_exact); counter->Inc(); } @@ -71,11 +71,11 @@ MxAtomIdCounter* MxAtomId::GetCounter(const char* p_str, LookupMode p_mode) MxAtomIdCounter* counter = new MxAtomIdCounter(p_str); switch (p_mode) { - case LookupMode_LowerCase: - case LookupMode_LowerCase2: + case e_lowerCase: + case e_lowerCase2: counter->GetKey()->ToLowerCase(); break; - case LookupMode_UpperCase: + case e_upperCase: counter->GetKey()->ToUpperCase(); break; } diff --git a/LEGO1/omni/src/common/mxcompositepresenter.cpp b/LEGO1/omni/src/common/mxcompositepresenter.cpp index d22c979d..5c5b612e 100644 --- a/LEGO1/omni/src/common/mxcompositepresenter.cpp +++ b/LEGO1/omni/src/common/mxcompositepresenter.cpp @@ -8,14 +8,6 @@ DECOMP_SIZE_ASSERT(MxCompositePresenter, 0x4c); -// FUNCTION: LEGO1 0x1000caf0 -MxBool MxCompositePresenter::VTable0x64(undefined4 p_undefined) -{ - if (m_compositePresenter) - return m_compositePresenter->VTable0x64(p_undefined); - return TRUE; -} - // FUNCTION: LEGO1 0x100b60b0 MxCompositePresenter::MxCompositePresenter() { @@ -120,7 +112,7 @@ MxLong MxCompositePresenter::Notify(MxParam& p_param) case c_notificationEndAction: VTable0x58((MxEndActionNotificationParam&) p_param); break; - case MXPRESENTER_NOTIFICATION: + case c_notificationPresenter: VTable0x5c((MxNotificationParam&) p_param); } @@ -163,8 +155,8 @@ void MxCompositePresenter::VTable0x58(MxEndActionNotificationParam& p_param) else { if (m_action->IsA("MxDSSerialAction") && it != m_list.end()) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); } } } @@ -179,8 +171,8 @@ void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param) if (*it == presenter) { m_list.erase(it++); - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); MxDSActionList* actions = ((MxDSMultiAction*) m_action)->GetActionList(); MxDSActionListCursor cursor(actions); @@ -194,8 +186,8 @@ void MxCompositePresenter::VTable0x5c(MxNotificationParam& p_param) else { if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); } } @@ -218,8 +210,8 @@ void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter) } else if (m_action->IsA("MxDSSerialAction")) { MxPresenter* presenter = *it; - if (presenter->GetCurrentTickleState() == TickleState_Idle) - presenter->SetTickleState(TickleState_Ready); + if (presenter->GetCurrentTickleState() == e_idle) + presenter->SetTickleState(e_ready); } return; } @@ -229,14 +221,13 @@ void MxCompositePresenter::VTable0x60(MxPresenter* p_presenter) // FUNCTION: LEGO1 0x100b6bc0 void MxCompositePresenter::SetTickleState(TickleState p_tickleState) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = p_tickleState; + ProgressTickleState(p_tickleState); for (MxCompositePresenterList::iterator it = m_list.begin(); it != m_list.end(); it++) { MxPresenter* presenter = *it; presenter->SetTickleState(p_tickleState); - if (m_action->IsA("MxDSSerialAction") && p_tickleState == TickleState_Ready) + if (m_action->IsA("MxDSSerialAction") && p_tickleState == e_ready) return; } } diff --git a/LEGO1/omni/src/common/mxcore.cpp b/LEGO1/omni/src/common/mxcore.cpp index 237ed1da..1266a1cb 100644 --- a/LEGO1/omni/src/common/mxcore.cpp +++ b/LEGO1/omni/src/common/mxcore.cpp @@ -2,12 +2,6 @@ #include "define.h" -// FUNCTION: LEGO1 0x10001f70 -MxResult MxCore::Tickle() -{ - return SUCCESS; -} - // FUNCTION: LEGO1 0x100ae1a0 MxCore::MxCore() { diff --git a/LEGO1/omni/src/common/mxmediamanager.cpp b/LEGO1/omni/src/common/mxmediamanager.cpp index e9b4fe6d..778d7f86 100644 --- a/LEGO1/omni/src/common/mxmediamanager.cpp +++ b/LEGO1/omni/src/common/mxmediamanager.cpp @@ -75,7 +75,7 @@ MxResult MxMediaManager::Tickle() } // FUNCTION: LEGO1 0x100b88c0 -void MxMediaManager::AddPresenter(MxPresenter& p_presenter) +void MxMediaManager::RegisterPresenter(MxPresenter& p_presenter) { MxAutoLocker lock(&this->m_criticalSection); @@ -83,7 +83,7 @@ void MxMediaManager::AddPresenter(MxPresenter& p_presenter) } // FUNCTION: LEGO1 0x100b8980 -void MxMediaManager::RemovePresenter(MxPresenter& p_presenter) +void MxMediaManager::UnregisterPresenter(MxPresenter& p_presenter) { MxAutoLocker lock(&this->m_criticalSection); MxPresenterListCursor cursor(this->m_presenters); diff --git a/LEGO1/omni/src/common/mxmediapresenter.cpp b/LEGO1/omni/src/common/mxmediapresenter.cpp index a9383e4d..2abc5007 100644 --- a/LEGO1/omni/src/common/mxmediapresenter.cpp +++ b/LEGO1/omni/src/common/mxmediapresenter.cpp @@ -11,18 +11,6 @@ DECOMP_SIZE_ASSERT(MxMediaPresenter, 0x50); DECOMP_SIZE_ASSERT(MxStreamChunkList, 0x18); DECOMP_SIZE_ASSERT(MxStreamChunkListCursor, 0x10); -// FUNCTION: LEGO1 0x1000c550 -MxMediaPresenter::~MxMediaPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000c5b0 -void MxMediaPresenter::Destroy() -{ - Destroy(FALSE); -} - // FUNCTION: LEGO1 0x100b54e0 void MxMediaPresenter::Init() { @@ -72,13 +60,12 @@ MxStreamChunk* MxMediaPresenter::CurrentChunk() if (m_subscriber) { chunk = m_subscriber->CurrentChunk(); - if (chunk && chunk->GetFlags() & MxDSChunk::Flag_Bit3) { - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); + if (chunk && chunk->GetFlags() & MxDSChunk::c_bit3) { + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_bit7); m_subscriber->NextChunk(); m_subscriber->DestroyChunk(chunk); chunk = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } } @@ -93,12 +80,11 @@ MxStreamChunk* MxMediaPresenter::NextChunk() if (m_subscriber) { chunk = m_subscriber->NextChunk(); - if (chunk && chunk->GetFlags() & MxDSChunk::Flag_Bit3) { - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_Bit7); + if (chunk && chunk->GetFlags() & MxDSChunk::c_bit3) { + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_bit7); m_subscriber->DestroyChunk(chunk); chunk = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + ProgressTickleState(e_done); } } @@ -112,7 +98,7 @@ MxResult MxMediaPresenter::StartAction(MxStreamController* p_controller, MxDSAct MxAutoLocker lock(&m_criticalSection); if (MxPresenter::StartAction(p_controller, p_action) == SUCCESS) { - if (m_action->GetFlags() & MxDSAction::Flag_Looping) { + if (m_action->GetFlags() & MxDSAction::c_looping) { m_loopingChunks = new MxStreamChunkList; m_loopingChunkCursor = new MxStreamChunkListCursor(m_loopingChunks); @@ -145,10 +131,9 @@ void MxMediaPresenter::EndAction() m_currentChunk = NULL; - if (m_action->GetFlags() & MxDSAction::Flag_World && - (!m_compositePresenter || !m_compositePresenter->VTable0x64(2))) { + if (m_action->GetFlags() & MxDSAction::c_world && (!m_compositePresenter || !m_compositePresenter->VTable0x64(2))) { MxPresenter::Enable(FALSE); - SetTickleState(TickleState_Idle); + SetTickleState(e_idle); } else { MxDSAction* action = m_action; @@ -192,13 +177,12 @@ void MxMediaPresenter::StreamingTickle() m_currentChunk = NextChunk(); if (m_currentChunk) { - if (m_currentChunk->GetFlags() & MxDSChunk::Flag_End) { + if (m_currentChunk->GetFlags() & MxDSChunk::c_end) { m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); } - else if (m_action->GetFlags() & MxDSAction::Flag_Looping) { + else if (m_action->GetFlags() & MxDSAction::c_looping) { LoopChunk(m_currentChunk); if (!IsEnabled()) { @@ -220,16 +204,12 @@ void MxMediaPresenter::RepeatingTickle() if (m_currentChunk) { MxLong time = m_currentChunk->GetTime(); - if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (time <= m_action->GetElapsedTime() % m_action->GetLoopCount()) + ProgressTickleState(e_unk5); } else { - if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) + ProgressTickleState(e_unk5); } } } @@ -238,7 +218,7 @@ void MxMediaPresenter::RepeatingTickle() void MxMediaPresenter::DoneTickle() { m_previousTickleStates |= 1 << m_currentTickleState; - m_currentTickleState = TickleState_Idle; + m_currentTickleState = e_idle; EndAction(); } @@ -265,13 +245,13 @@ void MxMediaPresenter::Enable(MxBool p_enable) if (p_enable) { MxLong time = Timer()->GetTime(); m_action->SetUnknown90(time); - SetTickleState(TickleState_Repeating); + SetTickleState(e_repeating); } else { if (m_loopingChunkCursor) m_loopingChunkCursor->Reset(); m_currentChunk = NULL; - SetTickleState(TickleState_Done); + SetTickleState(e_done); } } } diff --git a/LEGO1/omni/src/common/mxobjectfactory.cpp b/LEGO1/omni/src/common/mxobjectfactory.cpp index a4e5efd1..93f2e0a0 100644 --- a/LEGO1/omni/src/common/mxobjectfactory.cpp +++ b/LEGO1/omni/src/common/mxobjectfactory.cpp @@ -19,7 +19,7 @@ DECOMP_SIZE_ASSERT(MxObjectFactory, 0x38); // 100af1db // FUNCTION: LEGO1 0x100b0d80 MxObjectFactory::MxObjectFactory() { -#define X(V) this->m_id##V = MxAtomId(#V, LookupMode_Exact); +#define X(V) this->m_id##V = MxAtomId(#V, e_exact); FOR_MXOBJECTFACTORY_OBJECTS(X) #undef X } @@ -28,7 +28,7 @@ MxObjectFactory::MxObjectFactory() MxCore* MxObjectFactory::Create(const char* p_name) { MxCore* object = NULL; - MxAtomId atom(p_name, LookupMode_Exact); + MxAtomId atom(p_name, e_exact); if (0) { } diff --git a/LEGO1/omni/src/common/mxpresenter.cpp b/LEGO1/omni/src/common/mxpresenter.cpp index 0595aee7..9d074278 100644 --- a/LEGO1/omni/src/common/mxpresenter.cpp +++ b/LEGO1/omni/src/common/mxpresenter.cpp @@ -18,101 +18,10 @@ DECOMP_SIZE_ASSERT(MxPresenter, 0x40); -// FUNCTION: LEGO1 0x1000be30 -void MxPresenter::VTable0x14() -{ -} - -// FUNCTION: LEGO1 0x1000be40 -void MxPresenter::ReadyTickle() -{ - ParseExtra(); - - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; -} - -// FUNCTION: LEGO1 0x1000be60 -void MxPresenter::StartingTickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; -} - -// FUNCTION: LEGO1 0x1000be80 -void MxPresenter::StreamingTickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; -} - -// FUNCTION: LEGO1 0x1000bea0 -void MxPresenter::RepeatingTickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; -} - -// FUNCTION: LEGO1 0x1000bec0 -void MxPresenter::Unk5Tickle() -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; -} - -// FUNCTION: LEGO1 0x1000bee0 -void MxPresenter::DoneTickle() -{ - m_previousTickleStates |= 1 << m_currentTickleState; - m_currentTickleState = TickleState_Idle; -} - -// FUNCTION: LEGO1 0x1000bf00 -MxPresenter::~MxPresenter() -{ -} - -// FUNCTION: LEGO1 0x1000bf70 -MxResult MxPresenter::AddToManager() -{ - return SUCCESS; -} - -// FUNCTION: LEGO1 0x1000bf80 -void MxPresenter::Destroy() -{ - Init(); -} - -// FUNCTION: LEGO1 0x1000bf90 -void MxPresenter::SetTickleState(TickleState p_tickleState) -{ - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = p_tickleState; -} - -// FUNCTION: LEGO1 0x1000bfb0 -MxBool MxPresenter::HasTickleStatePassed(TickleState p_tickleState) -{ - return m_previousTickleStates & (1 << (unsigned char) p_tickleState); -} - -// FUNCTION: LEGO1 0x1000bfc0 -MxResult MxPresenter::PutData() -{ - return SUCCESS; -} - -// FUNCTION: LEGO1 0x1000bfd0 -MxBool MxPresenter::IsHit(MxS32 p_x, MxS32 p_y) -{ - return FALSE; -} - // FUNCTION: LEGO1 0x100b4d50 void MxPresenter::Init() { - m_currentTickleState = TickleState_Idle; + m_currentTickleState = e_idle; m_action = NULL; m_location = MxPoint32(0, 0); m_displayZ = 0; @@ -127,13 +36,12 @@ MxResult MxPresenter::StartAction(MxStreamController*, MxDSAction* p_action) this->m_action = p_action; - const Vector3Data& location = this->m_action->GetLocation(); + const Mx3DPointFloat& location = this->m_action->GetLocation(); MxS32 previousTickleState = this->m_currentTickleState; this->m_location = MxPoint32(this->m_action->GetLocation()[0], this->m_action->GetLocation()[1]); this->m_displayZ = this->m_action->GetLocation()[2]; - this->m_previousTickleStates |= 1 << (unsigned char) previousTickleState; - this->m_currentTickleState = TickleState_Ready; + ProgressTickleState(e_ready); return SUCCESS; } @@ -162,7 +70,7 @@ void MxPresenter::EndAction() this->m_action = NULL; MxS32 previousTickleState = 1 << m_currentTickleState; this->m_previousTickleStates |= previousTickleState; - this->m_currentTickleState = TickleState_Idle; + this->m_currentTickleState = e_idle; } // FUNCTION: LEGO1 0x100b4fc0 @@ -188,7 +96,7 @@ void MxPresenter::ParseExtra() MxS32 val = token ? atoi(token) : 0; MxEntity* result = MxOmni::GetInstance()->FindWorld(buf, val, this); - m_action->SetFlags(m_action->GetFlags() | MxDSAction::Flag_World); + m_action->SetFlags(m_action->GetFlags() | MxDSAction::c_world); if (result) SendToCompositePresenter(MxOmni::GetInstance()); @@ -204,11 +112,11 @@ void MxPresenter::SendToCompositePresenter(MxOmni* p_omni) #ifdef COMPAT_MODE { - MxNotificationParam param(MXPRESENTER_NOTIFICATION, this); + MxNotificationParam param(c_notificationPresenter, this); NotificationManager()->Send(m_compositePresenter, ¶m); } #else - NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(MXPRESENTER_NOTIFICATION, this)); + NotificationManager()->Send(m_compositePresenter, &MxNotificationParam(c_notificationPresenter, this)); #endif m_action->SetOrigin(p_omni ? p_omni : MxOmni::GetInstance()); @@ -222,32 +130,32 @@ MxResult MxPresenter::Tickle() MxAutoLocker lock(&this->m_criticalSection); switch (this->m_currentTickleState) { - case TickleState_Ready: + case e_ready: this->ReadyTickle(); - if (m_currentTickleState != TickleState_Starting) + if (m_currentTickleState != e_starting) break; - case TickleState_Starting: + case e_starting: this->StartingTickle(); - if (m_currentTickleState != TickleState_Streaming) + if (m_currentTickleState != e_streaming) break; - case TickleState_Streaming: + case e_streaming: this->StreamingTickle(); - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) break; - case TickleState_Repeating: + case e_repeating: this->RepeatingTickle(); - if (m_currentTickleState != TickleState_unk5) + if (m_currentTickleState != e_unk5) break; - case TickleState_unk5: + case e_unk5: this->Unk5Tickle(); - if (m_currentTickleState != TickleState_Done) + if (m_currentTickleState != e_done) break; - case TickleState_Done: + case e_done: this->DoneTickle(); default: break; @@ -263,9 +171,9 @@ void MxPresenter::Enable(MxBool p_enable) MxU32 flags = this->m_action->GetFlags(); if (p_enable) - this->m_action->SetFlags(flags | MxDSAction::Flag_Enabled); + this->m_action->SetFlags(flags | MxDSAction::c_enabled); else - this->m_action->SetFlags(flags & ~MxDSAction::Flag_Enabled); + this->m_action->SetFlags(flags & ~MxDSAction::c_enabled); } } @@ -277,7 +185,7 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) if (!name || strlen(name) == 0) { switch (p_action.GetType()) { - case MxDSType_Anim: + case MxDSObject::e_anim: format = ((MxDSAnim&) p_action).GetMediaFormat(); switch (format) { case FOURCC(' ', 'F', 'L', 'C'): @@ -289,7 +197,7 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) } break; - case MxDSType_Sound: + case MxDSObject::e_sound: format = ((MxDSSound&) p_action).GetMediaFormat(); switch (format) { case FOURCC(' ', 'M', 'I', 'D'): @@ -301,17 +209,17 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) } break; - case MxDSType_SerialAction: - case MxDSType_ParallelAction: - case MxDSType_SelectAction: + case MxDSObject::e_serialAction: + case MxDSObject::e_parallelAction: + case MxDSObject::e_selectAction: name = "MxCompositePresenter"; break; - case MxDSType_Event: + case MxDSObject::e_event: name = "MxEventPresenter"; break; - case MxDSType_Still: + case MxDSObject::e_still: name = "MxStillPresenter"; break; } @@ -321,7 +229,7 @@ const char* PresenterNameDispatch(const MxDSAction& p_action) } // FUNCTION: LEGO1 0x100b5410 -MxEntity* MxPresenter::CreateEntityBackend(const char* p_name) +MxEntity* MxPresenter::CreateEntity(const char* p_name) { char buffer[512]; char buffer2[512]; @@ -344,5 +252,5 @@ MxEntity* MxPresenter::CreateEntityBackend(const char* p_name) // FUNCTION: LEGO1 0x100b54c0 MxBool MxPresenter::IsEnabled() { - return this->m_action && this->m_action->GetFlags() & MxDSAction::Flag_Enabled; + return this->m_action && this->m_action->GetFlags() & MxDSAction::c_enabled; } diff --git a/LEGO1/omni/src/common/mxutil.cpp b/LEGO1/omni/src/common/mxutil.cpp index 538368d1..29b71863 100644 --- a/LEGO1/omni/src/common/mxutil.cpp +++ b/LEGO1/omni/src/common/mxutil.cpp @@ -1,6 +1,9 @@ #include "mxutil.h" +#include "mxdsaction.h" +#include "mxdsactionlist.h" #include "mxdsfile.h" +#include "mxdsmultiaction.h" #include "mxdsobject.h" #include "mxrect32.h" @@ -8,45 +11,45 @@ void (*g_omniUserMessage)(const char*, int); // FUNCTION: LEGO1 0x100b6e10 -MxBool FUN_100b6e10( - MxS32 p_bitmapWidth, - MxS32 p_bitmapHeight, - MxS32 p_videoParamWidth, - MxS32 p_videoParamHeight, - MxS32* p_left, - MxS32* p_top, - MxS32* p_right, - MxS32* p_bottom, +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 topLeft(*p_left, *p_top); - MxRect32 bitmapRect(MxPoint32(0, 0), MxSize32(p_bitmapWidth, p_bitmapHeight)); + MxPoint32 rect1Origin(*p_rect1Left, *p_rect1Top); + MxRect32 rect1(MxPoint32(0, 0), MxSize32(p_rect1Width, p_rect1Height)); - MxPoint32 bottomRight(*p_right, *p_bottom); - MxRect32 videoParamRect(MxPoint32(0, 0), MxSize32(p_videoParamWidth, p_videoParamHeight)); + 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(topLeft); + rect.AddPoint(rect1Origin); - if (!rect.IntersectsWith(bitmapRect)) + if (!rect.IntersectsWith(rect1)) return FALSE; - rect.Intersect(bitmapRect); - rect.SubtractPoint(topLeft); - rect.AddPoint(bottomRight); + rect.Intersect(rect1); + rect.SubtractPoint(rect1Origin); + rect.AddPoint(rect2Origin); - if (!rect.IntersectsWith(videoParamRect)) + if (!rect.IntersectsWith(rect2)) return FALSE; - rect.Intersect(videoParamRect); - rect.SubtractPoint(bottomRight); + rect.Intersect(rect2); + rect.SubtractPoint(rect2Origin); - *p_left += rect.GetLeft(); - *p_top += rect.GetTop(); - *p_right += rect.GetLeft(); - *p_bottom += rect.GetTop(); + *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; @@ -112,6 +115,21 @@ void SetOmniUserMessage(void (*p_userMsg)(const char*, int)) g_omniUserMessage = p_userMsg; } +// FUNCTION: LEGO1 0x100b7220 +void FUN_100b7220(MxDSAction* p_action, MxU32 p_newFlags, MxBool p_setFlags) +{ + p_action->SetFlags(!p_setFlags ? p_action->GetFlags() & ~p_newFlags : p_action->GetFlags() | p_newFlags); + + if (p_action->IsA("MxDSMultiAction")) { + MxDSActionListCursor cursor(((MxDSMultiAction*) p_action)->GetActionList()); + MxDSAction* action; + + while (cursor.Next(action)) { + FUN_100b7220(action, p_newFlags, p_setFlags); + } + } +} + // Should probably be somewhere else // FUNCTION: LEGO1 0x100c0280 MxDSObject* CreateStreamObject(MxDSFile* p_file, MxS16 p_ofs) diff --git a/LEGO1/omni/src/common/mxvariable.cpp b/LEGO1/omni/src/common/mxvariable.cpp index a60051fd..7b0a46c1 100644 --- a/LEGO1/omni/src/common/mxvariable.cpp +++ b/LEGO1/omni/src/common/mxvariable.cpp @@ -4,21 +4,3 @@ #include "mxstring.h" DECOMP_SIZE_ASSERT(MxVariable, 0x24) - -// FUNCTION: LEGO1 0x1003bea0 -MxString* MxVariable::GetValue() -{ - return &m_value; -} - -// FUNCTION: LEGO1 0x1003beb0 -void MxVariable::SetValue(const char* p_value) -{ - m_value = p_value; -} - -// FUNCTION: LEGO1 0x1003bec0 -void MxVariable::Destroy() -{ - delete this; -} diff --git a/LEGO1/omni/src/common/mxvariabletable.cpp b/LEGO1/omni/src/common/mxvariabletable.cpp index d7c6f54f..9503ee5e 100644 --- a/LEGO1/omni/src/common/mxvariabletable.cpp +++ b/LEGO1/omni/src/common/mxvariabletable.cpp @@ -50,6 +50,8 @@ void MxVariableTable::SetVariable(MxVariable* p_var) // FUNCTION: LEGO1 0x100b78f0 const char* MxVariableTable::GetVariable(const char* p_key) { + // STRING: ISLE 0x41008c + // STRING: LEGO1 0x100f01d4 const char* value = ""; MxHashTableCursor cursor(this); MxVariable* var = new MxVariable(p_key); diff --git a/LEGO1/omni/src/entity/mxentity.cpp b/LEGO1/omni/src/entity/mxentity.cpp index 1f507257..2edc65f6 100644 --- a/LEGO1/omni/src/entity/mxentity.cpp +++ b/LEGO1/omni/src/entity/mxentity.cpp @@ -1,22 +1,3 @@ #include "mxentity.h" DECOMP_SIZE_ASSERT(MxEntity, 0x10) - -// FUNCTION: LEGO1 0x10001070 -MxResult MxEntity::Create(MxS32 p_id, const MxAtomId& p_atom) -{ - this->m_mxEntityId = p_id; - this->m_atom = p_atom; - return SUCCESS; -} - -// FUNCTION: LEGO1 0x1000c110 -MxEntity::~MxEntity() -{ -} - -// FUNCTION: LEGO1 0x1001d190 -MxEntity::MxEntity() -{ - this->m_mxEntityId = -1; -} diff --git a/LEGO1/omni/src/event/mxeventpresenter.cpp b/LEGO1/omni/src/event/mxeventpresenter.cpp index 6a0a0cbd..03b0de14 100644 --- a/LEGO1/omni/src/event/mxeventpresenter.cpp +++ b/LEGO1/omni/src/event/mxeventpresenter.cpp @@ -33,7 +33,7 @@ MxResult MxEventPresenter::AddToManager() if (EventManager()) { ret = SUCCESS; - EventManager()->AddPresenter(*this); + EventManager()->RegisterPresenter(*this); } return ret; @@ -43,7 +43,7 @@ MxResult MxEventPresenter::AddToManager() void MxEventPresenter::Destroy() { if (EventManager()) - EventManager()->RemovePresenter(*this); + EventManager()->UnregisterPresenter(*this); m_criticalSection.Enter(); @@ -71,20 +71,17 @@ void MxEventPresenter::ReadyTickle() CopyData(chunk); m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } // FUNCTION: LEGO1 0x100c2eb0 void MxEventPresenter::StartingTickle() { - MxStreamChunk* chunk = NextChunk(); + MxStreamChunk* chunk = CurrentChunk(); - if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; - } + if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) + ProgressTickleState(e_streaming); } // FUNCTION: LEGO1 0x100c2ef0 @@ -93,8 +90,8 @@ MxResult MxEventPresenter::PutData() MxAutoLocker lock(&m_criticalSection); if (IsEnabled()) { - if (m_currentTickleState >= TickleState_Streaming && - (m_currentTickleState <= TickleState_Repeating || m_currentTickleState == TickleState_Done)) { + if (m_currentTickleState >= e_streaming && + (m_currentTickleState <= e_repeating || m_currentTickleState == e_done)) { if (m_currentChunk && m_currentChunk->GetLength()) { if (m_data[12] == 2) { const char* data = (const char*) m_currentChunk->GetData(); @@ -106,7 +103,7 @@ MxResult MxEventPresenter::PutData() variableTable->SetVariable(key, value); } - if (m_currentTickleState == TickleState_Streaming) + if (m_currentTickleState == e_streaming) m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; } diff --git a/LEGO1/omni/src/main/mxomni.cpp b/LEGO1/omni/src/main/mxomni.cpp index 377ba481..f9fa5733 100644 --- a/LEGO1/omni/src/main/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) { @@ -391,11 +378,23 @@ 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 @@ -418,7 +417,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); } } diff --git a/LEGO1/omni/src/notify/mxactionnotificationparam.cpp b/LEGO1/omni/src/notify/mxactionnotificationparam.cpp index 5573677f..c5f816e7 100644 --- a/LEGO1/omni/src/notify/mxactionnotificationparam.cpp +++ b/LEGO1/omni/src/notify/mxactionnotificationparam.cpp @@ -3,18 +3,6 @@ DECOMP_SIZE_ASSERT(MxActionNotificationParam, 0x14) DECOMP_SIZE_ASSERT(MxEndActionNotificationParam, 0x14) -// FUNCTION: LEGO1 0x100510c0 -MxNotificationParam* MxActionNotificationParam::Clone() -{ - return new MxActionNotificationParam(this->m_type, this->m_sender, this->m_action, this->m_realloc); -} - -// FUNCTION: LEGO1 0x10051270 -MxNotificationParam* MxEndActionNotificationParam::Clone() -{ - return new MxEndActionNotificationParam(c_notificationEndAction, this->m_sender, this->m_action, this->m_realloc); -} - // FUNCTION: LEGO1 0x100b0300 MxNotificationParam* MxStartActionNotificationParam::Clone() { diff --git a/LEGO1/omni/src/notify/mxnotificationparam.cpp b/LEGO1/omni/src/notify/mxnotificationparam.cpp index 0797c9f1..cb15a2df 100644 --- a/LEGO1/omni/src/notify/mxnotificationparam.cpp +++ b/LEGO1/omni/src/notify/mxnotificationparam.cpp @@ -3,9 +3,3 @@ #include "decomp.h" DECOMP_SIZE_ASSERT(MxNotificationParam, 0xc); - -// FUNCTION: LEGO1 0x10010390 -MxNotificationParam* MxNotificationParam::Clone() -{ - return new MxNotificationParam(m_type, m_sender); -} diff --git a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp index c0708acc..5833d18f 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamcontroller.cpp @@ -129,7 +129,7 @@ void MxDiskStreamController::FUN_100c7980() if (m_unk0x3c.size() && m_unk0x8c < m_provider->GetStreamBuffersNum()) { buffer = new MxDSBuffer(); - if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBufferType_Chunk) != SUCCESS) { + if (buffer->AllocateBuffer(m_provider->GetFileSize(), MxDSBuffer::e_chunk) != SUCCESS) { if (buffer) delete buffer; return; @@ -213,10 +213,10 @@ void MxDiskStreamController::FUN_100c7cb0(MxDSStreamingAction* p_action) void MxDiskStreamController::FUN_100c7ce0(MxDSBuffer* p_buffer) { switch (p_buffer->GetMode()) { - case MxDSBufferType_Chunk: + case MxDSBuffer::e_chunk: m_unk0x8c--; - case MxDSBufferType_Allocate: - case MxDSBufferType_Unknown: + case MxDSBuffer::e_allocate: + case MxDSBuffer::e_unknown: delete p_buffer; break; } @@ -301,6 +301,23 @@ MxResult MxDiskStreamController::VTable0x20(MxDSAction* p_action) return SUCCESS; } +// FUNCTION: LEGO1 0x100c8120 +void MxDiskStreamController::FUN_100c8120(MxDSAction* p_action) +{ + VTable0x30(p_action); + + if (m_provider) { + m_provider->VTable0x20(p_action); + } + + while (TRUE) { + MxDSAction* found = m_unk0x54.Find(p_action, TRUE); + if (!found) + break; + delete found; + } +} + // FUNCTION: LEGO1 0x100c8160 MxResult MxDiskStreamController::VTable0x24(MxDSAction* p_action) { diff --git a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp index 08046ad4..7b4b6ef5 100644 --- a/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxdiskstreamprovider.cpp @@ -174,7 +174,7 @@ MxResult MxDiskStreamProvider::FUN_100d1780(MxDSStreamingAction* p_action) if (!buffer) return FAILURE; - if (buffer->AllocateBuffer(GetFileSize(), MxDSBufferType_Allocate) != SUCCESS) { + if (buffer->AllocateBuffer(GetFileSize(), MxDSBuffer::e_allocate) != SUCCESS) { delete buffer; return FAILURE; } @@ -215,18 +215,20 @@ void MxDiskStreamProvider::PerformWork() } } + MxDSBuffer* buffer; + { MxAutoLocker lock(&m_criticalSection); if (!m_list.PopFrontStreamingAction(streamingAction)) - return; + goto done; } if (streamingAction->GetUnknowna0()->GetWriteOffset() < 0x20000) { g_unk0x10102878--; } - MxDSBuffer* buffer = streamingAction->GetUnknowna0(); + buffer = streamingAction->GetUnknowna0(); if (m_pFile->GetPosition() == streamingAction->GetBufferOffset() || m_pFile->Seek(streamingAction->GetBufferOffset(), 0) == 0) { @@ -251,6 +253,7 @@ void MxDiskStreamProvider::PerformWork() } } +done: if (streamingAction) { controller->FUN_100c8670(streamingAction); } @@ -279,7 +282,7 @@ MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) MxU32 size = p_action->GetUnknowna0()->GetWriteOffset() - p_action->GetUnknown94() + p_action->GetBufferOffset() + (p_action->GetUnknowna4() ? p_action->GetUnknowna4()->GetWriteOffset() : 0); - if (buffer->AllocateBuffer(size, MxDSBufferType_Allocate) != SUCCESS) { + if (buffer->AllocateBuffer(size, MxDSBuffer::e_allocate) != SUCCESS) { if (!buffer) return FAILURE; @@ -327,12 +330,12 @@ MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) if (!buffer3) return FAILURE; - if (buffer3->AllocateBuffer(size, MxDSBufferType_Allocate) == SUCCESS) { + if (buffer3->AllocateBuffer(size, MxDSBuffer::e_allocate) == SUCCESS) { memcpy(buffer3->GetBuffer(), p_action->GetUnknowna4()->GetBuffer(), size); - p_action->GetUnknowna4()->SetMode(MxDSBufferType_Allocate); + p_action->GetUnknowna4()->SetMode(MxDSBuffer::e_allocate); delete p_action->GetUnknowna4(); - buffer3->SetMode(MxDSBufferType_Unknown); + buffer3->SetMode(MxDSBuffer::e_unknown); p_action->SetUnknowna4(buffer3); MxDSBuffer* buffer4 = p_action->GetUnknowna0(); MxU32 unk0x14 = buffer4->GetUnknown14(); @@ -349,6 +352,8 @@ MxResult MxDiskStreamProvider::FUN_100d1b20(MxDSStreamingAction* p_action) 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 { diff --git a/LEGO1/omni/src/stream/mxdsbuffer.cpp b/LEGO1/omni/src/stream/mxdsbuffer.cpp index 54ed0ca2..380cc1e0 100644 --- a/LEGO1/omni/src/stream/mxdsbuffer.cpp +++ b/LEGO1/omni/src/stream/mxdsbuffer.cpp @@ -22,7 +22,7 @@ MxDSBuffer::MxDSBuffer() m_unk0x1c = 0; m_writeOffset = 0; m_bytesRemaining = 0; - m_mode = MxDSBufferType_Preallocated; + m_mode = e_preallocated; m_unk0x30 = 0; } @@ -31,12 +31,12 @@ MxDSBuffer::~MxDSBuffer() { if (m_pBuffer != NULL) { switch (m_mode) { - case MxDSBufferType_Allocate: - case MxDSBufferType_Unknown: + case e_allocate: + case e_unknown: delete[] m_pBuffer; break; - case MxDSBufferType_Chunk: { + case e_chunk: { MxU32 offset = m_writeOffset / 1024; MxStreamer* streamer = Streamer(); @@ -77,16 +77,16 @@ MxDSBuffer::~MxDSBuffer() } // FUNCTION: LEGO1 0x100c6640 -MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, MxDSBufferType p_mode) +MxResult MxDSBuffer::AllocateBuffer(MxU32 p_bufferSize, Type p_mode) { MxResult result = FAILURE; switch (p_mode) { - case MxDSBufferType_Allocate: + case e_allocate: m_pBuffer = new MxU8[p_bufferSize]; break; - case MxDSBufferType_Chunk: { + case e_chunk: { MxStreamer* streamer = Streamer(); switch (p_bufferSize / 1024) { @@ -150,7 +150,7 @@ MxResult MxDSBuffer::SetBufferPointer(MxU8* p_buffer, MxU32 p_size) m_pIntoBuffer2 = p_buffer; m_bytesRemaining = p_size; m_writeOffset = p_size; - m_mode = MxDSBufferType_Preallocated; + m_mode = e_preallocated; return SUCCESS; } @@ -291,24 +291,24 @@ MxResult MxDSBuffer::ParseChunk( { MxResult result = SUCCESS; - if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && m_unk0x30->GetUnknowna8() && p_header->GetTime() < 0) { + if (m_unk0x30->GetFlags() & MxDSAction::c_bit3 && m_unk0x30->GetUnknowna8() && p_header->GetTime() < 0) { delete p_header; return SUCCESS; } p_header->SetTime(p_header->GetTime() + m_unk0x30->GetUnknowna8()); - if (p_header->GetFlags() & MxDSChunk::Flag_Split) { + if (p_header->GetFlags() & MxDSChunk::c_split) { MxU32 length = p_header->GetLength() + MxDSChunk::GetHeaderSize() + 8; MxDSBuffer* buffer = new MxDSBuffer(); - if (buffer && buffer->AllocateBuffer(length, MxDSBufferType_Allocate) == SUCCESS && + if (buffer && buffer->AllocateBuffer(length, e_allocate) == SUCCESS && buffer->CalcBytesRemaining((MxU8*) p_data) == SUCCESS) { *p_streamingAction = new MxDSStreamingAction((MxDSStreamingAction&) *p_action); if (*p_streamingAction) { MxU16* flags = MxStreamChunk::IntoFlags(buffer->GetBuffer()); - *flags = p_header->GetFlags() & ~MxDSChunk::Flag_Split; + *flags = p_header->GetFlags() & ~MxDSChunk::c_split; delete p_header; (*p_streamingAction)->SetUnknowna0(buffer); @@ -323,9 +323,9 @@ MxResult MxDSBuffer::ParseChunk( return FAILURE; } else { - if (p_header->GetFlags() & MxDSChunk::Flag_End) { + if (p_header->GetFlags() & MxDSChunk::c_end) { if (m_unk0x30->HasId(p_header->GetObjectId())) { - if (m_unk0x30->GetFlags() & MxDSAction::Flag_Bit3 && + if (m_unk0x30->GetFlags() & MxDSAction::c_bit3 && (m_unk0x30->GetLoopCount() > 1 || m_unk0x30->GetDuration() == -1)) { if (p_action->GetObjectId() == p_header->GetObjectId()) { @@ -456,7 +456,7 @@ MxResult MxDSBuffer::CalcBytesRemaining(MxU8* p_data) { MxResult result = FAILURE; - if (m_mode == MxDSBufferType_Allocate && m_bytesRemaining != 0) { + if (m_mode == e_allocate && m_bytesRemaining != 0) { MxU32 bytesRead; MxU8* ptr; diff --git a/LEGO1/omni/src/stream/mxdschunk.cpp b/LEGO1/omni/src/stream/mxdschunk.cpp index 79b9fea1..61d794cc 100644 --- a/LEGO1/omni/src/stream/mxdschunk.cpp +++ b/LEGO1/omni/src/stream/mxdschunk.cpp @@ -15,7 +15,7 @@ MxDSChunk::MxDSChunk() // FUNCTION: LEGO1 0x100be170 MxDSChunk::~MxDSChunk() { - if (m_flags & Flag_Bit1) + if (m_flags & c_bit1) delete[] m_data; } diff --git a/LEGO1/omni/src/stream/mxdssubscriber.cpp b/LEGO1/omni/src/stream/mxdssubscriber.cpp index f93969e1..82ca1730 100644 --- a/LEGO1/omni/src/stream/mxdssubscriber.cpp +++ b/LEGO1/omni/src/stream/mxdssubscriber.cpp @@ -119,7 +119,7 @@ void MxDSSubscriber::DestroyChunk(MxStreamChunk* p_chunk) if (p_chunk) delete p_chunk; } - else if (p_chunk->GetFlags() & MxDSChunk::Flag_Bit1 && p_chunk) + else if (p_chunk->GetFlags() & MxDSChunk::c_bit1 && p_chunk) delete p_chunk; } } diff --git a/LEGO1/omni/src/stream/mxramstreamprovider.cpp b/LEGO1/omni/src/stream/mxramstreamprovider.cpp index 232e347b..ca091d12 100644 --- a/LEGO1/omni/src/stream/mxramstreamprovider.cpp +++ b/LEGO1/omni/src/stream/mxramstreamprovider.cpp @@ -47,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; } @@ -124,22 +124,22 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size) data += MxDSChunk::Size(*psize); if ((*MxDSChunk::IntoType(data2) == FOURCC('M', 'x', 'C', 'h')) && - (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::Flag_Split)) { + (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::c_split)) { if (*MxStreamChunk::IntoObjectId(data2) == *MxStreamChunk::IntoObjectId(data3) && - (*MxStreamChunk::IntoFlags(data3) & MxDSChunk::Flag_Split) && + (*MxStreamChunk::IntoFlags(data3) & MxDSChunk::c_split) && *MxStreamChunk::IntoTime(data2) == *MxStreamChunk::IntoTime(data3)) { MxDSBuffer::Append(data2, data3); continue; } else - *MxStreamChunk::IntoFlags(data2) &= ~MxDSChunk::Flag_Split; + *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::Flag_End)) + (*MxStreamChunk::IntoFlags(data2) & MxDSChunk::c_end)) break; } else @@ -151,6 +151,6 @@ MxU32 ReadData(MxU8* p_buffer, MxU32 p_size) } while (data < end); } - *MxStreamChunk::IntoFlags(data2) &= ~MxDSChunk::Flag_Split; + *MxStreamChunk::IntoFlags(data2) &= ~MxDSChunk::c_split; return MxDSChunk::End(data2) - p_buffer; } diff --git a/LEGO1/omni/src/stream/mxstreamchunk.cpp b/LEGO1/omni/src/stream/mxstreamchunk.cpp index 4dceabec..ba833186 100644 --- a/LEGO1/omni/src/stream/mxstreamchunk.cpp +++ b/LEGO1/omni/src/stream/mxstreamchunk.cpp @@ -54,7 +54,7 @@ MxResult MxStreamChunk::SendChunk(MxStreamListMxDSSubscriber& p_subscriberList, { for (MxStreamListMxDSSubscriber::iterator it = p_subscriberList.begin(); it != p_subscriberList.end(); it++) { if ((*it)->GetObjectId() == m_objectId && (*it)->GetUnknown48() == p_obj24val) { - if (m_flags & MxDSChunk::Flag_End && m_buffer) { + if (m_flags & MxDSChunk::c_end && m_buffer) { m_buffer->ReleaseRef(this); m_buffer = NULL; } diff --git a/LEGO1/omni/src/stream/mxstreamcontroller.cpp b/LEGO1/omni/src/stream/mxstreamcontroller.cpp index caacbb5f..204bdab8 100644 --- a/LEGO1/omni/src/stream/mxstreamcontroller.cpp +++ b/LEGO1/omni/src/stream/mxstreamcontroller.cpp @@ -82,7 +82,7 @@ MxResult MxStreamController::Open(const char* p_filename) MxAutoLocker lock(&m_criticalSection); MakeSourceName(sourceName, p_filename); - this->m_atom = MxAtomId(sourceName, LookupMode_LowerCase2); + this->m_atom = MxAtomId(sourceName, e_lowerCase2); return SUCCESS; } @@ -271,7 +271,7 @@ MxResult MxStreamController::FUN_100c1f00(MxDSAction* p_action) if (!chunk) return FAILURE; - chunk->SetFlags(MxDSChunk::Flag_Bit3); + chunk->SetFlags(MxDSChunk::c_bit3); chunk->SetObjectId(objectId); if (chunk->SendChunk(m_subscriberList, FALSE, p_action->GetUnknown24()) != SUCCESS) diff --git a/LEGO1/omni/src/stream/mxstreamer.cpp b/LEGO1/omni/src/stream/mxstreamer.cpp index 245a757f..d8d64fb5 100644 --- a/LEGO1/omni/src/stream/mxstreamer.cpp +++ b/LEGO1/omni/src/stream/mxstreamer.cpp @@ -50,7 +50,7 @@ MxStreamController* MxStreamer::Open(const char* p_name, MxU16 p_lookupType) if (!GetOpenStream(p_name)) { switch (p_lookupType) { - case e_DiskStream: + case e_diskStream: stream = new MxDiskStreamController(); break; case e_RAMStream: @@ -84,11 +84,11 @@ MxLong MxStreamer::Close(const char* p_name) else { #ifdef COMPAT_MODE { - MxStreamerNotification notification(MXSTREAMER_DELETE_NOTIFY, NULL, c); + MxStreamerNotification notification(c_notificationStreamer, NULL, c); NotificationManager()->Send(this, ¬ification); } #else - NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c)); + NotificationManager()->Send(this, &MxStreamerNotification(c_notificationStreamer, NULL, c)); #endif } @@ -121,6 +121,15 @@ MxStreamController* MxStreamer::GetOpenStream(const char* p_name) return NULL; } +// FUNCTION: LEGO1 0x100b98f0 +void MxStreamer::FUN_100b98f0(MxDSAction* p_action) +{ + MxStreamController* controller = GetOpenStream(p_action->GetAtomId().GetInternal()); + if (controller && controller->IsA("MxDiskStreamController")) { + ((MxDiskStreamController*) controller)->FUN_100c8120(p_action); + } +} + // FUNCTION: LEGO1 0x100b9930 MxResult MxStreamer::AddStreamControllerToOpenList(MxStreamController* p_stream) { @@ -184,7 +193,7 @@ MxBool MxStreamer::FUN_100b9b30(MxDSObject& p_dsObject) // FUNCTION: LEGO1 0x100b9b60 MxLong MxStreamer::Notify(MxParam& p_param) { - if (((MxNotificationParam&) p_param).GetNotification() == MXSTREAMER_DELETE_NOTIFY) { + if (((MxNotificationParam&) p_param).GetNotification() == c_notificationStreamer) { MxDSAction ds; ds.SetUnknown24(-2); @@ -196,11 +205,11 @@ MxLong MxStreamer::Notify(MxParam& p_param) else { #ifdef COMPAT_MODE { - MxStreamerNotification notification(MXSTREAMER_DELETE_NOTIFY, NULL, c); + MxStreamerNotification notification(c_notificationStreamer, NULL, c); NotificationManager()->Send(this, ¬ification); } #else - NotificationManager()->Send(this, &MxStreamerNotification(MXSTREAMER_DELETE_NOTIFY, NULL, c)); + NotificationManager()->Send(this, &MxStreamerNotification(c_notificationStreamer, NULL, c)); #endif } } diff --git a/LEGO1/omni/src/video/mxbitmap.cpp b/LEGO1/omni/src/video/mxbitmap.cpp index 4f2393cf..0d83bba2 100644 --- a/LEGO1/omni/src/video/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,12 +11,6 @@ DECOMP_SIZE_ASSERT(MxBITMAPINFO, 0x428); // (1998) GLOBAL: LEGO1 0x10102184 MxU16 g_bitmapSignature = TWOCC('B', 'M'); -// FUNCTION: LEGO1 0x1004e0d0 -int MxBitmap::VTable0x28(int) -{ - return -1; -} - // FUNCTION: LEGO1 0x100bc980 MxBitmap::MxBitmap() { @@ -109,7 +104,7 @@ MxResult MxBitmap::ImportBitmapInfo(MxBITMAPINFO* p_info) } if (this->m_data) { - delete this->m_data; + delete[] this->m_data; this->m_data = NULL; } } @@ -213,14 +208,88 @@ 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 diff --git a/LEGO1/omni/src/video/mxdisplaysurface.cpp b/LEGO1/omni/src/video/mxdisplaysurface.cpp index 4824c87b..a065b1b1 100644 --- a/LEGO1/omni/src/video/mxdisplaysurface.cpp +++ b/LEGO1/omni/src/video/mxdisplaysurface.cpp @@ -7,6 +7,7 @@ DECOMP_SIZE_ASSERT(MxDisplaySurface, 0xac); +// GLOBAL: LEGO1 0x1010215c MxU32 g_unk0x1010215c = 0; // FUNCTION: LEGO1 0x100ba500 @@ -33,7 +34,7 @@ void MxDisplaySurface::Init() } // FUNCTION: LEGO1 0x100ba640 -void MxDisplaySurface::FUN_100ba640() +void MxDisplaySurface::ClearScreen() { MxS32 backBuffers; DDSURFACEDESC desc; @@ -304,7 +305,7 @@ void MxDisplaySurface::VTable0x28( MxS32 p_height ) { - if (FUN_100b6e10( + if (GetRectIntersection( p_bitmap->GetBmiWidth(), p_bitmap->GetBmiHeightAbs(), m_videoParam.GetRect().GetWidth(), @@ -327,30 +328,7 @@ void MxDisplaySurface::VTable0x28( } if (hr == DD_OK) { - MxU8* data; - - switch (p_bitmap->GetBmiHeader()->biCompression) { - case BI_RGB: { - MxS32 rowsBeforeTop; - if (p_bitmap->GetBmiHeight() < 0) - rowsBeforeTop = p_top; - else - rowsBeforeTop = p_bitmap->GetBmiHeightAbs() - p_top - 1; - data = p_bitmap->GetBitmapData() + p_left + (p_bitmap->GetBmiStride() * rowsBeforeTop); - break; - } - case BI_RGB_TOPDOWN: - data = p_bitmap->GetBitmapData(); - break; - default: { - MxS32 rowsBeforeTop; - if (p_bitmap->GetBmiHeight() < 0) - rowsBeforeTop = 0; - else - rowsBeforeTop = p_bitmap->GetBmiHeightAbs() - 1; - data = p_bitmap->GetBitmapData() + (p_bitmap->GetBmiStride() * rowsBeforeTop); - } - } + MxU8* data = p_bitmap->GetStart(p_left, p_top); if (m_videoParam.Flags().GetF1bit3()) { p_bottom *= 2; @@ -563,10 +541,142 @@ void MxDisplaySurface::ReleaseDC(HDC p_hdc) this->m_ddSurface2->ReleaseDC(p_hdc); } -// STUB: LEGO1 0x100bbc60 -LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44(MxBitmap*, undefined4*, undefined4, undefined4) +// FUNCTION: LEGO1 0x100bbc60 +LPDIRECTDRAWSURFACE MxDisplaySurface::VTable0x44( + MxBitmap* p_bitmap, + undefined4* p_ret, + undefined4 p_doNotWriteToSurface, + undefined4 p_transparent +) { - return NULL; + 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) != S_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) != S_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) != S_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; } // FUNCTION: LEGO1 0x100bc070 diff --git a/LEGO1/omni/src/video/mxflcpresenter.cpp b/LEGO1/omni/src/video/mxflcpresenter.cpp index 76cc7efe..2fc22265 100644 --- a/LEGO1/omni/src/video/mxflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxflcpresenter.cpp @@ -2,6 +2,7 @@ #include "decomp.h" #include "mxbitmap.h" +#include "mxdsmediaaction.h" #include "mxomni.h" #include "mxpalette.h" #include "mxvideomanager.h" @@ -11,24 +12,24 @@ DECOMP_SIZE_ASSERT(MxFlcPresenter, 0x68); // FUNCTION: LEGO1 0x100b3310 MxFlcPresenter::MxFlcPresenter() { - this->m_flicHeader = NULL; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; + this->m_flcHeader = NULL; + this->m_flags &= ~c_bit2; + this->m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b3420 MxFlcPresenter::~MxFlcPresenter() { - if (this->m_flicHeader) { - delete this->m_flicHeader; + if (this->m_flcHeader) { + delete this->m_flcHeader; } } // 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()); + m_flcHeader = (FLIC_HEADER*) new MxU8[p_chunk->GetLength()]; + memcpy(m_flcHeader, p_chunk->GetData(), p_chunk->GetLength()); } // FUNCTION: LEGO1 0x100b34d0 @@ -38,7 +39,37 @@ void MxFlcPresenter::CreateBitmap() delete m_bitmap; m_bitmap = new MxBitmap; - m_bitmap->SetSize(m_flicHeader->width, m_flicHeader->height, NULL, FALSE); + 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 diff --git a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp index fdd991a9..59540cb3 100644 --- a/LEGO1/omni/src/video/mxloopingflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingflcpresenter.cpp @@ -19,9 +19,9 @@ MxLoopingFlcPresenter::~MxLoopingFlcPresenter() // FUNCTION: LEGO1 0x100b4410 void MxLoopingFlcPresenter::Init() { - this->m_unk0x68 = 0; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; + this->m_elapsedDuration = 0; + this->m_flags &= ~c_bit2; + this->m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b4430 @@ -40,15 +40,88 @@ void MxLoopingFlcPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::Flag_End) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; - } + if (chunk->GetFlags() & MxDSChunk::c_end) + ProgressTickleState(e_repeating); else { LoadFrame(chunk); LoopChunk(chunk); - m_unk0x68 += m_flicHeader->speed; + 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/omni/src/video/mxloopingsmkpresenter.cpp b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp index efa758cd..51ed74c8 100644 --- a/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxloopingsmkpresenter.cpp @@ -21,8 +21,8 @@ MxLoopingSmkPresenter::~MxLoopingSmkPresenter() void MxLoopingSmkPresenter::Init() { this->m_elapsedDuration = 0; - this->m_flags &= ~Flag_Bit2; - this->m_flags &= ~Flag_Bit3; + this->m_flags &= ~c_bit2; + this->m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b49d0 @@ -51,10 +51,8 @@ void MxLoopingSmkPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::Flag_End) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; - } + if (chunk->GetFlags() & MxDSChunk::c_end) + ProgressTickleState(e_repeating); else { LoadFrame(chunk); LoopChunk(chunk); @@ -67,10 +65,8 @@ void MxLoopingSmkPresenter::NextFrame() // FUNCTION: LEGO1 0x100b4a90 void MxLoopingSmkPresenter::VTable0x8c() { - if (m_action->GetDuration() < m_elapsedDuration) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (m_action->GetDuration() < m_elapsedDuration) + ProgressTickleState(e_unk5); else { MxStreamChunk* chunk; m_loopingChunkCursor->Current(chunk); @@ -112,7 +108,7 @@ void MxLoopingSmkPresenter::RepeatingTickle() m_loopingChunkCursor->Next(chunk); - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) break; } } diff --git a/LEGO1/omni/src/video/mxsmkpresenter.cpp b/LEGO1/omni/src/video/mxsmkpresenter.cpp index 17985fdd..b8001623 100644 --- a/LEGO1/omni/src/video/mxsmkpresenter.cpp +++ b/LEGO1/omni/src/video/mxsmkpresenter.cpp @@ -23,8 +23,8 @@ void MxSmkPresenter::Init() { m_currentFrame = 0; memset(&m_mxSmack, 0, sizeof(m_mxSmack)); - m_flags &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags &= ~c_bit2; + m_flags &= ~c_bit3; } // FUNCTION: LEGO1 0x100b3900 diff --git a/LEGO1/omni/src/video/mxstillpresenter.cpp b/LEGO1/omni/src/video/mxstillpresenter.cpp index 20e6b3a2..4b81d6f1 100644 --- a/LEGO1/omni/src/video/mxstillpresenter.cpp +++ b/LEGO1/omni/src/video/mxstillpresenter.cpp @@ -10,15 +10,10 @@ DECOMP_SIZE_ASSERT(MxStillPresenter, 0x6c); -// GLOBAL: LEGO1 0x10101eb0 +// GLOBAL: LEGO1 0x101020e0 +// STRING: LEGO1 0x10101eb0 const char* g_strBmpIsmap = "BMP_ISMAP"; -// FUNCTION: LEGO1 0x100435b0 -void MxStillPresenter::Destroy() -{ - Destroy(FALSE); -} - // FUNCTION: LEGO1 0x100b9c70 void MxStillPresenter::Destroy(MxBool p_fromDestructor) { @@ -80,13 +75,13 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) MxRect32 rect(x, y, width + x, height + y); MVideoManager()->InvalidateRect(rect); - if (m_flags & Flag_Bit2) { + if (m_flags & c_bit2) { undefined4 und = 0; m_unk0x58 = MxOmni::GetInstance()->GetVideoManager()->GetDisplaySurface()->VTable0x44( m_bitmap, &und, - (m_flags & Flag_Bit4) / 8, - m_action->GetFlags() & MxDSAction::Flag_Bit4 + (m_flags & c_bit4) / 8, + m_action->GetFlags() & MxDSAction::c_bit4 ); delete m_alpha; @@ -96,9 +91,9 @@ void MxStillPresenter::LoadFrame(MxStreamChunk* p_chunk) m_bitmap = NULL; if (m_unk0x58 && und) - m_flags |= Flag_Bit3; + m_flags |= c_bit3; else - m_flags &= ~Flag_Bit3; + m_flags &= ~c_bit3; } } @@ -115,7 +110,7 @@ void MxStillPresenter::StartingTickle() { MxVideoPresenter::StartingTickle(); - if (m_currentTickleState == TickleState_Streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) + if (m_currentTickleState == e_streaming && ((MxDSMediaAction*) m_action)->GetPaletteManagement()) RealizePalette(); } @@ -127,8 +122,7 @@ void MxStillPresenter::StreamingTickle() if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { m_chunkTime = chunk->GetTime(); NextFrame(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); if (m_action->GetDuration() == -1 && m_compositePresenter) m_compositePresenter->VTable0x60(this); @@ -139,10 +133,8 @@ void MxStillPresenter::StreamingTickle() void MxStillPresenter::RepeatingTickle() { if (m_action->GetDuration() != -1) { - if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_unk5; - } + if (m_action->GetElapsedTime() >= m_action->GetStartTime() + m_action->GetDuration()) + ProgressTickleState(e_unk5); } } @@ -163,17 +155,17 @@ 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())); @@ -184,7 +176,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()); } } @@ -193,8 +185,8 @@ void MxStillPresenter::ParseExtra() { MxPresenter::ParseExtra(); - if (m_action->GetFlags() & MxDSAction::Flag_Bit5) - m_flags |= Flag_Bit4; + if (m_action->GetFlags() & MxDSAction::c_bit5) + m_flags |= c_bit4; MxU32 len = m_action->GetExtraLength(); @@ -215,9 +207,9 @@ void MxStillPresenter::ParseExtra() } if (KeyValueStringParse(output, g_strBmpIsmap, buf)) { - m_flags |= Flag_Bit5; - m_flags &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags |= c_bit5; + m_flags &= ~c_bit2; + m_flags &= ~c_bit3; } } diff --git a/LEGO1/omni/src/video/mxvideomanager.cpp b/LEGO1/omni/src/video/mxvideomanager.cpp index f58ff13f..9a2a6cee 100644 --- a/LEGO1/omni/src/video/mxvideomanager.cpp +++ b/LEGO1/omni/src/video/mxvideomanager.cpp @@ -13,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) { } diff --git a/LEGO1/omni/src/video/mxvideopresenter.cpp b/LEGO1/omni/src/video/mxvideopresenter.cpp index 23c12cfb..ebc08487 100644 --- a/LEGO1/omni/src/video/mxvideopresenter.cpp +++ b/LEGO1/omni/src/video/mxvideopresenter.cpp @@ -8,66 +8,6 @@ DECOMP_SIZE_ASSERT(MxVideoPresenter, 0x64); DECOMP_SIZE_ASSERT(MxVideoPresenter::AlphaMask, 0xc); -// FUNCTION: LEGO1 0x1000c700 -void MxVideoPresenter::LoadHeader(MxStreamChunk* p_chunk) -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c710 -void MxVideoPresenter::CreateBitmap() -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c720 -void MxVideoPresenter::LoadFrame(MxStreamChunk* p_chunk) -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c730 -void MxVideoPresenter::RealizePalette() -{ - // Empty -} - -// FUNCTION: LEGO1 0x1000c740 -MxVideoPresenter::~MxVideoPresenter() -{ - Destroy(TRUE); -} - -// FUNCTION: LEGO1 0x1000c7a0 -void MxVideoPresenter::Destroy() -{ - Destroy(FALSE); -} - -// FUNCTION: LEGO1 0x1000c7b0 -LPDIRECTDRAWSURFACE MxVideoPresenter::VTable0x78() -{ - return m_unk0x58; -} - -// FUNCTION: LEGO1 0x1000c7c0 -MxBool MxVideoPresenter::VTable0x7c() -{ - return (m_bitmap != NULL) || (m_alpha != NULL); -} - -// FUNCTION: LEGO1 0x1000c7e0 -MxS32 MxVideoPresenter::GetWidth() -{ - return m_alpha ? m_alpha->m_width : m_bitmap->GetBmiWidth(); -} - -// FUNCTION: LEGO1 0x1000c800 -MxS32 MxVideoPresenter::GetHeight() -{ - return m_alpha ? m_alpha->m_height : m_bitmap->GetBmiHeightAbs(); -} - // FUNCTION: LEGO1 0x100b24f0 MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) { @@ -80,7 +20,6 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) m_bitmask = new MxU8[size]; memset(m_bitmask, 0, size); - MxU32 biCompression = p_bitmap.GetBmiHeader()->biCompression; MxU32 rowsBeforeTop; MxU8* bitmapSrcPtr; @@ -92,36 +31,25 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) // Reminder: Negative biHeight means this is a top-down DIB. // Otherwise it is bottom-up. - if (biCompression == BI_RGB) { - // DECOMP: I think this must be an OR. If not, the check for - // biCompression == 16 gets optimized away. - if (biCompression == BI_RGB_TOPDOWN || p_bitmap.GetBmiHeight() < 0) { + switch (p_bitmap.GetBmiHeader()->biCompression) { + case BI_RGB: { + if (p_bitmap.GetBmiHeight() < 0) rowsBeforeTop = 0; - } - else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs(); - rowsBeforeTop--; - } - - goto seek_to_last_row; + else + rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; + bitmapSrcPtr = p_bitmap.GetBitmapData() + (p_bitmap.GetBmiStride() * rowsBeforeTop); + break; } - else if (biCompression == BI_RGB_TOPDOWN) { - // DECOMP: This is the only condition where we skip the - // calculation below. + case BI_RGB_TOPDOWN: bitmapSrcPtr = p_bitmap.GetBitmapData(); - } - else { - if (p_bitmap.GetBmiHeight() < 0) { + break; + default: { + if (p_bitmap.GetBmiHeight() < 0) rowsBeforeTop = 0; - } - else { - rowsBeforeTop = p_bitmap.GetBmiHeightAbs(); - rowsBeforeTop--; - } - - // TODO: would prefer not to use goto if we can figure this structure out - seek_to_last_row: - bitmapSrcPtr = p_bitmap.GetBmiStride() * rowsBeforeTop + p_bitmap.GetBitmapData(); + else + rowsBeforeTop = p_bitmap.GetBmiHeightAbs() - 1; + bitmapSrcPtr = p_bitmap.GetBitmapData() + (p_bitmap.GetBmiStride() * rowsBeforeTop); + } } // How many bytes are there for each row of the bitmap? @@ -129,15 +57,15 @@ MxVideoPresenter::AlphaMask::AlphaMask(const MxBitmap& p_bitmap) // If this is a bottom-up DIB, we will walk it in reverse. // TODO: Same rounding trick as in MxBitmap MxS32 rowSeek = ((m_width + 3) & -4); - if (p_bitmap.GetBmiHeight() < 0) + if (p_bitmap.GetBmiHeader()->biCompression != BI_RGB_TOPDOWN && p_bitmap.GetBmiHeight() > 0) rowSeek = -rowSeek; // The actual offset into the m_bitmask array. The two for-loops // are just for counting the pixels. MxS32 offset = 0; - MxU8* tPtr = bitmapSrcPtr; for (MxS32 j = 0; j < m_height; j++) { + MxU8* tPtr = bitmapSrcPtr; for (MxS32 i = 0; i < m_width; i++) { if (*tPtr) { // TODO: Second CDQ instruction for abs() should not be there. @@ -189,29 +117,29 @@ void MxVideoPresenter::Init() m_unk0x5c = 1; m_unk0x58 = NULL; m_unk0x60 = -1; - m_flags &= ~Flag_Bit1; + m_flags &= ~c_bit1; if (MVideoManager() != NULL) { MVideoManager(); - m_flags |= Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags |= c_bit2; + m_flags &= ~c_bit3; } - m_flags &= ~Flag_Bit4; - m_flags &= ~Flag_Bit5; + m_flags &= ~c_bit4; + m_flags &= ~c_bit5; } // FUNCTION: LEGO1 0x100b27b0 void MxVideoPresenter::Destroy(MxBool p_fromDestructor) { if (MVideoManager() != NULL) - MVideoManager()->RemovePresenter(*this); + MVideoManager()->UnregisterPresenter(*this); if (m_unk0x58) { m_unk0x58->Release(); m_unk0x58 = NULL; - m_flags &= ~Flag_Bit2; - m_flags &= ~Flag_Bit3; + m_flags &= ~c_bit2; + m_flags &= ~c_bit3; } if (MVideoManager() && (m_alpha || m_bitmap)) { @@ -223,7 +151,7 @@ void MxVideoPresenter::Destroy(MxBool p_fromDestructor) 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; @@ -240,10 +168,9 @@ void MxVideoPresenter::NextFrame() { MxStreamChunk* chunk = NextChunk(); - if (chunk->GetFlags() & MxDSChunk::Flag_End) { + if (chunk->GetFlags() & MxDSChunk::c_end) { m_subscriber->DestroyChunk(chunk); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Repeating; + ProgressTickleState(e_repeating); } else { LoadFrame(chunk); @@ -255,7 +182,7 @@ void MxVideoPresenter::NextFrame() MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) { MxDSAction* action = GetAction(); - if ((action == NULL) || (((action->GetFlags() & MxDSAction::Flag_Bit11) == 0) && !IsEnabled()) || + if ((action == NULL) || (((action->GetFlags() & MxDSAction::c_bit11) == 0) && !IsEnabled()) || (!m_bitmap && !m_alpha)) return FALSE; @@ -307,7 +234,7 @@ MxBool MxVideoPresenter::IsHit(MxS32 p_x, MxS32 p_y) if (m_flags & 0x10) return (MxBool) *pixel; - if ((GetAction()->GetFlags() & MxDSAction::Flag_Bit4) && *pixel == 0) + if ((GetAction()->GetFlags() & MxDSAction::c_bit4) && *pixel == 0) return FALSE; return TRUE; @@ -357,7 +284,7 @@ void MxVideoPresenter::PutFrame() LPDIRECTDRAWSURFACE ddSurface = displaySurface->GetDirectDrawSurface2(); MxRect32 rectSrc, rectDest; - if (m_action->GetFlags() & MxDSAction::Flag_Bit5) { + if (m_action->GetFlags() & MxDSAction::c_bit5) { if (m_unk0x58) { // TODO: Match rectSrc.SetPoint(MxPoint32(0, 0)); @@ -413,7 +340,7 @@ void MxVideoPresenter::PutFrame() rectDest.SetBottom(rectDest.GetTop() + regionRect->GetHeight()); } - if (m_action->GetFlags() & MxDSAction::Flag_Bit4) { + if (m_action->GetFlags() & MxDSAction::c_bit4) { if (m_unk0x58) { if (PrepareRects(rectDest, rectSrc) >= 0) ddSurface->Blt((LPRECT) &rectDest, m_unk0x58, (LPRECT) &rectSrc, DDBLT_KEYSRC, NULL); @@ -460,8 +387,7 @@ void MxVideoPresenter::ReadyTickle() LoadHeader(chunk); m_subscriber->DestroyChunk(chunk); ParseExtra(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Starting; + ProgressTickleState(e_starting); } } @@ -472,15 +398,14 @@ void MxVideoPresenter::StartingTickle() if (chunk && m_action->GetElapsedTime() >= chunk->GetTime()) { CreateBitmap(); - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Streaming; + ProgressTickleState(e_streaming); } } // FUNCTION: LEGO1 0x100b2fe0 void MxVideoPresenter::StreamingTickle() { - if (m_action->GetFlags() & MxDSAction::Flag_Bit10) { + if (m_action->GetFlags() & MxDSAction::c_bit10) { if (!m_currentChunk) MxMediaPresenter::StreamingTickle(); @@ -504,13 +429,13 @@ void MxVideoPresenter::StreamingTickle() LoadFrame(m_currentChunk); m_subscriber->DestroyChunk(m_currentChunk); m_currentChunk = NULL; - m_flags |= Flag_Bit1; + m_flags |= c_bit1; - if (m_currentTickleState != TickleState_Streaming) + if (m_currentTickleState != e_streaming) break; } - if (m_flags & Flag_Bit1) + if (m_flags & c_bit1) m_unk0x5c = 5; } } @@ -519,7 +444,7 @@ void MxVideoPresenter::StreamingTickle() void MxVideoPresenter::RepeatingTickle() { if (IsEnabled()) { - if (m_action->GetFlags() & MxDSAction::Flag_Bit10) { + if (m_action->GetFlags() & MxDSAction::c_bit10) { if (!m_currentChunk) MxMediaPresenter::RepeatingTickle(); @@ -542,13 +467,13 @@ void MxVideoPresenter::RepeatingTickle() LoadFrame(m_currentChunk); m_currentChunk = NULL; - m_flags |= Flag_Bit1; + m_flags |= c_bit1; - if (m_currentTickleState != TickleState_Repeating) + if (m_currentTickleState != e_repeating) break; } - if (m_flags & Flag_Bit1) + if (m_flags & c_bit1) m_unk0x5c = 5; } } @@ -564,15 +489,11 @@ void MxVideoPresenter::Unk5Tickle() if (m_unk0x60 == -1) m_unk0x60 = m_action->GetElapsedTime(); - if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; - } - } - else { - m_previousTickleStates |= 1 << (unsigned char) m_currentTickleState; - m_currentTickleState = TickleState_Done; + if (m_action->GetElapsedTime() >= m_unk0x60 + ((MxDSMediaAction*) m_action)->GetSustainTime()) + ProgressTickleState(e_done); } + else + ProgressTickleState(e_done); } } @@ -583,7 +504,7 @@ MxResult MxVideoPresenter::AddToManager() if (MVideoManager()) { result = SUCCESS; - MVideoManager()->AddPresenter(*this); + MVideoManager()->RegisterPresenter(*this); } return result; @@ -614,7 +535,7 @@ MxResult MxVideoPresenter::PutData() { MxAutoLocker lock(&m_criticalSection); - if (IsEnabled() && m_currentTickleState >= TickleState_Streaming && m_currentTickleState <= TickleState_unk5) + if (IsEnabled() && m_currentTickleState >= e_streaming && m_currentTickleState <= e_unk5) PutFrame(); return SUCCESS; diff --git a/LEGO1/realtime/matrix.cpp b/LEGO1/realtime/matrix.cpp index 818650eb..806e6659 100644 --- a/LEGO1/realtime/matrix.cpp +++ b/LEGO1/realtime/matrix.cpp @@ -1,180 +1,5 @@ - #include "matrix.h" #include "decomp.h" -#include "math.h" -#include - -DECOMP_SIZE_ASSERT(Matrix4, 0x40); -DECOMP_SIZE_ASSERT(Matrix4Impl, 0x8); -DECOMP_SIZE_ASSERT(Matrix4Data, 0x48); - -// FUNCTION: LEGO1 0x10002320 -void Matrix4Impl::EqualsMatrixData(const Matrix4& p_matrix) -{ - *m_data = p_matrix; -} - -// FUNCTION: LEGO1 0x10002340 -void Matrix4Impl::EqualsMatrixImpl(const Matrix4Impl* p_other) -{ - *m_data = *p_other->m_data; -} - -// FUNCTION: LEGO1 0x10002360 -void Matrix4Impl::AnotherSetData(Matrix4& p_data) -{ - m_data = &p_data; -} - -// FUNCTION: LEGO1 0x10002380 -const Matrix4* Matrix4Impl::GetData() const -{ - return m_data; -} - -// FUNCTION: LEGO1 0x10002390 -Matrix4* Matrix4Impl::GetData() -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100023a0 -const float* Matrix4Impl::Element(int p_row, int p_col) const -{ - return &(*m_data)[p_row][p_col]; -} - -// FUNCTION: LEGO1 0x100023c0 -float* Matrix4Impl::Element(int p_row, int p_col) -{ - return &(*m_data)[p_row][p_col]; -} - -// FUNCTION: LEGO1 0x100023e0 -void Matrix4Impl::Clear() -{ - memset(m_data, 0, 16 * sizeof(float)); -} - -// FUNCTION: LEGO1 0x100023f0 -void Matrix4Impl::SetIdentity() -{ - Clear(); - (*m_data)[0][0] = 1.0f; - (*m_data)[1][1] = 1.0f; - (*m_data)[2][2] = 1.0f; - (*m_data)[3][3] = 1.0f; -} - -// FUNCTION: LEGO1 0x10002430 -Matrix4Impl* Matrix4Impl::operator+=(const Matrix4& p_matrix) -{ - for (int i = 0; i < 16; ++i) - ((float*) m_data)[i] += ((float*) &p_matrix)[i]; - return this; -} - -// Matches but instructions are significantly out of order. Probably not wrong -// code given that the very similar SetTranslation does match. -// FUNCTION: LEGO1 0x10002460 -void Matrix4Impl::TranslateBy(const float* p_x, const float* p_y, const float* p_z) -{ - ((float*) m_data)[12] += *p_x; - ((float*) m_data)[13] += *p_y; - ((float*) m_data)[14] += *p_z; -} - -// FUNCTION: LEGO1 0x100024a0 -void Matrix4Impl::SetTranslation(const float* p_x, const float* p_y, const float* p_z) -{ - (*m_data)[3][0] = *p_x; - (*m_data)[3][1] = *p_y; - (*m_data)[3][2] = *p_z; -} - -// FUNCTION: LEGO1 0x100024d0 -void Matrix4Impl::EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b) -{ - float* cur = (float*) m_data; - for (int row = 0; row < 4; ++row) { - for (int col = 0; col < 4; ++col) { - *cur = 0.0f; - for (int k = 0; k < 4; ++k) { - *cur += p_a[row][k] * p_b[k][col]; - } - cur++; - } - } -} - -// FUNCTION: LEGO1 0x10002530 -void Matrix4Impl::EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b) -{ - EqualsDataProduct(*p_a->m_data, *p_b->m_data); -} - -// Not close, Ghidra struggles understinging this method so it will have to -// be manually worked out. Included since I at least figured out what it was -// doing with rotateIndex and what overall operation it's trying to do. -// STUB: LEGO1 0x10002550 -void Matrix4Impl::ToQuaternion(Vector4Impl* p_outQuat) -{ - /* - float trace = m_data[0] + m_data[5] + m_data[10]; - if (trace > 0) { - trace = sqrt(trace + 1.0); - p_outQuat->GetData()[3] = trace * 0.5f; - p_outQuat->GetData()[0] = (m_data[9] - m_data[6]) * trace; - p_outQuat->GetData()[1] = (m_data[2] - m_data[8]) * trace; - p_outQuat->GetData()[2] = (m_data[4] - m_data[1]) * trace; - return; - } - - // ~GLOBAL: LEGO1 0x100d4090 - static int rotateIndex[] = {1, 2, 0}; - - // Largest element along the trace - int largest = m_data[0] < m_data[5]; - if (*Element(largest, largest) < m_data[10]) - largest = 2; - - int next = rotateIndex[largest]; - int nextNext = rotateIndex[next]; - float valueA = *Element(nextNext, nextNext); - float valueB = *Element(next, next); - float valueC = *Element(largest, largest); - - // Above is somewhat decomped, below is pure speculation since the automatic - // decomp becomes very garbled. - float traceValue = sqrt(valueA - valueB - valueC + 1.0); - - p_outQuat->GetData()[largest] = traceValue * 0.5f; - traceValue = 0.5f / traceValue; - - p_outQuat->GetData()[3] = (m_data[next + 4 * nextNext] - m_data[nextNext + 4 * next]) * traceValue; - p_outQuat->GetData()[next] = (m_data[next + 4 * largest] + m_data[largest + 4 * next]) * traceValue; - p_outQuat->GetData()[nextNext] = (m_data[nextNext + 4 * largest] + m_data[largest + 4 * nextNext]) * traceValue; - */ -} - -// No idea what this function is doing and it will be hard to tell until -// we have a confirmed usage site. -// STUB: LEGO1 0x10002710 -int Matrix4Impl::FromQuaternion(const Vector4Impl& p_vec) -{ - return -1; -} - -// FUNCTION: LEGO1 0x10002850 -void Matrix4Impl::operator=(const Matrix4Impl& p_other) -{ - EqualsMatrixImpl(&p_other); -} - -// FUNCTION: LEGO1 0x10002860 -void Matrix4Data::operator=(const Matrix4Data& p_other) -{ - EqualsMatrixImpl(&p_other); -} +DECOMP_SIZE_ASSERT(Matrix4, 0x8); diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index c087d331..9a301a01 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -3,90 +3,166 @@ #include "vector.h" -/* - * A simple array of four Vector4s that can be indexed into. - */ -class Matrix4 { -public: - float rows[4][4]; // storage is public for easy access +#include - inline Matrix4() {} - /* - Matrix4(const Vector4& x_axis, const Vector4& y_axis, const Vector4& z_axis, const Vector4& position) - { - rows[0] = x_axis; - rows[1] = y_axis; - rows[2] = z_axis; - rows[3] = position; - } - Matrix4(const float m[4][4]) - { - rows[0] = m[0]; - rows[1] = m[1]; - rows[2] = m[2]; - rows[3] = m[3]; - } - */ - const float* operator[](long i) const { return rows[i]; } - float* operator[](long i) { return rows[i]; } +struct UnknownMatrixType { + float m_data[4][4]; }; // VTABLE: LEGO1 0x100d4350 // SIZE 0x8 -class Matrix4Impl { +class Matrix4 { public: - inline Matrix4Impl(Matrix4& p_data) { SetData(p_data); } + inline Matrix4(float (*p_data)[4]) { SetData(p_data); } + + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. + + // FUNCTION: LEGO1 0x10002320 + virtual void Equals(float (*p_data)[4]) { memcpy(m_data, p_data, sizeof(float) * 4 * 4); } // vtable+0x04 + + // FUNCTION: LEGO1 0x10002340 + virtual void Equals(const Matrix4& p_matrix) + { + memcpy(m_data, p_matrix.m_data, sizeof(float) * 4 * 4); + }; // vtable+0x00 + + // FUNCTION: LEGO1 0x10002360 + virtual void SetData(float (*p_data)[4]) { m_data = p_data; } // vtable+0x0c - // vtable + 0x00 - virtual void EqualsMatrixImpl(const Matrix4Impl* p_other); - virtual void EqualsMatrixData(const Matrix4& p_matrix); // FUNCTION: LEGO1 0x10002370 - virtual void SetData(Matrix4& p_data) { m_data = &p_data; } - virtual void AnotherSetData(Matrix4& p_data); + virtual void SetData(UnknownMatrixType& p_matrix) { m_data = p_matrix.m_data; }; // vtable+0x08 - // vtable + 0x10 - virtual Matrix4* GetData(); - virtual const Matrix4* GetData() const; - virtual float* Element(int p_row, int p_col); - virtual const float* Element(int p_row, int p_col) const; + // FUNCTION: LEGO1 0x10002380 + virtual float (*GetData())[4] { return m_data; }; // vtable+0x14 - // vtable + 0x20 - virtual void Clear(); - virtual void SetIdentity(); - virtual void operator=(const Matrix4Impl& p_other); - virtual Matrix4Impl* operator+=(const Matrix4& p_matrix); + // FUNCTION: LEGO1 0x10002390 + virtual float (*GetData() const)[4] { return m_data; }; // vtable+0x10 - // vtable + 0x30 - virtual void TranslateBy(const float* p_x, const float* p_y, const float* p_z); - virtual void SetTranslation(const float* p_x, const float* p_y, const float* p_z); - virtual void EqualsMxProduct(const Matrix4Impl* p_a, const Matrix4Impl* p_b); - virtual void EqualsDataProduct(const Matrix4& p_a, const Matrix4& p_b); + // FUNCTION: LEGO1 0x100023a0 + virtual float* Element(int p_row, int p_col) { return &m_data[p_row][p_col]; } // vtable+0x1c - // vtable + 0x40 - virtual void ToQuaternion(Vector4Impl* p_resultQuat); - virtual int FromQuaternion(const Vector4Impl& p_vec); + // FUNCTION: LEGO1 0x100023c0 + virtual const float* Element(int p_row, int p_col) const { return &m_data[p_row][p_col]; }; // vtable+0x18 - inline float& operator[](size_t idx) { return ((float*) m_data)[idx]; } + // FUNCTION: LEGO1 0x100023e0 + virtual void Clear() { memset(m_data, 0, 16 * sizeof(float)); }; // vtable+0x20 + + // FUNCTION: LEGO1 0x100023f0 + virtual void SetIdentity() + { + Clear(); + m_data[0][0] = 1.0f; + m_data[1][1] = 1.0f; + m_data[2][2] = 1.0f; + m_data[3][3] = 1.0f; + } // vtable+0x24 + + // FUNCTION: LEGO1 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..4f48c333 100644 --- a/LEGO1/realtime/orientableroi.cpp +++ b/LEGO1/realtime/orientableroi.cpp @@ -2,8 +2,24 @@ #include "decomp.h" +#include + DECOMP_SIZE_ASSERT(OrientableROI, 0xdc) +// FUNCTION: LEGO1 0x100a4420 +OrientableROI::OrientableROI() +{ + FILLVEC3(m_world_bounding_box.Min(), 888888.8); + FILLVEC3(m_world_bounding_box.Max(), -888888.8); + ZEROVEC3(m_world_bounding_sphere.Center()); + m_world_bounding_sphere.Radius() = 0.0; + ZEROVEC3(m_world_velocity); + IDENTMAT4(m_local2world); + + m_unk0xd4 = 0; + m_unk0xd8 |= c_bit1 | c_bit2; +} + // FUNCTION: LEGO1 0x100a5910 void OrientableROI::VTable0x1c() { @@ -12,27 +28,27 @@ void OrientableROI::VTable0x1c() } // FUNCTION: LEGO1 0x100a5930 -void OrientableROI::SetLocalTransform(const Matrix4Impl& p_transform) +void OrientableROI::SetLocalTransform(const Matrix4& p_transform) { - reinterpret_cast(m_local2world) = p_transform; + reinterpret_cast(m_local2world) = p_transform; UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); } // FUNCTION: LEGO1 0x100a5960 -void OrientableROI::VTable0x24(const Matrix4Data& p_transform) +void OrientableROI::VTable0x24(const MxMatrix& p_transform) { - Matrix4Data l_matrix(m_local2world); - m_local2world.EqualsMxProduct(&p_transform, &l_matrix); + MxMatrix l_matrix(m_local2world); + m_local2world.Product(p_transform, l_matrix); UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); } // FUNCTION: LEGO1 0x100a59b0 -void OrientableROI::UpdateWorldData(const Matrix4Data& p_transform) +void OrientableROI::UpdateWorldData(const MxMatrix& p_transform) { - Matrix4Data l_matrix(m_local2world); - m_local2world.EqualsMxProduct(&l_matrix, &p_transform); + MxMatrix l_matrix(m_local2world); + m_local2world.Product(l_matrix, p_transform); UpdateWorldBoundingVolumes(); UpdateWorldVelocity(); @@ -50,9 +66,9 @@ void OrientableROI::UpdateWorldVelocity() } // FUNCTION: LEGO1 0x100a5d80 -const Vector3& OrientableROI::GetWorldVelocity() const +const float* OrientableROI::GetWorldVelocity() const { - return (Vector3&) *m_world_velocity.GetData(); + return m_world_velocity.GetData(); } // FUNCTION: LEGO1 0x100a5d90 diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index 82db8271..36b8ae50 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -1,47 +1,59 @@ #ifndef ORIENTABLEROI_H #define ORIENTABLEROI_H -#include "matrix.h" +#include "decomp.h" +#include "mxgeometry/mxmatrix.h" #include "roi.h" // VTABLE: LEGO1 0x100dbc08 // SIZE 0xdc class OrientableROI : public ROI { public: - // FUNCTION: LEGO1 0x100a4420 - OrientableROI() - { - FILLVEC3(m_world_bounding_box.Min(), 888888.8); - FILLVEC3(m_world_bounding_box.Max(), -888888.8); - ZEROVEC3(m_world_bounding_sphere.Center()); - m_world_bounding_sphere.Radius() = 0.0; - ZEROVEC3(m_world_velocity); - IDENTMAT4(m_local2world.GetMatrix()); - } + enum { + c_bit1 = 0x01, + c_bit2 = 0x02 + }; - virtual const Vector3& GetWorldVelocity() const override; // vtable+0x8 + OrientableROI(); + + virtual const float* GetWorldVelocity() const override; // vtable+0x8 virtual const BoundingBox& GetWorldBoundingBox() const override; // vtable+0xc virtual const BoundingSphere& GetWorldBoundingSphere() const override; // vtable+0x10 // FUNCTION: LEGO1 0x100a5db0 - virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 - virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 - virtual void VTable0x1c(); // vtable+0x1c - virtual void SetLocalTransform(const Matrix4Impl& p_transform); // vtable+0x20 - virtual void VTable0x24(const Matrix4Data& p_transform); // vtable+0x24 - virtual void UpdateWorldData(const Matrix4Data& p_transform); // vtable+0x28 - virtual void UpdateWorldVelocity(); // vtable+0x2c + virtual void VTable0x14() { VTable0x1c(); } // vtable+0x14 + virtual void UpdateWorldBoundingVolumes() = 0; // vtable+0x18 + virtual void VTable0x1c(); // vtable+0x1c + virtual void SetLocalTransform(const Matrix4& p_transform); // vtable+0x20 + virtual void VTable0x24(const MxMatrix& p_transform); // vtable+0x24 + virtual void UpdateWorldData(const MxMatrix& p_transform); // vtable+0x28 + virtual void UpdateWorldVelocity(); // vtable+0x2c - // SYNTHETIC: LEGO1 0x100a4630 - // OrientableROI::`scalar deleting destructor' + const MxMatrix& GetLocal2World() const { return m_local2world; } + const float* GetWorldPosition() const { return m_local2world[3]; } + const float* GetWorldDirection() const { return m_local2world[2]; } + const float* GetWorldUp() const { return m_local2world[1]; } protected: - char m_unk0xc; // 0xc - Matrix4Data m_local2world; // 0x10 - BoundingBox m_world_bounding_box; // 0x58 + MxMatrix m_local2world; // 0x10 + BoundingBox m_world_bounding_box; // 0x58 + + // Unclear whether the following vectors are: + // 1) Part of m_world_bounding_box; + // 2) A second BoundingBox; + // 3) Standalone vectors + + Mx3DPointFloat m_unk0x80; // 0x80 + Mx3DPointFloat m_unk0x94; // 0x94 BoundingSphere m_world_bounding_sphere; // 0xa8 - Vector3Data m_world_velocity; // 0xc0 - unsigned int m_unk0xd4; // 0xd4 - unsigned int m_unk0xd8; // 0xd8 + Mx3DPointFloat m_world_velocity; // 0xc0 + undefined4 m_unk0xd4; // 0xd4 + undefined4 m_unk0xd8; // 0xd8 }; +// SYNTHETIC: LEGO1 0x100a4630 +// OrientableROI::`scalar deleting destructor' + +// SYNTHETIC: LEGO1 0x100aa2f0 +// OrientableROI::~OrientableROI + #endif // ORIENTABLEROI_H diff --git a/LEGO1/realtime/realtime.cpp b/LEGO1/realtime/realtime.cpp index 750082ec..829b2271 100644 --- a/LEGO1/realtime/realtime.cpp +++ b/LEGO1/realtime/realtime.cpp @@ -1,45 +1,20 @@ #include "realtime.h" +#include + // FUNCTION: LEGO1 0x100a5b40 -void CalcLocalTransform( - const Vector3Impl& p_posVec, - const Vector3Impl& p_dirVec, - const Vector3Impl& p_upVec, - Matrix4Impl& p_outMatrix -) +void CalcLocalTransform(const Vector3& p_posVec, const Vector3& p_dirVec, const Vector3& p_upVec, Matrix4& p_outMatrix) { float x_axis[3], y_axis[3], z_axis[3]; - // This is an unrolled version of the "NORMVEC3" macro, - // used here to apply a silly hack to get a 100% match - { - const float dirVec1Operation = (p_dirVec)[1] * (p_dirVec)[1]; - double len = sqrt(((p_dirVec)[0] * (p_dirVec)[0] + dirVec1Operation + (p_dirVec)[2] * (p_dirVec)[2])); - ((z_axis)[0] = (p_dirVec)[0] / (len), (z_axis)[1] = (p_dirVec)[1] / (len), (z_axis)[2] = (p_dirVec)[2] / (len)); - } - + NORMVEC3(z_axis, p_dirVec); NORMVEC3(y_axis, p_upVec) - VXV3(x_axis, y_axis, z_axis); - - // Exact same thing as pointed out by the above comment - { - const float axis2Operation = (x_axis)[2] * (x_axis)[2]; - double len = sqrt(((x_axis)[0] * (x_axis)[0] + axis2Operation + (x_axis)[1] * (x_axis)[1])); - ((x_axis)[0] = (x_axis)[0] / (len), (x_axis)[1] = (x_axis)[1] / (len), (x_axis)[2] = (x_axis)[2] / (len)); - } - + NORMVEC3(x_axis, x_axis); VXV3(y_axis, z_axis, x_axis); - - // Again, the same thing - { - const float axis2Operation = (y_axis)[2] * (y_axis)[2]; - double len = sqrt(((y_axis)[0] * (y_axis)[0] + axis2Operation + (y_axis)[1] * (y_axis)[1])); - ((y_axis)[0] = (y_axis)[0] / (len), (y_axis)[1] = (y_axis)[1] / (len), (y_axis)[2] = (y_axis)[2] / (len)); - } - - SET4from3(&p_outMatrix[0], x_axis, 0); - SET4from3(&p_outMatrix[4], y_axis, 0); - SET4from3(&p_outMatrix[8], z_axis, 0); - SET4from3(&p_outMatrix[12], p_posVec, 1); + NORMVEC3(y_axis, y_axis); + SET4from3(p_outMatrix[0], x_axis, 0); + SET4from3(p_outMatrix[1], y_axis, 0); + SET4from3(p_outMatrix[2], z_axis, 0); + SET4from3(p_outMatrix[3], p_posVec, 1); } diff --git a/LEGO1/realtime/realtime.h b/LEGO1/realtime/realtime.h index ae166dfa..cb8298a1 100644 --- a/LEGO1/realtime/realtime.h +++ b/LEGO1/realtime/realtime.h @@ -9,11 +9,6 @@ VDS3(dst, src, len); \ } -void CalcLocalTransform( - const Vector3Impl& p_posVec, - const Vector3Impl& p_dirVec, - const Vector3Impl& p_upVec, - Matrix4Impl& p_outMatrix -); +void CalcLocalTransform(const Vector3& p_posVec, const Vector3& p_dirVec, const Vector3& p_upVec, Matrix4& p_outMatrix); #endif // REALTIME_H diff --git a/LEGO1/realtime/realtimeview.cpp b/LEGO1/realtime/realtimeview.cpp index 5d1fc1a6..9522d1c1 100644 --- a/LEGO1/realtime/realtimeview.cpp +++ b/LEGO1/realtime/realtimeview.cpp @@ -30,8 +30,7 @@ void RealtimeView::SetPartsThreshold(float p_threshold) // FUNCTION: LEGO1 0x100a5e00 float RealtimeView::GetUserMaxLOD() { - // TODO - return 0; + return g_userMaxLod; } // FUNCTION: LEGO1 0x100a5e10 diff --git a/LEGO1/realtime/roi.h b/LEGO1/realtime/roi.h index c8458cd7..08db5080 100644 --- a/LEGO1/realtime/roi.h +++ b/LEGO1/realtime/roi.h @@ -5,39 +5,39 @@ #include "compat.h" #include "lodlist.h" +#include "mxgeometry/mxgeometry3d.h" #include "mxstl/stlcompat.h" #include "realtime/realtime.h" -#include "vector.h" /* * A simple bounding box object with Min and Max accessor methods. */ +// SIZE 0x28 class BoundingBox { public: - const Vector3Data& Min() const { return min; } - Vector3Data& Min() { return min; } - const Vector3Data& Max() const { return max; } - Vector3Data& Max() { return max; } + const Mx3DPointFloat& Min() const { return min; } + Mx3DPointFloat& Min() { return min; } + const Mx3DPointFloat& Max() const { return max; } + Mx3DPointFloat& Max() { return max; } private: - Vector3Data min; - Vector3Data max; - Vector3Data m_unk0x28; - Vector3Data m_unk0x3c; + Mx3DPointFloat min; + Mx3DPointFloat max; }; /* * A simple bounding sphere object with center and radius accessor methods. */ +// SIZE 0x18 class BoundingSphere { public: - const Vector3Data& Center() const { return center; } - Vector3Data& Center() { return center; } + const Mx3DPointFloat& Center() const { return center; } + Mx3DPointFloat& Center() { return center; } const float& Radius() const { return radius; } float& Radius() { return radius; } private: - Vector3Data center; + Mx3DPointFloat center; float radius; }; @@ -74,13 +74,14 @@ typedef vector ROIList; typedef vector IntList; // VTABLE: LEGO1 0x100dbc38 -// SIZE 0xc +// SIZE 0x10 class ROI { public: ROI() { m_comp = 0; m_lods = 0; + m_unk0xc = 1; } virtual ~ROI() { @@ -89,7 +90,7 @@ class ROI { assert(!m_lods); } virtual float IntrinsicImportance() const = 0; // vtable+0x4 - virtual const Vector3& GetWorldVelocity() const = 0; // vtable+0x8 + virtual const float* GetWorldVelocity() const = 0; // vtable+0x8 virtual const BoundingBox& GetWorldBoundingBox() const = 0; // vtable+0xc virtual const BoundingSphere& GetWorldBoundingSphere() const = 0; // vtable+0x10 @@ -102,8 +103,16 @@ class ROI { int GetLODCount() const { return m_lods ? m_lods->Size() : 0; } const CompoundObject* GetComp() const { return m_comp; } + // SYNTHETIC: LEGO1 0x100a5d60 + // ROI::`scalar deleting destructor' + protected: CompoundObject* m_comp; // 0x4 LODListBase* m_lods; // 0x8 + undefined m_unk0xc; // 0xc }; + +// SYNTHETIC: LEGO1 0x100a5d50 +// ROI::~ROI + #endif // ROI_H diff --git a/LEGO1/realtime/vector.cpp b/LEGO1/realtime/vector.cpp index 390cfdd9..57c93e66 100644 --- a/LEGO1/realtime/vector.cpp +++ b/LEGO1/realtime/vector.cpp @@ -1,457 +1,7 @@ - #include "vector.h" #include "decomp.h" -#include -#include - -DECOMP_SIZE_ASSERT(Vector2Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector3Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector4Impl, 0x8); -DECOMP_SIZE_ASSERT(Vector3Data, 0x14); -DECOMP_SIZE_ASSERT(Vector4Data, 0x18); - -// FUNCTION: LEGO1 0x10001f80 -void Vector2Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; -} - -// FUNCTION: LEGO1 0x10001fa0 -void Vector2Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; -} - -// FUNCTION: LEGO1 0x10001fc0 -void Vector2Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; -} - -// FUNCTION: LEGO1 0x10001fe0 -void Vector2Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; -} - -// FUNCTION: LEGO1 0x10002000 -void Vector2Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; -} - -// FUNCTION: LEGO1 0x10002020 -void Vector2Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; -} - -// FUNCTION: LEGO1 0x10002040 -float Vector2Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_b[0] * p_a[0] + p_b[1] * p_a[1]; -} - -// FUNCTION: LEGO1 0x10002070 -void Vector2Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; -} - -// FUNCTION: LEGO1 0x10002090 -float* Vector2Impl::GetData() -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100020a0 -const float* Vector2Impl::GetData() const -{ - return m_data; -} - -// FUNCTION: LEGO1 0x100020b0 -void Vector2Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; -} - -// FUNCTION: LEGO1 0x100020d0 -float Vector2Impl::Dot(float* p_a, float* p_b) const -{ - return DotImpl(p_a, p_b); -} - -// FUNCTION: LEGO1 0x100020f0 -float Vector2Impl::Dot(Vector2Impl* p_a, Vector2Impl* p_b) const -{ - return DotImpl(p_a->m_data, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002110 -float Vector2Impl::Dot(float* p_a, Vector2Impl* p_b) const -{ - return DotImpl(p_a, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002130 -float Vector2Impl::Dot(Vector2Impl* p_a, float* p_b) const -{ - return DotImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002150 -float Vector2Impl::LenSquared() const -{ - return m_data[0] * m_data[0] + m_data[1] * m_data[1]; -} - -// FUNCTION: LEGO1 0x10002160 -int Vector2Impl::Unitize() -{ - float sq = LenSquared(); - if (sq > 0.0f) { - float root = sqrt(sq); - if (root > 0) { - DivScalarImpl(&root); - return 0; - } - } - return -1; -} - -// FUNCTION: LEGO1 0x100021c0 -void Vector2Impl::Add(float p_value) -{ - AddScalarImpl(p_value); -} - -// FUNCTION: LEGO1 0x100021d0 -void Vector2Impl::Add(float* p_other) -{ - AddVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x100021e0 -void Vector2Impl::Add(Vector2Impl* p_other) -{ - AddVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x100021f0 -void Vector2Impl::Sub(float* p_other) -{ - SubVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002200 -void Vector2Impl::Sub(Vector2Impl* p_other) -{ - SubVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002210 -void Vector2Impl::Mul(float* p_other) -{ - MullVectorImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002220 -void Vector2Impl::Mul(Vector2Impl* p_other) -{ - MullVectorImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002230 -void Vector2Impl::Mul(float& p_value) -{ - MullScalarImpl(&p_value); -} - -// FUNCTION: LEGO1 0x10002240 -void Vector2Impl::Div(float& p_value) -{ - DivScalarImpl(&p_value); -} - -// FUNCTION: LEGO1 0x10002250 -void Vector2Impl::SetVector(float* p_other) -{ - EqualsImpl(p_other); -} - -// FUNCTION: LEGO1 0x10002260 -void Vector2Impl::SetVector(Vector2Impl* p_other) -{ - EqualsImpl(p_other->m_data); -} - -// FUNCTION: LEGO1 0x10002270 -void Vector3Impl::EqualsCrossImpl(float* p_a, float* p_b) -{ - m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; - m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; - m_data[2] = p_a[0] * p_b[1] - p_a[1] * p_b[0]; -} - -// FUNCTION: LEGO1 0x100022c0 -void Vector3Impl::EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b) -{ - EqualsCrossImpl(p_a->m_data, p_b->m_data); -} - -// FUNCTION: LEGO1 0x100022e0 -void Vector3Impl::EqualsCross(Vector3Impl* p_a, float* p_b) -{ - EqualsCrossImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002300 -void Vector3Impl::EqualsCross(float* p_a, Vector3Impl* p_b) -{ - EqualsCrossImpl(p_a, p_b->m_data); -} - -// FUNCTION: LEGO1 0x10002870 -void Vector4Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; - m_data[2] += p_value[2]; - m_data[3] += p_value[3]; -} - -// FUNCTION: LEGO1 0x100028b0 -void Vector4Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; - m_data[2] += p_value; - m_data[3] += p_value; -} - -// FUNCTION: LEGO1 0x100028f0 -void Vector4Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; - m_data[2] -= p_value[2]; - m_data[3] -= p_value[3]; -} - -// FUNCTION: LEGO1 0x10002930 -void Vector4Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; - m_data[2] *= p_value[2]; - m_data[3] *= p_value[3]; -} - -// FUNCTION: LEGO1 0x10002970 -void Vector4Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; - m_data[2] *= *p_value; - m_data[3] *= *p_value; -} - -// FUNCTION: LEGO1 0x100029b0 -void Vector4Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; - m_data[2] /= *p_value; - m_data[3] /= *p_value; -} - -// FUNCTION: LEGO1 0x100029f0 -float Vector4Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_a[0] * p_b[0] + p_a[2] * p_b[2] + (p_a[1] * p_b[1] + p_a[3] * p_b[3]); -} - -// FUNCTION: LEGO1 0x10002a20 -void Vector4Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; - vec[2] = p_data[2]; - vec[3] = p_data[3]; -} - -// FUNCTION: LEGO1 0x10002a40 -void Vector4Impl::SetMatrixProductImpl(float* p_vec, float* p_mat) -{ - m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; - m_data[1] = p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; - m_data[2] = p_vec[0] * p_mat[2] + p_vec[1] * p_mat[6] + p_vec[2] * p_mat[10] + p_vec[4] * p_mat[14]; - m_data[3] = p_vec[0] * p_mat[3] + p_vec[1] * p_mat[7] + p_vec[2] * p_mat[11] + p_vec[4] * p_mat[15]; -} - -// FUNCTION: LEGO1 0x10002ae0 -void Vector4Impl::SetMatrixProduct(Vector4Impl* p_a, float* p_b) -{ - SetMatrixProductImpl(p_a->m_data, p_b); -} - -// FUNCTION: LEGO1 0x10002b00 -void Vector4Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 0.0f; - vec[3] = 0.0f; -} - -// FUNCTION: LEGO1 0x10002b20 -float Vector4Impl::LenSquared() const -{ - return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2] + m_data[3] * m_data[3]; -} - -// FUNCTION: LEGO1 0x10002b40 -void Vector4Impl::EqualsScalar(float* p_value) -{ - m_data[0] = *p_value; - m_data[1] = *p_value; - m_data[2] = *p_value; - m_data[3] = *p_value; -} - -// Note close yet, included because I'm at least confident I know what operation -// it's trying to do. -// STUB: LEGO1 0x10002b70 -int Vector4Impl::NormalizeQuaternion() -{ - float* v = m_data; - float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; - if (magnitude > 0.0f) { - float theta = v[3] * 0.5f; - v[3] = cos(theta); - float frac = sin(theta); - magnitude = frac / sqrt(magnitude); - v[0] *= magnitude; - v[1] *= magnitude; - v[2] *= magnitude; - return 0; - } - return -1; -} - -// FUNCTION: LEGO1 0x10002bf0 -void Vector4Impl::UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b) -{ - float* bDat = p_b->m_data; - float* aDat = p_a->m_data; - - this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); - this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; - this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; - this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; - - m_data[0] = p_b->m_data[3] * p_a->m_data[0] + p_a->m_data[3] * p_b->m_data[0] + m_data[0]; - m_data[1] = p_b->m_data[1] * p_a->m_data[3] + p_a->m_data[1] * p_b->m_data[3] + m_data[1]; - m_data[2] = p_b->m_data[2] * p_a->m_data[3] + p_a->m_data[2] * p_b->m_data[3] + m_data[2]; -} - -// FUNCTION: LEGO1 0x10003a60 -void Vector3Impl::AddVectorImpl(float* p_value) -{ - m_data[0] += p_value[0]; - m_data[1] += p_value[1]; - m_data[2] += p_value[2]; -} - -// FUNCTION: LEGO1 0x10003a90 -void Vector3Impl::AddScalarImpl(float p_value) -{ - m_data[0] += p_value; - m_data[1] += p_value; - m_data[2] += p_value; -} - -// FUNCTION: LEGO1 0x10003ac0 -void Vector3Impl::SubVectorImpl(float* p_value) -{ - m_data[0] -= p_value[0]; - m_data[1] -= p_value[1]; - m_data[2] -= p_value[2]; -} - -// FUNCTION: LEGO1 0x10003af0 -void Vector3Impl::MullVectorImpl(float* p_value) -{ - m_data[0] *= p_value[0]; - m_data[1] *= p_value[1]; - m_data[2] *= p_value[2]; -} - -// FUNCTION: LEGO1 0x10003b20 -void Vector3Impl::MullScalarImpl(float* p_value) -{ - m_data[0] *= *p_value; - m_data[1] *= *p_value; - m_data[2] *= *p_value; -} - -// FUNCTION: LEGO1 0x10003b50 -void Vector3Impl::DivScalarImpl(float* p_value) -{ - m_data[0] /= *p_value; - m_data[1] /= *p_value; - m_data[2] /= *p_value; -} - -// FUNCTION: LEGO1 0x10003b80 -float Vector3Impl::DotImpl(float* p_a, float* p_b) const -{ - return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; -} - -// FUNCTION: LEGO1 0x10003ba0 -void Vector3Impl::EqualsImpl(float* p_data) -{ - float* vec = m_data; - vec[0] = p_data[0]; - vec[1] = p_data[1]; - vec[2] = p_data[2]; -} - -// FUNCTION: LEGO1 0x10003bc0 -void Vector3Impl::Clear() -{ - float* vec = m_data; - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 0.0f; -} - -// FUNCTION: LEGO1 0x10003bd0 -float Vector3Impl::LenSquared() const -{ - return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; -} - -// FUNCTION: LEGO1 0x10003bf0 -void Vector3Impl::EqualsScalar(float* p_value) -{ - m_data[0] = *p_value; - m_data[1] = *p_value; - m_data[2] = *p_value; -} +DECOMP_SIZE_ASSERT(Vector2, 0x8); +DECOMP_SIZE_ASSERT(Vector3, 0x8); +DECOMP_SIZE_ASSERT(Vector4, 0x8); diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 1af21c9a..eb03d29d 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -1,115 +1,145 @@ #ifndef VECTOR_H #define VECTOR_H -#include +#include "compat.h" -/* - * A simple array of three floats that can be indexed into. - */ -class Vector3 { -public: - float elements[3]; // storage is public for easy access - - Vector3() {} - Vector3(float x, float y, float z) - { - elements[0] = x; - elements[1] = y; - elements[2] = z; - } - - Vector3(const float v[3]) - { - elements[0] = v[0]; - elements[1] = v[1]; - elements[2] = v[2]; - } - - const float& operator[](long i) const { return elements[i]; } - float& operator[](long i) { return elements[i]; } -}; - -/* - * A simple array of four floats that can be indexed into. - */ -struct Vector4 { -public: - float elements[4]; // storage is public for easy access - - inline Vector4() {} - Vector4(float x, float y, float z, float w) - { - elements[0] = x; - elements[1] = y; - elements[2] = z; - elements[3] = w; - } - Vector4(const float v[4]) - { - elements[0] = v[0]; - elements[1] = v[1]; - elements[2] = v[2]; - elements[3] = v[3]; - } - - const float& operator[](long i) const { return elements[i]; } - float& operator[](long i) { return elements[i]; } -}; +#include +#include // VTABLE: LEGO1 0x100d4288 -// SIZE 0x8 -class Vector2Impl { +// SIZE 0x08 +class Vector2 { public: // FUNCTION: LEGO1 0x1000c0f0 - inline Vector2Impl(float* p_data) { SetData(p_data); } + inline Vector2(float* p_data) { SetData(p_data); } - // vtable + 0x00 (no virtual destructor) - virtual void AddScalarImpl(float p_value) = 0; - virtual void AddVectorImpl(float* p_value) = 0; - virtual void SubVectorImpl(float* p_value) = 0; - virtual void MullScalarImpl(float* p_value) = 0; + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. + + // FUNCTION: LEGO1 0x10001f80 + virtual void AddImpl(float* p_value) + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x10001fa0 + virtual void AddImpl(float p_value) + { + m_data[0] += p_value; + m_data[1] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x10001fc0 + virtual void SubImpl(float* p_value) + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + } // vtable+0x08 + + // Those are also overloads in all likelihood, + // but we need a type to do that. + + // FUNCTION: LEGO1 0x10002000 + virtual void MulScalarImpl(float* p_value) + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10001fe0 + virtual void MulVectorImpl(float* p_value) + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x10002020 + virtual void DivScalarImpl(float* p_value) + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x10002040 + virtual float DotImpl(float* p_a, float* p_b) const { return p_b[0] * p_a[0] + p_b[1] * p_a[1]; } // vtable+0x18 - // vtable + 0x10 - virtual void MullVectorImpl(float* p_value) = 0; - virtual void DivScalarImpl(float* p_value) = 0; - virtual float DotImpl(float* p_a, float* p_b) const = 0; // FUNCTION: LEGO1 0x10002060 - virtual void SetData(float* p_data) { m_data = p_data; } + virtual void SetData(float* p_data) { m_data = p_data; } // vtable+0x1c - // vtable + 0x20 - virtual void EqualsImpl(float* p_data) = 0; - virtual float* GetData(); - virtual const float* GetData() const; - virtual void Clear() = 0; + // FUNCTION: LEGO1 0x10002070 + virtual void EqualsImpl(float* p_data) { memcpy(m_data, p_data, sizeof(float) * 2); } // vtable+0x20 - // vtable + 0x30 - virtual float Dot(Vector2Impl* p_a, float* p_b) const; - virtual float Dot(float* p_a, Vector2Impl* p_b) const; - virtual float Dot(Vector2Impl* p_a, Vector2Impl* p_b) const; - virtual float Dot(float* p_a, float* p_b) const; + // FUNCTION: LEGO1 0x10002090 + virtual float* GetData() { return m_data; } // vtable+0x28 - // vtable + 0x40 - virtual float LenSquared() const = 0; - virtual int Unitize(); + // FUNCTION: LEGO1 0x100020a0 + virtual const float* GetData() const { return m_data; } // vtable+0x24 - // vtable + 0x48 - virtual void Add(Vector2Impl* p_other); - virtual void Add(float* p_other); - virtual void Add(float p_value); + // FUNCTION: LEGO1 0x100020b0 + virtual void Clear() { memset(m_data, 0, sizeof(float) * 2); } // vtable+0x2c - // vtable + 0x54 - virtual void Sub(Vector2Impl* p_other); - virtual void Sub(float* p_other); + // FUNCTION: LEGO1 0x100020d0 + virtual float Dot(float* p_a, float* p_b) const { return DotImpl(p_a, p_b); } // vtable+0x3c - // vtable + 0x5C - virtual void Mul(float* p_value); - virtual void Mul(Vector2Impl* p_other); - virtual void Mul(float& p_other); - virtual void Div(float& p_value); + // FUNCTION: LEGO1 0x100020f0 + virtual float Dot(Vector2* p_a, Vector2* p_b) const { return DotImpl(p_a->m_data, p_b->m_data); } // vtable+0x38 - // vtable + 0x6C - virtual void SetVector(Vector2Impl* p_other); - virtual void SetVector(float* p_other); + // FUNCTION: LEGO1 0x10002110 + virtual float Dot(float* p_a, Vector2* p_b) const { return DotImpl(p_a, p_b->m_data); } // vtable+0x34 + + // FUNCTION: LEGO1 0x10002130 + virtual float Dot(Vector2* p_a, float* p_b) const { return DotImpl(p_a->m_data, p_b); } // vtable+0x30 + + // FUNCTION: LEGO1 0x10002150 + virtual float LenSquared() const { return m_data[0] * m_data[0] + m_data[1] * m_data[1]; } // vtable+0x40 + + // FUNCTION: LEGO1 0x10002160 + virtual int Unitize() + { + float sq = LenSquared(); + if (sq > 0.0f) { + float root = sqrt(sq); + if (root > 0) { + DivScalarImpl(&root); + return 0; + } + } + return -1; + } // vtable+0x44 + + // FUNCTION: LEGO1 0x100021c0 + virtual void Add(float p_value) { AddImpl(p_value); } // vtable+0x50 + + // FUNCTION: LEGO1 0x100021d0 + virtual void Add(float* p_other) { AddImpl(p_other); } // vtable+0x4c + + // FUNCTION: LEGO1 0x100021e0 + virtual void Add(Vector2* p_other) { AddImpl(p_other->m_data); } // vtable+0x48 + + // FUNCTION: LEGO1 0x100021f0 + virtual void Sub(float* p_other) { SubImpl(p_other); } // vtable+0x58 + + // FUNCTION: LEGO1 0x10002200 + virtual void Sub(Vector2* p_other) { SubImpl(p_other->m_data); } // vtable+0x54 + + // FUNCTION: LEGO1 0x10002210 + virtual void Mul(float* p_other) { MulVectorImpl(p_other); } // vtable+0x64 + + // FUNCTION: LEGO1 0x10002220 + virtual void Mul(Vector2* p_other) { MulVectorImpl(p_other->m_data); } // vtable+0x60 + + // FUNCTION: LEGO1 0x10002230 + virtual void Mul(float& p_value) { MulScalarImpl(&p_value); } // vtable+0x5c + + // FUNCTION: LEGO1 0x10002240 + virtual void Div(float& p_value) { DivScalarImpl(&p_value); } // vtable+0x68 + + // FUNCTION: LEGO1 0x10002250 + virtual void SetVector(float* p_other) { EqualsImpl(p_other); } // vtable+0x70 + + // FUNCTION: LEGO1 0x10002260 + virtual void SetVector(Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c inline float& operator[](size_t idx) { return m_data[idx]; } inline const float& operator[](size_t idx) const { return m_data[idx]; } @@ -119,100 +149,261 @@ class Vector2Impl { }; // VTABLE: LEGO1 0x100d4518 -// SIZE 0x8 -class Vector3Impl : public Vector2Impl { +// SIZE 0x08 +class Vector3 : public Vector2 { public: - inline Vector3Impl(float* p_data) : Vector2Impl(p_data) {} + // FUNCTION: LEGO1 0x1001d150 + inline Vector3(float* p_data) : Vector2(p_data) {} - void AddScalarImpl(float p_value); + // Hack: Some code initializes a Vector3 from a (most likely) const float* source. + // Example: LegoCameraController::GetWorldUp + // Vector3 however is a class that can mutate its underlying source, making + // initialization with a const source fundamentally incompatible. + inline Vector3(const float* p_data) : Vector2((float*) p_data) {} - void AddVectorImpl(float* p_value); + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. - void SubVectorImpl(float* p_value); - void MullScalarImpl(float* p_value); - void MullVectorImpl(float* p_value); - void DivScalarImpl(float* p_value); - float DotImpl(float* p_a, float* p_b) const; + // FUNCTION: LEGO1 0x10002270 + virtual void EqualsCrossImpl(float* p_a, float* p_b) + { + m_data[0] = p_a[1] * p_b[2] - p_a[2] * p_b[1]; + m_data[1] = p_a[2] * p_b[0] - p_a[0] * p_b[2]; + m_data[2] = p_a[0] * p_b[1] - p_a[1] * p_b[0]; + } // vtable+0x74 - void EqualsImpl(float* p_data); + // FUNCTION: LEGO1 0x100022c0 + virtual void EqualsCross(Vector3* p_a, Vector3* p_b) { EqualsCrossImpl(p_a->m_data, p_b->m_data); } // vtable+0x80 - void Clear(); + // FUNCTION: LEGO1 0x100022e0 + virtual void EqualsCross(Vector3* p_a, float* p_b) { EqualsCrossImpl(p_a->m_data, p_b); } // vtable+0x7c - float LenSquared() const; + // FUNCTION: LEGO1 0x10002300 + virtual void EqualsCross(float* p_a, Vector3* p_b) { EqualsCrossImpl(p_a, p_b->m_data); } // vtable+0x78 - // vtable + 0x74 - virtual void EqualsCrossImpl(float* p_a, float* p_b); - virtual void EqualsCross(float* p_a, Vector3Impl* p_b); - virtual void EqualsCross(Vector3Impl* p_a, float* p_b); - virtual void EqualsCross(Vector3Impl* p_a, Vector3Impl* p_b); - virtual void EqualsScalar(float* p_value); + // FUNCTION: LEGO1 0x10003bf0 + virtual void EqualsScalar(float* p_value) + { + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; + } // vtable+0x84 + + // Vector2 overrides + + // FUNCTION: LEGO1 0x10003a60 + virtual void AddImpl(float* p_value) override + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x10003a90 + virtual void AddImpl(float p_value) override + { + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x10003ac0 + virtual void SubImpl(float* p_value) override + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; + } // vtable+0x08 + + // FUNCTION: LEGO1 0x10003b20 + virtual void MulScalarImpl(float* p_value) override + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10003af0 + virtual void MulVectorImpl(float* p_value) override + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x10003b50 + virtual void DivScalarImpl(float* p_value) override + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x10003b80 + virtual float DotImpl(float* p_a, float* p_b) const override + { + return p_a[0] * p_b[0] + p_a[2] * p_b[2] + p_a[1] * p_b[1]; + } // vtable+0x18 + + // FUNCTION: LEGO1 0x10003ba0 + virtual void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 3); } // vtable+0x20 + + // FUNCTION: LEGO1 0x10003bc0 + virtual void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10003bd0 + virtual float LenSquared() const override + { + return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2]; + } // vtable+0x40 inline void Fill(float p_value) { EqualsScalar(&p_value); } + + friend class Mx3DPointFloat; }; // VTABLE: LEGO1 0x100d45a0 // SIZE 0x8 -class Vector4Impl : public Vector3Impl { +class Vector4 : public Vector3 { public: - inline Vector4Impl(float* p_data) : Vector3Impl(p_data) {} + inline Vector4(float* p_data) : Vector3(p_data) {} - void AddScalarImpl(float p_value); + // Note: virtual function overloads appear in the virtual table + // in reverse order of appearance. - void AddVectorImpl(float* p_value); - - void SubVectorImpl(float* p_value); - void MullScalarImpl(float* p_value); - void MullVectorImpl(float* p_value); - void DivScalarImpl(float* p_value); - float DotImpl(float* p_a, float* p_b) const; - - void EqualsImpl(float* p_data); - - void Clear(); - - float LenSquared() const; - - void EqualsScalar(float* p_value); - - // vtable + 0x88 - virtual void SetMatrixProduct(Vector4Impl* p_a, float* p_b); - virtual void SetMatrixProductImpl(float* p_vec, float* p_mat); - virtual int NormalizeQuaternion(); - virtual void UnknownQuaternionOp(Vector4Impl* p_a, Vector4Impl* p_b); - - inline Vector4& GetVector() { return *((Vector4*) m_data); } -}; - -// VTABLE: LEGO1 0x100d4488 -// SIZE 0x14 -class Vector3Data : public Vector3Impl { -public: - inline Vector3Data() : Vector3Impl(m_vector.elements) {} - inline Vector3Data(float p_x, float p_y, float p_z) : Vector3Impl(m_vector.elements), m_vector(p_x, p_y, p_z) {} - - void CopyFrom(Vector3Data& p_other) + // FUNCTION: LEGO1 0x10002a40 + virtual void SetMatrixProduct(float* p_vec, float* p_mat) { - EqualsImpl(p_other.m_data); + m_data[0] = p_vec[0] * p_mat[0] + p_vec[1] * p_mat[4] + p_vec[2] * p_mat[8] + p_vec[3] * p_mat[12]; + m_data[1] = p_vec[0] * p_mat[1] + p_vec[1] * p_mat[5] + p_vec[2] * p_mat[9] + p_vec[4] * p_mat[13]; + m_data[2] = p_vec[0] * p_mat[2] + p_vec[1] * p_mat[6] + p_vec[2] * p_mat[10] + p_vec[4] * p_mat[14]; + m_data[3] = p_vec[0] * p_mat[3] + p_vec[1] * p_mat[7] + p_vec[2] * p_mat[11] + p_vec[4] * p_mat[15]; + } // vtable+0x8c - float* dest = m_vector.elements; - float* src = p_other.m_vector.elements; - for (size_t i = sizeof(m_vector) / sizeof(float); i > 0; --i) - *dest++ = *src++; + // FUNCTION: LEGO1 0x10002ae0 + virtual void SetMatrixProduct(Vector4* p_a, float* p_b) { SetMatrixProduct(p_a->m_data, p_b); } // vtable+0x88 + + inline virtual int NormalizeQuaternion(); // vtable+90 + inline virtual void UnknownQuaternionOp(Vector4* p_a, Vector4* p_b); // vtable+94 + + // Vector3 overrides + + // FUNCTION: LEGO1 0x10002870 + virtual void AddImpl(float* p_value) override + { + m_data[0] += p_value[0]; + m_data[1] += p_value[1]; + m_data[2] += p_value[2]; + m_data[3] += p_value[3]; + } // vtable+0x04 + + // FUNCTION: LEGO1 0x100028b0 + virtual void AddImpl(float p_value) override + { + m_data[0] += p_value; + m_data[1] += p_value; + m_data[2] += p_value; + m_data[3] += p_value; + } // vtable+0x00 + + // FUNCTION: LEGO1 0x100028f0 + virtual void SubImpl(float* p_value) override + { + m_data[0] -= p_value[0]; + m_data[1] -= p_value[1]; + m_data[2] -= p_value[2]; + m_data[3] -= p_value[3]; + } // vtable+0x08 + + // FUNCTION: LEGO1 0x10002970 + virtual void MulScalarImpl(float* p_value) override + { + m_data[0] *= *p_value; + m_data[1] *= *p_value; + m_data[2] *= *p_value; + m_data[3] *= *p_value; + } // vtable+0x0c + + // FUNCTION: LEGO1 0x10002930 + virtual void MulVectorImpl(float* p_value) override + { + m_data[0] *= p_value[0]; + m_data[1] *= p_value[1]; + m_data[2] *= p_value[2]; + m_data[3] *= p_value[3]; + } // vtable+0x10 + + // FUNCTION: LEGO1 0x100029b0 + virtual void DivScalarImpl(float* p_value) override + { + m_data[0] /= *p_value; + m_data[1] /= *p_value; + m_data[2] /= *p_value; + m_data[3] /= *p_value; + } // vtable+0x14 + + // FUNCTION: LEGO1 0x100029f0 + virtual float DotImpl(float* p_a, float* p_b) const override + { + return p_a[0] * p_b[0] + p_a[2] * p_b[2] + (p_a[1] * p_b[1] + p_a[3] * p_b[3]); + } // vtable+0x18 + + // FUNCTION: LEGO1 0x10002a20 + virtual void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 4); } // vtable+0x20 + + // FUNCTION: LEGO1 0x10002b00 + virtual void Clear() override { memset(m_data, 0, sizeof(float) * 4); } // vtable+0x2c + + // FUNCTION: LEGO1 0x10002b20 + virtual float LenSquared() const override + { + return m_data[1] * m_data[1] + m_data[0] * m_data[0] + m_data[2] * m_data[2] + m_data[3] * m_data[3]; + } // vtable+0x40 + + // FUNCTION: LEGO1 0x10002b40 + virtual void EqualsScalar(float* p_value) override + { + m_data[0] = *p_value; + m_data[1] = *p_value; + m_data[2] = *p_value; + m_data[3] = *p_value; + } // vtable+0x84 +}; + +// Note close yet, included because I'm at least confident I know what operation +// it's trying to do. +// STUB: LEGO1 0x10002b70 +inline int Vector4::NormalizeQuaternion() +{ + float* v = m_data; + float magnitude = v[1] * v[1] + v[2] * v[2] + v[0] * v[0]; + if (magnitude > 0.0f) { + float theta = v[3] * 0.5f; + v[3] = cos(theta); + float frac = sin(theta); + magnitude = frac / sqrt(magnitude); + v[0] *= magnitude; + v[1] *= magnitude; + v[2] *= magnitude; + return 0; } - inline void EqualsCross(Vector3Data& p_a, Vector3Data& p_b) { EqualsCrossImpl(p_a.m_data, p_b.m_data); } + return -1; +} -private: - Vector3 m_vector; -}; +// FUNCTION: LEGO1 0x10002bf0 +inline void Vector4::UnknownQuaternionOp(Vector4* p_a, Vector4* p_b) +{ + float* bDat = p_b->m_data; + float* aDat = p_a->m_data; -// VTABLE: LEGO1 0x100d41e8 -// SIZE 0x18 -class Vector4Data : public Vector4Impl { -public: - inline Vector4Data() : Vector4Impl(m_vector.elements) {} + this->m_data[3] = aDat[3] * bDat[3] - (bDat[0] * aDat[0] + aDat[2] * bDat[2] + aDat[1] * aDat[1]); + this->m_data[0] = bDat[2] * aDat[1] - bDat[1] * aDat[2]; + this->m_data[1] = aDat[2] * bDat[0] - bDat[2] * aDat[0]; + this->m_data[2] = bDat[1] * aDat[0] - aDat[1] * bDat[0]; -private: - Vector4 m_vector; -}; + m_data[0] = p_b->m_data[3] * p_a->m_data[0] + p_a->m_data[3] * p_b->m_data[0] + m_data[0]; + m_data[1] = p_b->m_data[1] * p_a->m_data[3] + p_a->m_data[1] * p_b->m_data[3] + m_data[1]; + m_data[2] = p_b->m_data[2] * p_a->m_data[3] + p_a->m_data[2] * p_b->m_data[3] + m_data[2]; +} #endif // VECTOR_H diff --git a/LEGO1/res/resource.h b/LEGO1/res/resource.h index 5a51e019..2402acad 100644 --- a/LEGO1/res/resource.h +++ b/LEGO1/res/resource.h @@ -8,5 +8,3 @@ #define LEGO1_LEAF5 108 #define LEGO1_LEAF3 109 #define LEGO1_BUSY 111 - -#define APP_ICON 105 diff --git a/LEGO1/tgl/d3drm/camera.cpp b/LEGO1/tgl/d3drm/camera.cpp index 5084c2ca..9e000ba8 100644 --- a/LEGO1/tgl/d3drm/camera.cpp +++ b/LEGO1/tgl/d3drm/camera.cpp @@ -12,7 +12,7 @@ void* CameraImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a3700 -Result CameraImpl::SetTransformation(const FloatMatrix4& matrix) +Result CameraImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* pTransformation = Translate(matrix, helper); diff --git a/LEGO1/tgl/d3drm/group.cpp b/LEGO1/tgl/d3drm/group.cpp index 022dc757..4b966cd2 100644 --- a/LEGO1/tgl/d3drm/group.cpp +++ b/LEGO1/tgl/d3drm/group.cpp @@ -9,7 +9,7 @@ void* GroupImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a31e0 -Result GroupImpl::SetTransformation(const FloatMatrix4& matrix) +Result GroupImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper); diff --git a/LEGO1/tgl/d3drm/impl.h b/LEGO1/tgl/d3drm/impl.h index 4c76a365..1e017cf2 100644 --- a/LEGO1/tgl/d3drm/impl.h +++ b/LEGO1/tgl/d3drm/impl.h @@ -36,7 +36,7 @@ class MeshImpl; class TextureImpl; class UnkImpl; -// VTABLE 0x100db910 +// VTABLE: LEGO1 0x100db910 class RendererImpl : public Renderer { public: RendererImpl() : m_data(0) {} @@ -105,7 +105,7 @@ void RendererImpl::Destroy() } } -// VTABLE 0x100db988 +// VTABLE: LEGO1 0x100db988 class DeviceImpl : public Device { public: DeviceImpl() : m_data(0) {} @@ -142,7 +142,7 @@ class DeviceImpl : public Device { IDirect3DRMDevice2* m_data; }; -// VTABLE 0x100db9e8 +// VTABLE: LEGO1 0x100db9e8 class ViewImpl : public View { public: ViewImpl() : m_data(0) {} @@ -194,7 +194,7 @@ class ViewImpl : public View { IDirect3DRMViewport* m_data; }; -// VTABLE 0x100dbad8 +// VTABLE: LEGO1 0x100dbad8 class CameraImpl : public Camera { public: CameraImpl() : m_data(0) {} @@ -209,7 +209,7 @@ class CameraImpl : public Camera { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -219,7 +219,7 @@ class CameraImpl : public Camera { IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbaf8 +// VTABLE: LEGO1 0x100dbaf8 class LightImpl : public Light { public: LightImpl() : m_data(0) {} @@ -234,7 +234,7 @@ class LightImpl : public Light { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); virtual Result SetColor(float r, float g, float b); inline IDirect3DRMFrame2* ImplementationData() const { return m_data; } @@ -245,7 +245,7 @@ class LightImpl : public Light { IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbb88 +// VTABLE: LEGO1 0x100dbb88 class MeshImpl : public Mesh { public: MeshImpl() : m_data(0) {} @@ -285,7 +285,7 @@ class MeshImpl : public Mesh { MeshData* m_data; }; -// VTABLE 0x100dba68 +// VTABLE: LEGO1 0x100dba68 class GroupImpl : public Group { public: GroupImpl() : m_data(0) {} @@ -300,7 +300,7 @@ class GroupImpl : public Group { virtual void* ImplementationDataPtr(); // vtable+0x08 - virtual Result SetTransformation(const FloatMatrix4&); + virtual Result SetTransformation(FloatMatrix4&); virtual Result SetColor(float r, float g, float b, float a); // vtable+0x10 @@ -324,7 +324,7 @@ class GroupImpl : public Group { IDirect3DRMFrame2* m_data; }; -// VTABLE 0x100dbb18 +// VTABLE: LEGO1 0x100dbb18 class UnkImpl : public Unk { public: UnkImpl() : m_data(0) {} @@ -384,7 +384,7 @@ class TglD3DRMIMAGE { int m_texelsAllocatedByClient; }; -// VTABLE 0x100dbb48 +// VTABLE: LEGO1 0x100dbb48 class TextureImpl : public Texture { public: TextureImpl() : m_data(0) {} @@ -474,7 +474,7 @@ inline D3DRMPROJECTIONTYPE Translate(ProjectionType tglProjectionType) // Yes this function serves no purpose, originally they intended it to // convert from doubles to floats but ended up using floats throughout // the software stack. -inline D3DRMMATRIX4D* Translate(const FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4) +inline D3DRMMATRIX4D* Translate(FloatMatrix4& tglMatrix4x4, D3DRMMATRIX4D& rD3DRMMatrix4x4) { for (int i = 0; i < (sizeof(rD3DRMMatrix4x4) / sizeof(rD3DRMMatrix4x4[0])); i++) { for (int j = 0; j < (sizeof(rD3DRMMatrix4x4[0]) / sizeof(rD3DRMMatrix4x4[0][0])); j++) { diff --git a/LEGO1/tgl/d3drm/light.cpp b/LEGO1/tgl/d3drm/light.cpp index 5ceafa4b..dfc23b44 100644 --- a/LEGO1/tgl/d3drm/light.cpp +++ b/LEGO1/tgl/d3drm/light.cpp @@ -12,7 +12,7 @@ void* LightImpl::ImplementationDataPtr() } // FUNCTION: LEGO1 0x100a3780 -Result LightImpl::SetTransformation(const FloatMatrix4& matrix) +Result LightImpl::SetTransformation(FloatMatrix4& matrix) { D3DRMMATRIX4D helper; D3DRMMATRIX4D* d3dMatrix = Translate(matrix, helper); diff --git a/LEGO1/tgl/tgl.h b/LEGO1/tgl/tgl.h index dfc18f3f..b8a09c3e 100644 --- a/LEGO1/tgl/tgl.h +++ b/LEGO1/tgl/tgl.h @@ -98,15 +98,18 @@ 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 @@ -142,11 +145,14 @@ class Renderer : public Object { // 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,12 +265,15 @@ 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; @@ -266,12 +287,15 @@ class Group : public Object { // 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/viewmanager/viewlodlist.h b/LEGO1/viewmanager/viewlodlist.h index 9dc06d7b..df918350 100644 --- a/LEGO1/viewmanager/viewlodlist.h +++ b/LEGO1/viewmanager/viewlodlist.h @@ -89,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 @@ -119,4 +138,11 @@ inline int ViewLODList::Release() return m_refCount; } +#ifdef _DEBUG +inline void ViewLODList::Dump(void (*pTracer)(const char*, ...)) const +{ + // FIXME: dump something +} +#endif + #endif // VIEWLODLIST_H diff --git a/LEGO1/viewmanager/viewmanager.cpp b/LEGO1/viewmanager/viewmanager.cpp index 8ec2aad2..7d412641 100644 --- a/LEGO1/viewmanager/viewmanager.cpp +++ b/LEGO1/viewmanager/viewmanager.cpp @@ -1,7 +1,32 @@ #include "viewmanager.h" +// STUB: LEGO1 0x100a5eb0 +ViewManager::ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view) +{ +} + +// STUB: LEGO1 0x100a60c0 +ViewManager::~ViewManager() +{ +} + // STUB: LEGO1 0x100a64d0 void ViewManager::RemoveAll(ViewROI*) { // TODO } + +// STUB: LEGO1 0x100a6d50 +void ViewManager::SetResolution(int width, int height) +{ +} + +// STUB: LEGO1 0x100a6d70 +void ViewManager::SetFrustrum(float fov, float front, float back) +{ +} + +// STUB: LEGO1 0x100a6da0 +void ViewManager::SetPOVSource(const OrientableROI* point_of_view) +{ +} diff --git a/LEGO1/viewmanager/viewmanager.h b/LEGO1/viewmanager/viewmanager.h index 2b0d102e..f2ccc6c6 100644 --- a/LEGO1/viewmanager/viewmanager.h +++ b/LEGO1/viewmanager/viewmanager.h @@ -1,11 +1,26 @@ #ifndef VIEWMANAGER_H #define VIEWMANAGER_H -class ViewROI; +#include "viewroi.h" +// VTABLE: LEGO1 0x100dbd88 +// SIZE 0x1bc class ViewManager { public: + ViewManager(Tgl::Renderer* pRenderer, Tgl::Group* scene, const OrientableROI* point_of_view); + virtual ~ViewManager(); + __declspec(dllexport) void RemoveAll(ViewROI*); + + void SetPOVSource(const OrientableROI* point_of_view); + void SetResolution(int width, int height); + void SetFrustrum(float fov, float front, float back); + + // SYNTHETIC: LEGO1 0x100a6000 + // ViewManager::`scalar deleting destructor' + +private: + undefined m_pad[0x1b8]; }; #endif // VIEWMANAGER_H diff --git a/LEGO1/viewmanager/viewroi.cpp b/LEGO1/viewmanager/viewroi.cpp index 523814a2..ff846394 100644 --- a/LEGO1/viewmanager/viewroi.cpp +++ b/LEGO1/viewmanager/viewroi.cpp @@ -2,6 +2,8 @@ #include "decomp.h" +#include + DECOMP_SIZE_ASSERT(ViewROI, 0xe0) // GLOBAL: LEGO1 0x101013d8 @@ -26,13 +28,15 @@ Tgl::Group* ViewROI::GetGeometry() } // FUNCTION: LEGO1 0x100a9ee0 -void ViewROI::UpdateWorldData(const Matrix4Data& parent2world) +void ViewROI::UpdateWorldData(const MxMatrix& parent2world) { OrientableROI::UpdateWorldData(parent2world); + if (geometry) { - Tgl::FloatMatrix4 mat; - SETMAT4(mat, m_local2world.GetMatrix()); - Tgl::Result result = geometry->SetTransformation(mat); + Tgl::FloatMatrix4 matrix; + Matrix4 in(matrix); + SETMAT4(in, m_local2world); + Tgl::Result result = geometry->SetTransformation(matrix); // assert(Tgl::Succeeded(result)); } } diff --git a/LEGO1/viewmanager/viewroi.h b/LEGO1/viewmanager/viewroi.h index 02d69ab5..7157033a 100644 --- a/LEGO1/viewmanager/viewroi.h +++ b/LEGO1/viewmanager/viewroi.h @@ -52,7 +52,7 @@ class ViewROI : public OrientableROI { protected: Tgl::Group* geometry; - void UpdateWorldData(const Matrix4Data& parent2world); + void UpdateWorldData(const MxMatrix& parent2world); }; // SYNTHETIC: LEGO1 0x100aa250 diff --git a/tools/README.md b/tools/README.md index da23d84c..b24a8f50 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. @@ -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/isledecomp/bin.py b/tools/isledecomp/isledecomp/bin.py index 26dd00f8..3b600af6 100644 --- a/tools/isledecomp/isledecomp/bin.py +++ b/tools/isledecomp/isledecomp/bin.py @@ -97,6 +97,8 @@ def __init__(self, filename: str, find_str: bool = False) -> None: self.find_str = find_str self._potential_strings = {} self._relocated_addrs = set() + self.imports = [] + self.thunks = [] def __enter__(self): logger.debug("Bin %s Enter", self.filename) @@ -132,6 +134,8 @@ def __enter__(self): sect.virtual_address += self.imagebase self._populate_relocations() + self._populate_imports() + self._populate_thunks() # This is a (semi) expensive lookup that is not necesssary in every case. # We can find strings in the original if we have coverage using STRING markers. @@ -238,6 +242,78 @@ def _populate_relocations(self): (relocated_addr,) = struct.unpack(" bool: return section is not None + def read_string(self, offset: int, chunk_size: int = 1000) -> Optional[bytes]: + """Read until we find a zero byte.""" + b = self.read(offset, chunk_size) + if b is None: + return None + + try: + return b[: b.index(b"\x00")] + except ValueError: + # No terminator found, just return what we have + return b + def read(self, offset: int, size: int) -> Optional[bytes]: """Read (at most) the given number of bytes at the given virtual address. If we return None, the given address points to uninitialized data.""" diff --git a/tools/isledecomp/isledecomp/compare/asm/__init__.py b/tools/isledecomp/isledecomp/compare/asm/__init__.py new file mode 100644 index 00000000..3fd22f6e --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/asm/__init__.py @@ -0,0 +1,2 @@ +from .parse import ParseAsm +from .swap import can_resolve_register_differences diff --git a/tools/isledecomp/isledecomp/compare/asm/parse.py b/tools/isledecomp/isledecomp/compare/asm/parse.py new file mode 100644 index 00000000..ee9c9154 --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/asm/parse.py @@ -0,0 +1,152 @@ +"""Converts x86 machine code into text (i.e. assembly). The end goal is to +compare the code in the original and recomp binaries, using longest common +subsequence (LCS), i.e. difflib.SequenceMatcher. +The capstone library takes the raw bytes and gives us the mnemnonic +and operand(s) for each instruction. We need to "sanitize" the text further +so that virtual addresses are replaced by symbol name or a generic +placeholder string.""" + +import re +from typing import Callable, List, Optional, Tuple +from collections import namedtuple +from capstone import Cs, CS_ARCH_X86, CS_MODE_32 + +disassembler = Cs(CS_ARCH_X86, CS_MODE_32) + +ptr_replace_regex = re.compile(r"ptr \[(0x[0-9a-fA-F]+)\]") + +DisasmLiteInst = namedtuple("DisasmLiteInst", "address, size, mnemonic, op_str") + + +def from_hex(string: str) -> Optional[int]: + try: + return int(string, 16) + except ValueError: + pass + + return None + + +class ParseAsm: + def __init__( + self, + relocate_lookup: Optional[Callable[[int], bool]] = None, + name_lookup: Optional[Callable[[int], str]] = None, + ) -> None: + self.relocate_lookup = relocate_lookup + self.name_lookup = name_lookup + self.replacements = {} + self.number_placeholders = True + + def reset(self): + self.replacements = {} + + def is_relocated(self, addr: int) -> bool: + if callable(self.relocate_lookup): + return self.relocate_lookup(addr) + + return False + + def lookup(self, addr: int) -> Optional[str]: + """Return a replacement name for this address if we find one.""" + if (cached := self.replacements.get(addr, None)) is not None: + return cached + + if callable(self.name_lookup): + if (name := self.name_lookup(addr)) is not None: + self.replacements[addr] = name + return name + + return None + + def replace(self, addr: int) -> str: + """Same function as lookup above, but here we return a placeholder + if there is no better name to use.""" + if (name := self.lookup(addr)) is not None: + return name + + # The placeholder number corresponds to the number of addresses we have + # already replaced. This is so the number will be consistent across the diff + # if we can replace some symbols with actual names in recomp but not orig. + idx = len(self.replacements) + 1 + placeholder = f"" if self.number_placeholders else "" + self.replacements[addr] = placeholder + return placeholder + + def sanitize(self, inst: DisasmLiteInst) -> Tuple[str, str]: + if len(inst.op_str) == 0: + # Nothing to sanitize + return (inst.mnemonic, "") + + # For jumps or calls, if the entire op_str is a hex number, the value + # is a relative offset. + # Otherwise (i.e. it looks like `dword ptr [address]`) it is an + # absolute indirect that we will handle below. + # Providing the starting address of the function to capstone.disasm has + # automatically resolved relative offsets to an absolute address. + # We will have to undo this for some of the jumps or they will not match. + op_str_address = from_hex(inst.op_str) + + if op_str_address is not None: + if inst.mnemonic == "call": + return (inst.mnemonic, self.replace(op_str_address)) + + if inst.mnemonic == "jmp": + # The unwind section contains JMPs to other functions. + # If we have a name for this address, use it. If not, + # do not create a new placeholder. We will instead + # fall through to generic jump handling below. + potential_name = self.lookup(op_str_address) + if potential_name is not None: + return (inst.mnemonic, potential_name) + + if inst.mnemonic.startswith("j"): + # i.e. if this is any jump + # Show the jump offset rather than the absolute address + jump_displacement = op_str_address - (inst.address + inst.size) + return (inst.mnemonic, hex(jump_displacement)) + + def filter_out_ptr(match): + """Helper for re.sub, see below""" + offset = from_hex(match.group(1)) + + if offset is not None: + # We assume this is always an address to replace + placeholder = self.replace(offset) + return f"ptr [{placeholder}]" + + # Strict regex should ensure we can read the hex number. + # But just in case: return the string with no changes + return match.group(0) + + op_str = ptr_replace_regex.sub(filter_out_ptr, inst.op_str) + + # Performance hack: + # Skip this step if there is nothing left to consider replacing. + if "0x" in op_str: + # Replace immediate values with name or placeholder (where appropriate) + words = op_str.split(", ") + for i, word in enumerate(words): + try: + inttest = int(word, 16) + # If this value is a virtual address, it is referenced absolutely, + # which means it must be in the relocation table. + if self.is_relocated(inttest): + words[i] = self.replace(inttest) + except ValueError: + pass + op_str = ", ".join(words) + + return inst.mnemonic, op_str + + def parse_asm(self, data: bytes, start_addr: Optional[int] = 0) -> List[str]: + asm = [] + + for inst in disassembler.disasm_lite(data, start_addr): + # Use heuristics to disregard some differences that aren't representative + # of the accuracy of a function (e.g. global offsets) + result = self.sanitize(DisasmLiteInst(*inst)) + # mnemonic + " " + op_str + asm.append(" ".join(result)) + + return asm diff --git a/tools/isledecomp/isledecomp/compare/asm/swap.py b/tools/isledecomp/isledecomp/compare/asm/swap.py new file mode 100644 index 00000000..599444cf --- /dev/null +++ b/tools/isledecomp/isledecomp/compare/asm/swap.py @@ -0,0 +1,80 @@ +import re + +REGISTER_LIST = set( + [ + "ax", + "bp", + "bx", + "cx", + "di", + "dx", + "eax", + "ebp", + "ebx", + "ecx", + "edi", + "edx", + "esi", + "esp", + "si", + "sp", + ] +) +WORDS = re.compile(r"\w+") + + +def get_registers(line: str): + to_replace = [] + # use words regex to find all matching positions: + for match in WORDS.finditer(line): + reg = match.group(0) + if reg in REGISTER_LIST: + to_replace.append((reg, match.start())) + return to_replace + + +def replace_register( + lines: list[str], start_line: int, reg: str, replacement: str +) -> list[str]: + return [ + line.replace(reg, replacement) if i >= start_line else line + for i, line in enumerate(lines) + ] + + +# Is it possible to make new_asm the same as original_asm by swapping registers? +def can_resolve_register_differences(original_asm, new_asm): + # Split the ASM on spaces to get more granularity, and so + # that we don't modify the original arrays passed in. + original_asm = [part for line in original_asm for part in line.split()] + new_asm = [part for line in new_asm for part in line.split()] + + # Swapping ain't gonna help if the lengths are different + if len(original_asm) != len(new_asm): + return False + + # Look for the mismatching lines + for i, original_line in enumerate(original_asm): + new_line = new_asm[i] + if new_line != original_line: + # Find all the registers to replace + to_replace = get_registers(original_line) + + for replace in to_replace: + (reg, reg_index) = replace + replacing_reg = new_line[reg_index : reg_index + len(reg)] + if replacing_reg in REGISTER_LIST: + if replacing_reg != reg: + # Do a three-way swap replacing in all the subsequent lines + temp_reg = "&" * len(reg) + new_asm = replace_register(new_asm, i, replacing_reg, temp_reg) + new_asm = replace_register(new_asm, i, reg, replacing_reg) + new_asm = replace_register(new_asm, i, temp_reg, reg) + else: + # No replacement to do, different code, bail out + return False + # Check if the lines are now the same + for i, original_line in enumerate(original_asm): + if new_asm[i] != original_line: + return False + return True diff --git a/tools/isledecomp/isledecomp/compare/core.py b/tools/isledecomp/isledecomp/compare/core.py index 07860203..58f99d32 100644 --- a/tools/isledecomp/isledecomp/compare/core.py +++ b/tools/isledecomp/isledecomp/compare/core.py @@ -1,11 +1,15 @@ import os import logging -from typing import List, Optional +import difflib +import struct +from dataclasses import dataclass +from typing import Iterable, List, Optional from isledecomp.cvdump.demangler import demangle_string_const from isledecomp.cvdump import Cvdump, CvdumpAnalysis from isledecomp.parser import DecompCodebase from isledecomp.dir import walk_source_dir from isledecomp.types import SymbolType +from isledecomp.compare.asm import ParseAsm, can_resolve_register_differences from .db import CompareDb, MatchInfo from .lines import LinesDb @@ -13,6 +17,25 @@ 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 ''}" + + class Compare: # pylint: disable=too-many-instance-attributes def __init__(self, orig_bin, recomp_bin, pdb_file, code_dir): @@ -27,6 +50,7 @@ def __init__(self, orig_bin, recomp_bin, pdb_file, code_dir): self._load_cvdump() self._load_markers() self._find_original_strings() + self._match_thunks() def _load_cvdump(self): logger.info("Parsing %s ...", self.pdb_file) @@ -63,13 +87,19 @@ def _load_cvdump(self): if sym.node_type == SymbolType.STRING: string_info = demangle_string_const(sym.decorated_name) + if string_info is None: + logger.debug( + "Could not demangle string symbol: %s", sym.decorated_name + ) + continue + # TODO: skip unicode for now. will need to handle these differently. if string_info.is_utf16: continue raw = self.recomp_bin.read(addr, sym.size()) try: - sym.friendly_name = raw.decode("latin1") + sym.friendly_name = raw.decode("latin1").rstrip("\x00") except UnicodeDecodeError: pass @@ -112,6 +142,26 @@ def _load_markers(self): for tbl in codebase.iter_vtables(): self._db.match_vtable(tbl.offset, tbl.name) + for string in codebase.iter_strings(): + # Not that we don't trust you, but we're checking the string + # annotation to make sure it is accurate. + try: + # TODO: would presumably fail for wchar_t strings + orig = self.orig_bin.read_string(string.offset).decode("latin1") + string_correct = string.name == orig + except UnicodeDecodeError: + string_correct = False + + if not string_correct: + logger.error( + "Data at 0x%x does not match string %s", + string.offset, + repr(string.name), + ) + continue + + self._db.match_string(string.offset, string.name) + def _find_original_strings(self): """Go to the original binary and look for the specified string constants to find a match. This is a (relatively) expensive operation so we only @@ -126,15 +176,231 @@ def _find_original_strings(self): self._db.match_string(addr, string) - def get_one_function(self, addr: int) -> Optional[MatchInfo]: - """i.e. verbose mode for reccmp""" - return self._db.get_one_function(addr) + def _match_thunks(self): + orig_byaddr = { + addr: (dll.upper(), name) for (dll, name, addr) in self.orig_bin.imports + } + recomp_byname = { + (dll.upper(), name): addr for (dll, name, addr) in self.recomp_bin.imports + } + # Combine these two dictionaries. We don't care about imports from recomp + # not found in orig because: + # 1. They shouldn't be there + # 2. They are already identified via cvdump + orig_to_recomp = { + addr: recomp_byname.get(pair, None) for addr, pair in orig_byaddr.items() + } + + # Now: we have the IAT offset in each matched up, so we need to make + # the connection between the thunk functions. + # We already have the symbol name we need from the PDB. + orig_thunks = { + iat_ofs: func_ofs for (func_ofs, iat_ofs) in self.orig_bin.thunks + } + recomp_thunks = { + iat_ofs: func_ofs for (func_ofs, iat_ofs) in self.recomp_bin.thunks + } + + for orig, recomp in orig_to_recomp.items(): + self._db.set_pair(orig, recomp, SymbolType.POINTER) + thunk_from_orig = orig_thunks.get(orig, None) + thunk_from_recomp = recomp_thunks.get(recomp, None) + + if thunk_from_orig is not None and thunk_from_recomp is not None: + self._db.set_function_pair(thunk_from_orig, thunk_from_recomp) + # Don't compare thunk functions for now. The comparison isn't + # "useful" in the usual sense. We are only looking at the 6 + # bytes of the jmp instruction and not the larger context of + # where this function is. Also: these will always match 100% + # because we are searching for a match to register this as a + # function in the first place. + self._db.skip_compare(thunk_from_orig) + + def _compare_function(self, match: MatchInfo) -> DiffReport: + if match.size == 0: + # Report a failed match to make the user aware of the empty function. + return DiffReport( + match_type=SymbolType.FUNCTION, + orig_addr=match.orig_addr, + recomp_addr=match.recomp_addr, + name=match.name, + ) + + orig_raw = self.orig_bin.read(match.orig_addr, match.size) + recomp_raw = self.recomp_bin.read(match.recomp_addr, match.size) + + def orig_should_replace(addr: int) -> bool: + return addr > self.orig_bin.imagebase and self.orig_bin.is_relocated_addr( + addr + ) + + def recomp_should_replace(addr: int) -> bool: + return ( + addr > self.recomp_bin.imagebase + and self.recomp_bin.is_relocated_addr(addr) + ) + + def orig_lookup(addr: int) -> Optional[str]: + m = self._db.get_by_orig(addr) + if m is None: + return None + + return m.match_name() + + def recomp_lookup(addr: int) -> Optional[str]: + m = self._db.get_by_recomp(addr) + if m is None: + return None + + return m.match_name() + + orig_parse = ParseAsm( + relocate_lookup=orig_should_replace, name_lookup=orig_lookup + ) + recomp_parse = ParseAsm( + relocate_lookup=recomp_should_replace, name_lookup=recomp_lookup + ) + + orig_asm = orig_parse.parse_asm(orig_raw, match.orig_addr) + recomp_asm = recomp_parse.parse_asm(recomp_raw, match.recomp_addr) + + diff = difflib.SequenceMatcher(None, orig_asm, recomp_asm) + ratio = diff.ratio() + + if ratio != 1.0: + # Check whether we can resolve register swaps which are actually + # perfect matches modulo compiler entropy. + is_effective_match = can_resolve_register_differences(orig_asm, recomp_asm) + unified_diff = difflib.unified_diff(orig_asm, recomp_asm, n=10) + else: + is_effective_match = False + unified_diff = [] + + return DiffReport( + 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_functions(self) -> List[MatchInfo]: - return self._db.get_matches(SymbolType.FUNCTION) + return self._db.get_matches_by_type(SymbolType.FUNCTION) - def compare_functions(self): - pass + 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 @@ -145,5 +411,6 @@ def compare_pointers(self): def compare_strings(self): pass - def compare_vtables(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 index 850f25fd..43d6811b 100644 --- a/tools/isledecomp/isledecomp/compare/db.py +++ b/tools/isledecomp/isledecomp/compare/db.py @@ -2,7 +2,6 @@ addresses/symbols that we want to compare between the original and recompiled binaries.""" import sqlite3 import logging -from collections import namedtuple from typing import List, Optional from isledecomp.types import SymbolType @@ -16,12 +15,36 @@ size int, should_skip int default(FALSE) ); + CREATE INDEX `symbols_or` ON `symbols` (orig_addr); CREATE INDEX `symbols_re` ON `symbols` (recomp_addr); - CREATE INDEX `symbols_na` ON `symbols` (compare_type, name); """ -MatchInfo = namedtuple("MatchInfo", "orig_addr, recomp_addr, size, name") +class MatchInfo: + def __init__( + self, + ctype: Optional[int], + orig: Optional[int], + recomp: Optional[int], + name: Optional[str], + size: Optional[int], + ) -> None: + self.compare_type = SymbolType(ctype) if ctype is not None else None + self.orig_addr = orig + self.recomp_addr = recomp + self.name = name + self.size = size + + def match_name(self) -> str: + """Combination of the name and compare type. + Intended for name substitution in the diff. If there is a diff, + it will be more obvious what this symbol indicates.""" + if self.name is None: + return None + + ctype = self.compare_type.name if self.compare_type is not None else "UNK" + name = repr(self.name) if ctype == "STRING" else self.name + return f"{name} ({ctype})" def matchinfo_factory(_, row): @@ -59,24 +82,58 @@ def get_unmatched_strings(self) -> List[str]: return [string for (string,) in cur.fetchall()] - def get_one_function(self, addr: int) -> Optional[MatchInfo]: + def get_matches(self) -> Optional[MatchInfo]: cur = self._db.execute( - """SELECT orig_addr, recomp_addr, size, name + """SELECT compare_type, orig_addr, recomp_addr, name, size FROM `symbols` - WHERE compare_type = ? - AND orig_addr = ? + WHERE orig_addr IS NOT NULL AND recomp_addr IS NOT NULL AND should_skip IS FALSE ORDER BY orig_addr """, - (SymbolType.FUNCTION.value, 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_matches(self, compare_type: SymbolType) -> List[MatchInfo]: + def get_by_orig(self, addr: int) -> Optional[MatchInfo]: cur = self._db.execute( - """SELECT orig_addr, recomp_addr, size, name + """SELECT compare_type, orig_addr, recomp_addr, name, size + FROM `symbols` + WHERE 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 @@ -90,14 +147,20 @@ def get_matches(self, compare_type: SymbolType) -> List[MatchInfo]: return cur.fetchall() - def set_function_pair(self, orig: int, recomp: int) -> bool: - """For lineref match or _entry""" + def set_pair( + self, orig: int, recomp: int, compare_type: Optional[SymbolType] = None + ) -> bool: + compare_value = compare_type.value if compare_type is not None else None cur = self._db.execute( "UPDATE `symbols` SET orig_addr = ?, compare_type = ? WHERE recomp_addr = ?", - (orig, SymbolType.FUNCTION.value, recomp), + (orig, compare_value, recomp), ) return cur.rowcount > 0 + + def set_function_pair(self, orig: int, recomp: int) -> bool: + """For lineref match or _entry""" + self.set_pair(orig, recomp, SymbolType.FUNCTION) # TODO: Both ways required? def skip_compare(self, orig: int): @@ -107,6 +170,12 @@ def skip_compare(self, orig: int): 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` @@ -147,3 +216,5 @@ def match_string(self, addr: int, value: str) -> bool: if not did_match: escaped = repr(value) logger.error("Failed to find string: %s", escaped) + + return did_match diff --git a/tools/isledecomp/isledecomp/cvdump/analysis.py b/tools/isledecomp/isledecomp/cvdump/analysis.py index 720593be..330429dd 100644 --- a/tools/isledecomp/isledecomp/cvdump/analysis.py +++ b/tools/isledecomp/isledecomp/cvdump/analysis.py @@ -94,7 +94,11 @@ def set_decorated(self, name: str): def name(self) -> Optional[str]: """Prefer "friendly" name if we have it. This is what we have been using to match functions.""" - return self.friendly_name or self.decorated_name + return ( + self.friendly_name + if self.friendly_name is not None + else self.decorated_name + ) def size(self) -> Optional[int]: if self.confirmed_size is not None: diff --git a/tools/isledecomp/isledecomp/cvdump/demangler.py b/tools/isledecomp/isledecomp/cvdump/demangler.py index 340f19a3..07fca42f 100644 --- a/tools/isledecomp/isledecomp/cvdump/demangler.py +++ b/tools/isledecomp/isledecomp/cvdump/demangler.py @@ -4,6 +4,7 @@ """ import re from collections import namedtuple +from typing import Optional class InvalidEncodedNumberError(Exception): @@ -30,13 +31,12 @@ def parse_encoded_number(string: str) -> int: StringConstInfo = namedtuple("StringConstInfo", "len is_utf16") -def demangle_string_const(symbol: str) -> StringConstInfo: +def demangle_string_const(symbol: str) -> Optional[StringConstInfo]: """Don't bother to decode the string text from the symbol. We can just read it from the binary once we have the length.""" match = string_const_regex.match(symbol) if match is None: - # See below - return StringConstInfo(0, False) + return None try: strlen = ( @@ -45,10 +45,7 @@ def demangle_string_const(symbol: str) -> StringConstInfo: else int(match.group("len")) ) except (ValueError, InvalidEncodedNumberError): - # This would be an annoying error to fail on if we get a bad symbol. - # For now, just assume a zero length string because this will probably - # raise some eyebrows during the comparison. - strlen = 0 + return None is_utf16 = match.group("is_utf16") == "1" return StringConstInfo(len=strlen, is_utf16=is_utf16) diff --git a/tools/isledecomp/isledecomp/cvdump/parser.py b/tools/isledecomp/isledecomp/cvdump/parser.py index 613cd4a4..d14abe88 100644 --- a/tools/isledecomp/isledecomp/cvdump/parser.py +++ b/tools/isledecomp/isledecomp/cvdump/parser.py @@ -36,7 +36,7 @@ # e.g. `S_GDATA32: [0003:000004A4], Type: T_32PRCHAR(0470), g_set` _gdata32_regex = re.compile( - r"S_GDATA32: \[(?P
\w{4}):(?P\w{8})\], Type:\s*(?P\S+), (?P\S+)" + r"S_GDATA32: \[(?P
\w{4}):(?P\w{8})\], Type:\s*(?P\S+), (?P.+)" ) diff --git a/tools/isledecomp/isledecomp/parser/codebase.py b/tools/isledecomp/isledecomp/parser/codebase.py index 54ab4035..184b1256 100644 --- a/tools/isledecomp/isledecomp/parser/codebase.py +++ b/tools/isledecomp/isledecomp/parser/codebase.py @@ -6,6 +6,7 @@ ParserFunction, ParserVtable, ParserVariable, + ParserString, ) @@ -42,3 +43,6 @@ def iter_vtables(self) -> Iterator[ParserVtable]: def iter_variables(self) -> Iterator[ParserVariable]: return filter(lambda s: isinstance(s, ParserVariable), self._symbols) + + def iter_strings(self) -> Iterator[ParserString]: + return filter(lambda s: isinstance(s, ParserString), self._symbols) diff --git a/tools/isledecomp/isledecomp/parser/error.py b/tools/isledecomp/isledecomp/parser/error.py index eb1aa7b8..81123381 100644 --- a/tools/isledecomp/isledecomp/parser/error.py +++ b/tools/isledecomp/isledecomp/parser/error.py @@ -70,6 +70,10 @@ class ParserError(Enum): # a comment -- i.e. VTABLE or GLOBAL -- could not extract the name NO_SUITABLE_NAME = 204 + # ERROR: Two STRING markers have the same module and offset, but the strings + # they annotate are different. + WRONG_STRING = 205 + @dataclass class ParserAlert: diff --git a/tools/isledecomp/isledecomp/parser/linter.py b/tools/isledecomp/isledecomp/parser/linter.py index 54406ce9..b44487df 100644 --- a/tools/isledecomp/isledecomp/parser/linter.py +++ b/tools/isledecomp/isledecomp/parser/linter.py @@ -1,7 +1,7 @@ from typing import List, Optional from .parser import DecompParser from .error import ParserAlert, ParserError -from .node import ParserSymbol +from .node import ParserSymbol, ParserString def get_checkorder_filter(module): @@ -19,6 +19,9 @@ def __init__(self) -> None: # This is _not_ reset between files and is intended to report offset reuse # when scanning the entire directory. self._offsets_used = set() + # Keep track of strings we have seen. Persists across files. + # Module/offset can be repeated for string markers but the strings must match. + self._strings = {} def reset(self, full_reset: bool = False): self.alerts = [] @@ -28,6 +31,7 @@ def reset(self, full_reset: bool = False): if full_reset: self._offsets_used.clear() + self._strings = {} def file_is_header(self): return self._filename.lower().endswith(".h") @@ -36,17 +40,31 @@ def _load_offsets_from_list(self, marker_list: List[ParserSymbol]): """Helper for loading (module, offset) tuples while the DecompParser has them broken up into three different lists.""" for marker in marker_list: + is_string = isinstance(marker, ParserString) + value = (marker.module, marker.offset) if value in self._offsets_used: - self.alerts.append( - ParserAlert( - code=ParserError.DUPLICATE_OFFSET, - line_number=marker.line_number, - line=f"0x{marker.offset:08x}", + if is_string: + if self._strings[value] != marker.name: + self.alerts.append( + ParserAlert( + code=ParserError.WRONG_STRING, + line_number=marker.line_number, + line=f"0x{marker.offset:08x}, {repr(self._strings[value])} vs. {repr(marker.name)}", + ) + ) + else: + self.alerts.append( + ParserAlert( + code=ParserError.DUPLICATE_OFFSET, + line_number=marker.line_number, + line=f"0x{marker.offset:08x}", + ) ) - ) else: self._offsets_used.add(value) + if is_string: + self._strings[value] = marker.name def _check_function_order(self): """Rules: @@ -82,6 +100,7 @@ def _check_offset_uniqueness(self): self._load_offsets_from_list(self._parser.functions) self._load_offsets_from_list(self._parser.vtables) self._load_offsets_from_list(self._parser.variables) + self._load_offsets_from_list(self._parser.strings) def _check_byname_allowed(self): if self.file_is_header(): diff --git a/tools/isledecomp/isledecomp/parser/marker.py b/tools/isledecomp/isledecomp/parser/marker.py index d2e181dd..de8c6f05 100644 --- a/tools/isledecomp/isledecomp/parser/marker.py +++ b/tools/isledecomp/isledecomp/parser/marker.py @@ -3,6 +3,19 @@ from enum import Enum +class MarkerCategory(Enum): + """For the purposes of grouping multiple different DecompMarkers together, + assign a rough "category" for the MarkerType values below. + It's really only the function types that have to get folded down, but + we'll do that in a structured way to permit future expansion.""" + + FUNCTION = 1 + VARIABLE = 2 + STRING = 3 + VTABLE = 4 + ADDRESS = 100 # i.e. no comparison required or possible + + class MarkerType(Enum): UNKNOWN = -100 FUNCTION = 1 @@ -51,6 +64,23 @@ def module(self) -> str: def offset(self) -> int: return self._offset + @property + def category(self) -> MarkerCategory: + if self.is_vtable(): + return MarkerCategory.VTABLE + + if self.is_variable(): + return MarkerCategory.VARIABLE + + if self.is_string(): + return MarkerCategory.STRING + + # TODO: worth another look if we add more types, but this covers it + if self.is_regular_function() or self.is_explicit_byname(): + return MarkerCategory.FUNCTION + + return MarkerCategory.ADDRESS + def is_regular_function(self) -> bool: """Regular function, meaning: not an explicit byname lookup. FUNCTION markers can be _implicit_ byname. diff --git a/tools/isledecomp/isledecomp/parser/node.py b/tools/isledecomp/isledecomp/parser/node.py index b6561fd6..71d4ebdd 100644 --- a/tools/isledecomp/isledecomp/parser/node.py +++ b/tools/isledecomp/isledecomp/parser/node.py @@ -55,3 +55,8 @@ class ParserVariable(ParserSymbol): @dataclass class ParserVtable(ParserSymbol): pass + + +@dataclass +class ParserString(ParserSymbol): + pass diff --git a/tools/isledecomp/isledecomp/parser/parser.py b/tools/isledecomp/isledecomp/parser/parser.py index d4153b3c..3c955fc3 100644 --- a/tools/isledecomp/isledecomp/parser/parser.py +++ b/tools/isledecomp/isledecomp/parser/parser.py @@ -3,11 +3,11 @@ from typing import List, Iterable, Iterator, Optional from enum import Enum from .util import ( - is_blank_or_comment, get_class_name, get_variable_name, get_synthetic_name, remove_trailing_comment, + get_string_contents, ) from .marker import ( DecompMarker, @@ -19,6 +19,7 @@ ParserFunction, ParserVariable, ParserVtable, + ParserString, ) from .error import ParserAlert, ParserError @@ -43,17 +44,16 @@ def __init__(self) -> None: def insert(self, marker: DecompMarker) -> bool: """Return True if this insert would overwrite""" - module = marker.module - if module in self.markers: + key = (marker.category, marker.module) + if key in self.markers: return True - # TODO: type converted back to string version here instead of using enum - self.markers[module] = (marker.type.name, marker.offset) + self.markers[key] = marker return False def iter(self) -> Iterator[DecompMarker]: - for module, (marker_type, offset) in self.markers.items(): - yield DecompMarker(marker_type, module, offset) + for _, marker in self.markers.items(): + yield marker def empty(self): self.markers = {} @@ -111,17 +111,21 @@ def reset(self): self.function_sig = "" @property - def functions(self) -> List[ParserSymbol]: + def functions(self) -> List[ParserFunction]: return [s for s in self._symbols if isinstance(s, ParserFunction)] @property - def vtables(self) -> List[ParserSymbol]: + def vtables(self) -> List[ParserVtable]: return [s for s in self._symbols if isinstance(s, ParserVtable)] @property - def variables(self) -> List[ParserSymbol]: + def variables(self) -> List[ParserVariable]: return [s for s in self._symbols if isinstance(s, ParserVariable)] + @property + def strings(self) -> List[ParserString]: + return [s for s in self._symbols if isinstance(s, ParserString)] + def iter_symbols(self, module: Optional[str] = None) -> Iterator[ParserSymbol]: for s in self._symbols: if module is None or s.module == module: @@ -225,21 +229,35 @@ def _variable_marker(self, marker: DecompMarker): else: self.state = ReaderState.IN_GLOBAL - def _variable_done(self, name: str): - if not name.startswith("g_"): - self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) + def _variable_done( + self, variable_name: Optional[str] = None, string_value: Optional[str] = None + ): + if variable_name is None and string_value is None: + self._syntax_error(ParserError.NO_SUITABLE_NAME) + return for marker in self.var_markers.iter(): - self._symbols.append( - ParserVariable( - type=marker.type, - line_number=self.line_number, - module=marker.module, - offset=marker.offset, - name=name, - is_static=self.state == ReaderState.IN_FUNC_GLOBAL, + if marker.is_string(): + self._symbols.append( + ParserString( + type=marker.type, + line_number=self.line_number, + module=marker.module, + offset=marker.offset, + name=string_value, + ) + ) + else: + self._symbols.append( + ParserVariable( + type=marker.type, + line_number=self.line_number, + module=marker.module, + offset=marker.offset, + name=variable_name, + is_static=self.state == ReaderState.IN_FUNC_GLOBAL, + ) ) - ) self.var_markers.empty() if self.state == ReaderState.IN_FUNC_GLOBAL: @@ -298,20 +316,8 @@ def _handle_marker(self, marker: DecompMarker): else: self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - elif marker.is_string(): - # TODO: We are ignoring string markers for the moment. - # We already have a lot of them in the codebase, though, so we'll - # hang onto them for now in case we can use them later. - # To match up string constants, the strategy will be: - # 1. Use cvdump to find all string constants in the recomp - # 2. In the original binary, look at relocated vaddrs from .rdata - # 3. Try to match up string data from #1 with locations in #2 - - # Throw the syntax error we would throw if we were parsing these - if self.state not in (ReaderState.SEARCH, ReaderState.IN_FUNC): - self._syntax_error(ParserError.INCOMPATIBLE_MARKER) - - elif marker.is_variable(): + # Strings and variables are almost the same thing + elif marker.is_string() or marker.is_variable(): if self.state in ( ReaderState.SEARCH, ReaderState.IN_GLOBAL, @@ -418,24 +424,39 @@ def read_line(self, line: str): # function we have already parsed if state == IN_FUNC_GLOBAL. # However, we are not tolerant of _any_ syntax problems in our # CI actions, so the solution is to just fix the invalid marker. - if is_blank_or_comment(line): - self._syntax_error(ParserError.NO_SUITABLE_NAME) + variable_name = None + + global_markers_queued = any( + m.is_variable() for m in self.var_markers.iter() + ) + + if len(line_strip) == 0: + self._syntax_warning(ParserError.UNEXPECTED_BLANK_LINE) return - # We don't have a foolproof mechanism to tell what is and is not a variable. - # If the GLOBAL is being declared on a `return` statement, though, this is - # not correct. It is either a string literal (which will be handled differently) - # or it is not the variable declaration, which is incorrect decomp syntax. - if line.strip().startswith("return"): - self._syntax_error(ParserError.GLOBAL_NOT_VARIABLE) - return + if global_markers_queued: + # Not the greatest solution, but a consequence of combining GLOBAL and + # STRING markers together. If the marker precedes a return statement, it is + # valid for a STRING marker to be here, but not a GLOBAL. We need to look + # ahead and tell whether this *would* fail. + if line_strip.startswith("return"): + self._syntax_error(ParserError.GLOBAL_NOT_VARIABLE) + return + if line_strip.startswith("//"): + # If we found a comment, assume implicit lookup-by-name + # function and end here. We know this is not a decomp marker + # because it would have been handled already. + variable_name = get_synthetic_name(line) + else: + variable_name = get_variable_name(line) + # This is out of our control for library variables, but all of our + # variables should start with "g_". + if variable_name is not None and not variable_name.startswith("g_"): + self._syntax_warning(ParserError.GLOBAL_MISSING_PREFIX) - name = get_variable_name(line) - if name is None: - self._syntax_error(ParserError.NO_SUITABLE_NAME) - return + string_name = get_string_contents(line) - self._variable_done(name) + self._variable_done(variable_name, string_name) elif self.state == ReaderState.IN_VTABLE: vtable_class = get_class_name(line) diff --git a/tools/isledecomp/isledecomp/parser/util.py b/tools/isledecomp/isledecomp/parser/util.py index a106d841..dd90fd03 100644 --- a/tools/isledecomp/isledecomp/parser/util.py +++ b/tools/isledecomp/isledecomp/parser/util.py @@ -1,6 +1,7 @@ # C++ Parser utility functions and data structures import re from typing import Optional +from ast import literal_eval # The goal here is to just read whatever is on the next line, so some # flexibility in the formatting seems OK @@ -12,6 +13,10 @@ trailingCommentRegex = re.compile(r"(\s*(?://|/\*).*)$") +# Get string contents, ignore escape characters that might interfere +doubleQuoteRegex = re.compile(r"(\"(?:[^\"\\]|\\.)*\")") + + def get_synthetic_name(line: str) -> Optional[str]: """Synthetic names appear on a single line comment on the line after the marker. If that's not what we have, return None""" @@ -86,3 +91,20 @@ def get_variable_name(line: str) -> Optional[str]: return match.group("name") return None + + +def get_string_contents(line: str) -> Optional[str]: + """Return the first C string seen on this line. + We have to unescape the string, and a simple way to do that is to use + python's ast.literal_eval. I'm sure there are many pitfalls to doing + it this way, but hopefully the regex will ensure reasonably sane input.""" + + try: + if (match := doubleQuoteRegex.search(line)) is not None: + return literal_eval(match.group(1)) + # pylint: disable=broad-exception-caught + # No way to predict what kind of exception could occur. + except Exception: + pass + + return None diff --git a/tools/isledecomp/isledecomp/utils.py b/tools/isledecomp/isledecomp/utils.py index ce4896fd..637eee33 100644 --- a/tools/isledecomp/isledecomp/utils.py +++ b/tools/isledecomp/isledecomp/utils.py @@ -26,17 +26,3 @@ def print_diff(udiff, plain): def get_file_in_script_dir(fn): return os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), fn) - - -class OffsetPlaceholderGenerator: - def __init__(self): - self.counter = 0 - self.replacements = {} - - def get(self, replace_addr): - if replace_addr in self.replacements: - return self.replacements[replace_addr] - self.counter += 1 - replacement = f"" - self.replacements[replace_addr] = replacement - return replacement diff --git a/tools/isledecomp/tests/test_demangler.py b/tools/isledecomp/tests/test_demangler.py index 5343bdcc..32cac502 100644 --- a/tools/isledecomp/tests/test_demangler.py +++ b/tools/isledecomp/tests/test_demangler.py @@ -14,6 +14,7 @@ 14, True, ), + ("??_C@_00A@?$AA@", 0, False), ] diff --git a/tools/isledecomp/tests/test_linter.py b/tools/isledecomp/tests/test_linter.py index 84ce6495..95d19515 100644 --- a/tools/isledecomp/tests/test_linter.py +++ b/tools/isledecomp/tests/test_linter.py @@ -112,3 +112,33 @@ def test_duplicate_offsets(linter): # Full reset will forget seen offsets. linter.reset(True) assert linter.check_lines(lines, "test.h", "TEST") is True + + +def test_duplicate_strings(linter): + """Duplicate string markers are okay if the string value is the same.""" + string_lines = [ + "// STRING: TEST 0x1000", + 'return "hello world";', + ] + + # No problem to use this marker twice. + assert linter.check_lines(string_lines, "test.h", "TEST") is True + assert linter.check_lines(string_lines, "test.h", "TEST") is True + + different_string = [ + "// STRING: TEST 0x1000", + 'return "hi there";', + ] + + # Same address but the string is different + assert linter.check_lines(different_string, "greeting.h", "TEST") is False + assert len(linter.alerts) == 1 + assert linter.alerts[0].code == ParserError.WRONG_STRING + + same_addr_reused = [ + "// GLOBAL:TEXT 0x1000", + "int g_test = 123;", + ] + + # This will fail like any other offset reuse. + assert linter.check_lines(same_addr_reused, "other.h", "TEST") is False diff --git a/tools/isledecomp/tests/test_parser.py b/tools/isledecomp/tests/test_parser.py index 853e773d..6d8b72b1 100644 --- a/tools/isledecomp/tests/test_parser.py +++ b/tools/isledecomp/tests/test_parser.py @@ -442,3 +442,82 @@ def test_static_variable(parser): ) assert len(parser.variables) == 2 assert parser.variables[1].is_static is True + + +def test_reject_global_return(parser): + """Previously we had annotated strings with the GLOBAL marker. + For example: if a function returned a string. We now want these to be + annotated with the STRING marker.""" + + parser.read_lines( + [ + "// FUNCTION: TEST 0x5555", + "void test_function() {", + " // GLOBAL: TEST 0x8888", + ' return "test";', + "}", + ] + ) + assert len(parser.variables) == 0 + assert len(parser.alerts) == 1 + assert parser.alerts[0].code == ParserError.GLOBAL_NOT_VARIABLE + + +def test_global_string(parser): + """We now allow GLOBAL and STRING markers for the same item.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "// STRING: TEXT 0x5555", + 'char* g_test = "hello";', + ] + ) + assert len(parser.variables) == 1 + assert len(parser.strings) == 1 + assert len(parser.alerts) == 0 + + assert parser.variables[0].name == "g_test" + assert parser.strings[0].name == "hello" + + +def test_comment_variables(parser): + """Match on hidden variables from libraries.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "// g_test", + ] + ) + assert len(parser.variables) == 1 + assert parser.variables[0].name == "g_test" + + +def test_flexible_variable_prefix(parser): + """Don't alert to library variables that lack the g_ prefix. + This is out of our control.""" + + parser.read_lines( + [ + "// GLOBAL: TEST 0x1234", + "// some_other_variable", + ] + ) + assert len(parser.variables) == 1 + assert len(parser.alerts) == 0 + assert parser.variables[0].name == "some_other_variable" + + +def test_string_ignore_g_prefix(parser): + """String annotations above a regular variable should not alert to + the missing g_ prefix. This is only required for GLOBAL markers.""" + + parser.read_lines( + [ + "// STRING: TEST 0x1234", + 'const char* value = "";', + ] + ) + assert len(parser.strings) == 1 + assert len(parser.alerts) == 0 diff --git a/tools/isledecomp/tests/test_parser_statechange.py b/tools/isledecomp/tests/test_parser_statechange.py index cb54cf0a..be37e3c8 100644 --- a/tools/isledecomp/tests/test_parser_statechange.py +++ b/tools/isledecomp/tests/test_parser_statechange.py @@ -15,7 +15,7 @@ (_rs.SEARCH, "TEMPLATE", _rs.IN_TEMPLATE, None), (_rs.SEARCH, "VTABLE", _rs.IN_VTABLE, None), (_rs.SEARCH, "LIBRARY", _rs.IN_LIBRARY, None), - (_rs.SEARCH, "STRING", _rs.SEARCH, None), + (_rs.SEARCH, "STRING", _rs.IN_GLOBAL, None), (_rs.WANT_SIG, "FUNCTION", _rs.WANT_SIG, None), (_rs.WANT_SIG, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -33,7 +33,7 @@ (_rs.IN_FUNC, "TEMPLATE", _rs.IN_TEMPLATE, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "VTABLE", _rs.IN_VTABLE, _pe.MISSED_END_OF_FUNCTION), (_rs.IN_FUNC, "LIBRARY", _rs.IN_LIBRARY, _pe.MISSED_END_OF_FUNCTION), - (_rs.IN_FUNC, "STRING", _rs.IN_FUNC, None), + (_rs.IN_FUNC, "STRING", _rs.IN_FUNC_GLOBAL, None), (_rs.IN_TEMPLATE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_TEMPLATE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), @@ -60,7 +60,7 @@ (_rs.IN_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), - (_rs.IN_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_GLOBAL, "STRING", _rs.IN_GLOBAL, None), (_rs.IN_FUNC_GLOBAL, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "GLOBAL", _rs.IN_FUNC_GLOBAL, None), @@ -69,7 +69,7 @@ (_rs.IN_FUNC_GLOBAL, "TEMPLATE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "VTABLE", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_FUNC_GLOBAL, "LIBRARY", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), - (_rs.IN_FUNC_GLOBAL, "STRING", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), + (_rs.IN_FUNC_GLOBAL, "STRING", _rs.IN_FUNC_GLOBAL, None), (_rs.IN_VTABLE, "FUNCTION", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), (_rs.IN_VTABLE, "GLOBAL", _rs.SEARCH, _pe.INCOMPATIBLE_MARKER), diff --git a/tools/isledecomp/tests/test_parser_util.py b/tools/isledecomp/tests/test_parser_util.py index af102fc2..8a403710 100644 --- a/tools/isledecomp/tests/test_parser_util.py +++ b/tools/isledecomp/tests/test_parser_util.py @@ -10,6 +10,7 @@ is_blank_or_comment, get_class_name, get_variable_name, + get_string_contents, ) @@ -158,3 +159,18 @@ def test_get_class_name_none(line: str): @pytest.mark.parametrize("line,name", variable_name_cases) def test_get_variable_name(line: str, name: str): assert get_variable_name(line) == name + + +string_match_cases = [ + ('return "hello world";', "hello world"), + ('"hello\\\\"', "hello\\"), + ('"hello \\"world\\""', 'hello "world"'), + ('"hello\\nworld"', "hello\nworld"), + # Only match first string if there are multiple options + ('Method("hello", "world");', "hello"), +] + + +@pytest.mark.parametrize("line, string", string_match_cases) +def test_get_string_contents(line: str, string: str): + assert get_string_contents(line) == string diff --git a/tools/isledecomp/tests/test_sanitize.py b/tools/isledecomp/tests/test_sanitize.py new file mode 100644 index 00000000..67d95b4f --- /dev/null +++ b/tools/isledecomp/tests/test_sanitize.py @@ -0,0 +1,179 @@ +from typing import Optional +import pytest +from isledecomp.compare.asm.parse import DisasmLiteInst, ParseAsm + + +def mock_inst(mnemonic: str, op_str: str) -> DisasmLiteInst: + """Mock up the named tuple DisasmLite from just a mnemonic and op_str. + To be used for tests on sanitize that do not require the instruction address + or size. i.e. any non-jump instruction.""" + return DisasmLiteInst(0, 0, mnemonic, op_str) + + +identity_cases = [ + ("", ""), + ("sti", ""), + ("push", "ebx"), + ("ret", ""), + ("ret", "4"), + ("mov", "eax, 0x1234"), +] + + +@pytest.mark.parametrize("mnemonic, op_str", identity_cases) +def test_identity(mnemonic, op_str): + """Confirm that nothing is substituted.""" + p = ParseAsm() + inst = mock_inst(mnemonic, op_str) + result = p.sanitize(inst) + assert result == (mnemonic, op_str) + + +ptr_replace_cases = [ + ("byte ptr [0x5555]", "byte ptr []"), + ("word ptr [0x5555]", "word ptr []"), + ("dword ptr [0x5555]", "dword ptr []"), + ("qword ptr [0x5555]", "qword ptr []"), + ("eax, dword ptr [0x5555]", "eax, dword ptr []"), + ("dword ptr [0x5555], eax", "dword ptr [], eax"), + ("dword ptr [0x5555], 0", "dword ptr [], 0"), + ("dword ptr [0x5555], 8", "dword ptr [], 8"), + # Same value, assumed to be an addr in the first appearance + # because it is designated as 'ptr', but we have not provided the + # relocation table lookup method so we do not replace the second appearance. + ("dword ptr [0x5555], 0x5555", "dword ptr [], 0x5555"), +] + + +@pytest.mark.parametrize("start, end", ptr_replace_cases) +def test_ptr_replace(start, end): + """Anything in square brackets (with the 'ptr' prefix) will always be replaced.""" + p = ParseAsm() + inst = mock_inst("", start) + (_, op_str) = p.sanitize(inst) + assert op_str == end + + +call_replace_cases = [ + ("ebx", "ebx"), + ("0x1234", ""), + ("dword ptr [0x1234]", "dword ptr []"), + ("dword ptr [ecx + 0x10]", "dword ptr [ecx + 0x10]"), +] + + +@pytest.mark.parametrize("start, end", call_replace_cases) +def test_call_replace(start, end): + """Call with hex operand is always replaced. + Otherwise, ptr replacement rules apply, but skip `this` calls.""" + p = ParseAsm() + inst = mock_inst("call", start) + (_, op_str) = p.sanitize(inst) + assert op_str == end + + +def test_jump_displacement(): + """Display jump displacement (offset from end of jump instruction) + instead of destination address.""" + p = ParseAsm() + inst = DisasmLiteInst(0x1000, 2, "je", "0x1000") + (_, op_str) = p.sanitize(inst) + assert op_str == "-0x2" + + +@pytest.mark.xfail(reason="Not implemented yet") +def test_jmp_table(): + """Should detect the characteristic jump table instruction + (for a switch statement) and use placeholder.""" + p = ParseAsm() + inst = mock_inst("jmp", "dword ptr [eax*4 + 0x5555]") + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr [eax*4 + ]" + + +name_replace_cases = [ + ("byte ptr [0x5555]", "byte ptr [_substitute_]"), + ("word ptr [0x5555]", "word ptr [_substitute_]"), + ("dword ptr [0x5555]", "dword ptr [_substitute_]"), + ("qword ptr [0x5555]", "qword ptr [_substitute_]"), +] + + +@pytest.mark.parametrize("start, end", name_replace_cases) +def test_name_replace(start, end): + """Make sure the name lookup function is called if present""" + + def substitute(_: int) -> str: + return "_substitute_" + + p = ParseAsm(name_lookup=substitute) + inst = mock_inst("mov", start) + (_, op_str) = p.sanitize(inst) + assert op_str == end + + +def test_replacement_cache(): + p = ParseAsm() + inst = mock_inst("inc", "dword ptr [0x1234]") + + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr []" + + (_, op_str) = p.sanitize(inst) + assert op_str == "dword ptr []" + + +def test_replacement_numbering(): + """If we can use the name lookup for the first address but not the second, + the second replacement should be not .""" + + def substitute_1234(addr: int) -> Optional[str]: + return "_substitute_" if addr == 0x1234 else None + + p = ParseAsm(name_lookup=substitute_1234) + + (_, op_str) = p.sanitize(mock_inst("inc", "dword ptr [0x1234]")) + assert op_str == "dword ptr [_substitute_]" + + (_, op_str) = p.sanitize(mock_inst("inc", "dword ptr [0x5555]")) + assert op_str == "dword ptr []" + + +def test_relocate_lookup(): + """Immediate values would be relocated if they are actually addresses. + So we can use the relocation table to check whether a given value is an + address or just some number.""" + + def relocate_lookup(addr: int) -> bool: + return addr == 0x1234 + + p = ParseAsm(relocate_lookup=relocate_lookup) + (_, op_str) = p.sanitize(mock_inst("mov", "eax, 0x1234")) + assert op_str == "eax, " + + (_, op_str) = p.sanitize(mock_inst("mov", "eax, 0x5555")) + assert op_str == "eax, 0x5555" + + +def test_jump_to_function(): + """A jmp instruction can lead us directly to a function. This can be found + in the unwind section at the end of a function. However: we do not want to + assume this is the case for all jumps. Only replace the jump with a name + if we can find it using our lookup.""" + + def substitute_1234(addr: int) -> Optional[str]: + return "_substitute_" if addr == 0x1234 else None + + p = ParseAsm(name_lookup=substitute_1234) + inst = DisasmLiteInst(0x1000, 2, "jmp", "0x1234") + (_, op_str) = p.sanitize(inst) + assert op_str == "_substitute_" + + # Should not replace this jump. + # 0x1000 (start addr) + # + 2 (size of jump instruction) + # + 0x5555 (displacement, the value we want) + # = 0x6557 + inst = DisasmLiteInst(0x1000, 2, "jmp", "0x6557") + (_, op_str) = p.sanitize(inst) + assert op_str == "0x5555" diff --git a/tools/ncc/ncc.style b/tools/ncc/ncc.style index 57bc8dd7..8dc0091b 100644 --- a/tools/ncc/ncc.style +++ b/tools/ncc/ncc.style @@ -1,7 +1,7 @@ ClassName: '^[A-Z][a-zA-Z0-9]+$' CppMethod: '^operator|^FUN_[a-f0-9]{8}$|^VTable0x[a-f0-9]{1,8}$|^(?!VTable)[A-Z][a-zA-Z0-9]+$' -# EnumConstantName EnumName: '^\(unnamed|^[A-Z][a-zA-Z0-9]+$' +EnumConstantName: '^(c_|e_)[a-z][a-zA-Z0-9]+$' FunctionName: '^operator|^FUN_[a-f0-9]{8}$|^VTable0x[a-f0-9]{1,8}$|^(?!VTable)[A-Z][a-zA-Z0-9]+$' ParameterName: '^p_(unk0x[a-f0-9]{1,8}$|(?!unk)[a-z][a-zA-Z0-9]*)$|^$' StructName: '^\(anon|^\(unnamed|^[A-Z][a-zA-Z0-9]+$' diff --git a/tools/ncc/skip.yml b/tools/ncc/skip.yml index fa8546d9..ec7f46a0 100644 --- a/tools/ncc/skip.yml +++ b/tools/ncc/skip.yml @@ -12,6 +12,7 @@ m_HWDesc: 'Allow this variable name' m_HELDesc: 'Allow this variable name' p_HWDesc: 'Allow this variable name' p_HELDesc: 'Allow this variable name' +e_RAMStream: 'Allow this enum constant' p_milliseconds: 'Probably a bug with function call' m_increaseAmount: "Can't currently detect member in union" -m_increaseFactor: "Can't currently detect member in union" +m_increaseFactor: "Can't currently detect member in union" \ No newline at end of file diff --git a/tools/reccmp/reccmp.py b/tools/reccmp/reccmp.py index b7027435..69783cb2 100755 --- a/tools/reccmp/reccmp.py +++ b/tools/reccmp/reccmp.py @@ -2,167 +2,21 @@ import argparse import base64 -import difflib import json import logging import os -import re from isledecomp import ( Bin, get_file_in_script_dir, - OffsetPlaceholderGenerator, print_diff, ) from isledecomp.compare import Compare as IsleCompare - -from capstone import Cs, CS_ARCH_X86, CS_MODE_32 -import colorama +from 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): @@ -197,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.", @@ -226,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( @@ -258,199 +192,105 @@ def main(): args = parser.parse_args() + if not os.path.isfile(args.original): + parser.error(f"Original binary {args.original} does not exist") + + if not os.path.isfile(args.recompiled): + parser.error(f"Recompiled binary {args.recompiled} does not exist") + + if not os.path.isfile(args.pdb): + parser.error(f"Symbols PDB {args.pdb} does not exist") + + if not os.path.isdir(args.decomp_dir): + parser.error(f"Source directory {args.decomp_dir} does not exist") + + return args + + +def main(): + args = parse_args() logging.basicConfig(level=args.loglevel, format="[%(levelname)s] %(message)s") - colorama.init() - - verbose = None - found_verbose_target = False - if args.verbose: - try: - verbose = int(args.verbose, 16) - except ValueError: - parser.error("invalid verbose argument") - html_path = args.html - - plain = args.no_color - - original = args.original - if not os.path.isfile(original): - parser.error(f"Original binary {original} does not exist") - - recomp = args.recompiled - if not os.path.isfile(recomp): - parser.error(f"Recompiled binary {recomp} does not exist") - - syms = args.pdb - if not os.path.isfile(syms): - parser.error(f"Symbols PDB {syms} does not exist") - - source = args.decomp_dir - if not os.path.isdir(source): - parser.error(f"Source directory {source} does not exist") - - svg = args.svg - - with Bin(original, find_str=True) as origfile, Bin(recomp) as recompfile: - if verbose is not None: + with Bin(args.original, find_str=True) as origfile, Bin( + args.recompiled + ) as recompfile: + if args.verbose is not None: # Mute logger events from compare engine logging.getLogger("isledecomp.compare.db").setLevel(logging.CRITICAL) logging.getLogger("isledecomp.compare.lines").setLevel(logging.CRITICAL) - isle_compare = IsleCompare(origfile, recompfile, syms, source) + isle_compare = IsleCompare(origfile, recompfile, args.pdb, args.decomp_dir) print() - capstone_disassembler = Cs(CS_ARCH_X86, CS_MODE_32) + ### Compare one or none. + + if args.verbose is not None: + match = isle_compare.compare_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 = [] - matches = [] - if verbose is not None: - match = isle_compare.get_one_function(verbose) - if match is not None: - found_verbose_target = True - matches = [match] - else: - matches = isle_compare.get_functions() + for match in isle_compare.compare_all(): + print_match_oneline( + match, show_both_addrs=args.print_rec_addr, is_plain=args.no_color + ) - for match in matches: - # The effective_ratio is the ratio when ignoring differing register - # allocation vs the ratio is the true ratio. - ratio = 0.0 - effective_ratio = 0.0 - if match.size: - origasm = parse_asm( - capstone_disassembler, - origfile, - match.orig_addr, - match.size, - ) - recompasm = parse_asm( - capstone_disassembler, - recompfile, - match.recomp_addr, - match.size, + if match.match_type == SymbolType.FUNCTION: + function_count += 1 + total_accuracy += match.ratio + total_effective_accuracy += match.effective_ratio + + # If html, record the diffs to an HTML file + if args.html is not None: + htmlinsert.append( + { + "address": f"0x{match.orig_addr:x}", + "name": match.name, + "matching": match.effective_ratio, + "diff": "\n".join(match.udiff), + } ) - diff = difflib.SequenceMatcher(None, origasm, recompasm) - ratio = diff.ratio() - effective_ratio = ratio + ## Generate files and show summary. - 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 + if args.html is not None: + gen_html(args.html, json.dumps(htmlinsert)) - 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 - ) + implemented_funcs = function_count - if effective_ratio == 1.0 and ratio != 1.0: - if plain: - percenttext += "*" - else: - percenttext += colorama.Fore.RED + "*" + colorama.Style.RESET_ALL + if args.total: + function_count = int(args.total) - if args.print_rec_addr: - addrs = f"0x{match.orig_addr:x} / 0x{match.recomp_addr:x}" - else: - addrs = hex(match.orig_addr) + 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 not verbose: - print( - f" {match.name} ({addrs}) is {percenttext} similar to the original" + 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, ) - function_count += 1 - total_accuracy += ratio - total_effective_accuracy += effective_ratio - - if match.size: - udiff = difflib.unified_diff(origasm, recompasm, n=10) - - # If verbose, print the diff for that function to the output - if verbose: - if effective_ratio == 1.0: - ok_text = ( - "OK!" - if plain - else ( - colorama.Fore.GREEN - + "✨ OK! ✨" - + colorama.Style.RESET_ALL - ) - ) - if ratio == 1.0: - print(f"{addrs}: {match.name} 100% match.\n\n{ok_text}\n\n") - else: - print( - f"{addrs}: {match.name} Effective 100%% match. (Differs in register allocation only)\n\n{ok_text} (still differs in register allocation)\n\n" - ) - else: - print_diff(udiff, plain) - - print( - f"\n{match.name} is only {percenttext} similar to the original, diff above" - ) - - # If html, record the diffs to an HTML file - if html_path: - htmlinsert.append( - { - "address": f"0x{match.orig_addr:x}", - "name": match.name, - "matching": effective_ratio, - "diff": "\n".join(udiff), - } - ) - - if html_path: - gen_html(html_path, json.dumps(htmlinsert)) - - if verbose: - if not found_verbose_target: - print(f"Failed to find the function with address 0x{verbose:x}") - else: - implemented_funcs = function_count - - if args.total: - function_count = int(args.total) - - if function_count > 0: - effective_accuracy = total_effective_accuracy / function_count * 100 - actual_accuracy = total_accuracy / function_count * 100 - print( - f"\nTotal effective accuracy {effective_accuracy:.2f}% across {function_count} functions ({actual_accuracy:.2f}% actual accuracy)" - ) - - if svg: - gen_svg( - svg, - os.path.basename(original), - args.svg_icon, - implemented_funcs, - function_count, - total_effective_accuracy, - ) - if __name__ == "__main__": raise SystemExit(main()) diff --git a/util/compat.h b/util/compat.h index 3c83def6..b38a1c7c 100644 --- a/util/compat.h +++ b/util/compat.h @@ -3,13 +3,13 @@ // Various macros to enable compiling with other/newer compilers. -#ifdef __MINGW32__ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1100) #define COMPAT_MODE #endif // Use `COMPAT_CONST` where something ought to be 'const', and a newer compiler would complain if it // wasn't, but we know it isn't 'const' in the original code. -#ifdef __MINGW32__ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER >= 1100) #define COMPAT_CONST const #else #define COMPAT_CONST diff --git a/util/decomp.h b/util/decomp.h index 4e539eaf..3470fcc3 100644 --- a/util/decomp.h +++ b/util/decomp.h @@ -1,7 +1,7 @@ #ifndef DECOMP_H #define DECOMP_H -#if defined(_MSC_VER) +#if defined(ENABLE_DECOMP_ASSERTS) #define DECOMP_STATIC_ASSERT(V) \ namespace \ { \