Merge remote-tracking branch 'origin/master' into v/arm-instructions

This commit is contained in:
Tyler Wilding
2026-06-14 22:46:53 -04:00
4709 changed files with 408948 additions and 348870 deletions
+8
View File
@@ -0,0 +1,8 @@
13153231
48171810
7569514
6624576
2515356
70249609
5276694
89345505
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
key: linux-ubuntu-22.04--Release-linux-clang-static-${{ github.sha }}
+1
View File
@@ -74,6 +74,7 @@ jobs:
path: |
./jak1*.json
./jak2*.json
./jak3*.json
- name: Log Run ID
run: echo ${{ github.run_id }}
+1 -1
View File
@@ -43,7 +43,7 @@ jobs:
libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
key: linux-ubuntu-22.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+1 -1
View File
@@ -34,7 +34,7 @@ jobs:
sudo update-alternatives --set g++ /usr/bin/g++-10
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
key: linux-ubuntu-22.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+1 -1
View File
@@ -35,7 +35,7 @@ jobs:
fi
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
key: macos-15-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+1 -1
View File
@@ -45,7 +45,7 @@ jobs:
fi
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
key: macos-15-intel-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+159
View File
@@ -0,0 +1,159 @@
name: 🧪 Offline Tests
on:
push:
branches:
- master
pull_request:
branches:
- master
issue_comment:
types: [created]
concurrency:
group: offline-tests
cancel-in-progress: false
# curl -s https://api.github.com/users/<GH_USER_NAME> | jq -r .id
jobs:
validate-author:
name: Verify Permissions
runs-on: self-hosted
if: github.repository == 'open-goal/jak-project'
timeout-minutes: 5
outputs:
trusted: ${{ steps.verify.outputs.trusted }}
sha: ${{ steps.verify.outputs.sha }}
steps:
- id: verify
name: Verify Permissions
if: github.event_name != 'issue_comment' || github.event.issue.pull_request
env:
EVENT: ${{ github.event_name }}
AUTHOR_ID: ${{ github.event.pull_request.user.id }}
COMMENT_ID: ${{ github.event.comment.user.id }}
COMMENT: ${{ github.event.comment.body }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
set -e
mkdir -p ./.tmp-ci
curl -fsSL \
https://raw.githubusercontent.com/open-goal/jak-project/master/.github/offline-allowlist.txt \
-o ./.tmp-ci/allowlist.txt
is_trusted=false
# ---- PUSH: always trusted ----
if [ "$EVENT" = "push" ]; then
echo "push event detected, these are always trusted"
is_trusted=true
SHA="${{ github.sha }}"
# ---- PULL REQUEST: check author ----
elif [ "$EVENT" = "pull_request" ]; then
echo "pull request event detected, these may be trusted if in the allowlist"
SHA="${{ github.event.pull_request.head.sha }}"
if grep -Fxq "$AUTHOR_ID" ./.tmp-ci/allowlist.txt; then
echo "PR author found in the allowlist, it's trusted"
is_trusted=true
else
echo "PR author NOT found in the allowlist"
fi
# ---- ISSUE COMMENT: "ok to test" gate ----
elif [ "$EVENT" = "issue_comment" ]; then
echo "comment event detected, these may be trusted if in the allowlist"
SHA=$(gh api repos/${{ github.repository }}/pulls/$PR_NUMBER --jq '.head.sha')
if [ "$COMMENT" = "ok to test" ] && grep -Fxq "$COMMENT_ID" ./.tmp-ci/allowlist.txt; then
is_trusted=true
fi
fi
echo "trusted=$is_trusted" >> "$GITHUB_OUTPUT"
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
rm -rf ./.tmp-ci
offline-tests:
name: Run Tests
needs: validate-author
if: needs.validate-author.outputs.trusted == 'true' && github.repository == 'open-goal/jak-project'
runs-on: self-hosted
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v4
with:
repository: ${{ github.repository }}
ref: ${{ needs.validate-author.outputs.sha }}
clean: false
- name: Build Binaries
run: |
cmake -B build --preset="Release-linux-clang-static" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build build --target offline-test --target extractor --parallel $(`nproc`)
- name: Build Release
run: |
rm -r ./ci-artifacts || true
mkdir ./ci-artifacts
chmod +x ./.github/scripts/releases/extract_build_unix.sh
PREP_BIN=false ./.github/scripts/releases/extract_build_unix.sh ./ci-artifacts ./build ./
cp ./build/decompiler/extractor ./ci-artifacts
- name: Install Jak 1
run: |
cd ./ci-artifacts
./extractor ~/isos/jak1_ntsc.iso --game jak1 --extract --validate --proj-path "$PWD/data"
./extractor ~/isos/jak1_ntsc.iso --game jak1 --decompile --proj-path "$PWD/data"
./extractor ~/isos/jak1_ntsc.iso --game jak1 --compile --proj-path "$PWD/data"
rm -r ./data/out || true
rm -r ./data/iso_data || true
rm -r ./data/decompiler_out || true
- name: Install Jak 2
run: |
cd ./ci-artifacts
./extractor ~/isos/jak2_ntsc.iso --game jak2 --extract --validate --proj-path "$PWD/data"
./extractor ~/isos/jak2_ntsc.iso --game jak2 --decompile --proj-path "$PWD/data"
./extractor ~/isos/jak2_ntsc.iso --game jak2 --compile --proj-path "$PWD/data"
rm -r ./data/out || true
rm -r ./data/iso_data || true
rm -r ./data/decompiler_out || true
- name: Install Jak 3
run: |
cd ./ci-artifacts
./extractor ~/isos/jak3_ntsc.iso --game jak3 --extract --validate --proj-path "$PWD/data"
./extractor ~/isos/jak3_ntsc.iso --game jak3 --decompile --proj-path "$PWD/data"
./extractor ~/isos/jak3_ntsc.iso --game jak3 --compile --proj-path "$PWD/data"
rm -r ./data/out || true
rm -r ./data/iso_data || true
rm -r ./data/decompiler_out || true
- name: Cleanup Installation
run: |
rm -r ./ci-artifacts || true
- name: Run Offline Tests - Jak 1
run: |
7z x ~/isos/jak1_ntsc.iso -o./iso_data/jak1 -aos
task set-game-jak1
task offline-tests
rm -rf ./iso_data/jak1/*
- name: Run Offline Tests - Jak 2
run: |
7z x ~/isos/jak2_ntsc.iso -o./iso_data/jak2 -aos
task set-game-jak2
task offline-tests
rm -rf ./iso_data/jak2/*
- name: Run Offline Tests - Jak 3
run: |
7z x ~/isos/jak3_ntsc.iso -o./iso_data/jak3 -aos
task set-game-jak3
task offline-tests
rm -rf ./iso_data/jak3/*
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
}
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+1 -1
View File
@@ -31,7 +31,7 @@ jobs:
}
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.22
uses: hendrikmuhs/ccache-action@v1.2.23
with:
variant: sccache
key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+1
View File
@@ -87,3 +87,4 @@ __pycache__/
unifont-15.0.03.ttf
*.diff
goalc-report.html
_new-all-types.gc
+26
View File
@@ -96,6 +96,18 @@
"jak3"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "offline-test.exe (bin\\offline-test.exe)",
"name": "Tests - Offline Tests - Jak X",
"args": [
"--iso_data_path",
"${workspaceRoot}/iso_data/jakx",
"--game",
"jakx"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
@@ -224,6 +236,20 @@
"-debug"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Jak 3 - Runtime (release)",
"args": [
"-v",
"--game",
"jak3",
"--",
"-boot",
"-fakeiso"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
+15
View File
@@ -3,6 +3,21 @@
// For more documentation on how to configure debug tasks,
// see: https://zed.dev/docs/debugger
[
{
"label": "Run Debugger - Jak X",
// "build": "Build - gk",
"program": "$ZED_WORKTREE_ROOT/out/build/Debug/bin/decompiler.exe",
"args": [
"./decompiler/config/jakx/jakx_config.jsonc",
"./iso_data",
"./decompiler_out",
"--version ntsc_v1",
"--config-override",
"{\"decompile_code\": true, \"levels_extract\": false}",
],
"request": "launch",
"adapter": "CodeLLDB",
},
{
"label": "Game - Jak 1 (Windows)",
"build": "Build - gk",
+12 -3
View File
@@ -97,7 +97,7 @@ tasks:
build-debug:
desc: "Build the project using the generated CMake"
cmds:
- "cmake {{.CMAKE_BUILD_DIR_DEBUG}} --parallel 8 --target goalc"
- "cmake {{.CMAKE_BUILD_DIR_DEBUG}} --parallel 8"
repl:
desc: "Start the REPL"
preconditions:
@@ -126,9 +126,18 @@ tasks:
cmds:
- "{{.FORMATTER_BIN_RELEASE_DIR}}/formatter --write --file '{{.FILE}}'"
# DECOMPILING
disasm:
cmds:
- '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler "./decompiler/config/{{.DECOMP_CONFIG}}" "./iso_data" "./decompiler_out" --version "{{.DECOMP_CONFIG_VERSION}}" --config-override ''{"disassemble_code": true, "dump_function_metadata": true, "levels_extract": false}'''
decomp-no-override:
cmds:
- '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler "./decompiler/config/{{.DECOMP_CONFIG}}" "./iso_data" "./decompiler_out" --version "{{.DECOMP_CONFIG_VERSION}}"'
decomp:
cmds:
- '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler "./decompiler/config/{{.DECOMP_CONFIG}}" "./iso_data" "./decompiler_out" --version "{{.DECOMP_CONFIG_VERSION}}" --config-override ''{"decompile_code": true, "levels_extract": false}'''
disasm-file:
cmds:
- '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler "./decompiler/config/{{.DECOMP_CONFIG}}" "./iso_data" "./decompiler_out" --version "{{.DECOMP_CONFIG_VERSION}}" --config-override ''{"disassemble_code": true, "decompile_code": false, "levels_extract": false, "allowed_objects": ["{{.FILE}}"]}'''
decomp-file:
cmds:
- '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler "./decompiler/config/{{.DECOMP_CONFIG}}" "./iso_data" "./decompiler_out" --version "{{.DECOMP_CONFIG_VERSION}}" --config-override ''{"decompile_code": true, "levels_extract": false, "allowed_objects": ["{{.FILE}}"]}'''
@@ -218,12 +227,12 @@ tasks:
- '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test{{.EXE_FILE_EXTENSION}} --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --file {{.FILE}}'
offline-tests-fast:
cmds:
- '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test{{.EXE_FILE_EXTENSION}} --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --pretty-print --num_threads 32 --dump_current_output --fail-on-cmp'
- '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test{{.EXE_FILE_EXTENSION}} --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --pretty-print --num_threads 8 --dump_current_output --fail-on-cmp'
# TODO - amalgamate offline-tests and this task, run twice if the previous step fails
update-ref-tests:
cmds:
- cmd: "{{.PYTHON}} ./scripts/tasks/delete-file-or-folder.py --path failures"
- cmd: '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --pretty-print --num_threads 32 --dump_current_output --fail-on-cmp'
- cmd: '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --pretty-print --num_threads 8 --dump_current_output --fail-on-cmp'
ignore_error: true
- "{{.PYTHON}} ./scripts/update_decomp_reference.py ./failures ./test/decompiler/reference/ --game {{.GAME}}"
- task: offline-tests-fast
+45 -8
View File
@@ -284,16 +284,53 @@ std::vector<ReplaceInfo> replace_info_jak2 = {
{"~Y~3L<FLAG_PART_FILL>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~1L<FLAG_PART_VERT_STRIPE_RIGHT>~]"
"~-1H~Y~3L<FLAG_PART_FILL>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~+26H",
"<FLAG_DENMARK>"},
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-19H~1L<FLAG_PART_VERT_STRIPE_MIDDLE>~Z~-23H~7L<FLAG_PART_VERT_"
"STRIPE_RIGHT>~Z~-23H~7L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~"
"+26H",
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-2H~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-10H~1L<FLAG_PART_VERT_STRIPE_LEFT>~Z~-5H~1L<FLAG_PART_VERT_STRIPE_"
"LEFT>~Z~-23H~7L<FLAG_PART_VERT_STRIPE_RIGHT>~Z~-22H~7L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L"
"<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~+26H",
"<FLAG_NORWAY>"},
{"~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-19H~1L<FLAG_PART_VERT_STRIPE_MIDDLE>~Z~-23H~3L<FLAG_PART_VERT_"
"STRIPE_RIGHT>~Z~-23H~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~"
"+26H",
{"~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-2H~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-10H~1L<FLAG_PART_VERT_STRIPE_LEFT>~Z~-5H~1L<FLAG_PART_VERT_STRIPE_"
"LEFT>~Z~-23H~3L<FLAG_PART_VERT_STRIPE_RIGHT>~Z~-22H~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L"
"<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~+26H",
"<FLAG_ICELAND>"},
{"~Y~6L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+15H~3L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+30H~3L<FLAG_"
"PART_VERT_STRIPE_LARGE>~Z~+4H~+2V~5L<FLAG_PART_KOREA_CIRCLE_FILL>~Z~+47H",
"<FLAG_PORTUGUAL>"},
{"~Y~3L~~~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-2H~Y~3L~~"
"~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_DUTCH>"},
{"~Y~26L<FLAG_PART_FILL>~]~-1H~Y~26L<FLAG_PART_FILL>~Z~-10H~-3V~5L<PAD_PART_DPAD_D>~Z~-10H"
"~+6V~5L<PAD_PART_DPAD_U>~Z~-5H~+1V~5L<PAD_PART_DPAD_L>~Z~-14H~+1V~5L<PAD_PART_DPAD_R>~Z"
"~-11H~+1V~7L<FLAG_PART_KOREA_CIRCLE_FILL>~Z~+26H",
"<FLAG_BRAZIL>"},
{"~Y~3L~~~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~26L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-2H~Y~3L~~"
"~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~26L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_HUNGARY>"},
{"~Y~3L<FLAG_PART_FILL>~Z~5L<FLAG_PART_USA_STRIPES_RIGHT>~]~-2H~Y~3L<FLAG_PART_FILL>~Z~5L"
"<FLAG_PART_USA_STRIPES_RIGHT>~Z~+26H",
"<FLAG_CATALAN>"},
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-5V~3L<FLAG_PART_HORZ_STRIPE"
"_BOTTOM>~]~-2H~+5V~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-5V~3L"
"<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_POLAND>"},
{"~Y~5L~~~Z~26L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-2H~Y~5L~~"
"~Z~26L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_LITHUANIA>"},
{"~Y~1L<FLAG_PART_FILL>~]~-2H~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-5V~3L"
"<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-22H~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-22H~-5V~3L"
"<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-23H~7L<FLAG_PART_VERT_STRIPE_LEFT>~Z~-26H~-3V~7L"
"<PAD_PART_DPAD_D>~Z~+6V~-26H~7L<PAD_PART_DPAD_U>~Z~-21H~+1V~7L<PAD_PART_DPAD_L>~Z~+26H",
"<FLAG_CZECH>"},
{"~Y~3L~~~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-1H~Y~3L~~"
"~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-11H~+2V~3L"
"<FLAG_PART_JAPAN_SUN>~Z~-9H~+2V~1L+~Z~-8V~-8H~7L-~Z~-8V~-3H~7L-~Z~+26H",
"<FLAG_CROATIA>"},
{"~Y~1L<FLAG_PART_FILL>~Z~21L<FLAG_PART_UK_CROSS_LEFT>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>"
"~Z~1L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~21L<FLAG_PART_UK_CROSS_"
"RIGHT>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~-4H~1L<FLAG_PART_VERT_STRIPE_LEFT>~Z~1L~~"
"~Z~-11H~7L<FLAG_PART_KOREA_CIRCLE_FILL>~Z~-8V~-8H~3L-~Z~-8V~-4H~3L-~Z~+26H",
"<FLAG_GALICIA>"},
// korean jamo -- only relevant for the language selection since
// non-korean languages don't run through the `convert-korean-text` function and hence the
+42 -8
View File
@@ -284,20 +284,54 @@ std::vector<ReplaceInfo> replace_info_jak3 = {
{"~Y~3L<FLAG_PART_FILL>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~1L<FLAG_PART_VERT_STRIPE_RIGHT>~]"
"~-1H~Y~3L<FLAG_PART_FILL>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~+26H",
"<FLAG_DENMARK>"},
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-19H~1L<FLAG_PART_VERT_STRIPE_MIDDLE>~Z~-23H~7L<FLAG_PART_VERT_"
"STRIPE_RIGHT>~Z~-23H~7L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~"
"+26H",
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-2H~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-10H~1L<FLAG_PART_VERT_STRIPE_LEFT>~Z~-5H~1L<FLAG_PART_VERT_STRIPE_"
"LEFT>~Z~-23H~7L<FLAG_PART_VERT_STRIPE_RIGHT>~Z~-22H~7L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L"
"<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~+26H",
"<FLAG_NORWAY>"},
{"~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-19H~1L<FLAG_PART_VERT_STRIPE_MIDDLE>~Z~-23H~3L<FLAG_PART_VERT_"
"STRIPE_RIGHT>~Z~-23H~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~"
"+26H",
{"~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_PART_TOP_BOTTOM_STRIPE>~]~-2H~Y~1L<FLAG_PART_FILL>~Z~7L<FLAG_"
"PART_TOP_BOTTOM_STRIPE>~Z~-10H~1L<FLAG_PART_VERT_STRIPE_LEFT>~Z~-5H~1L<FLAG_PART_VERT_STRIPE_"
"LEFT>~Z~-23H~3L<FLAG_PART_VERT_STRIPE_RIGHT>~Z~-22H~3L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L"
"<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~+26H",
"<FLAG_ICELAND>"},
{"~Y~6L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+15H~3L<FLAG_PART_VERT_STRIPE_LARGE>~Z~+30H~3L<FLAG_"
"PART_VERT_STRIPE_LARGE>~Z~+4H~5L<FLAG_PART_PORTUGUAL_1>~Z~+2H~3L<FLAG_PART_PORTUGUAL_2>~Z~+"
"2H~1L<FLAG_PART_PORTUGUAL_3>~Z~+47H",
"<FLAG_PORTUGUAL>"},
{"~Y~3L~~~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-2H~Y~3L~~"
"~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_DUTCH>"},
{"~Y~26L<FLAG_PART_FILL>~]~-1H~Y~26L<FLAG_PART_FILL>~Z~-10H~-3V~5L<PAD_PART_DPAD_D>~Z~-10H"
"~+6V~5L<PAD_PART_DPAD_U>~Z~-5H~+1V~5L<PAD_PART_DPAD_L>~Z~-14H~+1V~5L<PAD_PART_DPAD_R>~Z"
"~-11H~+1V~7L<FLAG_PART_KOREA_CIRCLE_FILL>~Z~+26H",
"<FLAG_BRAZIL>"},
{"~Y~3L~~~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~26L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-2H~Y~3L~~"
"~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~26L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_HUNGARY>"},
{"~Y~3L<FLAG_PART_FILL>~Z~5L<FLAG_PART_USA_STRIPES_RIGHT>~]~-2H~Y~3L<FLAG_PART_FILL>~Z~5L"
"<FLAG_PART_USA_STRIPES_RIGHT>~Z~+26H",
"<FLAG_CATALAN>"},
{"~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-5V~3L<FLAG_PART_HORZ_STRIPE"
"_BOTTOM>~]~-2H~+5V~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-5V~3L"
"<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_POLAND>"},
{"~Y~5L~~~Z~26L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-2H~Y~5L~~"
"~Z~26L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~+26H",
"<FLAG_LITHUANIA>"},
{"~Y~1L<FLAG_PART_FILL>~]~-2H~Y~1L<FLAG_PART_FILL>~Z~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-5V~3L"
"<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-22H~3L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-22H~-5V~3L"
"<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-23H~7L<FLAG_PART_VERT_STRIPE_LEFT>~Z~-26H~-3V~7L"
"<PAD_PART_DPAD_D>~Z~+6V~-26H~7L<PAD_PART_DPAD_U>~Z~-21H~+1V~7L<PAD_PART_DPAD_L>~Z~+26H",
"<FLAG_CZECH>"},
{"~Y~3L~~~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-1H~Y~3L~~"
"~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~7L<FLAG_PART_HORZ_STRIPE_BOTTOM>~Z~-11H~+2V~3L"
"<FLAG_PART_JAPAN_SUN>~Z~-9H~+2V~1L+~Z~-8V~-8H~7L-~Z~-8V~-3H~7L-~Z~+26H",
"<FLAG_CROATIA>"},
{"~Y~1L<FLAG_PART_FILL>~Z~21L<FLAG_PART_UK_CROSS_LEFT>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>"
"~Z~1L<FLAG_PART_HORZ_STRIPE_BOTTOM>~]~-1H~Y~1L<FLAG_PART_FILL>~Z~21L<FLAG_PART_UK_CROSS_"
"RIGHT>~Z~1L<FLAG_PART_HORZ_STRIPE_MIDDLE>~Z~-4H~1L<FLAG_PART_VERT_STRIPE_LEFT>~Z~1L~~"
"~Z~-11H~7L<FLAG_PART_KOREA_CIRCLE_FILL>~Z~-8V~-8H~3L-~Z~-8V~-4H~3L-~Z~+26H",
"<FLAG_GALICIA>"},
// korean jamo -- only relevant for the language selection since
// non-korean languages don't run through the `convert-korean-text` function and hence the
+17
View File
@@ -26,3 +26,20 @@ files:
- "en-GB"
- "fi"
- "fi-Fi"
- source: /game/assets/jak3/text/game_custom_text_en-US.json
translation: /game/assets/jak3/text/game_custom_text_%locale%.json
- source: /game/assets/jak3/subtitle/subtitle_lines_en-US.json
translation: /game/assets/jak3/subtitle/subtitle_lines_%locale%.json
excluded_target_languages:
- "fr-FR"
- "de-DE"
- "es-ES"
- "it"
- "it-IT"
- "ja-JP"
- "ko"
- "en-GB"
- "fi"
- "fi-Fi"
- "ru-RU"
- "pt-PT"
@@ -26,6 +26,9 @@
// float types: float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°)
// vector types: vector (normal floats), vector4m (meters), vector3m (meters with w set to 1.0), vector-vol (normal floats with w in meters), movie-pos (meters with w in degrees)
// special types: symbol, type, string, eco-info, cell-info, buzzer-info, water-height
// by default, lumps will always use the default keyframe value of -1000000000.0 (DEFAULT_RES_TIME).
// most of the actor code will be using that value, but there are some exceptions (camera entities, water volumes, etc.)
// you can specify a different keyframe by suffixing the lump type with e.g. "@0.5", so for a float at keyframe 0.5, the type would be "float@0.5".
//
// examples:
//
@@ -137,6 +140,50 @@
}
],
// Camera entities you want to use in your level. These are used to dynamically adjust camera settings/modes when Jak enters a volume.
// There are a couple of different camera modes, depending on what lumps are present:
// - cam-circular: orbits a specified point. requires "pivot" lump.
// - optional lumps: "maxAngle", "focalPull"
// - cam-standoff: requires "align" lump.
// - cam-string: the default camera mode. used when any of these lumps are present to override the default cam mode behavior:
// - "stringMaxLength", "stringMinLength", "stringMaxHeight", "stringMinHeight"
//
// Some generic lumps that can be used for all camera modes:
// - "fov": set the camera fov (default is 64).
// - "interpTime": set the cam blend time when entering the camera entity volume.
// - "tiltAdjust": set the camera roll value.
//
// There's a "flags" lump that takes a cam-slave-options enum value:
// "flags": ["enum-uint32", "(cam-slave-options SAME_SIDE COLLIDE)"]
//
// There's three different volume types (these all have to be defined in keyframe 0, e.g. ["vector-vol@0.0": ...]):
// vol: sets camera entity when Jak is inside.
// pvol: preferred volume when camera entities overlap.
// cutoutvol: disables camera entity when Jak is inside.
//
// "interesting" is an optional vector lump that can be set to be used as a "point of interest" for the camera to focus on.
"cameras": [
{
"trans": [17.26, 9.0, 13.2],
"quat": [0, 1, 0, 0],
"lump": {
"name": "test-cam",
"flags": ["enum-uint32", "(cam-slave-options SAME_SIDE)"],
"pivot": ["vector3m", [15.0761, 2.6482, 25.548]],
"interpTime": ["float", 1.0],
"vol": [
"vector-vol@0",
[-0.09046, 0.025624, 0.99557, 32.528575],
[-0.995854, 0.007292, -0.090673, -8.671137],
[0.09046, -0.025624, -0.99557, -16.528584],
[0.995854, -0.007292, 0.090673, 24.671144],
[-0.009584, -0.999645, 0.024858, 0.695884],
[0.009584, 0.999645, -0.024858, 15.304117]
]
}
}
],
"actors": [
{
"trans": [-21.6238, 20.0496, 17.1191], // translation
@@ -26,6 +26,9 @@
// float types: float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°)
// vector types: vector (normal floats), vector4m (meters), vector3m (meters with w set to 1.0), vector-vol (normal floats with w in meters), movie-pos (meters with w in degrees)
// special types: symbol, type, string, eco-info, cell-info, buzzer-info, water-height
// by default, lumps will always use the default keyframe value of -1000000000.0 (DEFAULT_RES_TIME).
// most of the actor code will be using that value, but there are some exceptions (camera entities, water volumes, etc.)
// you can specify a different keyframe by suffixing the lump type with e.g. "@0.5", so for a float at keyframe 0.5, the type would be "float@0.5".
//
// examples:
//
@@ -53,9 +56,12 @@
// The base actor id for your custom level. If you have multiple levels, this should be unique!
"base_id": 100,
// Base id for regions.
"base_region_id": 0,
// All art groups you want to use in your custom level. Will add their models and corresponding textures to the FR3 file.
// Commented out so that the release builds don't have to double-decompile the game
// "art_groups": ["yakow-ag"],
// "art_groups": ["yakow-ag", "water-anim-fortress-ag"],
// If you have any custom models in the "custom_assets/jak2/models/custom_levels" folder that you want to use in your level, add them to this list.
// Note: Like with art groups, these should also be added to your level's .gd file.
@@ -69,6 +75,177 @@
// If you want all textures from a tpage, you can just do ["tpage-name"].
"textures": ["yak-medfur-end"], // for yakow texture fix
// Any regions you want to include in your custom level.
// Regions run scripts that do things like loading specific levels,
// playing ambient sounds, checking if a task is completed in order to e.g. open airlocks, play cutscenes, etc.
//
// They can have three scripts that run on different conditions:
// - A single time when entering the region's bounds (on-enter)
// - Once every frame while you are inside a region (on-inside)
// - A single time when exiting a region's bounds (on-exit)
// Scripts are Lisp pairs, e.g. (want-load 'ctysluma 'ctyindb 'ctywide).
// The list of commands that can be used is too exhaustive to show here and there is no proper documentation for this,
// but you can refer to https://github.com/open-goal/jak-project/blob/master/goal_src/jak2/engine/util/script.gc
// for more information or inspect other regions via the debug menu in-game for examples.
//
// There are two special cases for script forms: "entity-actor" and "actor-group".
// Region scripts can refer to entities or actor groups that are stored inside the level data,
// so forms that start with either of these will be changed during the level building process to insert a reference
// to the given object.
//
// Regions can either be spheres, planes or volumes.
// Spheres do not need anything special, just the trans and bsphere, but if you want a face or a volume,
// you need to additionally specify a "face" or a "volume" key.
// A "face" key contains the face normal and a list of points.
// A "volume" key contains a list of faces.
//
// There are different types of regions like ones that get triggered based on camera position, Jak's position, etc.
// Each type of region is stored in its own region tree, each of which has its own bsphere that all its regions must be encompassed within.
// The full list is as follows:
// target (Jak based), camera (camera based), data (?), water (water volumes), city_vis (?),
// sample (?), light (presumably for foreground lights), entity (?)
"region_trees": {
// camera regions are activated when the camera enters their bounds
"camera": {
// every region tree has its own bsphere. all of a tree's regions must be encompassed within this sphere.
"bsphere": [0, 0, 0, 50],
"regions": [
{
"id": 1,
"shape": "sphere", // can be "sphere", "face" or "volume"
"trans": [-17, 4, 30],
"bsphere": [-17, 4, 30, 5],
// "(actor-group 2)" will be replaced with an actual reference
// to the actor-group in the level data with id 2.
"on-enter": "(begin (print 'enter1) (send-event (actor-group 2) 'none))",
"on-inside": "(begin (sound-play-loop \"punch\") (sound-play-loop \"spin\"))",
"on-exit": "(print 'exit1)"
}
]
},
// target regions are activated when Jak enters their bounds
"target": {
"bsphere": [0, 0, 0, 50],
"regions": [
{
"id": 2,
"shape": "face",
"on-enter": "(begin (print 'enter14) (send-event \"test-actor\" 'rot))",
"bsphere": [3.37, 6.2, 16.59, 7.0711],
"face": {
"normal": [-0.615662, 0.0, -0.788011, -15.147877],
"points": [
[-0.570054, 0, 19.668308],
[-0.570053, 11, 19.668308],
[7.310053, 0, 13.511692],
[7.310053, 11, 13.511692]
]
}
}
]
},
// water regions are used to define water volumes
"water": {
"bsphere": [0, 0, 0, 200],
"regions": [
{
"id": 3,
"shape": "sphere",
// "(entity-actor water-anim-test-zone-1)" will be replaced with an actual reference of the entity with that name.
"on-inside": "(water water-anim (entity-actor water-anim-test-zone-1) (swim wade))",
"trans": [5.0, 6.0, -66.0],
"bsphere": [5.0, 6.0, -66.0, 50.0]
},
{
"id": 4,
"shape": "volume",
"on-inside": "(water height 0.0 (swim wade))",
"bsphere": [5.1664, 9.4453, 51.2316, 25.2828],
"volume": {
"faces": [
{
"normal": [-1.0, 0.0, 0.0, 11.785238],
"points": [
[-11.785238, -2.468076, 65.720734],
[-11.785238, 21.358631, 65.720734],
[-11.785238, -2.468076, 36.742477],
[-11.785238, 21.358631, 36.742477]
]
},
{
"normal": [0.0, 0.0, -1.0, -36.742475],
"points": [
[-11.785238, -2.468076, 36.742477],
[-11.785238, 21.358631, 36.742477],
[22.118128, -2.468076, 36.742477],
[22.118128, 21.358631, 36.742477]
]
},
{
"normal": [1.0, 0.0, 0.0, 22.118128],
"points": [
[22.118128, -2.468076, 36.742477],
[22.118128, 21.358631, 36.742477],
[22.118128, -2.468076, 65.720734],
[22.118128, 21.358631, 65.720734]
]
},
{
"normal": [0.0, 0.0, 1.0, 65.72073],
"points": [
[22.118128, -2.468076, 65.720734],
[22.118128, 21.358631, 65.720734],
[-11.785238, -2.468076, 65.720734],
[-11.785238, 21.358631, 65.720734]
]
},
{
"normal": [0.0, -1.0, 0.0, 2.468076],
"points": [
[-11.785238, -2.468076, 36.742477],
[22.118128, -2.468076, 36.742477],
[-11.785238, -2.468076, 65.720734],
[22.118128, -2.468076, 65.720734]
]
},
{
"normal": [0.0, 1.0, 0.0, 21.358631],
"points": [
[22.118128, 21.358631, 36.742477],
[-11.785238, 21.358631, 36.742477],
[22.118128, 21.358631, 65.720734],
[-11.785238, 21.358631, 65.720734]
]
}
]
}
}
]
},
"data": {},
"city_vis": {},
"sample": {},
"light": {},
"entity": {}
},
// Actor groups you want to include in your level.
//
// Actor groups are arrays of entities, used for example in regions to send events to a list of actors
// or in "battles" as a list of enemies that need to be defeated before being able to progress.
// You can give them an id, this has no effect in-game, but it is used for region scripts so the level builder
// knows which actor group to insert.
"actor_groups": [
{
"id": 0,
"entities": ["test-crate", "test-eco", "test-yakow"]
},
{
"id": 2,
"entities": ["test-crate", "test-actor"]
}
],
"actors": [
{
"trans": [-15.2818, 15.2461, 17.136], // translation
@@ -115,6 +292,24 @@
"lump": {
"name": "test-actor"
}
},
{
"trans": [5, 6.778769493103027, -66],
"etype": "water-anim-test-zone",
"game_task": 0,
"quat": [0.0, 0.0, 0.0, 1.0],
"bsphere": [5, 6.778769493103027, -66, 50],
"lump": {
"look": ["int32", 21],
"name": "water-anim-test-zone-1",
"water-height": [
"water-height",
6.77869987487793,
0.5,
2.0,
"(water-flags can-swim can-wade)"
]
}
}
]
}
@@ -26,6 +26,9 @@
// float types: float, meters (1 meter = 4096.0 units), degrees (65536.0 = 360°)
// vector types: vector (normal floats), vector4m (meters), vector3m (meters with w set to 1.0), vector-vol (normal floats with w in meters), movie-pos (meters with w in degrees)
// special types: symbol, type, string, eco-info, cell-info, buzzer-info, water-height
// by default, lumps will always use the default keyframe value of -1000000000.0 (DEFAULT_RES_TIME).
// most of the actor code will be using that value, but there are some exceptions (camera entities, water volumes, etc.)
// you can specify a different keyframe by suffixing the lump type with e.g. "@0.5", so for a float at keyframe 0.5, the type would be "float@0.5".
//
// examples:
//
@@ -53,9 +56,12 @@
// The base actor id for your custom level. If you have multiple levels, this should be unique!
"base_id": 100,
// Base id for regions.
"base_region_id": 0,
// All art groups you want to use in your custom level. Will add their models and corresponding textures to the FR3 file.
// Commented out so that the release builds don't have to double-decompile the game
// "art_groups": ["yakow-ag"],
// "art_groups": ["yakow-ag", "water-anim-waspala-ag"],
// If you have any custom models in the "custom_assets/jak3/models/custom_levels" folder that you want to use in your level, add them to this list.
// Note: Like with art groups, these should also be added to your level's .gd file.
@@ -69,6 +75,177 @@
// If you want all textures from a tpage, you can just do ["tpage-name"].
"textures": ["yak-medfur-end"], // for yakow texture fix
// Any regions you want to include in your custom level.
// Regions run scripts that do things like loading specific levels,
// playing ambient sounds, checking if a task is completed in order to e.g. open airlocks, play cutscenes, etc.
//
// They can have three scripts that run on different conditions:
// - A single time when entering the region's bounds (on-enter)
// - Once every frame while you are inside a region (on-inside)
// - A single time when exiting a region's bounds (on-exit)
// Scripts are Lisp pairs, e.g. (want-load 'ctysluma 'ctyindb 'ctywide).
// The list of commands that can be used is too exhaustive to show here and there is no proper documentation for this,
// but you can refer to https://github.com/open-goal/jak-project/blob/master/goal_src/jak3/engine/util/script.gc
// for more information or inspect other regions via the debug menu in-game for examples.
//
// There are two special cases for script forms: "entity-actor" and "actor-group".
// Region scripts can refer to entities or actor groups that are stored inside the level data,
// so forms that start with either of these will be changed during the level building process to insert a reference
// to the given object.
//
// Regions can either be spheres, planes or volumes.
// Spheres do not need anything special, just the trans and bsphere, but if you want a face or a volume,
// you need to additionally specify a "face" or a "volume" key.
// A "face" key contains the face normal and a list of points.
// A "volume" key contains a list of faces.
//
// There are different types of regions like ones that get triggered based on camera position, Jak's position, etc.
// Each type of region is stored in its own region tree, each of which has its own bsphere that all its regions must be encompassed within.
// The full list is as follows:
// target (Jak based), camera (camera based), data (?), water (water volumes), city_vis (?),
// sample (?), light (presumably for foreground lights), entity (?)
"region_trees": {
// camera regions are activated when the camera enters their bounds
"camera": {
// every region tree has its own bsphere. all of a tree's regions must be encompassed within this sphere.
"bsphere": [0, 0, 0, 50],
"regions": [
{
"id": 1,
"shape": "sphere", // can be "sphere", "face" or "volume"
"trans": [-17, 4, 30],
"bsphere": [-17, 4, 30, 5],
// "(actor-group 2)" will be replaced with an actual reference
// to the actor-group in the level data with id 2.
"on-enter": "(begin (print 'enter1) (send-event (actor-group 2) 'none))",
"on-inside": "(begin (sound-play-loop \"punch\") (sound-play-loop \"spin\"))",
"on-exit": "(print 'exit1)"
}
]
},
// target regions are activated when Jak enters their bounds
"target": {
"bsphere": [0, 0, 0, 50],
"regions": [
{
"id": 2,
"shape": "face",
"on-enter": "(begin (print 'enter14) (send-event \"test-actor\" 'rot))",
"bsphere": [3.37, 6.2, 16.59, 7.0711],
"face": {
"normal": [-0.615662, 0.0, -0.788011, -15.147877],
"points": [
[-0.570054, 0, 19.668308],
[-0.570053, 11, 19.668308],
[7.310053, 0, 13.511692],
[7.310053, 11, 13.511692]
]
}
}
]
},
// water regions are used to define water volumes
"water": {
"bsphere": [0, 0, 0, 200],
"regions": [
{
"id": 3,
"shape": "sphere",
// "(entity-actor water-anim-test-zone-1)" will be replaced with an actual reference of the entity with that name.
"on-inside": "(water water-anim (entity-actor water-anim-test-zone-1) (swim wade))",
"trans": [5.0, 6.0, -66.0],
"bsphere": [5.0, 6.0, -66.0, 50.0]
},
{
"id": 4,
"shape": "volume",
"on-inside": "(water height 0.0 (swim wade))",
"bsphere": [5.1664, 9.4453, 51.2316, 25.2828],
"volume": {
"faces": [
{
"normal": [-1.0, 0.0, 0.0, 11.785238],
"points": [
[-11.785238, -2.468076, 65.720734],
[-11.785238, 21.358631, 65.720734],
[-11.785238, -2.468076, 36.742477],
[-11.785238, 21.358631, 36.742477]
]
},
{
"normal": [0.0, 0.0, -1.0, -36.742475],
"points": [
[-11.785238, -2.468076, 36.742477],
[-11.785238, 21.358631, 36.742477],
[22.118128, -2.468076, 36.742477],
[22.118128, 21.358631, 36.742477]
]
},
{
"normal": [1.0, 0.0, 0.0, 22.118128],
"points": [
[22.118128, -2.468076, 36.742477],
[22.118128, 21.358631, 36.742477],
[22.118128, -2.468076, 65.720734],
[22.118128, 21.358631, 65.720734]
]
},
{
"normal": [0.0, 0.0, 1.0, 65.72073],
"points": [
[22.118128, -2.468076, 65.720734],
[22.118128, 21.358631, 65.720734],
[-11.785238, -2.468076, 65.720734],
[-11.785238, 21.358631, 65.720734]
]
},
{
"normal": [0.0, -1.0, 0.0, 2.468076],
"points": [
[-11.785238, -2.468076, 36.742477],
[22.118128, -2.468076, 36.742477],
[-11.785238, -2.468076, 65.720734],
[22.118128, -2.468076, 65.720734]
]
},
{
"normal": [0.0, 1.0, 0.0, 21.358631],
"points": [
[22.118128, 21.358631, 36.742477],
[-11.785238, 21.358631, 36.742477],
[22.118128, 21.358631, 65.720734],
[-11.785238, 21.358631, 65.720734]
]
}
]
}
}
]
},
"data": {},
"city_vis": {},
"sample": {},
"light": {},
"entity": {}
},
// Actor groups you want to include in your level.
//
// Actor groups are arrays of entities, used for example in regions to send events to a list of actors
// or in "battles" as a list of enemies that need to be defeated before being able to progress.
// You can give them an id, this has no effect in-game, but it is used for region scripts so the level builder
// knows which actor group to insert.
"actor_groups": [
{
"id": 0,
"entities": ["test-crate", "test-eco", "test-yakow"]
},
{
"id": 2,
"entities": ["test-crate", "test-actor"]
}
],
"actors": [
{
"trans": [-15.2818, 15.2461, 17.136], // translation
@@ -116,6 +293,24 @@
"lump": {
"name": "test-actor"
}
},
{
"trans": [5, 6.778769493103027, -66],
"etype": "water-anim-test-zone",
"game_task": 0,
"quat": [0.0, 0.0, 0.0, 1.0],
"bsphere": [5, 6.778769493103027, -66, 50],
"lump": {
"look": ["int32", 7],
"name": "water-anim-test-zone-1",
"water-height": [
"water-height",
6.77869987487793,
0.5,
2.0,
"(water-flag can-swim can-wade)"
]
}
}
]
}
+2 -1
View File
@@ -60,6 +60,7 @@ add_library(
level_extractor/extract_common.cpp
level_extractor/extract_hfrag.cpp
level_extractor/extract_joint_group.cpp
level_extractor/extract_anim.cpp
level_extractor/extract_level.cpp
level_extractor/extract_merc.cpp
level_extractor/extract_tfrag.cpp
@@ -100,7 +101,7 @@ target_link_libraries(decomp
stb_image
xdelta3
tiny_gltf
)
)
add_executable(decompiler
main.cpp)
+14 -6
View File
@@ -62,7 +62,8 @@ FormElement* SetVarOp::get_as_form(FormPool& pool, const Env& env) const {
m_dst,
pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::ADDRESS_OF),
pool.alloc_single_element_form<StackSpillValueElement>(nullptr, -1, offset, false)),
pool.alloc_single_element_form<StackSpillValueElement>(
nullptr, -1, offset, make_stack_slot_access(offset), false)),
true, env.stack_slot_entries.at(offset).typespec);
}
} else {
@@ -843,10 +844,16 @@ FormElement* StackSpillLoadOp::get_as_form(FormPool& pool, const Env& env) const
if (kv != env.stack_slot_entries.end()) {
type = kv->second.typespec;
}
return pool.alloc_element<SetVarElement>(m_dst,
pool.alloc_single_element_form<StackSpillValueElement>(
nullptr, m_size, m_offset, m_is_signed),
true, type);
std::optional<TypeSpec> read_type;
if (env.has_type_analysis()) {
read_type = env.get_types_before_op(m_my_idx).get_slot(m_offset).typespec();
}
return pool.alloc_element<SetVarElement>(
m_dst,
pool.alloc_single_element_form<StackSpillValueElement>(
nullptr, m_size, m_offset, env.get_stack_slot_access_for_op(m_my_idx, m_offset),
m_is_signed, read_type),
true, type);
}
FormElement* StackSpillStoreOp::get_as_form(FormPool& pool, const Env& env) const {
@@ -866,6 +873,7 @@ FormElement* StackSpillStoreOp::get_as_form(FormPool& pool, const Env& env) cons
}
}
return pool.alloc_element<StackSpillStoreElement>(m_value, m_size, m_offset, cast_type);
return pool.alloc_element<StackSpillStoreElement>(
m_value, m_size, m_offset, env.get_stack_slot_access_for_op(m_my_idx, m_offset), cast_type);
}
} // namespace decompiler
+242
View File
@@ -4,6 +4,7 @@
#include <stdexcept>
#include <unordered_set>
#include "AtomicOp.h"
#include "Form.h"
#include "common/goos/PrettyPrinter.h"
@@ -162,6 +163,10 @@ std::string Env::get_variable_name(const RegisterAccess& access) const {
}
std::string Env::get_variable_name_name_only(const RegisterAccess& access) const {
if (is_stack_slot_access(access)) {
return get_spill_slot_var_name(get_stack_slot_offset_from_access(access));
}
if (access.reg().get_kind() == Reg::FPR || access.reg().get_kind() == Reg::GPR) {
auto& var_info = m_var_names.lookup(access.reg(), access.idx(), access.mode());
return var_info.name();
@@ -172,6 +177,14 @@ std::string Env::get_variable_name_name_only(const RegisterAccess& access) const
}
VariableWithCast Env::get_variable_and_cast(const RegisterAccess& access) const {
if (is_stack_slot_access(access)) {
VariableWithCast result;
auto original_name = get_spill_slot_var_name(get_stack_slot_offset_from_access(access));
auto remapped = m_var_remap.find(original_name);
result.name = remapped != m_var_remap.end() ? remapped->second : original_name;
return result;
}
if (access.reg().get_kind() == Reg::FPR || access.reg().get_kind() == Reg::GPR) {
auto& var_info = m_var_names.lookup(access.reg(), access.idx(), access.mode());
// this is a bit of a confusing process. The first step is to grab the auto-generated name:
@@ -272,6 +285,10 @@ goos::Object Env::get_variable_name_with_cast(Register reg, int atomic_idx, Acce
}
std::optional<TypeSpec> Env::get_user_cast_for_access(const RegisterAccess& access) const {
if (is_stack_slot_access(access)) {
return {};
}
if (access.reg().get_kind() == Reg::FPR || access.reg().get_kind() == Reg::GPR) {
auto& var_info = m_var_names.lookup(access.reg(), access.idx(), access.mode());
std::string original_name = var_info.name();
@@ -310,6 +327,22 @@ std::optional<TypeSpec> Env::get_user_cast_for_access(const RegisterAccess& acce
* of the variable.
*/
TypeSpec Env::get_variable_type(const RegisterAccess& access, bool using_user_var_types) const {
if (is_stack_slot_access(access)) {
auto offset = get_stack_slot_offset_from_access(access);
auto it = stack_slot_entries.find(offset);
if (it != stack_slot_entries.end()) {
auto type_of_var = it->second.typespec;
if (using_user_var_types) {
auto retype_kv = m_var_retype.find(it->second.name());
if (retype_kv != m_var_retype.end()) {
type_of_var = retype_kv->second;
}
}
return type_of_var;
}
return TypeSpec("object");
}
if (access.reg().get_kind() == Reg::FPR || access.reg().get_kind() == Reg::GPR) {
auto& var_info = m_var_names.lookup(access.reg(), access.idx(), access.mode());
std::string original_name = var_info.name();
@@ -328,6 +361,37 @@ TypeSpec Env::get_variable_type(const RegisterAccess& access, bool using_user_va
}
}
TP_Type Env::get_variable_tp_type(const RegisterAccess& access, bool using_user_var_types) const {
if (is_stack_slot_access(access)) {
auto offset = get_stack_slot_offset_from_access(access);
auto it = stack_slot_entries.find(offset);
if (it != stack_slot_entries.end()) {
auto type_of_var = it->second.tp_type;
if (using_user_var_types) {
auto retype_kv = m_var_retype.find(it->second.name());
if (retype_kv != m_var_retype.end()) {
type_of_var = TP_Type::make_from_ts(retype_kv->second);
}
}
return type_of_var;
}
return TP_Type::make_from_ts(TypeSpec("object"));
}
if (access.reg().get_kind() == Reg::FPR || access.reg().get_kind() == Reg::GPR) {
auto& var_info = m_var_names.lookup(access.reg(), access.idx(), access.mode());
if (using_user_var_types) {
auto retype_kv = m_var_retype.find(var_info.name());
if (retype_kv != m_var_retype.end()) {
return TP_Type::make_from_ts(retype_kv->second);
}
}
return var_info.type;
}
throw std::runtime_error("TP types are not supported for this kind of register");
}
/*!
* Update the Env with the result of the type analysis pass.
*/
@@ -420,6 +484,9 @@ std::vector<VariableNames::VarInfo> Env::extract_visible_variables(
std::vector<std::pair<RegId, RegisterAccess>> vars;
for (auto& x : var_set) {
if (is_stack_slot_access(x)) {
continue;
}
if (x.reg().get_kind() == Reg::FPR || x.reg().get_kind() == Reg::GPR) {
vars.push_back(std::make_pair(get_program_var_id(x), x));
}
@@ -480,6 +547,16 @@ FunctionVariableDefinitions Env::local_var_type_list(const Form* top_level_form,
int nargs_to_ignore) const {
ASSERT(nargs_to_ignore <= 8);
auto vars = extract_visible_variables(top_level_form);
std::unordered_set<int> visible_stack_slots;
if (top_level_form) {
RegAccessSet var_set;
top_level_form->collect_vars(var_set, true);
for (const auto& var : var_set) {
if (is_stack_slot_access(var)) {
visible_stack_slots.insert(get_stack_slot_offset_from_access(var));
}
}
}
FunctionVariableDefinitions result;
std::vector<goos::Object> elts;
@@ -514,11 +591,17 @@ FunctionVariableDefinitions Env::local_var_type_list(const Form* top_level_form,
// it looks like this is the order the GOAL compiler itself used.
std::vector<StackSpillEntry> spills;
for (auto& x : stack_slot_entries) {
if (top_level_form && !visible_stack_slots.count(x.first)) {
continue;
}
spills.push_back(x.second);
}
std::sort(spills.begin(), spills.end(),
[](const StackSpillEntry& a, const StackSpillEntry& b) { return a.offset < b.offset; });
for (auto& x : spills) {
if (m_vars_defined_in_let.find(x.name()) != m_vars_defined_in_let.end()) {
continue;
}
elts.push_back(pretty_print::build_list(x.name(), x.typespec.print()));
count++;
}
@@ -539,27 +622,186 @@ std::unordered_set<RegId, RegId::hash> Env::get_ssa_var(const RegAccessSet& vars
}
RegId Env::get_program_var_id(const RegisterAccess& var) const {
if (is_stack_slot_access(var)) {
return RegId(Register(Reg::GPR, Reg::SP), get_stack_slot_var_id_from_access(var));
}
return m_var_names.lookup(var.reg(), var.idx(), var.mode()).reg_id;
}
const UseDefInfo& Env::get_use_def_info(const RegisterAccess& ra) const {
ASSERT(has_local_vars());
if (is_stack_slot_access(ra)) {
return m_stack_slot_use_def_info.at(get_program_var_id(ra));
}
auto var_id = get_program_var_id(ra);
return m_var_names.use_def_info.at(var_id);
}
RegisterAccess Env::get_stack_slot_access_for_op(int op_id, int offset) const {
auto it = m_stack_slot_var_by_op.find(op_id);
if (it == m_stack_slot_var_by_op.end()) {
return make_stack_slot_access(offset);
}
return make_stack_slot_access(offset, it->second);
}
void Env::disable_def(const RegisterAccess& access, DecompWarnings& warnings) {
if (is_stack_slot_access(access)) {
// Stack-slot use/def info is intentionally immutable during expression building.
// Unlike registers, the stack-slot analysis models value lifetimes through merged control flow
// with synthetic phi-like vars, and mutating counts here would desynchronize later accesses
// from that analysis.
return;
}
if (has_local_vars()) {
m_var_names.disable_def(access, warnings);
}
}
void Env::disable_use(const RegisterAccess& access) {
if (is_stack_slot_access(access)) {
// See disable_def above.
return;
}
if (has_local_vars()) {
m_var_names.disable_use(access);
}
}
void Env::rebuild_stack_slot_use_def_info() {
m_stack_slot_use_def_info.clear();
m_stack_slot_var_by_op.clear();
if (!func || !func->ir2.atomic_ops) {
return;
}
const auto& ops = *func->ir2.atomic_ops;
const int block_count = (int)ops.block_id_to_first_atomic_op.size();
std::vector<int> op_to_block(ops.ops.size(), -1);
for (int block_id = 0; block_id < block_count; block_id++) {
for (int op_id = ops.block_id_to_first_atomic_op.at(block_id);
op_id < ops.block_id_to_end_atomic_op.at(block_id); op_id++) {
op_to_block.at(op_id) = block_id;
}
}
std::unordered_set<int> offsets;
for (int op_id = 0; op_id < (int)ops.ops.size(); op_id++) {
if (auto* store = dynamic_cast<const StackSpillStoreOp*>(ops.ops.at(op_id).get())) {
offsets.insert(store->offset());
} else if (auto* load = dynamic_cast<const StackSpillLoadOp*>(ops.ops.at(op_id).get())) {
offsets.insert(load->offset());
}
}
int next_var_id = 1;
for (int offset : offsets) {
std::vector<bool> reads_before_write(block_count, false);
std::vector<bool> writes(block_count, false);
for (int block_id = 0; block_id < block_count; block_id++) {
bool seen_write = false;
for (int op_id = ops.block_id_to_first_atomic_op.at(block_id);
op_id < ops.block_id_to_end_atomic_op.at(block_id); op_id++) {
const auto* op = ops.ops.at(op_id).get();
if (auto* load = dynamic_cast<const StackSpillLoadOp*>(op)) {
if (load->offset() == offset && !seen_write) {
reads_before_write.at(block_id) = true;
}
} else if (auto* store = dynamic_cast<const StackSpillStoreOp*>(op)) {
if (store->offset() == offset) {
writes.at(block_id) = true;
seen_write = true;
}
}
}
}
std::vector<bool> live_in(block_count, false);
std::vector<bool> live_out(block_count, false);
bool changed = true;
while (changed) {
changed = false;
for (int block_id = block_count - 1; block_id >= 0; block_id--) {
bool new_live_out = false;
for (int succ : {func->basic_blocks.at(block_id).succ_branch,
func->basic_blocks.at(block_id).succ_ft}) {
if (succ != -1 && live_in.at(succ)) {
new_live_out = true;
}
}
bool new_live_in =
reads_before_write.at(block_id) || (new_live_out && !writes.at(block_id));
if (new_live_in != live_in.at(block_id) || new_live_out != live_out.at(block_id)) {
live_in.at(block_id) = new_live_in;
live_out.at(block_id) = new_live_out;
changed = true;
}
}
}
std::vector<int> phi_var(block_count, -1);
std::vector<std::vector<int>> phi_sources(block_count);
for (int block_id = 0; block_id < block_count; block_id++) {
if (live_in.at(block_id)) {
phi_var.at(block_id) = next_var_id++;
}
}
for (int block_id = 0; block_id < block_count; block_id++) {
int current_var = live_in.at(block_id) ? phi_var.at(block_id) : -1;
for (int op_id = ops.block_id_to_first_atomic_op.at(block_id);
op_id < ops.block_id_to_end_atomic_op.at(block_id); op_id++) {
const auto* op = ops.ops.at(op_id).get();
if (auto* load = dynamic_cast<const StackSpillLoadOp*>(op)) {
if (load->offset() != offset) {
continue;
}
ASSERT(current_var != -1);
m_stack_slot_var_by_op[op_id] = current_var;
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), current_var)];
info.uses.push_back({op_id, block_id, AccessMode::READ, false});
info.ssa_vars.insert(current_var);
} else if (auto* store = dynamic_cast<const StackSpillStoreOp*>(op)) {
if (store->offset() != offset) {
continue;
}
current_var = next_var_id++;
m_stack_slot_var_by_op[op_id] = current_var;
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), current_var)];
info.defs.push_back({op_id, block_id, AccessMode::WRITE, false});
info.ssa_vars.insert(current_var);
}
}
if (!live_out.at(block_id)) {
continue;
}
ASSERT(current_var != -1);
for (int succ :
{func->basic_blocks.at(block_id).succ_branch, func->basic_blocks.at(block_id).succ_ft}) {
if (succ != -1 && live_in.at(succ)) {
phi_sources.at(succ).push_back(current_var);
}
}
}
for (int block_id = 0; block_id < block_count; block_id++) {
if (phi_var.at(block_id) == -1) {
continue;
}
int first_op = ops.block_id_to_first_atomic_op.at(block_id);
for (int src_var : phi_sources.at(block_id)) {
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), src_var)];
info.uses.push_back({first_op, block_id, AccessMode::READ, false});
}
}
}
}
/*!
* Set the stack hints. This must be done before type analysis.
* This actually parses the types, so it should be done after the dts is set up.
+36
View File
@@ -44,6 +44,36 @@ struct StackSpillEntry {
}
};
constexpr int STACK_SLOT_VAR_STRIDE = 1 << 16;
inline bool is_stack_slot_access(const RegisterAccess& access) {
return access.reg() == Register(Reg::GPR, Reg::SP) && access.idx() < 0;
}
inline int get_stack_slot_offset_from_access(const RegisterAccess& access) {
ASSERT(is_stack_slot_access(access));
return (-access.idx() - 1) / STACK_SLOT_VAR_STRIDE;
}
inline int get_stack_slot_var_id_from_access(const RegisterAccess& access) {
ASSERT(is_stack_slot_access(access));
return (-access.idx() - 1) % STACK_SLOT_VAR_STRIDE;
}
inline RegisterAccess make_stack_slot_access(int offset, int var_id = 0) {
ASSERT(var_id >= 0);
ASSERT(var_id < STACK_SLOT_VAR_STRIDE);
return RegisterAccess(AccessMode::READ, Register(Reg::GPR, Reg::SP),
-1 - (offset * STACK_SLOT_VAR_STRIDE + var_id), true);
}
inline bool same_expression_var(const RegisterAccess& a, const RegisterAccess& b) {
if (is_stack_slot_access(a) || is_stack_slot_access(b)) {
return a == b;
}
return a.reg() == b.reg();
}
struct FunctionVariableDefinitions {
std::optional<goos::Object> local_vars;
bool had_pp = false;
@@ -126,6 +156,7 @@ class Env {
void set_local_vars(const VariableNames& names) {
m_var_names = names;
m_has_local_vars = true;
rebuild_stack_slot_use_def_info();
}
void set_end_var(RegisterAccess var) { m_end_var = var; }
@@ -193,6 +224,7 @@ class Env {
}
const UseDefInfo& get_use_def_info(const RegisterAccess& ra) const;
RegisterAccess get_stack_slot_access_for_op(int op_id, int offset) const;
void disable_use(const RegisterAccess& access);
void disable_def(const RegisterAccess& access, DecompWarnings& warnings);
@@ -228,6 +260,8 @@ class Env {
bool pp_mapped_by_behavior() const { return m_pp_mapped_by_behavior; }
private:
void rebuild_stack_slot_use_def_info();
RegisterAccess m_end_var;
bool m_has_reg_use = false;
@@ -235,6 +269,8 @@ class Env {
bool m_has_local_vars = false;
VariableNames m_var_names;
std::unordered_map<RegId, UseDefInfo, RegId::hash> m_stack_slot_use_def_info;
std::unordered_map<int, int> m_stack_slot_var_by_op;
bool m_has_types = false;
bool m_pp_mapped_by_behavior = false;
+26 -5
View File
@@ -7,6 +7,7 @@
#include "common/type_system/TypeSystem.h"
#include "common/util/print_float.h"
#include "decompiler/IR2/Env.h"
#include "decompiler/ObjectFile/LinkedObjectFile.h"
#include "decompiler/util/DecompilerTypeSystem.h"
#include "decompiler/util/data_decompile.h"
@@ -2775,8 +2776,13 @@ void VectorFloatLoadStoreElement::collect_vf_regs(RegSet& regs) const {
StackSpillStoreElement::StackSpillStoreElement(SimpleAtom value,
int size,
int stack_offset,
RegisterAccess access,
const std::optional<TypeSpec>& cast_type)
: m_value(value), m_size(size), m_stack_offset(stack_offset), m_cast_type(cast_type) {}
: m_value(value),
m_size(size),
m_stack_offset(stack_offset),
m_access(access),
m_cast_type(cast_type) {}
goos::Object StackSpillStoreElement::to_form_internal(const Env& env) const {
return pretty_print::build_list(
@@ -2801,11 +2807,24 @@ void StackSpillStoreElement::get_modified_regs(RegSet&) const {}
// StackSpillValueElement
////////////////////////////////
StackSpillValueElement::StackSpillValueElement(int size, int stack_offset, bool is_signed)
: m_size(size), m_stack_offset(stack_offset), m_is_signed(is_signed) {}
StackSpillValueElement::StackSpillValueElement(int size,
int stack_offset,
RegisterAccess access,
bool is_signed,
std::optional<TypeSpec> read_type)
: m_size(size),
m_stack_offset(stack_offset),
m_access(access),
m_is_signed(is_signed),
m_read_type(std::move(read_type)) {}
goos::Object StackSpillValueElement::to_form_internal(const Env& env) const {
return pretty_print::to_symbol(env.get_spill_slot_var_name(m_stack_offset));
auto var = m_access;
auto base = pretty_print::to_symbol(env.get_spill_slot_var_name(m_stack_offset));
if (m_read_type && env.get_variable_type(var, true) != *m_read_type) {
return pretty_print::build_list("the-as", m_read_type->print(), base);
}
return base;
}
void StackSpillValueElement::apply(const std::function<void(FormElement*)>& f) {
@@ -2813,7 +2832,9 @@ void StackSpillValueElement::apply(const std::function<void(FormElement*)>& f) {
}
void StackSpillValueElement::apply_form(const std::function<void(Form*)>&) {}
void StackSpillValueElement::collect_vars(RegAccessSet&, bool) const {}
void StackSpillValueElement::collect_vars(RegAccessSet& vars, bool) const {
vars.insert(m_access);
}
void StackSpillValueElement::get_modified_regs(RegSet&) const {}
////////////////////////////////
+13 -1
View File
@@ -1545,6 +1545,7 @@ class StackSpillStoreElement : public FormElement {
StackSpillStoreElement(SimpleAtom value,
int size,
int stack_offset,
RegisterAccess access,
const std::optional<TypeSpec>& cast_type);
goos::Object to_form_internal(const Env& env) const override;
void apply(const std::function<void(FormElement*)>& f) override;
@@ -1553,18 +1554,27 @@ class StackSpillStoreElement : public FormElement {
void get_modified_regs(RegSet& regs) const override;
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
const std::optional<TypeSpec>& cast_type() const { return m_cast_type; }
const RegisterAccess& access() const { return m_access; }
int stack_offset() const { return m_stack_offset; }
private:
SimpleAtom m_value;
int m_size = -1;
int m_stack_offset = -1;
RegisterAccess m_access;
std::optional<TypeSpec> m_cast_type;
};
// the value from a stack load.
class StackSpillValueElement : public FormElement {
public:
StackSpillValueElement(int size, int stack_offset, bool is_signed);
StackSpillValueElement(int size,
int stack_offset,
RegisterAccess access,
bool is_signed,
std::optional<TypeSpec> read_type = std::nullopt);
int stack_offset() const { return m_stack_offset; }
const RegisterAccess& access() const { return m_access; }
goos::Object to_form_internal(const Env& env) const override;
void apply(const std::function<void(FormElement*)>& f) override;
void apply_form(const std::function<void(Form*)>& f) override;
@@ -1579,7 +1589,9 @@ class StackSpillValueElement : public FormElement {
private:
int m_size = -1;
int m_stack_offset = -1;
RegisterAccess m_access;
bool m_is_signed = false;
std::optional<TypeSpec> m_read_type;
};
class MethodOfTypeElement : public FormElement {
+226 -40
View File
@@ -12,6 +12,7 @@
#include "common/util/BitUtils.h"
#include "common/util/print_float.h"
#include "decompiler/IR2/Env.h"
#include "decompiler/IR2/ExpressionHelpers.h"
#include "decompiler/IR2/bitfields.h"
#include "decompiler/ObjectFile/LinkedObjectFile.h"
@@ -65,6 +66,56 @@
namespace decompiler {
namespace {
Form* cast_form(Form* in, const TypeSpec& new_type, FormPool& pool, const Env& env, bool tc_pass);
TypeSpec get_input_type_for_access(const Env& env, const RegisterAccess& access) {
if (is_stack_slot_access(access)) {
return env.get_variable_type(access, true);
}
return env.get_types_before_op(access.idx()).get(access.reg()).typespec();
}
Form* cast_stack_slot_var_if_needed(Form* in,
const TypeSpec& desired_type,
FormPool& pool,
const Env& env) {
auto atom = form_as_atom(in);
if (atom && atom->is_var() && is_stack_slot_access(atom->var()) &&
env.get_variable_type(atom->var(), true) != desired_type) {
return cast_form(in, desired_type, pool, env, false);
}
return in;
}
Form* cast_inlined_function_symbol_if_needed(Form* in,
const TypeSpec& desired_type,
FormPool& pool,
const Env& env) {
if (!env.has_type_analysis() || desired_type.base_type() != "function") {
return in;
}
auto existing_cast = in->try_as_element<CastElement>();
if (existing_cast && existing_cast->type() == desired_type) {
return in;
}
auto obj = in->to_form(env);
if (!obj.is_symbol()) {
return in;
}
try {
auto symbol_type = env.dts->lookup_symbol_type(obj.as_symbol().name_ptr);
if (symbol_type.base_type() == "function" && symbol_type != desired_type) {
return pool.form<CastElement>(desired_type, in);
}
} catch (const std::runtime_error&) {
}
return in;
}
Form* strip_pcypld_64(Form* in) {
auto m = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::PCPYLD),
{Matcher::integer(0), Matcher::any(0)}),
@@ -347,6 +398,9 @@ Form* repop_passthrough_arg(Form* in,
auto as_atom = form_as_atom(in);
if (as_atom && as_atom->is_var()) {
if (is_stack_slot_access(as_atom->var())) {
return in;
}
return stack.pop_reg(as_atom->var().reg(), {}, env, true, -1, orig_out, found_orig_out);
}
return in;
@@ -377,18 +431,37 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
const std::optional<RegSet>& consumes = std::nullopt,
const std::vector<int>& times_used = {}) {
// to submit to stack to attempt popping
std::vector<Register> submit_regs;
// submit_reg[i] is for var submit_reg_to_var[i]
std::vector<size_t> submit_reg_to_var;
std::vector<RegisterAccess> submit_vars;
// submit_vars[i] is for var submit_var_to_var[i]
std::vector<size_t> submit_var_to_var;
// build submission for stack
std::unordered_map<Register, int, Register::hash> reg_counts;
std::unordered_map<std::string, int> stack_var_counts;
for (auto& v : vars) {
reg_counts[v.reg()]++;
if (is_stack_slot_access(v)) {
stack_var_counts[env.get_variable_name_name_only(v)]++;
} else {
reg_counts[v.reg()]++;
}
}
for (size_t var_idx = 0; var_idx < vars.size(); var_idx++) {
const auto& var = vars.at(var_idx);
if (is_stack_slot_access(var)) {
int times = 1;
if (!times_used.empty()) {
times = times_used.at(var_idx);
}
auto& use_def = env.get_use_def_info(var);
if (stack_var_counts.at(env.get_variable_name_name_only(var)) == 1 &&
use_def.use_count() == times && use_def.def_count() == 1) {
submit_var_to_var.push_back(var_idx);
submit_vars.push_back(var);
}
continue;
}
auto& ri = env.reg_use().op.at(var.idx());
RegSet consumes_to_use = consumes.value_or(ri.consumes);
if (consumes_to_use.find(var.reg()) != consumes_to_use.end()) {
@@ -402,8 +475,8 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
auto& use_def = env.get_use_def_info(var);
if (use_def.use_count() == times && use_def.def_count() == 1) {
submit_reg_to_var.push_back(var_idx);
submit_regs.push_back(var.reg());
submit_var_to_var.push_back(var_idx);
submit_vars.push_back(var);
} else {
// auto var_id = env.get_program_var_id(var);
// lg::print(
@@ -429,9 +502,9 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
// submit and get a result! If the stack has nothing to pop, the result here may be nullptr.
std::vector<Form*> pop_result;
// loop in reverse (later vals first)
for (size_t i = submit_regs.size(); i-- > 0;) {
for (size_t i = submit_vars.size(); i-- > 0;) {
// figure out what var we are:
auto var_idx = submit_reg_to_var.at(i);
auto var_idx = submit_var_to_var.at(i);
// anything _less_ than this should be unmodified by the pop
// it's fine to modify yourself in your pop.
@@ -442,7 +515,7 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
// do the pop, with the barrier to prevent out-of-sequence popping.
pop_result.push_back(
stack.pop_reg(submit_regs.at(i), pop_barrier_regs, env, allow_side_effects));
stack.pop_reg(submit_vars.at(i), pop_barrier_regs, env, allow_side_effects));
}
// now flip back to the source order for making the final result
std::reverse(pop_result.begin(), pop_result.end());
@@ -452,9 +525,9 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
forms.resize(vars.size(), nullptr);
if (!pop_result.empty()) {
// success!
for (size_t i = 0; i < submit_regs.size(); i++) {
for (size_t i = 0; i < submit_vars.size(); i++) {
// fill out vars from our submission
forms.at(submit_reg_to_var.at(i)) = pop_result.at(i);
forms.at(submit_var_to_var.at(i)) = pop_result.at(i);
}
}
@@ -555,6 +628,14 @@ std::vector<Form*> pop_to_forms(const std::vector<RegisterAccess>& vars,
for (size_t i = 0; i < vars.size(); i++) {
auto atom = form_as_atom(forms[i]);
bool is_var = atom && atom->is_var();
if (is_var && is_stack_slot_access(atom->var())) {
auto access_type = get_input_type_for_access(env, vars[i]);
if (env.get_variable_type(atom->var(), true) != access_type) {
forms[i] = cast_form(forms[i], access_type, pool, env);
atom = form_as_atom(forms[i]);
is_var = atom && atom->is_var();
}
}
auto cast = env.get_user_cast_for_access(vars[i]);
// only cast if we didn't get a var (compacting expressions).
// there is a separate system for casting variables that will do a better job.
@@ -1008,6 +1089,26 @@ void SimpleExpressionElement::update_from_stack_float_2_nestable(const Env& env,
bool allow_side_effects) {
if (is_float_type(env, m_my_idx, m_expr.get_arg(0).var()) &&
is_float_type(env, m_my_idx, m_expr.get_arg(1).var())) {
if (m_expr.get_arg(0).var() == m_expr.get_arg(1).var()) {
auto arg =
pop_to_forms({m_expr.get_arg(0).var()}, env, pool, stack, allow_side_effects, {}, {2})
.at(0);
if (kind == FixedOperatorKind::MULTIPLICATION) {
result->push_back(pool.alloc_element<GenericElement>(
GenericOperator::make_function(pool.form<ConstantTokenElement>("square")), arg));
return;
}
auto atom = form_as_atom(arg);
if (atom) {
auto arg_copy = pool.form<SimpleAtomElement>(*atom);
auto new_form =
make_and_compact_math_op(arg, arg_copy, {}, {}, pool, env, kind, true, false);
result->push_back(new_form);
return;
}
}
auto args = pop_to_forms({m_expr.get_arg(0).var(), m_expr.get_arg(1).var()}, env, pool, stack,
allow_side_effects);
auto new_form =
@@ -1146,7 +1247,9 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
}
}
ASSERT(used_index);
result->push_back(pool.alloc_element<DerefElement>(args.at(1), out.addr_of, tokens));
result->push_back(pool.alloc_element<DerefElement>(
cast_stack_slot_var_if_needed(args.at(1), arg1_type.typespec(), pool, env),
out.addr_of, tokens));
return;
} else {
throw std::runtime_error(
@@ -1186,7 +1289,9 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
}
}
ASSERT(used_index);
result->push_back(pool.alloc_element<DerefElement>(args.at(1), out.addr_of, tokens));
result->push_back(pool.alloc_element<DerefElement>(
cast_stack_slot_var_if_needed(args.at(1), arg1_type.typespec(), pool, env),
out.addr_of, tokens));
return;
} else {
throw std::runtime_error(
@@ -1215,7 +1320,9 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
}
}
ASSERT(used_index);
result->push_back(pool.alloc_element<DerefElement>(args.at(1), out.addr_of, tokens));
result->push_back(pool.alloc_element<DerefElement>(
cast_stack_slot_var_if_needed(args.at(1), arg1_type.typespec(), pool, env),
out.addr_of, tokens));
return;
} else {
throw std::runtime_error(
@@ -1267,7 +1374,9 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
}
}
ASSERT(used_index);
result->push_back(pool.alloc_element<DerefElement>(args.at(0), rd_ok.addr_of, tokens));
result->push_back(pool.alloc_element<DerefElement>(
cast_stack_slot_var_if_needed(args.at(0), arg0_type.typespec(), pool, env),
rd_ok.addr_of, tokens));
return;
} else {
throw std::runtime_error(fmt::format(
@@ -1318,7 +1427,9 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
}
}
ASSERT(used_index);
result->push_back(pool.alloc_element<DerefElement>(args.at(1), rd_ok.addr_of, tokens));
result->push_back(pool.alloc_element<DerefElement>(
cast_stack_slot_var_if_needed(args.at(1), arg1_type.typespec(), pool, env),
rd_ok.addr_of, tokens));
return;
} else {
// TODO - output error to IR
@@ -1341,7 +1452,9 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
tokens.push_back(to_token(tok));
}
result->push_back(pool.alloc_element<DerefElement>(args.at(1), out.addr_of, tokens));
result->push_back(pool.alloc_element<DerefElement>(
cast_stack_slot_var_if_needed(args.at(1), arg1_type.typespec(), pool, env), out.addr_of,
tokens));
return;
}
}
@@ -2357,7 +2470,7 @@ void SimpleExpressionElement::update_from_stack_int_to_float(const Env& env,
// the gpr->fpr operation beacuse it doesn't matter.
auto fpr_convert_matcher =
Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::GPR_TO_FPR), {Matcher::any(0)});
auto type = env.get_types_before_op(var.idx()).get(var.reg()).typespec();
auto type = get_input_type_for_access(env, var);
// want to allow any child of integer so integer enums can also be converted to floats.
if (env.dts->ts.tc(TypeSpec("integer"), type) || type == TypeSpec("seconds")) {
auto mr = match(fpr_convert_matcher, arg);
@@ -2379,7 +2492,7 @@ void SimpleExpressionElement::update_from_stack_float_to_int(const Env& env,
bool allow_side_effects) {
auto var = m_expr.get_arg(0).var();
auto arg = pop_to_forms({var}, env, pool, stack, allow_side_effects).at(0);
auto type = env.get_types_before_op(var.idx()).get(var.reg()).typespec();
auto type = get_input_type_for_access(env, var);
auto fpr_convert_matcher =
Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::GPR_TO_FPR), {Matcher::any(0)});
auto mr = match(fpr_convert_matcher, arg);
@@ -2412,7 +2525,7 @@ void SimpleExpressionElement::update_from_stack_subu_l32_s7(const Env& env,
bool allow_side_effects) {
auto var = m_expr.get_arg(0).var();
auto arg = pop_to_forms({var}, env, pool, stack, allow_side_effects).at(0);
auto type = env.get_types_before_op(var.idx()).get(var.reg()).typespec();
auto type = get_input_type_for_access(env, var);
if (type != TypeSpec("handle")) {
env.func->warnings.warning(
".subu (32-bit) used on a {} at idx {}. This probably should be a handle.", type.print(),
@@ -2623,6 +2736,12 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
// if we are a reg-reg move that consumes the original, push it without popping from stack.
// it is the Stack's responsibility to untangle these later on.
if (m_src->is_single_element()) {
auto spill_value = dynamic_cast<StackSpillValueElement*>(m_src->back());
if (spill_value) {
stack.push_non_seq_reg_to_reg(m_dst, spill_value->access(), m_src, m_src_type, m_var_info);
return;
}
auto src_as_se = dynamic_cast<SimpleExpressionElement*>(m_src->back());
if (src_as_se) {
if (src_as_se->expr().kind() == SimpleExpression::Kind::IDENTITY &&
@@ -2634,9 +2753,15 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
}
auto var = src_as_se->expr().get_arg(0).var();
auto& info = env.reg_use().op.at(var.idx());
if (var.reg() == Register(Reg::GPR, Reg::S6) ||
info.consumes.find(var.reg()) != info.consumes.end()) {
bool is_consumed_reg_move = false;
if (is_stack_slot_access(var)) {
auto& use_def = env.get_use_def_info(var);
is_consumed_reg_move = use_def.use_count() == 1 && use_def.def_count() == 1;
} else {
auto& info = env.reg_use().op.at(var.idx());
is_consumed_reg_move = info.consumes.find(var.reg()) != info.consumes.end();
}
if (var.reg() == Register(Reg::GPR, Reg::S6) || is_consumed_reg_move) {
stack.push_non_seq_reg_to_reg(m_dst, src_as_se->expr().get_arg(0).var(), m_src,
m_src_type, m_var_info);
return;
@@ -3495,8 +3620,14 @@ void FunctionCallElement::update_from_stack(const Env& env,
}
TypeSpec function_type;
auto& in_type_state = env.get_types_before_op(all_pop_vars.at(0).idx());
auto& tp_type = in_type_state.get(all_pop_vars.at(0).reg());
const TypeState* in_type_state = nullptr;
TP_Type tp_type;
if (!is_stack_slot_access(all_pop_vars.at(0))) {
in_type_state = &env.get_types_before_op(all_pop_vars.at(0).idx());
tp_type = in_type_state->get(all_pop_vars.at(0).reg());
} else {
tp_type = env.get_variable_tp_type(all_pop_vars.at(0), true);
}
if (env.has_type_analysis()) {
function_type = tp_type.typespec();
}
@@ -3504,7 +3635,8 @@ void FunctionCallElement::update_from_stack(const Env& env,
// if we're actually a go:
Form* go_next_state = nullptr;
if (tp_type.kind == TP_Type::Kind::ENTER_STATE_FUNCTION) {
auto& next_state_type = in_type_state.next_state_type;
ASSERT(in_type_state);
auto& next_state_type = in_type_state->next_state_type;
if (next_state_type.typespec().base_type() != "state") {
throw std::runtime_error("Bad state type in expressions (not state): " +
next_state_type.print());
@@ -3591,7 +3723,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
auto val = unstacked.at(arg_id + 1); // first is the function itself.
auto& var = all_pop_vars.at(arg_id + 1);
if (has_good_types) {
auto actual_arg_type = env.get_types_before_op(var.idx()).get(var.reg()).typespec();
auto actual_arg_type = get_input_type_for_access(env, var);
if (arg_id == 0) {
first_arg_type = actual_arg_type;
@@ -3965,7 +4097,9 @@ void FunctionCallElement::update_from_stack(const Env& env,
}
}
new_form = pool.alloc_element<GenericElement>(GenericOperator::make_function(unstacked.at(0)),
auto called_function =
cast_inlined_function_symbol_if_needed(unstacked.at(0), function_type, pool, env);
new_form = pool.alloc_element<GenericElement>(GenericOperator::make_function(called_function),
arg_forms);
{
@@ -3997,7 +4131,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
ASSERT(new_args.size() >= 3);
for (size_t i = 0; i < 3; i++) {
auto& var = all_pop_vars.at(i + 1); // 0 is the function itself.
auto arg_type = env.get_types_before_op(var.idx()).get(var.reg()).typespec();
auto arg_type = get_input_type_for_access(env, var);
if (!env.dts->ts.tc(expected_arg_types.at(i), arg_type)) {
new_args.at(i) = pool.form<CastElement>(expected_arg_types.at(i), new_args.at(i));
}
@@ -4027,7 +4161,7 @@ void FunctionCallElement::update_from_stack(const Env& env,
if (match_result.matched) {
auto& alloc = match_result.maps.strings.at(allocation);
if (alloc != "global" && alloc != "debug" && alloc != "process" &&
alloc != "loading-level") {
alloc != "loading-level" && alloc != "process-level-heap") {
throw std::runtime_error("Unrecognized heap symbol for new: " + alloc);
}
auto type_2 = match_result.maps.strings.at(type_for_arg);
@@ -5031,9 +5165,11 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac
// determine if set destination is used
bool set_unused = false;
if (rewrite_as_set) {
auto& info = env.reg_use().op.at(last_var->idx());
if (info.written_and_unused.find(last_var->reg()) != info.written_and_unused.end()) {
set_unused = true;
if (!is_stack_slot_access(*last_var)) {
auto& info = env.reg_use().op.at(last_var->idx());
if (info.written_and_unused.find(last_var->reg()) != info.written_and_unused.end()) {
set_unused = true;
}
}
}
@@ -6019,7 +6155,7 @@ void ConditionElement::push_to_stack(const Env& env, FormPool& pool, FormStack&
if (m_src[i]->is_var()) {
auto& var = m_src[i]->var();
vars.push_back(var);
source_types.push_back(env.get_types_before_op(var.idx()).get(var.reg()).typespec());
source_types.push_back(get_input_type_for_access(env, var));
} else if (m_src[i]->is_int()) {
if (m_src[i]->get_int() == 0 && condition_uses_float(m_kind)) {
// if we're doing a floating point comparison, and one of our arguments is a constant
@@ -6072,7 +6208,7 @@ void ConditionElement::update_from_stack(const Env& env,
if (m_src[i]->is_var()) {
auto& var = m_src[i]->var();
vars.push_back(var);
source_types.push_back(env.get_types_before_op(var.idx()).get(var.reg()).typespec());
source_types.push_back(get_input_type_for_access(env, var));
} else if (m_src[i]->is_int()) {
if (m_src[i]->get_int() == 0 && condition_uses_float(m_kind)) {
// if we're doing a floating point comparison, and one of our arguments is a constant
@@ -6915,11 +7051,53 @@ void StackSpillStoreElement::push_to_stack(const Env& env, FormPool& pool, FormS
src = pool.form<SimpleAtomElement>(m_value);
}
auto dst = pool.form<ConstantTokenElement>(env.get_spill_slot_var_name(m_stack_offset));
if (m_cast_type) {
src = cast_form(src, *m_cast_type, pool, env);
}
stack.push_form_element(pool.alloc_element<SetFormFormElement>(dst, src), true);
TypeSpec stack_type("object");
auto it = env.stack_slot_entries.find(m_stack_offset);
if (it != env.stack_slot_entries.end()) {
stack_type = it->second.typespec;
} else if (m_cast_type) {
stack_type = *m_cast_type;
}
auto src_as_generic = src->try_as_element<GenericElement>();
if (src_as_generic && !src_as_generic->op().is_func()) {
using InplaceOpInfo = std::pair<FixedOperatorKind, FixedOperatorKind>;
const static std::array<InplaceOpInfo, 6> in_place_ops = {
InplaceOpInfo{FixedOperatorKind::ADDITION, FixedOperatorKind::ADDITION_IN_PLACE},
InplaceOpInfo{FixedOperatorKind::ADDITION_PTR, FixedOperatorKind::ADDITION_PTR_IN_PLACE},
InplaceOpInfo{FixedOperatorKind::LOGAND, FixedOperatorKind::LOGAND_IN_PLACE},
InplaceOpInfo{FixedOperatorKind::LOGIOR, FixedOperatorKind::LOGIOR_IN_PLACE},
InplaceOpInfo{FixedOperatorKind::LOGCLEAR, FixedOperatorKind::LOGCLEAR_IN_PLACE},
InplaceOpInfo{FixedOperatorKind::LOGXOR, FixedOperatorKind::LOGXOR_IN_PLACE},
};
auto dst_var = m_access;
auto dst_form = pool.form<SimpleAtomElement>(SimpleAtom::make_var(dst_var))->to_form(env);
for (const auto& [kind, inplace_kind] : in_place_ops) {
if (!src_as_generic->op().is_fixed(kind)) {
continue;
}
for (int inplace_arg : {0, 1}) {
if (src_as_generic->elts().at(inplace_arg)->to_form(env) != dst_form) {
continue;
}
if (inplace_arg != 0) {
std::swap(src_as_generic->elts().at(0), src_as_generic->elts().at(1));
}
src_as_generic->op() = GenericOperator::make_fixed(inplace_kind);
stack.push_form_element(src_as_generic, true);
return;
}
}
}
stack.push_value_to_reg(m_access, src, true, stack_type);
}
namespace {
@@ -7173,13 +7351,21 @@ void StackStructureDefElement::update_from_stack(const Env&,
result->push_back(this);
}
void StackSpillValueElement::update_from_stack(const Env&,
FormPool&,
void StackSpillValueElement::update_from_stack(const Env& env,
FormPool& pool,
FormStack&,
std::vector<FormElement*>* result,
bool) {
mark_popped();
result->push_back(this);
auto var = m_access;
Form* form =
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, SimpleAtom::make_var(var));
if (m_read_type && env.get_variable_type(var, true) != *m_read_type) {
form = cast_form(form, *m_read_type, pool, env);
}
for (auto elt : form->elts()) {
result->push_back(elt);
}
}
void GetSymbolStringPointer::update_from_stack(const Env&,
+81 -17
View File
@@ -9,6 +9,26 @@
#include "decompiler/util/DecompilerTypeSystem.h"
namespace decompiler {
namespace {
bool nonempty_intersection(const RegSet& a, const RegSet& b) {
for (auto x : a) {
if (b.find(x) != b.end()) {
return true;
}
}
return false;
}
bool can_inline_non_seq_source(const RegisterAccess& src, const Env& env) {
if (!is_stack_slot_access(src)) {
return true;
}
const auto& use_def = env.get_use_def_info(src);
return use_def.use_count() == 1 && use_def.def_count() == 1;
}
} // namespace
std::string FormStack::StackEntry::print(const Env& env) const {
if (destination.has_value()) {
ASSERT(source && !elt);
@@ -116,19 +136,61 @@ Form* FormStack::pop_reg(const RegisterAccess& var,
const Env& env,
bool allow_side_effects,
int begin_idx) {
return pop_reg(var.reg(), barrier, env, allow_side_effects, begin_idx);
}
RegSet modified;
size_t begin = m_stack.size();
if (begin_idx >= 0) {
begin = begin_idx;
}
for (size_t i = begin; i-- > 0;) {
auto& entry = m_stack.at(i);
if (entry.active) {
if (entry.destination.has_value() && same_expression_var(*entry.destination, var)) {
entry.source->get_modified_regs(modified);
if (!allow_side_effects && entry.source->has_side_effects()) {
return nullptr;
}
if (nonempty_intersection(modified, barrier)) {
return nullptr;
}
entry.active = false;
ASSERT(entry.source);
if (entry.non_seq_source.has_value()) {
ASSERT(entry.sequence_point == false);
if (can_inline_non_seq_source(*entry.non_seq_source, env)) {
auto result = pop_reg(*entry.non_seq_source, barrier, env, allow_side_effects, i);
if (result) {
return result;
}
}
}
namespace {
bool nonempty_intersection(const RegSet& a, const RegSet& b) {
for (auto x : a) {
if (b.find(x) != b.end()) {
return true;
return entry.source;
} else {
if (entry.sequence_point) {
return nullptr;
}
if (entry.source) {
ASSERT(!entry.elt);
entry.source->get_modified_regs(modified);
if (!allow_side_effects) {
return nullptr;
}
} else {
ASSERT(entry.elt);
entry.elt->get_modified_regs(modified);
if (!allow_side_effects && entry.elt->has_side_effects()) {
return nullptr;
}
}
}
} else {
if (entry.destination.has_value() && same_expression_var(*entry.destination, var)) {
return nullptr;
}
}
}
return false;
return nullptr;
}
} // namespace
Form* FormStack::pop_reg(Register reg,
const RegSet& barrier,
@@ -164,13 +226,15 @@ Form* FormStack::pop_reg(Register reg,
ASSERT(entry.source);
if (entry.non_seq_source.has_value()) {
ASSERT(entry.sequence_point == false);
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env, allow_side_effects, i);
if (result) {
if (found_orig_out) {
*found_orig_out = true;
*orig_out = *entry.destination;
if (can_inline_non_seq_source(*entry.non_seq_source, env)) {
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env, allow_side_effects, i);
if (result) {
if (found_orig_out) {
*found_orig_out = true;
*orig_out = *entry.destination;
}
return result;
}
return result;
}
}
@@ -325,7 +389,7 @@ std::vector<FormElement*> FormStack::rewrite(FormPool& pool, const Env& env) con
while (keep_going && !result.empty()) {
keep_going = false;
auto last_op_as_set = dynamic_cast<SetVarElement*>(result.back());
if (last_op_as_set && last_op_as_set->dst().reg() == var_to_get.reg()) {
if (last_op_as_set && same_expression_var(last_op_as_set->dst(), var_to_get)) {
result.pop_back();
auto as_one = dynamic_cast<SimpleExpressionElement*>(
last_op_as_set->src()->try_as_single_element());
@@ -384,7 +448,7 @@ std::optional<RegisterAccess> rewrite_to_get_var(std::vector<FormElement*>& defa
while (keep_going && !default_result.empty()) {
keep_going = false;
auto last_op_as_set = dynamic_cast<SetVarElement*>(default_result.back());
if (last_op_as_set && last_op_as_set->dst().reg() == var_to_get.reg() &&
if (last_op_as_set && same_expression_var(last_op_as_set->dst(), var_to_get) &&
(first || last_op_as_set->info().is_compactable)) {
default_result.pop_back();
auto as_one =
+7
View File
@@ -305,6 +305,13 @@ bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out, const Env* cons
}
}
auto as_stack_spill =
dynamic_cast<StackSpillValueElement*>(input->try_as_single_active_element());
if (as_stack_spill) {
got = true;
result = as_stack_spill->access();
}
if (got) {
if (m_kind == Kind::REG) {
return result.reg() == *m_reg;
@@ -18,6 +18,7 @@
#include "fmt/format.h"
#include "third-party/json.hpp"
#include "third-party/zstd/lib/common/xxhash.h"
namespace decompiler {
/*!
@@ -710,6 +711,21 @@ std::string LinkedObjectFile::print_asm_function_disassembly(const std::string&
return result;
}
// Currently, just hashes the contents of every function, this makes it easy to
// compare between games to see if something is identical
void LinkedObjectFile::dump_asm_function_metadata(
std::unordered_map<std::string, std::string>& map) {
ASSERT(segments <= 3);
for (int seg = segments; seg-- > 0;) {
// functions
for (auto& func : functions_by_seg.at(seg)) {
const auto& function_rep = print_function_disassembly(func, seg, false, "");
const auto func_hash = XXH64(function_rep.data(), function_rep.size(), 0);
map.emplace(func.name(), fmt::format("{}", func_hash));
}
}
}
/*!
* Print disassembled functions and data segments.
*/
+1
View File
@@ -67,6 +67,7 @@ class LinkedObjectFile {
bool write_hex,
const std::string& extra_name);
std::string print_asm_function_disassembly(const std::string& my_name);
void dump_asm_function_metadata(std::unordered_map<std::string, std::string>& map);
u32 read_data_word(const DecompilerLabel& label);
const DecompilerLabel& get_label_by_name(const std::string& name) const;
+20 -1
View File
@@ -11,6 +11,7 @@
#include <cstring>
#include <map>
#include <set>
#include <unordered_map>
#include "LinkedObjectFileCreation.h"
@@ -34,6 +35,7 @@
#include "decompiler/data/game_text.h"
#include "decompiler/data/tpage.h"
#include "third-party/json.hpp"
#include "third-party/xdelta3/xdelta3.h"
namespace decompiler {
@@ -630,18 +632,28 @@ void ObjectFileDB::write_object_file_words(const fs::path& output_dir,
void ObjectFileDB::write_disassembly(const fs::path& output_dir,
bool disassemble_data,
bool disassemble_code,
bool print_hex) {
bool print_hex,
bool dump_function_metadata) {
lg::info("- Writing functions...");
Timer timer;
uint32_t total_bytes = 0, total_files = 0;
std::string asm_functions;
std::unordered_map<std::string, std::unordered_map<std::string, std::string>>
file_func_metadata_map = {};
for_each_obj([&](ObjectFileData& obj) {
if (((obj.obj_version == 3 || (obj.obj_version == 5 && obj.linked_data.has_any_functions())) &&
disassemble_code) ||
(obj.obj_version != 3 && disassemble_data)) {
auto file_text = obj.linked_data.print_disassembly(print_hex);
if (dump_function_metadata) {
if (!file_func_metadata_map.contains(obj.to_unique_name())) {
file_func_metadata_map[obj.to_unique_name()] =
std::unordered_map<std::string, std::string>{};
}
obj.linked_data.dump_asm_function_metadata(file_func_metadata_map[obj.to_unique_name()]);
}
asm_functions += obj.linked_data.print_asm_function_disassembly(obj.to_unique_name());
auto file_name = output_dir / (obj.to_unique_name() + ".asm");
@@ -655,6 +667,11 @@ void ObjectFileDB::write_disassembly(const fs::path& output_dir,
total_files++;
file_util::write_text_file(output_dir / "asm_functions.func", asm_functions);
if (dump_function_metadata) {
json data = file_func_metadata_map;
file_util::write_text_file(output_dir / "_func_metadata.json", data.dump(2));
}
lg::info("Wrote functions dumps:");
lg::info(" Total {} files", total_files);
lg::info(" Total {} MB", total_bytes / ((float)(1u << 20u)));
@@ -751,6 +768,7 @@ std::string ObjectFileDB::process_tpages(TextureDB& tex_db,
animated_slots = jak3_animated_texture_slots();
break;
case GameVersion::JakX:
// TODO jakx - Implement animation
break;
default:
ASSERT_NOT_REACHED();
@@ -1109,6 +1127,7 @@ void ObjectFileDB::dump_art_info(const fs::path& output_dir) {
ag_result += "\n";
}
file_util::create_dir_if_needed_for_file(ag_fpath);
file_util::write_text_file(ag_fpath, ag_result);
auto jg_fpath = output_dir / "import" / "joint-nodes.gc";
+2 -1
View File
@@ -196,7 +196,8 @@ class ObjectFileDB {
void write_disassembly(const fs::path& output_dir,
bool disassemble_data,
bool disassemble_code,
bool print_hex);
bool print_hex,
bool dump_function_metadata);
void process_object_file_data(
ObjectFileData& data,
+33 -2
View File
@@ -315,6 +315,10 @@ FieldPrint get_field_print(const std::string& str) {
if (c1 == '1' || c1 == '2') {
c1 = next();
}
if (c1 != 'T' && c1 == 'd') {
printf("HACK: skipping %s\n", str.data());
return handle_custom_prints(field_print, str);
}
ASSERT(c1 == 'T');
// next the name:
@@ -336,9 +340,12 @@ FieldPrint get_field_print(const std::string& str) {
// (format "~Tstack[~D] @ #x~X~%" (-> obj allocated-length) (-> obj stack))
if (num_char == '~') {
num_char = next();
ASSERT(num_char == 'D');
if (num_char != 'D') {
return handle_custom_prints(field_print, str);
}
ASSERT_MSG(num_char == 'D', fmt::format("unexpected: {}", num_char));
num_char = next();
ASSERT(num_char == ']');
ASSERT_MSG(num_char == ']', fmt::format("unexpected: {}", num_char));
// distinguish from dynamic arrays that are set to size 0
field_print.array_size = size = FieldPrint::DYNAMIC_ARRAY;
}
@@ -1022,15 +1029,31 @@ bool get_ptr_offset_constant_nonzero(const SimpleExpression& math, Register base
bool get_ptr_offset(AtomicOp* ir, Register dst, Register base, int* result) {
auto as_set = dynamic_cast<SetVarOp*>(ir);
if (!as_set) {
printf("not a set, actual type: %s\n", typeid(*ir).name());
return false;
}
if (as_set->dst().reg() != dst) {
printf("bad dst");
return false;
}
return get_ptr_offset_constant_nonzero(as_set->src(), base, result);
}
bool get_ptr_offset_load_var_op(AtomicOp* ir, Register dst, Register base, int* result) {
auto as_load = dynamic_cast<LoadVarOp*>(ir);
if (!as_load) {
printf("not a set, actual type: %s\n", typeid(*ir).name());
return false;
}
if (as_load->get_set_destination().reg() != dst) {
printf("bad dst");
return false;
}
return get_ptr_offset_constant_nonzero(as_load->src(), base, result);
}
int identify_array_field(int idx,
Function& function,
TypeInspectorResult* result,
@@ -1050,6 +1073,10 @@ int identify_array_field(int idx,
ptr = get_ptr_offset(get_op, make_gpr(Reg::A3), make_gpr(Reg::GP), &offset);
} else {
ptr = get_ptr_offset(get_op, make_gpr(Reg::A2), make_gpr(Reg::GP), &offset);
// maybe they load it the other way (inline?)
if (!ptr) {
ptr = get_ptr_offset_load_var_op(get_op, make_gpr(Reg::A2), make_gpr(Reg::GP), &offset);
}
}
if (!ptr) {
@@ -1352,6 +1379,10 @@ std::string inspect_inspect_method(Function& inspect_method,
lg::print(" iim: {}\n", inspect_method.name());
TypeInspectorResult result;
ASSERT(type_name == inspect_method.guessed_name.type_name);
if (inspect_method.name() == "(method 3 process-tree)") {
printf("HACK: skipping method\n");
return fmt::format(";; {} TODO: skipped!\n", type_name);
}
TypeFlags flags;
flags.flag = 0;
result.found_flags = dts.lookup_flags(type_name, &flags.flag);
+6 -4
View File
@@ -110,13 +110,14 @@ void clean_up_cond_with_else(FormPool& pool, FormElement* ir, const Env& env) {
*/
void clean_up_until_loop(FormPool& pool, UntilElement* ir, const Env& env) {
auto condition_branch = get_condition_branch(ir->condition);
ASSERT(condition_branch.first);
ASSERT_MSG(condition_branch.first, fmt::format("bad condition branch in {}\n", env.func->name()));
if (condition_branch.first->op()->branch_delay().kind() != IR2_BranchDelay::Kind::NOP) {
ASSERT_MSG(
condition_branch.first->op()->branch_delay().kind() == IR2_BranchDelay::Kind::SET_REG_FALSE,
fmt::format(
"bad delay slot in until loop: {} in {}\n", env.func->name(),
condition_branch.first->op()->branch_delay().to_form(env.file->labels, env).print()));
"bad delay slot in until loop: {} in {}\n",
condition_branch.first->op()->branch_delay().to_form(env.file->labels, env).print(),
env.func->name()));
ir->false_destination = condition_branch.first->op()->branch_delay().var(0);
}
auto replacement = condition_branch.first->op()->get_condition_as_form(pool, env);
@@ -1974,7 +1975,8 @@ void clean_up_while_loops(FormPool& pool, Form* sequence, const Env& env) {
auto condition_branch = get_condition_branch(form_as_while->condition);
ASSERT(condition_branch.first);
ASSERT_MSG(condition_branch.first,
fmt::format("bad conditional branch in {}\n", env.func->name()));
ASSERT(condition_branch.first->op()->branch_delay().kind() == IR2_BranchDelay::Kind::NOP);
// printf("got while condition branch %s\n", condition_branch.first->print(file).c_str());
auto replacement = condition_branch.first->op()->get_condition_as_form(pool, env);
+41 -8
View File
@@ -45,6 +45,8 @@ If the previous let variables appear in the definition of new one, make the let
namespace {
FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool, LetRewriteStats& stats);
FormElement* rewrite_multi_let_as_vector_dot(LetElement* in, const Env& env, FormPool& pool);
bool let_uses_stack_slot_access(const LetElement* in);
std::vector<Form*> path_up_tree(Form* in, const Env&) {
std::vector<Form*> path;
@@ -2409,6 +2411,18 @@ FormElement* rewrite_set_font_single(LetElement* in,
FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool, LetRewriteStats& stats) {
// ordered based on frequency. for best performance, you check the most likely rewrites first!
if (in->entries().size() >= 6) {
auto as_vector_dot = rewrite_multi_let_as_vector_dot(in, env, pool);
if (as_vector_dot) {
stats.vector_dot++;
return as_vector_dot;
}
}
if (let_uses_stack_slot_access(in)) {
return nullptr;
}
auto as_unused = rewrite_empty_let(in, env, pool);
if (as_unused) {
stats.unused++;
@@ -3073,6 +3087,18 @@ FormElement* rewrite_multi_let(LetElement* in,
const Env& env,
FormPool& pool,
LetRewriteStats& stats) {
if (in->entries().size() >= 6) {
auto as_vector_dot = rewrite_multi_let_as_vector_dot(in, env, pool);
if (as_vector_dot) {
stats.vector_dot++;
return as_vector_dot;
}
}
if (let_uses_stack_slot_access(in)) {
return in;
}
if (in->entries().size() >= 2) {
auto as_with_dma_buf_add_bucket = rewrite_with_dma_buf_add_bucket(in, env, pool);
if (as_with_dma_buf_add_bucket) {
@@ -3101,14 +3127,6 @@ FormElement* rewrite_multi_let(LetElement* in,
}
}
if (in->entries().size() >= 6) {
auto as_vector_dot = rewrite_multi_let_as_vector_dot(in, env, pool);
if (as_vector_dot) {
stats.vector_dot++;
return as_vector_dot;
}
}
auto as_font_set_origin = rewrite_set_font_origin(in, env, pool);
if (as_font_set_origin) {
stats.font_method++;
@@ -3569,6 +3587,12 @@ FormElement* rewrite_let_sequence(const std::vector<LetElement*>& in,
const Env& env,
FormPool& pool,
LetRewriteStats& stats) {
for (const auto* let : in) {
if (let_uses_stack_slot_access(let)) {
return nullptr;
}
}
if (in.size() == 3) {
auto as_dma_buffer_add_gs_set = rewrite_dma_buffer_add_gs_set(in, env, pool);
if (as_dma_buffer_add_gs_set) {
@@ -3609,6 +3633,15 @@ Form* insert_cast_for_let(RegisterAccess dst,
return src;
}
bool let_uses_stack_slot_access(const LetElement* in) {
for (const auto& entry : in->entries()) {
if (is_stack_slot_access(entry.dest)) {
return true;
}
}
return false;
}
bool register_can_hold_var(const Register& reg) {
return reg.get_kind() == Reg::FPR || reg.get_kind() == Reg::GPR;
}
+3
View File
@@ -102,6 +102,9 @@ Config make_config_via_json(nlohmann::json& json) {
config.obj_file_name_map_file = json.at("obj_file_name_map_file").get<std::string>();
}
config.disassemble_code = json.at("disassemble_code").get<bool>();
if (json.contains("dump_function_metadata")) {
config.dump_function_metadata = json.at("dump_function_metadata").get<bool>();
}
config.decompile_code = json.at("decompile_code").get<bool>();
if (json.contains("format_code")) {
config.format_code = json.at("format_code").get<bool>();
+1
View File
@@ -108,6 +108,7 @@ struct Config {
std::string all_types_file;
bool disassemble_code = false;
bool dump_function_metadata = false;
bool decompile_code = false;
bool format_code = false;
bool write_scripts = false;
+140 -6
View File
@@ -12103,17 +12103,17 @@
(onground)
(tsurf)
(twall)
(t-ciel)
(t-ceil)
(t-act)
(csmf06)
(csmf07)
(csmf08)
(csmf09)
(on-water)
(csmf11)
(csmf12)
(impact-surf)
(t-bckgnd)
(csmf13)
(csmf14)
(t-ceil-sticky)
(csmf15)
(csmf16)
(csmf17)
@@ -12415,6 +12415,93 @@
(unknown-int34 int32 :offset 18992)
(unknown-int35 int32 :offset 18996)
(unknown-int36 int32 :offset 19000)
(transv-ctrl vector :inline :overlay-at unknown-vector00 :score 1)
(target-transv vector :inline :overlay-at unknown-vector01 :score 1)
(bent-gravity-normal vector :inline :overlay-at unknown-vector02 :score 1)
(last-transv vector :inline :overlay-at unknown-vector10 :score 1)
(draw-offset vector :inline :overlay-at unknown-vector11 :score 1)
(cspace-offset vector :inline :overlay-at unknown-vector12 :score 1)
(anim-collide-offset-world vector :inline :overlay-at unknown-vector14 :score 1)
(old-anim-collide-offset-world vector :inline :overlay-at unknown-vector15 :score 1)
(anim-collide-offset-delta-world vector :inline :overlay-at unknown-vector16 :score 1)
(to-target-pt-xz vector :inline :overlay-at unknown-vector20 :score 1)
(last-to-target-pt-xz vector :inline :overlay-at unknown-vector21 :score 1)
(turn-to-target vector :inline :overlay-at unknown-vector22 :score 1)
(last-turn-to-target vector :inline :overlay-at unknown-vector23 :score 1)
(pad-xz-dir vector :inline :overlay-at unknown-vector30 :score 1)
(last-pad-xz-dir vector :inline :overlay-at unknown-vector31 :score 1)
(force-turn-to-direction vector :inline :overlay-at unknown-vector40 :score 1)
(gravity-normal vector :inline :overlay-at unknown-vector50 :score 1)
(last-gravity-normal vector :inline :overlay-at unknown-vector51 :score 1)
(last-trans-any-surf vector :inline :overlay-at unknown-vector52 :score 1)
(ground-contact-normal vector :inline :overlay-at unknown-vector53 :score 1)
(ground-contact-sphere-center vector :inline :overlay-at unknown-vector55 :score 1)
(low-coverage-tangent vector :inline :overlay-at unknown-vector60 :score 1)
(btransv vector :inline :overlay-at unknown-vector61 :score 1)
(wall-contact-pt vector :inline :overlay-at unknown-vector70 :score 1)
(wall-contact-poly-normal vector :inline :overlay-at unknown-vector71 :score 1)
(actor-contact-pt vector :inline :overlay-at unknown-vector72 :score 1)
(actor-contact-normal vector :inline :overlay-at unknown-vector73 :score 1)
(ctrl-to-hands-offset vector :inline :overlay-at unknown-vector91 :score 1)
(edge-grab-edge-dir vector :inline :overlay-at unknown-vector100 :score 1)
(edge-grab-across-edge-dir vector :inline :overlay-at unknown-vector101 :score 1)
(low-coverage-overhang-plane-normal vector :inline :overlay-at unknown-vector-coverage-2 :score 1)
(low-coverage-tangent-xz vector :inline :overlay-at unknown-vector-coverage-3 :score 1)
(last-trans-leaving-surf vector :inline :overlay-at unknown-vector110 :score 1)
(highest-jump-mark vector :inline :overlay-at unknown-vector111 :score 1)
(wall-contact-normal vector :inline :overlay-at unknown-vector121 :score 1)
(quat-for-control quaternion :inline :overlay-at unknown-quaternion00 :score 1)
(override-quat quaternion :inline :overlay-at unknown-quaternion01 :score 1)
(w-R-c matrix :inline :overlay-at unknown-matrix00 :score 1)
(c-R-w matrix :inline :overlay-at unknown-matrix01 :score 1)
(ctrl-orientation matrix :inline :overlay-at unknown-matrix02 :score 1)
(mod-surface surface :overlay-at unknown-surface00 :score 1)
(current-surface surface :overlay-at unknown-surface01 :score 1)
(override-quat-alpha float :overlay-at unknown-float00 :score 1)
(ctrl-xz-vel float :overlay-at unknown-float01 :score 1)
(velocity-after-thrust float :overlay-at unknown-float02 :score 1)
(turn-to-angle float :overlay-at unknown-float10 :score 1)
(last-turn-to-angle float :overlay-at unknown-float11 :score 1)
(turn-to-magnitude float :overlay-at unknown-float12 :score 1)
(last-turn-to-magnitude float :overlay-at unknown-float13 :score 1)
(pad-magnitude float :overlay-at unknown-float20 :score 1)
(last-pad-magnitude float :overlay-at unknown-float21 :score 1)
(smack-speed-lerp-min float :overlay-at unknown-float40 :score 1)
(force-turn-to-strength float :overlay-at unknown-float41 :score 1)
(force-turn-to-speed float :overlay-at unknown-float50 :score 1)
(ground-local-norm-dot-grav float :overlay-at unknown-float60 :score 1)
(local-slope-z float :overlay-at unknown-float61 :score 1)
(local-slope-x float :overlay-at unknown-float62 :score 1)
(surface-slope-z float :overlay-at unknown-float63 :score 1)
(surface-slope-x float :overlay-at unknown-float64 :score 1)
(blocked-factor float :overlay-at unknown-float70 :score 1)
(blocked-in-air-factor float :overlay-at unknown-float71 :score 1)
(bend-amount float :overlay-at unknown-float80 :score 1)
(bend-target float :overlay-at unknown-float81 :score 1)
(bend-speed float :overlay-at unknown-float82 :score 1)
(average-xz-vel float :overlay-at unknown-float100 :score 1)
(low-coverage-slope-to-next1 float :overlay-at unknown-float-coverage-0 :score 1)
(low-coverage-slope-to-next2 float :overlay-at unknown-float-coverage-2 :score 1)
(idx-of-fastest-xz-vel int32 :overlay-at unknown-int10 :score 1)
(did-move-to-pole-or-max-jump-height int32 :overlay-at unknown-int21 :score 1)
(remaining-ctrl-iterations int32 :overlay-at unknown-int40 :score 1)
(history-data-idx int16 :overlay-at unknown-halfword00 :score 1)
(time-of-last-pad-read time-frame :overlay-at unknown-dword00 :score 1)
(last-time-on-ground time-frame :overlay-at unknown-dword10 :score 1)
(last-time-on-surface time-frame :overlay-at unknown-dword11 :score 1)
(last-time-touching-actor time-frame :overlay-at unknown-dword20 :score 1)
(time-of-last-lc time-frame :overlay-at unknown-dword21 :score 1)
(last-attack-end-time time-frame :overlay-at unknown-dword33 :score 1)
(last-time-of-stuck time-frame :overlay-at unknown-dword36 :score 1)
(last-successful-compute-edge-time time-frame :overlay-at unknown-dword40 :score 1)
(target-attack-id int64 :overlay-at unknown-dword50 :score 1)
(attack-count int64 :overlay-at unknown-dword51 :score 1)
(actor-contact-handle handle :overlay-at unknown-handle00 :score 1)
(danger-mode symbol :overlay-at unknown-symbol30 :score 1)
(cpad cpad-info :overlay-at unknown-cpad-info00 :score 1)
(standard-dynamics dynamics :overlay-at unknown-dynamics00 :score 1)
(transv-history vector 16 :inline :overlay-at unknown-vector-array10 :score 1)
(camera-pos vector :inline :overlay-at unknown-qword00 :score 1)
)
:size-assert #x4a3c ;; #x4a2c
:method-count-assert 65
@@ -12690,9 +12777,17 @@
;; - Types
;; +++effect-control-h:effect-control-flag
(defenum effect-control-flag
:type uint32
:bitfield #t
(event 0)
)
;; ---effect-control-h:effect-control-flag
(deftype effect-control (basic)
((process process-drawable :offset-assert 4)
(flags uint32 :offset-assert 8)
(flags effect-control-flag :offset-assert 8)
(last-frame-group art-joint-anim :offset-assert 12)
(last-frame-num float :offset-assert 16)
(channel-offset int32 :offset-assert 20)
@@ -14454,7 +14549,7 @@
(deftype entity-camera (entity)
(
(connect connectable :inline :offset-assert 64)
(quat quaternion :inline :offset-assert 64)
)
:method-count-assert 27
:size-assert #x50
@@ -19634,6 +19729,43 @@
(wt31)
)
(defenum water-flag
:bitfield #t
:type uint32
(water-marks)
(active)
(can-wade)
(can-swim)
(swim-ground)
(part-splash)
(part-drip)
(wt07)
(use-ocean)
(touch-water)
(wading)
(swimming)
(under-water)
(head-under-water)
(bouncing)
(spawn-drip)
(jump-out)
(tar)
(mud)
(deadly)
(use-ripple-offset)
(no-grab-sound)
(part-rings)
(part-water)
(dark-eco)
(lava)
(wt26)
(wt27)
(wt28)
(wt29)
(wt30)
(wt31)
)
(defenum water-look
(water-anim-sunken-big-room 0)
(water-anim-sunken-first-room-from-entrance 1)
@@ -19720,6 +19852,7 @@
(drip-speed float :offset-assert 272)
(drip-height meters :offset-assert 276)
(drip-mult float :offset-assert 280)
(flag water-flag :overlay-at flags :score 1) ;; added
)
:method-count-assert 17
:size-assert #x11c
@@ -19745,6 +19878,7 @@
(attack-event symbol :offset-assert 192)
(target handle :offset-assert 200)
(flags water-flags :offset-assert 208)
(flag water-flag :overlay-at flags :score 1) ;; added
)
:heap-base #x70
:method-count-assert 30
File diff suppressed because it is too large Load Diff
@@ -4008,5 +4008,11 @@
"vars": {
"gp-0": "active-buffer"
}
},
"target-collision-reaction": {
"vars": {
"sv-96": "moving-flags",
"sv-104": "react-flags"
}
}
}
+3 -3
View File
@@ -2880,7 +2880,7 @@
(shutdown sound-rpc-shutdown :offset 0)
(list-sounds sound-rpc-list-sounds :offset 0)
(unload-music sound-rpc-unload-music :offset 0)
(mirror-mode sound-rpc-set-mirror-mode :overlay-at (-> data 0))
(mirror-mode sound-rpc-set-mirror-mode :offset 0)
)
:method-count-assert 9
:size-assert #x50
@@ -22506,7 +22506,7 @@ Levels store a reference to this which holds all the entities in the level."
)
(deftype entity-camera (entity)
((connect connectable :inline :offset-assert 64)) ;; guess from jak 1
((quat quaternion :inline :offset-assert 64))
:flag-assert #x1b00000050
)
@@ -35329,7 +35329,7 @@ Consists of a header and a list of [[merc-effect]]s."
(_type_) none) ;; 132
(enemy-method-133 (_type_) symbol) ;; 133
(get-attacker (_type_ process attack-info) process-focusable) ;; 134
(enemy-method-135 (_type_ int) sound-id) ;; 135
(play-damage-or-death-sound (_type_ int) sound-id) ;; 135
(enemy-method-136 (_type_) enemy-flag) ;; 136
)
)
@@ -2778,7 +2778,7 @@
[[1, 7], "v1", "drawable-region-prim"]
],
"(method 18 drawable-region-face)": [
[[33, 84], "v1", "(inline-array vector)"]
["_stack_", 56, "(inline-array vector)"]
],
"(method 18 drawable-tree-region-prim)": [
[[22, 49], "s2", "drawable-region-prim"]
@@ -4051,7 +4051,9 @@
[64, "a0", "process-drawable"]
],
"process-drawable2-shock-effect": [[59, "v0", "lightning-tracker"]],
"process-drawable-shock-effect": [[156, "v0", "lightning-tracker"]],
"process-drawable-shock-effect": [
["_stack_", 624, "(pointer lightning-tracker)"]
],
"(method 12 top-anim-joint-control)": [
[8, "a1", "art-joint-anim"],
[40, "a1", "art-joint-anim"]
@@ -5967,7 +5969,7 @@
"(post idle drill-plat)": [[4, "t9", "(function none)"]],
"(post idle grenade-point)": [[122, "v1", "lightning-tracker"]],
"(anon-function 12 strip-obs)": [
[103, "a0", "(pointer entity-actor)"],
["_stack_", 16, "(pointer entity-actor)"],
[287, "v1", "int"]
],
"(method 11 strip-hazard)": [
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -130,7 +130,7 @@
// turn this on if you want extracted level collision to be saved as .obj files in decompiler_out/<game>/collision
"rip_collision": false,
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": true,
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
"rip_streamed_audio": false,
@@ -1005,5 +1005,14 @@
[15, "(function external-art-buffer object)"],
[16, "(function external-art-buffer object)"],
[17, "(function external-art-buffer object)"]
]
],
"editable-player": [
[0, "(function object)"],
[3, "(function object int float object)"],
[4, "(function object int symbol)"],
[31, "(function editable editable-region symbol)"],
[32, "(function editable editable-region symbol)"],
[35, "(function editable symbol)"]
],
"editable": [[101, "(function object editable-filter)"]]
}
+7 -7
View File
@@ -41,9 +41,6 @@
"anim-test-anim-list-handler",
"anim-test-sequence-list-handler",
"anim-tester-get-playing-item",
"start-pilot-recorder",
"(anon-function 10 pilot-recorder)",
"(anon-function 10 sig-recorder)",
// actual asm
"quad-copy!",
"return-from-thread",
@@ -89,7 +86,6 @@
// CFG failed
"draw-inline-array-instance-shrub",
"(method 9 editable-region)", // condition branch assert hit
"test-to-from-spr",
"test-from-spr",
"test-to-spr",
@@ -101,7 +97,6 @@
"adgif-shader<-texture!",
// jak 3
"(method 10 manipulator)",
"(method 46 ff-squad-control)",
"memcpy"
],
@@ -466,7 +461,11 @@
"(anon-function 90 ctywide-obs)": [4],
"(anon-function 10 cty-sniper-turret)": [44],
"(method 33 rub-tower)": [9, 10],
"(method 30 gungame-manager)": [0, 4, 5, 7]
"(method 30 gungame-manager)": [0, 4, 5, 7],
"(method 9 editable-region)": [63],
"(method 10 manipulator)": [4],
"(method 18 mysql-nav-graph)": [0, 1, 2, 3, 4, 7, 9],
"(method 17 nav-mesh-editable)": [0, 1, 2, 7, 9, 24, 28, 33]
},
// Sometimes the game might use format strings that are fetched dynamically,
@@ -582,7 +581,8 @@
[378, 0],
[413, 0]
],
"(trans carry precur-bomb)": [[60, 0]]
"(trans carry precur-bomb)": [[60, 0]],
"hover-nav-graph-output": [[319, 0]]
},
"mips2c_functions_by_name": [
@@ -2465,5 +2465,29 @@
["L198", "(pointer uint8)", 16],
["L197", "(pointer uint16)", 48]
],
"game-task": [["L18", "(array game-task-node-command)"]]
"game-task": [["L18", "(array game-task-node-command)"]],
"editable-player": [
["L1431", "(inline-array vector4w)", 4],
["L1499", "uint64", true]
],
"editable": [
["L724", "rgba", true],
["L725", "rgba", true],
["L726", "rgba", true],
["L727", "rgba", true],
["L728", "rgba", true],
["L729", "rgba", true],
["L730", "rgba", true],
["L680", "vector"],
["L722", "uint64", true],
["L723", "rgba", true]
],
"nav-mesh-editor": [
["L560", "uint64", true],
["L504", "(inline-array triangulation-vert)", 256],
["L505", "(inline-array triangulation-vert)", 256],
["L555", "(pointer int32)", 1024],
["L556", "(inline-array vector)", 1024],
["L557", "uint64", true]
]
}
@@ -7,5 +7,6 @@
"task-manager-init-by-other": 2048,
"race-manager-init-by-other": 1024,
"neo-sat-shield-init-by-other": 64,
"bt-gun-manager-init-by-other": 256
"bt-gun-manager-init-by-other": 256,
"(method 11 tpl-holo-eye)": 384
}
@@ -195,8 +195,9 @@
"(code target-hit)": [[16, "vector"]],
"apply-pos-from-entity": [[208, "collide-query"]],
"target-death-main": [
[16, "event-message-block"],
[96, ["array", "level", 1]]
[16, "event-message-block"]
// this wrong stack cast was the reason Daxter's death quotes scenes didn't work
//[96, ["array", "level", 1]]
],
"find-nearest-focusable": [[48, "vector"]],
"target-gun-joint-pre0": [
@@ -1942,7 +1943,7 @@
"(code wait title-control)": [[16, "event-message-block"]],
"(code startup title-control)": [
[16, ["array", "symbol", 10]],
[64, "event-message-block"], // this memory is reused as both mc-slot-info and event-message-block
[64, "event-message-block"],
[368, ["array", "symbol", 10]]
],
"(method 9 nav-node)": [[48, ["inline-array", "vector", 2]]],
@@ -2519,5 +2520,132 @@
[32, "vector"],
[48, "vector"],
[64, "vector"]
],
"(method 9 editable-array)": [
[16, "vector"],
[96, "vector"]
],
"(method 23 editable-player)": [
[128, "vector"],
[112, "vector"]
],
"execute-move": [
[16, "vector"],
[32, "vector"]
],
"execute-mouse-move": [
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "vector"],
[80, "vector"],
[112, "vector"]
],
"update-manipulator-position": [[16, "vector"]],
"insert-wall": [[32, ["array", "int32", 2]]],
"insert-box": [[32, ["array", "int32", 8]]],
"(method 22 editable)": [
[16, "vector"],
[32, "vector"]
],
"(method 21 editable-entity)": [[80, "vector"]],
"(method 13 editable-plane)": [[64, ["inline-array", "vector", 4]]],
"(method 14 editable-point)": [
[80, ["inline-array", "vector", 4]],
[32, "vector"],
[48, "vector"]
],
"(method 31 editable-face)": [
[16, ["inline-array", "vector", 6]],
[112, ["inline-array", "vector", 6]],
[240, ["array", "editable-point", 6]],
[304, "matrix"]
],
"(method 14 editable-face)": [
[64, ["inline-array", "vector", 4]],
[208, ["inline-array", "vector", 6]],
[304, ["inline-array", "vector", 6]],
[416, "vector"]
],
"(method 13 editable-face)": [[64, ["inline-array", "vector", 6]]],
"(method 10 editable-face)": [[16, ["inline-array", "vector", 6]]],
"(method 37 editable-face)": [[16, ["inline-array", "vector", 6]]],
"(method 10 editable-plane)": [[16, ["inline-array", "vector", 4]]],
"(method 13 editable-array)": [
[96, "vector"],
[160, "vector"]
],
"(method 23 mysql-nav-graph)": [[16, ["inline-array", "vector", 5]]],
"(post draw-closest-minimap nav-graph-editor)": [
[64, ["inline-array", "vector", 5]]
],
"(method 29 nav-graph-editor)": [
[32, "vector"],
[48, ["inline-array", "vector", 2]],
[112, "vector"],
[128, "vector"],
[144, "vector"]
],
"(method 32 nav-graph-editor)": [[32, "vector"]],
"(method 31 nav-graph-editor)": [[16, ["inline-array", "vector", 5]]],
"(method 35 nav-graph-editor)": [[16, ["inline-array", "vector", 4]]],
"(method 37 nav-graph-editor)": [
[80, "vector"],
[880, ["inline-array", "vector", 4]]
],
"update-height": [[16, "vector"]],
"(method 33 nav-graph-editor)": [
[16, "vector"],
[48, ["inline-array", "vector", 2]]
],
"(method 49 nav-graph-editor)": [
[16, "vector"],
[32, "vector"]
],
"(method 47 nav-graph-editor)": [
[48, "vector"],
[96, "vector"],
[128, "vector"]
],
"(method 22 nav-mesh-editor)": [[80, "vector"]],
"(method 10 nav-mesh-poly)": [
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "vector"],
[80, "vector"],
[96, "vector"],
[112, "vector"],
[128, "vector"]
],
"snap-level-navmesh": [
[16, "vector"],
[64, "vector"]
],
"(method 16 nav-mesh-editable)": [
[16, "vector"],
[48, "vector"],
[32, "vector"]
],
"(method 15 nav-mesh-editable)": [[16, "vector"]],
"(method 12 nav-mesh-editable)": [[32, "vector"]],
"(method 14 nav-mesh-editable)": [
[16, ["inline-array", "vector", 4]],
[80, ["inline-array", "vector", 4]]
],
"camera-slave-debug": [
[16, "vector"],
[32, "vector"],
[48, "matrix"],
[128, "curve"]
],
"hover-nav-graph-output": [
[32, "vector"],
[48, "vector"]
],
"(method 25 pilot-recorder)": [[16, ["inline-array", "vector", 2]]],
"(method 22 pilot-recorder)": [
[16, ["inline-array", "vector", 4]],
[80, ["inline-array", "vector", 4]]
]
}
File diff suppressed because it is too large Load Diff
@@ -2164,5 +2164,20 @@
},
"set-font-color": {
"args": ["idx", "clr0", "clr1", "clr2", "clr3"]
},
"(anon-function 101 editable)": {
"vars": {
"gp-0": ["filter-type", "editable-filter"]
}
},
"(method 12 editable-region)": {
"vars": {
"v0-3": ["filter", "editable-filter"]
}
},
"(method 28 pilot-recorder)": {
"vars": {
"v0-0": ["flag", "pilrec-sample-flag"]
}
}
}
File diff suppressed because it is too large Load Diff
+16 -8
View File
@@ -43,15 +43,21 @@
"process_game_count": false,
// write goal imports for art groups
"process_art_groups": false,
// write goal imports for the part group table
"process_part_group_table": false,
// write out a json file containing the art info mapping, run this with all objects allowed
"dump_art_group_info": false,
// write out a json file containing the joint node mapping, run this with all objects allowed
"dump_joint_geo_info": false,
// TODO - not done yet
"dump_joint_geo_info": true,
// write out a json file containing tpage and texture mappings, run with all objects allowed
"dump_tex_info": false,
// write out a json file containing the part group table, run with all objects allowed
// TODO - not done yet
"dump_part_group_table": true,
// set to false to skip adding .STR files to the decompiler database
"read_spools": true,
"read_spools": false,
// write out spool subtitle text, implies read_spools
"process_subtitle_text": false,
// write out spool subtitle images, implies read_spools
@@ -102,15 +108,17 @@
"inputs_file": "decompiler/config/jakx/ntsc_v1/inputs.jsonc",
"art_info_file": "decompiler/config/jakx/ntsc_v1/art_info.jsonc",
"import_deps_file": "decompiler/config/jakx/ntsc_v1/import_deps.jsonc",
"all_types_file": "decompiler/config/ntsc_v1/all-types.gc",
"art_group_dump_file": "decompiler/config/ntsc_v1/art-group-info.min.json",
"joint_node_dump_file": "decompiler/config/ntsc_v1/joint-node-info.min.json",
"tex_dump_file": "decompiler/config/ntsc_v1/tex-info.min.json",
"process_stack_size_file": "decompiler/config/ntsc_v1/process_stack_size_overrides.jsonc",
"art_group_dump_file": "decompiler/config/jakx/ntsc_v1/art-group-info.min.json",
"joint_node_dump_file": "decompiler/config/jakx/ntsc_v1/joint-node-info.min.json",
"tex_dump_file": "decompiler/config/jakx/ntsc_v1/tex-info.min.json",
// TODO - regenerate once sparticle is decompiled
// "part_group_table_dump_file": "decompiler/config/jakx/ntsc_v1/part-groups.min.json",
"process_stack_size_file": "decompiler/config/jakx/ntsc_v1/process_stack_size_overrides.jsonc",
"all_types_file": "decompiler/config/jakx/all-types.gc",
// optional: a predetermined object file name map from a file.
// this will make decompilation naming consistent even if you only run on some objects.
"obj_file_name_map_file": "goal_src/jakx/build/all_objs.json",
// "obj_file_name_map_file": "goal_src/jakx/build/all_objs.json",
////////////////////////////
// LEVEL EXTRACTION
@@ -1,5 +1,3 @@
{
// "gkernel": [
// [17, "(function process symbol)"]
// ]
"profile": [[3, "(function profile-segment-array profile-collapse none)"]]
}
File diff suppressed because one or more lines are too long
+3 -39
View File
@@ -8,48 +8,12 @@
// so you only need to specify it when that's not the case.
// remap names for states and behaviors of these types
"type_remap": {
// "target": "jakb-ag",
// "sidekick": "daxter-ag",
// "wings": "jakb-ag",
// "lightjak-shield": "jakb-ag",
// "freeze-screen": "collectables-ag",
// "red-3-sphere": "gun-ag",
// "gun-dark-3-sphere": "gun-ag",
// "marauder": "marauder-male-ag",
// "glider-ring": "des-glider-ring-ag",
// "flut-racer": "flut-wild-ag",
// "was-pre-heart": "neo-satellite-heart-ag",
// "was-pre-beam": "neo-satellite-game-ring-ag",
// "was-pre-bubble": "neo-satellite-ps-symbols-ag",
// "maker": "dm-robot-ag",
// "mh-wasp": "neo-wasp-ag",
// "factory-boss": "errol-lowres-ag",
// "fac-robotank-turret": "fac-robotank-ag",
// "neo-sat-shield": "neo-satellite-shield-ag",
// "neo-sat": "neo-satellite-ag",
// "power-game-switcher": "switcher-ag",
// "power-game-player": "daxter-pac-man-ag",
// "power-game-glyph": "cipher-ag",
// "power-game-rings": "pow-rings-ag",
// "power-game-chaser": "flitter-ag",
// "power-game-zapper": "grunt-head-ag",
// "gungame-door": "fort-entry-gate-ag",
// "bt-mh-flyer": "bt-wasp-ag",
// "gunship-exploder": "kg-robot-transport-break",
// "gunship-engine": "kg-robot-transport-bomb",
// "protect-gunship": "kg-robot-transport",
// "gunship-missile": "cty-homing-missile"
},
"type_remap": {},
// remap names for types in an entire file (higher priority)
"file_override": {
// "target-indax": { "target": "daxter-ag" } // in target-indax.gc, the remap for 'target' will be set to 'daxter-ag'
},
"file_override": {},
// some art groups (like robotboss-ag) have a name for their model that differs
// from the usual ag-name + "-lod0". you can add those exceptions here.
"joint_node_hacks": {
// "robotboss-ag": "robotboss-basic"
}
"joint_node_hacks": {}
}
+92 -34
View File
@@ -2,73 +2,131 @@
////////////////////////////
// HACKS and ASM FUNCTIONS
////////////////////////////
"types_with_bad_inspect_methods": [
// "game-task-event"
],
"types_with_bad_inspect_methods": ["game-task-event", "game-task-control"],
"no_type_analysis_functions_by_name": [],
// this limits the number of cases in a cond. The first argument is the name of the function.
// the second argument is the name of the first condition in the cond. Use print_cfg to find it out.
// The third argument is the number of cases. If you set it too small it may fail to build the CFG.
"cond_with_else_max_lengths": [
// ["(method 20 res-lump)", "b0", 2],
],
"cond_with_else_max_lengths": [],
// if a cond with an else case is being used a value in a place where it looks wrong
// you can add the function name to this list and it will more aggressively reject this rewrite.
"aggressively_reject_cond_to_value_rewrite": [
// "(method 10 res-lump)",
],
"aggressively_reject_cond_to_value_rewrite": [],
// this provides a hint to the decompiler that these functions will have a lot of inline assembly.
// currently it just leaves pcpyld as an asm op.
"hint_inline_assembly_functions": [],
"asm_functions_by_name": [
// "name=",
// checking boxed type is different now - these make the cfg stuff sad
"name=",
// disabled to get decomp to work
"water-anim-event-handler",
"(anon-function 55 task-control)",
"(method 22 level)",
"(method 11 medius-cache)",
"(method 13 race-line)",
"(method 11 collide-mesh)",
// dma
"symlink2",
// actual asm
"quad-copy!",
"sin-rad",
"cos-rad",
"atan-series-rad",
"sign-float",
"(method 9 matrix)",
"quaternion->matrix-2",
"vector-rotate-y-fast!",
"(method 11 collide-mesh-cache)",
"generic-light-proc",
"dma-count-until-done"
],
// these functions use pairs and the decompiler
// will be less picky about types related to pairs.
"pair_functions_by_name": [
// "ref",
"ref",
"ref&",
"(method 4 pair)",
"last",
"member",
"nmember",
"assoc",
"assoce",
"nassoc",
"nassoce",
"append!",
"delete!",
"delete-car!",
"insert-cons!",
"sort"
],
// If format is used with the wrong number of arguments,
// it will often mess up the decompilation, as the decompiler assumes
// that they used the correct number. This will override the decompiler's
// automatic detection.
"bad_format_strings": {
// "~170h~5d~220h~5d~280h~5,,2f": 3,
"~170h~5d~220h~5d~280h~5,,2f": 3,
"~338h~5d~388h~5d~448h~5,,2f": 3
},
"blocks_ending_in_asm_branch": {
// "light-merge!": [1, 2, 3, 5, 7],
"sqlpipe-query": [21],
"(method 9 editable-region)": [63],
"find-nearest-entity": [7, 9],
// collide-shape
"(method 42 collide-shape)": [0, 1, 2, 3, 4, 7],
"(method 18 collide-shape-prim-mesh)": [2, 3, 4, 5, 6, 7],
"(method 12 collide-shape-prim-sphere)": [
1, 2, 3, 4, 5, 8, 10, 11, 13, 14, 15
],
"(method 12 collide-shape-prim-mesh)": [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16
],
// collide-mesh
"(method 11 collide-mesh)": [2, 4],
"(method 12 collide-mesh-cache)": [0, 1, 2, 3, 4, 5],
"(method 10 collide-mesh)": [2]
},
// Sometimes the game might use format strings that are fetched dynamically,
// for example using the game text lookup method
// Add information about those format instructions here.
// e.g. "function-name":[[op, argc], [op, argc], ...]
// where "op" is the op number for the call to format.
"dynamic_format_arg_counts": {
// "auto-save-post": [[182, 1]],
},
"dynamic_format_arg_counts": {},
"mips2c_functions_by_name": [
// "collide-do-primitives",
// collide-cache
"(method 9 collide-cache-prim)",
"(method 10 collide-cache-prim)",
"(method 17 collide-cache)",
// collide-mesh
"(method 12 collide-mesh)",
"(method 14 collide-mesh)",
"(method 15 collide-mesh)",
// shadow
"shadow-execute",
"shadow-add-double-edges",
"shadow-add-single-edges",
"shadow-add-facing-single-tris",
"shadow-add-double-tris",
"shadow-xform-verts",
"shadow-calc-dual-verts",
"shadow-scissor-edges",
"shadow-scissor-top",
"shadow-init-vars",
"shadow-find-facing-single-tris",
"shadow-find-single-edges",
"shadow-find-facing-double-tris",
"shadow-find-double-edges",
"shadow-add-verts",
"shadow-add-single-tris",
// foreground
"foreground-check-longest-edge-asm",
"foreground-merc",
// merc-blend-shape
"blerc-a-fragment",
"blerc-execute"
],
"mips2c_jump_table_functions": {},
// there are some missing textures. I don't know what the game actually does here.
// the format for entries is [level, tpage, index]
"missing_textures": [
// ["wasintro", 0, 0],
],
"missing_textures": [],
// some object files have garbage pad data at the end which makes the decompiler
// assume they must be different files, such as the art group for orb-cache-top.
// this just suppresses a message.
+370 -370
View File
@@ -9,377 +9,377 @@
// you want to run on the entire game.
"dgo_names": [
// engine files
"CGO/ART.CGO",
"CGO/COMMON.CGO",
"CGO/ENGINE.CGO",
// "CGO/ART.CGO",
// "CGO/COMMON.CGO",
// "CGO/ENGINE.CGO",
"CGO/KERNEL.CGO",
"CGO/GAME.CGO"
// "DGO/ASHCRED.DGO",
// "DGO/ASHLEV.DGO",
// "DGO/ASHVL.DGO",
// "DGO/ASHVL2.DGO",
// "DGO/ASHVL3.DGO",
// "DGO/ATL.DGO",
// "DGO/ATOLLART.DGO",
// "DGO/ATOLLCTF.DGO",
// "DGO/ATOLLS.DGO",
// "DGO/ATOPLOW.DGO",
// "DGO/ATX.DGO",
// "DGO/BEARL.DGO",
// "DGO/BOBCL.DGO",
// "DGO/BRDROOM.DGO",
// "DGO/BRDROOMF.DGO",
// "DGO/CANFOOT.DGO",
// "DGO/CANSPARS.DGO",
// "DGO/CANSPARW.DGO",
// "DGO/CANTBOX.DGO",
// "DGO/CANYONS.DGO",
// "DGO/CANYONTT.DGO",
// "DGO/CANYONW.DGO",
// "DGO/CARS.DGO",
// "DGO/CHEEL.DGO",
// "DGO/CLF.DGO",
// "DGO/CLFX.DGO",
// "DGO/CLIFCTF.DGO",
// "DGO/CLIFFART.DGO",
// "DGO/CLIFFSS.DGO",
// "DGO/CLIFHUNT.DGO",
// "DGO/CLIFTRN.DGO",
// "DGO/CNSPFOOT.DGO",
// "DGO/CNSPTBOX.DGO",
// "DGO/CNSPTT.DGO",
// "DGO/COL.DGO",
// "DGO/COLART.DGO",
// "DGO/COLICLCT.DGO",
// "DGO/COLICTF.DGO",
// "DGO/COLIREV.DGO",
// "DGO/COLISEUS.DGO",
// "DGO/COLX.DGO",
// "DGO/COUGL.DGO",
// "DGO/CREDITS.DGO",
// "DGO/CSX.DGO",
// "DGO/CSY.DGO",
// "DGO/CYA.DGO",
// "DGO/CYB.DGO",
// "DGO/CYC.DGO",
// "DGO/CYD.DGO",
// "DGO/CYE.DGO",
// "DGO/CYX.DGO",
// "DGO/CYY.DGO",
// "DGO/DAXCRED.DGO",
// "DGO/DAXLEV.DGO",
// "DGO/DAXTL.DGO",
// "DGO/DESACTF.DGO",
// "DGO/DESARENS.DGO",
// "DGO/DESART.DGO",
// "DGO/DESCLCT.DGO",
// "DGO/DESHUNT.DGO",
// "DGO/DESHUNT2.DGO",
// "DGO/DESISLES.DGO",
// "DGO/DESRAPT.DGO",
// "DGO/DESREV.DGO",
// "DGO/DETHRACE.DGO",
// "DGO/DISLEART.DGO",
// "DGO/DISLECTF.DGO",
// "DGO/DKA.DGO",
// "DGO/DKB.DGO",
// "DGO/DKC.DGO",
// "DGO/DKD.DGO",
// "DGO/DKE.DGO",
// "DGO/DKKRFOOT.DGO",
// "DGO/DKKRTBOX.DGO",
// "DGO/DKKRTT.DGO",
// "DGO/DKKX.DGO",
// "DGO/DKKY.DGO",
// "DGO/DKX.DGO",
// "DGO/DOCKFOOT.DGO",
// "DGO/DOCKKRAS.DGO",
// "DGO/DOCKKRAW.DGO",
// "DGO/DOCKSS.DGO",
// "DGO/DOCKSTT.DGO",
// "DGO/DOCKSW.DGO",
// "DGO/DOCKTBOX.DGO",
// "DGO/DRA.DGO",
// "DGO/DRB.DGO",
// "DGO/DRC.DGO",
// "DGO/DRD.DGO",
// "DGO/DRDKFOOT.DGO",
// "DGO/DRDKTBOX.DGO",
// "DGO/DRDKTT.DGO",
// "DGO/DRDX.DGO",
// "DGO/DRDY.DGO",
// "DGO/DROMDOCS.DGO",
// "DGO/DROMDOCW.DGO",
// "DGO/DROMES.DGO",
// "DGO/DROMETT.DGO",
// "DGO/DROMEW.DGO",
// "DGO/DROMEX.DGO",
// "DGO/DROMFOOT.DGO",
// "DGO/DROMTBOX.DGO",
// "DGO/DRONE.DGO",
// "DGO/DRX.DGO",
// "DGO/DRY.DGO",
// "DGO/DSI.DGO",
// "DGO/DSR.DGO",
// "DGO/DSRX.DGO",
// "DGO/DSX.DGO",
// "DGO/EIGHT.DGO",
// "DGO/EIGHTB.DGO",
// "DGO/FALCL.DGO",
// "DGO/FMVLEV.DGO",
// "DGO/FOXL.DGO",
// "DGO/GARAGE.DGO",
// "DGO/GARAGEB.DGO",
// "DGO/GILAL.DGO",
// "DGO/GTBCRED.DGO",
// "DGO/GTBLEV.DGO",
// "DGO/GTBVL.DGO",
// "DGO/HAVENS.DGO",
// "DGO/HAVENW.DGO",
// "DGO/HAVJUNGS.DGO",
// "DGO/HAVJUNGW.DGO",
// "DGO/HAVNFOOT.DGO",
// "DGO/HAVNTBOX.DGO",
// "DGO/HAVSEWS.DGO",
// "DGO/HAVSEWW.DGO",
// "DGO/HAVTFOOT.DGO",
// "DGO/HAVTOURS.DGO",
// "DGO/HAVTOURW.DGO",
// "DGO/HAVTT.DGO",
// "DGO/HAVTTBOX.DGO",
// "DGO/HJNGFOOT.DGO",
// "DGO/HJX.DGO",
// "DGO/HJY.DGO",
// "DGO/HSX.DGO",
// "DGO/HSY.DGO",
// "DGO/HVA.DGO",
// "DGO/HVB.DGO",
// "DGO/HVC.DGO",
// "DGO/HVD.DGO",
// "DGO/HVE.DGO",
// "DGO/HVJGTBOX.DGO",
// "DGO/HVJGTT.DGO",
// "DGO/HVSWFOOT.DGO",
// "DGO/HVSWTBOX.DGO",
// "DGO/HVSWTT.DGO",
// "DGO/HVTRTT.DGO",
// "DGO/HVX.DGO",
// "DGO/HVY.DGO",
// "DGO/IBX.DGO",
// "DGO/IBY.DGO",
// "DGO/ICA.DGO",
// "DGO/ICB.DGO",
// "DGO/ICBGTT.DGO",
// "DGO/ICC.DGO",
// "DGO/ICD.DGO",
// "DGO/ICEBERGS.DGO",
// "DGO/ICEBERGW.DGO",
// "DGO/ICEBFOOT.DGO",
// "DGO/ICEBTBOX.DGO",
// "DGO/ICEFOOT.DGO",
// "DGO/ICEPASSS.DGO",
// "DGO/ICEPASSW.DGO",
// "DGO/ICEPFOOT.DGO",
// "DGO/ICEPTBOX.DGO",
// "DGO/ICES.DGO",
// "DGO/ICETBOX.DGO",
// "DGO/ICETFOOT.DGO",
// "DGO/ICETOURS.DGO",
// "DGO/ICETOURW.DGO",
// "DGO/ICETRN.DGO",
// "DGO/ICETT.DGO",
// "DGO/ICETTBOX.DGO",
// "DGO/ICEW.DGO",
// "DGO/ICPSTT.DGO",
// "DGO/ICTRTT.DGO",
// "DGO/ICX.DGO",
// "DGO/ICY.DGO",
// "DGO/IPX.DGO",
// "DGO/IPY.DGO",
// "DGO/JAKCRED.DGO",
// "DGO/JAKLEV.DGO",
// "DGO/JAKVL.DGO",
// "DGO/JGA.DGO",
// "DGO/JGB.DGO",
// "DGO/JGC.DGO",
// "DGO/JGD.DGO",
// "DGO/JGE.DGO",
// "DGO/JGF.DGO",
// "DGO/JGG.DGO",
// "DGO/JGX.DGO",
// "DGO/JGY.DGO",
// "DGO/JKALEV.DGO",
// "DGO/JKBLEV.DGO",
// "DGO/JKCLEV.DGO",
// "DGO/JUNGFOOT.DGO",
// "DGO/JUNGLES.DGO",
// "DGO/JUNGLETT.DGO",
// "DGO/JUNGLEW.DGO",
// "DGO/JUNGTBOX.DGO",
// "DGO/JUNGTRN.DGO",
// "DGO/KAELEV.DGO",
// "DGO/KCR.DGO",
// "DGO/KCROSART.DGO",
// "DGO/KCROSCTF.DGO",
// "DGO/KCROSSS.DGO",
// "DGO/KCRSCLCT.DGO",
// "DGO/KCRSPLOW.DGO",
// "DGO/KCRX.DGO",
// "DGO/KEICRED.DGO",
// "DGO/KIELEV.DGO",
// "DGO/KIEVL.DGO",
// "DGO/KLECRED.DGO",
// "DGO/KLELEV.DGO",
// "DGO/KLEVL.DGO",
// "DGO/KLEVL2.DGO",
// "DGO/KRA.DGO",
// "DGO/KRASFOOT.DGO",
// "DGO/KRASS.DGO",
// "DGO/KRASTBOX.DGO",
// "DGO/KRASTRN.DGO",
// "DGO/KRASTT.DGO",
// "DGO/KRASW.DGO",
// "DGO/KRATFOOT.DGO",
// "DGO/KRATOURS.DGO",
// "DGO/KRATOURW.DGO",
// "DGO/KRATTBOX.DGO",
// "DGO/KRB.DGO",
// "DGO/KRC.DGO",
// "DGO/KRTRTT.DGO",
// "DGO/KRX.DGO",
// "DGO/KRY.DGO",
// "DGO/LEOPL.DGO",
// "DGO/MENU2.DGO",
// "DGO/MENUMAP.DGO",
// "DGO/MONGL.DGO",
// "DGO/OSMLEV.DGO",
// "DGO/PANTL.DGO",
// "DGO/PEAKFOOT.DGO",
// "DGO/PEAKS.DGO",
// "DGO/PEAKTBOX.DGO",
// "DGO/PEAKTT.DGO",
// "DGO/PEAKW.DGO",
// "DGO/PECCRED.DGO",
// "DGO/PECLEV.DGO",
// "DGO/PECVL.DGO",
// "DGO/PKA.DGO",
// "DGO/PKB.DGO",
// "DGO/PKC.DGO",
// "DGO/PKD.DGO",
// "DGO/PKE.DGO",
// "DGO/PKX.DGO",
// "DGO/POSSL.DGO",
// "DGO/RACEWEAP.DGO",
// "DGO/RATLEV.DGO",
// "DGO/RAYCRED.DGO",
// "DGO/RAYLEV.DGO",
// "DGO/RAYVL.DGO",
// "DGO/RAYVL2.DGO",
// "DGO/RAZCRED.DGO",
// "DGO/RAZLEV.DGO",
// "DGO/RAZVL.DGO",
// "DGO/RTH.DGO",
// "DGO/RUSTYH.DGO",
// "DGO/S2A.DGO",
// "DGO/S3A.DGO",
// "DGO/SBWLCTF.DGO",
// "DGO/SEWERS.DGO",
// "DGO/SEWERTT.DGO",
// "DGO/SEWERW.DGO",
// "DGO/SEWFOOT.DGO",
// "DGO/SEWTBOX.DGO",
// "DGO/SIGCRED.DGO",
// "DGO/SIGLEV.DGO",
// "DGO/SIGVL.DGO",
// "DGO/SIGVL2.DGO",
// "DGO/SIGVL3.DGO",
// "DGO/SNAKL.DGO",
// "DGO/SNO.DGO",
// "DGO/SNOBART.DGO",
// "DGO/SNOBOWLS.DGO",
// "DGO/SNOWFOOT.DGO",
// "DGO/SNOWS.DGO",
// "DGO/SNOWTBOX.DGO",
// "DGO/SNOWTRN2.DGO",
// "DGO/SNOWTT.DGO",
// "DGO/SNOX.DGO",
// "DGO/SNW.DGO",
// "DGO/SNWX.DGO",
// "DGO/SPA.DGO",
// "DGO/SPARFOOT.DGO",
// "DGO/SPARGUSS.DGO",
// "DGO/SPARGUSW.DGO",
// "DGO/SPARTEMS.DGO",
// "DGO/SPARTEMW.DGO",
// "DGO/SPARTT.DGO",
// "DGO/SPATFOOT.DGO",
// "DGO/SPATOURS.DGO",
// "DGO/SPATOURW.DGO",
// "DGO/SPATTBOX.DGO",
// "DGO/SPB.DGO",
// "DGO/SPC.DGO",
// "DGO/SPD.DGO",
// "DGO/SPE.DGO",
// "DGO/SPRGSTBX.DGO",
// "DGO/SPTMFOOT.DGO",
// "DGO/SPTMTBOX.DGO",
// "DGO/SPTMTT.DGO",
// "DGO/SPTRTT.DGO",
// "DGO/SPX.DGO",
// "DGO/SPY.DGO",
// "DGO/STX.DGO",
// "DGO/STY.DGO",
// "DGO/SWA.DGO",
// "DGO/SWB.DGO",
// "DGO/SWC.DGO",
// "DGO/SWD.DGO",
// "DGO/SWE.DGO",
// "DGO/SWF.DGO",
// "DGO/SWX.DGO",
// "DGO/TARLEV.DGO",
// "DGO/TEMPFOOT.DGO",
// "DGO/TEMPLES.DGO",
// "DGO/TEMPLETT.DGO",
// "DGO/TEMPLEW.DGO",
// "DGO/TEMPTBOX.DGO",
// "DGO/THACRED.DGO",
// "DGO/THALEV.DGO",
// "DGO/THAVL.DGO",
// "DGO/THAVL2.DGO",
// "DGO/THAVL3.DGO",
// "DGO/THBCRED.DGO",
// "DGO/THBLEV.DGO",
// "DGO/THBVL.DGO",
// "DGO/THBVL2.DGO",
// "DGO/THBVL3.DGO",
// "DGO/THCCRED.DGO",
// "DGO/THCLEV.DGO",
// "DGO/THCVL.DGO",
// "DGO/THCVL2.DGO",
// "DGO/THCVL3.DGO",
// "DGO/TIGEL.DGO",
// "DGO/TOADL.DGO",
// "DGO/TORCRED.DGO",
// "DGO/TORLEV.DGO",
// "DGO/TORVL.DGO",
// "DGO/TORVL2.DGO",
// "DGO/TORVL3.DGO",
// "DGO/TPA.DGO",
// "DGO/TPB.DGO",
// "DGO/TPC.DGO",
// "DGO/TPD.DGO",
// "DGO/TPE.DGO",
// "DGO/TPX.DGO",
// "DGO/TPY.DGO",
// "DGO/TURTL.DGO",
// "DGO/UR8CRED.DGO",
// "DGO/UR8LEV.DGO",
// "DGO/UR8VL.DGO",
// "DGO/UR8VL2.DGO",
// "DGO/UR8VL3.DGO",
// "DGO/WOLFL.DGO",
// "DGO/WOMBL.DGO",
// "DGO/XIMLEV.DGO"
"CGO/GAME.CGO",
"DGO/ASHCRED.DGO",
"DGO/ASHLEV.DGO",
"DGO/ASHVL.DGO",
"DGO/ASHVL2.DGO",
"DGO/ASHVL3.DGO",
"DGO/ATL.DGO",
"DGO/ATOLLART.DGO",
"DGO/ATOLLCTF.DGO",
"DGO/ATOLLS.DGO",
"DGO/ATOPLOW.DGO",
"DGO/ATX.DGO",
"DGO/BEARL.DGO",
"DGO/BOBCL.DGO",
"DGO/BRDROOM.DGO",
"DGO/BRDROOMF.DGO",
"DGO/CANFOOT.DGO",
"DGO/CANSPARS.DGO",
"DGO/CANSPARW.DGO",
"DGO/CANTBOX.DGO",
"DGO/CANYONS.DGO",
"DGO/CANYONTT.DGO",
"DGO/CANYONW.DGO",
"DGO/CARS.DGO",
"DGO/CHEEL.DGO",
"DGO/CLF.DGO",
"DGO/CLFX.DGO",
"DGO/CLIFCTF.DGO",
"DGO/CLIFFART.DGO",
"DGO/CLIFFSS.DGO",
"DGO/CLIFHUNT.DGO",
"DGO/CLIFTRN.DGO",
"DGO/CNSPFOOT.DGO",
"DGO/CNSPTBOX.DGO",
"DGO/CNSPTT.DGO",
"DGO/COL.DGO",
"DGO/COLART.DGO",
"DGO/COLICLCT.DGO",
"DGO/COLICTF.DGO",
"DGO/COLIREV.DGO",
"DGO/COLISEUS.DGO",
"DGO/COLX.DGO",
"DGO/COUGL.DGO",
"DGO/CREDITS.DGO",
"DGO/CSX.DGO",
"DGO/CSY.DGO",
"DGO/CYA.DGO",
"DGO/CYB.DGO",
"DGO/CYC.DGO",
"DGO/CYD.DGO",
"DGO/CYE.DGO",
"DGO/CYX.DGO",
"DGO/CYY.DGO",
"DGO/DAXCRED.DGO",
"DGO/DAXLEV.DGO",
"DGO/DAXTL.DGO",
"DGO/DESACTF.DGO",
"DGO/DESARENS.DGO",
"DGO/DESART.DGO",
"DGO/DESCLCT.DGO",
"DGO/DESHUNT.DGO",
"DGO/DESHUNT2.DGO",
"DGO/DESISLES.DGO",
"DGO/DESRAPT.DGO",
"DGO/DESREV.DGO",
"DGO/DETHRACE.DGO",
"DGO/DISLEART.DGO",
"DGO/DISLECTF.DGO",
"DGO/DKA.DGO",
"DGO/DKB.DGO",
"DGO/DKC.DGO",
"DGO/DKD.DGO",
"DGO/DKE.DGO",
"DGO/DKKRFOOT.DGO",
"DGO/DKKRTBOX.DGO",
"DGO/DKKRTT.DGO",
"DGO/DKKX.DGO",
"DGO/DKKY.DGO",
"DGO/DKX.DGO",
"DGO/DOCKFOOT.DGO",
"DGO/DOCKKRAS.DGO",
"DGO/DOCKKRAW.DGO",
"DGO/DOCKSS.DGO",
"DGO/DOCKSTT.DGO",
"DGO/DOCKSW.DGO",
"DGO/DOCKTBOX.DGO",
"DGO/DRA.DGO",
"DGO/DRB.DGO",
"DGO/DRC.DGO",
"DGO/DRD.DGO",
"DGO/DRDKFOOT.DGO",
"DGO/DRDKTBOX.DGO",
"DGO/DRDKTT.DGO",
"DGO/DRDX.DGO",
"DGO/DRDY.DGO",
"DGO/DROMDOCS.DGO",
"DGO/DROMDOCW.DGO",
"DGO/DROMES.DGO",
"DGO/DROMETT.DGO",
"DGO/DROMEW.DGO",
"DGO/DROMEX.DGO",
"DGO/DROMFOOT.DGO",
"DGO/DROMTBOX.DGO",
"DGO/DRONE.DGO",
"DGO/DRX.DGO",
"DGO/DRY.DGO",
"DGO/DSI.DGO",
"DGO/DSR.DGO",
"DGO/DSRX.DGO",
"DGO/DSX.DGO",
"DGO/EIGHT.DGO",
"DGO/EIGHTB.DGO",
"DGO/FALCL.DGO",
"DGO/FMVLEV.DGO",
"DGO/FOXL.DGO",
"DGO/GARAGE.DGO",
"DGO/GARAGEB.DGO",
"DGO/GILAL.DGO",
"DGO/GTBCRED.DGO",
"DGO/GTBLEV.DGO",
"DGO/GTBVL.DGO",
"DGO/HAVENS.DGO",
"DGO/HAVENW.DGO",
"DGO/HAVJUNGS.DGO",
"DGO/HAVJUNGW.DGO",
"DGO/HAVNFOOT.DGO",
"DGO/HAVNTBOX.DGO",
"DGO/HAVSEWS.DGO",
"DGO/HAVSEWW.DGO",
"DGO/HAVTFOOT.DGO",
"DGO/HAVTOURS.DGO",
"DGO/HAVTOURW.DGO",
"DGO/HAVTT.DGO",
"DGO/HAVTTBOX.DGO",
"DGO/HJNGFOOT.DGO",
"DGO/HJX.DGO",
"DGO/HJY.DGO",
"DGO/HSX.DGO",
"DGO/HSY.DGO",
"DGO/HVA.DGO",
"DGO/HVB.DGO",
"DGO/HVC.DGO",
"DGO/HVD.DGO",
"DGO/HVE.DGO",
"DGO/HVJGTBOX.DGO",
"DGO/HVJGTT.DGO",
"DGO/HVSWFOOT.DGO",
"DGO/HVSWTBOX.DGO",
"DGO/HVSWTT.DGO",
"DGO/HVTRTT.DGO",
"DGO/HVX.DGO",
"DGO/HVY.DGO",
"DGO/IBX.DGO",
"DGO/IBY.DGO",
"DGO/ICA.DGO",
"DGO/ICB.DGO",
"DGO/ICBGTT.DGO",
"DGO/ICC.DGO",
"DGO/ICD.DGO",
"DGO/ICEBERGS.DGO",
"DGO/ICEBERGW.DGO",
"DGO/ICEBFOOT.DGO",
"DGO/ICEBTBOX.DGO",
"DGO/ICEFOOT.DGO",
"DGO/ICEPASSS.DGO",
"DGO/ICEPASSW.DGO",
"DGO/ICEPFOOT.DGO",
"DGO/ICEPTBOX.DGO",
"DGO/ICES.DGO",
"DGO/ICETBOX.DGO",
"DGO/ICETFOOT.DGO",
"DGO/ICETOURS.DGO",
"DGO/ICETOURW.DGO",
"DGO/ICETRN.DGO",
"DGO/ICETT.DGO",
"DGO/ICETTBOX.DGO",
"DGO/ICEW.DGO",
"DGO/ICPSTT.DGO",
"DGO/ICTRTT.DGO",
"DGO/ICX.DGO",
"DGO/ICY.DGO",
"DGO/IPX.DGO",
"DGO/IPY.DGO",
"DGO/JAKCRED.DGO",
"DGO/JAKLEV.DGO",
"DGO/JAKVL.DGO",
"DGO/JGA.DGO",
"DGO/JGB.DGO",
"DGO/JGC.DGO",
"DGO/JGD.DGO",
"DGO/JGE.DGO",
"DGO/JGF.DGO",
"DGO/JGG.DGO",
"DGO/JGX.DGO",
"DGO/JGY.DGO",
"DGO/JKALEV.DGO",
"DGO/JKBLEV.DGO",
"DGO/JKCLEV.DGO",
"DGO/JUNGFOOT.DGO",
"DGO/JUNGLES.DGO",
"DGO/JUNGLETT.DGO",
"DGO/JUNGLEW.DGO",
"DGO/JUNGTBOX.DGO",
"DGO/JUNGTRN.DGO",
"DGO/KAELEV.DGO",
"DGO/KCR.DGO",
"DGO/KCROSART.DGO",
"DGO/KCROSCTF.DGO",
"DGO/KCROSSS.DGO",
"DGO/KCRSCLCT.DGO",
"DGO/KCRSPLOW.DGO",
"DGO/KCRX.DGO",
"DGO/KEICRED.DGO",
"DGO/KIELEV.DGO",
"DGO/KIEVL.DGO",
"DGO/KLECRED.DGO",
"DGO/KLELEV.DGO",
"DGO/KLEVL.DGO",
"DGO/KLEVL2.DGO",
"DGO/KRA.DGO",
"DGO/KRASFOOT.DGO",
"DGO/KRASS.DGO",
"DGO/KRASTBOX.DGO",
"DGO/KRASTRN.DGO",
"DGO/KRASTT.DGO",
"DGO/KRASW.DGO",
"DGO/KRATFOOT.DGO",
"DGO/KRATOURS.DGO",
"DGO/KRATOURW.DGO",
"DGO/KRATTBOX.DGO",
"DGO/KRB.DGO",
"DGO/KRC.DGO",
"DGO/KRTRTT.DGO",
"DGO/KRX.DGO",
"DGO/KRY.DGO",
"DGO/LEOPL.DGO",
"DGO/MENU2.DGO",
"DGO/MENUMAP.DGO",
"DGO/MONGL.DGO",
"DGO/OSMLEV.DGO",
"DGO/PANTL.DGO",
"DGO/PEAKFOOT.DGO",
"DGO/PEAKS.DGO",
"DGO/PEAKTBOX.DGO",
"DGO/PEAKTT.DGO",
"DGO/PEAKW.DGO",
"DGO/PECCRED.DGO",
"DGO/PECLEV.DGO",
"DGO/PECVL.DGO",
"DGO/PKA.DGO",
"DGO/PKB.DGO",
"DGO/PKC.DGO",
"DGO/PKD.DGO",
"DGO/PKE.DGO",
"DGO/PKX.DGO",
"DGO/POSSL.DGO",
"DGO/RACEWEAP.DGO",
"DGO/RATLEV.DGO",
"DGO/RAYCRED.DGO",
"DGO/RAYLEV.DGO",
"DGO/RAYVL.DGO",
"DGO/RAYVL2.DGO",
"DGO/RAZCRED.DGO",
"DGO/RAZLEV.DGO",
"DGO/RAZVL.DGO",
"DGO/RTH.DGO",
"DGO/RUSTYH.DGO",
"DGO/S2A.DGO",
"DGO/S3A.DGO",
"DGO/SBWLCTF.DGO",
"DGO/SEWERS.DGO",
"DGO/SEWERTT.DGO",
"DGO/SEWERW.DGO",
"DGO/SEWFOOT.DGO",
"DGO/SEWTBOX.DGO",
"DGO/SIGCRED.DGO",
"DGO/SIGLEV.DGO",
"DGO/SIGVL.DGO",
"DGO/SIGVL2.DGO",
"DGO/SIGVL3.DGO",
"DGO/SNAKL.DGO",
"DGO/SNO.DGO",
"DGO/SNOBART.DGO",
"DGO/SNOBOWLS.DGO",
"DGO/SNOWFOOT.DGO",
"DGO/SNOWS.DGO",
"DGO/SNOWTBOX.DGO",
"DGO/SNOWTRN2.DGO",
"DGO/SNOWTT.DGO",
"DGO/SNOX.DGO",
"DGO/SNW.DGO",
"DGO/SNWX.DGO",
"DGO/SPA.DGO",
"DGO/SPARFOOT.DGO",
"DGO/SPARGUSS.DGO",
"DGO/SPARGUSW.DGO",
"DGO/SPARTEMS.DGO",
"DGO/SPARTEMW.DGO",
"DGO/SPARTT.DGO",
"DGO/SPATFOOT.DGO",
"DGO/SPATOURS.DGO",
"DGO/SPATOURW.DGO",
"DGO/SPATTBOX.DGO",
"DGO/SPB.DGO",
"DGO/SPC.DGO",
"DGO/SPD.DGO",
"DGO/SPE.DGO",
"DGO/SPRGSTBX.DGO",
"DGO/SPTMFOOT.DGO",
"DGO/SPTMTBOX.DGO",
"DGO/SPTMTT.DGO",
"DGO/SPTRTT.DGO",
"DGO/SPX.DGO",
"DGO/SPY.DGO",
"DGO/STX.DGO",
"DGO/STY.DGO",
"DGO/SWA.DGO",
"DGO/SWB.DGO",
"DGO/SWC.DGO",
"DGO/SWD.DGO",
"DGO/SWE.DGO",
"DGO/SWF.DGO",
"DGO/SWX.DGO",
"DGO/TARLEV.DGO",
"DGO/TEMPFOOT.DGO",
"DGO/TEMPLES.DGO",
"DGO/TEMPLETT.DGO",
"DGO/TEMPLEW.DGO",
"DGO/TEMPTBOX.DGO",
"DGO/THACRED.DGO",
"DGO/THALEV.DGO",
"DGO/THAVL.DGO",
"DGO/THAVL2.DGO",
"DGO/THAVL3.DGO",
"DGO/THBCRED.DGO",
"DGO/THBLEV.DGO",
"DGO/THBVL.DGO",
"DGO/THBVL2.DGO",
"DGO/THBVL3.DGO",
"DGO/THCCRED.DGO",
"DGO/THCLEV.DGO",
"DGO/THCVL.DGO",
"DGO/THCVL2.DGO",
"DGO/THCVL3.DGO",
"DGO/TIGEL.DGO",
"DGO/TOADL.DGO",
"DGO/TORCRED.DGO",
"DGO/TORLEV.DGO",
"DGO/TORVL.DGO",
"DGO/TORVL2.DGO",
"DGO/TORVL3.DGO",
"DGO/TPA.DGO",
"DGO/TPB.DGO",
"DGO/TPC.DGO",
"DGO/TPD.DGO",
"DGO/TPE.DGO",
"DGO/TPX.DGO",
"DGO/TPY.DGO",
"DGO/TURTL.DGO",
"DGO/UR8CRED.DGO",
"DGO/UR8LEV.DGO",
"DGO/UR8VL.DGO",
"DGO/UR8VL2.DGO",
"DGO/UR8VL3.DGO",
"DGO/WOLFL.DGO",
"DGO/WOMBL.DGO",
"DGO/XIMLEV.DGO"
],
"levels_to_extract": [],
File diff suppressed because one or more lines are too long
@@ -1,6 +1,14 @@
{
// "math": [
// ["L108", "(pointer float)", 32],
// ["L109", "(pointer float)", 32]
// ],
"ambient-h": [["L1", "(inline-array talker-speech-class)", 233]],
"pat-h": [["L1", "(inline-array pat-mode-info)", 4]],
"foreground-h": [["L4", "(pointer bucket-id-16)", 462]],
"texture-anim-h": [["L1", "(pointer uint8)", 256]],
"process-nettable-h": [["L13", "(pointer uint32)", 95]],
"math": [
["L109", "(pointer float)", 32],
["L108", "(pointer float)", 32]
],
"timer-h": [["L15", "(pointer uint32)", 12]],
"game-task-h": [["L178", "(pointer text-id)", 24]],
"profile": [["L3", "(inline-array profile-spec)", 13]]
}
File diff suppressed because one or more lines are too long
@@ -1,4 +1,2 @@
// This overrides the stack size for calls to stack-size-set! in given functions.
{
// "(method 29 target)": 2048,
}
{}
@@ -1,3 +1,77 @@
{
// "quaternion-smooth-seek!": [[16, ["inline-array", "quaternion", 2]]],
"quaternion-smooth-seek!": [[16, ["inline-array", "quaternion", 2]]],
"rotate-vector-to-vector": [[16, "quaternion"]],
"nearest-dist2-between-moving-points": [[16, ["inline-array", "vector", 2]]],
"vector-segment-xz-distance-point!": [[16, "matrix"]],
"vector-interp-angle!": [[16, "quaternion"]],
"vector-cap-rotation!": [[16, "quaternion"]],
"vector-line-xz-distance-point!": [[16, "matrix"]],
"vector-circle-tangent-new": [
[32, "vector"],
[48, "vector"]
],
"v-slrp2!": [
[32, "vector"],
[64, "matrix"]
],
"v-slrp3!": [[32, "vector"]],
"collide-list-fill-bg-using-box": [
[32, "matrix"],
[96, "collide-query"]
],
"collide-list-fill-bg-using-line-sphere": [
[32, "matrix"],
[96, "collide-query"]
],
"(method 9 touching-list)": [[16, "add-prims-touching-work"]],
"(method 9 curve-color-fast)": [[16, "rgbaf"]],
"(method 9 curve2d-fast)": [
[16, "vector"],
[32, "vector"]
],
"evaluate-color-curve-fast": [[16, "vector"]],
"evaluate-curve-fast": [
[16, "vector"],
[32, "vector"]
],
"add-debug-box-with-transform": [
[16, ["inline-array", "vector", 8]],
[144, ["inline-array", "vector", 2]],
[176, "vector"]
],
"add-debug-curve": [
[16, "vector"],
[32, "vector"]
],
"add-debug-sphere-from-table": [
[16, "vector"],
[48, "vector"],
[64, "vector"]
],
"make-debug-sphere-table": [
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "vector"],
[80, "vector"],
[96, "vector"],
[112, "vector"]
],
"eul->matrix": [[16, "vector"]],
"joint-mod-joint-set-world-handler": [
[32, "vector"],
[48, "vector"]
],
"joint-mod-blend-world-callback": [[16, "joint-mod-blend-world-work"]],
"(method 20 lightning-bolt)": [[16, "vector"]],
"update-light-hash": [
[16, "bounding-box"],
[48, "vector"],
[64, "vector"]
],
"(method 10 simple-sprite-system)": [[16, ["array", "texture-id", 128]]],
"(method 10 cubic-curve)": [[16, "trajectory"]],
"(method 11 cubic-curve)": [[16, "trajectory"]],
"(method 12 cubic-curve)": [[16, "trajectory"]],
"matrix<-parented-transformq!": [[16, "vector"]]
}
File diff suppressed because one or more lines are too long
+465 -16
View File
@@ -1,18 +1,467 @@
{
// "(method 2 array)": [
// [23, "gp", "(array int32)"],
// [43, "gp", "(array uint32)"],
// [63, "gp", "(array int64)"],
// [83, "gp", "(array uint64)"],
// [102, "gp", "(array int8)"],
// [121, "gp", "(array uint8)"],
// [141, "gp", "(array int16)"],
// [161, "gp", "(array uint16)"],
// [186, "gp", "(array uint128)"],
// [204, "gp", "(array int32)"],
// [223, "gp", "(array float)"],
// [232, "gp", "(array float)"],
// [249, "gp", "(array basic)"],
// [258, "gp", "(array basic)"]
// ],
"entity-actor-count": [["_stack_", 16, "res-tag"]],
"entity-actor-lookup": [["_stack_", 16, "res-tag"]],
"build-masks": [
[[18, 22], "a1", "drawable-tree-tfrag"],
[24, "a2", "drawable-inline-array-tfrag"],
[[27, 31], "a2", "(inline-array tfragment)"],
[[38, 42], "a1", "drawable-tree-tfrag-trans"],
[44, "a2", "drawable-inline-array-tfrag"],
[[47, 51], "a2", "(inline-array tfragment)"],
[[58, 62], "a1", "drawable-tree-tfrag-water"],
[64, "a2", "drawable-inline-array-tfrag"],
[[67, 71], "a2", "(inline-array tfragment)"],
[[78, 79], "a1", "drawable-tree-instance-tie"],
[123, "a1", "drawable-tree-instance-shrub"],
[[129, 133], "a2", "(inline-array prototype-bucket-shrub)"]
],
"cam-layout-function-call": [
[15, "gp", "(function string int basic object)"]
],
"cam-layout-save-cam-rot": [[13, "v0", "vector"]],
"cam-layout-save-campointsoffset": [[12, "v0", "vector"]],
"cam-layout-save-splineoffset": [
[37, "v0", "vector"],
[25, "v0", "vector"]
],
"clmf-save-all": [[18, "v1", "connection"]],
"execute-cam-post-hook-engine": [
[8, "s5", "connection"],
[[14, 17], "s5", "connection"],
[18, "t9", "(function object object object object object)"],
[9, "s5", "connection"]
],
"collide-list-fill-bg-using-box": [
[223, "a0", "collide-hash-scratch"],
[255, "a0", "collide-hash-scratch"],
[208, "v1", "collide-hash-scratch"],
[210, "v1", "collide-hash-scratch"],
[212, "v1", "collide-hash-scratch"],
[241, "v1", "collide-hash-scratch"],
[243, "v1", "collide-hash-scratch"],
[246, "v1", "collide-hash-scratch"]
],
"collide-list-fill-bg-using-line-sphere": [
[287, "a0", "collide-hash-scratch"],
[[272, 280], "v1", "collide-hash-scratch"],
[[239, 246], "v1", "collide-hash-scratch"],
[255, "a0", "collide-hash-scratch"],
[102, "v1", "float"]
],
"(method 0 collide-shape-prim-group)": [
[[6, 12], "v0", "collide-shape-prim-group"]
],
"(method 0 collide-shape-prim-mesh)": [
[[6, 11], "v0", "collide-shape-prim-mesh"]
],
"(method 0 collide-shape-prim-sphere)": [
[[5, 8], "v0", "collide-shape-prim-sphere"]
],
"(method 10 touching-list)": [[[5, 11], "s5", "touching-shapes-entry"]],
"(method 11 touching-list)": [
[8, "s5", "touching-shapes-entry"],
[11, "s5", "touching-shapes-entry"],
[13, "s5", "touching-shapes-entry"],
[48, "s5", "touching-shapes-entry"],
[52, "s5", "touching-shapes-entry"],
[10, "s5", "touching-shapes-entry"],
[33, "s5", "touching-shapes-entry"],
[50, "s5", "touching-shapes-entry"]
],
"(method 0 touching-list)": [[[6, 8], "v0", "touching-list"]],
"(method 11 touching-prims-entry-pool)": [
[[0, 8], "v1", "touching-prims-entry"],
[8, "v1", "pointer"],
[[9, 11], "v1", "touching-prims-entry"],
[[1, 20], "a1", "touching-prims-entry"]
],
"(method 0 engine)": [
[44, "v1", "pointer"],
[47, "v1", "pointer"],
[53, "v1", "connectable"],
[65, "v1", "connectable"]
],
"(method 0 engine-pers)": [
[32, "v1", "pointer"],
[23, "v1", "pointer"],
[26, "v1", "pointer"],
[24, "v1", "(pointer pointer)"]
],
"(method 11 connection)": [[5, "a1", "pointer"]],
"(method 12 engine)": [
[[0, 25], "s4", "connection"],
[13, "t9", "(function object object object object object)"]
],
"(method 13 engine)": [
[[0, 25], "s4", "connection"],
[13, "t9", "(function object object object object object)"]
],
"(method 19 engine)": [[8, "a0", "connection"]],
"(method 20 engine)": [[8, "a0", "connection"]],
"(method 21 engine)": [[8, "a0", "connection"]],
"(method 3 connection-pers)": [[97, "f0", "float"]],
"(method 9 connection)": [[8, "a0", "pointer"]],
"drawable-frag-count": [[[14, 20], "s5", "drawable-group"]],
"add-debug-sphere-from-table": [
[[38, 41], "v1", "vector"],
[[55, 59], "s0", "(inline-array vector)"]
],
"unpack-comp-huf": [[[21, 23], "t3", "(pointer uint16)"]],
"unpack-comp-rle": [[[10, 26], "a0", "(pointer int8)"]],
"dma-bucket-insert-tag": [
[[2, 6], "v1", "dma-bucket"],
[3, "a0", "dma-bucket"]
],
"dma-buffer-add-buckets": [
[[1, 4], "v1", "dma-bucket"],
[5, "v1", "pointer"],
[[9, 11], "v1", "dma-bucket"],
[11, "v1", "pointer"]
],
"dma-buffer-patch-buckets": [
[[3, 34], "a0", "dma-bucket"],
[[34, 38], "a0", "dma-packet"]
],
"disasm-dma-list": [
[43, "v1", "dma-packet"],
[266, "v1", "(pointer uint64)"],
[272, "v1", "(pointer uint64)"],
[133, "v1", "(pointer uint64)"],
[152, "v1", "(pointer uint64)"],
[167, "v1", "(pointer uint64)"],
[176, "v1", "(pointer uint64)"],
[198, "v1", "(pointer uint64)"],
[207, "v1", "(pointer uint64)"],
[238, "v1", "(pointer uint64)"],
[247, "v1", "(pointer uint64)"],
[282, "v1", "(pointer uint64)"],
[291, "v1", "(pointer uint64)"],
[324, "v1", "(pointer uint64)"],
[334, "v1", "(pointer uint64)"],
[141, "v1", "int"],
[25, "v1", "dma-tag"],
["_stack_", 16, "uint"],
["_stack_", 32, "dma-packet"],
["_stack_", 64, "dma-packet"],
["_stack_", 80, "dma-packet"]
],
"(method 16 drawable-inline-array-node)": [[[1, 7], "v1", "draw-node"]],
"(method 15 drawable-tree)": [
[[1, 4], "v1", "drawable-inline-array-node"],
[[29, 34], "t0", "drawable-inline-array-node"],
[[28, 32], "t2", "drawable-inline-array-node"],
[[42, 46], "t2", "(pointer int8)"]
],
"glst-find-node-by-name": [[6, "s5", "glst-named-node"]],
"glst-length-of-longest-name": [[5, "s5", "glst-named-node"]],
"history-print": [[20, "a1", "int"]],
"joint-mod-foot-rot-handler": [
[[0, 7], "s5", "joint-mod"],
[[35, 152], "s5", "joint-mod"]
],
"joint-mod-joint-set-handler": [[[2, 23], "s4", "joint-mod"]],
"joint-mod-joint-set-world-handler": [[[6, 197], "s5", "joint-mod"]],
"joint-mod-polar-look-at-callback": [
[[0, 363], "s5", "joint-mod-polar-look-at"]
],
"joint-mod-scale-handler": [[[1, 14], "s5", "joint-mod"]],
"real-joint-mod-gun-look-at-handler": [
[1, "v1", "joint-mod"],
[2, "v1", "joint-mod"]
],
"joint-mod-blend-local-callback": [[[1, 28], "gp", "joint-mod-blend-local"]],
"joint-mod-blend-world-callback": [[[1, 150], "gp", "joint-mod-blend-world"]],
"joint-mod-rotate-world-callback": [
[[0, 24], "s3", "joint-mod-rotate-world"]
],
"joint-mod-set-local-callback": [[[1, 24], "v1", "joint-mod-set-local"]],
"joint-mod-set-world-callback": [[[1, 4], "v1", "joint-mod-set-local"]],
"joint-mod-set-world-no-trans-callback": [
[[1, 25], "s4", "joint-mod-set-world-no-trans"]
],
"(method 15 lightning-bolt)": [
[47, "v1", "float"],
[64, "v1", "float"]
],
"(method 17 lightning-bolt)": [[36, "v1", "float"]],
"(method 20 lightning-bolt)": [
[15, "v1", "float"],
[32, "v1", "float"]
],
"(method 21 lightning-bolt)": [
[49, "v1", "float"],
[77, "v1", "float"],
["_stack_", 32, "float"]
],
"update-light-hash": [
[[234, 239], "a1", "light-hash-bucket"],
[[207, 211], "a0", "light-hash-bucket"]
],
"dgo-load-begin": [[[19, 43], "s1", "load-dgo-msg"]],
"dgo-load-continue": [[[5, 23], "gp", "load-dgo-msg"]],
"dgo-load-get-next": [[[14, 31], "v1", "load-dgo-msg"]],
"str-ambient-play": [[[7, 20], "s5", "play-chunk-msg"]],
"str-ambient-stop": [[[7, 20], "s5", "play-chunk-msg"]],
"str-load": [[[18, 44], "s2", "load-chunk-msg"]],
"str-load-status": [
[[18, 22], "v1", "load-chunk-msg"],
[26, "v1", "load-chunk-msg"]
],
"str-play-async": [[[7, 40], "s2", "play-chunk-msg"]],
"str-play-queue": [[[7, 98], "s4", "play-chunk-msg"]],
"str-play-stop": [[[7, 36], "s4", "play-chunk-msg"]],
"cube-root": [
[17, "f0", "float"],
[17, "f1", "float"],
[18, "f0", "float"],
[18, "f1", "float"],
[[23, 32], "f0", "float"]
],
"log2f": [
[12, "f0", "float"],
[12, "f1", "float"],
[19, "f0", "float"],
[19, "f1", "float"]
],
"logf": [
[12, "f0", "float"],
[12, "f1", "float"],
[19, "f0", "float"],
[19, "f1", "float"]
],
"debug-menu-find-from-template": [
[9, "s5", "string"],
[10, "s4", "debug-menu-item"],
[18, "s4", "debug-menu-item-submenu"],
[3, "s5", "debug-menu"]
],
"debug-menu-func-decode": [[18, "a0", "symbol"]],
"debug-menu-item-get-max-width": [
[5, "a0", "debug-menu-item-submenu"],
[20, "a0", "debug-menu-item-var"]
],
"debug-menu-item-var-joypad-handler": [
[206, "a1", "int"],
[207, "v1", "int"]
],
"debug-menu-item-var-make-float": [[32, "f0", "int"]],
"debug-menu-item-var-update-display-str": [
[48, "v1", "int"],
[63, "v1", "int"],
[68, "v1", "int"],
[46, "v1", "int"],
[45, "v1", "int"],
[65, "v1", "int"],
[66, "v1", "int"]
],
"debug-menu-rebuild": [[7, "a0", "debug-menu-item"]],
"debug-menu-send-msg": [
[17, "s2", "debug-menu-item-submenu"],
[12, "s2", "debug-menu-item"]
],
"(method 10 mysql-nav-node)": [[4, "v1", "mysql-nav-edge"]],
"(method 19 mysql-nav-graph)": [
[42, "a0", "mysql-nav-edge"],
[46, "a0", "mysql-nav-edge"],
[60, "a0", "mysql-nav-edge"]
],
"joint-channel-float-delete!": [
[7, "a0", "pointer"],
[7, "a1", "pointer"]
],
"num-func-chan": [[7, "v1", "joint-control-channel"]],
"ramdisk-load": [[[7, 12], "v1", "ramdisk-rpc-load"]],
"(method 15 res-lump)": [[132, "s5", "res-tag-pair"]],
"(method 16 res-lump)": [
[22, "t1", "(pointer uint64)"],
[29, "t2", "(pointer uint64)"]
],
"(method 17 res-lump)": [[22, "s4", "(pointer pointer)"]],
"(method 18 res-lump)": [["_stack_", 16, "object"]],
"(method 19 res-lump)": [
[38, "t2", "int"],
[38, "a2", "int"]
],
"(method 20 res-lump)": [[341, "t0", "(pointer uint128)"]],
"(method 21 res-lump)": [
["_stack_", 16, "res-tag"],
["_stack_", 32, "res-tag"]
],
"(method 0 script-context)": [[[8, 17], "v0", "script-context"]],
"shadow-vu1-add-matrix": [
[[11, 19], "a3", "dma-packet"],
[[26, 30], "v1", "matrix"]
],
"shrubbery-login-post-texture": [
[[13, 15], "a3", "qword"],
[16, "a3", "pointer"],
[24, "a3", "pointer"],
[[17, 23], "a3", "qword"],
[[13, 23], "a1", "qword"],
[14, "a2", "qword"],
[[27, 29], "a3", "qword"],
[[27, 29], "a1", "qword"],
[[35, 37], "a3", "qword"],
[[35, 37], "a2", "qword"]
],
"(method 2 sparticle-cpuinfo)": [[14, "f0", "float"]],
"sprite-add-2d-chunk": [
[[7, 21], "a0", "dma-packet"],
[[33, 53], "a0", "dma-packet"],
[[57, 77], "a0", "dma-packet"],
[[78, 88], "v1", "dma-packet"],
[65, "a3", "int"]
],
"sprite-add-3d-chunk": [
[[7, 21], "a0", "dma-packet"],
[[33, 53], "a0", "dma-packet"],
[[57, 77], "a0", "dma-packet"],
[[78, 88], "v1", "dma-packet"],
[65, "a3", "int"]
],
"sprite-add-frame-data": [[[3, 17], "a0", "dma-packet"]],
"add-shader-to-dma": [[[6, 8], "v1", "(pointer uint32)"]],
"sprite-glow-add-simple-sprite": [
[[0, 33], "v1", "sprite-glow-ref-template"]
],
"sprite-glow-add-sprite": [[[0, 33], "v1", "sprite-glow-cnt-template"]],
"(method 9 texture-anim-layer)": [
[5, "v1", "symbol"],
[11, "v1", "symbol"]
],
"add-tfrag-data": [
[[3, 17], "a0", "dma-packet"],
[[24, 31], "v1", "dma-packet"]
],
"tfrag-end-buffer": [
[[21, 28], "a2", "dma-packet"],
[[31, 38], "a0", "(pointer vif-tag)"],
[[38, 42], "a0", "(pointer int32)"],
[[43, 49], "a0", "(pointer vif-tag)"]
],
"(method 9 clock)": [[47, "v1", "float"]],
"vector4-array-add!": [
[11, "s5", "(inline-array vector4)"],
[12, "s4", "(inline-array vector4)"],
[13, "gp", "(inline-array vector4)"]
],
"vector4-array-lerp!": [
[13, "s5", "(inline-array vector4)"],
[14, "s4", "(inline-array vector4)"],
[15, "gp", "(inline-array vector4)"]
],
"vector4-array-madd!": [
[13, "s5", "(inline-array vector4)"],
[14, "s4", "(inline-array vector4)"],
[15, "gp", "(inline-array vector4)"]
],
"vector4-array-msub!": [
[13, "s5", "(inline-array vector4)"],
[14, "s4", "(inline-array vector4)"],
[15, "gp", "(inline-array vector4)"]
],
"vector4-array-mul!": [
[11, "s5", "(inline-array vector4)"],
[12, "s4", "(inline-array vector4)"],
[13, "gp", "(inline-array vector4)"]
],
"vector4-array-scale!": [
[11, "s5", "(inline-array vector4)"],
[12, "gp", "(inline-array vector4)"]
],
"vector4-array-sub!": [
[11, "s5", "(inline-array vector4)"],
[12, "s4", "(inline-array vector4)"],
[13, "gp", "(inline-array vector4)"]
],
"ellipsoid-random-point-on!": [
[19, "v1", "float"],
[44, "v1", "float"]
],
"(method 15 engine)": [[[0, 36], "v1", "connection"]],
"(method 10 connection)": [[8, "a0", "pointer"]],
"(method 3 connection-minimap)": [
[97, "a3", "float"],
[[97, 99], "a3", "float"],
[97, "f0", "float"]
],
"(method 0 prim-strip)": [[[101, 121], "a0", "vector"]],
"(method 0 fact-info-target)": [[3, "v0", "fact-info-target"]],
"(method 0 fact-info-crate)": [[3, "v0", "fact-info-crate"]],
"(method 0 fact-info-enemy)": [
[7, "v0", "fact-info-enemy"],
["_stack_", 16, "res-tag"],
["_stack_", 32, "res-tag"]
],
"(method 0 fact-info)": [
[87, "v1", "(pointer int32)"],
[11, "v1", "res-lump"]
],
"(method 0 collide-shape-moving)": [[[5, 12], "v0", "collide-shape-moving"]],
"joint-mod-spinner-callback": [[[2, 63], "gp", "joint-mod-spinner"]],
"joint-mod-add-local-callback": [[[1, 37], "s4", "joint-mod-add-local"]],
"(top-level-login eye-h)": [[76, "a3", "eye-control"]],
"joint-mod-rotate-local-callback": [
[[2, 16], "v1", "joint-mod-rotate-local"]
],
"joint-mod-trans-rot-local-callback": [
[[2, 16], "v1", "joint-mod-trans-rot-local"]
],
"(method 8 res-lump)": [
[258, "s0", "array"],
[[157, 239], "s0", "(array object)"]
],
"(method 2 array)": [
[23, "gp", "(array int32)"],
[43, "gp", "(array uint32)"],
[63, "gp", "(array int64)"],
[83, "gp", "(array uint64)"],
[102, "gp", "(array int8)"],
[121, "gp", "(array uint8)"],
[141, "gp", "(array int16)"],
[161, "gp", "(array uint16)"],
[186, "gp", "(array uint128)"],
[204, "gp", "(array int32)"],
[223, "gp", "(array float)"],
[232, "gp", "(array float)"],
[249, "gp", "(array basic)"],
[258, "gp", "(array basic)"]
],
"(method 3 array)": [
[51, "gp", "(array int32)"],
[69, "gp", "(array uint32)"],
[87, "gp", "(array int64)"],
[105, "gp", "(array uint64)"],
[122, "gp", "(array int8)"],
[139, "gp", "(array int8)"],
[157, "gp", "(array int16)"],
[175, "gp", "(array uint16)"],
[198, "gp", "(array uint128)"],
[214, "gp", "(array int32)"],
[233, "gp", "(array float)"],
[250, "gp", "(array basic)"]
],
"(method 9 bounding-box)": [
[13, "a1", "(inline-array sphere)"],
[24, "a1", "(inline-array sphere)"],
[31, "a1", "(inline-array sphere)"],
[38, "a1", "(inline-array sphere)"]
],
"generate-rand-vector-on-sphere": [
[12, "v1", "float"],
[28, "v1", "float"]
],
"vector-segment-distance-point!": [[[21, 30], "f1", "float"]],
"string-cat-to-last-char": [
[3, "s5", "(pointer uint8)"],
[4, "s5", "string"]
],
"to-upper": [
[6, "a0", "(pointer uint8)"],
[8, "a0", "string"]
],
"mem-copy!": [
[[18, 69], "s5", "(pointer uint128)"],
[[18, 69], "s4", "(pointer uint128)"]
]
}
+517 -3
View File
@@ -1,5 +1,519 @@
{
// "(method 0 inline-array-class)": {
// "args": ["allocation", "type-to-make", "count"]
// },
"(method 0 inline-array-class)": {
"args": ["allocation", "type-to-make", "count"]
},
"(method 9 inline-array-class)": {
"args": ["object-to-insert"]
},
"(method 3 inline-array-class)": {
"args": ["idx-to-remove"]
},
"identity": {
"args": ["obj"]
},
"1/": {
"args": ["x"]
},
"+": {
"args": ["a", "b"]
},
"-": {
"args": ["a", "b"]
},
"*": {
"args": ["a", "b"]
},
"/": {
"args": ["a", "b"]
},
"ash": {
"args": ["x", "shift-amount"]
},
"mod": {
"args": ["a", "b"]
},
"rem": {
"args": ["a", "b"]
},
"abs": {
"args": ["x"]
},
"min": {
"args": ["a", "b"]
},
"max": {
"args": ["a", "b"]
},
"logior": {
"args": ["a", "b"]
},
"logand": {
"args": ["a", "b"]
},
"lognor": {
"args": ["a", "b"]
},
"logxor": {
"args": ["a", "b"]
},
"lognot": {
"args": ["x"]
},
"basic-type?": {
"args": ["obj", "typ"]
},
"type-type?": {
"args": ["check-type", "parent-type"]
},
"type?": {
"args": ["obj", "desired-type"]
},
"find-parent-method": {
"args": ["typ", "method-id"]
},
"ref&": {
"args": ["list", "idx"]
},
"ref": {
"args": ["list", "idx"]
},
"last": {
"args": ["list"]
},
"member": {
"args": ["obj-to-find", "list"]
},
"nmember": {
"args": ["obj-to-find", "list"]
},
"assoc": {
"args": ["key", "assoc-list"]
},
"assoce": {
"args": ["key", "assoc-list"]
},
"nassoc": {
"args": ["key", "assoc-list"]
},
"nassoce": {
"args": ["key", "assoc-list"]
},
"append!": {
"args": ["list", "new-obj"]
},
"delete!": {
"args": ["obj", "list"]
},
"delete-car!": {
"args": ["car-to-match", "list"]
},
"insert-cons!": {
"args": ["new-obj", "list"]
},
"sort": {
"args": ["list", "compare-func"]
},
"string->symbol-debug": {
"args": ["str"]
},
"symbol->string-debug": {
"args": ["sym"]
},
"symbol->hash": {
"args": ["sym"]
},
"mem-copy!": {
"args": ["dst", "src", "bytes"]
},
"qmem-copy<-!": {
"args": ["dst", "src", "qwc"]
},
"qmem-copy->!": {
"args": ["dst", "src", "qwc"]
},
"qmem-clear!": {
"args": ["dst", "qwc"]
},
"mem-set32!": {
"args": ["dst", "word-count", "value"]
},
"mem-or!": {
"args": ["dst", "src", "bytes"]
},
"fact": {
"args": ["x"]
},
"print": {
"args": ["obj"]
},
"printl": {
"args": ["obj"]
},
"inspect": {
"args": ["obj"]
},
"mem-print": {
"args": ["ptr", "word-count"]
},
"print-tree-bitmask": {
"args": ["mask", "count"]
},
"valid?": {
"args": [
"obj",
"expected-type",
"err-msg-str",
"allow-false",
"err-msg-dest"
]
},
"(method 10 collide-mesh-cache)": {
"args": ["this", "id"]
},
"(method 11 touching-prims-entry-pool)": {
"vars": {
"v1-0": "prev",
"a1-0": "current",
"a2-0": "next"
}
},
"add-debug-box-with-transform": {
"args": ["enable", "bucket", "box", "mat", "color"]
},
"add-debug-cspace": {
"args": ["enable", "bucket", "cs"]
},
"add-debug-text-sphere": {
"args": ["enable", "bucket", "pos", "radius", "text", "color"]
},
"add-debug-vector": {
"args": ["enable", "bucket", "base", "dir", "len-scale", "color"]
},
"debug-reset-buffers": {
"args": ["enable", "bucket", "p0", "p1", "color"]
},
"get-debug-text-3d": {
"args": ["enable", "bucket", "p0", "p1", "color", "mode", "color2"]
},
"transform-float-point": {
"args": ["src-world-pt", "dst-gs-screen-pt"]
},
"dma-bucket-insert-tag": {
"args": ["buckets", "bucket", "start-tag", "end-tag-to-patch"]
},
"dma-buffer-add-buckets": {
"args": ["dma-buf", "bucket-count"]
},
"dma-buffer-patch-buckets": {
"args": ["base", "count"]
},
"(method 0 dma-buffer)": {
"args": ["allocation", "type-to-make", "size-bytes"]
},
"dma-buffer-add-vu-function": {
"args": ["dma-buf", "vu-func", "flush-path-3"]
},
"dma-buffer-free": {
"args": ["dma-buf"]
},
"dma-buffer-inplace-new": {
"args": ["dma-buff", "size-bytes"]
},
"dma-buffer-length": {
"args": ["dma-buf"]
},
"dma-buffer-send": {
"args": ["chan", "buf"]
},
"dma-buffer-send-chain": {
"args": ["chan", "buf"]
},
"disasm-dma-list": {
"args": ["data", "mode", "verbose", "stream", "expected-size"]
},
"disasm-dma-tag": {
"args": ["tag", "format-dest"]
},
"disasm-vif-details": {
"args": ["fmt-dest", "vif-data", "unpack-cmd", "unpack-count"]
},
"disasm-vif-tag": {
"args": ["tag", "count", "format-dest", "details?"]
},
"(method 13 effect-control)": {
"args": ["this", "offset"]
},
"(method 11 focus)": {
"args": ["this", "cspec"]
},
"(method 0 clock)": {
"args": ["allocation", "type-to-make", "index"]
},
"(method 0 sql-result)": {
"args": ["allocation", "type-to-make", "num-elts"]
},
"(method 16 clock)": {
"args": ["this", "xor-val"]
},
"(method 17 clock)": {
"args": ["this", "xor-val"]
},
"(method 18 clock)": {
"args": ["this", "xor-val"]
},
"(method 19 clock)": {
"args": ["this", "xor-val"]
},
"(method 20 clock)": {
"args": ["this", "xor-val"]
},
"(method 21 clock)": {
"args": ["this", "xor-val"]
},
"(method 22 clock)": {
"args": ["this", "xor-val"]
},
"(method 23 clock)": {
"args": ["this", "xor-val"]
},
"(method 10 joint-mod-polar-look-at)": {
"args": ["this", "pos"]
},
"(method 11 joint-mod-polar-look-at)": {
"args": ["this", "other", "pos"]
},
"(method 12 joint-mod-polar-look-at)": {
"args": ["this", "duration", "final-val", "restart-if-in-progress"]
},
"(method 13 joint-mod)": {
"args": ["this", "x", "y", "z"]
},
"(method 13 joint-mod-polar-look-at)": {
"args": ["this", "duration", "restart-if-in-progress"]
},
"(method 14 joint-mod)": {
"args": ["this", "trans", "quat", "scale"]
},
"(method 9 joint-mod)": {
"args": ["this", "mode"]
},
"(method 9 joint-mod-ik)": {
"args": ["this", "pos"]
},
"joint-mod-blend-local-callback": {
"args": ["bone-cspace", "joint-transform"]
},
"joint-mod-blend-world-callback": {
"args": ["bone-cspace", "joint-transform"]
},
"joint-mod-rotate-world-callback": {
"args": ["bone-cspace", "joint-transform"]
},
"joint-mod-set-local-callback": {
"args": ["bone-cspace", "joint-transform"]
},
"joint-mod-set-world-callback": {
"args": ["bone-cspace", "joint-trasnform"]
},
"joint-mod-set-world-no-trans-callback": {
"args": ["bone-cspace", "joint-transform"]
},
"vector<-cspace2!": {
"args": ["output-vec", "input-cspace"]
},
"light-group-lerp!": {
"args": ["group", "backup-ptr", "other", "scalar"]
},
"light-group-madd!": {
"args": ["group", "backup-ptr", "other", "scalar"],
"vars": {
"s4-0": "new-light",
"f30-0": "ambi-scaled",
"f24-0": "dir0-scaled",
"f26-0": "dir1-scaled",
"f28-0": "dir2-scaled"
}
},
"light-group-process!": {
"args": ["vu-lights", "light-group", "vec1", "vec2"]
},
"light-group-scale!": {
"args": ["group", "backup-ptr", "scale"],
"vars": {
"arg1": "other",
"v1-4": "light-idx"
}
},
"light-group-slerp": {
"args": ["light-group-out", "light-group-a", "light-group-b", "alpha"],
"vars": {
"s2-0": "group-idx"
}
},
"light-merge!": {
"args": ["out", "other"]
},
"light-slerp": {
"args": ["light-out", "light-a", "light-b", "alpha"],
"vars": {
"s3-0": "clamped-alpha",
"f0-2": "extra-x-a",
"f1-2": "extra-x-b"
}
},
"lookup-light-sphere-by-name": {
"args": ["name", "hash"],
"vars": {
"s4-0": "num-lights",
"s3-0": "light"
}
},
"shadow-info-copy!": {
"args": ["dest", "src"],
"vars": {
"v1-0": "light-idx"
}
},
"vu-lights-default!": {
"args": ["lights"]
},
"destroy-mem": {
"args": ["start", "end"]
},
"dgo-load-begin": {
"args": ["name", "buffer1", "buffer2", "buffer-top"]
},
"dgo-load-continue": {
"args": ["buffer1", "buffer2", "buffer-top"]
},
"dgo-load-get-next": {
"args": ["done-out"]
},
"find-temp-buffer": {
"args": ["size"]
},
"str-ambient-play": {
"args": ["name"]
},
"str-ambient-stop": {
"args": ["name"]
},
"str-load": {
"args": ["name", "chunk-idx", "dest-addr", "max-len"]
},
"str-load-status": {
"args": ["maxlen-out"]
},
"str-play-async": {
"args": ["name", "id", "volume", "group"]
},
"str-play-queue": {
"args": ["name0", "name1", "name2", "name3", "ids", "mask"]
},
"str-play-stop": {
"args": ["name", "id"]
},
"merc-fragment-fp-data": {
"args": ["frag"]
},
"(method 13 mood-control)": {
"args": ["this", "target-interp", "rate-interp", "set-current-interp?"],
"vars": {
"f0-1": "clamped-interp"
}
},
"init-mood-control": {
"args": ["ctrl"]
},
"cspace-index-by-name-no-fail": {
"args": ["proc", "name"],
"vars": {
"v0-0": "idx"
}
},
"joint-channel-float-delete!": {
"args": ["chan"]
},
"num-func-+!": {
"args": ["chan", "arg1", "arg2", "arg3"]
},
"num-func--!": {
"args": ["chan", "arg1", "arg2", "arg3"]
},
"num-func-identity": {
"args": ["chan", "arg1", "arg2", "arg3"]
},
"num-func-loop!": {
"args": ["chan", "arg1", "arg2", "arg3"]
},
"num-func-loop-set!": {
"args": ["chan", "frame"]
},
"num-func-none": {
"args": ["chan", "arg1", "arg2", "arg3"]
},
"num-func-seek!": {
"args": ["chan", "arg1", "arg2", "arg3"]
},
"(method 15 res-lump)": {
"vars": {
"s5-0": ["tag-pair", "res-tag-pair"],
"s2-0": "existing-tag",
"s3-0": "data-size",
"v1-25": "resource-mem"
}
},
"(method 17 res-lump)": {
"args": ["this", "tag", "arg2"]
},
"(method 20 res-lump)": {
"args": ["this", "arg1", "tag-pair", "arg3"]
},
"(method 9 res-lump)": {
"args": ["this", "name", "mode", "time"]
},
"(method 0 rpc-buffer)": {
"args": ["allocation", "type-to-make", "elt-size", "elt-count"]
},
"(method 0 rpc-buffer-pair)": {
"args": ["allocation", "type-to-make", "elt-size", "elt-count", "rpc-port"]
},
"(method 12 rpc-buffer-pair)": {
"args": ["this", "print-stall-warning"]
},
"(method 9 rpc-buffer-pair)": {
"args": ["this", "fno", "recv-buffer", "recv-buffer-size"]
},
"(method 10 smush-control)": {
"vars": {
"f30-0": "elapsed-time",
"f0-2": "period"
}
},
"(method 11 smush-control)": {
"vars": {
"f30-0": "elapsed-time",
"f0-2": "period"
}
},
"(method 12 smush-control)": {
"args": [
"this",
"amplitude",
"period",
"duration",
"damp-amplitude",
"damp-period",
"clock"
]
},
"(method 9 clock)": {
"args": ["this", "rate"]
},
"vector-rad<-vector-deg!": {
"args": ["out", "in"]
},
"vector-rad<-vector-deg/2!": {
"args": ["out", "in"]
}
}
@@ -1,901 +0,0 @@
{
// NOTE: almost all of these were just copy pasted from jak2
// so it's impossible to know which are actually needed for jakx...
// commenting out incase there's something here actually needed
"gkernel": [
[17, "(function process symbol)"],
[24, "(function process symbol)"],
[26, "(function process symbol)"],
[29, "(function process symbol)"],
[32, "(function process symbol)"],
[34, "(function process symbol)"],
[36, "(function process symbol)"]
],
"profile": [[3, "(function profile-segment-array profile-collapse none)"]],
"surface-h": [
[0, "(function none)"],
[1, "(function none)"],
[2, "(function none)"]
],
"gsound": [
[1, "(function none)"],
[3, "(function none)"],
[5, "(function none)"]
],
"joint-mod": [[21, "(function cspace transformq none)"]],
"level-info": [
[0, "(function int)"],
[1, "(function int)"],
[2, "(function int)"]
],
"game-info": [
[11, "(function string none :behavior process)"],
[17, "(function symbol symbol int none :behavior process)"],
[
22,
"(function symbol symbol continue-point game-save resetter-spec none :behavior process)"
]
],
"game-task": [
[0, "(function symbol)"],
[1, "(function symbol)"],
[2, "(function symbol)"],
[3, "(function symbol)"]
],
"settings": [
[6, "(function engine-pers connection-pers object object symbol)"]
],
"generic-obs": [[51, "(function symbol :behavior touch-tracker)"]],
"target-util": [
[2, "(function none :behavior target)"],
[3, "(function none :behavior target)"],
[4, "(function none :behavior manipy)"],
[5, "(function none :behavior manipy)"],
[6, "(function none :behavior target)"]
],
"logic-target": [
[0, "(function external-art-buffer none)"],
[1, "(function external-art-buffer none)"]
],
"sidekick": [[6, "(function object vector int string :behavior sidekick)"]],
"target-handler": [
[10, "(function handle none :behavior target)"],
[14, "(function none :behavior target)"]
],
"target-anim": [
[3, "(function none :behavior target)"],
[4, "(function none :behavior target)"],
[7, "(function none :behavior target)"],
[8, "(function none :behavior target)"],
[13, "(function (pointer time-frame) none :behavior target)"],
[14, "(function none :behavior target)"],
[15, "(function none :behavior target)"],
[16, "(function none :behavior target)"],
[17, "(function none :behavior target)"]
],
"target": [
[1, "(function object :behavior target)"],
[7, "(function object :behavior target)"],
[18, "(function process-focusable object :behavior target)"],
[29, "(function surface surface surface int object :behavior target)"],
[35, "(function surface surface surface int object :behavior target)"],
[45, "(function surface surface surface int object :behavior target)"],
[46, "(function surface surface surface int object :behavior target)"],
[77, "(function surface surface surface int object :behavior target)"]
],
"target2": [
[12, "(function vector time-frame float object :behavior process)"],
[15, "(function object :behavior target)"],
[23, "(function object :behavior target)"],
[64, "(function symbol :behavior target)"]
],
"target-lightjak": [[68, "(function symbol object :behavior target)"]],
"target-invisible": [[10, "(function object :behavior target)"]],
"target-death": [
[1, "(function object :behavior target)"],
[2, "(function object :behavior target)"],
[3, "(function symbol object :behavior target)"],
[4, "(function object :behavior target)"],
[9, "(function handle object :behavior target)"],
[10, "(function object :behavior target)"],
[14, "(function process-drawable object)"],
[25, "(function surface surface surface int object :behavior target)"],
[26, "(function surface surface surface int object :behavior target)"],
[28, "(function continue-point object)"],
[34, "(function process symbol)"],
[35, "(function process symbol)"],
[36, "(function process symbol)"],
[37, "(function process symbol)"],
[38, "(function process symbol)"]
],
"target-gun": [
[15, "(function pickup-type pickup-type none :behavior target)"],
[16, "(function pickup-type none :behavior target)"],
[25, "(function surface surface surface int object :behavior target)"]
],
"target-board": [
[30, "(function surface surface surface int object :behavior target)"],
[31, "(function surface surface surface int object :behavior target)"],
[32, "(function surface surface surface int object :behavior target)"],
[33, "(function surface surface surface int object :behavior target)"],
[34, "(function surface surface surface int object :behavior target)"]
],
"vent": [
[26, "(function vent symbol)"],
[27, "(function vent symbol)"],
[28, "(function vent symbol)"],
[29, "(function vent symbol)"]
],
"crates": [[35, "(function process symbol)"]],
"collectables": [
[77, "(function part-tracker vector)"],
[78, "(function part-tracker vector)"]
],
"trajectory": [[15, "(function trajectory none)"]],
"progress": [[3, "(function int none :behavior process)"]],
"level": [
[25, "(function level-group int symbol)"],
[7, "(function none)"],
[4, "(function load-state sound-bank-state symbol)"]
],
"main": [
[11, "(function int none)"],
[9, "(function none)"],
[8, "(function none)"],
[7, "(function none)"],
[3, "(function symbol :behavior process)"]
],
"scene": [[4, "(function symbol :behavior scene-player)"]],
"pov-camera": [
[
7,
"(function process int symbol event-message-block object :behavior pov-camera)"
]
],
"airlock": [
[7, "(function object :behavior com-airlock)"],
[11, "(function object :behavior com-airlock)"],
[12, "(function object :behavior com-airlock)"]
],
"default-menu": [
[3, "(function object)"],
[4, "(function object)"],
[5, "(function object)"],
[6, "(function object)"],
[7, "(function int debug-menu-msg object)"],
[8, "(function object)"],
[9, "(function object)"],
[10, "(function object)"],
[11, "(function object)"],
[12, "(function object)"],
[13, "(function object)"],
[14, "(function object)"],
[15, "(function object)"],
[16, "(function object)"],
[17, "(function object)"],
[18, "(function int debug-menu-msg float object)"],
[20, "(function object)"],
[21, "(function object)"],
[22, "(function object)"],
[23, "(function object)"],
[24, "(function object)"],
[25, "(function object)"],
[26, "(function object)"],
[27, "(function int debug-menu-msg float object)"],
[28, "(function int debug-menu-msg float object)"],
[29, "(function object)"],
[30, "(function int debug-menu-msg float object)"],
[31, "(function int debug-menu-msg float object)"],
[32, "(function int debug-menu-msg float object)"],
[33, "(function int debug-menu-msg float object)"],
[34, "(function object)"],
[35, "(function object)"],
[36, "(function int debug-menu-msg float object)"],
[37, "(function int debug-menu-msg float object)"],
[38, "(function int debug-menu-msg float object)"],
[39, "(function int debug-menu-msg float object)"],
[40, "(function object)"],
[41, "(function object)"],
[42, "(function int debug-menu-msg float object)"],
[43, "(function int debug-menu-msg float object)"],
[44, "(function int debug-menu-msg float object)"],
[45, "(function int debug-menu-msg float object)"],
[46, "(function int debug-menu-msg float object)"],
[47, "(function int debug-menu-msg float object)"],
[48, "(function int debug-menu-msg float object)"],
[49, "(function int debug-menu-msg float object)"],
[50, "(function int debug-menu-msg float object)"],
[51, "(function int debug-menu-msg float object)"],
[52, "(function int debug-menu-msg float object)"],
[53, "(function int debug-menu-msg float object)"],
[54, "(function int debug-menu-msg float object)"],
[55, "(function int debug-menu-msg float object)"],
[56, "(function int debug-menu-msg float object)"],
[57, "(function int debug-menu-msg float object)"],
[58, "(function int debug-menu-msg float object)"],
[59, "(function int debug-menu-msg float object)"],
[60, "(function int debug-menu-msg float object)"],
[61, "(function int debug-menu-msg float object)"],
[62, "(function int debug-menu-msg float object)"],
[63, "(function int debug-menu-msg float object)"],
[64, "(function int debug-menu-msg float object)"],
[65, "(function int debug-menu-msg float object)"],
[66, "(function int debug-menu-msg float object)"],
[67, "(function int debug-menu-msg float object)"],
[68, "(function int debug-menu-msg float object)"],
[69, "(function int debug-menu-msg float object)"],
[70, "(function int debug-menu-msg float object)"],
[71, "(function int debug-menu-msg float object)"],
[72, "(function int debug-menu-msg float object)"],
[73, "(function int debug-menu-msg float object)"],
[74, "(function int debug-menu-msg float object)"],
[75, "(function int debug-menu-msg float object)"],
[76, "(function int debug-menu-msg float object)"],
[77, "(function int debug-menu-msg float object)"],
[78, "(function int debug-menu-msg float object)"],
[79, "(function int debug-menu-msg float object)"],
[80, "(function int debug-menu-msg float object)"],
[81, "(function int debug-menu-msg float object)"],
[82, "(function int debug-menu-msg float object)"],
[83, "(function int debug-menu-msg float object)"],
[84, "(function int debug-menu-msg float object)"],
[85, "(function int debug-menu-msg float object)"],
[86, "(function int debug-menu-msg float object)"],
[87, "(function int debug-menu-msg float object)"],
[88, "(function int debug-menu-msg float object)"],
[89, "(function int debug-menu-msg float object)"],
[90, "(function int debug-menu-msg float object)"],
[91, "(function int debug-menu-msg float object)"],
[92, "(function int debug-menu-msg float object)"],
[93, "(function int debug-menu-msg float object)"],
[94, "(function int debug-menu-msg float object)"],
[95, "(function int debug-menu-msg float object)"],
[96, "(function int debug-menu-msg float object)"],
[97, "(function int debug-menu-msg float object)"],
[98, "(function int debug-menu-msg float object)"],
[99, "(function int debug-menu-msg float object)"],
[100, "(function int debug-menu-msg float object)"],
[101, "(function int debug-menu-msg float object)"],
[102, "(function int debug-menu-msg float object)"],
[103, "(function int debug-menu-msg float object)"],
[104, "(function int debug-menu-msg float object)"],
[105, "(function int debug-menu-msg float object)"],
[106, "(function int debug-menu-msg float object)"],
[107, "(function int debug-menu-msg float object)"],
[108, "(function int debug-menu-msg float object)"],
[109, "(function int debug-menu-msg float object)"],
[110, "(function int debug-menu-msg float object)"],
[111, "(function int debug-menu-msg float object)"],
[112, "(function int debug-menu-msg float object)"],
[113, "(function int debug-menu-msg float object)"],
[114, "(function int debug-menu-msg float object)"],
[115, "(function int debug-menu-msg float object)"],
[116, "(function int debug-menu-msg float object)"],
[117, "(function int debug-menu-msg float object)"],
[118, "(function int debug-menu-msg float object)"],
[119, "(function int debug-menu-msg float object)"],
[120, "(function int debug-menu-msg float object)"],
[121, "(function int debug-menu-msg float object)"],
[122, "(function int debug-menu-msg float object)"],
[123, "(function int debug-menu-msg float object)"],
[124, "(function int debug-menu-msg float object)"],
[125, "(function int debug-menu-msg float object)"],
[126, "(function int debug-menu-msg float object)"],
[127, "(function int debug-menu-msg float object)"],
[128, "(function int debug-menu-msg float object)"],
[129, "(function int debug-menu-msg float object)"],
[130, "(function int debug-menu-msg float object)"],
[131, "(function int debug-menu-msg float object)"],
[132, "(function int debug-menu-msg float object)"],
[133, "(function int debug-menu-msg float object)"],
[134, "(function int debug-menu-msg float object)"],
[135, "(function int debug-menu-msg float object)"],
[136, "(function int debug-menu-msg float object)"],
[137, "(function int debug-menu-msg float object)"],
[138, "(function int debug-menu-msg float object)"],
[139, "(function int debug-menu-msg float object)"],
[140, "(function int debug-menu-msg float object)"],
[141, "(function int debug-menu-msg float object)"],
[142, "(function int debug-menu-msg float object)"],
[143, "(function int debug-menu-msg float object)"],
[144, "(function int debug-menu-msg float object)"],
[145, "(function int debug-menu-msg float object)"],
[146, "(function int debug-menu-msg float object)"],
[147, "(function int debug-menu-msg float object)"],
[148, "(function int debug-menu-msg float object)"],
[149, "(function int debug-menu-msg float object)"],
[150, "(function int debug-menu-msg float object)"],
[151, "(function int debug-menu-msg float object)"],
[152, "(function int debug-menu-msg float object)"],
[153, "(function int debug-menu-msg float object)"],
[154, "(function int debug-menu-msg float object)"],
[155, "(function int debug-menu-msg float object)"],
[156, "(function int debug-menu-msg float object)"],
[157, "(function int debug-menu-msg float object)"],
[158, "(function int debug-menu-msg float object)"],
[159, "(function int debug-menu-msg float object)"],
[160, "(function object)"],
[161, "(function object)"],
[162, "(function object)"],
[163, "(function object)"],
[164, "(function object)"],
[165, "(function object)"],
[166, "(function object)"],
[167, "(function object)"],
[168, "(function int debug-menu-msg object)"],
[169, "(function int debug-menu-msg object)"],
[170, "(function int debug-menu-msg object)"],
[171, "(function int debug-menu-msg object)"],
[172, "(function int debug-menu-msg object)"],
[173, "(function int debug-menu-msg float object)"],
[174, "(function int debug-menu-msg float object)"],
[175, "(function int debug-menu-msg float object)"],
[176, "(function int debug-menu-msg float object)"],
[177, "(function int debug-menu-msg float object)"],
[178, "(function int debug-menu-msg float object)"],
[179, "(function int debug-menu-msg float object)"],
[180, "(function int debug-menu-msg float object)"],
[181, "(function int debug-menu-msg float object)"],
[182, "(function int debug-menu-msg float object)"],
[183, "(function int debug-menu-msg float object)"],
[184, "(function int debug-menu-msg float object)"],
[185, "(function int debug-menu-msg float object)"],
[186, "(function int debug-menu-msg float object)"],
[187, "(function int debug-menu-msg float object)"],
[188, "(function int debug-menu-msg float object)"],
[189, "(function int debug-menu-msg float object)"],
[190, "(function int debug-menu-msg float object)"],
[191, "(function int debug-menu-msg float object)"],
[192, "(function int debug-menu-msg float object)"],
[193, "(function int debug-menu-msg float object)"],
[194, "(function int debug-menu-msg float object)"],
[195, "(function int debug-menu-msg float object)"],
[196, "(function int debug-menu-msg float object)"],
[197, "(function int debug-menu-msg float object)"],
[198, "(function int debug-menu-msg float object)"],
[199, "(function int debug-menu-msg float object)"],
[200, "(function int debug-menu-msg float object)"],
[201, "(function int debug-menu-msg float object)"],
[202, "(function int debug-menu-msg float object)"],
[203, "(function int debug-menu-msg float object)"],
[204, "(function int debug-menu-msg float object)"],
[205, "(function int debug-menu-msg float object)"],
[206, "(function int debug-menu-msg float object)"],
[207, "(function int debug-menu-msg float object)"],
[208, "(function int debug-menu-msg float object)"],
[209, "(function int debug-menu-msg float object)"],
[210, "(function int debug-menu-msg float object)"],
[211, "(function int debug-menu-msg float object)"],
[212, "(function int debug-menu-msg float object)"],
[213, "(function int debug-menu-msg float object)"],
[214, "(function int debug-menu-msg float object)"],
[215, "(function symbol debug-menu-msg float float object)"],
[216, "(function symbol debug-menu-msg float float object)"],
[217, "(function int debug-menu-msg float object)"],
[218, "(function symbol debug-menu-msg float float object)"],
[219, "(function symbol debug-menu-msg float float object)"],
[220, "(function symbol debug-menu-msg float float object)"],
[221, "(function symbol debug-menu-msg float float object)"],
[222, "(function symbol debug-menu-msg float float object)"],
[223, "(function symbol debug-menu-msg float float object)"],
[224, "(function symbol debug-menu-msg float float object)"],
[225, "(function symbol debug-menu-msg float float object)"],
[226, "(function symbol debug-menu-msg float float object)"],
[227, "(function symbol debug-menu-msg float float object)"],
[228, "(function symbol debug-menu-msg float float object)"],
[229, "(function symbol debug-menu-msg float float object)"],
[230, "(function symbol debug-menu-msg float float object)"],
[231, "(function symbol debug-menu-msg float float object)"],
[232, "(function symbol debug-menu-msg float float object)"],
[233, "(function symbol debug-menu-msg float float object)"],
[234, "(function symbol debug-menu-msg float float object)"],
[235, "(function object)"],
[236, "(function object)"],
[237, "(function symbol debug-menu-msg float float object)"],
[239, "(function symbol debug-menu-msg object)"],
[240, "(function int debug-menu-msg float object)"],
[241, "(function int debug-menu-msg float object)"],
[242, "(function int debug-menu-msg float object)"],
[243, "(function int debug-menu-msg float object)"],
[244, "(function debug-menu debug-menu symbol)"],
[245, "(function debug-menu debug-menu symbol)"],
[246, "(function debug-menu debug-menu symbol)"],
[247, "(function debug-menu debug-menu symbol)"]
],
"enemy-states": [[38, "(function object :behavior enemy)"]],
"scene-actor": [
[0, "(function none)"],
[1, "(function flut-npc none)"],
[2, "(function flut-npc art-element)"],
[39, "(function flut-npc flut-npc)"]
],
"warp-gate": [
[0, "(function object)"],
[8, "(function string object :behavior process)"],
[12, "(function object :behavior target)"]
],
"gun-yellow-shot": [[59, "(function handle object :behavior process)"]],
"gun-dark-shot": [
[25, "(function collide-shape-prim none :behavior gravity-spinner)"],
[34, "(function handle float object :behavior process)"]
],
"entity": [
[11, "(function process object)"],
[16, "(function process object)"],
[57, "(function process object)"],
[61, "(function process object)"]
],
"target-darkjak": [
[5, "(function object :behavior target)"],
[
20,
"(function (pointer float) (pointer int64) (pointer int64) object :behavior target)"
],
[21, "(function object :behavior target)"]
],
"memory-usage": [
[2, "(function process-drawable symbol)"],
[3, "(function basic symbol)"]
],
"bug-report": [
[0, "(function object :behavior bug-report)"],
[1, "(function object :behavior bug-report)"]
],
"relocate": [[7, "(function sparticle-system sparticle-cpuinfo none)"]],
"target-mech": [
[7, "(function object :behavior target)"],
[8, "(function object :behavior target)"],
[9, "(function object :behavior target)"],
[18, "(function surface surface surface int object :behavior target)"],
[19, "(function surface surface surface int object :behavior target)"]
],
"mech-states": [[57, "(function object :behavior target)"]],
"target-flut": [
[14, "(function surface surface surface int object :behavior target)"],
[20, "(function object :behavior target)"],
[21, "(function object :behavior target)"],
[33, "(function process-focusable object)"],
[72, "(function object)"],
[73, "(function object :behavior target)"],
[74, "(function object :behavior target)"]
],
"nav-control": [
[0, "(function object nav-control none)"],
[1, "(function object nav-control none)"],
[2, "(function object nav-control none)"],
[3, "(function object nav-control none)"],
[4, "(function object nav-control none)"],
[5, "(function object nav-control none)"],
[6, "(function object nav-control none)"],
[7, "(function object nav-control none)"],
[8, "(function object nav-control none)"],
[9, "(function object nav-control none)"]
],
"nav-enemy": [[7, "(function enemy-jump-info none :behavior nav-enemy)"]],
"task-control": [
[53, "(function game-task-node-info symbol object)"],
[54, "(function game-task-node-info object)"],
[67, "(function pair symbol)"]
],
"merc-death": [[3, "(function time-frame :behavior process-drawable)"]],
"vehicle-states": [
[10, "(function collide-shape-prim none)"],
[12, "(function collide-shape-prim none)"]
],
"prebot-states": [[21, "(function vector :behavior prebot)"]],
"wasall-obs": [
[0, "(function object)"],
[1, "(function object)"],
[2, "(function object)"],
[3, "(function object)"]
],
"roboguard": [
[1, "(function cspace transformq none)"],
[2, "(function cspace transformq none)"],
[25, "(function int int float object :behavior roboguard)"],
[45, "(function roboguard symbol object)"]
],
"vehicle": [
[6, "(function collide-shape-prim none)"],
[7, "(function collide-shape-prim none)"]
],
"wvehicle-wheel": [
[7, "(function collide-shape-prim none)"],
[11, "(function collide-shape-prim none)"],
[17, "(function collide-shape-prim none)"]
],
"wvehicle-states": [
[20, "(function collide-shape-prim none)"],
[22, "(function collide-shape-prim none)"]
],
"wvehicle": [[6, "(function collide-shape-prim none)"]],
"pilot-states": [
[15, "(function surface surface surface int object :behavior target)"]
],
"was-squad-control": [[16, "(function object object)"]],
"des-cactus": [[13, "(function collide-shape-prim none)"]],
"desertg-obs": [
[4, "(function collide-shape-prim none)"],
[7, "(function collide-shape-prim none)"]
],
"desertf-obs": [[7, "(function none)"]],
"temple-obs2": [
[43, "(function symbol)"],
[46, "(function object :behavior tpl-watcher)"]
],
"temple-scenes": [
[0, "(function none)"],
[1, "(function none)"],
[2, "(function none)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"]
],
"des-beast-2": [
[1, "(function cspace transformq none)"],
[2, "(function cspace transformq none)"],
[23, "(function projectile none)"]
],
"scorpion-gun": [
[33, "(function cspace transformq none)"],
[34, "(function cspace transformq none)"]
],
"hover-formation": [
[10, "(function form-search-info float)"],
[11, "(function int int form-search-info uint)"],
[14, "(function vector object)"],
[15, "(function int int (pointer object) int)"]
],
"robo-hover": [
[14, "(function robo-hover cspace float float vector vector int object)"]
],
"tower-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"]
],
"forest-kill-plants": [
[5, "(function engine-pers connection-pers object object symbol)"],
[7, "(function engine-pers connection-pers object object symbol)"]
],
"forest-tasks": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function none :behavior scene-player)"],
[11, "(function none :behavior scene-player)"],
[12, "(function none :behavior scene-player)"],
[13, "(function none :behavior scene-player)"],
[14, "(function none :behavior scene-player)"],
[15, "(function none :behavior scene-player)"],
[16, "(function none :behavior scene-player)"],
[17, "(function none :behavior scene-player)"],
[18, "(function none :behavior scene-player)"],
[19, "(function none :behavior scene-player)"],
[20, "(function none :behavior scene-player)"],
[21, "(function none :behavior scene-player)"]
],
"neo-wasp": [[15, "(function neo-wasp cspace transformq float float none)"]],
"for-turret": [
[1, "(function cspace transformq none)"],
[2, "(function cspace transformq none)"],
[3, "(function cspace transformq none)"],
[4, "(function cspace transformq none)"]
],
"volcano-obs": [[38, "(function cspace transformq none)"]],
"spiky-frog": [[9, "(function cspace transformq none)"]],
"volcano-scenes": [
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"]
],
"mantis": [
[8, "(function mantis vector float int vector vector)"],
[15, "(function mantis collide-shape-moving vector symbol)"]
],
"wcar-faccar": [[9, "(function handle object :behavior process)"]],
"wasstadb-obs": [[5, "(function object)"]],
"arena-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"]
],
"traffic-engine": [
[24, "(function traffic-find-segment-struct nav-segment none)"]
],
"desert-scenes": [
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function none :behavior scene-player)"],
[11, "(function none :behavior scene-player)"],
[12, "(function none :behavior scene-player)"],
[13, "(function none :behavior scene-player)"],
[14, "(function none :behavior scene-player)"],
[15, "(function none :behavior scene-player)"],
[16, "(function none :behavior scene-player)"],
[17, "(function none :behavior scene-player)"],
[18, "(function none :behavior scene-player)"],
[19, "(function none :behavior scene-player)"],
[20, "(function none :behavior scene-player)"],
[21, "(function none :behavior scene-player)"],
[22, "(function none :behavior scene-player)"],
[23, "(function none :behavior scene-player)"],
[24, "(function none :behavior scene-player)"],
[25, "(function none :behavior scene-player)"],
[26, "(function none :behavior scene-player)"],
[27, "(function none :behavior scene-player)"],
[28, "(function none :behavior scene-player)"],
[29, "(function none :behavior scene-player)"],
[30, "(function none :behavior scene-player)"],
[31, "(function none :behavior scene-player)"],
[32, "(function none :behavior scene-player)"],
[33, "(function none :behavior scene-player)"],
[34, "(function none :behavior scene-player)"],
[35, "(function none :behavior scene-player)"],
[36, "(function symbol :behavior scene-player)"]
],
"throne-scenes": [[0, "(function none :behavior scene-player)"]],
"terraformer-setup": [[38, "(function object :behavior manipy)"]],
"mined-scenes": [
[6, "(function none :behavior scene-player)"],
[7, "(function process-drawable vector none :behavior scene-player)"],
[8, "(function process-drawable vector none :behavior scene-player)"]
],
"wasteland-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function none :behavior scene-player)"]
],
"wasdoors-scenes": [[2, "(function none :behavior scene-player)"]],
"wasdef-manager": [
[7, "(function process-tree object)"],
[8, "(function process-tree object)"],
[9, "(function process-tree object)"]
],
"des-burning-bush": [[37, "(function symbol)"]],
"mh-wasp": [
[9, "(function mh-wasp cspace float float vector vector int none)"]
],
"mh-bat": [
[1, "(function cspace transformq none)"],
[21, "(function object :behavior mh-bat)"],
[26, "(function object :behavior mh-bat)"],
[30, "(function object :behavior mh-bat)"],
[34, "(function object :behavior mh-bat)"],
[39, "(function object :behavior mh-bat)"]
],
"factoryc-obs2": [
[67, "(function (pointer joint-exploder) :behavior fac-break-floor)"]
],
"factory-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function process-drawable none :behavior scene-player)"],
[11, "(function none :behavior scene-player)"],
[12, "(function none :behavior scene-player)"],
[13, "(function none :behavior scene-player)"],
[14, "(function none :behavior scene-player)"],
[15, "(function none :behavior scene-player)"]
],
"factory-boss-setup": [[37, "(function object :behavior manipy)"]],
"factory-boss-scenes": [
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"]
],
"bot": [[25, "(function gui-connection symbol :behavior bot)"]],
"oasis-defense": [
[4, "(function collide-shape-prim none)"],
[11, "(function collide-shape-prim none)"]
],
"ash-oasis-course": [
[0, "(function ashelin-oasis object)"],
[1, "(function ashelin-oasis object)"],
[2, "(function asht-wait-spot ashelin-oasis object)"],
[3, "(function ashelin-oasis symbol)"]
],
"comb-obs": [
[16, "(function collide-shape-prim none)"],
[33, "(function collide-shape-prim none)"],
[49, "(function collide-shape-prim none)"]
],
"comb-sentry": [[19, "(function collide-shape-prim none)"]],
"comb-field": [[5, "(function symbol)"]],
"comb-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"]
],
"railx-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function none :behavior scene-player)"],
[11, "(function none :behavior scene-player)"]
],
"title-obs": [
[20, "(function external-art-buffer int)"],
[22, "(function game-task object)"],
[26, "(function vector :behavior manipy)"],
[30, "(function object :behavior manipy)"]
],
"ff-squad-control": [
[6, "(function process-focusable traffic-object-type-info none)"],
[7, "(function process-focusable traffic-object-type-info none)"],
[8, "(function process-focusable traffic-object-type-info none)"],
[9, "(function crimson-guard traffic-object-type-info none)"]
],
"guard": [
[31, "(function crimson-guard collide-shape vector symbol)"],
[49, "(function process city-attacker-info int)"]
],
"guard-tazer": [
[7, "(function collide-shape-prim none)"],
[13, "(function collide-shape-prim none)"]
],
"roboguard-city": [
[13, "(function cspace transformq none)"],
[78, "(function roboguard-city symbol quaternion :behavior process)"]
],
"ctywide-obs": [[93, "(function symbol)"]],
"ctywide-scenes": [
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"]
],
"ctyport-obs": [[5, "(function collide-shape-prim none)"]],
"ctyport-scenes": [
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"]
],
"ctyport-attack": [[45, "(function object :behavior process)"]],
"intro-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function none :behavior scene-player)"],
[11, "(function none :behavior scene-player)"],
[12, "(function none :behavior scene-player)"],
[13, "(function none :behavior scene-player)"],
[14, "(function none :behavior scene-player)"],
[15, "(function none :behavior scene-player)"],
[16, "(function none :behavior scene-player)"],
[17, "(function none :behavior scene-player)"],
[18, "(function none :behavior scene-player)"],
[19, "(function none :behavior scene-player)"],
[20, "(function none :behavior scene-player)"],
[21, "(function none :behavior scene-player)"],
[22, "(function none :behavior scene-player)"],
[23, "(function none :behavior scene-player)"],
[24, "(function none :behavior scene-player)"],
[25, "(function none :behavior scene-player)"],
[26, "(function none :behavior scene-player)"],
[27, "(function none :behavior scene-player)"],
[28, "(function none :behavior scene-player)"],
[29, "(function none :behavior scene-player)"],
[30, "(function none :behavior scene-player)"],
[31, "(function none :behavior scene-player)"],
[32, "(function none :behavior scene-player)"],
[33, "(function none :behavior scene-player)"],
[34, "(function none :behavior scene-player)"],
[35, "(function none :behavior scene-player)"],
[36, "(function none :behavior scene-player)"],
[37, "(function none :behavior scene-player)"],
[38, "(function none :behavior scene-player)"],
[39, "(function none :behavior scene-player)"]
],
"freehq-scenes": [[0, "(function none :behavior scene-player)"]],
"hiphog-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"]
],
"rubble-attack": [[7, "(function int)"]],
"rublcst-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function none :behavior scene-player)"],
[11, "(function none :behavior scene-player)"],
[12, "(function none :behavior scene-player)"],
[13, "(function none :behavior scene-player)"]
],
"vinroom-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"]
],
"gungame-manager": [[6, "(function process symbol)"]],
"blow-tower-obs2": [
[16, "(function bt-mh-flyer cspace float float vector vector int none)"],
[117, "(function bt-roboguard symbol quaternion)"],
[124, "(function cspace transformq none)"]
],
"cty-blow-tower": [
[39, "(function collide-shape-prim none)"],
[27, "(function process symbol)"],
[46, "(function collide-shape-prim none)"],
[69, "(function process object)"]
],
"assault-enemies": [
[36, "(function assault-crimson-guard city-attacker-info int)"]
],
"assault-task": [[11, "(function symbol :behavior process)"]],
"precura-obs": [[98, "(function symbol :behavior process)"]],
"precurd-scenes": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"],
[2, "(function none :behavior scene-player)"],
[3, "(function none :behavior scene-player)"],
[4, "(function none :behavior scene-player)"],
[5, "(function none :behavior scene-player)"],
[6, "(function none :behavior scene-player)"],
[7, "(function none :behavior scene-player)"],
[8, "(function none :behavior scene-player)"],
[9, "(function none :behavior scene-player)"],
[10, "(function none :behavior scene-player)"],
[11, "(function none :behavior scene-player)"],
[12, "(function none :behavior scene-player)"],
[13, "(function none :behavior scene-player)"],
[14, "(function none :behavior scene-player)"]
]
}
@@ -1,785 +0,0 @@
{
////////////////////////////
// HACKS and ASM FUNCTIONS
////////////////////////////
"types_with_bad_inspect_methods": [
"game-task-event",
"game-task-control",
"predator-edge",
"manipy",
"process-tree",
"vector",
"target",
"vehicle-load-parts"
],
"no_type_analysis_functions_by_name": [],
// this limits the number of cases in a cond. The first argument is the name of the function.
// the second argument is the name of the first condition in the cond. Use print_cfg to find it out.
// The third argument is the number of cases. If you set it too small it may fail to build the CFG.
"cond_with_else_max_lengths": [
["(method 20 res-lump)", "b0", 2],
["(method 11 res-lump)", "b0", 1],
["(method 12 res-lump)", "b0", 1]
],
// if a cond with an else case is being used a value in a place where it looks wrong
// you can add the function name to this list and it will more aggressively reject this rewrite.
"aggressively_reject_cond_to_value_rewrite": [
"(method 10 res-lump)",
"(method 11 res-lump)",
"(method 12 res-lump)"
],
// this provides a hint to the decompiler that these functions will have a lot of inline assembly.
// currently it just leaves pcpyld as an asm op.
"hint_inline_assembly_functions": [],
"asm_functions_by_name": [
// checking boxed type is different now - these make the cfg stuff sad
"name=",
"(method 77 grenadier)",
"display-list-control",
"anim-test-anim-list-handler",
"anim-test-sequence-list-handler",
"anim-tester-get-playing-item",
"start-pilot-recorder",
"(anon-function 10 pilot-recorder)",
"(anon-function 10 sig-recorder)",
// actual asm
"quad-copy!",
"return-from-thread",
"return-from-thread-dead",
"reset-and-call",
"(method 10 cpu-thread)",
"(method 11 cpu-thread)",
"(method 0 catch-frame)",
"throw-dispatch",
"throw",
"run-function-in-process",
"set-to-run-bootstrap",
"return-from-exception",
"exp",
"(method 17 bounding-box)",
"(method 9 bounding-box)",
"(method 9 matrix)",
"quaternion->matrix-2",
"sin-rad",
"cos-rad",
"atan-series-rad",
"sign-float",
"dma-count-until-done",
"(method 11 collide-mesh-cache)",
"cpu-delay",
"qword-read-time",
"dma-test-func",
"move-test-func",
"symlink2",
"blerc-a-fragment",
"blerc-execute",
"foreground-check-longest-edge-asm",
"generic-light-proc",
"(method 17 collide-edge-work)",
"(method 10 collide-cache-prim)",
"(method 17 collide-cache)",
"(method 16 ocean)",
// unknown instructions
// logand with #f arg
// "bugfix?",
// CFG failed
"draw-inline-array-instance-shrub",
"(method 9 editable-region)", // condition branch assert hit
"test-to-from-spr",
"test-from-spr",
"test-to-spr",
"test-seq-read",
"test-worst-read",
"test-seq-write",
"test-worst-write",
// texture
"adgif-shader<-texture!",
// jak 3
"(method 10 manipulator)",
"(method 46 ff-squad-control)",
"memcpy",
// jak x
"get-string-length",
"rand-uint31-gen",
"vector-rotate-y-fast!",
// jak x decompiler crashes
"(method 13 race-line)",
"(method 23 gui-control)",
"(method 34 sky-work)",
"(method 35 sky-work)",
"(method 11 collide-mesh)",
"target-standard-event-handler",
"display-loop-main",
"(method 22 level)",
"(method 11 medius-cache)",
"water-anim-event-handler"
],
// these functions use pairs and the decompiler
// will be less picky about types related to pairs.
"pair_functions_by_name": [
"ref",
"ref&",
"(method 4 pair)",
"last",
"member",
"nmember",
"assoc",
"assoce",
"nassoc",
"nassoce",
"append!",
"delete!",
"delete-car!",
"insert-cons!",
"sort",
"unload-package",
"display-loop-main",
"lookup-level-info",
"(method 24 level-group)",
"(method 19 level-group)",
// script
"command-get-time",
"command-get-param",
"command-get-quoted-param",
"command-get-entity",
"(method 9 script-context)",
"(anon-function 6 script)",
"(anon-function 49 script)",
"(anon-function 52 script)",
"(anon-function 72 script)",
"(anon-function 73 script)",
"(anon-function 74 script)",
"(anon-function 75 script)",
"(anon-function 76 script)",
"(anon-function 80 script)",
"(method 11 script-context)",
"(method 10 script-context)",
"command-get-trans",
"key-assoc",
"(anon-function 0 script)",
// default-menu
"dm-scene-load-pick-func",
"debug-menu-make-continue-sub-menu",
"debug-menu-make-from-template",
"debug-menu-context-make-default-menus",
"debug-menu-make-task-menu",
"(method 19 gui-control)",
// menu
"debug-menu-rebuild",
"debug-menu-find-from-template",
"debug-menu-render",
"debug-menu-context-select-next-or-prev-item",
"debug-menu-context-select-new-item",
"debug-menu-send-msg",
// airlock
"(method 24 com-airlock)",
"(method 19 gui-control)",
"(method 28 editable)",
"execute-select",
"(method 29 editable)",
"(method 25 editable)",
// game-info
"(method 20 game-info)",
"print-continues",
// task-control
"(anon-function 55 task-control)",
"(method 17 load-state)",
"(method 12 level)",
"bg",
"update-sound-banks",
"entity-remap-names",
"(method 8 process-tree)",
"(post play-anim scene-player)",
"(method 25 scene-player)",
"(method 25 scene-player)",
"scene-player-init",
"next-continue",
"(method 25 warp-gate)",
"(code use warp-gate)",
"cspace-inspect-tree",
"(method 11 mtn-step-plat-rocks-a)",
"(method 11 mtn-step-plat-rocks-b)",
"(method 11 mtn-step-plat-rocks-c)",
"(method 22 fort-floor-spike-b)",
"prototypes-game-visible-set!",
"(method 22 fort-floor-spike-a)",
"(method 22 fort-floor-spike-b)",
"(method 22 fort-floor-spike-c)",
"(method 11 sew-catwalk)",
"(method 11 mtn-aval-rocks)",
"(method 11 gar-curtain)",
"(method 10 level-load-info)",
"(method 29 level-group)",
"(method 26 level-group)",
"(method 19 level)",
"(method 10 level)",
"update-sound-banks",
"level-base-level-name",
"borrow-city-expansion",
"add-want-level",
"level-find-borrow-slot",
"(method 18 level)",
"(method 11 tow-tentacle)",
"city-sound-expand-want-list",
"(method 12 cty-borrow-manager)",
"(method 16 cty-borrow-manager)",
"mark-permanent-holds",
"update-sound-info",
"insert-into-sound-list",
// title-obs
"(anon-function 22 title-obs)",
"cty-faction-evaluate-commands",
"traffic-manager-event-handler",
"(method 20 cty-faction-manager)"
],
// If format is used with the wrong number of arguments,
// it will often mess up the decompilation, as the decompiler assumes
// that they used the correct number. This will override the decompiler's
// automatic detection.
"bad_format_strings": {
"~170h~5d~220h~5d~280h~5,,2f": 3,
"~338h~5d~388h~5d~448h~5,,2f": 3,
"~30Htf: ~8D~134Hpr: ~8D~252Hsh: ~8D~370Hhd: ~8D~%": 4,
"~30Hal: ~8D~131Hwa: ~8D~252Hsp: ~8D~370Hwp: ~8D~%": 4,
"ERROR: <asg> ~A in spool anim loop for ~A ~D, but not loaded.~": 3,
// TODO - these should be automatic
" tfrag ~192H~5DK ~280Htfragment~456H~5DK~%": 2,
" tie-proto ~192H~5DK ~280Hsky~456H~5DK~%": 2,
" tie-instance ~192H~5DK ~280Htie-fragment~456H~5DK~%": 2,
" shrub-proto ~192H~5DK ~280Htie-scissor~456H~5DK~%": 2,
" shrub-instance ~192H~5DK ~280Hshrubbery~456H~5DK~%": 2,
" collision ~192H~5DK ~280Htie-generic~456H~5DK~%": 2,
" pris-anim ~192H~5DK ~280Hpris-generic~456H~5DK~%": 2,
" textures ~192H~5DK ~280Htextures~456H~5DK~%": 2,
" misc ~192H~5DK ~280Hsprite~456H~5DK~%": 2,
" entity ~192H~5DK~%": 1,
" pris-geo ~192H~5DK ~280Hpris-fragment~456H~5DK~%": 2,
"~33L~S~32L ~S": 2,
"~32L~S ~33L~S~1L": 2,
"~35L~S~33L ~S": 2,
"~1L~S~35L ~S": 2,
"~35L~S ~1L~S~1L": 2,
"~33L~S~35L ~S": 2,
"~33L~C~34L~S~33L~C": 3,
"~35L~S ~33L~S~1L": 2,
"~33L~S ~35L~S~1L": 2,
"~33L~C": 1,
"~33L~S~44L ~S": 2,
"~44L~S ~33L~S": 2,
"~10Htfrag: ~8,,0m": 1,
"~140Hshrub: ~8,,0m": 1,
"~272Halpha: ~8,,0m~%": 1,
"~27Htie: ~8,,0m": 1,
"~140Hfg-tf: ~8,,0m": 1,
"~270Hfg-pr: ~8,,0m~%": 1,
"~10Hfg-wa: ~8,,0m": 1,
"~140Hfg-sh: ~8,,0m": 1,
"~267Hfg-p2: ~8,,0m~%": 1,
"~30Hp2: ~8D~131Hhf: ~8D~%~1K": 2,
"Current time (~d:~d) [mission-percentage ~f~%": 2,
"~0K~Name~130HID~+50HVol~+15HPitch~+24HPan~+18HEar~+24HDist~%": 1,
"~130H~5D ~4D ~5D ~4D ~3D ~5,,0M~%": 5
},
"blocks_ending_in_asm_branch": {
"light-merge!": [1, 2, 3, 5, 7],
"bsp-camera-asm": [1, 2, 3, 4, 6, 7],
"level-remap-texture": [2, 3, 4, 5, 6],
"start-perf-stat-collection": [26],
"end-perf-stat-collection": [0],
"(method 23 gui-control)": [10, 46, 50, 58, 81, 90, 101],
"find-offending-process-focusable": [16, 19],
"(method 19 process-drawable)": [0, 2, 3, 7, 10, 11, 30],
"(anon-function 11 game-save)": [0, 3, 4, 5],
"(anon-function 3 game-save)": [15, 16],
"(anon-function 12 lightjak-wings)": [2, 3],
"target-standard-event-handler": [
5, 6, 7, 20, 64, 65, 66, 67, 72, 73, 83, 84, 85, 86, 87, 88, 96, 97, 109,
264, 265, 282, 283, 284, 290, 291, 306, 336, 350, 351, 412, 415, 427
],
"(method 9 curve-color-fast)": [0, 1],
"evaluate-color-curve-fast": [0, 1],
"(anon-function 0 target-death)": [71, 131, 132, 137],
"target-board-handler": [15, 16, 20],
"sprite-draw-distorters": [4, 5],
"(method 10 simple-sprite-system)": [0],
"add-debug-box-with-transform": [0, 3],
"add-debug-line-sphere": [0],
"bones-mtx-calc-execute": [19, 7],
"foreground-draw": [0, 1, 126],
"unpack-comp-rle": [1, 3, 5, 6],
"unpack-comp-huf": [2, 4, 5, 6, 7, 8, 9],
"unpack-comp-lzo": [
0,
1,
4,
5,
6,
7,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35, // branch fwd 39
39, // branch fwd no delay
43, // goto 18
45 // goto 6
],
"(method 16 level)": [0, 1, 5, 13, 14, 15],
"upload-vis-bits": [2, 6, 3, 0],
"set-background-regs!": [4, 3],
"draw-drawable-tree-instance-shrub": [5, 7, 9, 11],
"draw-drawable-tree-instance-tie": [21, 23, 31, 33],
"(method 12 flow-control)": [3, 9, 22],
"(method 26 level-group)": [40, 41, 67],
"borrow-city-expansion": [0, 9, 13, 15, 17],
"dma-add-process-drawable": [0, 77],
"real-main-draw-hook": [120, 122],
"display-frame-finish": [61],
"display-loop-main": [130],
"(method 63 collide-shape-moving)": [1, 2, 14, 49],
"(method 67 collide-shape-moving)": [2, 3, 13],
"(method 51 rigid-body-object)": [5],
"(anon-function 2 rigid-body-queue)": [0, 2],
"(method 15 rigid-body-queue)": [5, 6, 7, 9],
"(method 13 rigid-body-queue)": [5, 6, 7, 9],
"(method 11 rigid-body-queue)": [0, 6, 7, 9],
"(method 10 rigid-body-queue)": [10, 34, 37],
"(method 9 los-control)": [0, 43],
"load-game-text-info": [19, 20, 21],
"draw-actor-marks": [8],
"find-nearest-entity": [7, 9],
"(method 13 collide-cache)": [7, 9],
"(method 11 collide-mesh)": [2, 4],
"(method 12 collide-mesh-cache)": [0, 1, 2, 3, 4, 5],
"(method 10 collide-mesh)": [2],
"(method 42 collide-shape)": [0, 1, 2, 3, 4, 7],
"(method 18 collide-shape-prim-mesh)": [2, 3, 4, 5, 6, 7],
"(method 18 collide-shape-prim-sphere)": [2, 3, 4],
"(method 15 collide-shape-prim-sphere)": [1, 2, 3, 4, 5, 6],
"(method 16 collide-shape-prim-sphere)": [0, 1, 2, 3, 4],
"(method 36 collide-shape)": [8, 9],
"(method 45 collide-shape)": [33],
"(method 40 collide-shape)": [
0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
],
"(method 12 collide-shape-prim-group)": [1, 2, 3, 4, 5, 6],
"(method 13 collide-shape-prim)": [1, 2, 3, 4, 5, 6],
"(method 12 collide-shape-prim-sphere)": [
1, 2, 3, 4, 5, 8, 10, 11, 13, 14, 15
],
"(method 12 collide-shape-prim-mesh)": [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16
],
"update-actor-hash": [0, 2, 4],
"(method 24 grid-hash)": [39, 35, 22, 15],
"(anon-function 4 gun-states)": [
18, 128, 129, 131, 133, 135, 138, 139, 143
],
"(method 16 sparticle-launch-control)": [25, 35, 36, 48, 62, 65, 100, 102],
"(anon-function 17 target-ladder)": [0, 1],
"command-get-process": [46],
"foreground-draw-hud": [0, 7, 8, 9, 16, 22],
"target-flut-falling-anim-trans": [8, 9],
"(method 12 nav-mesh)": [0, 1, 2, 9],
"(method 20 nav-mesh)": [9],
"(method 21 nav-mesh)": [7],
"(method 29 nav-mesh)": [0, 1, 2, 4],
"(method 33 nav-mesh)": [10, 11, 12, 13],
"(method 34 nav-mesh)": [0, 1, 2, 4],
"(method 35 nav-mesh)": [0, 1, 2, 4],
"(method 36 nav-mesh)": [1, 2],
"(method 37 nav-mesh)": [4],
"(method 45 nav-mesh)": [1, 2],
"(method 46 nav-mesh)": [1, 2, 19, 20],
"(method 48 nav-mesh)": [4, 5, 6, 8],
"(method 49 nav-mesh)": [0, 1, 2, 3, 5],
"(method 18 nav-control)": [11, 12, 19, 20, 31, 34],
"(method 19 nav-control)": [9, 10],
"(method 40 nav-state)": [1, 2],
"point-poly-distance-min": [0, 1, 2, 3, 4, 5, 6, 7, 10],
"find-closest-circle-ray-intersection": [0, 4, 15, 16, 17, 18],
"(method 39 vehicle)": [0, 10, 12, 15],
"(anon-function 7 vehicle-states)": [0, 2],
"(method 11 vehicle-hud-requests)": [0, 6, 7, 10],
"(anon-function 12 neo-juicer)": [29, 30],
"(method 160 neo-grenadier)": [1, 2, 3],
"(method 82 spydroid-orig)": [13],
"(method 118 vehicle)": [3, 4, 7, 8, 9, 10, 17, 26, 30, 31, 33],
"(method 25 squad-control)": [0, 4, 5, 7],
"target-pilot-post": [0, 29],
"(method 36 was-squad-control)": [0, 8, 14, 16],
"(anon-function 6 nst-tasks)": [4, 9, 10, 16, 23, 30],
"(method 33 task-manager-nest-cocoons)": [3, 7, 13, 28],
"(method 90 wvehicle)": [29, 37, 38, 44],
"(anon-function 2 artifact-race)": [40, 55, 56, 57, 65, 66],
"(anon-function 27 course-race)": [6],
"(anon-function 65 temple-obs)": [5, 6],
"(anon-function 5 target-turret)": [0, 1, 2, 3],
"dp-bipedal-consider-attacks": [15, 19],
"(anon-function 25 volcanox-obs)": [3, 5, 6],
"(method 36 task-manager-arena-fight-base)": [11],
"(method 28 hud-wasgun)": [0, 1, 2, 4],
"(method 15 hud-wasgun)": [8, 28, 29, 30, 54],
"(method 15 vehicle-controller)": [0, 3, 5, 6, 7, 10],
"(method 51 hvehicle)": [5],
"(method 159 hvehicle)": [0, 1, 10, 19, 21, 23, 26],
"(method 18 vehicle-controller)": [0, 1, 74, 75],
"glider-too-low?": [2, 19, 21],
"(method 39 task-manager-desert-glide)": [0, 3, 4, 9],
"(method 36 task-manager-desert-glide)": [20, 50, 60],
"(method 37 task-manager-desert-glide)": [11, 12, 23, 29, 31],
"(method 34 task-manager-desert-glide)": [3],
"(anon-function 20 target-flut)": [0, 38, 39],
"(anon-function 14 flut-racer)": [7, 17, 19],
"(method 28 conveyor)": [22],
"generic-merc-execute-all": [7, 15],
"check-enemy": [0, 1],
"(method 91 h-warf)": [0],
"(method 51 h-warf)": [5],
"(method 44 nav-graph)": [0, 7, 8, 26, 34],
"(method 15 city-level-info)": [0, 1, 2, 6, 7, 9, 11, 13],
"(method 10 traffic-suppressor)": [0, 1, 2, 4],
"(method 18 traffic-tracker)": [5, 6, 7, 8],
"(method 21 traffic-tracker)": [0],
"(method 9 cty-faction-manager)": [8],
"(method 46 traffic-engine)": [0, 1, 2, 4],
"(method 42 traffic-engine)": [6],
"(method 17 traffic-manager)": [7, 19, 27, 28, 29, 30, 41],
"(anon-function 10 guard-rifle)": [9],
"(method 261 crimson-guard)": [52, 64],
"(anon-function 13 metalhead-predator)": [24, 25],
"(anon-function 90 ctywide-obs)": [4],
"(anon-function 10 cty-sniper-turret)": [44],
"(method 33 rub-tower)": [9, 10],
"(method 30 gungame-manager)": [0, 4, 5, 7],
"closest-pt-in-triangle": [17],
"find-knot-span": [0, 1, 2, 3, 5, 6, 7, 8, 9],
"curve-evaluate!": [0, 2, 5, 6, 7, 8, 9],
"circle-circle-xz-intersect": [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
]
},
// Sometimes the game might use format strings that are fetched dynamically,
// for example using the game text lookup method
// Add information about those format instructions here.
// e.g. "function-name":[[op, argc], [op, argc], ...]
// where "op" is the op number for the call to format.
"dynamic_format_arg_counts": {
"auto-save-post": [[182, 1]],
"(method 10 menu-secret-option)": [[289, 1]],
"(method 10 menu-create-game-option)": [[49, 1]],
"(method 10 menu-format-card-option)": [[49, 1]],
"(method 10 menu-card-removed-option)": [[49, 1]],
"(method 10 menu-insert-card-option)": [[49, 1]],
"(method 10 menu-hero-mode-message-option)": [[50, 1]],
"(method 10 menu-secrets-insufficient-space-option)": [[51, 1]],
"(method 10 menu-error-loading-option)": [
[65, 1],
[100, 1]
],
"(method 10 menu-insufficient-space-option)": [
[72, 1],
[112, 1]
],
"(method 10 menu-error-auto-saving-option)": [[73, 1]],
"(method 10 menu-loading-option)": [[113, 1]],
"(method 10 menu-icon-info-option)": [[150, 1]],
"(method 17 hud-goal)": [[71, 0]],
"(method 17 hud-miss)": [[71, 0]],
"(method 16 resetter)": [
[68, 1],
[101, 1],
[130, 1]
],
"(method 32 task-manager-desert-turtle-training)": [[59, 1]],
"(method 24 race-manager)": [[97, 1]],
"(method 25 race-manager)": [
[97, 1],
[126, 1]
],
"(method 15 hud-race-final-stats)": [[131, 0]],
"(method 15 hud-wasbbv-goal-time)": [[74, 0]],
"(method 32 task-manager-lightjak-training)": [[53, 0]],
"(method 18 hover-training-manager)": [[69, 0]],
"(method 37 task-manager-arena-training)": [[67, 1]],
"(method 15 hud-arena-final-stats)": [
[103, 0],
[147, 0]
],
"(method 35 task-manager-arena-fight-base)": [[53, 0]],
"(method 32 task-manager-arena-gun-training)": [[53, 0]],
"(method 26 task-manager-arena-fight-2)": [
[72, 0],
[186, 0]
],
"(method 37 task-manager-wascity-gungame)": [
[48, 0],
[78, 0],
[119, 0],
[157, 0],
[195, 0],
[227, 0],
[268, 0],
[306, 0],
[338, 0],
[379, 0],
[411, 0],
[446, 0]
],
"(method 30 was-pre-game)": [
[184, 0],
[276, 0]
],
"(method 32 task-manager-throne-gun-training)": [[53, 0]],
"(method 17 hud-spider-killed)": [[71, 0]],
"(trans idle des-burning-bush)": [
[226, 1],
[257, 0]
],
"(method 37 des-burning-bush)": [
[278, 0],
[336, 0]
],
"(method 38 des-burning-bush)": [
[109, 0],
[153, 0],
[196, 0]
],
"(method 15 freeze-time-hud)": [[108, 0]],
"(method 17 freeze-time-hud)": [[97, 0]],
"(method 15 hud-wasbbv-score)": [[61, 0]],
"(method 15 hud-wasbbv-goal)": [[64, 0]],
"(method 32 task-manager-dark-punch-training)": [[53, 0]],
"(method 32 task-manager-lightjak-training-shield)": [[53, 0]],
"(trans credits highres-viewer-manager)": [[185, 0]],
"(trans idle hirez-viewer)": [[356, 0]],
"(trans idle burning-bush)": [
[171, 1],
[202, 0]
],
"(method 33 task-manager-bbush-board)": [[86, 0]],
"(method 17 board-score-hud)": [[71, 0]],
"(method 23 gungame-manager)": [
[52, 0],
[90, 0],
[128, 0],
[164, 0],
[194, 0],
[235, 0],
[273, 0],
[305, 0],
[346, 0],
[378, 0],
[413, 0]
],
"(trans carry precur-bomb)": [[60, 0]]
},
"mips2c_functions_by_name": [
"collide-do-primitives",
"moving-sphere-triangle-intersect",
"calc-animation-from-spr",
"draw-string-asm",
// "draw-string",
// "get-string-length",
"adgif-shader<-texture-with-update!",
"init-boundary-regs",
"draw-boundary-polygon",
"render-boundary-quad",
"render-boundary-tri",
"clip-polygon-against-negative-hyperplane",
"clip-polygon-against-positive-hyperplane",
"sp-init-fields!",
"particle-adgif",
"sp-launch-particles-var",
"sparticle-motion-blur",
"sp-process-block-2d",
"sp-process-block-3d",
"set-tex-offset",
"draw-large-polygon",
"render-sky-quad",
"render-sky-tri",
"(method 17 sky-work)",
"(method 18 sky-work)",
"(method 32 sky-work)",
"(method 31 sky-work)",
"(method 29 sky-work)",
"(method 30 sky-work)",
// "(method 34 sky-work)",
// "(method 35 sky-work)",
"(method 11 collide-hash)",
"(method 12 collide-hash)",
"fill-bg-using-box-new",
"fill-bg-using-line-sphere-new",
"(method 12 collide-mesh)",
"(method 14 collide-mesh)",
"(method 15 collide-mesh)",
"(method 10 collide-edge-hold-list)",
"(method 19 collide-edge-work)",
"(method 9 edge-grab-info)",
"(method 16 collide-edge-work)",
"(method 17 collide-edge-work)",
"(method 18 collide-edge-work)",
"draw-large-polygon-ocean",
"render-ocean-quad",
"init-ocean-far-regs",
"(method 14 ocean)",
"(method 15 ocean)",
"(method 16 ocean)",
"(method 18 grid-hash)",
"(method 19 grid-hash)",
"(method 20 grid-hash)",
"(method 22 grid-hash)",
"(method 28 sphere-hash)",
"(method 33 sphere-hash)",
"(method 29 sphere-hash)",
"(method 30 sphere-hash)",
"(method 31 sphere-hash)",
"(method 32 sphere-hash)",
"(method 32 spatial-hash)",
"(method 34 spatial-hash)",
"(method 35 spatial-hash)",
"(method 36 spatial-hash)",
"(method 38 spatial-hash)",
"(method 10 collide-shape-prim-mesh)",
"(method 10 collide-shape-prim-sphere)",
"(method 10 collide-shape-prim-group)",
"(method 11 collide-shape-prim-mesh)",
"(method 11 collide-shape-prim-sphere)",
"(method 11 collide-shape-prim-group)",
"(method 9 collide-cache-prim)",
"(method 10 collide-cache-prim)",
"(method 17 collide-cache)",
"(method 9 collide-puss-work)",
"(method 10 collide-puss-work)",
"bones-mtx-calc",
"foreground-check-longest-edge-asm",
"foreground-merc",
"add-light-sphere-to-light-group",
"light-hash-add-items",
"light-hash-count-items",
"light-hash-get-bucket-index",
// nav-mesh / nav-control related
// TODO - it would be nice to eventually figure out the asm blocks for the majority of these
"nav-state-patch-pointers",
"(method 20 nav-engine)",
// "find-closest-circle-ray-intersection",
// "(method 18 nav-control)",
"nav-dma-send-to-spr-no-flush",
"nav-dma-send-from-spr-no-flush",
"(method 17 nav-engine)",
"(method 18 nav-engine)",
"(method 21 nav-engine)",
"(method 39 nav-state)",
"setup-blerc-chains-for-one-fragment",
"blerc-execute",
"ripple-create-wave-table",
"ripple-execute-init",
"ripple-apply-wave-table",
"ripple-matrix-scale",
"(method 53 squid)",
"init-vortex-regs",
"render-vortex-quad",
"draw-large-polygon-vortex",
"foreground-generic-merc",
"generic-merc-init-asm",
"mercneric-convert",
"high-speed-reject",
"generic-translucent",
"generic-merc-query",
"generic-merc-death",
"generic-merc-execute-asm",
"generic-merc-do-chain",
"generic-light-proc",
"generic-envmap-proc",
"generic-prepare-dma-double",
"generic-prepare-dma-single",
"generic-warp-source-proc",
"generic-warp-dest-proc",
"generic-warp-dest",
"generic-warp-envmap-dest",
"generic-no-light-proc",
"(method 21 cloth-system)",
"debug-line-clip?",
"(method 9 font-work)",
"live-func-curve",
"birth-func-curve",
"sparticle-motion-blur-dirt",
"foreground-draw-hud",
"shadow-execute",
"shadow-add-double-edges",
"shadow-add-single-edges",
"shadow-add-facing-single-tris",
"shadow-add-double-tris",
"shadow-xform-verts",
"shadow-calc-dual-verts",
"shadow-scissor-edges",
"shadow-scissor-top",
"shadow-init-vars",
"shadow-find-facing-single-tris",
"shadow-find-single-edges",
"shadow-find-facing-double-tris",
"shadow-find-double-edges",
"shadow-add-verts",
"shadow-add-single-tris"
],
"mips2c_jump_table_functions": {},
// there are some missing textures. I don't know what the game actually does here.
// the format for entries is [level, tpage, index]
"missing_textures": [
["lfac", 0, 0],
["ltow", 0, 0],
["lcit", 0, 0],
["pow", 0, 0],
["wasintro", 0, 0],
["lfacctyb", 0, 0],
["intpfall", 0, 0],
["lfaccity", 0, 0],
["ltowcity", 0, 0],
["powergd", 0, 0],
["lcitysml", 0, 0]
],
// some object files have garbage pad data at the end which makes the decompiler
// assume they must be different files, such as the art group for orb-cache-top.
// this just suppresses a message.
"expected_merged_objs": []
}
@@ -1,15 +0,0 @@
// This overrides the stack size for calls to stack-size-set! in given functions.
{
// NOTE: almost all of these were just copy pasted from jak2
// so it's impossible to know which are actually needed for jakx...
// commenting out incase there's something here actually needed
"(method 29 target)": 2048,
"(method 11 part-spawner)": 64,
"(method 11 elevator)": 1024,
"scene-player-init": 1024,
"task-manager-init-by-other": 2048,
"race-manager-init-by-other": 1024,
"neo-sat-shield-init-by-other": 64,
"bt-gun-manager-init-by-other": 256
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+100 -47
View File
@@ -100,57 +100,110 @@ void TextureDB::add_index_texture(u32 tpage,
}
void TextureDB::merge_textures(const fs::path& base_path) {
for (auto& tex : textures) {
fs::path full_path = base_path / tpage_names.at(tex.second.page) / (tex.second.name + ".png");
if (fs::exists(full_path)) {
lg::info("Merging {}", full_path.string().c_str());
int w, h;
auto merge_data = stbi_load(full_path.string().c_str(), &w, &h, 0, 4); // rgba channels
if (!merge_data) {
lg::warn("failed to load PNG file: {}", full_path.string().c_str());
continue;
} else if (w != tex.second.w || h != tex.second.h) {
lg::warn("merge texture does not match the same dimensions: {}, {} != {} || {} != {}",
full_path.string().c_str(), w, tex.second.w, h, tex.second.h);
stbi_image_free(merge_data);
continue;
}
// Merge any non-transparent pixels into the existing texture
for (int i = 0; i < w * h * 4; i += 4) {
const auto merge_pixel_a = merge_data[i + 3];
if (merge_pixel_a != 0) {
u32 merge_pixel;
memcpy(&merge_pixel, &merge_data[i], sizeof(u32));
tex.second.rgba_bytes.at(i / 4) = merge_pixel;
}
}
stbi_image_free(merge_data);
}
}
merge_texture_dir = base_path;
}
void TextureDB::replace_textures(const fs::path& path) {
fs::path base_path(path);
for (auto& tex : textures) {
fs::path full_path = base_path / tpage_names.at(tex.second.page) / (tex.second.name + ".png");
if (!fs::exists(full_path)) {
full_path = base_path / "_all" / (tex.second.name + ".png");
if (!fs::exists(full_path))
continue;
}
lg::info("Replacing {}", tpage_names.at(tex.second.page) + "/" + (tex.second.name));
int w, h;
auto data = stbi_load(full_path.string().c_str(), &w, &h, 0, 4); // rgba channels
if (!data) {
lg::warn("failed to load PNG file: {}", full_path.string().c_str());
continue;
}
tex.second.rgba_bytes.resize(w * h);
memcpy(tex.second.rgba_bytes.data(), data, w * h * 4);
tex.second.w = w;
tex.second.h = h;
stbi_image_free(data);
replace_texture_dir = path;
}
void TextureDB::merge_texture(u32 id, std::vector<u32>& rgba) const {
if (!merge_texture_dir) {
return;
}
const auto& tex = textures.at(id);
fs::path full_path = *merge_texture_dir / tpage_names.at(tex.page) / (tex.name + ".png");
if (!fs::exists(full_path)) {
return;
}
lg::info("Merging {}", full_path.string().c_str());
int w, h;
auto merge_data = stbi_load(full_path.string().c_str(), &w, &h, 0, 4);
if (!merge_data) {
lg::warn("failed to load PNG file: {}", full_path.string().c_str());
return;
}
if (w != tex.w || h != tex.h) {
lg::warn("merge texture does not match the same dimensions: {}, {} != {} || {} != {}",
full_path.string().c_str(), w, tex.w, h, tex.h);
stbi_image_free(merge_data);
return;
}
// Merge any non-transparent pixels into the existing texture
for (int i = 0; i < w * h * 4; i += 4) {
const auto merge_pixel_a = merge_data[i + 3];
if (merge_pixel_a != 0) {
u32 merge_pixel;
memcpy(&merge_pixel, &merge_data[i], sizeof(u32));
rgba.at(i / 4) = merge_pixel;
}
}
stbi_image_free(merge_data);
}
std::optional<ResolvedTextureData> TextureDB::replace_texture(u32 id) const {
if (!replace_texture_dir) {
return std::nullopt;
}
const auto& tex = textures.at(id);
const auto& tpage_name = tpage_names.at(tex.page);
fs::path full_path = *replace_texture_dir / tpage_name / (tex.name + ".png");
if (!fs::exists(full_path)) {
full_path = *replace_texture_dir / "_all" / (tex.name + ".png");
if (!fs::exists(full_path)) {
return std::nullopt;
}
}
lg::info("Replacing {}", tpage_name + "/" + tex.name);
int w, h;
auto data = stbi_load(full_path.string().c_str(), &w, &h, 0, 4);
if (!data) {
lg::warn("failed to load PNG file: {}", full_path.string().c_str());
return std::nullopt;
}
ResolvedTextureData result;
result.w = static_cast<u16>(w);
result.h = static_cast<u16>(h);
result.rgba.resize(w * h);
memcpy(result.rgba.data(), data, w * h * 4);
stbi_image_free(data);
return result;
}
ResolvedTextureData TextureDB::resolve_texture(u32 id) const {
const auto& tex = textures.at(id);
ResolvedTextureData result{
.w = tex.w,
.h = tex.h,
.rgba = tex.rgba_bytes,
};
merge_texture(id, result.rgba);
if (auto replacement = replace_texture(id)) {
result = std::move(*replacement);
}
return result;
}
/*!
+13
View File
@@ -1,6 +1,7 @@
#pragma once
#include <map>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
@@ -11,6 +12,12 @@
#include "common/util/FileUtil.h"
namespace decompiler {
struct ResolvedTextureData {
u16 w;
u16 h;
std::vector<u32> rgba;
};
struct TextureDB {
TextureDB();
struct TextureData {
@@ -25,12 +32,16 @@ struct TextureDB {
std::map<u32, TextureData> textures;
std::unordered_map<u32, std::string> tpage_names;
std::unordered_map<std::string, std::set<u32>> texture_ids_per_level;
std::optional<fs::path> merge_texture_dir;
std::optional<fs::path> replace_texture_dir;
// special textures for animation.
std::map<u32, tfrag3::IndexTexture> index_textures_by_combo_id;
std::unordered_map<std::string, u32> animated_tex_output_to_anim_slot;
ResolvedTextureData resolve_texture(u32 id) const;
static constexpr int kPlaceholderWhiteTexturePage = INT16_MAX;
static constexpr int kPlaceholderWhiteTextureId = 0;
@@ -57,6 +68,8 @@ struct TextureDB {
void merge_textures(const fs::path& base_path);
void replace_textures(const fs::path& path);
void merge_texture(u32 id, std::vector<u32>& rgba) const;
std::optional<ResolvedTextureData> replace_texture(u32 id) const;
std::string generate_texture_dest_adjustment_table() const;
};
+17 -2
View File
@@ -130,7 +130,7 @@ int run_decompilation_process(decompiler::Config config,
// print disassembly
if (config.disassemble_code || config.disassemble_data) {
db.write_disassembly(out_folder, config.disassemble_data, config.disassemble_code,
config.write_hex_near_instructions);
config.write_hex_near_instructions, config.dump_function_metadata);
}
if (config.process_art_groups) {
@@ -180,7 +180,7 @@ int run_decompilation_process(decompiler::Config config,
if (config.generate_all_types) {
ASSERT_MSG(config.decompile_code, "Must decompile code to generate all-types");
db.ir2_analyze_all_types(out_folder / "new-all-types.gc", config.old_all_types_file,
db.ir2_analyze_all_types(out_folder / "_new-all-types.gc", config.old_all_types_file,
config.hacks.types_with_bad_inspect_methods);
}
@@ -195,6 +195,12 @@ int run_decompilation_process(decompiler::Config config,
}
if (config.dump_part_group_table) {
if (!config.process_part_group_table || !config.decompile_code) {
lg::error(
"[DUMP] 'dump_part_group_table' set without setting 'process_part_group_table' or "
"'decompile_code'");
}
lg::info("[DUMP] Dumping part group table");
db.dump_part_group_table(out_folder, config.part_group_table);
}
@@ -243,6 +249,11 @@ int run_decompilation_process(decompiler::Config config,
lg::info("[Mem] After spool handling: {} MB", get_peak_rss() / (1024 * 1024));
TextureDB tex_db;
if (config.dump_tex_info && (!config.process_tpages && config.levels_extract)) {
lg::error(
"[DUMP] 'dump_tex_info' set without also setting 'process_tpages' or 'levels_extract'");
return 1;
}
if (config.process_tpages || config.levels_extract) {
auto textures_out = out_folder / "textures";
auto dump_out = out_folder / "import";
@@ -254,6 +265,10 @@ int run_decompilation_process(decompiler::Config config,
tex_db.generate_texture_dest_adjustment_table());
}
if (config.dump_tex_info) {
if (!config.write_tpage_imports) {
lg::error("[DUMP] 'dump_tex_info' set without setting 'write_tpage_imports'");
return 1;
}
auto texture_file_name = out_folder / "dump" / "tex-info.min.json";
nlohmann::json texture_json = db.dts.textures;
file_util::create_dir_if_needed_for_file(texture_file_name);
+131
View File
@@ -16,6 +16,136 @@ struct Joint {
math::Matrix4f bind_pose_T_w;
};
struct UncompressedSingleJointAnim {
std::vector<math::Vector3f> trans_frames;
std::vector<math::Vector3f> scale_frames;
std::vector<math::Vector4f> quat_frames;
};
struct UncompressedJointAnim {
std::string name;
std::vector<UncompressedSingleJointAnim> joints;
float framerate = 30;
int frames = 0;
};
struct CompressedMatrixMetadata {
bool is_animated[2];
};
struct CompressedFrame {
std::vector<u16> data16;
std::vector<u32> data32;
std::vector<u64> data64;
int size_bytes() const { return data16.size() * 2 + data32.size() * 4 + data64.size() * 8; }
};
struct CompressedJointMetadata {
bool animated_trans = false;
bool animated_quat = false;
bool animated_scale = false;
bool big_trans_mode = false;
};
struct CompressedAnim {
std::string name;
CompressedFrame fixed;
std::vector<CompressedFrame> frames;
bool matrix_animated[2] = {false, false};
std::vector<CompressedJointMetadata> joint_metadata;
float framerate = 60;
};
struct JointAnimCompressedHDR {
u32 control_bits[14];
u32 num_joints;
u32 matrix_bits;
JointAnimCompressedHDR() {
for (auto& bit : control_bits) {
bit = 0;
}
num_joints = 1;
matrix_bits = 0;
}
};
struct JointAnimCompressedFixed {
JointAnimCompressedHDR hdr;
u32 offset_64;
u32 offset_32;
u32 offset_16;
u32 reserved;
math::Vector4f data[133];
int num_data_qw_used = 0;
bool mat[2] = {false, false};
math::Matrix4f mats[2] = {math::Matrix4f::zero(), math::Matrix4f::zero()};
u64 data64_size;
u32 data32_size;
u16 data16_size;
std::vector<u64> data64;
std::vector<u32> data32;
std::vector<u16> data16;
JointAnimCompressedFixed() {
offset_64 = 0;
offset_32 = 0;
offset_16 = 0;
reserved = 0;
data[0] = math::Vector4f(1.0f, 0.0f, 0.0f, 0.0f);
data[1] = math::Vector4f(0.0f, 1.0f, 0.0f, 0.0f);
data[2] = math::Vector4f(0.0f, 0.0f, 1.0f, 0.0f);
data[3] = math::Vector4f(0.0f, 0.0f, 0.0f, 1.0f);
data[4] = math::Vector4f(1.0f, 0.0f, 0.0f, 0.0f);
data[5] = math::Vector4f(0.0f, 1.0f, 0.0f, 0.0f);
data[6] = math::Vector4f(0.0f, 0.0f, 1.0f, 0.0f);
data[7] = math::Vector4f(0.0f, 0.0f, 0.0f, 1.0f);
num_data_qw_used = 8;
}
};
struct JointAnimCompressedFrame {
u32 offset_64;
u32 offset_32;
u32 offset_16;
u32 reserved;
// math::Vector4f data[133];
u32 num_data_qw_used = 0;
bool mat[2] = {false, false};
math::Matrix4f mats[2] = {math::Matrix4f::zero(), math::Matrix4f::zero()};
u64 data64_size;
u32 data32_size;
u16 data16_size;
std::vector<u64> data64;
std::vector<u32> data32;
std::vector<u16> data16;
JointAnimCompressedFrame() {
offset_64 = 0;
offset_32 = 0;
offset_16 = 0;
reserved = 0;
}
};
struct JointAnimCompressedControl {
u32 num_frames;
u32 fixed_qwc;
u32 frame_qwc;
JointAnimCompressedFixed fixed;
std::vector<JointAnimCompressedFrame> frame;
};
struct ArtJointAnim {
std::string name;
float speed;
float artist_base;
float artist_step;
s16 length;
JointAnimCompressedControl frames;
};
/*!
* Data extracted from art groups that is not needed for .FR3, but is potentially needed for other
* stuff (skeleton export).
@@ -24,6 +154,7 @@ struct ArtData {
std::string art_group_name;
std::string art_name;
std::vector<Joint> joint_group;
std::vector<ArtJointAnim> anims;
};
} // namespace level_tools
+299
View File
@@ -0,0 +1,299 @@
#include "extract_anim.h"
#include "common_formats.h"
#include "decompiler/ObjectFile/LinkedObjectFile.h"
#include "decompiler/util/goal_data_reader.h"
#include "third-party/lzokay/lzokay.hpp"
namespace decompiler {
static std::vector<u8> get_plain_data_bytes_up_to_label(const Ref& ref) {
const auto& words = ref.data->words_by_seg.at(ref.seg);
int start_word = ref.byte_offset / 4;
std::vector<u8> result;
for (int w = start_word; w < (int)words.size(); w++) {
if (words[w].kind() != LinkedWord::PLAIN_DATA)
break;
for (int b = 0; b < 4; b++)
result.push_back(words[w].get_byte(b));
}
return result;
}
static u32 read_u32(const u8* p) {
u32 v;
memcpy(&v, p, 4);
return v;
}
static void parse_fixed_from_buf(const u8* p,
level_tools::JointAnimCompressedFixed& fixed,
u32 fixed_qwc) {
memcpy(fixed.hdr.control_bits, p, sizeof(u32) * 14);
fixed.hdr.num_joints = read_u32(p + 56);
fixed.hdr.matrix_bits = read_u32(p + 60);
fixed.offset_64 = read_u32(p + 64);
fixed.offset_32 = read_u32(p + 68);
fixed.offset_16 = read_u32(p + 72);
fixed.reserved = read_u32(p + 76);
fixed.data64_size = fixed.offset_32 - fixed.offset_64;
fixed.data32_size = fixed.offset_16 - fixed.offset_32;
int data16 = (int)((fixed_qwc - 5) * 16) - (int)fixed.data64_size - (int)fixed.data32_size;
ASSERT(data16 >= 0);
fixed.data16_size = (u16)data16;
fixed.mat[0] = (fixed.hdr.matrix_bits & 1) == 0;
fixed.mat[1] = (fixed.hdr.matrix_bits & 2) == 0;
const u8* data = p + 80;
int d64 = (int)fixed.data64_size;
int d32 = (int)fixed.data32_size;
int d16 = (int)fixed.data16_size;
fixed.data64.resize((d64 + 7) / 8);
if (d64 > 0)
memcpy(fixed.data64.data(), data + fixed.offset_64, d64);
fixed.data32.resize((d32 + 3) / 4);
if (d32 > 0)
memcpy(fixed.data32.data(), data + fixed.offset_32, d32);
fixed.data16.resize((d16 + 1) / 2);
if (d16 > 0)
memcpy(fixed.data16.data(), data + fixed.offset_16, d16);
}
static void parse_frame_from_buf(const u8* p,
level_tools::JointAnimCompressedFrame& frame,
u32 frame_qwc) {
frame.offset_64 = read_u32(p + 0);
frame.offset_32 = read_u32(p + 4);
frame.offset_16 = read_u32(p + 8);
frame.reserved = read_u32(p + 12);
frame.data64_size = frame.offset_32 - frame.offset_64;
frame.data32_size = frame.offset_16 - frame.offset_32;
int data16 = (int)((frame_qwc - 1) * 16) - (int)frame.data64_size - (int)frame.data32_size;
ASSERT(data16 >= 0);
frame.data16_size = (u16)data16;
const u8* data = p + 16;
int fd64 = (int)frame.data64_size;
int fd32 = (int)frame.data32_size;
int fd16 = (int)frame.data16_size;
frame.data64.resize((fd64 + 7) / 8);
if (fd64 > 0)
memcpy(frame.data64.data(), data + frame.offset_64, fd64);
frame.data32.resize((fd32 + 3) / 4);
if (fd32 > 0)
memcpy(frame.data32.data(), data + frame.offset_32, fd32);
frame.data16.resize((fd16 + 1) / 2);
if (fd16 > 0)
memcpy(frame.data16.data(), data + frame.offset_16, fd16);
}
void extract_animations(const ObjectFileData& ag_data,
const DecompilerTypeSystem& dts,
GameVersion version,
std::map<std::string, level_tools::ArtData>& out) {
auto ja_locs = find_objects_with_type(ag_data.linked_data, "art-joint-anim");
if (ja_locs.empty()) {
lg::warn("extract_animations: art group {} has no anims, skipping", ag_data.name_in_dgo);
return;
}
// jak 2/3 split the first word into num-frames + flags
const bool has_flags = version != GameVersion::Jak1;
for (auto loc : ja_locs) {
TypedRef ref(Ref{&ag_data.linked_data, 0, loc * 4}, dts.ts.lookup_type("art-joint-anim"));
auto master_art_name = read_string_field(ref, "master-art-group-name", dts, false);
level_tools::ArtJointAnim ja;
ja.name = read_string_field(ref, "name", dts, false);
ja.speed = read_plain_data_field<float>(ref, "speed", dts);
ja.artist_base = read_plain_data_field<float>(ref, "artist-base", dts);
ja.artist_step = read_plain_data_field<float>(ref, "artist-step", dts);
Ref jacc = deref_label(get_field_ref(ref, "frames", dts));
int jacc_word_off = 0;
u32 first_word = deref_u32(jacc, jacc_word_off++);
ja.frames.num_frames = has_flags ? (first_word & 0xFFFF) : first_word;
ja.frames.fixed_qwc = deref_u32(jacc, jacc_word_off++);
ja.frames.frame_qwc = deref_u32(jacc, jacc_word_off++);
// jak 2/3 may lzo compress the animation, check the flag bit
const bool lzo_compressed = has_flags && ((first_word >> 16) & 1) != 0;
// lg::info("{}: extracting anim {} (compressed {})", ag_data.name_in_dgo, ja.name,
// lzo_compressed);
Ref fixed_ptr = jacc;
fixed_ptr.byte_offset += jacc_word_off * 4;
Ref fixed_ref = deref_label(fixed_ptr);
if (lzo_compressed) {
size_t decompressed_size =
((size_t)ja.frames.fixed_qwc + (size_t)ja.frames.num_frames * ja.frames.frame_qwc) * 16;
auto compressed = get_plain_data_bytes_up_to_label(fixed_ref);
ASSERT(!compressed.empty());
std::vector<u8> decompressed(decompressed_size);
size_t out_size = 0;
auto lzo_result = lzokay::decompress(compressed.data(), compressed.size(),
decompressed.data(), decompressed.size(), out_size);
ASSERT(lzo_result == lzokay::EResult::Success ||
lzo_result == lzokay::EResult::InputNotConsumed);
// if (out_size != decompressed_size) {
// lg::warn("lzo decomp size mismatch for '{}' in '{}': got {} bytes, expected {}", ja.name,
// ag_data.name_in_dgo, out_size, decompressed_size);
// }
parse_fixed_from_buf(decompressed.data(), ja.frames.fixed, ja.frames.fixed_qwc);
size_t frame_base = (size_t)ja.frames.fixed_qwc * 16;
for (int i = 0; i < (int)ja.frames.num_frames; i++) {
auto& frame = ja.frames.frame.emplace_back();
parse_frame_from_buf(
decompressed.data() + frame_base + (size_t)i * ja.frames.frame_qwc * 16, frame,
ja.frames.frame_qwc);
}
} else {
int fixed_word_off = 0;
// fixed hdr
memcpy_from_plain_data((u8*)ja.frames.fixed.hdr.control_bits, fixed_ref, 4 * 14);
fixed_word_off += 14;
ja.frames.fixed.hdr.num_joints = deref_u32(fixed_ref, fixed_word_off++);
ja.frames.fixed.hdr.matrix_bits = deref_u32(fixed_ref, fixed_word_off++);
ja.frames.fixed.offset_64 = deref_u32(fixed_ref, fixed_word_off++);
ja.frames.fixed.offset_32 = deref_u32(fixed_ref, fixed_word_off++);
ja.frames.fixed.offset_16 = deref_u32(fixed_ref, fixed_word_off++);
ja.frames.fixed.reserved = deref_u32(fixed_ref, fixed_word_off++);
ja.frames.fixed.data64_size = ja.frames.fixed.offset_32 - ja.frames.fixed.offset_64;
ja.frames.fixed.data32_size = ja.frames.fixed.offset_16 - ja.frames.fixed.offset_32;
{
int data16 = (int)((ja.frames.fixed_qwc - 5) * 16) - (int)ja.frames.fixed.data64_size -
(int)ja.frames.fixed.data32_size;
ASSERT(data16 >= 0);
ja.frames.fixed.data16_size = (u16)data16;
}
// matrix flags
ja.frames.fixed.mat[0] = (ja.frames.fixed.hdr.matrix_bits & 1) == 0;
ja.frames.fixed.mat[1] = (ja.frames.fixed.hdr.matrix_bits & 2) == 0;
fixed_ref.byte_offset += fixed_word_off * 4;
int d64_bytes = (int)ja.frames.fixed.data64_size;
int d32_bytes = (int)ja.frames.fixed.data32_size;
int d16_bytes = (int)ja.frames.fixed.data16_size;
ja.frames.fixed.data64.resize((d64_bytes + 7) / 8);
if (d64_bytes > 0) {
Ref d64 = fixed_ref;
d64.byte_offset += ja.frames.fixed.offset_64;
memcpy_from_plain_data((u8*)ja.frames.fixed.data64.data(), d64, d64_bytes);
}
ja.frames.fixed.data32.resize((d32_bytes + 3) / 4);
if (d32_bytes > 0) {
Ref d32 = fixed_ref;
d32.byte_offset += ja.frames.fixed.offset_32;
memcpy_from_plain_data((u8*)ja.frames.fixed.data32.data(), d32, d32_bytes);
}
ja.frames.fixed.data16.resize((d16_bytes + 1) / 2);
if (d16_bytes > 0) {
Ref d16 = fixed_ref;
d16.byte_offset += ja.frames.fixed.offset_16;
memcpy_from_plain_data((u8*)ja.frames.fixed.data16.data(), d16, d16_bytes);
}
Ref frames_ref = jacc;
frames_ref.byte_offset += 16;
for (int i = 0; i < (int)ja.frames.num_frames; i++) {
Ref frame_ref = deref_label(frames_ref);
int frame_off = 0;
auto& frame = ja.frames.frame.emplace_back();
frame.offset_64 = deref_u32(frame_ref, frame_off++);
frame.offset_32 = deref_u32(frame_ref, frame_off++);
frame.offset_16 = deref_u32(frame_ref, frame_off++);
frame.reserved = deref_u32(frame_ref, frame_off++);
frame.data64_size = frame.offset_32 - frame.offset_64;
frame.data32_size = frame.offset_16 - frame.offset_32;
{
int data16 = (int)((ja.frames.frame_qwc - 1) * 16) - (int)frame.data64_size -
(int)frame.data32_size;
ASSERT(data16 >= 0);
frame.data16_size = (u16)data16;
}
Ref frame_data = frame_ref;
frame_data.byte_offset += frame_off * 4;
int fd64_bytes = (int)frame.data64_size;
int fd32_bytes = (int)frame.data32_size;
int fd16_bytes = (int)frame.data16_size;
frame.data64.resize((fd64_bytes + 7) / 8);
if (fd64_bytes > 0) {
Ref fd64 = frame_data;
fd64.byte_offset += frame.offset_64;
memcpy_from_plain_data((u8*)frame.data64.data(), fd64, fd64_bytes);
}
frame.data32.resize((fd32_bytes + 3) / 4);
if (fd32_bytes > 0) {
Ref fd32 = frame_data;
fd32.byte_offset += frame.offset_32;
memcpy_from_plain_data((u8*)frame.data32.data(), fd32, fd32_bytes);
}
frame.data16.resize((fd16_bytes + 1) / 2);
if (fd16_bytes > 0) {
Ref fd16 = frame_data;
fd16.byte_offset += frame.offset_16;
memcpy_from_plain_data((u8*)frame.data16.data(), fd16, fd16_bytes);
}
frames_ref.byte_offset += 4;
}
}
// some master art groups and model names do not match, this remaps the model name based on the
// animation name prefix for these rare exceptions
PerGameVersion<std::vector<std::string>> mdl_name_remap{
{},
{
"collectables-bomb-blast",
"collectables-health",
"collectables-gem",
"collectables-generic-blast",
"collectables-generic-ripples",
"collectables-skill",
},
{
"collectables-bomb-blast",
"collectables-health",
"collectables-gem",
"collectables-generic-blast",
"collectables-generic-ripples",
"collectables-skill",
"collectables-warp-time",
},
{},
};
auto lst = mdl_name_remap[version];
auto remap = std::ranges::find_if(lst.begin(), lst.end(), [&](const std::string& prefix) {
return ja.name.find(prefix) != std::string::npos;
});
if (remap != lst.end()) {
const auto& mdl_prefix = *remap;
out[mdl_prefix + "-lod0"].anims.push_back(ja);
// out[mdl_name + "-lod1"].anims.push_back(ja);
// out[mdl_name + "-lod2"].anims.push_back(ja);
} else {
out[master_art_name + "-lod0"].anims.push_back(ja);
// out[master_art_name + "-lod1"].anims.push_back(ja);
// out[master_art_name + "-lod2"].anims.push_back(ja);
}
}
}
} // namespace decompiler
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include "common/custom_data/Tfrag3Data.h"
#include "decompiler/ObjectFile/ObjectFileDB.h"
#include "decompiler/level_extractor/common_formats.h"
#include "goalc/build_actor/common/build_actor.h"
namespace decompiler {
void extract_animations(const ObjectFileData& ag_data,
const DecompilerTypeSystem& dts,
GameVersion version,
std::map<std::string, level_tools::ArtData>& out);
} // namespace decompiler
+35 -20
View File
@@ -3,6 +3,8 @@
#include <set>
#include <thread>
#include "extract_anim.h"
#include "common/log/log.h"
#include "common/util/FileUtil.h"
#include "common/util/SimpleThreadGroup.h"
@@ -59,18 +61,17 @@ bool is_valid_bsp(const decompiler::LinkedObjectFile& file) {
return true;
}
tfrag3::Texture make_texture(u32 id,
const TextureDB::TextureData& tex,
const std::string& tpage_name,
bool pool_load) {
tfrag3::Texture make_texture(u32 id, const TextureDB& tex_db, bool pool_load) {
const auto& tex = tex_db.textures.at(id);
auto resolved = tex_db.resolve_texture(id);
tfrag3::Texture new_tex;
new_tex.combo_id = id;
new_tex.w = tex.w;
new_tex.h = tex.h;
new_tex.debug_tpage_name = tpage_name;
new_tex.w = resolved.w;
new_tex.h = resolved.h;
new_tex.debug_tpage_name = tex_db.tpage_names.at(tex.page);
new_tex.debug_name = tex.name;
new_tex.data = tex.rgba_bytes;
new_tex.combo_id = id;
new_tex.data = std::move(resolved.rgba);
new_tex.load_to_pool = pool_load;
return new_tex;
}
@@ -78,12 +79,13 @@ tfrag3::Texture make_texture(u32 id,
void add_all_textures_from_level(tfrag3::Level& lev,
const std::string& level_name,
const TextureDB& tex_db) {
const auto& level_it = tex_db.texture_ids_per_level.find(level_name);
if (level_it != tex_db.texture_ids_per_level.end()) {
for (auto id : level_it->second) {
const auto& tex = tex_db.textures.at(id);
lev.textures.push_back(make_texture(id, tex, tex_db.tpage_names.at(tex.page), true));
}
auto level_it = tex_db.texture_ids_per_level.find(level_name);
if (level_it == tex_db.texture_ids_per_level.end()) {
return;
}
for (auto id : level_it->second) {
lev.textures.push_back(make_texture(id, tex_db, true));
}
}
@@ -129,6 +131,7 @@ void extract_art_groups_from_level(const ObjectFileDB& db,
extract_merc(ag_file, tex_db, db.dts, tex_remap, level_data, false, db.version(),
swapped_info);
extract_joint_group(ag_file, db.dts, db.version(), art_group_data);
extract_animations(ag_file, db.dts, db.version(), art_group_data);
}
}
}
@@ -310,8 +313,7 @@ void extract_common(const ObjectFileDB& db,
if (config.common_tpages.count(normal_texture.page) && !textures_we_have_id.count(id)) {
textures_we_have.insert(normal_texture.name);
textures_we_have_id.insert(id);
tfrag_level.textures.push_back(
make_texture(id, normal_texture, tex_db.tpage_names.at(normal_texture.page), true));
tfrag_level.textures.push_back(make_texture(id, tex_db, true));
}
}
@@ -320,13 +322,16 @@ void extract_common(const ObjectFileDB& db,
if (config.animated_textures.count(normal_texture.name) &&
!textures_we_have.count(normal_texture.name)) {
textures_we_have.insert(normal_texture.name);
tfrag_level.textures.push_back(
make_texture(id, normal_texture, tex_db.tpage_names.at(normal_texture.page), false));
tfrag_level.textures.push_back(make_texture(id, tex_db, false));
}
}
Serializer ser;
tfrag_level.serialize(ser);
if (!config.rip_levels) {
tfrag_level.textures.clear();
tfrag_level.textures.shrink_to_fit();
}
auto compressed =
compression::compress_zstd(ser.get_save_result().first, ser.get_save_result().second);
@@ -366,6 +371,10 @@ void extract_from_level(const ObjectFileDB& db,
Serializer ser;
level_data.serialize(ser);
if (!config.rip_levels) {
level_data.textures.clear();
level_data.textures.shrink_to_fit();
}
auto compressed =
compression::compress_zstd(ser.get_save_result().first, ser.get_save_result().second);
lg::info("stats for {}", level_data.level_name);
@@ -405,12 +414,18 @@ void extract_all_levels(const ObjectFileDB& db,
auto entities_dir = file_util::get_jak_project_dir() / "decompiler_out" /
game_version_names[config.game_version] / "entities";
file_util::create_dir_if_needed(entities_dir);
int num_workers = dgo_names.size();
if (tex_db.replace_texture_dir) {
num_workers = 1;
}
SimpleThreadGroup threads;
threads.run(
[&](int idx) {
extract_from_level(db, tex_db, dgo_names[idx], config, output_path, entities_dir);
},
dgo_names.size());
dgo_names.size(), num_workers);
threads.join();
}
+1 -4
View File
@@ -61,10 +61,7 @@ void extract_all_levels(const ObjectFileDB& db,
void add_all_textures_from_level(tfrag3::Level& lev,
const std::string& level_name,
const TextureDB& tex_db);
tfrag3::Texture make_texture(u32 id,
const TextureDB::TextureData& tex,
const std::string& tpage_name,
bool pool_load);
tfrag3::Texture make_texture(u32 id, const TextureDB& tex_db, bool pool_load);
std::vector<level_tools::TextureRemap> extract_tex_remap(const ObjectFileDB& db,
const std::string& dgo_name);
std::optional<ObjectFileRecord> get_bsp_file(const std::vector<ObjectFileRecord>& records,
+280
View File
@@ -1,5 +1,6 @@
#include "fr3_to_gltf.h"
#include <algorithm>
#include <unordered_map>
#include "common/custom_data/Tfrag3Data.h"
@@ -879,6 +880,276 @@ int make_inv_matrix_bind_poses(const std::vector<level_tools::Joint>& joints,
return accessor_idx;
}
level_tools::UncompressedJointAnim decompress_anim(const level_tools::ArtJointAnim& art_anim) {
constexpr float kQuatScale = 0.000030517578125f;
constexpr float kScaleScale = 0.000244140625f;
constexpr float kTransScale = 4.f / 4096.f;
auto read_f32 = [](const u8*& ptr) -> float {
float v;
memcpy(&v, ptr, 4);
ptr += 4;
return v;
};
auto read_s16 = [](const u8*& ptr) -> float {
s16 v;
memcpy(&v, ptr, 2);
ptr += 2;
return v;
};
const auto& ctrl = art_anim.frames;
const auto& fixed = ctrl.fixed;
const auto& hdr = fixed.hdr;
int num_joints = (int)hdr.num_joints;
int total_frames = (int)ctrl.num_frames;
level_tools::UncompressedJointAnim out;
out.name = art_anim.name;
out.framerate = art_anim.speed > 0.f ? art_anim.speed * 60.f : 30.f;
out.frames = total_frames;
out.joints.resize(2 + num_joints);
auto d64 = (const u8*)fixed.data64.data();
auto d32 = (const u8*)fixed.data32.data();
auto d16 = (const u8*)fixed.data16.data();
if (fixed.mat[0])
d64 += 64;
if (fixed.mat[1])
d64 += 64;
for (int tqi = 0; tqi < num_joints; tqi++) {
int ctrl_idx = tqi / 8;
int ctrl_shift = 4 * (tqi % 8);
int c = 0xf & (hdr.control_bits[ctrl_idx] >> ctrl_shift);
auto& joint = out.joints[2 + tqi];
if (!(c & 0b0001)) {
math::Vector3f t;
if (c & 0b1000) {
t.x() = read_f32(d64) / 4096.f;
t.y() = read_f32(d64) / 4096.f;
t.z() = read_f32(d32) / 4096.f;
} else {
t.x() = read_s16(d32) * kTransScale;
t.y() = read_s16(d32) * kTransScale;
t.z() = read_s16(d16) * kTransScale;
}
joint.trans_frames.push_back(t);
}
if (!(c & 0b0010)) {
math::Vector4f q;
q.x() = read_s16(d64) * kQuatScale;
q.y() = read_s16(d64) * kQuatScale;
q.z() = read_s16(d64) * kQuatScale;
q.w() = read_s16(d64) * kQuatScale;
joint.quat_frames.push_back(q);
}
if (!(c & 0b0100)) {
math::Vector3f s;
s.x() = read_s16(d32) * kScaleScale;
s.y() = read_s16(d32) * kScaleScale;
s.z() = read_s16(d16) * kScaleScale;
joint.scale_frames.push_back(s);
}
}
for (int fi = 0; fi < total_frames; fi++) {
const auto& frame = ctrl.frame[fi];
const u8* data64 = (const u8*)frame.data64.data();
const u8* data32 = (const u8*)frame.data32.data();
const u8* data16 = (const u8*)frame.data16.data();
if (!fixed.mat[0])
data64 += sizeof(math::Matrix4f);
if (!fixed.mat[1])
data64 += sizeof(math::Matrix4f);
for (int tqi = 0; tqi < num_joints; tqi++) {
int ctrl_idx = tqi / 8;
int ctrl_shift = 4 * (tqi % 8);
int c = 0xf & (hdr.control_bits[ctrl_idx] >> ctrl_shift);
auto& joint = out.joints[2 + tqi];
if (c & 0b0001) {
math::Vector3f t;
if (c & 0b1000) {
t.x() = read_f32(data64) / 4096.f;
t.y() = read_f32(data64) / 4096.f;
t.z() = read_f32(data32) / 4096.f;
} else {
t.x() = read_s16(data32) * kTransScale;
t.y() = read_s16(data32) * kTransScale;
t.z() = read_s16(data16) * kTransScale;
}
joint.trans_frames.push_back(t);
}
if (c & 0b0010) {
math::Vector4f q;
q.x() = read_s16(data64) * kQuatScale;
q.y() = read_s16(data64) * kQuatScale;
q.z() = read_s16(data64) * kQuatScale;
q.w() = read_s16(data64) * kQuatScale;
joint.quat_frames.push_back(q);
}
if (c & 0b0100) {
math::Vector3f s;
s.x() = read_s16(data32) * kScaleScale;
s.y() = read_s16(data32) * kScaleScale;
s.z() = read_s16(data16) * kScaleScale;
joint.scale_frames.push_back(s);
}
}
}
for (int ji = 2; ji < (int)out.joints.size(); ji++) {
auto& joint = out.joints[ji];
while ((int)joint.trans_frames.size() < total_frames) {
if (joint.trans_frames.empty())
joint.trans_frames.emplace_back(0.f, 0.f, 0.f);
else
joint.trans_frames.push_back(joint.trans_frames[0]);
}
while ((int)joint.quat_frames.size() < total_frames) {
if (joint.quat_frames.empty())
joint.quat_frames.emplace_back(0.f, 0.f, 0.f, 1.f);
else
joint.quat_frames.push_back(joint.quat_frames[0]);
}
while ((int)joint.scale_frames.size() < total_frames) {
if (joint.scale_frames.empty())
joint.scale_frames.emplace_back(1.f, 1.f, 1.f);
else
joint.scale_frames.push_back(joint.scale_frames[0]);
}
}
return out;
}
int make_anim_float_accessor(const std::vector<float>& values, tinygltf::Model& model) {
int buf_idx = (int)model.buffers.size();
auto& buf = model.buffers.emplace_back();
buf.data.resize(values.size() * sizeof(float));
memcpy(buf.data.data(), values.data(), buf.data.size());
int bv_idx = (int)model.bufferViews.size();
auto& bv = model.bufferViews.emplace_back();
bv.buffer = buf_idx;
bv.byteOffset = 0;
bv.byteLength = buf.data.size();
int acc_idx = (int)model.accessors.size();
auto& acc = model.accessors.emplace_back();
acc.bufferView = bv_idx;
acc.byteOffset = 0;
acc.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
acc.count = (int)values.size();
acc.type = TINYGLTF_TYPE_SCALAR;
if (!values.empty()) {
float mn = values[0], mx = values[0];
for (float v : values) {
mn = std::min(mn, v);
mx = std::max(mx, v);
}
acc.minValues = {(double)mn};
acc.maxValues = {(double)mx};
}
return acc_idx;
}
int make_anim_vec3_accessor(const std::vector<math::Vector3f>& values, tinygltf::Model& model) {
static_assert(sizeof(math::Vector3f) == 3 * sizeof(float));
int buf_idx = (int)model.buffers.size();
auto& buf = model.buffers.emplace_back();
buf.data.resize(values.size() * sizeof(math::Vector3f));
memcpy(buf.data.data(), values.data(), buf.data.size());
int bv_idx = (int)model.bufferViews.size();
auto& bv = model.bufferViews.emplace_back();
bv.buffer = buf_idx;
bv.byteOffset = 0;
bv.byteLength = buf.data.size();
int acc_idx = (int)model.accessors.size();
auto& acc = model.accessors.emplace_back();
acc.bufferView = bv_idx;
acc.byteOffset = 0;
acc.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
acc.count = (int)values.size();
acc.type = TINYGLTF_TYPE_VEC3;
return acc_idx;
}
int make_anim_vec4_accessor(const std::vector<math::Vector4f>& values, tinygltf::Model& model) {
static_assert(sizeof(math::Vector4f) == 4 * sizeof(float));
int buf_idx = (int)model.buffers.size();
auto& buf = model.buffers.emplace_back();
buf.data.resize(values.size() * sizeof(math::Vector4f));
memcpy(buf.data.data(), values.data(), buf.data.size());
int bv_idx = (int)model.bufferViews.size();
auto& bv = model.bufferViews.emplace_back();
bv.buffer = buf_idx;
bv.byteOffset = 0;
bv.byteLength = buf.data.size();
int acc_idx = (int)model.accessors.size();
auto& acc = model.accessors.emplace_back();
acc.bufferView = bv_idx;
acc.byteOffset = 0;
acc.componentType = TINYGLTF_COMPONENT_TYPE_FLOAT;
acc.count = (int)values.size();
acc.type = TINYGLTF_TYPE_VEC4;
return acc_idx;
}
void add_animation_to_gltf(const level_tools::UncompressedJointAnim& anim,
const tinygltf::Skin& skin,
tinygltf::Model& model) {
if (anim.frames == 0 || anim.joints.size() <= 2)
return;
auto& gltf_anim = model.animations.emplace_back();
gltf_anim.name = anim.name;
std::vector<float> times(anim.frames);
for (int i = 0; i < anim.frames; i++)
times[i] = i / anim.framerate;
int time_acc = make_anim_float_accessor(times, model);
int n_anim_joints = (int)anim.joints.size();
int n_skin_joints = (int)skin.joints.size();
for (int ji = 2; ji < n_anim_joints && ji < n_skin_joints; ji++) {
const auto& joint = anim.joints[ji];
int target_node = skin.joints[ji];
auto add_channel = [&](int val_acc, const std::string& path) {
int si = (int)gltf_anim.samplers.size();
auto& sampler = gltf_anim.samplers.emplace_back();
sampler.input = time_acc;
sampler.output = val_acc;
sampler.interpolation = "LINEAR";
auto& channel = gltf_anim.channels.emplace_back();
channel.sampler = si;
channel.target_node = target_node;
channel.target_path = path;
};
if ((int)joint.trans_frames.size() == anim.frames)
add_channel(make_anim_vec3_accessor(joint.trans_frames, model), "translation");
if ((int)joint.quat_frames.size() == anim.frames)
add_channel(make_anim_vec4_accessor(joint.quat_frames, model), "rotation");
if ((int)joint.scale_frames.size() == anim.frames)
add_channel(make_anim_vec3_accessor(joint.scale_frames, model), "scale");
}
}
void add_merc(const tfrag3::Level& level,
const std::map<std::string, level_tools::ArtData>& art_data,
const tfrag3::MercModel& mmodel,
@@ -956,6 +1227,15 @@ void add_merc(const tfrag3::Level& level,
skin.inverseBindMatrices = make_inv_matrix_bind_poses(game_bones, model);
}
if (art != art_data.end() && !art->second.anims.empty() && node.skin >= 0 &&
node.skin < model.skins.size()) {
const auto& skin = model.skins[node.skin];
for (const auto& ja : art->second.anims) {
auto uncompressed = decompress_anim(ja);
add_animation_to_gltf(uncompressed, skin, model);
}
}
for (size_t effect_idx = 0; effect_idx < mmodel.effects.size(); effect_idx++) {
const auto& effect = mmodel.effects[effect_idx];
for (size_t draw_idx = 0; draw_idx < effect.all_draws.size(); draw_idx++) {
+2 -1
View File
@@ -1070,7 +1070,8 @@ const std::unordered_map<
}},
{GameVersion::JakX,
{
// TODO
{"lightning-probe-vars",
{{"probe-dirs", ArrayFieldDecompMeta(TypeSpec("vector"), 16)}}},
}}};
goos::Object decompile_structure(const TypeSpec& type,
+1 -1
View File
@@ -16,5 +16,5 @@ constexpr PerGameVersion<int> SYMBOL_TO_STRING_MEM_OFFSET_DECOMP = {
8167 * 8, jak2::SYM_TO_STRING_OFFSET, -99999, -99999, // not supported this way!
};
constexpr PerGameVersion<int> OFFSET_OF_NEXT_STATE_STORE = {72, 64, 68, 68};
constexpr PerGameVersion<int> OFFSET_OF_NEXT_STATE_STORE = {72, 64, 68, 76};
} // namespace decompiler
+1
View File
@@ -59,6 +59,7 @@ set(RUNTIME_SOURCE
graphics/opengl_renderer/loader/Loader.cpp
graphics/opengl_renderer/loader/LoaderStages.cpp
graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp
graphics/opengl_renderer/ocean/OceanEnvmap.cpp
graphics/opengl_renderer/ocean/OceanMid_PS2.cpp
graphics/opengl_renderer/ocean/OceanMid.cpp
graphics/opengl_renderer/ocean/OceanMidAndFar.cpp
@@ -34,7 +34,7 @@
"USANDO AS ESTAÇÕES DE TRANSPORTE QUE OS PRECURSORES ESPALHARAM POR TODO O MUNDO.",
"IF YOU COME ACROSS ONE OF THESE PADS I CAN LOCK ON TO YOUR COMMUNICATOR'S LOCATION",
"AND SEND YOU THE ZOOMER!",
"KEEP AN EYE OUT FOR A TRANS-PAD WHEN YOU EXPLORE MISTY ISLAND, AND WHEREVER ELSE YOU GO!"
"KEEP AN EYE OUT FOR A TRANS-PAD WHEN YOU EXPLORE ILHA NEBULOSA, AND WHEREVER ELSE YOU GO!"
],
"assistant-lavatube-end-resolution": [
"EI! ONDE É QUE ANDA O PEQUENO, VERDE, E RUGOSO?",
@@ -81,7 +81,7 @@
],
"assistant-reminder-1-race-bike": [
"I'VE DEFINITELY FIGURED OUT HOW TO USE THE TRANS-PADS.",
"NOW GO TO MISTY ISLAND AND I'LL SEND THE ZOOMER OVER TO YOU."
"NOW GO TO ILHA NEBULOSA AND I'LL SEND THE ZOOMER OVER TO YOU."
],
"assistant-village2-introduction": [
"WHOA!",
@@ -373,7 +373,7 @@
"I'LL GIVE YOU A POWER CELL",
"IF YOU CAN CATCH 200 POUNDS OF THEM CRITTERS!",
"AND I'LL LET YOU AND SHRIMP HERE",
"USE MY SPEEDBOAT TO GET TO MISTY ISLAND.",
"USE MY SPEEDBOAT TO GET TO ILHA NEBULOSA.",
"YOU'S WANT TO TRY THE CHALLENGE?"
],
"fisher-reject": [
@@ -786,55 +786,55 @@
"HEI! UH, JAK? O VELHOTE VERDE DISSE-A-NOS PARA NÃO VIRMOS AQUI!"
],
"sage-intro-sequence-d1": [
"WHAT IN GREEN TARNATION DO YOU TWO WANT?",
"WE- WE- WE WAS- THEY WAS- I'M- I WAS-",
"DON'T TELL ME! INSTEAD OF HEEDING MY WISDOM",
"THE TWO OF YOU WENT MUCKING AROUND",
"IN THE ONLY PLACE THAT I TOLD YOU NOT TO GO: MISTY ISLAND!",
"THAT'S RIGHT! AND THEN-",
"AND, DAXTER, YOU FINALLY TOOK A MUCH-NEEDED BATH",
"BUT IN A BATHTUB FILLED WITH DARK ECO.",
"LOOK, OLD MAN, ARE YOU GONNA KEEP YAPPIN'",
"OR YOU GONNA HELP ME OUTTA THIS MESS!?",
"I'M GONNA KEEP YAPPIN'! BECAUSE IN MY PROFESSIONAL OPINION",
"THE CHANGE IS AN IMPROVEMENT.",
"AND BESIDES... I COULDN'T HELP YOU IF I WANTED TO.",
"WHAT!?",
"THERE'S ONLY ONE PERSON WHO HAS STUDIED DARK ECO LONG ENOUGH",
"TO HAVE A CHANCE AT RETURNING YOU TO YOUR PREVIOUS FORM:",
"GOL ACHERON, THE SAGE.",
"BUT HE LIVES FAR TO THE NORTH. FAR, FAR TO THE NORTH.",
"NOBODY HAS SPOKEN TO HIM IN AGES.",
"I WOULD TELEPORT YOU THERE, BUT I CAN'T DO THAT EITHER.",
"NONE OF THE THREE SAGES THAT MAINTAIN THE OTHER TELEPORTER GATES",
"HAVE SEEN FIT TO TURN THEIR ENDS ON FOR QUITE A WHILE!"
"MAS QUE DIABOS VOCÊS DOIS QUEREM??",
"NÓS- NÓS- NÓS ÉRAMOS- ELES ERAM- EU SOU- EU ERA -",
"NÃO ME DIGAS! EM VEZ DE DARES OUVIDOS À MINHA SABEDORIA",
"VOCÊS OS DOIS FORAM VAGUEAR POR AÍ",
"NO ÚNICO LUGAR ONDE EU VOS DISSE PARA NÃO IR: ILHA NEBULOSA!",
"É ISSO MESMO! E DEPOIS-",
"E, DAXTER, FINALMENTE TOMASTE UM BANHO QUE JÁ ESTAVAS A PRECISAR",
"MAS NUMA BANHEIRA CHEIA DE ECO NEGRO.",
"OLHA VELHOTE, VAIS CONTINUAR O SERMÃO",
"OU VAIS AJUDAR-ME A SAIR DESTA CONFUSÃO!?",
"VOU CONTINUAR A FALAR! PORQUE, PORQUE NA MINHA OPINIÃO PROFISSIONAL",
"A MUDANÇA É UMA MELHORIA.",
"E APESAR DISSO... MESMO QUE EU QUISESSE, NÃO PODERIA TE AJUDAR.",
"O QUÊ!?",
"SÓ EXISTE UMA PESSOA QUE TENHA ESTUDADO O ECO NEGRO POR TEMPO SUFICIENTE",
"PARA TER A OPORTUNIDADE DE TE TRAZER À TUA FORMA ORIGINAL:",
"GOL ACHERON, O SÁBIO.",
"MAS ELE VIVE PARA NORTE. NORTE, BEM LONGE DAQUI.",
"NINGUÉM FALA COM ELE HÁ ANOS",
"EU TELETRANSPORTAVA-TE PARA LÁ, MAS TAMBÉM NÃO CONSIGO FAZER ISSO.",
"NENHUM DOS TRÊS SÁBIOS QUE MANTÉM OS OUTROS PORTAIS DE TELETRANSPORTE",
"ACHOU POR BEM LIGÁ-LOS HÁ JÁ BASTANTE TEMPO!"
],
"sage-intro-sequence-d2": [
"THE ONLY OTHER WAY NORTH IS BY FOOT THROUGH THE FIRE CANYON",
"BUT ITS VOLCANIC SOIL IS HOT ENOUGH TO MELT PRECURSOR METAL.",
"YOU CAN'T JUST WALK THROUGH IT.",
"BUT YOU COULD FLY OVER IT",
"IF YOU HAD A ZOOMER EQUIPPED WITH A HEAT SHIELD.",
"I JUST HAPPEN TO BE WORKING ON SUCH A THING AT THIS VERY MOMENT.",
"ALL I WOULD NEED IS TWENTY POWER CELLS TO GIVE IT ENOUGH ENERGY",
"TO WITHSTAND THE CANYON'S HEAT. ISN'T THAT RIGHT, DADDY?",
"YES, KEIRA, THAT MIGHT WORK. BUT WHERE ARE A BOY",
"AND A HALF!",
"GOING TO GET TWENTY POWER CELLS?",
"FROM THE VILLAGERS! MOST OF THEM HAVE A POWER CELL OR TWO",
"STASHED AWAY SOMEWHERE.",
"AND EVEN IF THEY AREN'T WILLING TO JUST GIVE THEM AWAY",
"GREASING THEIR PALMS WITH A FEW PRECURSOR ORBS SHOULD DO THE TRICK.",
"AND I BET THERE ARE EVEN MORE OF THEM OUT IN THE WILDS JUST WAITING FOR SOME",
"BRAVE ADVENTURER TO FIND.",
"WELL WE'VE GOT THE BRAVE ADVENTURER, AT LEAST.",
"BRAVE ADVENTURER?",
"YOU TWO COULDN'T FIND YOUR WAY OUT OF THE VILLAGE WITHOUT TRAINING!",
"BEFORE YOU DO ANYTHING ELSE, YOU BETTER GO THROUGH THE WARP GATE AND GET",
"SOME PRACTICE ON GEYSER ROCK.",
"UH, WE WON'T FIND ANY MORE OF THAT DARK GOOEY ECO STUFF, WILL WE?",
"'CAUSE I'D HATE TO FALL IN AGAIN AND TURN INTO YOU!",
"GET IN THERE! BEFORE I TURN YOU BOTH INTO FERNS!"
"A ÚNICA OUTRA MANEIRA DE CHEGAR AO NORTE É A PÉ, ATRAVÉS DO DESFILADEIRO DO FOGO",
"MAS O SEU SOLO VULCÂNICO É SUFICIENTEMENTE QUENTE PARA DERRETER O METAL PRECURSOR.",
"NÃO PODES SIMPLESMENTE ATRAVESSÁ-LO A PÉ.",
"MAS PODEM PASSAR POR CIMA A VOAR.",
"SE TIVESSEM UM ZOOMER EQUIPADO COM UM PROTECTOR TÉRMICO.",
"POR COINCIDÊNCIA, ESTOU A TRABALHAR NUM NESTE PRECISO MOMENTO.",
"TUDO O QUE PRECISO SÃO VINTE CÈLULAS DE ENERGIA PARA TER CARGA SUFICIENTE",
"PARA AGUENTAR O CALOR DO DESFILADEIRO. NÃO É VERDADE, PAPÁ?",
"SIM, KEIRA, ISSO PODE FUNCIONAR. MAS COM UM RAPAZ?",
"E MEIO!",
"VÃO ARRANJAR VINTE CÉLULAS DE ENERGIA?",
"DOS MORADORES DA ALDEIA! A MAIORIA DELES TEM UMA OU DUAS BATERIAS",
"GUARDADAS EM ALGUM LUGAR.",
"E MESMO QUE NÃO ESTEJAM DISPOSTOS A SIMPLESMENTE OFERECÊ-LAS",
"DAR-LHES ALGUMAS ESFERAS PRECURSORAS DEVE AJUDAR A CONVENCÊ-LOS.",
"E APOSTO QUE DEVEM HAVER ALGUMAS POR AÍ ESPALHADAS HÁ ESPERA QUE ALGUM",
"AVENTUREIRO CORAJOSO AS ENCONTRE.",
"BEM, PELO MENOS TEMOS O AVENTUREIRO CORAJOSO.",
"AVENTUREIRO CORAJOSO?",
"SEM TREINO VOCÊS DOIS NEM CONSEGUIAM SAIR DA ALDEIA",
"ANTES DE FAZEREM QUALQUER COISA, É MELHOR ATRAVESSAREM O PORTAL E IREM",
"PRATICAR NA ROCHA DO GEYSER.",
"HUM, NÃO VAMOS ENCONTRAR MAIS DAQUELA PORCARIA ECO NEGRA E PEGAJOSA, POIS NÃO?",
"PORQUE EU IA ODIAR CAIR NAQUELA LAMA DE NOVO E FICAR COMO TU!",
"ENTREM AÍ! ANTES QUE EU VOS TRANSFORME OS DOIS EM FETOS!"
],
"sage-intro-sequence-e": [
"GOOD TRAINING, BOYS, BUT THAT'S NOTHING COMPARED TO THE CHALLENGES THAT LIE AHEAD.",
@@ -852,12 +852,12 @@
"sage-introduction-misty-cannon": [
"OH, IT'S THE CONQUERING HEROES.",
"GOOD, I WANTED TO TALK WITH YOU TWO ABOUT SOMETHING SERIOUS.",
"THERE APPEARS TO BE QUITE A BIT OF LURKER ACTIVITY ON MISTY ISLAND.",
"THERE APPEARS TO BE QUITE A BIT OF LURKER ACTIVITY ON ILHA NEBULOSA.",
"I CAN SEE THEM BOMBARDING THE PRECURSOR SILO FROM MY LOOKOUT TOWER.",
"IF THE LURKERS OPEN IT UP AND RELEASE THE DARK ECO, WE COULD ALL END UP",
"RUNNING AROUND LOOKING AS RIDICULOUS AS THIS ANNOYING LITTLE SPECIMEN.",
"JAK, IT'S TIME FOR YOU TO PROVE YOUR WORTH.",
"GET THE FISHERMAN TO LET YOU TAKE HIS BOAT BACK TO MISTY ISLAND",
"GET THE FISHERMAN TO LET YOU TAKE HIS BOAT BACK TO ILHA NEBULOSA",
"GET TO THE TOP OF THE PRECURSOR SILO AND TAKE OUT THAT CANNON.",
"AND... WHAT ABOUT ME?",
"YOU? WHY DON'T YOU MOP MY FLOORS? THEY SEEM TO HAVE LOST THEIR SHINE LATELY."
@@ -876,7 +876,7 @@
"sage-reminder-1-misty-cannon": [
"THE BOMBARDMENT IS GETTING WORSE!",
"FIND THE FISHERMAN IN THE JUNGLE, GET PERMISSION TO USE HIS BOAT",
"AND GET OVER TO MISTY ISLAND TO STOP THE CANNON.",
"AND GET OVER TO ILHA NEBULOSA TO STOP THE CANNON.",
"AND YOU DAXTER, YOU NEED TO GET MOPPING. THIS PLACE IS A MESS!"
],
"sage-reminder-2-generic": [
@@ -967,10 +967,10 @@
"AS A MATTER OF FACT, WITHOUT MY MUSE, I JUST CAN'T SCULPT.",
"BUT WITH HER AROUND... I SEE BEAUTY IN EVERYTHING, YOU KNOW?",
"RIGHT NOW I COULDN'T CHISEL MY WAY OUT OF A BOX.",
"I THINK SHE RAN AWAY TO THAT MISTY ISLAND.",
"I THINK SHE RAN AWAY TO THAT ILHA NEBULOSA.",
"AWW, I JUST HOPE SHE'S ALL RIGHT.",
"IT'S WORTH A POWER CELL IF YOU BRING HER BACK TO ME!",
"WAIT A MINUTE! WE ARE NOT GOING BACK TO MISTY ISLAND!",
"WAIT A MINUTE! WE ARE NOT GOING BACK TO ILHA NEBULOSA!",
"ARE WE?"
],
"sculptor-reminder-1": [
@@ -981,25 +981,25 @@
"HERE, TAKE THIS POWER CELL. I WON'T NEED IT NOW THAT I HAVE MY INSPIRATION BACK!"
],
"sidekick-human-intro-sequence-b": [
"CONTINUE YOUR SEARCH FOR ARTIFACTS AND ECO.",
"IF THE LOCALS POSSESS PRECURSOR ITEMS, YOU KNOW WHAT TO DO.",
"DEAL HARSHLY WITH ANYBODY WHO STRAYS FROM THE VILLAGE.",
"WE WILL ATTACK IT IN DUE TIME."
"CONTINUEM A VOSSA PESQUISA POR ARTEFACTOS E ECO.",
"SE OS ALDEÔES POSSUIREM ITENS PRECURSORES, VOCÊS SABEM O QUE FAZER.",
"LIDEM COM DUREZA QUALQUER UM QUE SE AFASTAR DA ALDEIA.",
"IREMOS ATACAR NA HORA CERTA."
],
"sidekick-human-intro-sequence-c": [
"WHAT ARE WE DOING HERE ANYWAY, JAK? THIS PLACE GIVES ME THE CREEPS!",
"HUH?",
"(GROAN) STUPID PRECURSOR JUNK!",
"EEK! WHAT IS THAT DARK OOZE? IT SURE DON'T LOOK FRIENDLY.",
"O QUE É QUE ESTAMOS AQUI A FAZER, JAK? ESTE SÍTIO DA-ME ARREPIOS!",
"HÃ?",
"(SUSPIRO) LIXO ESTÚPIDO DE PRECURSORES!",
"NHEC! O QUE É ESTA GOSMA ESCURA? NÃO PARECE NADA AMIGAVÉL.",
"O SÁBIO FALA O TEMPO TODO SOBRE OS PRECURSORES QUE CONSTRUÍRAM ESTE LUGAR.",
"\"WHERE DID THEY GO? WHY DID THEY BUILD THIS CRAP?\"",
"NOW I LIKE PRECURSOR ORBS AND POWER CELLS AS MUCH AS THE NEXT GUY",
"BUT IF YOU ASK ME, THEY MUST HAVE BEEN REAL LOSERS.",
"WHOA! HOW DID YOU DO THAT?",
"\"ONDE É QUE ELES FORAM? PORQUE É QUE CONSTRUIRAM ESTA PORCARIA?\"",
"EU GOSTA DE ORBS PRECURSORAS E CÉLULAS DE ENERGIA TANTO COMO QUALQUER OUTRA PESSOA",
"MAS SE QUERES A MINHA OPINIÃO, DEVEM TER SIDO UM BANDO DE FALHADOS",
"UAU! COMO É QUE FIZESTE ISSO?",
"JAK, EU ACHO QUE ESTAMOS EM SARILHOS!",
"MAN, THAT STUNG.",
"I TOLD YOU WE SHOULDN'T HAVE COME HERE, AND YOU LISTENED?",
"O QUÊ?",
"CARAMBA, ISSO DOEU.",
"EU DISSE-TE QUE NÃO DEVIAMOS TER VINDO PARA CÁ, E TU OUVISTE-ME?",
"O QUE FOI?",
"WAAAAAAAAHHHHHHHH!!",
"OKAY, OKAY. ESTOU BEM, ESTOU BEM...",
"WAAAAAAAAHHHHHHHH!!"
@@ -2077,7 +2077,7 @@
],
"sksp0011": [
"WE SHOULD ASK THE FISHERMAN DOWN BY THE JUNGLE RIVER",
"IF WE CAN BORROW HIS SPEEDBOAT TO ZOOM ON OVER TO MISTY ISLAND!"
"IF WE CAN BORROW HIS SPEEDBOAT TO ZOOM ON OVER TO ILHA NEBULOSA!"
],
"sksp0013": [
"DID YOU SEE THE SIZE OF THE BITE",
@@ -44,7 +44,7 @@
"Sig näyttää teille alkeet.",
"Te nuorukaiset siis tahdotte aavikkolaisiksi?",
"No, katsotaan mihin te pystytte, kun pääsemme toiminnan keskelle.",
"Krew haluaa uusia saaliita houkuttamaan lisää asiakkaita,",
"Krew tahtoo uusia saaliita houkuttamaan asiakkaita,",
"joten aion napata viisi törkeää metallipäätä pumppaamolla.",
"Älä suotta tutise, chilipippuri, koska rokkaamme Rauhantekijällä!",
"Vauh, minulle kelpaisi tuollainen! Mistä sait sen?",
@@ -57,7 +57,7 @@
"atoll-3-intro": [
"Eräs vanha vartiotoverini lähetettiin pumppaamolle.",
"Partiosta ei ole kuulunut takaisin, ja koska mihin te siellä törmäsitte,",
"pelkään, että nainen on avun tarpeessa.",
"pelkään että nainen on avun tarpeessa.",
"Sanoitko \"nainen\"?",
"Älä edes kuvittelekaan!",
"LOPETA! Tämä on vakavaa, senkin ääliö!",
@@ -199,7 +199,7 @@
"Pölhö! Etkö tajua?! Se on ohi, Jak!",
"Kaikki sankarit kuolivat aikoja sitten! On vain selviytyminen...",
"keinolla millä hyvänsä!",
"Kaupunki on minun! Nämä elämät ovat minun! Tämä sota on minun!",
"Kaupunki on minun! Nämä henget ovat minun! Tämä sota on minun!",
"Ja sodassa... ihmisiä kuolee! Tappakaa hänet!",
"Varokaa!",
"Voitto on minun, Jak!",
@@ -209,7 +209,7 @@
"city-class-2-race-intro": [
"Kappas, törmäämme jälleen, ecohirviö.",
"Missä Keira on?",
"Älä huoli, pidän häntä silmilläni.",
"Älä huoli, pidän häntä silmälläni.",
"Olet kaupungin puheenaihe, Jak!",
"Annat kansalle toivoa... Miten säälittävää.",
"Olisin nauttinut sinun tappamisesta vankilassa,",
@@ -250,7 +250,7 @@
"Epäilitkö taitojani? Olen Jakin apukuskina kaiken aikaa!",
"Hei, milloin saan voittajan suukon?",
"Ehkä myöhemmin... jos olet hyvä poika.",
"Heippa. Näytimme niille kakkosluokan häviäjille paikkansa.",
"Moikka. Näytimme niille kakkosluokan häviäjille paikkansa.",
"Minä näin.",
"Driftasit vähän korkealle parissa mutkassa, mutta pysyit pystyssä!",
"Olen ylpeä sinusta, Dax.",
@@ -307,7 +307,7 @@
"Kaikkihan hänet tuntevat.",
"Ja Keira on...",
"Ystävä. Erittäin hyvä ystävä.",
"Kiitos avustasi tankkerin kanssa, Jak. Säästit paljon henkiä.",
"Kiitos avustasi tankkerin kanssa, Jak. Pelastit paljon henkiä.",
"En ole kuin isäni.",
"Pikkutytöstä asti olen katsellut kaduille sieltä typerästä tornista",
"ja kuvitellut parempaa paikkaa.",
@@ -370,7 +370,7 @@
"Sanoisin, että tulet häviämään paljon rahaa.",
"Koska minä aion kilpailla ja aion myös voittaa!",
"Aagghh! Sinä senkin...",
"Sinusta alkaa tulla enemmän hankaluuksia kuin hyötyä!",
"Sinusta alkaa olla enemmän hankaluuksia kuin hyötyä!",
"Sinuna en ottaisi liian rennosi. Jokainen on uhrattavissa!",
"Onko kiire kuolemaan?!",
"Meidän ei tarvitse odottaa suurkisaan asti!",
@@ -460,7 +460,7 @@
"Auttakaa minua nitistämään metallipäät!"
],
"city-intercept-tanker-res": [
"Saimme ne kaikki!",
"Se oli siinä!",
"Metallipäät tulevat päivä päivältä röyhkeämmiksi.",
"Ihan kuin ne koettelisivat puolustuksiamme hyökkäyksillään.",
"Minulla on paha tunne tästä.",
@@ -498,8 +498,8 @@
"Olen kiireinen juuri nyt.",
"Te taidatte olla Krewin uudet juoksupojat.",
"Kuule, en tahdo olla töykeä, saavuitte kyllä nopeasti,",
"mutta en ole kiinnostunut uusista ajajista juuri nyt,",
"ja minulla on tekemistä...",
"mutta en ole kiinnostunut uusista ajajista juuri nyt.",
"Ja minulla on tekemistä...",
"Voimmeko auttaa mitenkään?",
"Ette! Työstän salaista... \"ajoneuvoprojektia\".",
"Okei, pahoittelut...",
@@ -510,7 +510,7 @@
"city-keira-hover-challenge-res": [
"Voitimme stadionhaasteen.",
"Kiva. Teillä riittää tuuria.",
"Eikö teillä ole ketään hakattavana tai jolta kerätä rahaa, tai jotain?",
"Eikö teidän pitäisi olla kiristämässä tai hakkaamassa jotakuta?",
"Et taida pitää meistä?",
"Teette hommia sille limapallo Krewille. Miksi en pitäisi?",
"Olet näköjään voittanut muutaman kisan.",
@@ -537,19 +537,19 @@
"Voi pojat, kelluuko tuossa oikeaa kultaa?",
"Entäs tämä violetti litku?...",
"Glug, glug, glug... HUH!",
"Jak. Joudutte rottasi kanssa hoitaa noutoja puolestani.",
"Jak. Saisitte rottasi kanssa hoitaa noutoja puolestani.",
"Hellurei, leukaläjä... Mitäs rikoksille kuuluu?",
"Mikäs häntä vaivaa?",
"Mikä häntä vaivaa?",
"Ei mikään... olen ihan kunnossa...",
"huolehdi omista asioistasi...",
"Minusta joskus tuntuu niin kovin...",
"\"Minusta joskus tuntuu niin kovin...\"",
"Kuuntele, minulla on kuusi \"asiakasta\" ympäri kaupunkia,",
"jotka aikovat tehdä rahapudotuksia minulle.",
"Sinun täytyy noutaa jokainen rahapussi mahdollisimman nopeasti",
"ja \"hoidella\" jokainen utelias vartija nuuskimasta.",
"Jos saavut rahapussille liian myöhään,",
"joku jalankulkija voi napata sen.",
"...OLO ON KUIVAA!...",
"\"...OLO ON KUIVAA!...\"",
"Tiedätkö mikä ongelmasi on, Krew? Sinulta puuttuu visio...",
"Tämä paikka voisi olla oikea huippu mesta...",
"Tarvitsemme lisää tanssia, lisää hauskaa, lisää naisia!",
@@ -561,7 +561,7 @@
"Mmm, rahankerääjäni palasivat.",
"Tässä on asepäivitys.",
"Nyt poistukaa! Tarvitsen kauneusuneni.",
"Usko pois, veliseni. Päivässä ei tunnit riitä."
"Usko pois, siihen ei päivässä tunnit riitä."
],
"city-krew-delivery-intro": [
"\"Räjäytyskaksikko\" on palannut!",
@@ -585,18 +585,18 @@
],
"city-meet-brutter-intro": [
"Paroni lähetti kätyrinsä kiusamaan minua tuttuun tapaansa!",
"Terveysrikkomuksia! Jälkiveroja!",
"Terveysrikkomuksia! Jäännösveroja!",
"Kaikki haluavat minusta palasen. Oi voi...",
"Sinun onneksesi palasia kyllä riittää!",
"Lastin tuhoaminen satamalla oli tärkeämpää kuin tiedättekään.",
"Minulla on uusi projekti meneillään,",
"enkä tahdo kenenkään nuuskivan toimituksiani.",
"Sanotaanpa, että jos kaikki sujuu suunnitellusti,",
"Sanotaanpa että jos kaikki sujuu suunnitellusti,",
"tulen kuormittamaan markkinat metallipää-saaliilla. Hahaha...",
"Kuitenkin, minulla on uusi tehtävä teille.",
"Eräs virkaveljeni, Brutter, toimii kanssani pakkotyökaupassa.",
"Tarkoitat kai orjakauppaa?",
"Sanoisin \"vapaudesta vapautettu\".",
"Sanoisin mieluummin \"vapaudesta vapautettu\".",
"Vaanijat ovat kaupungin alemman luokan työvoimaa.",
"Brutter maksaa minulle mainiosti avustani vapauttaa vaanijoita",
"ja saada ne turvallisesti ulos kaupungista.",
@@ -629,7 +629,7 @@
"Palkkiona myönnän sinulle pimeän voiman."
],
"city-oracle-level-1": [
"Metallipäät ovat pelänneet sinua ainiaan, vihaisa.",
"Metallipäät ovat pelänneet sinua ainiaan.",
"Jo nyt metallipäiden johtaja tietää sinun voivan tuhota hänet",
"ja pelastaa rotumme viimeisen mahdollisuuden.",
"Sinulla on nyt hallinnassasi toinen pimeä voima!"
@@ -689,12 +689,12 @@
"Ne puree ja satuttaa kylää pahalaatuisesti",
"ja vaanijaveljet ovat ansassa kuin eläimet!",
"Haloo? Ne ovat eläimiä.",
"Emme enää pahoja, vaanivia ja luuttomia.",
"Emme ole enää pahoja, vaanivia ja luuttomia.",
"Me hyviä nyt. Metallipäiset on pahoja. Ne on vihollisia.",
"Taidamme kaikki seilata samassa paatissa.",
"Ja paatti uppoaa alta aikayksikön!",
"Pyydän, pelastakaa kuusi vaanijaveljeä äkkiä,",
"ja Brutter suukottaa teidän jalkoja!"
"niin Brutter suukottaa teidän jalkoja!"
],
"city-shuttle-underground-intro": [
"Kaupungissa on hälytystila.",
@@ -819,7 +819,7 @@
"Silti, jokaisella sisunsa arvoisella johtajalla",
"on aina varasuunnitelma...",
"Muista, ensimmäinen sääntö pommin rakentamisessa...",
"on aina rakentaa kaksi!",
"on aina rakentaa kaksi...",
"Ääh, okei! Menen sisään!",
"No onpas täällä sotkuista! Käämejä ja katkaisimia sikin sokin!",
"Pitäisikö irrottaa sininen johto?",
@@ -880,10 +880,10 @@
"avataksesi Marin portin kanjonille."
],
"dig-find-totem-res": [
"Hoidan! Hetkonen...",
"Minä hoidan! Hetkinen...",
"Ehkä tällä kertaa sinä voisit noutaa jutun!",
"Näyttääpä siellä hurjalta! Älähän satuta itseäsi, Jak!",
"Se on kirous, ei vain?"
"Hurjalta näyttää! Älä satuta itseäsi, Jak!",
"Taidan olla kirottu, enkö?"
],
"dig-knock-down-scaffolding-intro": [
"Samos pyysi meidät tuomaan lapsen luoksesi.",
@@ -897,7 +897,7 @@
"Mahtavia otuksia.",
"Me näimme ison tulevan repeämäportista kerran.",
"Hän oli ruma kuin mikä!",
"Hmmmphh... Minulla on arvokasta tietoa teille.",
"Hmph... Minulla on arvokasta tietoa teille.",
"Paroni suorittaa kaivausta kaivannolla.",
"Hän edelleen etsii sitä naurettavaa hautaa.",
"Rehellisesti, en usko sen olevan olemassa,",
@@ -913,14 +913,14 @@
"Torn on pettänyt meidät!",
"Torn tarkoitti hyvää. Hän vain suojeli yhtä joukostamme.",
"Meidän täytyy saada se kivi takaisin!",
"Se on työn alla!",
"Se on työn alla.",
"Niin, se on työmme alla!",
"Olen aliarvioinut paronin,",
"ja nyt hän on myös kaapannut pojan!",
"ja nyt hän on myös kaapannut pojan.",
"Mieti. Mikä voisi olla paronin seuraava siirto?",
"No, jos Edeltäjäkivi olisi minulla kaikessa voimassaan,",
"rakentaisin sillä valtavan palatsin.",
"Palatsin, jossa on suurin joukkio naisia, mitä on ikinä nähty.",
"Palatsin, jossa on suurin joukko naisia mitä on ikinä nähty.",
"Ja siellä olisi uima-allas täytetty reunoja myöten suklaalla...",
"hieman minttuista...",
"Joo, joo, valtava allas täynnä tahmeaa suklaata!",
@@ -1006,7 +1006,7 @@
"Miksi se paikka raunioilla on niin tärkeä teille?",
"Vanhassa talossa sijaitsee voimakas energialähde.",
"Se vetää metallipäitä puoleensa.",
"Ihan totta? Tunsimme henkilön, joka asui siellä!",
"Ihan totta? Tunsimme henkilön, joka asui siellä.",
"Te siis olette ne tulokkaat, jotka toistuvasti joutuvat pulaan.",
"Voi ei, et sinä!",
"Tervetuloa vaatimattomaan vastarintaliikkeeseemme.",
@@ -1052,8 +1052,8 @@
"Melkoinen tarina.",
"Taidatkin olla tarvitsemani \"eläin\" yhteen vaaralliseen tehtävään.",
"Taistelumetallipäitä on havaittu ympäri Havenin metsää!",
"Näillä mokomilla on naamiopinta, joten niitä on vaikea nähdä,",
"mutta etköhän sinä pärjää \"tappajavaistollasi\".",
"Näillä mokomilla on naamiopinta, joten niitä on vaikea nähdä.",
"Mutta etköhän sinä pärjää \"tappajavaistollasi\".",
"Käy metsässä ja pistä ne nippuun!"
],
"forest-protect-samos-intro-a": [
@@ -1098,7 +1098,7 @@
"Paroni suunnittelee tuhota Edeltäjäkiven!",
"Hän aikoo särkeä sen auki jotenkin!",
"Jos hän onnistuu, siitä vapautuva energia on yli ymmärryksen!",
"Se tuhoaisi maailman ja myös... kaiken elämän!",
"Se tuhoaisi maailman ja kaiken elämän mukanaan!",
"Kasvit anovat suojelua! Sinun täytyy pysäyttää paroni, Jak!",
"Pysäytä hänet, keinolla millä hyvänsä!"
],
@@ -1115,7 +1115,7 @@
"ja teidän täytyy räjäyttää kaikki ammukset sen sisältä.",
"Kaiken kun saatte, niin me aiheutamme suuriskun paronille.",
"Mehän tässä ne työt teemme.",
"ME aiheutamme suuriskun!",
"ME sen suuriskun aiheutamme!",
"Sopii. Haluan paronin tietävän, että MINÄ satutan häntä."
],
"fortress-blow-up-ammo-res-a": [
@@ -1149,12 +1149,12 @@
],
"fortress-save-friends-res": [
"Mitä kuuluu, beibi?",
"Metallipää-mäiskijä on pelastaa päivän!",
"Niin ja annoin Jakin tulla mukaani myös!",
"Metallipää-mäiskijä pelastaa päivän!",
"Annoin myös Jakin tulla mukaani.",
"Oih, pikku sankarini!",
"Samos, oletko kunnossa?",
"Mikä sinulla oikein kesti?!",
"Sain halkooni kuusi ikärengasta odotellessani teidän apuanne!",
"Sain halkooni kuusi ikärengasta teitä odotellessani!",
"Hyvät hyssykät! Mitä sinulle on tapahtunut, Jak?",
"Hetkonen! Se olet sinä! Siis se toinen sinä!",
"Tai siis... no tiedätte kyllä.",
@@ -1168,8 +1168,8 @@
"Ai, joku luulee itäneensä.",
"Jos sinulla olisi edes puolet viisaudestani,",
"ymmärtäisit, että tärkein tehtävämme on löytää lapsi!",
"Kuules, senkin kurttuinen käpy,",
"minä päätän asiasta ja sanon, että sotkemme paronin varoja.",
"Kuules, senkin kurttuinen käpy, minä päätän asiasta",
"ja sanon että käymme paronin voimavarojen kimppuun.",
"Pitääkö teidät kaksi erottaa?",
"Vin aktivoi portaalin! Nyt on aika lähteä!"
],
@@ -1326,7 +1326,7 @@
"Hmm, tuoksahtaa hieman...",
"palaneelta saulumilta?",
"Aaaaahhhh!!!",
"Äää, huh, hah, poppaa, poppaa, kuumaa, polttaa, huhhahhaa...",
"Äää, huh, hah, poppaa, kuumaa, polttaa, huhhahhaa...",
"Ahhhhh..."
],
"mountain-shard-res": [
@@ -1346,7 +1346,7 @@
"HA HA HAA! Maista tätä!",
"Tuo jos mikä herätti ne.",
"Mennään hoitamaan homma.",
"Mitä? Siis mennään tuonne? Tulen perässäsi..."
"Mitä? Siis mennään tuonne? Tulen heti perässäsi..."
],
"nest-kor-boss-fight-intro-b": [
"Viimein, päätitte liittyä seuraamme.",
@@ -1355,7 +1355,7 @@
"Ei tällä kertaa!",
"Ah, mutta lapsi on niin suuri osa tätä. Suuri osa sinua.",
"Etkö tunnista häntä? Poika on sinä, Jak!",
"Ja tämä paikka... täällä sinä sait alkusi, tulevaisuudessa!",
"Ja tämä paikka... täällä sinä sait alkusi. Tulevaisuudessa!",
"Mutta miten...",
"Sinut piilotettiin menneisyyteen sen toivossa,",
"että keräisit taitosi kohdataksesi minut nyt.",
@@ -1400,7 +1400,7 @@
"Tiesin sen.",
"Olet kunnossa?!",
"Ettehän te kirsikat luulleet,",
"että joku iso haiseva lisko estäisi minut kaupungin suurjuhlasta?",
"että joku iso haiseva lisko estäisi minut kaupungin suurjuhlista?",
"Tiesin, että olet liian kova pala purtavaksi!"
],
"outro-nest": [
@@ -1449,7 +1449,7 @@
"Voit aloittaa kaupungin korjaamisen huomenna.",
"Tänä iltana juhlimme uusien ystäviemme kanssa.",
"Sitä paitsi, tahdon niin nähdä sinun tanssivan.",
"Ei onnistu."
"Epätodennäköistä."
],
"outro-port": [
"Pelastit kaupungin ja kaiken muunkin, poikani!",
@@ -1479,7 +1479,7 @@
"Ei, vaan sinä kerrot... TASAN NYT! AAHH!",
"AAHH! Sinä senkin... UUH! AUH!",
"Hei! Tuo on likaista tappelua!",
"Jak, poikani. Tulevaisuus odottaa!"
"Jak, poikani, tulevaisuus odottaa!"
],
"palace-boss-res": [
"Antamani pimeät voimat eivät suojele sinua ikuisesti!",
@@ -1513,11 +1513,11 @@
"olisimme teljenneet hänet jo aikoja sitten!",
"Kuten haluatte.",
"Tarpeeksi kun suostuttelen, niin olen varma, että vakoojamme...",
"Mikä tuo oli?!"
"Mikä se oli?!"
],
"palace-outside-window-res-b": [
"Seinissämme siis piileksii rotta!",
"Rotta ja hänen toverinsa, näemmä.",
"Rotta ja hänen toverinsa näemmä.",
"Tuliko ikävä pimeän econ kokeitamme?",
"No, saanen päästää teidät molemmat kärsimyksestä!"
],
@@ -1604,7 +1604,7 @@
"Kuulemma haaveilet liittyä taisteluun kaupungin puolesta.",
"Väärän puolen valitseminen voi koitua... epäterveelliseksi.",
"Haluamme tavata Varjon.",
"Ha ha ha. Ei onnistu.",
"Ha ha ha. Epätodennäköistä.",
"Jos tahdotte liittyä johonkin, sirkus voi ottaa teidät vastaan.",
"Ellei teiltä löydy sisua todella hankalaan tehtävään.",
"Varastakaa paronin lippu raunioituneen tornin huipulta",
@@ -1629,7 +1629,7 @@
"ja annan sinulle maukkaan asepäivityksen, jos onnistut.",
"Annas kun arvaan... Likaista, sameaa vettä?",
"Haisee pahemmalta kuin hönkäsi osterifestareilla?",
"Täydempänä metallipäitä kuin lautasesi kertabuffetissa?",
"Täynnempänä metallipäitä kuin lautasesi buffetissa?",
"Ja tietenkin, tappavempia aseita kuin tiukat vaippasi kesäpäivänä?",
"Kuules donitsinreikä, miksemme me leijuisi ympäriinsä laiskotellen",
"ja sinä käyt hoitamassa putkityöt?",
@@ -1724,7 +1724,7 @@
],
"sewer-drain-res": [
"Huh... Koppi! Missä olisitkaan ilman minua, Dax?",
"No, luultavasti en olisi puoli metriä pitkä, karvainen,",
"No, luultavasti en olisi puoli metriä pitkä, karvainen",
"ja hörhöilemässä viemäreissä ilman housuja...",
"Kaipaan housuja."
],
@@ -1763,7 +1763,7 @@
"Tämä on vääryys! Edeltäjäkivi ei ollut sinua varten!"
],
"tomb-boss-res": [
"Hyvä yritys, mutta kivi yhä minun!",
"Hyvä yritys, mutta kivi yhä minulla!",
"Älä huoli... aion käyttää sitä sen täydellä potentiaalilla.",
"Pian kaikki vastustajani tuhoutuvat sen voimasta!"
],
@@ -1776,8 +1776,7 @@
"Miehuuden testit ovat taatusti täynnä vaaroja",
"ja Marin perillisen tulee kohdata ne yksin.",
"Kyllä se siitä. Sinä pystyt siihen!",
"Se on vain syvä, sysipimeä,",
"\"ääriään-myöten-täynnä-tuskallista-kuolemaa\", vanha hauta.",
"Se on vain syvä, sysipimeä hauta täynnä tuskallista kuolemaa...",
"Itse en menisi sinne.",
"Tervetuloa, Marin perillinen.",
"Viimein, valittu seisoo edessäni.",
@@ -1826,7 +1825,7 @@
"Mikään ei pysäytä meitä, koska olemme...",
"AAAGGGHHH!",
"SIG!",
"Tuota... mikäs on varasuunnitelma?"
"Tuota... olikos varasuunnitelmaa?"
],
"vin-rescue": [
"Aaahhh! Pysykää kaukana!",
@@ -8859,8 +8858,8 @@
],
"prop056": [
"Täällä huipulla voi tulla niin yksinäistä.",
"Täältä katsoen näen, kuinka mätä kaupunkimme on",
"kuinka mätä kaupunkimme on toivottoman elvytyksen tarpeessa.",
"Täältä katsoen näen, kuinka mätä kaupunkimme",
"on toivottoman elvytyksen tarpeessa.",
"Tämä mielessä, tulemme purkamaan useita alueita piakkoin!",
"Kaikki valitukset tätä rakennusaloitetta vastaan",
"tuodaan henkilökohtaisesti linnoituksen vankilaan,",
@@ -8898,7 +8897,7 @@
"ja piipahtaa vanhassa mökissäni.",
"On aika noutaa jotain, mitä piilotin sinne kauan sitten.",
"Onnea matkaan! Ja Daxter...",
"siivoa paikkani, kun olette siellä!"
"siivoat sitten joka nurkan!"
],
"sam002": [
"Tämä on Samos. Nyt kun te pojat olette täällä,",
@@ -8915,8 +8914,8 @@
],
"sam004": [
"Pärjäsit hyvin, Jak.",
"Onneksi Edeltäjäkivi ei ollut siinä pommissa, kun se räjähti,",
"tai kukaan meistä ei olisi täällä juuri nyt.",
"Onneksi Edeltäjäkivi ei ollut siinä pommissa kun se räjähti,",
"tai muuten kukaan meistä ei hengittäisi juuri nyt.",
"Tule takaisin kisatalliin niin pian kuin voit."
],
"sam005": [
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -16,13 +16,6 @@
"010e": "Päällä",
"010f": "Pois",
"0110": "Käytä suuntanäppäimiä",
"0111": "<FLAG_USA> English",
"0112": "<FLAG_FRANCE> Fran,cais",
"0113": "<FLAG_GERMAN> Deutsch",
"0114": "<FLAG_SPAIN> Español",
"0115": "<FLAG_ITALIAN> Italiano",
"0116": "<FLAG_KOREA> ~Y~Z<K32e>~Z<K31a>~Z<K3c8>~Y~Z<K35e>~Z<K36b>~Z<K3de>~Y~Z<K30f>~Z<K31d>",
"0117": "<FLAG_JAPAN> にほんご",
"0118": "Kuvasuhde",
"0119": "Peräkkäispyyhkäisy",
"011a": "Videotila",
@@ -504,7 +497,7 @@
"02f6": "Kor ja lapsi",
"02f7": "Pelasta lisää vaanijoita",
"02f8": "Marin haudan legenda",
"02f9": "Se on kirous, eikö vain?",
"02f9": "Kirottu",
"02fa": "Pora romahtaa",
"02fb": "Valotorni nousee",
"02fc": "Sinetti avaa portin",
@@ -236,20 +236,20 @@
"1339": "Display",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Hint Subtitles",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Pressure Sensitivity",
"134b": "Swap R1 and R2",
"134c": "Trigger Effects"
@@ -236,20 +236,20 @@
"1339": "Mostra",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Subtítols amb Suggeriments",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Sensibilitat a la pressió",
"134b": "Intercanviar R1 i R2",
"134c": "Efectes pels Gatells"
@@ -236,20 +236,20 @@
"1339": "Obrazovka",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Titulky nápovědy",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Citlivost na tlak",
"134b": "Prohodit R1 a R2",
"134c": "Efekty spouští"
@@ -236,20 +236,20 @@
"1339": "Skærm",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Hint Subtitles",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Pressure Sensitivity",
"134b": "Swap R1 and R2",
"134c": "Trigger Effects"
@@ -236,20 +236,20 @@
"1339": "Anzeige",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Hinweis-Untertitel",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Druckempfindlichkeit",
"134b": "R1 und R2 tauschen",
"134c": "Trigger-Effekte"
@@ -236,20 +236,20 @@
"1339": "Display",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Hint Subtitles",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Pressure Sensitivity",
"134b": "Swap R1 and R2",
"134c": "Trigger Effects"
@@ -236,20 +236,20 @@
"1339": "Display",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Hint Subtitles",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Pressure Sensitivity",
"134b": "Swap R1 and R2",
"134c": "Trigger Effects"
@@ -236,20 +236,20 @@
"1339": "Pantalla",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Subtítulos de sugerencia",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Sensibilidad a la presión",
"134b": "Intercambiar R1 y R2",
"134c": "Efectos de Gatillos"
@@ -136,7 +136,7 @@
"1292": "Palauta oletukset",
"1293": "Ohjainasetukset",
"1294": "Valitse ohjain",
"1295": "Analogisauvan katvealue",
"1295": "Ohjaussauvan katvealue",
"1296": "Älä huomioi ikkunan ulkopuolella",
"1297": "LED-valo kunnolle",
"1298": "LED-valo muille tiloille",
@@ -207,7 +207,7 @@
"1314": "Varoitus!",
"1315": "Tämä asetus on erittäin kokeellinen. Kun peliä ei pelata 60 Hz:n kuvataajuudella, visuaalisia sekä pelattavuuden ongelmia voi ilmaantua sen seurauksena.",
"1316": "Paikallinen tulos",
"1317": "Analogisauvan herkkyys",
"1317": "Ohjaussauvan herkkyys",
"1320": "Ei mitään",
"1321": "Pyörähdys",
"1322": "Nopeuslisä",
@@ -236,20 +236,20 @@
"1339": "Näyttö",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Vinkkien tekstitys",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Näppäinten paineherkkyys",
"134b": "Vaihda R1- ja R2-toiminnot",
"134c": "Ohjaimen liipaisintehosteet"
@@ -236,20 +236,20 @@
"1339": "Écran",
"133a": "<FLAG_FINLAND> Suomi",
"133b": "Sous-titres d'indices.",
"133c": "Português",
"133d": "Svenska ",
"133e": "Dansk",
"133f": "Norsk",
"1340": "Nederlands",
"1341": "Português (Brasil)",
"1342": "Magyar",
"1343": "Català",
"1344": "Íslenska ",
"1345": "Polski",
"1346": "Lietuvių Kalba",
"1347": "Čeština",
"1348": "Hrvatski",
"1349": "Galego",
"133c": "<FLAG_PORTUGUAL> Português",
"133d": "<FLAG_SWEDEN> Svenska",
"133e": "<FLAG_DENMARK> Dansk",
"133f": "<FLAG_NORWAY> Norsk",
"1340": "<FLAG_DUTCH> Nederlands",
"1341": "<FLAG_BRAZIL> Português (Brasil)",
"1342": "<FLAG_HUNGARY> Magyar",
"1343": "<FLAG_CATALAN> Català",
"1344": "<FLAG_ICELAND> Íslenska",
"1345": "<FLAG_POLAND> Polski",
"1346": "<FLAG_LITHUANIA> Lietuvių Kalba",
"1347": "<FLAG_CZECH> Čeština",
"1348": "<FLAG_CROATIA> Hrvatski",
"1349": "<FLAG_GALICIA> Galego",
"134a": "Sensibilité à la pression.",
"134b": "Inversez R1 et R2.",
"134c": "Déclencher des effets."

Some files were not shown because too many files have changed in this diff Show More