Compare commits

..
129 Commits
Author SHA1 Message Date
Jordan 21d27233d2 [decompiler] Fix Sound-Effects Extraction on Windows (#4459)
Some of the sound effects in Jak 2 have an * in their name, which is a
forbidden character for a filename on Windows.
This was causing errors with the sound effects extraction. In this PR I
replace forbidden characters with an underscore (_)
in the filenames of extracted sound effects.
2026-11-07 14:18:22 -05:00
Tyler Wilding 75b7f2b3ab d/jx: Part 7 - add fixes to most of the files i deferred in the last PR (#4469) 2026-11-07 14:12:37 -05:00
Alex Anderson f1b3de907c goalc: treat WSA_IO_PENDING as a socket timeout on windows (#4465)
On Windows 11 26H2 (build 26300), goalc drops its connection to the game
after a few seconds idle. After that, every form fails with “Compilation
generated code, but wasn’t supposed to”, and (lt) can’t reconnect.

When a recv hits SO_RCVTIMEO, Windows sometimes reports WSA_IO_PENDING
(997) instead of WSAETIMEDOUT. The socket is still fine, but
socket_timed_out() doesn’t recognize 997, so the listener disconnects.
This change treats it as a timeout too.

Tested as a binary patch on the ArchipelaGOAL v0.5.9 goalc.exe, where it
fixed the issue. I haven’t built this branch from source.

AI disclosure: I used Claude Code to process the logs and diagnose the
issue, the change is my own.
2026-11-03 12:45:58 -05:00
Tyler Wilding 3d20187fd3 d/jx: Part 6 - 135 more files decompiled (#4463)
woo

TODO:
- [x] Update the mips2c stuff because i shuffled some of the methods
that were mips2c'd
- [x] Make the type tests / [x] offline tests pass
- [x] partially revert changes to `gstate`
2026-11-03 01:11:00 -05:00
OpenGOAL BotandOpenGOALBot 33f364db4a CI: Periodic Controller Database Update (#4464)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-11-03 01:07:38 -05:00
Matt DallmeyerandTyler Wilding c7db3c9adb d/jx pad, most ofkeyboard, bunch of vehicle/level enums (#4460)
Co-authored-by: Tyler Wilding <[email protected]>
2026-10-31 18:19:33 -04:00
Hat Kid 94684e32f6 decompx: many decompiler improvements, new tools, fix offline tests, and a bunch of files (#4462)
Decompiler fixes/improvements:

- Support for more complex array accesses like 2D arrays
- Support for `srl`
- Support and mark functions that put `s7` on the stack as either C
callees or interrupt handlers
- Misc fixes for bitfields
- Warn when float infinity appears and replace `(gpr->fpr #x7f800000)`
with `(the-as float #x7f800000)`
- Fix `deftype`'s `:overlay-at` by using correctly aligned stride size
for inline arrays (this broke offline tests for `wvehicle-hud-h`)
- Parallel offline tests should now correctly print all errors at the
end instead of just `Compiler Error`

New decomp tools (UI for these will be PR'd to the extension repo soon):

- ASM branch permuter
- Method call searcher
- FIeld access searcher

Files

- `view`
- `lobby-dma`
- `entity`
- `game-info`
- `game-save`
- `settings`
- `ambient`
- `attackable-hash`
- `part-tester`
- `pilot-states`
- `target-pilot`
- `target-death`
- `logic-target`
- `target`
- `speech`
- `path`
- `load-state`
- `mem-buffer`
- `mem-buffer-h`
2026-10-27 17:18:34 +01:00
Tyler WildingandHat Kid e4aa2b260c d/jx: Part 5 - another 100ish files (#4450)
Notably a lot done related to process-drawable/camera/nav code, the core
engine files are dwindling.

Also finally commits all the static data files for textures/joints/etc

---------

Co-authored-by: Hat Kid <[email protected]>
2026-10-24 15:17:23 -04:00
Hat Kid d2a4685b70 type searcher: fix jak x (#4456) 2026-10-22 16:55:31 +02:00
Jordan 6076aab5a9 [Jak X] Updating hacks.jsonc so that we avoid decompiling ASM functions (#4452)
This PR updates the `hacks.jsonc` file so that the decompiler doesn't
try to compile asm functions in `net-mgr-dme` or `net-mgr-medius-rooms`.
2026-10-19 17:36:35 -04:00
OpenGOAL BotandOpenGOALBot cbabe7b7ef CI: Periodic Controller Database Update (#4453)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-10-19 17:36:11 -04:00
Tyler Wilding 32c3cf7397 github: add AI policy, contributing gidelines, and a PR template that all xref each other (#4447)
Please submit all complaints and insults via the game's "Bug Report"
feature
<img width="311" height="579" alt="Screenshot 2026-10-15 at 9 18 45 PM"
src="https://github.com/user-attachments/assets/82fb2446-72ca-4a09-bb82-bcc21bf60b64"
/>
2026-10-15 21:27:51 -04:00
Matt Dallmeyer b6c8430c0b [jak3] Fix glider crash after playing sniper cannon mission (#4443)
The `relocate` method for `simple-prim` is defined twice, first in
`generic-obs.gc` and then again here in `cty-sniper-turret`. This
removes the one from the mission-specific code.

The only other type making use of `simple-prim` is used in the glider
mission. So on first playthrough, it runs fine, using the
`generic-obs.gc` method. But once you've played the sniper cannons
mission once, after it unloads, we no longer have a relocate method for
`simple-prim` on hand. So the glider mission crashes
2026-10-14 05:05:21 +02:00
Blake645 abc82729ad [Jak 3] Fix Onin's Tent Minimap icon showing up in the desert (#4435)
Added a couple of flags to the `onintent` icon in the `define
*minimap-class-list*` in `minimap.gc` to match other haven city icons.
It seemed like ND never realized this so it just never got fixed.
Before:
<img width="1098" height="626" alt="Screenshot 2026-09-30 232736"
src="https://github.com/user-attachments/assets/58d26124-e054-425f-bd45-e343ba32798b"
/>
<img width="1045" height="311" alt="Screenshot 2026-09-30 232804"
src="https://github.com/user-attachments/assets/c169b9c4-14cd-4ed1-a8aa-865fcf75836a"
/>

After:
<img width="1094" height="615" alt="Screenshot 2026-09-30 232949"
src="https://github.com/user-attachments/assets/3bdd842e-8b70-4dfd-b876-6fd3c8e2898e"
/>
<img width="649" height="473" alt="Screenshot 2026-09-30 233041"
src="https://github.com/user-attachments/assets/e0596d61-f5f5-4f6e-ac6f-61db9b62812b"
/>
2026-10-13 01:28:47 -04:00
dependabot[bot] fd1976dcc8 build(deps): bump hendrikmuhs/ccache-action from 1.2.23 to 1.2.24 (#4434)
Bumps
[hendrikmuhs/ccache-action](https://github.com/hendrikmuhs/ccache-action)
from 1.2.23 to 1.2.24.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/hendrikmuhs/ccache-action/releases">hendrikmuhs/ccache-action's
releases</a>.</em></p>
<blockquote>
<h2>v1.2.24</h2>
<h2>What's Changed</h2>
<ul>
<li>metadata: Add release of ccache on linux-riscv64 by <a
href="https://github.com/luhenry"><code>@​luhenry</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/442">hendrikmuhs/ccache-action#442</a></li>
<li>Update sccache to 0.15.0 by <a
href="https://github.com/luhenry"><code>@​luhenry</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/444">hendrikmuhs/ccache-action#444</a></li>
</ul>
<h2>dependabot updates</h2>
<ul>
<li>Bump fast-xml-builder from 1.1.4 to 1.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/445">hendrikmuhs/ccache-action#445</a></li>
<li>Bump jest from 30.3.0 to 30.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/446">hendrikmuhs/ccache-action#446</a></li>
<li>Bump <code>@​types/node</code> from 25.6.0 to 25.9.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/449">hendrikmuhs/ccache-action#449</a></li>
<li>Bump fast-xml-parser from 5.5.7 to 5.8.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/443">hendrikmuhs/ccache-action#443</a></li>
<li>Bump actions/checkout from 6 to 7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/454">hendrikmuhs/ccache-action#454</a></li>
<li>Bump <code>@​vercel/ncc</code> from 0.38.4 to 0.44.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/458">hendrikmuhs/ccache-action#458</a></li>
<li>Bump to sccache v0.17.0 and ccache v4.13.6 by <a
href="https://github.com/luhenry"><code>@​luhenry</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/464">hendrikmuhs/ccache-action#464</a></li>
<li>Bump <code>@​types/node</code> from 25.9.1 to 26.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/461">hendrikmuhs/ccache-action#461</a></li>
<li>Bump <code>@​actions/cache</code> from 6.0.0 to 6.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/460">hendrikmuhs/ccache-action#460</a></li>
<li>Bump undici from 6.24.1 to 6.28.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/462">hendrikmuhs/ccache-action#462</a></li>
<li>Bump brace-expansion by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/463">hendrikmuhs/ccache-action#463</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/hendrikmuhs/ccache-action/compare/v1.2.23...v1.2.24">https://github.com/hendrikmuhs/ccache-action/compare/v1.2.23...v1.2.24</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/f09c25b45002a07be2955cbe52e8cee55643f89d"><code>f09c25b</code></a>
update code</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/19aa42b6ca68c1069b56d8bb2f291392b0216516"><code>19aa42b</code></a>
Bump brace-expansion (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/463">#463</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/de5fb0399f8b488d7997df40e23da36e8a43e14e"><code>de5fb03</code></a>
Bump undici from 6.24.1 to 6.28.0 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/462">#462</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/480c732748d960a6ddc280d756dfa0595473e831"><code>480c732</code></a>
Bump <code>@​actions/cache</code> from 6.0.0 to 6.2.0 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/460">#460</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/613119fd3907ba70834cfb38a73148dae1482c6a"><code>613119f</code></a>
Bump <code>@​types/node</code> from 25.9.1 to 26.2.0 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/461">#461</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/32bcd49b86abd7a2d659aeb782b9a8fefaf63cb6"><code>32bcd49</code></a>
Bump to sccache v0.17.0 and ccache v4.13.6 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/464">#464</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/9e3d904369d9bf49d300a32d7fb1b6f15c5c5e14"><code>9e3d904</code></a>
Bump <code>@​vercel/ncc</code> from 0.38.4 to 0.44.1 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/458">#458</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/9bb417d028933250488db49d13b07e017ee194b9"><code>9bb417d</code></a>
Bump actions/checkout from 6 to 7 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/454">#454</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/9e72c68cf32eb51fa30568928aca57ff79155270"><code>9e72c68</code></a>
update code after package updates</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/5685f76b5f826f81494dfc055898742f06c26bf5"><code>5685f76</code></a>
Bump fast-xml-parser from 5.5.7 to 5.8.0 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/443">#443</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/hendrikmuhs/ccache-action/compare/v1.2.23...v1.2.24">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=hendrikmuhs/ccache-action&package-manager=github_actions&previous-version=1.2.23&new-version=1.2.24)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 16:45:31 -04:00
dependabot[bot] 25df2f95ed build(deps): bump mathieudutour/github-tag-action from 6.2 to 7 (#4433)
Bumps
[mathieudutour/github-tag-action](https://github.com/mathieudutour/github-tag-action)
from 6.2 to 7.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/mathieudutour/github-tag-action/blob/master/CHANGELOG.md">mathieudutour/github-tag-action's
changelog</a>.</em></p>
<blockquote>
<p>v7 upgrades the action to Node 24 and introduces breaking changes to
version calculation and branch handling. Review the migration guide
before upgrading from v6.</p>
<ul>
<li>Run on Node 24 and ship a self-contained <code>dist/</code> bundle
with both supported commit presets, templates, dependencies, and license
notices. Refresh the lockfile, remove the old Octokit dependency chain,
and retain proxy support.</li>
<li>Align analysis and changelogs on Conventional Commits, including
<code>feat!</code>. Angular remains selectable.</li>
<li>Match whole branch names; an empty prerelease list now means no
prerelease branches. Never publish from PR events or recursively process
tag events. Preview versions include a commit SHA suffix.</li>
<li>Fetch all tags and all compare-commit pages. Explicitly restricted
tag fetching fails when results might be incomplete. Read initial commit
history instead of comparing against a fabricated HEAD baseline.</li>
<li>Skip version creation when no eligible commits remain, unless custom
or forced versioning was explicitly requested.</li>
<li>Keep stable release baselines separate from unrelated prereleases;
match prerelease identifiers exactly, honor the first prerelease
default, increment existing RCs, and allow higher-level changes to
advance the RC base.</li>
<li>Add path/scope/ignore filters, opt-in squash-bullet parsing,
tag-stream filtering, explicit bump/version inputs, local/moving/rolling
tags, repository/ref/directory overrides, and release metadata
outputs.</li>
<li>Retry transient API reads and fall back to complete local Git
history for compare failures. No history means no guessed release.
Optional soft failure clears release outputs.</li>
</ul>
<h2>Migration</h2>
<p>See <a
href="https://github.com/mathieudutour/github-tag-action/blob/master/docs/migrating-to-v7.md">Migrating
from v6 to v7</a> for changed defaults, workflow examples, prerelease
behavior, and a dry-run validation procedure.</p>
<p>New inputs are opt-in unless explicitly described above and require
v7. See the <a
href="https://github.com/mathieudutour/github-tag-action/blob/master/README.md">README</a>
for the full input contract.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/af99e60ce8132224b8e6ebab5023449fe256ed46"><code>af99e60</code></a>
fix CI on windows</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/8e15535db64483b84d3598dbf36eca1662cdbfe7"><code>8e15535</code></a>
version 7</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/9d35d648e836d5db77936aa35a3a5c7bc16092c8"><code>9d35d64</code></a>
Bump ws from 7.5.5 to 7.5.10 (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/216">#216</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/17d01dc92c1e62b097ea60d6c63b9f2b73c7b998"><code>17d01dc</code></a>
Bump braces from 3.0.2 to 3.0.3 (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/215">#215</a>)</li>
<li>See full diff in <a
href="https://github.com/mathieudutour/github-tag-action/compare/v6.2...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=mathieudutour/github-tag-action&package-manager=github_actions&previous-version=6.2&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-12 16:45:20 -04:00
OpenGOAL BotandOpenGOALBot f68700f196 CI: Periodic Controller Database Update (#4437)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-10-12 16:39:34 -04:00
Luminar Light ed028a4e8a jak1: Fix hint subtitles sometimes missing (#4440)
Some months ago I noticed that I wasn't seeing hint subtitles in TPL
anymore. Specifically, I was seeing the speaker names, but not the
subtitles themselves. I looked into it briefly back then and failed to
find anything, so I assumed it was something wrong with my setup
somehow.

I have returned to the issue, and managed to fix it. Now I consistently
see all subtitles, as I should. I always had the subtitles in the other
games working fine, and after my fix I still see them.

Before:
<img width="1920" height="1080" alt="2026-10-10T16-10-59"
src="https://github.com/user-attachments/assets/63a417fb-2f37-4950-a0ba-b9f28b02cae0"
/>

After:
<img width="1920" height="1080" alt="2026-10-10T16-58-55"
src="https://github.com/user-attachments/assets/4e58b34b-a253-458b-8be0-877c73767c3b"
/>

The fix was to provide default values in the subtitle metadata structs.
I remember that c++ fields/structs can end up having garbage data if you
don't provide values yourself, and this is probably also influenced by
the build config and maybe the PC itself. Anyway, with these changes, it
should always be good now regardless of who or what builds the project
(I usually use the Release msvc build config because Release clang has a
history of failing me).

Maybe it is worth mentioning that I always play with the setting that
forces speaker name to appear at all times. Not sure if relevant.

I have also discovered that the reload-subtitles feature of Jak 1 was
not working anymore, so I have made some adjustments and now it is
working fine.

While my solution fixed my issue, it is possible that it is not the
right way. The c++ language is not a language I am very experienced
with, so if my solution is unprofessional, please let me know and tell
me how I should approach it instead. But I am certain that the issue is
with field initialization somehow, and this is one way to fix that.

EDIT: Worth mentioning that I properly see all subtitles in current
latest OpenGOAL (launcher v2.11.2, tooling v0.3.8), which further
reinforces the idea that it is some fields that get unpredictable
values, influenced by the build config or build device. My issue is only
when I build the project myself. And it may impact other people, or it
may become an issue for official OpenGOAL too in the future.
2026-10-12 16:39:14 -04:00
rafalekkB efb21c3e8c [jak3] polish translation (#4431)
<img width="1913" height="1073" alt="image"
src="https://github.com/user-attachments/assets/584ec767-d612-4634-a677-6853fad76924"
/>

- translates base game text in jak3 to polish
- minor fixes for jak2 polish translation
- fixes an error in game_text.gp where every line referenced jak2 folder
instead of jak3
- increases text heap size to 128KB so the game doesn't crash when
loading the translated file
2026-09-30 14:52:29 -04:00
OpenGOAL BotandOpenGOALBot d6f33ab506 CI: Periodic Controller Database Update (#4432)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-09-29 11:01:59 -04:00
Matt Dallmeyer 76e8eeca35 [jak3] logior! instead of set! HERO_MODE_FEATURES (#4425)
For Act 2/3/Post-game, `set!`-ing the features ends up removing some
features given by task progression (e.g. `darkjak-smack`). Fix is to use
`logior!` instead so that we upsert the hero mode features and leave
task progression features alone.
2026-09-22 14:44:54 +02:00
Tyler Wilding 6445b4a50a ci: use gh instead of git in release-pipeline (#4423)
CI sure is fun
2026-09-20 00:13:09 -04:00
Tyler Wilding 24c9aa9f93 ci: ensure explicit tag is pushed in release pipeline (#4422)
while `gh release create` will create the tag for you, it only gets
created after the release is published. Which means the final step that
uploads the artifacts fails (it tries to checkout the tag, and it fails,
since it doesn't exist yet)
2026-09-20 00:10:10 -04:00
trippandTyler Wilding 9f0be81a23 extractor: dont default to x86 instructions on arm64 (#4420)
Co-authored-by: Tyler Wilding <[email protected]>
2026-09-19 23:10:25 -04:00
Tyler Wilding 9bd79e5d8a ci: allow explicitly providing the release tag (#4421)
Last release was bad, went to delete it and remake it. Found out that
immutable releases also means an implicit tag protection that you cannot
disable. This is a good thing, unfortunate that I forgot about it before
deleting the tag.

Anyway...this will resolve it (allows me to push 0.3.8 and it'll still
generate the release notes with the last tag (0.3.6), atleast that's the
theory
2026-09-19 22:26:24 -04:00
tripp 64b3bb9068 goalc: default to arm64 when built for ARM (#4419) 2026-09-19 21:53:50 -04:00
tripp 712cdfbaa2 decompiler: limit level extraction workers to hardware concurrency (#4417)
fixes an issue from my previous pull request #4278.
this change restores the previous behavior prior and prevents the level
extraction process from creating too many threads, ultimately resulting
in the decompiler failing.
2026-09-19 19:37:05 -04:00
Alex 31c3733673 jak2: fix language change not working through progress menu (#4418)
The game only actually changes audio language if the settings engine
notices it has changed, so `user-current` can't be changed here.
2026-09-18 15:29:08 +01:00
JordanandTyler Wilding d04ac9d787 Time Of Day Colors for GLBs (#4111)
With help from @gratefulforest, I've implemented storing colours for
each time of day for meshes,
and updated the code to store 32 channel colours (8 times of day * 4
rgba channels).


https://github.com/user-attachments/assets/5d2fb82c-40b7-44ad-976f-acd5d4d57e1c

In addition, I've implemented a system @gratefulforest suggested which
makes adding different times of day
really easy for developers.
- If some times of day are missing, they use the closest time of day
that is defined, defaulting to the earlier of the two if there are two
equally closest defined times of day.
- If no times of day are defined, COLOR_0 is used, otherwise white is
used.

Log messages are concise and very informative:
```
[46:23:278] [info] Reading gltf mesh: /home/jakjm/git/jak-project/custom_assets/jak1/levels/test-zone/test-zone2.glb
[46:23:278] [warn] Plane missing some times of day, using sunrise:_EVENING, morning:_EVENING, noon:_TWILIGHT, afternoon:_TWILIGHT, sunset:_TWILIGHT, twilight:_TWILIGHT, evening:_EVENING, green sun:_EVENING
[46:23:278] [error] Cube.001 didn't have any colors, using white.
[46:23:278] [warn] Cube.002 had colors but no times of day, using COLOR_0.
[46:23:278] [warn] Cube.003 missing some times of day, using sunrise:_SUNRISE, morning:_SUNRISE, noon:_SUNRISE, afternoon:_SUNSET, sunset:_SUNSET, twilight:_SUNSET, evening:_SUNSET, green sun:_SUNRISE
[46:23:278] [warn] Cube.004 had colors but no times of day, using COLOR_0.
[46:23:278] [error] Cube.005 didn't have any colors, using white.
```

---------

Co-authored-by: Tyler Wilding <[email protected]>
2026-09-16 19:54:08 -04:00
Jordan 76e4bcb8bc [decompiler] Extracting Sound Effects and Music (#4401)
This PR adds the ability to extract sound effects to .wav files for each
of the four games, and music to .wav files for Jak1 and Jak2.

Basically what I have done is create a "fake player" which works the
same as the player from Player.cpp except we just take the raw audio
samples that would be sent to cubeb and then write them to wave files.

I shamelessly stole @Hat-Kid's code for flavas, for parsing the sound
effect names and for finding where the sound banks start for Jak 1 lol.
2026-09-16 19:29:11 -04:00
BreakPointsandTyler Wilding 613a8b22cd cmake: point to correct draco_features.h location (#4410)
Fixes the following error when running the "Install Jak" option in VS:
```
  CMake Error at third-party/draco/cmake_install.cmake:841 (file):
    file INSTALL cannot find
    "C:/Users/{WindowsUsername}/Documents/Coding/jak-project/out/build/Release/draco/draco_features.h":
    No error.
  Call Stack (most recent call first):
    cmake_install.cmake:48 (include)
  
  
  FAILED: [code=1] CMakeFiles/install.util 
  C:\WINDOWS\system32\cmd.exe /C "cd /D C:\Users\Jack\Documents\Coding\jak-project\out\build\Release && "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -P cmake_install.cmake"
  ninja: build stopped: subcommand failed.
Install succeeded.
```

The build was still useable but the error was bugging me.

Our version of `draco_features.h` is stored in
`third-party/draco/src/draco/draco_features.h` but `draco_install.cmake`
was not updated to reflect this change. Use the already defined
`${draco_features_file_name}` from `draco_options.cmake` to point to the
right place.

Disclosure: I didn't want to spend too much time dealing with cmake so I
pointed Qwen at the problem and it found a very simple solution. Using
`${draco_features_file_name}` to avoid hardcoding is neat. I fully
understand the fix, have tested it and all the descriptions were written
by me.
(AI Assisted)

---------

Co-authored-by: Tyler Wilding <[email protected]>
2026-09-16 19:23:45 -04:00
OpenGOAL BotandOpenGOALBot 78c14a9532 CI: Periodic Controller Database Update (#4416)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-09-16 19:10:25 -04:00
Gogoașă Cristian a42c071996 fix(docs): Update path for project-overview iso_data-help file (#4407)
Was trying to go through the README and the documentation on the project
to eventually start contributing and I noticed that this picture wasn't
rendering due to a faulty path in the markdown file.
2026-09-09 18:39:30 -04:00
Tyler Wilding 450b9449fe ci: fix issues in offline test workflow when running for an untrusted author (#4411) 2026-09-09 18:37:41 -04:00
OpenGOAL BotandOpenGOALBot 90ee91fcf0 CI: Periodic Controller Database Update (#4408)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-09-09 18:35:45 -04:00
Matt Dallmeyer ce97ce959b [jak3] game-score decomp cleanup, track minigame rank in autosplitter instead of task status (#4409)
The current autosplit options for side missions that track
bronze/gold/silver don't actually work (other than the explicit gold
options I added in #4398). This reworks these to track the player's best
rank in these missions (0=unranked, 1=bronze, 2=silver, 3=gold), and I
have the [corresponding autosplitter script
changes](https://github.com/open-goal/speedrunning/pull/35) to split
when reaching gold (rank 3). Should be okay to repurpose some of these
autosplitter fields since we haven't cut a release using them yet.

Along the way I filled out the `game-score` enum, made use of this enum
in place of uints throughout the code, and renamed things for a few
related `game-info` methods.
2026-09-08 04:50:53 +02:00
Tyler Wilding 6c719ae000 d/jx: Disassemble and compare VU programs, add reference tests, create a diff report (#4406)
All VU programs are unchanged except:

- `ocean-near-vu1` DIFFERENT
- `sparks-vu1` NEW
- `sprite-glow-vu1` DIFFERENT
- `tnear-vu1` DIFFERENT

And `hfrag`, `ocean` and `ocean-texture` have been removed.

A full breakdown:
```
================================================================================
Checking: background-vu0.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: bones-vu0.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: collide-vu0.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: emerc-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: etie-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: etn-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: foreground-vu0.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: generic-vu0.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: generic-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: merc-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: mercneric-vu0.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: ocean-mid-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: ocean-near-vu1.txt
================================================================================
!!! DIFFERENT !!!

--- ocean-near-vu1.txt
+++ ../jak3/ocean-near-vu1.txt
@@ -78,10 +78,20 @@
 .word 0x2ff
 .word 0x800206bc
 .word 0x2ff
+.word 0x903100a
+.word 0x2ff
+.word 0x884100a
+.word 0x2ff
 .word 0x80050032
 .word 0x2ff
 .word 0x800701f2
 .word 0x2ff
+.word 0x1fc1820
+.word 0x2ff
+.word 0x1fd1821
+.word 0x2ff
+.word 0x1fe2020
+.word 0x2ff
 .word 0x1f82922
 .word 0x2ff
 .word 0x1f92925
@@ -91,23 +101,23 @@
 .word 0x1fb292b
 .word 0x2ff
 .word 0x1ec292e
-.word 0x800601
+.word 0x9c0600
 .word 0x1ed2931
-.word 0x800641
+.word 0x9c0641
 .word 0x1ee2934
-.word 0x800681
+.word 0x9c0682
 .word 0x1ef2937
-.word 0x8006c1
+.word 0x9c06c3
 .word 0x1e8293a
-.word 0x800301
+.word 0x9d0300
 .word 0x3e5c122
-.word 0x800341
+.word 0x9d0341
 .word 0x3e5c925
-.word 0x800381
+.word 0x9d0382
 .word 0x3e5d128
-.word 0x8003c1
+.word 0x9d03c3
 .word 0x3e5d92b
-.word 0x800201
+.word 0x9e0200
 .word 0x3e5612e
 .word 0x2ff
 .word 0x3e56931
@@ -118,12 +128,26 @@
 .word 0x2ff
 .word 0x3e5413a
 .word 0x2ff
+.word 0x80031a32
+.word 0x2ff
+.word 0x80042232
+.word 0x2ff
 .word 0x1005281b
 .word 0x2ff
-.word 0x5a003fec
+.word 0x5a003fe7
 .word 0x2ff
 .word 0x80073ff2
 .word 0x2ff
+.word 0x843100a
+.word 0x2ff
+.word 0x824100a
+.word 0x2ff
+.word 0x1fc1820
+.word 0x2ff
+.word 0x1fd1821
+.word 0x2ff
+.word 0x1fe2020
+.word 0x2ff
 .word 0x1f82922
 .word 0x2ff
 .word 0x1f92925
@@ -133,23 +157,23 @@
 .word 0x1fb292b
 .word 0x2ff
 .word 0x1ec292e
-.word 0x800601
+.word 0x9c0600
 .word 0x1ed2931
-.word 0x800641
+.word 0x9c0641
 .word 0x1ee2934
-.word 0x800681
+.word 0x9c0682
 .word 0x1ef2937
-.word 0x8006c1
+.word 0x9c06c3
 .word 0x1e8293a
-.word 0x800301
+.word 0x9d0300
 .word 0x3e5c122
-.word 0x800341
+.word 0x9d0341
 .word 0x3e5c925
-.word 0x800381
+.word 0x9d0382
 .word 0x3e5d128
-.word 0x8003c1
+.word 0x9d03c3
 .word 0x3e5d92b
-.word 0x800201
+.word 0x9e0200
 .word 0x3e5612e
 .word 0x2ff
 .word 0x3e56931

================================================================================
Checking: shadow-vu0.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: shadow-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: shrub-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: sparks-vu1.txt
================================================================================
!!! MISSING: ../jak3/sparks-vu1.txt
!!! MISSING: sparks-vu1.txt does not exist in ../jak3

================================================================================
Checking: sprite-distort-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: sprite-glow-vu1.txt
================================================================================
!!! DIFFERENT !!!

--- sprite-glow-vu1.txt
+++ ../jak3/sprite-glow-vu1.txt
@@ -1,4 +1,4 @@
-.word 0x1005031e
+.word 0x10050320
 .word 0x2ff
 .word 0x1f903dc
 .word 0x2ff
@@ -66,17 +66,17 @@
 .word 0x2ff
 .word 0x1ed2004
 .word 0x1042101
-.word 0x3e54845
+.word 0x3e54844
 .word 0x5b1159
 .word 0x8025033c
 .word 0x410083
-.word 0x3e55046
+.word 0x3e55045
 .word 0x20025c
-.word 0x3e55847
-.word 0x2ff
-.word 0x3e56048
+.word 0x3e55846
+.word 0x2ff
+.word 0x3e56047
 .word 0x1002117
-.word 0x3e56849
+.word 0x3e56848
 .word 0x2ff
 .word 0x80000030
 .word 0x290247
@@ -178,7 +178,7 @@
 .word 0x18aa52f
 .word 0x80000030
 .word 0x1e5f1bf
-.word 0x3e5184c
+.word 0x3e5184b
 .word 0x1e5fc0a
 .word 0x3c5580b
 .word 0x191a46c
@@ -230,33 +230,33 @@
 .word 0x1ed697d
 .word 0x80000030
 .word 0x1ee717d
-.word 0x385583e
+.word 0x385583d
 .word 0x1f1897d
-.word 0x385603f
+.word 0x385603e
 .word 0x1f2917d
-.word 0x3856840
+.word 0x385683f
 .word 0x1f3997d
-.word 0x3857041
+.word 0x3857040
 .word 0x1f4a17d
-.word 0x3858819
-.word 0x2ff
-.word 0x385901b
+.word 0x3858818
+.word 0x2ff
+.word 0x385901a
 .word 0x2ff
 .word 0x3859808
 .word 0x2ff
 .word 0x385a009
 .word 0x2ff
-.word 0x385584e
-.word 0x2ff
-.word 0x3856050
-.word 0x2ff
-.word 0x3856852
-.word 0x2ff
-.word 0x3857054
+.word 0x385584d
+.word 0x2ff
+.word 0x385604f
+.word 0x2ff
+.word 0x3856851
+.word 0x2ff
+.word 0x3857053
 .word 0x2ff
 .word 0x80002efc
 .word 0x2ff
-.word 0x10010691
+.word 0x10010694
 .word 0x2ff
 .word 0x52001f8c
 .word 0x2ff

================================================================================
Checking: sprite-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: tfrag-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: tie-near-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: tie-vu1.txt
================================================================================
OK: Files are the same.

================================================================================
Checking: tnear-vu1.txt
================================================================================
!!! DIFFERENT !!!

--- tnear-vu1.txt
+++ ../jak3/tnear-vu1.txt
@@ -1421,9 +1421,9 @@
 .word 0x1916800
 .word 0x400403
 .word 0x40000008
+.word 0x2ff
+.word 0x1927000
 .word 0x400443
-.word 0x1927000
-.word 0x2ff
 .word 0x3eb802d
 .word 0x2ff
 .word 0x3eb882e
@@ -1435,39 +1435,39 @@
 .word 0x1916948
 .word 0x400403
 .word 0x40000001
+.word 0x2ff
+.word 0x1927148
 .word 0x400443
-.word 0x1927148
-.word 0x2ff
 .word 0x3eba02a
 .word 0x400483
 .word 0x3eba82b
+.word 0x2ff
+.word 0x3ebb02c
+.word 0x2ff
+.word 0x1f4581d
 .word 0x1998407
-.word 0x3ebb02c
+.word 0x1f55820
 .word 0x1998c47
-.word 0x1f4581d
-.word 0x1f6e93c
-.word 0x1f55820
+.word 0x3eb6027
 .word 0x1999487
-.word 0x3eb6027
-.word 0x191876f
 .word 0x3eb6828
-.word 0x19187ab
+.word 0x2ff
 .word 0x3eb801e
 .word 0x1f4a13c
 .word 0x3eb8821
 .word 0x1f5a93c
 .word 0x3eb9024
-.word 0x192ef6f
+.word 0x1f6e93c
 .word 0x3eb7029
-.word 0x192f7ab
+.word 0x2ff
+.word 0x3eba01d
+.word 0x2ff
+.word 0x3eba820
+.word 0x2ff
 .word 0x3ebb023
 .word 0x2ff
 .word 0x800e5872
 .word 0x2ff
-.word 0x3eba01d
-.word 0x2ff
-.word 0x3eba820
-.word 0x19de97c
 .word 0x1ff0297
 .word 0x2ff
 .word 0xb0f03fe
@@ -1475,7 +1475,7 @@
 .word 0x80040032
 .word 0x2ff
 .word 0x420f0007
-.word 0x19de93c
+.word 0x2ff
 .word 0x1006581c
 .word 0x2ff
 .word 0x420f0005
@@ -1541,20 +1541,20 @@
 .word 0x2c010002
 .word 0x2ff
 .word 0x2c0d0002
-.word 0x2ff
+.word 0x3eef87
 .word 0x5200080c
 .word 0x2ff
 .word 0x1f13002
 .word 0x2ff
 .word 0x52006803
 .word 0x2ff
-.word 0x80000030
+.word 0x81feebbc
 .word 0x2ff
 .word 0x400007e3
 .word 0x2ff
 .word 0x800841f2
 .word 0x2ff
-.word 0x420a0082
+.word 0x420a0077
 .word 0x2ff
 .word 0x80064072
 .word 0x2ff
@@ -1570,7 +1570,7 @@
 .word 0x2ff
 .word 0x5200681c
 .word 0x2ff
-.word 0x80000030
+.word 0x81feebbc
 .word 0x2ff
 .word 0x420a006e
 .word 0x2ff
@@ -1594,16 +1594,16 @@
 .word 0x2ff
 .word 0x80064772
 .word 0x2ff
+.word 0x1ec3000
+.word 0x2ff
+.word 0x1f43001
+.word 0x2ff
 .word 0x1f03002
 .word 0x2ff
-.word 0x1ec3000
-.word 0x2ff
-.word 0x1f43001
-.word 0x2ff
 .word 0x80042072
 .word 0x2ff
 .word 0x80000030
-.word 0x19d842c
+.word 0x2ff
 .word 0x81ec03bc
 .word 0x1ff632a
 .word 0x80000030
@@ -1671,14 +1671,14 @@
 .word 0x2c010002
 .word 0x2ff
 .word 0x2c0d0002
-.word 0x2ff
+.word 0x3eef87
 .word 0x500d0818
 .word 0x2ff
 .word 0x1f13802
 .word 0x2ff
 .word 0x5000080c
 .word 0x2ff
-.word 0x80000030
+.word 0x81feebbc
 .word 0x2ff
 .word 0x420a0038
 .word 0x2ff
@@ -1702,7 +1702,7 @@
 .word 0x2ff
 .word 0x80006235
 .word 0x2ff
-.word 0x420a0038
+.word 0x420a002d
 .word 0x2ff
 .word 0x80000030
 .word 0x2ff
@@ -1795,10 +1795,6 @@
 .word 0x80000030
 .word 0x2d6f86
 .word 0x80000030
-.word 0x3eef87
-.word 0x81feebbc
-.word 0x2ff
-.word 0x80000030
 .word 0x1ec6bac
 .word 0x80000030
 .word 0x1f4adac
@@ -1816,25 +1812,3 @@
 .word 0x1f6a5a8
 .word 0x80000030
 .word 0x1f284a8
-.word 0x80000030
-.word 0x3eef47
-.word 0x81fdf3bc
-.word 0x2ff
-.word 0x80000030
-.word 0x1ed63ac
-.word 0x80000030
-.word 0x1f5a5ac
-.word 0x80000030
-.word 0x1f184ac
-.word 0x800003bf
-.word 0x1e0739c
-.word 0x80000030
-.word 0x1e0b59c
-.word 0x80000030
-.word 0x1e0949c
-.word 0x80000030
-.word 0x1ee6bac
-.word 0x48005000
-.word 0x1f6adac
-.word 0x80000030
-.word 0x1f28cac
```
2026-09-04 23:01:17 -04:00
tripp 7bad6c10a9 decompiler: fix missing merc and shrub texture replacements (#4405)
fixes a regression introduced in #4278
2026-09-04 09:29:19 -04:00
Matt Dallmeyer e08d934dbd [jak3] Add autosplits for side mission golds, orbs per level (#4398)
For hundo, all satellite, all open orbs gamers

Goes along with https://github.com/open-goal/speedrunning/pull/35
2026-09-04 09:28:59 -04:00
Matt Dallmeyer 2796e0974b Add imgui option to restart in retail mode (#4404) 2026-09-04 09:28:21 -04:00
Tyler Wilding 9c86c86c74 d/jx: More files (#4360)
Breaks the 300 file milestone, also includes the majority of mips2c
functions carried forward. Some functions need some fixes in the c++
code to mips2c properly, and a small handful of the mips2c functions
require manual patching -- all spots were marked with `TODO - fix` that
had to be commented out to get things compiling.
2026-09-04 09:27:06 -04:00
JordanandTyler Wilding 65fc564c16 Added missing <algorithm> header to fix compiler error. (#4396)
When compiling today, I had this error on Arch Linux x86-64 due to the
missing <algorithm> header.
<img width="1952" height="1079" alt="Screenshot from 2026-08-27
22-53-33"
src="https://github.com/user-attachments/assets/c0101a23-ac2a-40a5-a1b9-b1e926e600a7"
/>

Adding the header fixes it.

---------

Co-authored-by: Tyler Wilding <[email protected]>
2026-08-31 22:52:59 -04:00
OpenGOAL BotandOpenGOALBot 91e8864a89 CI: Periodic Controller Database Update (#4403)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-08-31 22:52:44 -04:00
Matt Dallmeyer c115da577c [jak3] Extend speedrun menus for selecting secrets (#4397)
extends the secret selection menu to other categories (act 2, 3, etc)
and adds hero mode categories for act 2 and 3
2026-08-30 21:45:25 -04:00
Jordan 427c952558 [Jak 2 and Jak 3]: Fixing menu text boundaries and drawing alignments for Automatic and Custom aspect ratios (#4380)
This PR fixes the alignment of text and other elements in several menus
of Jak 3 (as well as some of Jak 2) when using Automatic or Custom
aspect ratios. It also cleans up some of the relevant functions which
are used to draw these menus (although I'm still learning how to clean
goal code).

I mostly used french text for testing (since the french text seems to
push the font boundaries to their limits a bit more).
I used Automatic 16:9 and Custom 4:1 aspect ratios for testing to see if
my changes scale to other aspect ratios properly, comparing with PS2 4:3
for reference.



### Jak 3

### Image Color Scale

Before:
- The black/white color scale would get stretched (beyond the limits of
the menu in 4x1)
<img width="1280" height="758" alt="color-scale-16x9-broken"
src="https://github.com/user-attachments/assets/4b3b897e-1417-42da-86a1-dd78926ccb73"
/>
<img width="1283" height="747" alt="color-scale-4x1-broken"
src="https://github.com/user-attachments/assets/44d192ba-5afe-43ae-9419-021123478a31"
/>

Reference (PS2 4:3 in OpenGoal):
<img width="1278" height="773" alt="color-scale-reference"
src="https://github.com/user-attachments/assets/d9bd8f4e-8f69-49a9-8a99-3fcd3d7a4097"
/>

After fixes:

<img width="1283" height="765" alt="color-scale-16x9-fixed"
src="https://github.com/user-attachments/assets/99422d7f-d688-4d91-8ce0-6ad0b7cb10df"
/>
<img width="1282" height="762" alt="color-scale-4x1-fixed"
src="https://github.com/user-attachments/assets/6011f30a-0c31-4ea9-afe1-735ec36f3d32"
/>




### Secrets menu

Before:
- The secret titles touch their costs (#4233).
- The alignment of the top line showing orbs available/cost and total
orbs collected is broken (more noticeable in 4:1)
- The alignment of the titles for groups of secrets is broken (more
noticeable in 4:1)
- The indentation for secret titles relative to the group of secrets is
also broken (again, more noticeable in 4:1)
<img width="1286" height="758" alt="secrets-broken-16x9"
src="https://github.com/user-attachments/assets/bd6c7dab-ce95-4349-bf1d-2a09f82fcbfe"
/>
<img width="1287" height="751" alt="secrets-broken-4x1"
src="https://github.com/user-attachments/assets/3e1ce842-19ba-49b3-92f9-52034ae1982f"
/>

Reference (PS2 4:3 in OpenGoal):

<img width="1280" height="761" alt="Screenshot from 2026-08-16 22-58-22"
src="https://github.com/user-attachments/assets/7326a1c7-b479-4fb7-9450-377a05ab7963"
/>

After fixes:
<img width="1280" height="722" alt="secrets-fixed-16x9"
src="https://github.com/user-attachments/assets/0a66d45f-3aa3-4cc8-ac88-c6aef20f1319"
/>
<img width="1286" height="713" alt="secrets-fixed-4x1"
src="https://github.com/user-attachments/assets/e8740739-42ac-4a12-aad1-e6620dfc73ed"
/>



### Secrets purchase menu

Before: 

- The text for the secret you're purchasing can get cut off if too big.
- As before, the top line showing orb cost/orbs collected is misaligned.
<img width="1288" height="754" alt="secrets-purchase-broken-16x9"
src="https://github.com/user-attachments/assets/49b709e3-c015-42ba-b0aa-034769286d77"
/>
<img width="1281" height="756" alt="secrets-purchase-broken-4x1"
src="https://github.com/user-attachments/assets/0c3c5e02-048a-4188-ada7-2413c384224b"
/>

Reference (PS2 4:3 in OpenGoal):

<img width="1286" height="753" alt="secrets-purchase-reference"
src="https://github.com/user-attachments/assets/bb0b1d1a-87f6-4343-8a82-2e1f968943cd"
/>

After fixes:
<img width="1286" height="759" alt="secrets-purchase-fixed-16x9"
src="https://github.com/user-attachments/assets/1d73593f-1d58-407e-9ce6-2da5bf0fd84b"
/>
<img width="1283" height="750" alt="secrets-purchase-fixed-4x1"
src="https://github.com/user-attachments/assets/85c7e14d-c6b2-4b21-83e5-173af5cba185"
/>


### Save/Load/Create Hero Mode Save menu

Here I show the load game screen only but the bugs were the same among
all 3 as the code is shared. The fixes apply to all 3 as well 😃

Before:

- The header text is cut off in french. 
- There is a faint red rectangle to the right of the menu (look closely!
It's a bit clearer and goes beyond the menu in 4x1).
- The left yellow boxes around the save-games that are not selected do
not scale properly (more noticeable in 4x1).

<img width="1284" height="749" alt="load-broken-Automatic"
src="https://github.com/user-attachments/assets/2ae3bd8b-42ec-49bc-9851-cbaace4ce64b"
/>
<img width="1285" height="751" alt="load-broken-4x1"
src="https://github.com/user-attachments/assets/655de844-748c-43f9-a2e8-d779fe3a8e19"
/>

Reference (PS2 4:3 in OpenGoal):
<img width="1281" height="762" alt="load-screen-4x3"
src="https://github.com/user-attachments/assets/e4e320c9-999a-44a7-8b3e-34cfdbeef5a1"
/>



After Fixes:

- Now headers that exceed the width of the menu screen will be shrunken
down to fit. This will hopefully work for any other menus that need it
as well 😃
- No more red rectangle on the right, and the yellow box to the left
around the save games scales properly.

<img width="1286" height="754" alt="load-fixed-automatic"
src="https://github.com/user-attachments/assets/1a48d811-5684-4f7e-a12a-19e896e30b48"
/>
<img width="1288" height="749" alt="load-fixed-4x1"
src="https://github.com/user-attachments/assets/f5a68cb1-576a-4927-977b-b3419aaf7c23"
/>


### Missions menu 

Before:

- Mission text is sometimes cut off on the right
- Mission text is shifted to the right (more noticeable in 4x1)

<img width="1286" height="753" alt="missions-alignment-broken-16x9"
src="https://github.com/user-attachments/assets/37175eb7-e191-4c09-bb72-b40819acd99b"
/>
<img width="1281" height="750" alt="missions-alignment-broken-16x9-2"
src="https://github.com/user-attachments/assets/482f351a-7386-4211-8434-cf60c0691fdb"
/>
<img width="1286" height="756" alt="missions-broken-4x1"
src="https://github.com/user-attachments/assets/4cbfa4d0-999b-4265-bed0-957958663037"
/>
<img width="1290" height="750" alt="missions-broken-4x1-2"
src="https://github.com/user-attachments/assets/4889b498-d6aa-4e6c-87fc-4dfadeac5827"
/>

Reference (PS2 4:3 in OpenGoal):
<img width="1284" height="768" alt="missions-reference-1"
src="https://github.com/user-attachments/assets/91a526c8-08c2-4a62-8219-09e967fab9c2"
/>
<img width="1276" height="755" alt="missions-reference-2"
src="https://github.com/user-attachments/assets/65c4e944-5b1f-479a-bf7c-eca19c81f5d6"
/>


After:
<img width="1281" height="760" alt="missions-fixed-16x9"
src="https://github.com/user-attachments/assets/a972daf0-1872-46f0-a829-cd8d292df1d6"
/>
<img width="1282" height="750" alt="missions-fixed-16x9-2"
src="https://github.com/user-attachments/assets/973611d6-a72c-43f8-b2f3-034e83f6c416"
/>
<img width="1289" height="760" alt="missions-alignment-fixed-4x1"
src="https://github.com/user-attachments/assets/699c5dbc-8c39-468d-9e14-94007a789e48"
/>
<img width="1281" height="755" alt="missions-alignment-fixed-4x1-2"
src="https://github.com/user-attachments/assets/89216187-d453-4d3e-8e8b-5ae365e7227d"
/>


### Jak 2 

### Secrets menu orb icon
Position was wrong in Automatic and some (but strangely, not all) Custom
Aspect ratios. A correction for the aspect ratio was also being applied
in the setter.

Before:
<img width="1284" height="755" alt="image"
src="https://github.com/user-attachments/assets/0a15e238-1d98-4ba7-86ce-b295e8d78d7a"
/>

After:
<img width="1283" height="755" alt="image"
src="https://github.com/user-attachments/assets/bd97de44-ef41-426c-a76f-d4fe99a35285"
/>

### Missions menu
- Indentation was not working, even in 4:3, due to a typo.
- Width was broken in Automatic and Custom

Before:
<img width="1281" height="753" alt="Screenshot from 2026-08-19 01-05-54"
src="https://github.com/user-attachments/assets/6f5e3cc4-3522-45a5-a45b-34a46a7db544"
/>

After:
<img width="1287" height="761" alt="image"
src="https://github.com/user-attachments/assets/cae5498b-6ca4-40ab-a31c-feb8899bc1e7"
/>
2026-08-28 16:42:47 +02:00
Tyler Wilding bebfb0cec8 ci: revert change to compilation check (#4394)
Not required anymore.

Eventually this test should be ran on the ARM version of the compiler in
addition to the x86 one, but im not in a rush, especially since it's
likely that the ARM backend will be less stable as it's literally brand
new.
2026-08-24 23:53:32 -04:00
ParkerandTyler Wilding de25f39439 arm64: Apple Silicon support (#4390)
Got OpenGOAL building and running natively on Apple Silicon.

This is the rest of the port after the smaller arm64 emitter PRs. I was
told pushing one big PR was okay. This covers goalc, the runtime,
linker, kernel and the GOAL asm.

The new paths have native tests. I also found four more emitter bugs
while running it. They're in scalar sqrt, 128-bit stores, scalar max and
indexed stores above 4 GB.

Spent a while cleaning it up so it's easier to read. 4am gotta sleep lol

Closes #3841

---------

Co-authored-by: Tyler Wilding <[email protected]>
2026-08-24 23:22:47 -04:00
Tyler Wilding 553a713aed ci: fix another macOS dependency (http2) (#4393)
These dependencies only crop up under the static build i suppose, brotli
was fixed, but now http/2 support is the new failure. Will actually
verify they will work here before merging this time.
2026-08-24 22:52:11 -04:00
Tyler Wilding d28a8e998e ci: install brotli explicitly on macOS runners (#4392)
Another out of no-where regression on the macOS runners...
https://github.com/open-goal/jak-project/actions/runs/32795420246
```
ld: library 'brotlidec' not found
```
2026-08-24 21:58:04 -04:00
Jordan 1c9262842f [Jak 3]: Fixing spelling of precursor in french. (#4381)
Fixed spelling mistake that occurs in the original game. précuseur ->
précurseur
2026-08-24 20:57:16 -04:00
Parker b59a6d1cf3 goalc: arm64 vector loads and stores with a register offset were wrong (#4386)
Some neon tests, plus the fix they needed to run at all.

`ldr q` and `str q` with a register offset had a bad option field so
they don't
decode. The s8 load was ignoring addr2 and reading from the base on its
own. A
few used post indexed forms, which move the address register.

Rest of the avx list to come.
2026-08-22 17:00:13 -04:00
Parker 8c926caa23 goalc: arm64 SIMD encoders emitted the wrong instructions (#4385)
Alters the opcode constants and the lane index maths, so the pext,
vector shift, shuffle, blend and splat helpers now emit the correct
ZIP1/ZIP2, SHL/SSHR/USHR, INS and DUP machine encodings for 128-bit
vector operations.

Adds an Imm5 field helper, which the lane-insert and duplicate encodings
need.

Follows #4384, from the same Apple Silicon work.
2026-08-22 16:34:00 -04:00
Parker 9e5ecef614 goalc: arm64 vector float ops were not float ops (#4384)
Alters the opcode constants in Base, so these helpers now emit the
correct FADD/FMAX/FMIN machine encodings for 4×f32 vector operations.

Found these while getting OpenGOAL running natively on Apple Silicon.
2026-08-21 18:39:37 -04:00
OpenGOAL BotandOpenGOALBot 04b256e9e0 CI: Periodic Controller Database Update (#4382)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-08-17 18:56:22 -04:00
Tyler Wilding bfc4c18ada goalc: replicate tests for the majority of ARM64 non-simd cases (#4377)
- Adds `capstone` as a disassembling library that could eventually
replace Zydis (for now left that alone)
- Replicates all of the existing x86 tests to ARM64, fixed a bunch of
underlying issues along the way
- There are a very small handful of tests remaining that need to be
enabled / fixed
2026-08-16 15:34:37 -04:00
Jordan 8565ddfbdd Fixed mirror world hud alignment. (#4373)
This PR fixes the hud icon positions in mirror world, resolving #4362. 
Now the orb and skull-gem icons are correctly positioned on the left
whether or not mirror world is active.

Normal:
<img width="1918" height="1042" alt="Screenshot from 2026-08-03
13-01-26"
src="https://github.com/user-attachments/assets/a33ef81f-43e7-4e8d-900d-2e7331588402"
/>
<img width="1922" height="1079" alt="Screenshot from 2026-08-03
13-05-17"
src="https://github.com/user-attachments/assets/06ce1b16-7e40-44e8-a144-25d654a089c8"
/>
Mirror world:
<img width="1924" height="1041" alt="Screenshot from 2026-08-03
12-59-31"
src="https://github.com/user-attachments/assets/68ed1d70-8314-4ef0-bdac-3a7de81a2d57"
/>
<img width="1924" height="1078" alt="Screenshot from 2026-08-03
13-05-35"
src="https://github.com/user-attachments/assets/b3b0a02c-fe11-4ed8-abe1-cbcad214379f"
/>

Closes #4362
2026-08-16 15:02:16 -04:00
Tyler Wilding 787e360fa9 cmake: look in /usr/lib64 for libraries as well (#4379) 2026-08-16 15:01:12 -04:00
OpenGOAL BotandOpenGOALBot 62a7494a10 CI: Periodic Controller Database Update (#4374)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-08-15 23:09:18 -04:00
Hat Kid 641fb572e8 decompiler: misc gltf exporter fixes (#4371)
This PR adds various fixes to the GLTF exporter:

- Merc and TIE envmaps now properly extract
- Changed joint offset in `convert_per_vertex_data` since we now export
the `align` bone
- The bone accessor for merc models now uses
`TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE`, fixing a decompiler crash when
attempting to reimport an extracted model into the game without first
importing it into Blender and re-exporting
- All model buffers now get merged into one large buffer before export,
saving some space and increasing parsing speed of GLB files
- Tfrags, TIEs and shrubs are now no longer stored in one giant mesh per
tree and get grouped into categories:
- Tfrags will be grouped by the tfrag tree name they come from (normal,
trans, dirt, ice, etc.) and get separated by the texture their material
uses (tfrags are not instanced, so this is the next best solution)
- TIEs and shrubs get grouped by tree index and separated by their proto
name (TIE wind will also be grouped separately)

<img width="1630" height="1716" alt="image"
src="https://github.com/user-attachments/assets/2ce31795-a445-4a0d-982d-413fd51833b2"
/>
<img width="497" height="291" alt="image"
src="https://github.com/user-attachments/assets/a8b44073-a33e-4c40-a5d7-2c7a328a86b4"
/>
<img width="484" height="750" alt="image"
src="https://github.com/user-attachments/assets/15392b94-60f3-4fee-97c5-cc6a50d298d5"
/>
<img width="525" height="684" alt="image"
src="https://github.com/user-attachments/assets/e3814105-7538-4028-9129-63b21d432528"
/>
<img width="1221" height="1298" alt="image"
src="https://github.com/user-attachments/assets/7aefa662-890a-4be8-9540-3e63fff52f28"
/>
2026-07-31 06:15:24 +02:00
tripp a4cb1ac1f0 fix: typo in decompression error checking (#4370) 2026-07-28 05:00:51 +02:00
Hat KidandTyler Wilding f9a4c5b33f custom levels: fix potential use after free in custom region generation on windows (#4369)
On Windows, the pairs produced by custom regions all become bogus,
probably due to some compiler differences.
Changing the pairs that get stored in the regions to not be pointers
should hopefully resolve this.
To be extra sure, I also pulled some `add_word(0)`s out into locals to
avoid any argument evaluation order shenanigans.

---------

Co-authored-by: Tyler Wilding <[email protected]>
2026-07-28 03:23:46 +02:00
SilversHotsuin a53a526b78 Jak1: Changed one line to fit the screen in 4X3 (Galician) (#4363)
Changed the line "PREME O BOTÓN START" (PRESS START) to fit the 1 line
preference regarding the menu strings
2026-07-27 19:19:47 -04:00
Alexander J. Semenuk 5d5e35fb9b fix: Windows toolchain compatibility (curl 8.21 re-vendor, endless reconfigure loop) (#4355)
## Problem

Windows builds break with a current local toolchain (Scoop LLVM 22.1.8,
CMake 4.4.0, VS 2026), in two independent ways:

1. The build stops at curl's deliberate guard: `#error "no non-blocking
method was found/used/set"` in `third-party/curl/lib/nonblock.c`.
2. From the second configure onward, `cmake --build` re-runs CMake in an
endless loop (observed 42 consecutive reconfigure cycles in a single
build). Likely the same mechanism behind the "endlessly building" VS
2026 note in `docs/setup/dev/vs.md`.

## Root cause

1. `third-party/curl/CMake/CurlTests.c` passes `int *` to
`ioctlsocket()`, whose third parameter is `u_long *`. Clang 22 promotes
`-Wincompatible-pointer-types` to a hard error in C, so the
`HAVE_IOCTLSOCKET_FIONBIO` try_compile silently fails and
`curl_config.h` never defines it. Upstream CI does not see this because
the windows-2022 runner image ships an older LLVM. GCC 14 promotes the
same warning to a hard error, which is very likely the `CurlTests.c.obj`
failure reported from MSYS2 in open-goal/jak-project#3551. Upstream curl
hit the identical problem with GCC 14 and fixed the probe in curl 8.8.0
(curl/curl#13578).
2. The root CMakeLists copies the build tree's `compile_commands.json`
into `<src>/build/` for clangd using `configure_file()`, which registers
its input as a configure dependency. CMake rewrites
`compile_commands.json` late in every generation, after
`CTestTestfile.cmake` and `cmake_install.cmake` (outputs of the same
Ninja regen rule), so once the dependency is registered the rule is
deterministically dirty and every `ninja` invocation re-runs CMake. A
pristine first configure is safe (the file does not exist yet, so the
`if(EXISTS ...)` guard skips the copy), which is why the loop looks
machine- or IDE-specific.

## Fix

1. Per review, re-vendor `third-party/curl` at the `curl-8_21_0` tag
(previously `curl-8_3_0`), which carries the upstream probe fix plus two
years of upstream development; `vendor.yaml` updated to match.
Adjustments the version jump forced:
- curl 8.15 removed the native macOS Secure Transport backend
(`CURL_USE_SECTRANSP`), so macOS now builds curl against OpenSSL like
Linux. The two macOS workflows install Homebrew `openssl@3` and export
`OPENSSL_ROOT_DIR` (keg-only), and the macOS setup docs gained the same
two lines.
- `CURL_BROTLI` / `CURL_ZSTD` switched to AUTO-detection in curl 8.10;
pinned OFF to keep the previous no-compression behavior and avoid
silently linking whatever the CI images happen to have.
- curl's new top-level `BUILD_EXAMPLES` cache option (default ON) leaked
into discord-rpc's identically named option and broke configure at a
nonexistent `examples/send-presence` directory; pinned OFF ahead of the
third-party subdirectories.

The diff is dominated by the mechanical tag-tree swap under
`third-party/curl` (linguist-vendored, collapsed in review). The
hand-written changes are `CMakeLists.txt`, the two macOS workflows,
`docs/setup/system/macos.md`, and `vendor.yaml`.
2. Swap `configure_file()` for `file(COPY ...)`: the same clangd copy
with no configure dependency registered. (`file(COPY_FILE ...
ONLY_IF_DIFFERENT)` would be cleaner still but requires CMake 3.21,
above the declared `cmake_minimum_required(VERSION 3.10)`.)

## Test plan

- [x] Fresh `cmake --preset Release-windows-clang` (LLVM 22, no cache
seeding) completes and logs `Enabled SSL backends: Schannel`; the
FIONBIO probe passes without the previous `#error`
- [x] Full Windows Release build from scratch in the branch worktree
(all 1422 targets)
- [x] goalc-test suite: 1509 passed, 0 failed
- [x] Second consecutive configure with `compile_commands.json` present:
the regen rule in `build.ninja` has no `compile_commands.json` input;
`<src>/build/compile_commands.json` is still refreshed for clangd
- [x] Repeated `ninja` invocations after a full build no longer re-run
CMake
- [x] macOS Intel and ARM CI green (first exercise of the OpenSSL
backend switch)

---

I work off a self-hosted forge, so this GitHub account is quiet; the
configure logs and ninja dirty-node traces from the investigation are
available if anyone wants the raw data.

(AI-assisted)
2026-07-27 19:19:18 -04:00
OpenGOAL BotandOpenGOALBot 888b300487 CI: Periodic Controller Database Update (#4368)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-07-27 19:08:06 -04:00
Hat Kid fe2086acfb goalc: add debug server (#4365)
This adds a debug server to `goalc` that sends JSON over the socket to
communicate with an external debugger using the Debug Adapter Protocol.

This lets us debug GOAL code in a proper debugger with breakpoints, step
over, step in and step out per line, stack frames and supports watches
for global symbols, registers and local variables (local variables only
work within the most recent stack frame). Special registers (`r13`,
`r14`, `r15`, argument registers, etc.) are tracked separately and the
current process register even displays the type of the current `pp` if
possible.

Watches that track addresses holding a reference type generate a list of
field names according to the object's type. All fields will show their
name, type and value and, depending on the type, will try to infer extra
info like symbol names/values, function names for `function` fields,
enum values and more. This also works nested, so any field that is also
a reference type can also be accessed and display its fields, etc.
Dynamic arrays are also supported where possible, e.g. in
`inline-array-class` children and boxed arrays, it will figure out the
value of the `length` field and access the memory up to that point so
all the elements can be accessed and viewed from the `data` field.

Our VS Code extension implements the DAP in
open-goal/opengoal-vscode#375.

Using it is as simple as connecting a REPL to a running game instance
with `(lt)`, compiling with `(mi)` and, with the extension installed,
pressing F5 in VS Code to start the debugger. By default, it will try to
connect to the game that the active `.gc` file is from, the socket port
is different per game (8128 for Jak 1, 8129 for Jak 2, 8130 for Jak 3).
The `launch.json` was updated with two entries for this, the second
entry lets you pick the game/port manually if desired.

~~Not tested on Windows.~~ Only supports x86 for now.
2026-07-27 22:28:28 +02:00
SilversHotsuin e0dc11554d Jak 1: Add Galician base text translation as well as game_text.gp update (#4358)
Added the file to have the menus of Jak 1 translated into Galician (main
menu, options, task/missions and their states, as well as some
minigames).

Already tested, at least on Windows 10, 4x3 aspect ratio and 1920x1080p
monitor.

--------

Translated and revised by: SilversHotsuin and Aziamuth
2026-07-25 13:49:12 -04:00
Matt Dallmeyer fcbcfb549a [jak1] Reinstate NaN check in nav code (#4359)
Inadvertently removed as part of improved decompiler stack variable
support #4222

We suspect this is the reason some nav-enemies have been randomly
disappearing in recent mods/versions

Thanks Evelyn for catching the regression
2026-07-23 22:44:51 +02:00
tripp a306052e84 [jak3] fix missing Hfrag desert terrain on macOS (#4353)
Fixes #4270
2026-07-22 23:04:43 -04:00
Alexander J. Semenuk b0ec3703f9 fix(runtime): add missing break after JakX goal_main (#4356)
(AI assisted)
2026-07-22 19:07:00 -04:00
Tyler Wilding 02e9579fb5 game: ensure overwritten subtitle lines have the merge flag disabled (#4352)
Fixes another long-standing subtitle translation bug.

There is a `merge` flag on each subtitle line, the idea being that we
would merge in the text from the base game if this was set. However in
jak 2 and beyond:
- The subtitles for english (base) are not predefined for the cutscenes,
only the hints. The rest are in the game files and we do not
simultaneously load both languages when the game is running so there is
no trivial fallback path.
- However, every subtitle language by default inherits the base games
metadata, where all `merge` flags are set to `true`

This means that all custom cutscene translations were being ignored
unless this flag was set to false in the metadata file for each line.
This is what finnish does since it changes the number of lines and their
timings, and is why it works fine.

This flag can probably be completely removed, as per the above, it
serves no actual purpose. All it does in our code is if it's set, we
skip the line when writing out the subtitle file.

But for now i simply just iterate through and flip these flags
automatically if the language overrode the cutscene. Tested on
english/finnish/pt-BR
<img width="648" height="467" alt="image"
src="https://github.com/user-attachments/assets/292e3dfe-df66-4d23-942a-b41f2b157bf8"
/>
2026-07-22 00:00:57 -04:00
Rafael Freitas 0935ce4ffa jak2: Add Brazilian Portuguese base game text (#4350)
Adds `game_base_text_pt-BR.json` — the missing base game text (menus,
options, mission tracker strings) for Brazilian Portuguese in Jak II.

The custom menu text and subtitles for pt-BR were already present in the
project; this fills in the last missing piece (`game_base_text`) needed
for the language to be fully usable in-game.

Tested in-game by switching to Portuguese and checking menus, pause
screen, and mission objective text.
2026-07-20 16:52:48 -04:00
OpenGOAL BotandOpenGOALBot 4e4d494e52 CI: Periodic Controller Database Update (#4351)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-07-20 16:52:36 -04:00
Alexander J. Semenuk eddd6fb019 fix(gfx): generate cloud mipmaps after unbinding the render FBO (#4344)
Found while investigating the jak2/jak3 one-frame sky flicker (see the
fog CLUT inline payload PR: `#4343`).

## Problem

`TextureAnimator::run_clouds` calls `glGenerateMipmap` on the final
cloud texture while that texture is still attached to the currently
bound draw framebuffer (the `FramebufferTexturePairContext` is still in
scope). Reading a texture that is attached to the bound framebuffer is a
driver hazard even outside a draw call.

Every other site in this file already avoids this: `run_slime` and
`opengl_upload_resize_texture` both close the FBO context scope before
generating mipmaps. `run_clouds` is the one outlier, presumably an
oversight.

## Fix

Scope the `FramebufferTexturePairContext` in braces and generate the
mipmaps after it restores the previous framebuffer binding, matching the
established pattern in the rest of the file.

## Test plan

- [ ] jak2/jak3 clouds render identically (hires and normal cloud modes)

(AI-assisted)
2026-07-19 14:59:17 -04:00
Tyler Wilding eaf48bb2f3 New Crowdin updates - July 2026 (#4349)
Closes #4328
2026-07-19 14:58:55 -04:00
rafalekkB 37f3562d06 Jak 2 - Polish base game text translation + updating font db (#4332)
basically initial commit to add support for polish base game text

needs work before you could push to master

im a little rusty so testing along side me if everything is working
would be appreciated

<img width="1919" height="1107" alt="jak2 pl menu"
src="https://github.com/user-attachments/assets/862dcbe0-1c6a-4b9e-9565-7aa91b0a9115"
/>
2026-07-18 16:32:50 -04:00
Matt Dallmeyer 726b48b0c4 [jak1] Prevent debug crash in subtitle code (#4348)
fixes this crash
https://gist.github.com/dallmeyer/0a5520379a3b96725af152bde66f63e8 which
can be reproduced by doing a HUD buffer on the bottom of LPC cell in
debug mode
2026-07-18 16:31:12 -04:00
Matt DallmeyerandHat Kid 425f143fcc Update def-actor to version 8 for jak3 (#4342)
v7 is copy/paste from jak2

https://github.com/open-goal/jak-project/blob/697337166da69af6515e97c5a9894b8ba2abc93c/goal_src/jak2/engine/data/art-h.gc#L423
https://github.com/open-goal/jak-project/blob/697337166da69af6515e97c5a9894b8ba2abc93c/goal_src/jak2/engine/load/file-io.gc#L109

but jak 3 uses v8

https://github.com/open-goal/jak-project/blob/697337166da69af6515e97c5a9894b8ba2abc93c/goal_src/jak3/engine/load/file-io.gc#L198-L199

---------

Co-authored-by: Hat Kid <[email protected]>
2026-07-14 04:32:00 +02:00
Matt Dallmeyer 697337166d [jak1] Patch autosave/progress lock in speedrun mode (#4340)
We already skip the "first autosave warning" prompt in speedrunner mode,
this just moves the check up a bit earlier, where it feels more
appropriate imo.

This also prevents a potential softlock from occurring in speedrunner
mode only, if you manage to bring up the progress menu while the first
autosave occurs/finishes (e.g. by pause buffering 7th scout fly, or one
of the citadel sage cells).

In that scenario, the `auto-save` process gets stuck in `done` state in
this loop because `progress-allowed?` is false due to the pending
powercell cutscene, and so we keep resetting `state-time`:

https://github.com/open-goal/jak-project/blob/d8710bb2f645528e598e2bd799708d9d945f76c6/goal_src/jak1/engine/game/game-save.gc#L1172-L1174
(in normal circumstances, this prevents the autosave prompt from popping
up during and shortly after the cell cutscene)

The problem is that the `progress` code has a sort of mirrored check,
where it will only `enter!` the next state if there is no `auto-save`
process:

https://github.com/open-goal/jak-project/blob/d8710bb2f645528e598e2bd799708d9d945f76c6/goal_src/jak1/pc/progress-pc.gc#L3600-L3609

Here's an example of the locked progress screen, I run some code in the
REPL to show the game is still running, and then use a breakpoint and
continue to artificially get past the `time-elapsed?` check in the
`auto-save` code

https://youtu.be/4eZlQbRq6l8
2026-07-10 22:49:52 -04:00
iHR4KandTyler Wilding d8710bb2f6 goalc: fix compilation error in arm64 code (#4337)
Co-authored-by: Tyler Wilding <[email protected]>
2026-07-06 22:52:31 -04:00
Hat Kid ad4653bd75 game: fall back to english splash screen before accessing map (#4336)
Likely cause of #4333
2026-07-04 02:29:08 +02:00
Tyler Wilding 76941379e9 goalc: Finish converting all load/store instructions to ARM64 (#4334)
All that remains (8 instructions) are division, and NEON instructions
that require me to convert the x86 control byte to NEON `TBL` values.
Those handful of instructions can be done later while doing the next
steps (finally something more interesting than just encoding
instructions).
2026-07-03 19:40:29 -04:00
Tyler Wilding bc1b24b0f3 cmake: disable libpsl when building libcurl (#4335) 2026-07-03 19:10:46 -04:00
OpenGOAL BotandOpenGOALBot 2490c94e97 CI: Periodic Controller Database Update (#4327)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-07-01 18:11:11 -04:00
dependabot[bot] f9acbe4d1b build(deps): bump actions/checkout from 4 to 7 (#4329)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to
7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v7.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>block checking out fork pr for pull_request_target and workflow_run
by <a href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li>
<li>Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the
minor-actions-dependencies group across 1 directory by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2458">actions/checkout#2458</a></li>
<li>Bump flatted from 3.3.1 to 3.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2460">actions/checkout#2460</a></li>
<li>Bump js-yaml from 4.1.0 to 4.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2461">actions/checkout#2461</a></li>
<li>Bump <code>@​actions/core</code> and
<code>@​actions/tool-cache</code> and Remove uuid by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2459">actions/checkout#2459</a></li>
<li>upgrade module to esm and update dependencies by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2463">actions/checkout#2463</a></li>
<li>Bump the minor-npm-dependencies group across 1 directory with 3
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2462">actions/checkout#2462</a></li>
<li>getting ready for checkout v7 release by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2464">actions/checkout#2464</a></li>
<li>update error wording by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2467">actions/checkout#2467</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6.0.3...v7.0.0">https://github.com/actions/checkout/compare/v6.0.3...v7.0.0</a></p>
<h2>v6.0.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Update changelog by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2357">actions/checkout#2357</a></li>
<li>fix: expand merge commit SHA regex and add SHA-256 test cases by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li>
<li>Fix checkout init for SHA-256 repositories by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2439">actions/checkout#2439</a></li>
<li>Update changelog for v6.0.3 by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2446">actions/checkout#2446</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/yaananth"><code>@​yaananth</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6...v6.0.3">https://github.com/actions/checkout/compare/v6...v6.0.3</a></p>
<h2>v6.0.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Add orchestration_id to git user-agent when ACTIONS_ORCHESTRATION_ID
is set by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2355">actions/checkout#2355</a></li>
<li>Fix tag handling: preserve annotations and explicit fetch-tags by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2356">actions/checkout#2356</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6.0.1...v6.0.2">https://github.com/actions/checkout/compare/v6.0.1...v6.0.2</a></p>
<h2>v6.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Update all references from v5 and v4 to v6 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2314">actions/checkout#2314</a></li>
<li>Add worktree support for persist-credentials includeIf by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2327">actions/checkout#2327</a></li>
<li>Clarify v6 README by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2328">actions/checkout#2328</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v6...v6.0.1">https://github.com/actions/checkout/compare/v6...v6.0.1</a></p>
<h2>v6.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>v6-beta by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2298">actions/checkout#2298</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>v7.0.0</h2>
<ul>
<li>Block checking out fork PR for pull_request_target and workflow_run
by <a href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2454">actions/checkout#2454</a></li>
<li>Bump actions/publish-immutable-action from 0.0.3 to 0.0.4 in the
minor-actions-dependencies group across 1 directory by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2458">actions/checkout#2458</a></li>
<li>Bump flatted from 3.3.1 to 3.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2460">actions/checkout#2460</a></li>
<li>Bump js-yaml from 4.1.0 to 4.2.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2461">actions/checkout#2461</a></li>
<li>Bump <code>@​actions/core</code> and
<code>@​actions/tool-cache</code> and Remove uuid by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2459">actions/checkout#2459</a></li>
<li>upgrade module to esm and update dependencies by <a
href="https://github.com/aiqiaoy"><code>@​aiqiaoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2463">actions/checkout#2463</a></li>
<li>Bump the minor-npm-dependencies group across 1 directory with 3
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/actions/checkout/pull/2462">actions/checkout#2462</a></li>
</ul>
<h2>v6.0.3</h2>
<ul>
<li>Fix checkout init for SHA-256 repositories by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2439">actions/checkout#2439</a></li>
<li>fix: expand merge commit SHA regex and add SHA-256 test cases by <a
href="https://github.com/yaananth"><code>@​yaananth</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2414">actions/checkout#2414</a></li>
</ul>
<h2>v6.0.2</h2>
<ul>
<li>Fix tag handling: preserve annotations and explicit fetch-tags by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2356">actions/checkout#2356</a></li>
</ul>
<h2>v6.0.1</h2>
<ul>
<li>Add worktree support for persist-credentials includeIf by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2327">actions/checkout#2327</a></li>
</ul>
<h2>v6.0.0</h2>
<ul>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
</ul>
<h2>v5.0.1</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<h2>v5.0.0</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
</ul>
<h2>v4.3.1</h2>
<ul>
<li>Port v6 cleanup to v4 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li>
</ul>
<h2>v4.3.0</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<h2>v4.2.2</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<h2>v4.2.1</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/checkout/commit/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0"><code>9c091bb</code></a>
update error wording (<a
href="https://redirect.github.com/actions/checkout/issues/2467">#2467</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/1044a6dea927916f2c38ba5aeffbc0a847b1221a"><code>1044a6d</code></a>
getting ready for checkout v7 release (<a
href="https://redirect.github.com/actions/checkout/issues/2464">#2464</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/f0282184c7ce73ab54c7e4ab5a617122602e575f"><code>f028218</code></a>
Bump the minor-npm-dependencies group across 1 directory with 3 updates
(<a
href="https://redirect.github.com/actions/checkout/issues/2462">#2462</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/d914b262ffc244530a203ab40decab34c3abf34d"><code>d914b26</code></a>
upgrade module to esm and update dependencies (<a
href="https://redirect.github.com/actions/checkout/issues/2463">#2463</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/537c7ef99cef6e5ddb5e7ff5d16d14510503801d"><code>537c7ef</code></a>
Bump <code>@​actions/core</code> and <code>@​actions/tool-cache</code>
and Remove uuid (<a
href="https://redirect.github.com/actions/checkout/issues/2459">#2459</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/130a169078a413d3a5246a393625e8e742f387f6"><code>130a169</code></a>
Bump js-yaml from 4.1.0 to 4.2.0 (<a
href="https://redirect.github.com/actions/checkout/issues/2461">#2461</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/7d09575332117a40b46e5e020664df234cd416f3"><code>7d09575</code></a>
Bump flatted from 3.3.1 to 3.4.2 (<a
href="https://redirect.github.com/actions/checkout/issues/2460">#2460</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/0f9f3aa320cb53abeb534aeb54048075d9697a0e"><code>0f9f3aa</code></a>
Bump actions/publish-immutable-action (<a
href="https://redirect.github.com/actions/checkout/issues/2458">#2458</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/f9e715a95fcd1f9253f77dd28f11e88d2d6460c7"><code>f9e715a</code></a>
block checking out fork pr for pull_request_target and workflow_run (<a
href="https://redirect.github.com/actions/checkout/issues/2454">#2454</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/df4cb1c069e1874edd31b4311f1884172cec0e10"><code>df4cb1c</code></a>
Update changelog for v6.0.3 (<a
href="https://redirect.github.com/actions/checkout/issues/2446">#2446</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/checkout/compare/v4...v7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4&new-version=7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-01 18:11:08 -04:00
Brian HoemandHat Kid 80e479611f Include merc normals for glb extraction (#4271)
Namely all I did was include the normals from MercVertex in with the glb
exporter. I also converted parts of MercVertex to use union structs for
faster casting. The union structs should just work on most compilers
from what I researched, if not I can revert that and go a different
route for that.

Co-authored-by: Hat Kid <[email protected]>
2026-06-30 22:01:02 +02:00
Hat Kid 8a73c3e997 989snd/overlord: implement PLUGIN_MESSAGE grain and STRV plugin system (#4319)
This implements the functionality for the `PLUGIN_MESSAGE` grain and the
989snd VAG plugin system, allowing sounds to queue up VAG streams.

Closes #2582
2026-06-30 21:21:34 +02:00
Matt Dallmeyer 2fff3306d1 [jak2/jak3] Speedrun menu - add Act 2/3, Open Orbs categories (#4314)
Adds these speedrun categories which require special setup:
- Jak 2
  - Act 2
  - Act 3
  - All Open Orbs (Endgame)
- Jak 3
  - Act 2
  - Act 3
  - Post-Game
  - Post-Game Hero Mode

https://github.com/open-goal/jak-project/issues/4214
2026-06-27 16:26:33 -04:00
Tyler Wilding e1ecbb5e9f i18n: adjust exclusions again (#4325)
- can't display korean text in jak 1
- shouldn't be excluded from text in jak 2
2026-06-27 16:19:33 -04:00
Tyler Wilding aa43a9fcd9 New Crowdin updates (#4324) 2026-06-25 14:43:32 -04:00
Tyler Wilding d07fbe6b74 i18n: third times the charm (#4323)
Missed reverting one `es`...
2026-06-23 21:18:37 -04:00
Tyler Wilding d3df40e554 i18n: update crowdin config (#4322)
take two....some languages do use the full locale (judging by the URLs)
2026-06-23 21:14:46 -04:00
Tyler Wilding 07fe735e68 i18n: update crowdin config (#4321)
Hopefully will resolve this issue
<img width="763" height="87" alt="image"
src="https://github.com/user-attachments/assets/e5c2a8f7-eb6c-48e0-b81e-1a815ba38d32"
/>
2026-06-23 21:06:10 -04:00
Tyler Wilding 8daf33492e goalc: Implement the bulk of ARM64 instructions from x86 (#4318)
Less than 100 instructions left to implement, with the vast vast
majority being load-and-stores. These will likely be knocked out quickly
but they require a more involved implementation than just simply
translating the instructions (several need multiple instructions, others
may need reserved registers (x16 or x17 are common for this purpose))

This is a good milestone to get something pushed to master.
2026-06-22 22:25:49 -04:00
ZedB0T f9a7fba6e2 Support identical imgui controller labels (#4290)
ImGUI does have ways to make sure the Internal IDs are unique and
separate from the display label, however I still thought that appending
a count to the end of the name was more clear/understandable.

If you add `ImGui::PushID(i);` Into the loop it appends i to the end of
the internal ID without modifying the display label. The other
alternative would be to use a syntax like
`ImGui::Button((controller_name + "##option1").c_str());` etc....

https://github.com/ocornut/imgui/blob/master/docs/FAQ.md#q-how-can-i-have-multiple-widgets-with-the-same-label


In both cases I think just adding a number that increments communicates
that its a different controller cleaner to the user.

Closes #4289
2026-06-22 19:59:21 -04:00
OpenGOAL BotandOpenGOALBot 85449e6c19 CI: Periodic Controller Database Update (#4320)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-06-22 19:58:58 -04:00
Hat Kid 0f9beb4610 decompiler: detect light-trail-tracker-spawn macro (#4317) 2026-06-17 18:57:59 +02:00
Hat Kid 0b799821ed decompiler: export blerc data to glb (#4316)
This adds the blerc data from merc models to the GLB export as shape
keys, also including the data from animations. Blender is unfortunately
a bit weird about this and only really lets you change what animated
weights are used via the NLA track editor by selecting both the
corresponding armature animation and then the one for the shape keys.
Additionally, due to the way the Blender GLB import works when you have
animated weights on a model + animations as actions for an armature, any
models that have blerc data get an extra useless empty, but this seems
to be harmless.

This PR also fixes materials that use texture animations so they now
have their base texture in the export, rather than using the default
material. Materials now also get named after their base texture for
easier recognition.
2026-06-17 02:41:39 +02:00
OpenGOAL BotandOpenGOALBot 86bbff237f CI: Periodic Controller Database Update (#4313)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-06-15 20:10:23 -04:00
Tyler WildingandHat Kid a3e004f475 d/jx: Another round of files (#4311)
Co-authored-by: Hat Kid <[email protected]>
2026-06-15 09:56:10 -04:00
Matt Dallmeyer 58d957a305 [jak3] track-skill: Better check for orbs collected from crate (#4312)
The one crate with gold triple orb in temple doesn't update `(-> e extra
perm user-int8 1)` the way I was expecting based on how the one crate
that drops two orbs behaved. This check fixes that and is a bit simpler
2026-06-15 06:23:12 +01:00
Hat Kid 41fd0b6cec custom levels: support camera entities and custom keyframe values (#4310) 2026-06-13 00:29:24 +02:00
Matt Dallmeyer feaa7fb873 [jak1] Show max of flying-lurker distances on HUD (#4309)
previously only showed the distance from `flying-lurker-1`, but any of
the 3 getting 500m can cause you to fail, so we should show the max
2026-06-11 07:26:41 +01:00
Matt Dallmeyer 396fd63c93 [jak3] Include orbs in crates for track skill debug option (#4275)
<img width="2756" height="2066" alt="image"
src="https://github.com/user-attachments/assets/88034b10-c502-4df0-b5b8-6d6357eed433"
/>
2026-06-10 19:48:38 -04:00
Tyler Wilding faa9b91c73 ci: move offline tests to a GHA self-hosted runner (#4308) 2026-06-09 21:25:33 -04:00
Tyler Wilding e41b6da568 ci: init offline runner allowlist (#4307)
Necessary scaffolding for offline test runner change, moving it off of
jenkins.
2026-06-08 20:13:30 -04:00
YohanDFNandTyler Wilding 70ef778a90 [jak3] proofreading & correcting FR subtitle lines (#4272)
This PR provides minor typo fixes and harmonizes the French subtitles
with the game's original terminology used in cutscenes and menus.

---------

Co-authored-by: Tyler Wilding <[email protected]>
2026-06-08 17:03:26 -04:00
tripp 560e191ca4 decompiler: reduce memory usage during texture pack installation by lazily loading texture replacements and serializing level building (#4278)
Three changes:
1. Add lazy merging/replacing for texture `rgba_bytes`.
2. Use a single thread when decompiling with texture replacements.
3. Drop textures after serializing and before compression.

These changes should enable users to install **massive** texture packs
without issue.
2026-06-08 17:02:19 -04:00
OpenGOAL BotandOpenGOALBot c81a315fa3 CI: Periodic Controller Database Update (#4306)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-06-08 17:00:54 -04:00
Hat Kid 4076b1477e jak3: fix zoom blur flashbang in retail (#4305)
When `do_zoom_blur` sets up its draw, it doesn't update the blend
settings, so it ends up inheriting the previous values.

In retail mode, the previous draw is from a texture animation, which
sets up the blend in a specific way that causes it to draw a white
texture over the screen. In debug mode, right before the zoom blur is
drawn, the debug text is drawn, which modifies the blend settings to
something that makes the blur look as it should.

Closes #4206
2026-06-07 21:28:59 +02:00
Hat Kid a5ef456e8b loader: allow manual reload of fr3 data (#4304)
This adds some buttons to the loader debug menu and GOAL functions to
allow you to manually force a reload of a level's FR3 data (including
the common level), allowing for live texture replacements, model swaps
and custom level modifications without requiring a game restart or
waiting for the loader to fully discard a level.
2026-06-07 16:45:33 +02:00
Hat Kid 25e105aa5d jak2/3: implement ocean envmap (#4303)
Implements the envmap for the ocean generated by
`ocean-method-89`/`ocean-method-88`.

While the resulting envmap looks accurate compared to PCSX2 in
Renderdoc, the end result does not seem 100% identical, but it is a big
improvement over the default placeholder texture.

Closes #3417
2026-06-07 07:27:43 +02:00
Matt Dallmeyer b948e954d0 [jak2/3] Fix dark/light eco HUD not flashing after save file is X hours old (#4285)
Once `(-> *display* game-clock frame-counter)` gets too large, in the
HUD flashing math the `sin` function breaks down at high values. It's
effectively reading the number of ticks (times a multiplier) as degrees,
so we can modulo that by 360 to avoid breaking `sin`

This applies to both the eco meter and the dark jak icon in jak 2 - the
icon stops flashing twice as early because it's multiplied by x4 vs the
eco meter x2.

example:

you can see dark jak icon stops flashing around 2:36:02
https://youtu.be/3V2GneLSY14?t=9362

and dark eco meter stops flashing between 4:30 and 4:37
https://youtu.be/3V2GneLSY14?t=16235
https://youtu.be/3V2GneLSY14?t=16619
2026-06-06 17:32:12 +01:00
Hat Kid b9d3f50ae8 deps: update to SDL 3.4.10 (#4301)
For Steam Controller (2026) support
2026-06-04 19:19:15 +02:00
Hat Kid 1254d93fbe custom levels: support custom regions in jak2/3 (#4300)
This adds support for generating pairs with `DataObjectGenerator` and
defining your own regions and `actor-group`s in custom levels.
2026-06-03 18:39:21 +02:00
Ziemas e00bc479f4 libco: Update to latest version from ares (#4282)
This also removes the LIBCO_MPROTECT setting, I don't know why I enabled
that but it prevented putting the context swap code in the text section.
2026-06-03 02:51:07 -04:00
Aloqas fa2f652d2f jak3: Dev commentary subtitles (#4281)
Subtitles for ND dev commentary tracks
2026-06-03 00:24:44 -04:00
OpenGOAL BotandOpenGOALBot bbb9abdbf8 CI: Periodic Controller Database Update (#4273)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-06-03 00:13:46 -04:00
Alex 89da645162 jak3: make actor LOD setting affect lightning quality in elec gates (#4292)
Carrying this over from Jak 2, where it significantly improved the elec
gates' look at a distance.
2026-05-31 16:55:46 +02:00
Hat Kid 3422e0525f decompiler: extract_anim model name remap (#4297)
In some rare cases, the master art group and model names do not match
for some animations (`collectables-ag` is a prime example for Jak 2/3,
which contains multiple different models).
2026-05-31 16:55:10 +02:00
Hat Kid e48289406e build-actor: set shader-cnt to 0 for dummy merc-fragment (#4296)
Inside the build actor tool's dummy `merc-fragment`'s `merc-fp-data`,
the `shader-cnt` is set to `1`, which means that `login-adgifs` runs for
the fragment and attempts to login the texture. We don't need to do this
for custom actors and it can cause crashes during level unloading when
textures get unlinked, so we can just set the `shader-cnt` to `0` to
prevent this.
2026-05-31 16:19:10 +02:00
Hat Kid 122de4ecf5 jak1: clean up control-info names and other misc cleanup (#4295)
After spending the last month staring at and comparing Jak 3 and Jak 1
versions of a bunch of `target` code for my jetboard mod, I figured this
would be a good opportunity to revive this ancient PR #1714 along with
some other small misc fixes/improvements.

Instead of directly replacing the old fields, I decided to opt for using
overlay fields to maintain backwards compatibility with existing manual
patches, files without ref tests and mods that might use these fields.
2026-05-31 15:08:41 +02:00
tripp fd17e337d6 jak2: add missing inline declaration in vector*! (#4287)
as per the description of #3846 
"Detect use of vector*!, which is **inlined in jak 2** and jak 3."

This function was missing the inline declaration resulting in the
compiled output differing.
2026-05-30 17:21:25 -04:00
Hat Kid 4e77d6ea61 jak1: fix mole crash on foot (#4294)
Another classic case of missing event args, though this one is fatal on
PS2 as well.
2026-05-30 11:14:29 +02:00
tripp c010073ddc game: fix missing event.type comparison in joystick axis motion handler (pressure sensitive axii) (#4286)
`SDL_EVENT_JOYSTICK_AXIS_MOTION` is an enum with `Value = 1536`, which
means the code current acts like: `else if (true &&
m_has_pressure_sensitive_buttons)`
2026-05-27 21:28:02 -04:00
Tyler Wilding 704972dd6a decomp: resolve first batch of trivial files (#4266) 2026-05-08 18:54:05 -04:00
Hat Kid 580b190371 jak3: fix dark eco vent powerup anim (#4269)
Yet another case of the PS2 getting insanely lucky with buggy ND code,
the eco vents send an event to Jak to make him go into the powerup
state, but do not pass any event arguments which determine what
animation to play and at what speed/start frame. For the dark eco vents,
PS2 manages to somehow get the correct value of `7`, but we are not so
lucky.

As a side effect of this fix, we also get the originally intended
behavior for the light eco vents of playing the full powerup animation
from the start at a slower speed, rather than the much shorter one you
see on PS2.

Closes #4268
2026-05-06 04:29:15 +02:00
Luís Mota 18988ff9fe Update Jak 1 Portuguese (pt-pt) translations (#4263)
Hello guys, I'm new here.
To give my contribution I've fully translated the intro sequence for Jak
1, some lines were missing.
2026-05-05 00:23:22 -04:00
OpenGOAL BotandOpenGOALBot 87190890cf CI: Periodic Controller Database Update (#4262)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2026-05-04 17:36:21 -04:00
Hat Kid c4bc4d3ff4 jak3: fix region regression (#4264) 2026-05-04 21:47:47 +02:00
11805 changed files with 4615366 additions and 332389 deletions

No files matched your search

+14
View File
@@ -0,0 +1,14 @@
# Contributing Guidelines
Thanks for being interested in contributing to our project in some way. To keep things brief, here are the quick notes.
## Policies
- Review our [AI usage policy](https://github.com/open-goal/jak-project/blob/master/AI_POLICY.md)
- No Android or mobile related contributions will be accepted, we aren't interested.
## The Hopefully Obvious
- Try to ensure your changes are well tested, clean and organized
- Be respectful, don't act like someone you would never want to associate with
- Be aware that depending on what you submit, it may not merge soon or ever depending on what it is. Don't take this personally -- reach out to us first to see if there is an appetite first before investing massive amounts of time into it.
+3
View File
@@ -1,5 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: AI Usage Policy
url: https://github.com/open-goal/jak-project/blob/master/AI_POLICY.md
about: Please follow the template and do not copy-paste AI generated output as your issue description.
- name: Feature Requests and Ideas
url: https://github.com/open-goal/jak-project/discussions/new/choose
about: Please use the discussion board to bring up feature requests and ideas. If there is interest in them, they can then be converted to an issue(s).
@@ -0,0 +1,5 @@
<!--
Please be familiar with:
- the AI Usage Policy - https://github.com/open-goal/jak-project/blob/master/AI_POLICY.md
- and the rest of the contributing guidelines - https://github.com/open-goal/jak-project/blob/master/.github/CONTRIBUTING.md
-->
+8
View File
@@ -0,0 +1,8 @@
13153231
48171810
7569514
6624576
2515356
70249609
5276694
89345505
+7 -7
View File
@@ -13,7 +13,7 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
ref: master
@@ -26,7 +26,7 @@ jobs:
libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev
- name: Setup sccache
uses: hendrikmuhs/[email protected]3
uses: hendrikmuhs/[email protected]4
with:
variant: sccache
key: linux-ubuntu-22.04--Release-linux-clang-static-${{ github.sha }}
@@ -48,7 +48,7 @@ jobs:
mv ./build ./build.master
- name: Checkout PR
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
clean: "false"
@@ -66,9 +66,9 @@ jobs:
- name: Compile and preserve (master)
run: |
./build.master/goalc/goalc --game jak1 --cmd "(make-group \"all-code\")"
./build.master/goalc/goalc --game jak2 --cmd "(make-group \"all-code\")"
./build.master/goalc/goalc --game jak3 --cmd "(make-group \"all-code\")"
./build.master/goalc/goalc --game jak1 --cmd '(make-group "all-code")'
./build.master/goalc/goalc --game jak2 --cmd '(make-group "all-code")'
./build.master/goalc/goalc --game jak3 --cmd '(make-group "all-code")'
mv ./out/jak1/obj ./out/jak1/obj.master
mv ./out/jak2/obj ./out/jak2/obj.master
mv ./out/jak3/obj ./out/jak3/obj.master
@@ -88,7 +88,7 @@ jobs:
ls -l ./out/jak2
ls -l ./out/jak3
set +e
python ./scripts/gsrc/compare-compilation-outputs.py --base "./out/jak1/obj.master,./out/jak2/obj.master,./out/jak3/obj.master" --compare "./out/jak1/obj.pr,./out/jak2/obj.pr,./out/jak3/obj.pr" --markdown
python ./scripts/ci/compare-compilation-outputs.py --base "./out/jak1/obj.master,./out/jak2/obj.master,./out/jak3/obj.master" --compare "./out/jak1/obj.pr,./out/jak2/obj.pr,./out/jak3/obj.pr" --markdown
SCRIPT_EXIT_CODE=$?
cat ./comp-diff-report.md >> $GITHUB_STEP_SUMMARY
if [ "$SCRIPT_EXIT_CODE" -ne 0 ]; then
+1 -1
View File
@@ -22,7 +22,7 @@ jobs:
BUILDCACHE_LOG_FILE: ${{ github.workspace }}/buildcache.log
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Install Package Dependencies
run: |
+4 -4
View File
@@ -16,7 +16,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Get Package Dependencies
run: |
@@ -37,13 +37,13 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Check for Trailing Whitespace in goal_src
run: python ./scripts/ci/lint-trailing-whitespace.py
- name: Check for Unresolved Conflicts
run: python ./scripts/gsrc/check-for-conflicts.py
run: python ./scripts/ci/check-for-conflicts.py
- name: Check for Incorrect Asserts
run: python ./scripts/ci/check-for-asserts.py
@@ -59,7 +59,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Install Python Dependencies
run: pip install unidiff colorama
+3 -3
View File
@@ -24,12 +24,12 @@ jobs:
# minimal checkout if we're NOT uploading artifacts
- name: Checkout Repository
if: ${{ ! inputs.uploadArtifacts }}
uses: actions/checkout@v6
uses: actions/checkout@v7
# full checkout with tags if we ARE uploading artifacts
- name: Checkout Repository with Tags
if: ${{ inputs.uploadArtifacts }}
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true
@@ -43,7 +43,7 @@ jobs:
libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev
- name: Setup sccache
uses: hendrikmuhs/[email protected]3
uses: hendrikmuhs/[email protected]4
with:
variant: sccache
key: linux-ubuntu-22.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+2 -2
View File
@@ -18,7 +18,7 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Install Package Dependencies
run: |
@@ -34,7 +34,7 @@ jobs:
sudo update-alternatives --set g++ /usr/bin/g++-10
- name: Setup sccache
uses: hendrikmuhs/[email protected]3
uses: hendrikmuhs/[email protected]4
with:
variant: sccache
key: linux-ubuntu-22.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+15 -5
View File
@@ -22,20 +22,30 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v6
if: ${{ ! inputs.uploadArtifacts }}
uses: actions/checkout@v7
- name: Checkout Repository with Tags
if: ${{ inputs.uploadArtifacts }}
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true
- name: Install Package Dependencies
env:
HOMEBREW_NO_INSTALL_CLEANUP: 1
HOMEBREW_NO_ANALYTICS: 1
run: |
if ! brew install ninja nasm; then
if ! brew install ninja nasm openssl@3 brotli nghttp2; then
brew update
brew install ninja nasm
brew install ninja nasm openssl@3 brotli nghttp2
fi
# keg-only, so give CMake's FindOpenSSL an explicit hint
echo "OPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" >> $GITHUB_ENV
- name: Setup sccache
uses: hendrikmuhs/[email protected]3
uses: hendrikmuhs/[email protected]4
with:
variant: sccache
key: macos-15-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
@@ -72,7 +82,7 @@ jobs:
uses: actions/upload-artifact@v7
if: ${{ inputs.uploadArtifacts }}
with:
name: opengoal-macos-arm-${{ inputs.cachePrefix }}
name: opengoal-macos-${{ inputs.cachePrefix }}
if-no-files-found: error
path: |
./build/goalc/goalc
+7 -5
View File
@@ -24,12 +24,12 @@ jobs:
# minimal checkout if we're NOT uploading artifacts
- name: Checkout Repository
if: ${{ ! inputs.uploadArtifacts }}
uses: actions/checkout@v6
uses: actions/checkout@v7
# full checkout with tags if we ARE uploading artifacts
- name: Checkout Repository with Tags
if: ${{ inputs.uploadArtifacts }}
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true
@@ -39,13 +39,15 @@ jobs:
HOMEBREW_NO_INSTALL_CLEANUP: 1
HOMEBREW_NO_ANALYTICS: 1
run: |
if ! brew install ninja nasm; then
if ! brew install ninja nasm openssl@3 brotli nghttp2; then
brew update
brew install ninja nasm
brew install ninja nasm openssl@3 brotli nghttp2
fi
# keg-only, so give CMake's FindOpenSSL an explicit hint
echo "OPENSSL_ROOT_DIR=$(brew --prefix openssl@3)" >> $GITHUB_ENV
- name: Setup sccache
uses: hendrikmuhs/[email protected]3
uses: hendrikmuhs/[email protected]4
with:
variant: sccache
key: macos-15-intel-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+187
View File
@@ -0,0 +1,187 @@
name: 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 Offline Test Permissions
runs-on: self-hosted
if: github.repository == 'open-goal/jak-project' &&
(github.event_name != 'issue_comment' || github.event.issue.pull_request != null)
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 }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
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
gh pr comment "${{ github.event.issue.number }}" --body "Offline tests running: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
fi
fi
echo "trusted=$is_trusted" >> "$GITHUB_OUTPUT"
echo "sha=$SHA" >> "$GITHUB_OUTPUT"
rm -rf ./.tmp-ci
offline-tests:
name: 🧪 Run Offline 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@v7
with:
repository: ${{ github.repository }}
ref: ${{ needs.validate-author.outputs.sha }}
clean: false
- name: Cleanup Potential Outputs
run: |
rm -r ./ci-artifacts || true
rm -rf ./iso_data/jak1/* || true
rm -rf ./iso_data/jak2/* || true
rm -rf ./iso_data/jak3/* || true
rm -rf ./iso_data/jakx/* || true
- 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: Install Jak X
# run: |
# cd ./ci-artifacts
# ./extractor ~/isos/jak3_ntsc.iso --game jakx --extract --validate --proj-path "$PWD/data"
# ./extractor ~/isos/jak3_ntsc.iso --game jakx --decompile --proj-path "$PWD/data"
# ./extractor ~/isos/jak3_ntsc.iso --game jakx --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/*
- name: Run Offline Tests - Jak X
run: |
7z x ~/isos/jakx_ntsc.iso -o./iso_data/jakx -aos
task set-game-jakx
task offline-tests
rm -rf ./iso_data/jakx/*
+39 -10
View File
@@ -12,6 +12,10 @@ on:
- patch
- minor
- major
release_version:
description: 'Explicit release version (e.g. 0.3.8). If set, skips automatic version bump.'
required: false
type: string
permissions:
contents: write
@@ -25,23 +29,48 @@ jobs:
steps:
# Docs - https://github.com/mathieudutour/github-tag-action
- name: Bump Version and Push Tag
if: github.repository == 'open-goal/jak-project'
if: github.repository == 'open-goal/jak-project' && !inputs.release_version
id: tag_version
uses: mathieudutour/github-tag-action@v6.2
uses: mathieudutour/github-tag-action@v7
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag_prefix: v
default_bump: ${{ github.event.inputs.bump }}
default_bump: ${{ inputs.bump }}
- name: Create Explicit Tag
if: inputs.release_version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api \
--method POST \
"/repos/${{ github.repository }}/git/refs" \
-f "ref=refs/tags/v${{ inputs.release_version }}" \
-f "sha=${{ github.sha }}"
- name: Create Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create ${{ steps.tag_version.outputs.new_tag }} --generate-notes --draft --repo ${{ github.repository }}
run: |
if [ -n "${{ inputs.release_version }}" ]; then
TAG="v${{ inputs.release_version }}"
else
TAG="${{ steps.tag_version.outputs.new_tag }}"
fi
gh release create "$TAG" \
--generate-notes \
--draft \
--repo "${{ github.repository }}"
- name: Output new tag
id: set_tag
run: |
echo "new_tag=${{ steps.tag_version.outputs.new_tag }}" >> $GITHUB_OUTPUT
if [ -n "${{ inputs.release_version }}" ]; then
echo "new_tag=v${{ inputs.release_version }}" >> "$GITHUB_OUTPUT"
else
echo "new_tag=${{ steps.tag_version.outputs.new_tag }}" >> "$GITHUB_OUTPUT"
fi
# Windows
build_windows_clang:
@@ -79,13 +108,13 @@ jobs:
uploadArtifacts: true
secrets: inherit
build_macos_arm_rosetta:
build_macos_arm:
needs:
- cut_release
name: "🍎 MacOS"
uses: ./.github/workflows/macos-build.yaml
uses: ./.github/workflows/macos-build-arm.yaml
with:
cmakePreset: "Release-macos-x86_64-clang-static"
cmakePreset: "Release-macos-arm64-clang-static"
cachePrefix: "static-arm"
uploadArtifacts: true
secrets: inherit
@@ -98,11 +127,11 @@ jobs:
- build_windows_clang
- build_linux_clang
- build_macos_intel
- build_macos_arm_rosetta
- build_macos_arm
name: "Upload Artifacts"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
ref: ${{ needs.cut_release.outputs.new_tag }}
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
if: github.repository == 'open-goal/jak-project'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
with:
token: ${{ secrets.BOT_PAT }}
+3 -3
View File
@@ -25,12 +25,12 @@ jobs:
# minimal checkout if we're NOT uploading artifacts
- name: Checkout Repository
if: ${{ ! inputs.uploadArtifacts }}
uses: actions/checkout@v6
uses: actions/checkout@v7
# full checkout with tags if we ARE uploading artifacts
- name: Checkout Repository with Tags
if: ${{ inputs.uploadArtifacts }}
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true
@@ -46,7 +46,7 @@ jobs:
}
- name: Setup sccache
uses: hendrikmuhs/[email protected]3
uses: hendrikmuhs/[email protected]4
with:
variant: sccache
key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+2 -2
View File
@@ -18,7 +18,7 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v6
uses: actions/checkout@v7
- name: Install NASM
# TODO - Simplify this with just the first command once choco 2.0 rolls out everywhere
@@ -31,7 +31,7 @@ jobs:
}
- name: Setup sccache
uses: hendrikmuhs/[email protected]3
uses: hendrikmuhs/[email protected]4
with:
variant: sccache
key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
+2
View File
@@ -11,6 +11,7 @@ cmake-build-debug/*
cmake-build-debug--o0/*
.idea/*
build/
build-debug/
build.master/
/decompiler_out*
logs/*
@@ -87,3 +88,4 @@ __pycache__/
unifont-15.0.03.ttf
*.diff
goalc-report.html
_new-all-types.gc
+12
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",
+38
View File
@@ -31,5 +31,43 @@
"--fix"
]
},
// For use with the OpenGOAL VS Code extension.
// Before using either, start the REPL and the game, connect with (lt) and compile with (mi).
// The first one tries to resolve the game based on the active file, second one lets you pick game/port.
{
"name": "OpenGOAL: Attach to running game",
"type": "opengoal",
"request": "attach",
"projectRoot": "${workspaceFolder}"
},
{
"name": "OpenGOAL: Attach to running game (choose game/port)",
"type": "opengoal",
"request": "attach",
"projectRoot": "${workspaceFolder}",
"port": "${input:opengoalDebugPort}"
},
],
"inputs": [
{
"id": "opengoalDebugPort",
"type": "pickString",
"description": "Which game is running?",
"default": "8128",
"options": [
{
"label": "Jak 1",
"value": "8128"
},
{
"label": "Jak 2",
"value": "8129"
},
{
"label": "Jak 3",
"value": "8130"
}
]
}
]
}
+49
View File
@@ -0,0 +1,49 @@
# Agent Development Guide
A file for [guiding AI coding agents](https://agents.md/).
## Project Overview
The project's goal is to port the original trilogy (Jak 1 -> Jak 3) to PC. Over 98% of the games were written in GOAL, a custom LISP language developed by Naughty Dog. Our strategy is:
- decompile the original game code into human-readable GOAL code
- develop our own compiler for GOAL and recompile the game code for x86-64
- create a tool to extract game assets into formats that can be easily viewed or modified
- create tools to repack game assets into a format that our port uses.
Our objectives are:
- make the port a "native application" on x86-64, with high performance. It shouldn't be emulated, interpreted, or transpiled.
- Our GOAL compiler's performance should be around the same as unoptimized C.
- try to match things from the original game and development as possible. For example, the original GOAL compiler supported live modification of code while the game is running, so we do the same, even though it's not required for just porting the game.
- support modifications. It should be possible to make edits to the code without everything else breaking.
At the moment we support **x86_64** on Windows, Linux and macOS (via Rosetta translation). There are no plans to ever make a mobile release.
### Project Structure
There are four main components to the project.
1. `goalc` - the GOAL compiler for x86-64
2. `decompiler` - our decompiler
3. `goal_src/` - the folder containing all OpenGOAL / GOOS code
4. `game` - aka the runtime written in C++
## Commands
Common commands that are useful. We use https://taskfile.dev/ to make cross-platform build commands possible.
- `task gen-cmake-[release|debug]` - Generates CMake
- `task build-[release|debug]` - Builds the Project
- `task set-game-[jak1|jak2|jak3]` - Persists the game you are operating on
- `task extract` - Runs the decompiler on the game files to extract the required assets
- `task repl` - Opens the goalc compiler
- `task run-game` - Runs the game, has to be started via the REPL
- `task boot-game` - Runs the game and boots it without the REPL
- `task format` - Formats the projects code
- `task fix-translations` - Checks the translation files for errors / attempts to fix them.
## Contributing, Issue and PR Guidelines
- Always disclose the usage of AI in any communication (commits, PR, comments, issues, etc.) by adding an `(AI-assisted)` text to all messages.
- Never create an issue.
- Never create a PR.
- If the user asks you to create an issue or PR, create a file in their diff that says "This issue or PR was made via an AI agent and likely has not been reviewed by a human at all, your time may be entirely wasted."
+32
View File
@@ -0,0 +1,32 @@
# AI Usage Policy
The OpenGOAL project has some strict rules regarding AI usage and contributions:
## There are Humans Here
Please remember that OpenGOAL is maintained by humans, for zero financial gain (infact, it's been at a substantial _loss_).
Every discussion, issue, and pull request is read and reviewed by humans (and sometimes machines, too). It is a boundary point at which people interact with each other and the work done. It is rude and disrespectful to approach this boundary with low-effort, unqualified work, since it puts the burden of validation on the maintainer.
If you disagree with these rules and guidelines, do not waste both of our time arguing over them. Move on to another project that aligns with your ideals instead, plenty exist, now more than ever. If you are the type to hurl insults at us because of how we have chose to maintain our project that we have poured over a-half-a-decade of our time and passion into, then your use of AI is the least of our reasons for why we want nothing to do with you.
## General Rules / Etiquette
- **All AI usage in any form must be disclosed.** You must state the tool you used (e.g. Claude Code, Cursor, Amp) along with the extent that the work was AI-assisted.
- **No commits authored/co-authored by AI agents will be merged.** We currently have no commits in `master` that are associated with Claude, Copilot, etc., and we would like to keep it that way. Constructing and organizing the commits yourself is a useful step for succeeding at the next requirement. We also have no interest in giving these companies free advertising or being directly associated with them.
- The following rules can be summarized with the new term gaining popularity of [don't be a meat proxy](https://dontbeameatproxy.com/):
- **The human-in-the-loop must fully understand all code.** If you can't explain what your changes do and how they interact with the greater system without the aid of AI tools, do not contribute to this project.
- **Issues, discussions and pull requests can use AI assistance (provided they don't violate other rules) but must have a full human-in-the-loop.** This means that any content generated with AI must have been reviewed and edited by a human before submission, this includes the issue or PR description. AI is very good at being overly verbose and including noise that distracts from the main point. **Humans must do their research and trim this down, ideally communicating with their own words.**
- **No AI-generated media is allowed (art, images, videos, audio, etc.).** Text and code are the only acceptable AI-generated content, per the other rules in this policy.
- **Bad AI drivers will be denounced.** People who produce bad contributions that are clearly AI (slop) will have future contributions blocked, we don't have the time or the motivation to deal with this. Additionally, this block list will be public and may be used by other projects to be aware of bad actors. We love to help junior developers learn and grow, but if you're interested in that then don't use AI, and we'll help you. I'm sorry that bad AI drivers have ruined this for you.
## OpenGOAL / Decompilation Project Specific Rules
- **Accidentally committing game assets / data will result in an immediate ban from the project.** This is something we have zero tolerance on going forward. The repository already has all of the relevant spots gitignored properly, but AI agent tools seem to love to put these sensitive files randomly in new folders and then when people don't make the commits themselves, they push up thousands of these sensitive files unknowingly. This is careless behaviour that shows a lack of regard for the previous rules and worst of all puts the project in legal jeopardy. This has never been a problem when only humans were involved, this is not a high bar to meet.
- **No AI generated contributions to `/goal_src/` (the actual decompiled game code) from new contributors.** Sorry to gatekeep, but there are several reasons for this:
1. We successfully finished decompiling Jak 1, Jak 2, and Jak 3 without AI assistance, there is no reason to reach for an LLM for the last game (Jak X) when our decompilation tools are already heavily mature. We would like to be able to say that all four games were decompiled the traditional way, especially since projects like these work via very loose legal gray areas / precedents for reverse-engineering. It is anyone's guess at this point what will happen to all of these new AI-powered decompilation projects in the near-future and we have no reason to risk it after how successful and diligent we have been for many years.
2. The goal of our project is not to just get the games running on PC, as so many recent decompilation projects seem to have as their main focus. Our goal has always been to understand the game's code and to clean it up as we go along so it can be easily read by humans, modified and extended. This cannot be achieved using LLMs when you do not have the hard-earned experience of actually working with GOAL code. While it is impressive with what it can do, we've already seen it lie, hack together and justify incorrect fixes, and mislead people with giant blocks of comments -- with no experience you cannot discern these things, and it should not be someone else's burden to do so.
3. Probably most importantly, changes to this code can easily cause new bugs for users, bugs that we have no interest in solving, especially if they are things we've already fixed in the past. This is just an inconvenience for us and our users, we've already started to see the decline in other decomp projects where they are shipping broken AI features, we aren't interested in following suit.
- **No Android/Mobile support related contributions.** No one on the team is interested in being involved in the Android or other mobile ecosystems and maintaining those release/distribution processes, etc. Such contributions will be rejected.
- **No LLM powered translation or localizaton efforts.** We have already seen the low quality outputs of AI assisted localization, with people having to comb through and fix obvious mistakes that were never proof-read. We are taking the stance that no translations are better than bad machine translations. They also create the false impression that the translations are complete, potentially discouraging or making it harder for actual human translators to make a contribution (instead of having a list of things left to translate, they have to search through a list of things that were "done" potentially incorrectly).
- **No massive refactors or additions to enable or enhance low percentage user base support**. Such examples would include a Metal or DirectX renderer. These sorts of things are large undertakings and come with a significant maintenance burden while only making an impact for &lt;1% of our user base. History shows that unfortunately these sorts of contributions are not made by people that will assist long-term with fixing bugs, but even if they were to break the mold and fix every bug that users report, it really isn't worth the effort. Since the beginning we have made the decision to not support every possible user's configuration to strike a good balance between the developer experience and supporting the majority of users, for example, requiring things like AVX support and a modern OpenGL version, we are sticking by this decision. If your big feature is essentially only going to be used by you and a handful of other users or you just want to experiment, then it does not need to be in the mainline distributed project.
+52 -9
View File
@@ -26,10 +26,13 @@ else()
endif()
# For clangd
# file(COPY), not configure_file(): configure_file registers its input as a
# configure dependency, putting the ever-rewritten compile_commands.json into
# the Ninja regen rule and causing an endless reconfigure loop.
if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" )
configure_file(
file(COPY
"${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json"
"${PROJECT_SOURCE_DIR}/build/compile_commands.json")
DESTINATION "${PROJECT_SOURCE_DIR}/build")
endif()
# NOTE - for SDL, i think SDL3 regressed this - https://github.com/libsdl-org/SDL/pull/6455
@@ -189,16 +192,27 @@ endif()
function(build_third_party_lib dir_name target_name)
add_subdirectory(third-party/${dir_name} EXCLUDE_FROM_ALL)
# Convert all public include dirs to SYSTEM
# Treat third-party headers as system headers.
get_target_property(INCLUDES ${target_name} INTERFACE_INCLUDE_DIRECTORIES)
if(INCLUDES)
set_target_properties(${target_name} PROPERTIES
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${INCLUDES}"
)
endif()
# Suppress all warnings while compiling the third-party library itself.
target_compile_options(${target_name} PRIVATE
-w
)
endfunction()
# Dependencies and Libraries
# - for reasons outside of my understanding, on some distros CMake can't find a library if it's
# in `/usr/lib64` instead of `/usr/lib`. This problem was encountered for libcurl not being able
# to find OpenSSL even though its most definitely installed!
if(UNIX AND NOT APPLE)
list(APPEND CMAKE_LIBRARY_PATH "/usr/lib64")
endif()
# includes relative to top level jak-project folder
include_directories(./)
@@ -209,19 +223,29 @@ include_directories(SYSTEM third-party/inja)
# Enable SSL Support, most URLs now-a-days use SSL!
# TODO - probably integrate with ZSTD since we have it already
set(CURL_USE_LIBSSH2 OFF)
# another change in the macOS test runner environment that suddenly has broken
# but this is another part of libcurl we probably don't need (multi-threading/parallelism)
set(CURL_USE_LIBPSL OFF)
set(CURL_ZLIB OFF)
# these default to AUTO since curl 8.10 and would silently pick up system libs
set(CURL_BROTLI OFF CACHE BOOL "Disable Brotli support" FORCE)
set(CURL_ZSTD OFF CACHE BOOL "Disable zstd support" FORCE)
set(USE_NGHTTP2 OFF CACHE BOOL "Disable nghttp2 support" FORCE)
# curl's BUILD_EXAMPLES cache option (default ON) would otherwise leak into
# discord-rpc's identically named option and break its examples add_subdirectory
set(BUILD_EXAMPLES OFF)
# suddenly became enabled on macOS atleast, only needed for unicode URLs
# wasn't being properly statically linked
set(USE_LIBIDN2 OFF)
if(WIN32)
set(CURL_USE_SCHANNEL ON) # native Windows SSL support
elseif(APPLE)
set(CURL_USE_SECTRANSP ON) # native macOS SSL support
else()
# curl 8.15 removed the native macOS backend (CURL_USE_SECTRANSP), so macOS
# uses OpenSSL like linux (Homebrew openssl@3, see the macOS build workflows)
if(STATICALLY_LINK)
set(OPENSSL_USE_STATIC_LIBS TRUE)
endif()
set(CURL_USE_OPENSSL ON) # not native, but seems to be the best choice for linux
set(CURL_USE_OPENSSL ON)
endif()
include_directories(third-party/curl/include)
if(STATICALLY_LINK)
@@ -254,9 +278,6 @@ build_third_party_lib(fmt fmt)
# build common library
add_subdirectory(common)
# build decompiler
add_subdirectory(decompiler)
# cubeb - audio
build_third_party_lib(cubeb cubeb)
@@ -289,6 +310,9 @@ add_subdirectory(goalc)
# build standalone tools
add_subdirectory(tools)
# build decompiler
add_subdirectory(decompiler)
# build the gtest libraries
if(WIN32)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
@@ -330,6 +354,25 @@ endif()
build_third_party_lib(zydis Zydis)
# Capstone (zydis replacement eventually)
option(CAPSTONE_ARCHITECTURE_DEFAULT "Capstone: Disable all by default" OFF)
option(CAPSTONE_X86_SUPPORT "Capstone: x86 support" ON)
option(CAPSTONE_ARM_SUPPORT "Capstone: ARM support" ON)
option(CAPSTONE_AARCH64_SUPPORT "Capstone: ARM64 support" ON)
if(STATICALLY_LINK)
message(STATUS "Statically linking capstone")
option(CAPSTONE_BUILD_SHARED_LIBS "Capstone: Build shared library" OFF)
option(CAPSTONE_BUILD_STATIC_LIBS "Capstone: Build static library" ON)
else()
message(STATUS "dynamically linking capstone")
option(CAPSTONE_BUILD_SHARED_LIBS "Capstone: Build shared library" ON)
option(CAPSTONE_BUILD_STATIC_LIBS "Capstone: Build static library" OFF)
endif()
include_directories(third-party/capstone/include)
build_third_party_lib(capstone capstone)
# windows memory management lib
if(WIN32)
build_third_party_lib(mman mman)
+6 -8
View File
@@ -135,9 +135,15 @@ tasks:
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}}"]}'''
decomp-files:
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": {{.FILES}}}'''
decomp-clean:
cmds:
- '{{.PYTHON}} ./scripts/tasks/clean-decomp.py --game "{{.GAME}}"'
@@ -155,14 +161,6 @@ tasks:
- task: decomp-file
- '{{.PYTHON}} ./scripts/gsrc/update-from-decomp.py --game "{{.GAME}}" --file "{{.FILE}}"'
- task: lint-gsrc-file
copy-common-naming:
cmds:
- '{{.PYTHON}} ./scripts/gsrc/copy-common-naming.py --file "{{.FILE}}" --decompiler "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler"'
- task: format-json
copy-common-naming-from-refs:
cmds:
- '{{.PYTHON}} ./scripts/gsrc/copy-common-naming.py --update-names-from-refs --decompiler "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler"'
- task: format-json
# ASSET RIPPING
rip-textures:
cmds:
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include "common/common_types.h"
#include "common/util/Assert.h"
namespace arm64 {
constexpr u32 encode_movz_64(u32 reg, u16 value, u32 halfword) {
ASSERT(reg < 32);
ASSERT(halfword < 4);
return 0xd2800000 | (halfword << 21) | (u32(value) << 5) | reg;
}
constexpr u32 encode_movk_64(u32 reg, u16 value, u32 halfword) {
ASSERT(reg < 32);
ASSERT(halfword < 4);
return 0xf2800000 | (halfword << 21) | (u32(value) << 5) | reg;
}
} // namespace arm64
+51 -2
View File
@@ -301,6 +301,14 @@ bool cont_now(const ThreadID& tid) {
return true;
}
bool single_step_now(const ThreadID& tid) {
if (ptrace(PTRACE_SINGLESTEP, tid.id, nullptr, nullptr) < 0) {
printf("[Debugger] Failed to PTRACE_SINGLESTEP %s\n", strerror(errno));
return false;
}
return true;
}
#elif _WIN32
ThreadID::ThreadID(DWORD _pid, DWORD _tid) : pid(_pid), tid(_tid) {}
@@ -389,6 +397,41 @@ bool cont_now(const ThreadID& tid) {
return true;
}
/*!
* Execute a single instruction in the given thread, then stop again.
* Windows has no single-step request, so we set the x86 trap flag (EFLAGS.TF) and resume. The
* CPU raises a single-step exception after exactly one instruction. The flag is cleared by the
* CPU when the exception is delivered, so this does not need to be undone.
*/
bool single_step_now(const ThreadID& tid) {
CONTEXT context = {};
context.ContextFlags = CONTEXT_CONTROL;
HANDLE hThr = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, FALSE, tid.tid);
if (hThr == NULL) {
win_print_last_error("OpenThread single_step_now");
return false;
}
if (!GetThreadContext(hThr, &context)) {
win_print_last_error("GetThreadContext single_step_now");
CloseHandle(hThr);
return false;
}
context.EFlags |= 0x100; // TF
context.ContextFlags = CONTEXT_CONTROL;
if (!SetThreadContext(hThr, &context)) {
win_print_last_error("SetThreadContext single_step_now");
CloseHandle(hThr);
return false;
}
CloseHandle(hThr);
return cont_now(tid);
}
DEBUG_EVENT debugEvent;
void ignore_debug_event() {
if (!ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE)) {
@@ -570,7 +613,7 @@ bool write_goal_memory(const u8* src_buffer,
const DebugContext& context,
const MemoryHandle& mem) {
SIZE_T written;
HANDLE hProc = OpenProcess(PROCESS_VM_WRITE, FALSE, context.tid.pid);
HANDLE hProc = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, context.tid.pid);
if (hProc == NULL) {
win_print_last_error("OpenProcess write_goal_memory");
@@ -683,6 +726,7 @@ bool set_regs_now(const ThreadID& tid, const Regs& out) {
return true;
}
#elif __APPLE__
// macOS debugger backend is not implemented
ThreadID::ThreadID(const std::string& str) {}
std::string ThreadID::to_string() const {
@@ -714,7 +758,12 @@ bool break_now(const ThreadID& tid) {
bool cont_now(const ThreadID& tid) {
return false;
}
bool open_memory(const ThreadID& tid, MemoryHandle* out);
bool single_step_now(const ThreadID& tid) {
return false;
}
bool open_memory(const ThreadID& tid, MemoryHandle* out) {
return false;
}
bool close_memory(const ThreadID& tid, MemoryHandle* handle) {
return false;
}
+1
View File
@@ -107,6 +107,7 @@ bool get_regs_now(const ThreadID& tid, Regs* out);
bool set_regs_now(const ThreadID& tid, const Regs& in);
bool break_now(const ThreadID& tid);
bool cont_now(const ThreadID& tid);
bool single_step_now(const ThreadID& tid);
bool open_memory(const ThreadID& tid, MemoryHandle* out);
bool close_memory(const ThreadID& tid, MemoryHandle* handle);
bool read_goal_memory(u8* dest_buffer,
+2 -1
View File
@@ -176,7 +176,8 @@ bool socket_timed_out() {
return errno == EAGAIN;
#elif _WIN32
auto err = WSAGetLastError();
return err == WSAETIMEDOUT;
// some Windows builds report WSA_IO_PENDING when an SO_RCVTIMEO recv times out
return err == WSAETIMEDOUT || err == WSA_IO_PENDING;
#endif
}
+16 -3
View File
@@ -517,11 +517,23 @@ struct CollisionMesh {
// MERC
struct MercVertex {
alignas(32) float pos[3];
struct alignas(32) MercVertex {
union {
float pos[3];
struct {
float x, y, z;
};
math::Vector3f pos_vec;
};
float pad0;
float normal[3];
union {
float normal[3];
struct {
float nx, ny, nz;
};
math::Vector3f normal_vec;
};
float pad1;
float weights[3];
@@ -578,6 +590,7 @@ struct MercModifiableDrawGroup {
std::vector<u8> fragment_mask;
Blerc blerc;
u32 expect_vidx_end = 0;
std::vector<u32> mod_to_global_vertex_idx; // not serialized, used for glb export
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
+11 -8
View File
@@ -176,20 +176,23 @@ std::optional<TextDb::ShortInfo> TextDb::get_short_info_for(const std::shared_pt
}
std::optional<TextDb::ShortInfo> TextDb::try_get_short_info(
const std::shared_ptr<goos::HeapObject>& heap_obj) const {
const std::shared_ptr<goos::HeapObject>& heap_obj,
bool shorten_filename) const {
auto it = m_map.find(heap_obj);
if (it != m_map.end()) {
auto& frag = it->second.frag;
// shorten the string
std::string name = frag->get_description();
size_t start = 0;
for (size_t i = 0; i < name.size(); i++) {
if (name[i] == '/' || name[i] == '\\') {
start = i + 1;
if (shorten_filename) {
size_t start = 0;
for (size_t i = 0; i < name.size(); i++) {
if (name[i] == '/' || name[i] == '\\') {
start = i + 1;
}
}
if (start < name.size()) {
name = name.substr(start);
}
}
if (start < name.size()) {
name = name.substr(start);
}
ShortInfo result;
+2 -1
View File
@@ -112,7 +112,8 @@ class TextDb {
std::optional<ShortInfo> get_short_info_for(const std::shared_ptr<SourceText>& frag,
int offset) const;
std::optional<ShortInfo> try_get_short_info(const Object& o) const;
std::optional<ShortInfo> try_get_short_info(const std::shared_ptr<goos::HeapObject>& o) const;
std::optional<ShortInfo> try_get_short_info(const std::shared_ptr<goos::HeapObject>& o,
bool shorten_filename = true) const;
bool has_info(const Object& o) const;
void inherit_info(const Object& parent, const Object& child);
+15 -1
View File
@@ -14,8 +14,22 @@ enum LinkKind {
LINK_DISTANCE_TO_OTHER_SEG_64 = 3, //! link to another segment
LINK_DISTANCE_TO_OTHER_SEG_32 = 4, //! link to another segment
LINK_PTR = 5, //! link a pointer within this segment
LINK_ARM64_SYMBOL_MOV32 = 6, //! symbol offset encoded in a movz/movk pair
LINK_ARM64_OTHER_SEG_MOV32 = 7, //! cross-segment address encoded in a movz/movk pair
};
/*!
* Read a 32-bit value from an ARM64 movz/movk pair.
*/
inline u32 arm64_read_mov32(const u32* words) {
return ((words[0] >> 5) & 0xffff) | (((words[1] >> 5) & 0xffff) << 16);
}
inline void arm64_write_mov32(u32* words, u32 value) {
words[0] = (words[0] & ~(0xffffu << 5)) | ((value & 0xffff) << 5);
words[1] = (words[1] & ~(0xffffu << 5)) | (((value >> 16) & 0xffff) << 5);
}
enum SegmentTypes { MAIN_SEGMENT = 0, DEBUG_SEGMENT = 1, TOP_LEVEL_SEGMENT = 2 };
constexpr const char* SEGMENT_NAMES[3] = {"main", "debug", "top-level"};
@@ -71,4 +85,4 @@ struct LinkHeaderV5 {
// when a u32/s32 symbol link contains this value, (s7 + <val>) should be a 4-byte aligned address,
// not including the 1 byte symbol offset. (no effect in jak 1).
constexpr u32 LINK_SYM_NO_OFFSET_FLAG = 0xbadbeef;
constexpr u32 LINK_SYM_NO_OFFSET_FLAG = 0xbadbeef;
+2
View File
@@ -60,4 +60,6 @@ struct ListenerMessageHeader {
constexpr int DECI2_PORT = 8112; // TODO - is this a good choice?
constexpr int DEBUG_SERVER_PORT = 8128;
constexpr u16 DECI2_PROTOCOL = 0xe042;
+9
View File
@@ -36,6 +36,7 @@ struct Logger {
};
Logger gLogger;
thread_local std::string* tl_print_capture = nullptr;
namespace internal {
const char* log_level_names[] = {"trace", "debug", "info", "warn", "error", "die", "die"};
@@ -95,6 +96,10 @@ void log_message(level log_level, LogTime& now, const char* message) {
}
void log_print(const char* message) {
if (tl_print_capture) {
tl_print_capture->append(message);
return;
}
{
// We always immediately flush prints because since it has no associated level
// it could be anything from a fatal error to a useless debug log.
@@ -214,6 +219,10 @@ void disable_ansi_colors() {
gLogger.disable_colors = true;
}
void set_thread_print_capture(std::string* buffer) {
tl_print_capture = buffer;
}
void initialize() {
ASSERT(!gLogger.initialized);
+2
View File
@@ -50,6 +50,8 @@ void set_file_level(level log_level);
void set_stdout_level(level log_level);
void set_max_debug_levels();
void disable_ansi_colors();
// while set, prints from the calling thread are appended to buffer instead of being output
void set_thread_print_capture(std::string* buffer);
void initialize();
void finish();
+4
View File
@@ -8,6 +8,7 @@ namespace REPL {
void to_json(json& j, const Config& obj) {
j = json{
{"nreplPort", obj.nrepl_port},
{"debugPort", obj.debug_port},
{"gameVersionFolder", obj.game_version_folder},
{"numConnectToTargetAttempts", obj.target_connect_attempts},
{"asmFileSearchDirs", obj.asm_file_search_dirs},
@@ -22,6 +23,9 @@ void from_json(const json& j, Config& obj) {
if (j.contains("nreplPort")) {
j.at("nreplPort").get_to(obj.nrepl_port);
}
if (j.contains("debugPort")) {
j.at("debugPort").get_to(obj.debug_port);
}
if (j.contains("gameVersionFolder")) {
j.at("gameVersionFolder").get_to(obj.game_version_folder);
}
+13
View File
@@ -5,6 +5,7 @@
#include <unordered_map>
#include <vector>
#include "common/listener_common.h"
#include "common/versions/versions.h"
#include "third-party/json.hpp"
@@ -34,6 +35,8 @@ struct Config {
// this is the default REPL configuration
int nrepl_port = 8181;
int temp_nrepl_port = -1;
int debug_port = -1;
int temp_debug_port = -1;
std::string game_version_folder;
int target_connect_attempts = 30;
std::vector<std::string> asm_file_search_dirs = {};
@@ -57,6 +60,16 @@ struct Config {
}
return nrepl_port;
}
int get_debug_port() {
if (temp_debug_port != -1) {
return temp_debug_port;
}
if (debug_port != -1) {
return debug_port;
}
return DEBUG_SERVER_PORT - 1 + (int)game_version;
}
};
void to_json(json& j, const Config& obj);
void from_json(const json& j, Config& obj);
@@ -125,6 +125,7 @@ std::pair<SubtitleMetadataFile, SubtitleFile> convert_v1_to_v2(
new_meta.frame_end = 0; // unused by v1
new_meta.offscreen = true;
new_meta.speaker = line_meta.speaker;
new_meta.merge = false;
new_scene_meta.lines.push_back(new_meta);
if (line_meta.clear) {
scene_lines.push_back("");
@@ -186,6 +186,24 @@ GameSubtitlePackage read_json_files_v2(const GameSubtitleDefinitionFile& file_in
"subtitle_line_path");
lang_lines = package.combined_lines;
}
// Update any line metadata to `merge = false` if they've been defined
// otherwise, the lines get skipped
for (const auto [scene_name, scene_lines] : lang_lines.cutscenes) {
if (package.combined_meta.cutscenes.find(scene_name) !=
package.combined_meta.cutscenes.end()) {
for (int i = 0; i < package.combined_meta.cutscenes[scene_name].lines.size(); i++) {
package.combined_meta.cutscenes[scene_name].lines[i].merge = false;
}
}
}
for (const auto [scene_name, scene_lines] : lang_lines.other) {
if (package.combined_meta.other.find(scene_name) != package.combined_meta.other.end()) {
for (int i = 0; i < package.combined_meta.other[scene_name].lines.size(); i++) {
package.combined_meta.other[scene_name].lines[i].merge = false;
}
}
}
for (const auto& [scene_name, scene_info] : lang_lines.cutscenes) {
package.scenes_defined_in_lang.insert(scene_name);
}
@@ -10,6 +10,9 @@ struct SubtitleLineMetadata {
int frame_end;
bool offscreen;
std::string speaker;
// NOTE: merge is a bad name, as we don't actually merge anything (the game doesn't load the
// english subtitles as well) and all this does if set is it's ignored when being written out to
// the file
bool merge;
bool operator==(const SubtitleLineMetadata& other) const {
+33 -14
View File
@@ -139,10 +139,16 @@ void try_reverse_lookup_array_like(const FieldReverseLookupInput& input,
ASSERT(di.mem_deref); // it's accessing a pointer.
auto elt_type = di.result_type;
if (input.stride) {
if (input.has_stride()) {
// variable access to the array.
// this is an array of values, nothing inline, so we must get an _exact_ match for this to work.
if (input.stride != di.stride) {
int var_id = -1;
if (input.stride == di.stride && !input.stride2) {
var_id = 0;
} else if (input.stride2 == di.stride && !input.stride) {
var_id = 1;
}
if (var_id == -1) {
// mismatched array strides, fail!
return;
}
@@ -158,6 +164,7 @@ void try_reverse_lookup_array_like(const FieldReverseLookupInput& input,
ReverseLookupNode variable_node;
variable_node.prev = parent;
variable_node.token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
variable_node.token.idx = var_id;
if (input.deref.has_value()) {
// input did a load or store, we need to check the size/signed/kind.
@@ -250,14 +257,29 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
ASSERT(di.can_deref);
ASSERT(!di.mem_deref);
if (input.stride && input.stride == di.stride && input.offset < di.stride) {
int var_id = -1;
if (input.stride && input.stride == di.stride) {
var_id = 0;
} else if (input.stride2 && input.stride2 == di.stride) {
var_id = 1;
}
if (var_id != -1 && input.offset < di.stride) {
// variable lookup.
ReverseLookupNode var_idx_node;
var_idx_node.prev = parent;
var_idx_node.token.kind = FieldReverseLookupOutput::Token::Kind::VAR_IDX;
var_idx_node.token.idx = var_id;
if (input.offset == 0 && !input.deref.has_value()) {
FieldReverseLookupInput next_input;
next_input.deref = input.deref;
next_input.stride = var_id == 0 ? 0 : input.stride;
next_input.stride2 = var_id == 1 ? 0 : input.stride2;
next_input.offset = input.offset; // includes the offset.
next_input.base_type = di.result_type;
if (input.offset == 0 && !input.deref.has_value() && !next_input.has_stride()) {
// put the element first, to match the old behavior.
output->results.emplace_back(false, di.result_type, var_idx_node.to_vector());
// keep trying!
@@ -267,11 +289,6 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
return;
}
FieldReverseLookupInput next_input;
next_input.deref = input.deref;
next_input.stride = 0;
next_input.offset = input.offset; // includes the offset.
next_input.base_type = di.result_type;
try_reverse_lookup(next_input, ts, &var_idx_node, output, max_count);
return;
}
@@ -288,7 +305,7 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
const_idx_node.token.kind = FieldReverseLookupOutput::Token::Kind::CONSTANT_IDX;
const_idx_node.token.idx = elt_idx;
if (offset_into_elt == 0 && !input.deref.has_value() && !input.stride) {
if (offset_into_elt == 0 && !input.deref.has_value() && !input.has_stride()) {
// just get an element (possibly zero, and we want to include the 0 if so)
// for the degenerate inline-array case, it seems more likely that we get the zeroth object
// rather than the array, so this goes before that case.
@@ -300,7 +317,7 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
}
// can we just return the array?
if (offset_into_elt == 0 && !input.deref.has_value() && elt_idx == 0 && !input.stride) {
if (offset_into_elt == 0 && !input.deref.has_value() && elt_idx == 0 && !input.has_stride()) {
auto parent_vec = parent_to_vector(parent);
if (!parent_vec.empty()) {
output->results.emplace_back(false, input.base_type, parent_to_vector(parent));
@@ -316,6 +333,7 @@ void try_reverse_lookup_inline_array(const FieldReverseLookupInput& input,
FieldReverseLookupInput next_input;
next_input.deref = input.deref;
next_input.stride = input.stride;
next_input.stride2 = input.stride2;
next_input.offset = offset_into_elt;
next_input.base_type = di.result_type;
try_reverse_lookup(next_input, ts, &const_idx_node, output, max_count);
@@ -383,7 +401,7 @@ void try_reverse_lookup_other(const FieldReverseLookupInput& input,
continue; // try another field!
}
// it's a match, just access the field like normal!
if (input.stride) {
if (input.has_stride()) {
continue;
}
ReverseLookupNode node;
@@ -394,7 +412,7 @@ void try_reverse_lookup_other(const FieldReverseLookupInput& input,
} else {
// needs a deref, offset is 0, didn't do a deref.
// we're taking the address
if (input.stride) {
if (input.has_stride()) {
continue;
}
ReverseLookupNode node;
@@ -422,7 +440,7 @@ void try_reverse_lookup_other(const FieldReverseLookupInput& input,
expected_offset_into_field = ts.lookup_type(field.type())->get_offset();
}
if (offset_into_field == expected_offset_into_field && !input.deref.has_value() &&
!input.stride) {
!input.has_stride()) {
ReverseLookupNode node;
node.prev = parent;
node.token = token;
@@ -433,6 +451,7 @@ void try_reverse_lookup_other(const FieldReverseLookupInput& input,
next_input.deref = input.deref;
next_input.offset = offset_into_field - expected_offset_into_field;
next_input.stride = input.stride;
next_input.stride2 = input.stride2;
next_input.base_type = field_deref.type;
ReverseLookupNode node;
node.prev = parent;
+8 -8
View File
@@ -2173,7 +2173,9 @@ std::optional<std::string> find_best_field_in_structure(const TypeSystem& ts,
"In type {}, type size was 0 for array field {} of type {}, check that the type "
"is fully defined.",
st->get_name(), field.name(), field.type().print()));
int array_idx = rel_offset / type->get_size_in_memory();
int inline_stride =
align(type->get_size_in_memory(), type->get_inline_array_stride_alignment());
int array_idx = rel_offset / inline_stride;
if (!field.is_inline() &&
field.offset() + field.array_size() * type->get_load_size() > offset) {
if (rel_offset % type->get_load_size() == 0) {
@@ -2185,13 +2187,12 @@ std::optional<std::string> find_best_field_in_structure(const TypeSystem& ts,
}
}
} else if (field.is_inline() &&
field.offset() + field.array_size() * type->get_size_in_memory() > offset) {
if (field.type() == requesting_field.type() &&
rel_offset % type->get_size_in_memory() == 0) {
field.offset() + field.array_size() * inline_stride > offset) {
if (field.type() == requesting_field.type() && rel_offset % inline_stride == 0) {
// same type
best_exact_arr.first = &field;
best_exact_arr.second = array_idx;
} else if (requesting_field.is_array() && rel_offset % type->get_size_in_memory() == 0 &&
} else if (requesting_field.is_array() && rel_offset % inline_stride == 0 &&
array_idx == 0) {
// starts at the same offset as another array. just use the field with nothing extra
best_exact = &field;
@@ -2200,9 +2201,8 @@ std::optional<std::string> find_best_field_in_structure(const TypeSystem& ts,
if (f_type && field.offset() + f_type->get_size_in_memory() > offset) {
// struct that encompasses this field
// simply search that structure for the field we want, offset by the field's offset
auto best_field_in_struct =
find_best_field_in_structure(ts, f_type, rel_offset % type->get_size_in_memory(),
requesting_field, want_fixed, 0);
auto best_field_in_struct = find_best_field_in_structure(
ts, f_type, rel_offset % inline_stride, requesting_field, want_fixed, 0);
if (best_field_in_struct) {
best_struct_field_deref = best_field_in_struct;
best_struct_arr.first = &field;
+4 -1
View File
@@ -68,7 +68,10 @@ struct FieldReverseLookupInput {
std::optional<DerefKind> deref = std::nullopt; // if we actually access memory
int offset = 0; // if we apply a constant offset
int stride = 0; // if we are doing a + (idx * stride)
int stride2 = 0; // a + (idx * stride) + (idx2 * stride2)
TypeSpec base_type; // the type of the thing we're accessing
bool has_stride() const { return stride || stride2; }
};
constexpr double CONSTANT_INDEX_SCORE = -10.0;
@@ -77,7 +80,7 @@ struct FieldReverseLookupOutput {
struct Token {
enum class Kind { FIELD, CONSTANT_IDX, VAR_IDX } kind;
std::string name;
int idx = -1;
int idx = -1; // 0 for an index from stride and 1 from stride2
double field_score = 0.0;
double score() {
+2
View File
@@ -13,6 +13,8 @@ void SimpleThreadGroup::run(const std::function<void(int)>& func, int num_runs,
// copy the function, in case the user gives us a temporary function.
m_func = func;
num_workers = std::min<int>(num_workers, std::thread::hardware_concurrency());
int start_idx = 0;
for (int thread_idx = 0; thread_idx < num_workers; thread_idx++) {
int end_idx = ((thread_idx + 1) * num_runs) / num_workers;
+1 -1
View File
@@ -40,7 +40,7 @@ std::vector<u8> decompress_zstd(const void* data, size_t size) {
auto decomp_size = ZSTD_decompress(result.data(), decompressed_size,
(const u8*)data + sizeof(size_t), compressed_size);
if (ZSTD_isError(decomp_size)) {
ASSERT_MSG(false, fmt::format("ZSTD error: {}", ZSTD_getErrorName(compressed_size)));
ASSERT_MSG(false, fmt::format("ZSTD error: {}", ZSTD_getErrorName(decomp_size)));
}
ASSERT(decomp_size == decompressed_size);
+1
View File
@@ -247,6 +247,7 @@ std::vector<ReplaceInfo> replace_info_jak1 = {
// acute accents
{"A~Y~-21H~-5V'~Z", "Á"},
{"R~Y~-21H~-5V'~Z", "Ŕ"},
{"E~Y~-22H~-5V'~Z", "É"},
{"I~Y~-19H~-5V'~Z", "Í"},
{"O~Y~-22H~-4V'~Z", "Ó"},
+19 -15
View File
@@ -13,18 +13,20 @@ std::vector<ReplaceInfo> replace_info_jak2 = {
{"O~Y~-25H~-1V/~Z", "Ø"},
{"o~Y~-23H~+4V/~Z", "ø"},
{"A~Y~-13H~+8V,~Z", "Ą"},
{"a~Y~-8H~+6V,~Z", "ą"},
{"E~Y~-6H~+8V,~Z", "Ę"},
{"e~Y~-10H~+7V,~Z", "ę"},
{"L~Y~-21H~+0V/~Z", "Ł"},
{"l~Y~-16H~+0V/~Z", "ł"}, // TODO - this one is ugly, font character addition (small slash)
{"Z~Y~-25H~-11Vº~Z", "Ż"},
{"z~Y~-23H~-5Vº~Z", "ż"},
{"A~Y~-10H~+4V,~Z", "Ą"},
{"a~Y~-7H~+5V,~Z", "ą"},
{"E~Y~-10H~+4V,~Z", "Ę"},
{"e~Y~-12H~+4V,~Z", "ę"},
{"L~Y~-20H~+0V-~Z", "Ł"},
{"l~Y~-13H~+0V-~Z", "ł"}, // TODO font character addition (small slash)
{"Z~Y~-18H~-30V.~Z", "Ż"},
{"z~Y~-15H~-24V.~Z", "ż"},
{"a~Y~-25H~-5Vº~Z", "å"},
{"S~Y~-21H~-5V'~Z", "Ś"},
{"s~Y~-25H~-5V'~Z", "ś"},
{"n~Y~-25H~-5V'~Z", "ń"},
{"S~Y~-24H~-12V'~Z", "Ś"},
{"s~Y~-22H~-5V'~Z", "ś"},
{"N~Y~-26H~-9V'~Z", "Ń"},
{"n~Y~-24H~-5V'~Z", "ń"},
{"C~Y~-26H~-14V'~Z", "Ć"},
{"c~Y~-25H~-5V'~Z", "ć"},
{"o~Y~-25H~-4V<TIL>~Z", "õ"},
{"a~Y~-25H~-4V<TIL>~Z", "ã"},
@@ -62,18 +64,20 @@ std::vector<ReplaceInfo> replace_info_jak2 = {
// acute accents
{"A~Y~-21H~-5V'~Z", "Á"},
{"R~Y~-21H~-5V'~Z", "Ŕ"},
{"A~Y~-26H~-8V'~Z", "<Á_V2>"}, // unfortunate...
{"a~Y~-25H~-5V'~Z", "á"},
{"r~Y~-25H~-5V'~Z", "ŕ"},
{"E~Y~-23H~-9V'~Z", "É"},
{"e~Y~-26H~-5V'~Z", "é"},
{"I~Y~-19H~-8V'~Z", "Í"},
{"i~Y~-19H~-8V'~Z", "í"},
{"O~Y~-22H~-4V'~Z", "Ó"},
{"o~Y~-26H~-4V'~Z", "ó"},
{"O~Y~-26H~-12V'~Z", "Ó"},
{"o~Y~-26H~-5V'~Z", "ó"},
{"U~Y~-25H~-8V'~Z", "Ú"},
{"u~Y~-24H~-3V'~Z", "ú"},
{"Z~Y~-24H~-3V'~Z", "Ź"},
{"z~Y~-24H~-3V'~Z", "ź"},
{"Z~Y~-26H~-14V'~Z", "Ź"},
{"z~Y~-23H~-6V'~Z", "ź"},
// czech specific
{"Y~Y~-26H~-5V'~Z", "Ý"},
{"~+7Vy~-7V~Y~-24H~-3V'~Z", "ý"},
+19 -15
View File
@@ -13,18 +13,20 @@ std::vector<ReplaceInfo> replace_info_jak3 = {
{"O~Y~-25H~-1V/~Z", "Ø"},
{"o~Y~-23H~+4V/~Z", "ø"},
{"A~Y~-13H~+8V,~Z", "Ą"},
{"a~Y~-8H~+6V,~Z", "ą"},
{"E~Y~-6H~+8V,~Z", "Ę"},
{"e~Y~-10H~+7V,~Z", "ę"},
{"L~Y~-21H~+0V/~Z", "Ł"},
{"l~Y~-16H~+0V/~Z", "ł"}, // TODO - this one is ugly, font character addition (small slash)
{"Z~Y~-25H~-11Vº~Z", "Ż"},
{"z~Y~-23H~-5Vº~Z", "ż"},
{"A~Y~-10H~+4V,~Z", "Ą"},
{"a~Y~-7H~+5V,~Z", "ą"},
{"E~Y~-10H~+4V,~Z", "Ę"},
{"e~Y~-12H~+4V,~Z", "ę"},
{"L~Y~-20H~+0V-~Z", "Ł"},
{"l~Y~-13H~+0V-~Z", "ł"}, // TODO font character addition (small slash)
{"Z~Y~-18H~-30V.~Z", "Ż"},
{"z~Y~-15H~-24V.~Z", "ż"},
{"a~Y~-25H~-5Vº~Z", "å"},
{"S~Y~-21H~-5V'~Z", "Ś"},
{"s~Y~-25H~-5V'~Z", "ś"},
{"n~Y~-25H~-5V'~Z", "ń"},
{"S~Y~-24H~-12V'~Z", "Ś"},
{"s~Y~-22H~-5V'~Z", "ś"},
{"N~Y~-26H~-9V'~Z", "Ń"},
{"n~Y~-24H~-5V'~Z", "ń"},
{"C~Y~-26H~-14V'~Z", "Ć"},
{"c~Y~-25H~-5V'~Z", "ć"},
{"o~Y~-25H~-4V<TIL>~Z", "õ"},
{"a~Y~-25H~-4V<TIL>~Z", "ã"},
@@ -62,18 +64,20 @@ std::vector<ReplaceInfo> replace_info_jak3 = {
// acute accents
{"A~Y~-21H~-5V'~Z", "Á"},
{"R~Y~-21H~-5V'~Z", "Ŕ"},
{"A~Y~-26H~-8V'~Z", "<Á_V2>"}, // unfortunate...
{"a~Y~-25H~-5V'~Z", "á"},
{"r~Y~-25H~-5V'~Z", "ŕ"},
{"E~Y~-23H~-9V'~Z", "É"},
{"e~Y~-26H~-5V'~Z", "é"},
{"I~Y~-19H~-8V'~Z", "Í"},
{"i~Y~-19H~-8V'~Z", "í"},
{"O~Y~-22H~-4V'~Z", "Ó"},
{"o~Y~-26H~-4V'~Z", "ó"},
{"O~Y~-26H~-12V'~Z", "Ó"},
{"o~Y~-26H~-5V'~Z", "ó"},
{"U~Y~-25H~-8V'~Z", "Ú"},
{"u~Y~-24H~-3V'~Z", "ú"},
{"Z~Y~-24H~-3V'~Z", "Ź"},
{"z~Y~-24H~-3V'~Z", "ź"},
{"Z~Y~-26H~-14V'~Z", "Ź"},
{"z~Y~-23H~-6V'~Z", "ź"},
// czech specific
{"Y~Y~-26H~-5V'~Z", "Ý"},
{"~+7Vy~-7V~Y~-24H~-3V'~Z", "ý"},
+2
View File
@@ -62,8 +62,10 @@ std::vector<ReplaceInfo> replace_info_jakx = {
// acute accents
{"A~Y~-21H~-5V'~Z", "Á"},
{"R~Y~-21H~-5V'~Z", "Ŕ"},
{"A~Y~-26H~-8V'~Z", "<Á_V2>"}, // unfortunate...
{"a~Y~-25H~-5V'~Z", "á"},
{"r~Y~-25H~-5V'~Z", "ŕ"},
{"E~Y~-23H~-9V'~Z", "É"},
{"e~Y~-26H~-5V'~Z", "é"},
{"I~Y~-19H~-8V'~Z", "Í"},
+142 -47
View File
@@ -1,5 +1,6 @@
#include "gltf_util.h"
#include "algorithm"
#include "image_resize.h"
#include "common/log/log.h"
@@ -160,8 +161,7 @@ JointsAndWeights convert_per_vertex_data(const math::Vector4f& weights,
if (src == discard_idx) {
continue;
}
// this +1 is to account for align not existing in the gltf.
ret.joints[dst] = joints[src] + 2;
ret.joints[dst] = joints[src] + 1;
ret.weights[dst] = weights[src];
sum += ret.weights[dst];
dst++;
@@ -186,6 +186,46 @@ std::vector<JointsAndWeights> extract_and_flatten_joints_and_weights(
return ret;
}
std::vector<math::Vector<u8, 4>> colors_from_attribute(const tinygltf::Model& model, int attrib) {
const auto attrib_accessor = model.accessors[attrib];
const auto& buffer_view = model.bufferViews[attrib_accessor.bufferView];
const auto& buffer = model.buffers[buffer_view.buffer];
const auto data_ptr = buffer.data.data() + buffer_view.byteOffset + attrib_accessor.byteOffset;
const auto byte_stride = attrib_accessor.ByteStride(buffer_view);
const auto count = attrib_accessor.count;
std::vector<math::Vector<u8, 4>> colors;
switch (attrib_accessor.type) {
case TINYGLTF_TYPE_VEC4:
switch (attrib_accessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_FLOAT:
colors = extract_color_from_vec4_float(data_ptr, count, byte_stride);
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
colors = extract_color_from_vec4_u16(data_ptr, count, byte_stride);
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
colors = extract_color_from_vec4_u8(data_ptr, count, byte_stride);
break;
default:
lg::die("Unknown type for {}", attrib_accessor.componentType);
}
break;
case TINYGLTF_TYPE_VEC3:
switch (attrib_accessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_FLOAT:
colors = extract_color_from_vec3_float(data_ptr, count, byte_stride);
break;
default:
lg::die("Unknown component type for vec3 color {}", attrib_accessor.componentType);
}
break;
default:
lg::die("Unknown attribute type for color {}", attrib_accessor.type);
}
return colors;
}
/*!
* Extract positions, colors, and normals from a mesh.
*/
@@ -196,7 +236,7 @@ ExtractedVertices gltf_vertices(const tinygltf::Model& model,
bool get_normals,
const std::string& debug_name) {
std::vector<tfrag3::PreloadedVertex> result;
std::vector<math::Vector<u8, 4>> vtx_colors;
std::vector<math::Vector<u8, 32>> vtx_colors;
{
const auto& position_attrib = attributes.find("POSITION");
@@ -226,54 +266,108 @@ ExtractedVertices gltf_vertices(const tinygltf::Model& model,
new_vert.z = v_w.z() * 4096;
}
}
if (get_colors) {
const auto& color_attrib = attributes.find("COLOR_0");
if (color_attrib == attributes.end()) {
lg::error("Mesh {} didn't have any colors, using white", debug_name);
for (size_t i = 0; i < result.size(); i++) {
vtx_colors.emplace_back(0x80, 0x80, 0x80, 0xff);
}
} else {
const auto attrib_accessor = model.accessors[color_attrib->second];
const auto& buffer_view = model.bufferViews[attrib_accessor.bufferView];
const auto& buffer = model.buffers[buffer_view.buffer];
const auto data_ptr =
buffer.data.data() + buffer_view.byteOffset + attrib_accessor.byteOffset;
const auto byte_stride = attrib_accessor.ByteStride(buffer_view);
const auto count = attrib_accessor.count;
std::vector<math::Vector<u8, 4>> colors;
std::array<std::pair<std::string, std::optional<std::vector<math::Vector<u8, 4>>>>, 8>
times_of_day = {{{"_SUNRISE", std::nullopt},
{"_MORNING", std::nullopt},
{"_NOON", std::nullopt},
{"_AFTERNOON", std::nullopt},
{"_SUNSET", std::nullopt},
{"_TWILIGHT", std::nullopt},
{"_EVENING", std::nullopt},
{"_GREENSUN", std::nullopt}}};
std::optional<std::vector<math::Vector<u8, 4>>> color0 = std::nullopt;
vtx_colors.resize(result.size());
bool found_one = false;
bool found_all = true;
switch (attrib_accessor.type) {
case TINYGLTF_TYPE_VEC4:
switch (attrib_accessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_FLOAT:
colors = extract_color_from_vec4_float(data_ptr, count, byte_stride);
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT:
colors = extract_color_from_vec4_u16(data_ptr, count, byte_stride);
break;
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE:
colors = extract_color_from_vec4_u8(data_ptr, count, byte_stride);
break;
default:
lg::die("Unknown type for COLOR_0: {}", attrib_accessor.componentType);
for (auto& slot : times_of_day) {
if (const auto attr_val = attributes.find(slot.first); attr_val != attributes.end()) {
slot.second = colors_from_attribute(model, attr_val->second);
found_one = true;
} else {
found_all = false;
}
}
if (!found_one) {
if (const auto color0_iter = attributes.find("COLOR_0"); color0_iter != attributes.end()) {
color0 = colors_from_attribute(model, color0_iter->second);
lg::warn("{} had colors but no times of day, using COLOR_0.", debug_name);
} else {
const u32 WHITE_COLOR =
0xFF808080; // Because of little-endianness, FF is at the largest address in memory.
for (auto& vtx_color : vtx_colors) {
// Write white into the color slot for all times of day.
for (u8 byte_offset = 0; byte_offset < 32; byte_offset += 4) {
u8* target_ptr = vtx_color.data() + byte_offset;
std::memcpy(target_ptr, &WHITE_COLOR, sizeof(u32));
}
break;
case TINYGLTF_TYPE_VEC3:
switch (attrib_accessor.componentType) {
case TINYGLTF_COMPONENT_TYPE_FLOAT:
colors = extract_color_from_vec3_float(data_ptr, count, byte_stride);
break;
default:
lg::die("unkonwn component type for vec3 color {}", attrib_accessor.componentType);
}
lg::error("{} didn't have any colors, using white.", debug_name);
}
}
if (found_one || color0.has_value()) {
if (found_all) {
lg::info("{} had all times of day.", debug_name);
} else if (found_one) {
std::string log_string = "";
for (size_t slot_index = 0; slot_index < times_of_day.size(); ++slot_index) {
auto& slot = times_of_day[slot_index];
std::string time_name = slot.first;
std::string value_name;
if (slot.second.has_value()) {
value_name = slot.first;
} else { // If this time_of_day lacks a color, use color of closest time of day.
for (int i = 1; !slot.second.has_value(); ++i) { // Takes at most 4 iterations.
// Look forward and backward for closest time of day color.
int neg_index = (slot_index - i + 8) % 8;
int pos_index = (slot_index + i + 8) % 8;
if (const auto& neg_slot = times_of_day[neg_index];
attributes.contains(neg_slot.first)) {
slot.second = neg_slot.second.value();
value_name = neg_slot.first;
} else if (const auto& pos_slot = times_of_day[pos_index];
attributes.contains(pos_slot.first)) {
slot.second = pos_slot.second.value();
value_name = pos_slot.first;
}
}
}
break;
default:
lg::die("unknown attribute type for color {}", attrib_accessor.type);
time_name = time_name.substr(1);
std::transform(time_name.begin(), time_name.end(), time_name.begin(),
[](unsigned char c) { return std::tolower(c); });
if (time_name == "greensun")
time_name = "green sun";
std::string mapping = time_name + ":" + value_name;
log_string += log_string.empty() ? mapping : ", " + mapping;
}
lg::warn("{} missing some times of day, using {}", debug_name, log_string);
}
vtx_colors.insert(vtx_colors.end(), colors.begin(), colors.end());
// Create iterators to colors for each time of day.
std::array<std::vector<math::Vector<u8, 4>>::const_iterator, 8> iters;
for (int time = 0; time < 8; ++time) {
const std::vector<math::Vector<u8, 4>>& time_color = times_of_day[time].second.has_value()
? times_of_day[time].second.value()
: color0.value();
iters[time] = time_color.begin();
}
// Write the color for each time of day into vtx_colors.
for (auto& vtx_color : vtx_colors) {
for (int slot_index = 0; slot_index < 8; ++slot_index) {
u8* target_ptr = vtx_color.data() + (4 * slot_index);
auto& color_iter = iters[slot_index];
const u8* source_ptr = color_iter->data();
std::memcpy(target_ptr, source_ptr, sizeof(u32));
++color_iter; // Advance the iterator for this time of day.
}
}
}
}
@@ -756,14 +850,15 @@ std::size_t TieFullVertex::hash::operator()(const TieFullVertex& x) const {
return tfrag3::PackedTieVertices::Vertex::hash()(x.vertex) ^ std::hash<u16>()(x.color_index);
}
tfrag3::PackedTimeOfDay pack_time_of_day(const std::vector<math::Vector<u8, 4>>& color_palette) {
tfrag3::PackedTimeOfDay pack_time_of_day(const std::vector<math::Vector<u8, 32>>& color_palette) {
tfrag3::PackedTimeOfDay colors;
colors.color_count = (color_palette.size() + 3) & (~3);
colors.data.resize(colors.color_count * 8 * 4);
for (u32 color_index = 0; color_index < color_palette.size(); color_index++) {
for (u32 palette = 0; palette < 8; palette++) {
for (u32 channel = 0; channel < 4; channel++) {
colors.read(color_index, palette, channel) = color_palette[color_index][channel];
colors.read(color_index, palette, channel) =
color_palette[color_index][4 * palette + channel];
}
}
}
+3 -3
View File
@@ -46,7 +46,7 @@ std::vector<JointsAndWeights> extract_and_flatten_joints_and_weights(
struct ExtractedVertices {
std::vector<tfrag3::PreloadedVertex> vtx;
std::vector<math::Vector<u8, 4>> vtx_colors;
std::vector<math::Vector<u8, 32>> vtx_colors;
std::vector<math::Vector3f> normals;
};
@@ -178,13 +178,13 @@ math::Matrix4f matrix_from_trs(const math::Vector3f& trans,
const math::Vector4f& quat,
const math::Vector3f& scale);
tfrag3::PackedTimeOfDay pack_time_of_day(const std::vector<math::Vector<u8, 4>>& color_palette);
tfrag3::PackedTimeOfDay pack_time_of_day(const std::vector<math::Vector<u8, 32>>& color_palette);
struct MercExtractData {
TexturePool tex_pool;
std::vector<u32> new_indices;
std::vector<tfrag3::PreloadedVertex> new_vertices;
std::vector<math::Vector<u8, 4>> new_colors;
std::vector<math::Vector<u8, 32>> new_colors;
std::vector<math::Vector3f> normals;
std::vector<JointsAndWeights> joints_and_weights;
tfrag3::MercModel new_model;
+138 -44
View File
@@ -1,5 +1,7 @@
#include "os.h"
#include <fstream>
#include "common/common_types.h"
#include "common/log/log.h"
#include "common/util/string_util.h"
@@ -46,17 +48,133 @@ void __cpuidex(int result[4], int eax, int ecx) {
: "=a"(result[0]), "=b"(result[1]), "=c"(result[2]), "=d"(result[3])
: "0"(eax), "2"(ecx));
}
#else
// TODO ARM - implement ARM64 detection, check for NEON instead of AVX
// for now, just return 0's.
void __cpuidex(int result[4], int eax, int ecx) {
lg::warn("cpuid not implemented on this platform");
for (int i = 0; i < 4; i++) {
result[i] = 0;
}
}
#endif
void setup_cpu_info_windows(CpuInfo& info) {
#if defined(_M_X64) || defined(_M_IX86)
// Brand string
{
int result[4];
__cpuidex(result, 0, 0);
for (int r : {1, 3, 2}) {
int reg = result[r];
for (int i = 0; i < 4; i++) {
info.brand.push_back(reg & 0xff);
reg >>= 8;
}
}
}
// Model string
for (int leaf = 0x80000002; leaf <= 0x80000004; leaf++) {
int result[4];
__cpuidex(result, leaf, 0);
for (int reg : result) {
for (int i = 0; i < 4; i++) {
info.model.push_back(reg & 0xff);
reg >>= 8;
}
}
}
{
int result[4];
__cpuidex(result, 1, 0);
info.has_avx = result[2] & (1 << 28);
}
{
int result[4];
__cpuidex(result, 7, 0);
info.has_avx2 = result[1] & (1 << 5);
}
#elif defined(_M_ARM64)
info.brand = "ARM";
HKEY key;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
KEY_READ, &key) == ERROR_SUCCESS) {
char buf[256];
DWORD size = sizeof(buf);
if (RegQueryValueExA(key, "ProcessorNameString", nullptr, nullptr, reinterpret_cast<BYTE*>(buf),
&size) == ERROR_SUCCESS) {
info.model = buf;
}
RegCloseKey(key);
}
info.has_neon = IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE);
#endif
}
void setup_cpu_info_linux(CpuInfo& info) {
std::ifstream cpuinfo("/proc/cpuinfo");
std::string line;
while (std::getline(cpuinfo, line)) {
auto colon = line.find(':');
if (colon == std::string::npos) {
continue;
}
std::string key = line.substr(0, colon);
std::string value = line.substr(colon + 1);
while (!value.empty() && value.front() == ' ') {
value.erase(value.begin());
}
if (info.brand.empty() && key == "vendor_id") {
info.brand = value;
}
if (info.model.empty() && (key == "model name" || key == "Processor")) {
info.model = value;
}
}
#if defined(__aarch64__)
info.brand = "ARM";
#ifdef HWCAP_ASIMD
info.has_neon = getauxval(AT_HWCAP) & HWCAP_ASIMD;
#endif
#endif
#if defined(__x86_64__)
int result[4];
__cpuidex(result, 1, 0);
info.has_avx = result[2] & (1 << 28);
__cpuidex(result, 7, 0);
info.has_avx2 = result[1] & (1 << 5);
#endif
}
void setup_cpu_info_macos(CpuInfo& info) {
#if defined(__x86_64__)
int result[4];
__cpuidex(result, 0, 0);
for (int r : {1, 3, 2}) {
int reg = result[r];
for (int i = 0; i < 4; i++) {
info.brand.push_back(reg & 0xff);
reg >>= 8;
}
}
for (int leaf = 0x80000002; leaf <= 0x80000004; leaf++) {
__cpuidex(result, leaf, 0);
for (int reg : result) {
for (int i = 0; i < 4; i++) {
info.model.push_back(reg & 0xff);
reg >>= 8;
}
}
}
__cpuidex(result, 1, 0);
info.has_avx = result[2] & (1 << 28);
__cpuidex(result, 7, 0);
info.has_avx2 = result[1] & (1 << 5);
#elif defined(__aarch64__) || defined(__arm64__)
info.brand = "Apple";
char buf[128];
size_t len = sizeof(buf);
if (sysctlbyname("hw.model", buf, &len, nullptr, 0) == 0) {
info.model = buf;
}
info.has_neon = true;
#endif
}
CpuInfo gCpuInfo;
void setup_cpu_info() {
@@ -64,47 +182,23 @@ void setup_cpu_info() {
return;
}
// as a test, get the brand and model
for (u32 i = 0x80000002; i <= 0x80000004; i++) {
int result[4];
__cpuidex(result, i, 0);
for (auto reg : result) {
for (int c = 0; c < 4; c++) {
gCpuInfo.model.push_back(reg);
reg >>= 8;
}
}
}
{
int result[4];
__cpuidex(result, 0, 0);
for (auto r : {1, 3, 2}) {
for (int c = 0; c < 4; c++) {
gCpuInfo.brand.push_back(result[r]);
result[r] >>= 8;
}
}
}
// check for AVX2
{
int result[4];
__cpuidex(result, 7, 0);
gCpuInfo.has_avx2 = result[1] & (1 << 5);
}
{
int result[4];
__cpuidex(result, 1, 0);
gCpuInfo.has_avx = result[2] & (1 << 28);
}
#if defined(_WIN32)
setup_cpu_info_windows(gCpuInfo);
#elif defined(__APPLE__)
setup_cpu_info_macos(gCpuInfo);
#elif defined(__linux__)
setup_cpu_info_linux(gCpuInfo);
#else
gCpuInfo.brand = "Unknown Brand";
gCpuInfo.model = "Unknown Model";
#endif
printf("-------- CPU Information --------\n");
printf(" Brand: %s\n", gCpuInfo.brand.c_str());
printf(" Model: %s\n", gCpuInfo.model.c_str());
printf(" AVX : %s\n", gCpuInfo.has_avx ? "true" : "false");
printf(" AVX2 : %s\n", gCpuInfo.has_avx2 ? "true" : "false");
printf(" NEON : %s\n", gCpuInfo.has_neon ? "true" : "false");
fflush(stdout);
gCpuInfo.initialized = true;
+1
View File
@@ -11,6 +11,7 @@ struct CpuInfo {
bool initialized = false;
bool has_avx = false;
bool has_avx2 = false;
bool has_neon = false;
std::string brand;
std::string model;
+21 -17
View File
@@ -1,45 +1,49 @@
files:
- source: /game/assets/jak1/text/game_custom_text_en-US.json
translation: /game/assets/jak1/text/game_custom_text_%locale%.json
excluded_target_languages:
- "ko"
- "ru"
- source: /game/assets/jak1/subtitle/subtitle_lines_en-US.json
translation: /game/assets/jak1/subtitle/subtitle_lines_%locale%.json
excluded_target_languages:
- "fr-FR"
- "de-DE"
- "fr"
- "de"
- "es-ES"
- "it-IT"
- ja
- en-GB
- fi-Fi
- "it"
- "ja"
- "en-GB"
- "fi"
- "ko"
- "ru"
- source: /game/assets/jak2/text/game_custom_text_en-US.json
translation: /game/assets/jak2/text/game_custom_text_%locale%.json
excluded_target_languages:
- "ru"
- source: /game/assets/jak2/subtitle/subtitle_lines_en-US.json
translation: /game/assets/jak2/subtitle/subtitle_lines_%locale%.json
excluded_target_languages:
- "fr-FR"
- "de-DE"
- "fr"
- "de"
- "es-ES"
- "it"
- "it-IT"
- "ja-JP"
- "ja"
- "ko"
- "en-GB"
- "fi"
- "fi-Fi"
- "ru"
- 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"
- "fr"
- "de"
- "es-ES"
- "it"
- "it-IT"
- "ja-JP"
- "ja"
- "ko"
- "en-GB"
- "fi"
- "fi-Fi"
- "ru-RU"
- "pt-PT"
- "ru"
@@ -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 "[email protected]".
//
// 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. ["[email protected]": ...]):
// 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 "[email protected]".
//
// 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 "[email protected]".
//
// 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)"
]
}
}
]
}
+7 -2
View File
@@ -101,6 +101,7 @@ target_link_libraries(decomp
stb_image
xdelta3
tiny_gltf
sound
)
add_executable(decompiler
@@ -112,7 +113,9 @@ target_link_libraries(decompiler
lzokay
fmt
stb_image
tiny_gltf)
tiny_gltf
sound
)
add_executable(extractor
@@ -125,4 +128,6 @@ target_link_libraries(extractor
fmt
compiler
stb_image
tiny_gltf)
tiny_gltf
sound
)
+110 -11
View File
@@ -32,6 +32,70 @@ Register get_expected_fpr_backup(int n, int total) {
return fpr_backups.at((total - 1) - n);
}
/*!
* sd s7, 16(sp)
* bgezal r0, L
* sll r0, r0, 0
* L26:
* sd fp, 8(sp) ;; not done by interrupt handlers
* daddiu fp, ra, -20
* lw s7, L24(fp)
* lw s7, 0(s7)
* daddiu s7, s7, -8 ;; -16 in jak 1
*/
int match_called_from_c_prologue(const std::vector<Instruction>& instrs,
const LinkedObjectFile& file,
int start_word,
int idx,
bool* fp_backed_up) {
if (idx + 7 >= int(instrs.size()) ||
!is_no_link_gpr_store(instrs.at(idx), 8, make_gpr(Reg::S7), 16, make_gpr(Reg::SP))) {
return -1;
}
idx++;
// branch to the instruction after the delay slot to get the pc in ra
const auto& bgezal = instrs.at(idx);
if (bgezal.kind != InstructionKind::BGEZAL || bgezal.get_src(0).get_reg() != make_gpr(Reg::R0)) {
return -1;
}
int ra_idx = idx + 2;
const auto& target = file.labels.at(bgezal.get_label_target());
if (target.offset != (start_word + ra_idx) * 4 || !is_nop(instrs.at(idx + 1))) {
return -1;
}
idx = ra_idx;
*fp_backed_up = is_no_link_gpr_store(instrs.at(idx), 8, make_gpr(Reg::FP), 8, make_gpr(Reg::SP));
if (*fp_backed_up) {
idx++;
}
if (!is_gpr_2_imm_int(instrs.at(idx), InstructionKind::DADDIU, make_gpr(Reg::FP),
make_gpr(Reg::RA), -(ra_idx - 1) * 4)) {
return -1;
}
idx++;
const auto& s7_ptr = instrs.at(idx);
if (s7_ptr.kind != InstructionKind::LW || s7_ptr.get_dst(0).get_reg() != make_gpr(Reg::S7) ||
!s7_ptr.get_src(0).is_label() || s7_ptr.get_src(1).get_reg() != make_gpr(Reg::FP)) {
return -1;
}
idx++;
if (!is_no_ll_gpr_load(instrs.at(idx), 4, true, make_gpr(Reg::S7), 0, make_gpr(Reg::S7))) {
return -1;
}
idx++;
if (!is_gpr_2_imm_int(instrs.at(idx), InstructionKind::DADDIU, make_gpr(Reg::S7),
make_gpr(Reg::S7), {})) {
return -1;
}
return idx + 1;
}
} // namespace
Function::Function(int _start_word, int _end_word, GameVersion version)
@@ -86,11 +150,26 @@ void Function::analyze_prologue(const LinkedObjectFile& file) {
idx++;
}
{
// check for C callees and interrupt handlers (they back up s7 on the stack and restore it
// later)
bool c_fp_backed_up = false;
int c_prologue_end = -1;
if (prologue.ra_backed_up) {
c_prologue_end =
match_called_from_c_prologue(instructions, file, start_word, idx, &c_fp_backed_up);
}
if (c_prologue_end != -1) {
prologue.called_from_c = true;
prologue.fp_set = true;
if (c_fp_backed_up) {
prologue.fp_backed_up = true;
prologue.fp_backup_offset = 8;
}
idx = c_prologue_end;
} else {
auto& instr = instructions.at(idx);
// storing s7 on the stack is done by interrupt handlers, which we probably don't want to
// support
// anything else storing s7 on the stack is probably asm
if (instr.kind == InstructionKind::SD && instr.get_src(0).get_reg() == make_gpr(Reg::S7) &&
instr.get_src(2).get_reg() == make_gpr(Reg::SP)) {
lg::warn(
@@ -104,7 +183,8 @@ void Function::analyze_prologue(const LinkedObjectFile& file) {
}
// next is fp backup
if (is_no_link_gpr_store(instructions.at(idx), 8, Register(Reg::GPR, Reg::FP), {},
if (!prologue.called_from_c &&
is_no_link_gpr_store(instructions.at(idx), 8, Register(Reg::GPR, Reg::FP), {},
Register(Reg::GPR, Reg::SP))) {
prologue.fp_backed_up = true;
prologue.fp_backup_offset = get_gpr_store_offset_as_int(instructions.at(idx));
@@ -269,9 +349,6 @@ void Function::analyze_prologue(const LinkedObjectFile& file) {
ASSERT(prologue.total_stack_usage == total_stack);
}
// it's fine to have the entire first basic block be the prologue - you could loop back to the
// first instruction past the prologue.
ASSERT(basic_blocks.at(0).end_word >= prologue_end);
resize_first_block(prologue_end, file);
prologue.decoded = true;
@@ -279,10 +356,9 @@ void Function::analyze_prologue(const LinkedObjectFile& file) {
}
void Function::resize_first_block(int new_start, const LinkedObjectFile&) {
basic_blocks.at(0).start_word = new_start;
if (basic_blocks.size() >= 2 && basic_blocks.at(1).start_word == new_start) {
// block 1 is now zero size, so we should eliminate it
// the prologue of a function called from C spans two blocks because of the bgezal.
while (basic_blocks.size() >= 2 && basic_blocks.at(1).start_word <= new_start) {
// block 0 is entirely prologue, so merge it into block 1
auto& block0 = basic_blocks.at(0);
auto& block1 = basic_blocks.at(1);
block0.succ_ft = block1.succ_ft;
@@ -309,6 +385,9 @@ void Function::resize_first_block(int new_start, const LinkedObjectFile&) {
}
basic_blocks.pop_back();
}
ASSERT(basic_blocks.at(0).end_word >= new_start);
basic_blocks.at(0).start_word = new_start;
}
/*!
@@ -389,6 +468,13 @@ void Function::check_epilogue(const LinkedObjectFile& file) {
ASSERT(is_jr_ra(instructions.at(idx)));
idx--;
if (prologue.called_from_c && instructions.at(idx).kind == InstructionKind::EI) {
idx--;
ASSERT(instructions.at(idx).kind == InstructionKind::SYNCL);
idx--;
prologue.interrupt_handler = true;
}
// restore gprs
for (int i = 0; i < prologue.n_gpr_backup; i++) {
int gpr_idx = prologue.n_gpr_backup - (1 + i);
@@ -416,6 +502,13 @@ void Function::check_epilogue(const LinkedObjectFile& file) {
idx--;
}
// restore s7
if (prologue.called_from_c) {
ASSERT(
is_no_ll_gpr_load(instructions.at(idx), 8, true, make_gpr(Reg::S7), 16, make_gpr(Reg::SP)));
idx--;
}
// restore ra
if (prologue.ra_backed_up) {
ASSERT(is_no_ll_gpr_load(instructions.at(idx), 8, true, make_gpr(Reg::RA),
@@ -428,6 +521,12 @@ void Function::check_epilogue(const LinkedObjectFile& file) {
basic_blocks.back().end_word = idx + 1;
prologue.epilogue_ok = true;
epilogue_start = idx + 1;
if (prologue.interrupt_handler) {
warnings.info("Interrupt handler");
} else if (prologue.called_from_c) {
warnings.info("Called from C");
}
}
/*!
+5
View File
@@ -161,6 +161,11 @@ class Function {
bool fp_set = false;
// callbacks and interrupt handlers back up s7 and rebuild s7/fp themselves
bool called_from_c = false;
// re-enables interrupts in the epilogue
bool interrupt_handler = false;
int n_gpr_backup = 0;
int gpr_backup_offset = -1;
+63 -2
View File
@@ -22,6 +22,42 @@ RegClass get_reg_kind(const Register& r) {
return RegClass::INVALID;
}
}
/*!
* Try to resolve obj + (idx * stride) + (idx2 * stride2) as an access into a 2d array.
*/
ArrayFieldAccess* try_2d_array_access(const TP_Type& input_type,
const IR2_RegOffset& ro,
const DerefKind& dk,
const Env& env,
FormPool& pool,
TypeSpec* result_type) {
const auto& [stride, stride2] = input_type.get_sum_multipliers();
FieldReverseLookupInput rd_in;
rd_in.deref = dk;
rd_in.base_type = input_type.get_obj_plus_const_mult_typespec();
rd_in.stride = stride;
rd_in.stride2 = stride2;
rd_in.offset = ro.offset + input_type.get_sum_constant();
auto rd = env.dts->ts.reverse_field_lookup(rd_in);
if (!rd.success) {
return nullptr;
}
std::vector<DerefToken> tokens;
std::vector<int> index_strides;
for (auto& token : rd.tokens) {
tokens.push_back(to_token(token));
if (token.kind == FieldReverseLookupOutput::Token::Kind::VAR_IDX) {
index_strides.push_back(token.idx == 0 ? stride : stride2);
}
}
auto access = pool.alloc_element<ArrayFieldAccess>(ro.var, tokens, 1, ro.offset,
input_type.flipped_add_order());
access->set_index_strides(index_strides, input_type.get_sum_constant());
*result_type = rd.result_type;
return access;
}
} // namespace
ConditionElement* BranchOp::get_condition_as_form(FormPool& pool, const Env& env) const {
@@ -367,7 +403,20 @@ FormElement* StoreOp::get_as_form(FormPool& pool, const Env& env) const {
}
}
if (input_type.kind == TP_Type::Kind::OBJECT_PLUS_PRODUCT_WITH_CONSTANT) {
if (input_type.has_sum_multipliers()) {
DerefKind dk;
dk.is_store = true;
dk.reg_kind = get_reg_kind(ro.reg);
dk.size = m_size;
TypeSpec result_type;
if (auto access = try_2d_array_access(input_type, ro, dk, env, pool, &result_type)) {
return pool.alloc_element<StoreArrayAccess>(
access, m_value.as_expr(), m_my_idx, ro.var,
get_typecast_for_atom(m_value, env, coerce_to_reg_type(result_type), m_my_idx));
}
}
if (input_type.is_plain_product_plus_obj()) {
FieldReverseLookupInput rd_in;
DerefKind dk;
dk.is_store = true;
@@ -608,7 +657,19 @@ Form* LoadVarOp::get_load_src(FormPool& pool, const Env& env) const {
return pool.alloc_single_element_form<DynamicMethodAccess>(nullptr, ro.var);
}
if (input_type.kind == TP_Type::Kind::OBJECT_PLUS_PRODUCT_WITH_CONSTANT) {
if (input_type.has_sum_multipliers()) {
DerefKind dk;
dk.is_store = false;
dk.reg_kind = get_reg_kind(ro.reg);
dk.sign_extend = m_kind == Kind::SIGNED;
dk.size = m_size;
TypeSpec result_type;
if (auto access = try_2d_array_access(input_type, ro, dk, env, pool, &result_type)) {
return pool.alloc_single_form(nullptr, access);
}
}
if (input_type.is_plain_product_plus_obj()) {
FieldReverseLookupInput rd_in;
DerefKind dk;
dk.is_store = false;
+11 -3
View File
@@ -904,6 +904,11 @@ TypeState AsmOp::propagate_types_internal(const TypeState& input,
result.get(m_dst->reg()) = TP_Type::make_from_ts(coerce_to_reg_type(field.type()));
return result;
}
if (m_instr.src[1].get_imm() > 0 &&
dts.ts.tc(TypeSpec("integer"), result.get(m_src[0]->reg()).typespec())) {
result.get(m_dst->reg()) = TP_Type::make_from_ts("uint");
return result;
}
}
if (m_dst.has_value()) {
@@ -1008,9 +1013,11 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input,
if (method_id == GOAL_NEW_METHOD) {
return TP_Type::make_non_object_new(method_type, TypeSpec(type_name));
} else if (input_type.kind == TP_Type::Kind::TYPE_OF_TYPE_NO_VIRTUAL) {
return TP_Type::make_non_virtual_method(method_type, TypeSpec(type_name), method_id);
return TP_Type::make_non_virtual_method(method_type, TypeSpec(type_name), method_id,
method_info.name);
} else {
return TP_Type::make_virtual_method(method_type, TypeSpec(type_name), method_id);
return TP_Type::make_virtual_method(method_type, TypeSpec(type_name), method_id,
method_info.name);
}
}
@@ -1023,7 +1030,8 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input,
if (method_id != GOAL_NEW_METHOD && method_id != GOAL_RELOC_METHOD) {
// this can get us the wrong thing for `new` methods. And maybe relocate?
return TP_Type::make_non_virtual_method(
method_info.type.substitute_for_method_call("object"), TypeSpec("object"), method_id);
method_info.type.substitute_for_method_call("object"), TypeSpec("object"), method_id,
method_info.name);
}
}
}
+29
View File
@@ -1314,6 +1314,23 @@ class DerefElement : public FormElement {
std::vector<DerefToken> m_tokens;
};
struct Match2dIndices {
Form* idx[2] = {nullptr, nullptr};
Form* base = nullptr;
};
/*!
* find the two indices of (+ (* idx stride) (* idx2 stride2) constant [base]).
*/
std::optional<Match2dIndices> match_2d_indices(Form* in,
const std::vector<int>& strides,
s64 constant,
bool with_base,
const Env& env,
FormPool& pool);
std::vector<DerefToken> fill_2d_index_placeholders(const std::vector<DerefToken>& tokens,
const Match2dIndices& match);
class ArrayFieldAccess : public FormElement {
public:
ArrayFieldAccess(RegisterAccess source,
@@ -1340,12 +1357,24 @@ class ArrayFieldAccess : public FormElement {
bool flipped() const { return m_flipped; }
void set_index_strides(std::vector<int> strides, s64 constant) {
m_index_strides = std::move(strides);
m_index_constant = constant;
}
private:
void update_with_val_2d(Form* new_val,
const Env& env,
FormPool& pool,
std::vector<FormElement*>* result);
RegisterAccess m_source;
std::vector<DerefToken> m_deref_tokens;
int m_expected_stride = -1;
int m_constant_offset = -1;
bool m_flipped = false;
std::vector<int> m_index_strides;
s64 m_index_constant = 0;
};
class StorePlainDeref : public FormElement {
+285 -8
View File
@@ -902,9 +902,11 @@ void SimpleExpressionElement::update_from_stack_gpr_to_fpr(const Env& env,
std::vector<FormElement*>* result,
bool allow_side_effects) {
auto src = m_expr.get_arg(0);
auto src_type = env.get_types_before_op(src.var().idx()).get(src.var().reg());
auto src_is_float = false;
std::vector<FormElement*> src_fes;
if (src.is_var()) {
auto src_type = env.get_types_before_op(src.var().idx()).get(src.var().reg());
src_is_float = env.dts->ts.tc(TypeSpec("float"), src_type.typespec());
auto forms = pop_to_forms({src.var()}, env, pool, stack, allow_side_effects);
for (auto x : forms.at(0)->elts()) {
src_fes.push_back(x);
@@ -916,7 +918,7 @@ void SimpleExpressionElement::update_from_stack_gpr_to_fpr(const Env& env,
// set ourself to identity.
m_expr = src.as_expr();
if (env.dts->ts.tc(TypeSpec("float"), src_type.typespec())) {
if (src_is_float) {
// got a float as an input, we can convert it to an FPR with no effect.
for (auto x : src_fes) {
result->push_back(x);
@@ -932,6 +934,12 @@ void SimpleExpressionElement::update_from_stack_gpr_to_fpr(const Env& env,
if (proper_float(flt)) {
result->push_back(pool.alloc_element<ConstantFloatElement>(flt));
return;
} else if (frm->to_string(env) == "#x7f800000") {
auto cast = pool.alloc_element<CastElement>(TypeSpec("float"), frm);
env.func->warnings.warning("op {}: float inf {} moved to fpr", m_my_idx,
frm->to_string(env), cast->to_string(env));
result->push_back(cast);
return;
}
}
}
@@ -1153,6 +1161,11 @@ void SimpleExpressionElement::update_from_stack_si_1(const Env& env,
make_cast_if_needed(arg, in_type, TypeSpec("int"), pool, env)));
}
namespace {
Form* strip_int_or_uint_cast(Form* in);
Form* match_index_product(Form* in, int stride);
} // namespace
void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
FormPool& pool,
FormStack& stack,
@@ -1437,6 +1450,80 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env,
throw std::runtime_error("Failed to match product_with_constant inline array access 2.");
}
}
} else if ((arg1_type.is_product() && arg0_type.has_field_origin()) ||
(arg0_type.is_product() && arg1_type.has_field_origin())) {
// (+ (+ obj C1) (* idx C2)), where obj + C1 was already turned into a field access.
// same path as the element access with index 0.
bool field_first = arg1_type.is_product() && arg0_type.has_field_origin();
const auto& field_type = field_first ? arg0_type : arg1_type;
int stride = (field_first ? arg1_type : arg0_type).get_multiplier();
auto elt = lookup_array_element_from_field(env.dts->ts, field_type, stride);
auto idx = match_index_product(args.at(field_first ? 1 : 0), stride);
auto deref =
strip_int_or_uint_cast(args.at(field_first ? 0 : 1))->try_as_element<DerefElement>();
if (elt && idx && deref && !deref->is_addr_of() &&
deref->tokens().size() >= elt->tokens.size()) {
const auto& old_tokens = deref->tokens();
size_t start = old_tokens.size() - elt->tokens.size();
std::vector<DerefToken> tokens(old_tokens.begin(), old_tokens.begin() + start);
bool same_path = true;
for (size_t i = 0; i < elt->tokens.size() && same_path; i++) {
const auto& tok = elt->tokens.at(i);
const auto& old_tok = old_tokens.at(start + i);
switch (tok.kind) {
case FieldReverseLookupOutput::Token::Kind::FIELD:
same_path = old_tok.is_field_name(tok.name);
tokens.push_back(old_tok);
break;
case FieldReverseLookupOutput::Token::Kind::CONSTANT_IDX:
same_path = old_tok.is_int(tok.idx);
tokens.push_back(old_tok);
break;
case FieldReverseLookupOutput::Token::Kind::VAR_IDX:
same_path = old_tok.is_int(0);
tokens.push_back(DerefToken::make_int_expr(idx));
break;
}
}
if (same_path) {
result->push_back(pool.alloc_element<DerefElement>(deref->base(), false, tokens));
return;
}
}
if (elt) {
auto sum = pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::ADDITION_PTR),
args.at(field_first ? 0 : 1), args.at(field_first ? 1 : 0));
result->push_back(
pool.alloc_element<CastElement>(coerce_to_reg_type(elt->result_type), sum));
return;
}
} else if (arg0_type.kind == TP_Type::Kind::PRODUCT_SUM ||
arg1_type.kind == TP_Type::Kind::PRODUCT_SUM) {
bool sum_first = arg0_type.kind == TP_Type::Kind::PRODUCT_SUM;
const auto& sum_type = sum_first ? arg0_type : arg1_type;
const auto& base_type = sum_first ? arg1_type : arg0_type;
auto elt = lookup_2d_array_element(env.dts->ts, base_type.typespec(), sum_type);
if (elt && base_type.kind == TP_Type::Kind::TYPESPEC) {
std::vector<int> strides;
const auto& [stride, stride2] = sum_type.get_product_sum_multipliers();
for (auto& tok : elt->tokens) {
if (tok.kind == FieldReverseLookupOutput::Token::Kind::VAR_IDX) {
strides.push_back(tok.idx == 0 ? stride : stride2);
}
}
auto match = match_2d_indices(args.at(sum_first ? 0 : 1), strides,
sum_type.get_sum_constant(), false, env, pool);
if (!match) {
throw std::runtime_error(fmt::format("Failed to match 2d array access with add: {}",
args.at(sum_first ? 0 : 1)->to_string(env)));
}
result->push_back(pool.alloc_element<DerefElement>(
cast_stack_slot_var_if_needed(args.at(sum_first ? 1 : 0), base_type.typespec(), pool,
env),
false, fill_2d_index_placeholders(to_tokens(elt->tokens), *match)));
return;
}
} else if (arg0_type.kind == TP_Type::Kind::INTEGER_CONSTANT) {
// try to see if this is valid, from the type system.
FieldReverseLookupInput input;
@@ -1912,6 +1999,104 @@ Form* strip_int_or_uint_cast(Form* in) {
}
} // namespace
namespace {
/*!
* match (* idx stride) or (* stride idx) and return idx.
*/
Form* match_index_product(Form* in, int stride) {
auto stride_matcher =
Matcher::match_or({Matcher::cast("uint", Matcher::integer(stride)),
Matcher::cast("int", Matcher::integer(stride)), Matcher::integer(stride)});
auto idx_matcher = Matcher::match_or({Matcher::cast("uint", Matcher::any(0)),
Matcher::cast("int", Matcher::any(0)), Matcher::any(0)});
auto mult_matcher = Matcher::match_or(
{Matcher::op_fixed(FixedOperatorKind::MULTIPLICATION, {idx_matcher, stride_matcher}),
Matcher::op_fixed(FixedOperatorKind::MULTIPLICATION, {stride_matcher, idx_matcher})});
mult_matcher = Matcher::match_or(
{Matcher::cast("uint", mult_matcher), Matcher::cast("int", mult_matcher), mult_matcher});
auto mr = match(mult_matcher, in);
return mr.matched ? mr.maps.forms.at(0) : nullptr;
}
} // namespace
std::optional<Match2dIndices> match_2d_indices(Form* in,
const std::vector<int>& strides,
s64 constant,
bool with_base,
const Env& env,
FormPool& pool) {
ASSERT(strides.size() == 2 && strides.at(0) != strides.at(1));
int unit_slot = strides.at(0) == 1 ? 0 : (strides.at(1) == 1 ? 1 : -1);
if (unit_slot != -1 && with_base) {
return std::nullopt;
}
std::vector<Form*> terms;
std::function<void(Form*)> flatten = [&](Form* f) {
auto as_generic = strip_int_or_uint_cast(f)->try_as_element<GenericElement>();
if (as_generic && (as_generic->op().is_fixed(FixedOperatorKind::ADDITION) ||
as_generic->op().is_fixed(FixedOperatorKind::ADDITION_PTR))) {
for (auto elt : as_generic->elts()) {
flatten(elt);
}
} else {
terms.push_back(f);
}
};
flatten(in);
Match2dIndices result;
s64 found_constant = 0;
std::vector<Form*> unit_terms;
for (auto term : terms) {
bool used = false;
for (int i = 0; i < 2 && !used; i++) {
if (!result.idx[i] && i != unit_slot) {
result.idx[i] = match_index_product(term, strides.at(i));
used = result.idx[i];
}
}
if (used) {
continue;
}
if (auto as_int = get_goal_integer_constant(strip_int_or_uint_cast(term), env)) {
found_constant += *as_int;
} else if (unit_slot != -1) {
unit_terms.push_back(strip_int_or_uint_cast(term));
} else if (with_base && !result.base) {
result.base = strip_int_or_uint_cast(term);
} else {
return std::nullopt;
}
}
if (unit_terms.size() == 1) {
result.idx[unit_slot] = unit_terms.front();
} else if (unit_terms.size() > 1) {
result.idx[unit_slot] = pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::ADDITION), unit_terms);
}
if (!result.idx[0] || !result.idx[1] || (with_base && !result.base) ||
found_constant != constant) {
return std::nullopt;
}
return result;
}
std::vector<DerefToken> fill_2d_index_placeholders(const std::vector<DerefToken>& tokens,
const Match2dIndices& match) {
std::vector<DerefToken> result = tokens;
int placeholder = 0;
for (auto& x : result) {
if (x.kind() == DerefToken::Kind::EXPRESSION_PLACEHOLDER) {
ASSERT(placeholder < 2);
x = DerefToken::make_int_expr(match.idx[placeholder++]);
}
}
return result;
}
FormElement* SimpleExpressionElement::update_from_stack_logor_or_logand_helper(
const Env& env,
FixedOperatorKind kind,
@@ -1950,6 +2135,13 @@ FormElement* SimpleExpressionElement::update_from_stack_logor_or_logand_helper(
bitfield_info =
dynamic_cast<BitFieldType*>(env.dts->ts.lookup_type(arg0_reg_type.get_bitfield_type()));
ASSERT(bitfield_info);
} else if (arg0_reg_type.kind == TP_Type::Kind::TYPESPEC) {
// the variable isn't a bitfield, but it's cast to one here.
bitfield_info =
dynamic_cast<BitFieldType*>(env.dts->ts.lookup_type(arg0_reg_type.typespec()));
if (bitfield_info) {
bitfield_type = arg0_reg_type.typespec();
}
}
}
@@ -6288,6 +6480,21 @@ void ReturnElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
namespace {
bool is_zero_extended_32(const Env& env, const RegisterAccess& var) {
const auto& ops = env.func->ir2.atomic_ops->ops;
const auto& defs = env.get_use_def_info(var).defs;
if (defs.empty()) {
return false;
}
for (const auto& def : defs) {
auto load = dynamic_cast<const LoadVarOp*>(ops.at(def.op_id).get());
if (!load || load->kind() != LoadVarOp::Kind::UNSIGNED || load->size() > 4) {
return false;
}
}
return true;
}
void push_asm_srl_to_stack(const AsmOp* op,
FormElement* form_elt,
const Env& env,
@@ -6325,6 +6532,19 @@ void push_asm_srl_to_stack(const AsmOp* op,
ASSERT(other); // should immediately get a field.
stack.push_value_to_reg(*dst, pool.alloc_single_form(nullptr, other), true,
env.get_variable_type(*dst, true));
} else if (integer > 0 && env.dts->ts.tc(TypeSpec("integer"), arg0_type)) {
// srl shifts the lower 32 bits, the result is always zero-extended.
Form* low = src_var;
if (!is_zero_extended_32(env, *var)) {
low = pool.form<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::LOGAND), src_var,
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(UINT32_MAX)));
}
auto shr = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SHR), low,
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(integer)));
stack.push_value_to_reg(*dst, pool.alloc_single_form(nullptr, shr), true,
env.get_variable_type(*dst, true));
} else {
stack.push_form_element(form_elt, true);
// throw std::runtime_error(
@@ -6666,24 +6886,44 @@ void DynamicMethodAccess::update_from_stack(const Env& env,
auto reg1_matcher =
Matcher::match_or({Matcher::any_reg(1), Matcher::cast("int", Matcher::any_reg(1))});
bool is_type_parent = false;
// (+ (* method-id 4) (the-as int child-type))
auto mult_matcher =
Matcher::op_fixed(FixedOperatorKind::MULTIPLICATION, {reg0_matcher, Matcher::integer(4)});
auto matcher = Matcher::op_fixed(FixedOperatorKind::ADDITION, {mult_matcher, reg1_matcher});
auto match_result = match(matcher, new_val);
if (!match_result.matched) {
throw std::runtime_error("Could not match DynamicMethodAccess values: " +
new_val->to_string(env));
// check for access like (-> some-type parent)
auto reg0_matcher0 =
Matcher::match_or({Matcher::any_reg(0), Matcher::cast("uint", Matcher::any_reg(0))});
auto reg1_matcher0 = Matcher::cast(
"int", Matcher::deref(Matcher::any_reg(1), false, {DerefTokenMatcher::string("parent")}));
auto mult_matcher0 =
Matcher::op_fixed(FixedOperatorKind::MULTIPLICATION, {reg0_matcher0, Matcher::integer(4)});
auto matcher0 = Matcher::op_fixed(FixedOperatorKind::ADDITION, {mult_matcher0, reg1_matcher0});
auto m_result = match(matcher0, new_val);
if (m_result.matched) {
is_type_parent = true;
match_result = m_result;
} else {
throw std::runtime_error("Could not match DynamicMethodAccess values: " +
new_val->to_string(env));
}
}
auto idx = match_result.maps.regs.at(0);
auto base = match_result.maps.regs.at(1);
ASSERT(idx.has_value() && base.has_value());
auto deref = pool.alloc_element<DerefElement>(
var_to_form(base.value(), pool), false,
std::vector<DerefToken>{DerefToken::make_field_name("method-table"),
DerefToken::make_int_expr(var_to_form(idx.value(), pool))});
std::vector<DerefToken> token;
if (is_type_parent) {
token.push_back(DerefToken::make_field_name("parent"));
}
token.push_back(DerefToken::make_field_name("method-table"));
token.push_back(DerefToken::make_int_expr(var_to_form(idx.value(), pool)));
auto deref = pool.alloc_element<DerefElement>(var_to_form(base.value(), pool), false, token);
result->push_back(deref);
}
@@ -6691,11 +6931,48 @@ void DynamicMethodAccess::update_from_stack(const Env& env,
// ArrayFieldAccess
////////////////////////
/*!
* Rebuild an access into a 2d array from (+ (* idx stride) (* idx2 stride2) constant base), in any
* order and nesting.
*/
void ArrayFieldAccess::update_with_val_2d(Form* new_val,
const Env& env,
FormPool& pool,
std::vector<FormElement*>* result) {
std::optional<Match2dIndices> match;
if (std::find(m_index_strides.begin(), m_index_strides.end(), 1) != m_index_strides.end()) {
// the base can't be told apart from a stride 1 index, so use the order of the last add.
auto as_generic = strip_int_or_uint_cast(new_val)->try_as_element<GenericElement>();
if (as_generic && as_generic->elts().size() == 2 &&
(as_generic->op().is_fixed(FixedOperatorKind::ADDITION) ||
as_generic->op().is_fixed(FixedOperatorKind::ADDITION_PTR))) {
auto base = as_generic->elts().at(m_flipped ? 1 : 0);
auto rest = as_generic->elts().at(m_flipped ? 0 : 1);
match = match_2d_indices(rest, m_index_strides, m_index_constant, false, env, pool);
if (match) {
match->base = strip_int_or_uint_cast(base);
}
}
} else {
match = match_2d_indices(new_val, m_index_strides, m_index_constant, true, env, pool);
}
if (!match) {
throw std::runtime_error("Failed to match 2d array access: " + new_val->to_string(env));
}
result->push_back(pool.alloc_element<DerefElement>(
match->base, false, fill_2d_index_placeholders(m_deref_tokens, *match)));
}
void ArrayFieldAccess::update_with_val(Form* new_val,
const Env& env,
FormPool& pool,
std::vector<FormElement*>* result,
bool) {
if (!m_index_strides.empty()) {
update_with_val_2d(new_val, env, pool, result);
return;
}
int power_of_two = 0;
if (m_constant_offset == 0) {
+133 -2
View File
@@ -356,6 +356,52 @@ std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
return {};
}
/*!
* Setting a field to a field of another bitfield:
* (shl (the-as int (-> other g)) 8) or just (-> other r) for a field at bit 0.
* Only allowed if the field we read fits in the field we set
*/
std::optional<BitFieldDef> get_bitfield_set_from_field_read(Form* value,
const BitField& field,
int offset_in_bitfield,
const TypeSystem& ts,
const Env& env) {
Form* read = strip_int_or_uint_cast(value);
int shift = 0;
auto shl_matcher = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHL),
{Matcher::any(0), Matcher::any_integer(1)});
auto mr = match(shl_matcher, read);
if (mr.matched) {
read = strip_int_or_uint_cast(mr.maps.forms.at(0));
shift = mr.maps.ints.at(1);
}
if (shift != field.offset() - offset_in_bitfield) {
return std::nullopt;
}
auto deref = read->try_as_element<DerefElement>();
if (!deref || deref->is_addr_of() || deref->tokens().size() != 1 ||
deref->tokens().front().kind() != DerefToken::Kind::FIELD_NAME) {
return std::nullopt;
}
auto base = form_as_atom(deref->base());
if (!base || !base->is_var()) {
return std::nullopt;
}
auto read_type =
dynamic_cast<BitFieldType*>(ts.lookup_type(env.get_variable_type(base->var(), true)));
BitField read_field;
if (!read_type || !read_type->lookup_field(deref->tokens().front().field_name(), &read_field) ||
read_field.size() > field.size()) {
return std::nullopt;
}
BitFieldDef def;
def.value = read;
def.field_name = field.name();
def.is_signed = false;
return def;
}
} // namespace
void BitfieldAccessElement::push_pcpyud(const TypeSystem& ts, FormPool& pool, const Env& /*env*/) {
@@ -490,8 +536,11 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
int size = 64 - step.amount;
int start_bit = end_bit - size;
bool neg = false;
int neg_shift = 0;
if (start_bit < 0) {
// throw std::runtime_error("push_step: Bad bitfield start bit");
// the field ends up shifted left by however much the right shift fell short.
neg_shift = -start_bit;
size += start_bit;
start_bit = 0;
neg = true;
@@ -509,7 +558,7 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
auto result = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::SHL),
pool.form<CastElement>(TypeSpec("int"), pool.alloc_single_form(nullptr, deref)),
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(64 - step.amount)));
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(neg_shift)));
return result;
} else {
return deref;
@@ -621,6 +670,9 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
ASSERT(field);
auto val = get_bitfield_initial_set(step.value, as_bitfield, ts, pcpyud_offset);
if (!val) {
val = get_bitfield_set_from_field_read(step.value, *field, pcpyud_offset, ts, env);
}
if (!val) {
throw std::runtime_error(
@@ -781,6 +833,81 @@ Form* cast_sound_name(FormPool& pool, const Env& env, Form* in) {
return pool.form<ConstantTokenElement>(fmt::format("(static-sound-name \"{}\")", name));
}
std::optional<std::vector<Form*>> masked_sets_to_logior_args(const BitFieldType* type_info,
Form* in,
FormPool& pool,
const Env& env) {
auto any_matcher = [](int i) {
return Matcher::match_or({Matcher::cast("uint", Matcher::any(i)),
Matcher::cast("int", Matcher::any(i)), Matcher::any(i)});
};
auto clear_matcher =
Matcher::op_fixed(FixedOperatorKind::LOGAND, {any_matcher(0), any_matcher(1)});
auto set_matcher = Matcher::match_or(
{Matcher::op_fixed(FixedOperatorKind::LOGIOR, {clear_matcher, any_matcher(2)}),
Matcher::op_fixed(FixedOperatorKind::LOGIOR, {any_matcher(2), clear_matcher})});
struct FieldSet {
u64 mask;
Form* value;
};
std::vector<FieldSet> sets;
Form* base = strip_int_or_uint_cast(in);
while (true) {
auto mr = match(set_matcher, base);
if (!mr.matched) {
break;
}
auto mask = get_goal_integer_constant(strip_int_or_uint_cast(mr.maps.forms.at(1)), env);
if (!mask) {
break;
}
sets.push_back({*mask, mr.maps.forms.at(2)});
base = strip_int_or_uint_cast(mr.maps.forms.at(0));
}
auto constant = get_goal_integer_constant(base, env);
if (sets.empty() || !constant) {
return std::nullopt;
}
u64 constant_bits = *constant;
u64 dynamic_bits = 0;
std::vector<Form*> dynamic_values;
// innermost set first
for (auto it = sets.rbegin(); it != sets.rend(); ++it) {
auto& set = *it;
if (dynamic_bits & ~set.mask) {
// clears a field we already set, not a static def.
return std::nullopt;
}
constant_bits &= set.mask;
auto value = strip_int_or_uint_cast(set.value);
auto value_constant = get_goal_integer_constant(value, env);
if (value_constant) {
if (*value_constant & set.mask) {
return std::nullopt;
}
constant_bits |= *value_constant;
continue;
}
auto field = find_field_from_mask(env.dts->ts, type_info, ~set.mask, false);
auto def = get_bitfield_initial_set(value, type_info, env.dts->ts, 0);
if (!field || !def || def->field_name != field->name()) {
return std::nullopt;
}
dynamic_bits |= ~set.mask;
dynamic_values.push_back(set.value);
}
std::vector<Form*> args = {
pool.form<SimpleAtomElement>(SimpleAtom::make_int_constant(constant_bits))};
args.insert(args.end(), dynamic_values.begin(), dynamic_values.end());
return args;
}
std::optional<std::vector<BitFieldDef>> get_field_defs_from_expr(const BitFieldType* type_info,
Form* in,
const TypeSpec& typespec,
@@ -789,7 +916,11 @@ std::optional<std::vector<BitFieldDef>> get_field_defs_from_expr(const BitFieldT
std::optional<int> offset) {
auto in_as_generic = strip_int_or_uint_cast(in)->try_as_element<GenericElement>();
std::vector<Form*> args;
if (in_as_generic && in_as_generic->op().is_fixed(FixedOperatorKind::LOGIOR)) {
auto masked_args =
offset.value_or(0) == 0 ? masked_sets_to_logior_args(type_info, in, pool, env) : std::nullopt;
if (masked_args) {
args = *masked_args;
} else if (in_as_generic && in_as_generic->op().is_fixed(FixedOperatorKind::LOGIOR)) {
args = compact_nested_logiors(in_as_generic, env);
} else {
args = {strip_int_or_uint_cast(in)};
+1 -1
View File
@@ -669,7 +669,7 @@ void ObjectFileDB::write_disassembly(const fs::path& output_dir,
if (dump_function_metadata) {
json data = file_func_metadata_map;
file_util::write_text_file(output_dir / "func_metadata.json", data.dump(2));
file_util::write_text_file(output_dir / "_func_metadata.json", data.dump(2));
}
lg::info("Wrote functions dumps:");
+15 -2
View File
@@ -82,12 +82,14 @@ struct LetRewriteStats {
int call_parent_state_handler = 0;
int suspend_for = 0;
int font_method = 0;
int light_trail_tracker_spawn = 0;
int total() const {
return dotimes + countdown + abs + abs2 + unused + ja + case_no_else + case_with_else +
set_vector + set_vector2 + send_event + font_context_meth + proc_new + attack_info +
vector_dot + rand_float_gen + set_let + with_dma_buf_add_bucket + dma_buffer_add_gs_set +
launch_particles + call_parent_state_handler + suspend_for + font_method;
launch_particles + call_parent_state_handler + suspend_for + font_method +
light_trail_tracker_spawn;
}
std::string print() const {
@@ -117,6 +119,7 @@ struct LetRewriteStats {
out += fmt::format(" call_parent_state_handler: {}\n", call_parent_state_handler);
out += fmt::format(" suspend_for: {}\n", suspend_for);
out += fmt::format(" font_method: {}\n", font_method);
out += fmt::format(" light_trail_tracker_spawn: {}\n", light_trail_tracker_spawn);
return out;
}
@@ -143,6 +146,7 @@ struct LetRewriteStats {
result.launch_particles = launch_particles + other.launch_particles;
result.call_parent_state_handler = call_parent_state_handler + other.call_parent_state_handler;
result.suspend_for = suspend_for + other.suspend_for;
result.light_trail_tracker_spawn = light_trail_tracker_spawn + other.light_trail_tracker_spawn;
return result;
}
@@ -168,6 +172,7 @@ struct LetRewriteStats {
launch_particles += other.launch_particles;
call_parent_state_handler += other.call_parent_state_handler;
suspend_for += other.suspend_for;
light_trail_tracker_spawn += other.light_trail_tracker_spawn;
return *this;
}
};
@@ -383,12 +388,20 @@ class ObjectFileDB {
[[maybe_unused]] int fn = 0;
if (data.linked_data.segments == 3) {
for (size_t j = data.linked_data.functions_by_seg.at(seg).size(); j-- > 0;) {
f(data.linked_data.functions_by_seg.at(seg).at(j));
auto& func = data.linked_data.functions_by_seg.at(seg).at(j);
if (ir2_function_filter && &func != ir2_function_filter) {
continue;
}
f(func);
fn++;
}
}
}
// if set, ir2 passes only run on this function (used to re-analyze one function
// for the asm branch permuter)
const Function* ir2_function_filter = nullptr;
// Danger: after adding all object files, we assume that the vector never reallocates.
std::unordered_map<std::string, std::vector<ObjectFileData>> obj_files_by_name;
std::unordered_map<std::string, std::vector<ObjectFileRecord>> obj_files_by_dgo;
@@ -578,7 +578,7 @@ int get_start_idx_process(Function& function,
return -1;
}
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind ::IDENTITY,
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind::IDENTITY,
Register(Reg::GPR, Reg::GP), Register(Reg::GPR, Reg::GP))) {
lg::print("[iim] op 2 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env), function.name());
return -1;
@@ -764,7 +764,7 @@ int get_start_idx(Function& function,
return -1;
}
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind ::IDENTITY,
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind::IDENTITY,
Register(Reg::GPR, Reg::GP), Register(Reg::GPR, Reg::GP))) {
lg::print("[iim] op 2 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env), function.name());
return -1;
@@ -827,7 +827,7 @@ int get_start_idx(Function& function,
}
op_idx++;
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind ::IDENTITY,
if (!is_op_2(aos.ops.at(op_idx).get(), SimpleExpression::Kind::IDENTITY,
Register(Reg::GPR, Reg::A2), Register(Reg::GPR, Reg::GP))) {
lg::print("[iim] op 8 bad in {}: {}\n", aos.ops.at(op_idx)->to_string(env), function.name());
return -1;
+3 -1
View File
@@ -1855,9 +1855,11 @@ std::unique_ptr<AtomicOp> convert_5(const Instruction& i0,
break;
case GameVersion::Jak2:
case GameVersion::Jak3:
case GameVersion::JakX:
process_offset = 48;
break;
case GameVersion::JakX:
process_offset = 56;
break;
default:
ASSERT(false);
}
+14 -6
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);
@@ -180,8 +181,14 @@ void clean_up_return_final(const Function& f, ReturnElement* ir) {
ASSERT(dead);
auto src = dynamic_cast<SimpleExpressionElement*>(dead->src()->try_as_single_element());
ASSERT(src);
ASSERT(src->expr().is_identity() && src->expr().get_arg(0).is_int() &&
src->expr().get_arg(0).get_int() == 0);
auto ok = src->expr().is_identity() && src->expr().get_arg(0).is_int() &&
src->expr().get_arg(0).get_int() == 0;
if (!ok) {
throw std::runtime_error(
fmt::format("secondary assertion hit in `clean_up_return_final` in function: {} ",
f.guessed_name.to_string()));
}
ASSERT(ok);
ir->dead_code = nullptr;
}
@@ -1974,7 +1981,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);
+308
View File
@@ -1810,6 +1810,308 @@ FormElement* rewrite_part_tracker_new_jak2(const std::string& type,
->try_as_single_element();
}
FormElement* rewrite_light_trail_tracker_spawn(LetElement* in, const Env& env, FormPool& pool) {
// (let ((s5-0 (new 'stack-no-clear 'light-trail-tracker-spawn-params)))
// (set! (-> s5-0 tracked-obj) (process->handle this))
// (set! (-> s5-0 appearance) *blue-shot-trail*)
// (set! (-> s5-0 max-num-crumbs) (the int (* 0.2 (the float (-> s5-0 appearance max-age)))))
// (set! (-> s5-0 track-immediately?) #t)
// (let* ((v1-30 (estimate-light-trail-mem-usage
// (the-as uint (-> s5-0 max-num-crumbs))
// (the-as uint (= (-> s5-0 appearance lie-mode) (lie-mode use-two-strips)))))
// (s4-0 (get-process *default-dead-pool* light-trail-tracker-blue-3 (+ v1-30 8192) 1)))
// (when s4-0
// (let ((t9-4 (method-of-type process activate)))
// (t9-4 s4-0 this "light-trail" (the-as pointer #x70004000)))
// (run-now-in-process s4-0 light-trail-tracker-init-by-other s5-0)
// (-> s4-0 ppointer))))
// ->
// (light-trail-tracker-spawn light-trail-tracker-blue-3 :to this
// :params ((tracked-obj (process->handle this))
// (appearance *blue-shot-trail*)
// (max-num-crumbs (the int (* 0.2 (the float (-> *blue-shot-trail* max-age)))))
// (track-immediately? #t)))
if (env.version < GameVersion::Jak3) {
return nullptr;
}
if (in->entries().size() != 1) {
return nullptr;
}
auto params_var = in->entries().at(0).dest;
const auto& params_reg = params_var.reg();
auto params_src = in->entries().at(0).src->try_as_element<StackStructureDefElement>();
if (!params_src) {
return nullptr;
}
const auto& params_type = params_src->entry().ref_type;
if (!env.dts->ts.tc(TypeSpec("light-trail-tracker-spawn-params"), params_type)) {
return nullptr;
}
if (params_src->entry().hint.container_type != StackStructureHint::ContainerType::NONE) {
return nullptr;
}
auto body = in->body();
if (body->size() < 2) {
return nullptr;
}
// grab all the field setters
std::vector<std::pair<std::string, Form*>> fields;
std::unordered_map<std::string, Form*> field_values;
for (size_t idx = 0; idx + 1 < body->size(); ++idx) {
auto set_mr = match(Matcher::set(Matcher::deref(Matcher::reg(params_reg), false,
{DerefTokenMatcher::any_string(0)}),
Matcher::any(1)),
body->at(idx));
if (!set_mr.matched) {
return nullptr;
}
const auto& field_name = set_mr.maps.strings.at(0);
auto field_val = set_mr.maps.forms.at(1);
fields.emplace_back(field_name, field_val);
field_values[field_name] = field_val;
}
// (let ((v1-30 (estimate...))) (let ((s4-0 (get-process...))) (when s4-0 ...)))
auto mem_let = dynamic_cast<LetElement*>(body->at(body->size() - 1));
if (!mem_let || mem_let->entries().size() != 1 || mem_let->body()->size() != 1) {
return nullptr;
}
// (v1-30 (estimate-light-trail-mem-usage ...))
auto mem_var = mem_let->entries().at(0).dest;
auto est = mem_let->entries().at(0).src->try_as_element<GenericElement>();
if (!est || est->op().kind() != GenericOperator::Kind::FUNCTION_EXPR || !est->op().func() ||
!est->op().func()->to_form(env).is_symbol("estimate-light-trail-mem-usage")) {
return nullptr;
}
auto proc_let = dynamic_cast<LetElement*>(mem_let->body()->at(0));
if (!proc_let || proc_let->entries().size() != 1 || proc_let->body()->size() != 1) {
return nullptr;
}
// (s4-0 (get-process *default-dead-pool* light-trail-tracker-blue-3 (+ v1-30 8192) 1))
auto proc_var = proc_let->entries().at(0).dest;
const auto& proc_reg = proc_var.reg();
auto gp_mr = match(Matcher::func("get-process", {Matcher::any(0), Matcher::any_symbol(1),
Matcher::any(2), Matcher::any_integer(3)}),
proc_let->entries().at(0).src);
if (!gp_mr.matched) {
return nullptr;
}
const auto& proc_type = gp_mr.maps.strings.at(1);
if (!env.dts->ts.tc(TypeSpec("light-trail-tracker"), TypeSpec(proc_type))) {
return nullptr;
}
auto from_form = gp_mr.maps.forms.at(0);
auto unk = gp_mr.maps.ints.at(3);
// stack size is always (+ <estimated-mem> 8192)
if (!match(Matcher::op(GenericOpMatcher::or_match(
{GenericOpMatcher::fixed(FixedOperatorKind::ADDITION),
GenericOpMatcher::fixed(FixedOperatorKind::ADDITION_PTR)}),
{Matcher::reg(mem_var.reg()), Matcher::integer(8192)}),
gp_mr.maps.forms.at(2))
.matched) {
return nullptr;
}
// check the when
auto cast_type = TypeSpec("pointer", {TypeSpec(proc_type)});
auto when_matcher = Matcher::if_no_else(
Matcher::op(GenericOpMatcher::condition(IR2_Condition::Kind::TRUTHY),
{Matcher::reg(proc_reg)}),
Matcher::begin({Matcher::any(0),
Matcher::func_with_rest(Matcher::constant_token("run-now-in-process"),
{Matcher::reg(proc_reg), Matcher::any(1)}),
Matcher::any(2)}));
auto mr_with_shell = rewrite_shelled_return_form(
when_matcher, proc_let->body()->at(0), env, pool,
[&](FormElement* s_in, const MatchResult& /*mr*/, const Env& env_, FormPool& pool_) -> Form* {
auto as_when = dynamic_cast<CondNoElseElement*>(s_in);
if (!as_when) {
return nullptr;
}
const auto& when_body = as_when->entries.front().body->elts();
if (when_body.size() != 3) {
return nullptr;
}
// (let ((t9-4 (method-of-type process activate)))
// (t9-4 s4-0 this "light-trail" (the-as pointer #x70004000)))
auto activate_let = dynamic_cast<LetElement*>(when_body.at(0));
if (!activate_let || activate_let->entries().size() != 1 ||
activate_let->body()->size() != 1) {
return nullptr;
}
if (!match(Matcher::op_fixed(
FixedOperatorKind::METHOD_OF_TYPE,
{Matcher::symbol("process"), Matcher::constant_token("activate")}),
activate_let->entries().at(0).src)
.matched) {
return nullptr;
}
auto act_fn_reg = activate_let->entries().at(0).dest;
auto act_call_mr = match(
Matcher::func(Matcher::reg(act_fn_reg.reg()), {Matcher::reg(proc_reg), Matcher::any(0),
Matcher::any(1), Matcher::any(2)}),
activate_let->body()->at(0));
if (!act_call_mr.matched) {
return nullptr;
}
auto to_form = act_call_mr.maps.forms.at(0);
auto name_form = act_call_mr.maps.forms.at(1);
auto stack_form = act_call_mr.maps.forms.at(2);
// (run-now-in-process s4-0 light-trail-tracker-init-by-other s5-0)
auto run_gen = dynamic_cast<GenericElement*>(when_body.at(1));
if (!run_gen || !run_gen->op().func() ||
!run_gen->op().func()->to_form(env_).is_symbol("run-now-in-process")) {
return nullptr;
}
if (run_gen->elts().size() != 3) {
return nullptr;
}
auto init_form = run_gen->elts().at(1);
if (!match(Matcher::reg(params_reg), run_gen->elts().at(2)).matched) {
return nullptr;
}
// (-> s4-0 ppointer)
auto pptr_matcher =
Matcher::deref(Matcher::reg(proc_reg), false, {DerefTokenMatcher::string("ppointer")});
auto pptr_let = dynamic_cast<LetElement*>(when_body.at(2));
if (pptr_let) {
auto new_pptr = rewrite_empty_let(pptr_let, env, pool);
if (!new_pptr || !match(pptr_matcher, new_pptr).matched) {
return nullptr;
}
} else if (!match(pptr_matcher, when_body.at(2)).matched) {
return nullptr;
}
auto is_simple_base = [](Form* f) {
auto single = f->try_as_single_element();
if (!single) {
return false;
}
return dynamic_cast<DerefElement*>(single) || dynamic_cast<SimpleAtomElement*>(single) ||
dynamic_cast<SimpleExpressionElement*>(single) ||
dynamic_cast<ConstantTokenElement*>(single);
};
// dry run to check we can substitute all the derefs
for (auto& field : fields) {
Form* fval = field.second;
RegAccessSet uses;
fval->collect_vars(uses, true);
int var_uses = 0;
for (const auto& u : uses) {
if (u.reg() == params_reg) {
var_uses++;
}
}
if (var_uses == 0) {
continue;
}
int subst_derefs = 0;
bool bad = false;
fval->apply_form([&](Form* f) {
for (auto* e : f->elts()) {
auto deref = dynamic_cast<DerefElement*>(e);
if (!deref || !match(Matcher::reg(params_reg), deref->base()).matched) {
continue;
}
subst_derefs++;
if (deref->tokens().empty() ||
deref->tokens().at(0).kind() != DerefToken::Kind::FIELD_NAME) {
bad = true;
continue;
}
auto it = field_values.find(deref->tokens().at(0).field_name());
if (it == field_values.end() || !is_simple_base(it->second)) {
bad = true;
}
}
});
if (bad || subst_derefs != var_uses) {
return nullptr;
}
}
// do the inlining
for (auto& field : fields) {
Form* fval = field.second;
fval->apply_form([&](Form* f) {
for (auto*& e : f->elts()) {
auto deref = dynamic_cast<DerefElement*>(e);
if (!deref || !match(Matcher::reg(params_reg), deref->base()).matched) {
continue;
}
auto repl_base = field_values.at(deref->tokens().at(0).field_name());
std::vector rest(deref->tokens().begin() + 1, deref->tokens().end());
if (rest.empty()) {
e = repl_base->try_as_single_element();
} else {
e = pool_.alloc_element<DerefElement>(repl_base, deref->is_addr_of(), rest);
}
}
});
}
std::vector<Form*> args;
args.push_back(pool_.form<ConstantTokenElement>(proc_type));
if (!init_form->to_form(env_).is_symbol("light-trail-tracker-init-by-other")) {
ja_push_form_to_args(pool_, args, init_form, "init");
}
if (params_type != TypeSpec("light-trail-tracker-spawn-params")) {
args.push_back(pool_.form<ConstantTokenElement>(":params-type"));
args.push_back(pool_.form<ConstantTokenElement>(params_type.base_type()));
}
if (!from_form->to_form(env_).is_symbol("*default-dead-pool*")) {
ja_push_form_to_args(pool_, args, from_form, "from");
}
ja_push_form_to_args(pool_, args, to_form, "to");
auto name_str = dynamic_cast<StringConstantElement*>(name_form->try_as_single_element());
if (!name_str || name_str->value() != "light-trail") {
ja_push_form_to_args(pool_, args, name_form, "name");
}
if (stack_form->to_string(env_) != "(the-as pointer #x70004000)") {
ja_push_form_to_args(pool_, args, stack_form, "stack");
}
if (unk != 1) {
args.push_back(pool_.form<ConstantTokenElement>(":unk"));
args.push_back(pool_.form<ConstantTokenElement>(fmt::format("{}", unk)));
}
std::vector<Form*> param_pairs;
for (auto& [fname, fval] : fields) {
param_pairs.push_back(pool_.form<GenericElement>(
GenericOperator::make_function(pool_.form<ConstantTokenElement>(fname)), fval));
}
args.push_back(pool_.form<ConstantTokenElement>(":param-list"));
auto params_head = GenericOperator::make_function(param_pairs.at(0));
std::vector params_rest(param_pairs.begin() + 1, param_pairs.end());
args.push_back(pool_.form<GenericElement>(params_head, params_rest));
return pool_.form<GenericElement>(
GenericOperator::make_function(
pool_.form<ConstantTokenElement>("light-trail-tracker-spawn")),
args);
},
&cast_type);
if (!std::get<0>(mr_with_shell).matched) {
return nullptr;
}
return std::get<1>(mr_with_shell)->try_as_single_element();
}
FormElement* rewrite_call_parent_state_handler(LetElement* in, const Env& env, FormPool& pool) {
// (let ((t9-3 (-> (find-parent-state) code)))
// (if t9-3
@@ -2501,6 +2803,12 @@ FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool, LetRewr
return as_abs;
}
auto as_light_trail_tracker_spawn = rewrite_light_trail_tracker_spawn(in, env, pool);
if (as_light_trail_tracker_spawn) {
stats.light_trail_tracker_spawn++;
return as_light_trail_tracker_spawn;
}
auto as_proc_new = rewrite_proc_new(in, env, pool);
if (as_proc_new) {
stats.proc_new++;
+3
View File
@@ -336,6 +336,9 @@ Config make_config_via_json(nlohmann::json& json) {
if (json.contains("rip_streamed_audio")) {
config.rip_streamed_audio = json.at("rip_streamed_audio").get<bool>();
}
if (json.contains("rip_music")) {
config.rip_music = json.at("rip_music").get<bool>();
}
if (inputs_json.contains("animated_textures")) {
config.animated_textures =
+1
View File
@@ -177,6 +177,7 @@ struct Config {
bool levels_extract;
bool save_texture_pngs = false;
bool rip_streamed_audio = false;
bool rip_music = false;
DecompileHacks hacks;
+141 -7
View File
@@ -3790,7 +3790,7 @@
(deftype vif-bank (structure)
((stat uint32 :offset-assert 0)
(fbrst uint32 :offset 16)
(fbrst vif-fbrst :offset 16)
(err vif-err :offset 32)
(mark uint32 :offset 48)
(cycle uint32 :offset 64)
@@ -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
+4 -1
View File
@@ -127,9 +127,12 @@
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio/sfx and decompiler_out/<game>/audio/voice_lines
"rip_streamed_audio": false,
// whether or not to dump out music files to decompiler_out/<game>/audio/music
"rip_music": false,
////////////////////////////
// PATCHING OPTIONS
////////////////////////////
@@ -90,11 +90,6 @@
"symlink2", // F: asm branching
"dma-sync-hang",
// display
"vblank-handler", // F: weird asm for interrupt handler
"vif1-handler", // F: weird asm for interrupt handler
"vif1-handler-debug",
// texture
"adgif-shader<-texture!",
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
@@ -3066,7 +3066,7 @@
(deftype vif-bank (structure)
((stat uint32 :offset-assert 0)
(fbrst uint32 :offset 16)
(fbrst vif-fbrst :offset 16)
(err vif-err :offset 32)
(mark uint32 :offset 48)
(cycle uint32 :offset 64)
@@ -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
)
@@ -34427,7 +34427,7 @@ Consists of a header and a list of [[merc-effect]]s."
"Incremented everytime a metric is sampled
@see [[timer0-handler]]"
int)
(define-extern timer0-handler (function none))
(define-extern timer0-handler (function int int int none))
(define-extern sampler-start
"Reset the [[timer-bank]] EE registers.
- If [[*sampler-mem*]] is undefined, allocate 16.7MB in the debug segment
+4 -1
View File
@@ -133,9 +133,12 @@
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio/sfx and decompiler_out/<game>/audio/voice_lines
"rip_streamed_audio": false,
// whether or not to dump out music files to decompiler_out/<game>/audio/music
"rip_music": false,
////////////////////////////
// PATCHING OPTIONS
////////////////////////////
@@ -367,7 +367,6 @@
[[35, 37], "a3", "qword"],
[[35, 37], "a2", "qword"]
],
"(top-level-login eye-h)": [[[69, 77], "a1", "eye-control"]],
"entity-actor-lookup": [["_stack_", 16, "res-tag"]],
"entity-actor-count": [["_stack_", 16, "res-tag"]],
"(method 0 path-control)": [["_stack_", 16, "res-tag"]],
@@ -10020,7 +10019,8 @@
[111, "v1", "shadow-dcache"],
[116, "a0", "uint32"],
[[188, 246], "gp", "shadow-dcache"],
[93, "v1", "shadow-dcache"]
[93, "v1", "shadow-dcache"],
[123, "a1", "gs-rgbaq"]
],
"(method 40 battle)": [[26, "v0", "enemy-option"]],
"(method 9 texture-anim)": [
@@ -10157,5 +10157,16 @@
],
"(method 206 hal)": [[32, "a2", "bot"]],
"(method 209 hal)": [[32, "v1", "bot"]],
"(method 220 hal)": [[29, "v1", "bot"]]
"(method 220 hal)": [[29, "v1", "bot"]],
"vif1-handler": [
[1, "v1", "vif-bank"],
[4, "a0", "vif-bank"]
],
"vif1-handler-debug": [
[2, "a0", "vif-bank"],
[9, "a1", "timer-bank"],
[48, "v1", "vif-bank"],
[51, "a0", "vif-bank"]
],
"timer0-handler": [[17, "a0", "timer-bank"]]
}
@@ -4369,6 +4369,12 @@
"s3-1": ["points", "(inline-array vector)"]
}
},
"(method 10 menu-slider-option)": {
"vars": {
"sv-160": ["sv-160", "rgba"],
"sv-240": ["sv-240", "rgba"]
}
},
"(method 10 menu-missions-option)": {
"args": ["this", "progress", "font-ctx", "arg3", "arg4"],
"vars": {
+40 -60
View File
@@ -3199,7 +3199,7 @@
(deftype vif-bank (structure)
((stat uint32 :offset-assert 0)
(fbrst uint32 :offset 16)
(fbrst vif-fbrst :offset 16)
(err vif-err :offset 32)
(mark uint32 :offset 48)
(cycle uint32 :offset 64)
@@ -7782,7 +7782,6 @@
(load-buffer-mode level-memory-mode :offset-assert 4624) ;; guessed by decompiler
(display-start-time uint64 :offset-assert 4632) ;; time-frame
(memory-mask uint32 :offset-assert 4640)
; (UNKNOWN UNKNOWN :offset-assert -1) ;; field could not be read.
(task-mask task-mask :offset-assert 4644)
(tfrag-gs-test gs-test :offset-assert 4648)
(texture-dirty-masks texture-mask 11 :inline :offset-assert 4656) ;; guessed by decompiler
@@ -7808,9 +7807,7 @@
(level-type type :offset-assert 5368) ;; guessed by decompiler
(load-order uint64 :offset-assert 5376) ;; int64
(eye-slot-lowres uint8 11 :offset-assert 5384)
; (UNKNOWN UNKNOWN :offset-assert -1) ;; field could not be read.
(eye-slot-highres uint8 11 :offset-assert 5395)
; (UNKNOWN UNKNOWN :offset-assert -1) ;; field could not be read.
(unknown-pad uint8 14)
)
:method-count-assert 30
@@ -8834,7 +8831,7 @@
(progress-subtitles #x006e)
(progress-restart-mission #x006f)
(text-0072 #x0072)
(text-0073 #x0073)
(progress-saved-game #x0073)
(progress-qr #x0074)
(text-0075 #x0075)
(text-0076 #x0076)
@@ -11257,25 +11254,25 @@
;; +++settings-h:game-score
(defenum game-score
:type uint64
:type uint8
(none)
(gs0)
(gs1)
(gs2)
(gs3)
(gs4)
(gs5)
(gs6)
(gs7)
(gs8)
(gs9)
(gs10)
(gs11)
(gs12)
(gs13)
(gs14)
(gs15)
(gs16)
(neo-sat-game)
(turtle-race)
(snake-race)
(snake-air-time)
(snake-total-air-time)
(snake-jump-distance)
(snake-total-jump-distance)
(snake-roll-count)
(wascity-gungame-1)
(hoverboard)
(gungame-1)
(gungame-2)
(gungame-3)
(gungame-4)
(power-game)
(destroy-interceptors)
(arena-training)
(gs17)
(gs18)
(gs19)
@@ -15264,26 +15261,6 @@
:flag-assert #x900000100
)
#|
(deftype gsf-vertex-array (UNKNOWN)
((vtx gsf-vertex :dynamic :offset-assert 0) ;; guessed by decompiler
)
:method-count-assert 0
:size-assert #x0
:flag-assert #x0
)
|#
#|
(deftype gsf-fx-vertex-array (UNKNOWN)
((data gsf-fx-vertex :dynamic :offset-assert 0) ;; guessed by decompiler
)
:method-count-assert 0
:size-assert #x0
:flag-assert #x0
)
|#
(deftype gsf-vertex-array (structure)
((vtx gsf-vertex :dynamic :offset-assert 0)
)
@@ -17699,11 +17676,11 @@
(you-suck-stage (_type_ symbol int) int) ;; 24
(you-suck-scale (_type_ symbol int) float) ;; 25
(get-next-attack-id! (_type_) uint) ;; 26
(game-info-method-27 (_type_ game-score float) int) ;; 27
(get-game-score-ref (_type_ int) (pointer float)) ;; 28
(game-info-method-29 (_type_ int) int) ;; 29
(get-highscore-rank (_type_ int float) int) ;; 30
(game-info-method-31 (_type_ int int) float) ;; 31
(update-high-score! (_type_ game-score float) int) ;; 27
(get-game-score-ref (_type_ game-score) (pointer float)) ;; 28
(get-best-rank (_type_ game-score) int) ;; 29
(get-rank-for-score (_type_ game-score float) int) ;; 30
(get-goal-for-rank (_type_ game-score int) float) ;; 31
(calculate-percentage (_type_) float) ;; 32
(inc-death-count! (_type_) none) ;; 33
(get-max-ammo-for-gun (_type_ pickup-type) float) ;; 34
@@ -20818,6 +20795,7 @@
;; joint-mod-h ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; +++joint-mod-h:joint-mod-mode
(defenum joint-mod-mode
:bitfield #t
:type uint32
@@ -20835,6 +20813,7 @@
(foot-rot)
(joint-set-world)
)
;; ---joint-mod-h:joint-mod-mode
;; +++joint-mod-h:track-mode
(defenum track-mode
@@ -20850,6 +20829,7 @@
)
;; ---joint-mod-h:track-mode
;; +++joint-mod-h:joint-mod-ik-flags
(defenum joint-mod-ik-flags
:bitfield #t
:type uint32
@@ -20857,6 +20837,7 @@
(elbow-trans-neg)
(elbow-rot-neg)
)
;; ---joint-mod-h:joint-mod-ik-flags
(deftype joint-mod (basic)
"Utility to modify a joint transform from code, rather than just getting it from animation.
@@ -21045,7 +21026,6 @@
)
;; added - I really have no idea what is going on here
(deftype joint-mod-blend-world-work (structure)
((mat1 matrix :inline)
(mat2 matrix :inline)
@@ -26196,7 +26176,7 @@
)
(deftype entity-camera (entity)
((connect connectable :inline :offset-assert 64)
((quat quaternion :inline :offset-assert 64)
)
:flag-assert #x1b00000050
)
@@ -28111,7 +28091,7 @@
(draw-bg-box-outline (_type_ progress-box float) object) ;; 41
(draw-bg-box-alpha-2 (_type_ progress-box float) object) ;; 42
(draw-bg-box-alpha-1 (_type_ progress-box float) object) ;; 43
(progress-method-44 (_type_ font-context string) object) ;; 44
(draw-button-text (_type_ font-context string) object) ;; 44
(progress-method-45 (_type_ font-context float float string float float int) float) ;; 45
(draw-header (_type_ font-context float text-id) object) ;; 46
(progress-method-47 (_type_ font-context symbol symbol) object) ;; 47
@@ -28483,7 +28463,7 @@
(deftype highscore-page-info (structure)
((text text-id :offset-assert 0)
(secret game-secrets :offset-assert 8)
(game-score uint8 :offset-assert 16)
(game-score game-score :offset-assert 16)
(icon uint32 :offset-assert 20)
(icon-scalex float :offset-assert 24)
(icon-scaley float :offset-assert 28)
@@ -41064,7 +41044,7 @@
(define-extern *sampler-mem* pointer)
(define-extern *sampler-compare* uint)
(define-extern *sampler-count* int)
(define-extern timer0-handler (function none))
(define-extern timer0-handler (function int int int none))
(define-extern sampler-start (function none))
(define-extern sampler-stop (function none))
@@ -48177,7 +48157,7 @@
(been-out-of-turret? symbol :offset-assert 436)
(won? symbol :offset-assert 440)
(lost? symbol :offset-assert 444)
(game-score uint8 :offset-assert 448)
(game-score game-score :offset-assert 448)
(task-gold uint16 :offset-assert 450)
(task-silver uint16 :offset-assert 452)
(task-bronze uint16 :offset-assert 454)
@@ -52847,7 +52827,7 @@
(hud-score handle :offset-assert 312)
(hud-goal handle :offset-assert 320)
(squad-manager handle :offset 336)
(game-score uint8 :offset-assert 344)
(game-score game-score :offset-assert 344)
(last-cup uint8 :offset-assert 345)
(goal-cup uint8 :offset-assert 346)
(new-high-score symbol :offset-assert 348)
@@ -66121,7 +66101,7 @@
)
(deftype task-manager-bbush-time-trial-1 (task-manager-race)
((game-score uint8 :offset-assert 280)
((game-score game-score :offset-assert 280)
(hud-goal handle :offset-assert 288)
)
:method-count-assert 39
@@ -66143,7 +66123,7 @@
)
(deftype task-manager-bbush-rally (task-manager-race)
((game-score uint8 :offset-assert 280)
((game-score game-score :offset-assert 280)
(hud-goal handle :offset-assert 288)
)
:method-count-assert 39
@@ -68167,7 +68147,7 @@
(task-bronze game-task-node :offset-assert 20)
(task-silver game-task-node :offset 22)
(task-gold game-task-node :offset 24)
(game-score uint8 :offset 26)
(game-score game-score :offset 26)
(pass-speech uint16 :offset-assert 28)
(training-goal float :offset-assert 32)
(allowed-guns game-feature :offset-assert 40)
@@ -68218,7 +68198,7 @@
(task-bronze game-task-node :offset 428)
(end-door uint8 :offset 430)
(start-door uint8 :offset-assert 431)
(game-score uint8 :offset-assert 432)
(game-score game-score :offset-assert 432)
(training-goal float :offset-assert 436)
(training? symbol :offset-assert 440)
(state-time time-frame :offset-assert 448)
@@ -70429,7 +70409,7 @@
(challenge-done symbol :offset-assert 244)
(hud-score handle :offset-assert 248)
(hud-goal handle :offset-assert 256)
(game-score uint8 :offset-assert 264)
(game-score game-score :offset-assert 264)
(new-high-score symbol :offset-assert 268)
(goal-cup uint8 :offset-assert 272)
(last-cup uint8 :offset-assert 273)
+1 -1
View File
@@ -132,7 +132,7 @@
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio/sfx and decompiler_out/<game>/audio/voice_lines
"rip_streamed_audio": false,
////////////////////////////
+2 -97
View File
@@ -1,47 +1,29 @@
{
////////////////////////////
// HACKS and ASM FUNCTIONS
////////////////////////////
"types_with_bad_inspect_methods": [
"game-task-event",
"game-task-control",
"predator-edge",
"manipy"
],
"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",
// actual asm
"quad-copy!",
"return-from-thread",
"return-from-thread-dead",
@@ -69,7 +51,6 @@
"qword-read-time",
"dma-test-func",
"move-test-func",
"symlink2",
"blerc-a-fragment",
"blerc-execute",
@@ -79,13 +60,7 @@
"(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",
"test-to-from-spr",
"test-from-spr",
"test-to-spr",
@@ -93,16 +68,10 @@
"test-worst-read",
"test-seq-write",
"test-worst-write",
// texture
"adgif-shader<-texture!",
// jak 3
"(method 46 ff-squad-control)",
"memcpy"
],
// these functions use pairs and the decompiler
// will be less picky about types related to pairs.
"pair_functions_by_name": [
"ref",
"ref&",
@@ -124,7 +93,6 @@
"lookup-level-info",
"(method 24 level-group)",
"(method 19 level-group)",
// script
"command-get-time",
"command-get-param",
"command-get-quoted-param",
@@ -144,31 +112,26 @@
"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)",
@@ -213,24 +176,17 @@
"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,
@@ -270,16 +226,13 @@
"~32L~S~44L ~S": 2,
"~44L~S ~32L~S~1L": 2
},
"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],
@@ -302,36 +255,8 @@
"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
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, 39, 43, 45
],
"(method 16 level)": [0, 1, 5, 13, 14, 15],
"upload-vis-bits": [2, 6, 3, 0],
@@ -467,12 +392,6 @@
"(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,
// 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, 0]],
@@ -584,13 +503,11 @@
"(trans carry precur-bomb)": [[60, 0]],
"hover-nav-graph-output": [[319, 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",
@@ -669,12 +586,8 @@
"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)",
@@ -733,11 +646,7 @@
"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": [
["wasintro", 0, 0],
["lfacctyb", 0, 0],
@@ -747,9 +656,5 @@
["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": []
}
@@ -194,11 +194,7 @@
"arrive-at-continue": [[16, "event-message-block"]],
"(code target-hit)": [[16, "vector"]],
"apply-pos-from-entity": [[208, "collide-query"]],
"target-death-main": [
[16, "event-message-block"]
// this wrong stack cast was the reason Daxter's death quotes scenes didn't work
//[96, ["array", "level", 1]]
],
"target-death-main": [[16, "event-message-block"]],
"find-nearest-focusable": [[48, "vector"]],
"target-gun-joint-pre0": [
[640, ["inline-array", "sphere", 1]],
@@ -1943,7 +1939,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]]],
+33 -44
View File
@@ -211,7 +211,6 @@
"dma-buffer-patch-buckets": [
[[3, 34], "a0", "dma-bucket"],
[[34, 38], "a0", "dma-packet"]
// [34, "a0", "(inline-array dma-bucket)"]
],
"disasm-dma-list": [
[43, "v1", "dma-packet"],
@@ -255,11 +254,7 @@
[37, "t0", "(pointer int32)"]
],
"texture-page-dir-inspect": [[[137, 138], "v1", "adgif-shader"]],
"(method 24 texture-pool)": [
[[77, 100], "a1", "adgif-shader"]
// [[70, 93], "a1", "adgif-shader"],
// [92, "a1", "adgif-shader"]
],
"(method 24 texture-pool)": [[[77, 100], "a1", "adgif-shader"]],
"(method 8 res-lump)": [
[258, "s0", "array"],
[[157, 239], "s0", "(array object)"]
@@ -334,7 +329,6 @@
],
"joint-mod-blend-local-callback": [[[1, 28], "gp", "joint-mod-blend-local"]],
"joint-mod-blend-world-callback": [[[1, 150], "gp", "joint-mod-blend-world"]],
"(top-level-login eye-h)": [[77, "a3", "eye-control"]],
"entity-actor-lookup": [["_stack_", 16, "res-tag"]],
"entity-actor-count": [["_stack_", 16, "res-tag"]],
"(method 3 collide-query)": [
@@ -509,7 +503,7 @@
],
"merc-edge-stats": [[31, "v1", "merc-ctrl"]],
"(method 8 merc-ctrl)": [
[46, "s2", "pointer"], // was merc-fragment-control
[46, "s2", "pointer"],
[[22, 45], "s2", "merc-fragment-control"],
[[89, 93], "a1", "merc-blend-ctrl"],
[103, "a1", "pointer"]
@@ -2119,8 +2113,6 @@
[[14, 31], "s5", "adgif-shader"]
],
"add-debug-bound": [
//[105, "v1", "dma-packet"],
//[85, "a0", "dma-packet"],
["_stack_", 16, "dma-packet"],
[91, "v1", "dma-packet"]
],
@@ -2238,12 +2230,10 @@
[789, "v1", "float"],
[792, "v1", "float"],
[794, "v0", "float"],
// [784, "v1", "vector"],
[589, "v1", "float"],
[593, "v1", "float"],
[602, "v1", "float"],
[606, "v1", "float"]
// [796, "v1", "float"]
],
"master-track-target": [
[53, "gp", "process-focusable"],
@@ -2355,7 +2345,10 @@
[213, "s0", "continue-point"],
[222, "s0", "continue-point"]
],
"master-choose-entity": [[162, "s0", "(pointer camera-slave)"]],
"master-choose-entity": [
["_stack_", 96, "res-tag"],
[162, "s0", "(pointer camera-slave)"]
],
"bones-mtx-calc-execute": [
[[126, 154], "a0", "pris-mtx"],
[[126, 154], "a1", "pris-mtx"],
@@ -2552,19 +2545,6 @@
[[470, 515], "s1", "prototype-bucket-shrub"],
[[470, 658], "gp", "prototype-bucket-shrub"],
[[13, 56], "v1", "prototype-bucket-shrub"]
// [[102, 114], "a0", "shrub-near-packet"],
// [[114, 117], "v1", "vector4w-3"],
// [118, "a1", "vector4w"],
// [123, "v1", "dma-packet"],
// [[124, 126], "v1", "vector4w"],
// [[334, 364], "s1", "prototype-bucket-shrub"],
// [416, "a0", "drawable-group"],
// [420, "s1", "prototype-bucket-shrub"],
// [525, "v1", "drawable-group"],
// [[518, 535], "s1", "prototype-bucket-shrub"],
// [558, "s1", "prototype-bucket-shrub"],
// [[677, 718], "gp", "prototype-bucket-shrub"],
// [[696, 706], "a1", "prototype-bucket-shrub"]
],
"(method 8 drawable-tree-instance-shrub)": [[51, "v1", "drawable-group"]],
"(method 13 drawable-tree-instance-shrub)": [
@@ -3727,6 +3707,7 @@
[101, "s1", "process-focusable"],
[113, "s1", "process-focusable"]
],
"(method 21 gravity-ring)": [[160, "s4", "rgba"]],
"process-drawable-shock-effect-bullseye": [[85, "a0", "lightning-tracker"]],
"(method 14 level-group)": [
[62, "a0", "entity-actor"],
@@ -4135,7 +4116,6 @@
[191, "a3", "int"]
],
"(method 9 collide-cache)": [
//[[28, 56], "gp", "collide-shape-prim"],
[33, "gp", "collide-cache-prim"],
[35, "gp", "collide-shape-prim"],
[[50, 56], "gp", "collide-cache-prim"],
@@ -4149,10 +4129,7 @@
"command-get-float": [[20, "gp", "bfloat"]],
"command-get-int": [[17, "gp", "bfloat"]],
"(anon-function 2 memory-usage)": [[211, "v1", "collide-shape-moving"]],
"(method 8 process-tree)": [
[33, "v1", "symbol"]
// [6, "a3", "symbol"]
],
"(method 8 process-tree)": [[33, "v1", "symbol"]],
"(method 11 memory-usage-block)": [[112, "v1", "int"]],
"(method 14 draw-control)": [
[38, "t9", "(function object object object none)"]
@@ -4328,7 +4305,6 @@
[26, "a1", "(array int32)"],
[28, "v1", "(array int32)"],
[32, "a0", "(pointer int64)"],
// [33, "a0", "(pointer int64)"],
[44, "v1", "(pointer int32)"],
[46, "v1", "(pointer int32)"]
],
@@ -4449,14 +4425,18 @@
[5, "a0", "region-prim-area"]
],
"(method 9 region)": [
[[55, 60], "a0", "drawable-region-prim"],
[46, "a0", "drawable-inline-array-region-prim"],
[77, "a0", "drawable-inline-array-region-prim"],
[58, "v1", "region-prim-area"],
[4, "a0", "region-prim-area"],
[50, "v1", "drawable-region-prim"]
[4, "a0", "region-prim-area"]
],
"(method 17 drawable-tree-region-prim)": [
[[23, 28], "a0", "drawable-region-prim"],
[4, "a0", "region-prim-area"]
[23, "a0", "drawable-region-prim"],
[27, "a0", "drawable-region-prim"],
[21, "a0", "drawable-inline-array-region-prim"],
[42, "a0", "drawable-inline-array-region-prim"],
[4, "a0", "region-prim-area"],
[26, "v1", "region-prim-area"]
],
"command-get-trans": [
[40, "v1", "process-drawable"],
@@ -6026,6 +6006,7 @@
"(code opening sew-fence-gate)": [[18, "v1", "art-joint-anim"]],
"(code open sew-fence-gate)": [[10, "v1", "art-joint-anim"]],
"(code active sew-move-turret)": [[109, "v1", "art-joint-anim"]],
"(method 161 sew-laser-turret)": [[28, "s0", "rgba"]],
"(method 162 sew-laser-turret)": [
[41, "v1", "process-focusable"],
[45, "v1", "process-focusable"],
@@ -9421,7 +9402,7 @@
[226, "gp", "external-art-buffer"]
],
"(code startup title-control)": [
[[59, 149], "gp", "mc-slot-info"], // (+ sp-0 64) is reused as both mc-slot-info and event-message-block
[[59, 149], "gp", "mc-slot-info"],
[354, "v1", "process-drawable"],
[356, "s4", "quaternion"]
],
@@ -9793,10 +9774,6 @@
[62, "a0", "vector"],
[51, "a0", "vector"]
],
"(method 20 rope-system)": [
[11, "a1", "vector"],
[16, "a1", "vector"]
],
"(code preparing-for-launch desert-rescue-transport)": [
[10, "v1", "art-joint-anim"]
],
@@ -11429,7 +11406,8 @@
[114, "v1", "shadow-dcache"],
[119, "a0", "uint32"],
[[191, 249], "gp", "shadow-dcache"],
[96, "v1", "shadow-dcache"]
[96, "v1", "shadow-dcache"],
[126, "a1", "gs-rgbaq"]
],
"real-fog-texture-anim-func": [[[6, 160], "s2", "(pointer uint32)"]],
"(method 22 bigmap)": [
@@ -11915,5 +11893,16 @@
[24, "a0", "timer-bank"],
[1, "v1", "timer-bank"]
],
"(method 11 blow-tower-path-cursor)": [["_stack_", 52, "float"]]
"(method 11 blow-tower-path-cursor)": [["_stack_", 52, "float"]],
"vif1-handler-debug": [
[2, "a0", "vif-bank"],
[9, "a1", "timer-bank"],
[48, "v1", "vif-bank"],
[51, "a0", "vif-bank"]
],
"vif1-handler": [
[1, "v1", "vif-bank"],
[4, "a0", "vif-bank"]
],
"timer0-handler": [[17, "a0", "timer-bank"]]
}
@@ -2179,5 +2179,18 @@
"vars": {
"v0-0": ["flag", "pilrec-sample-flag"]
}
},
"(method 29 game-info)": {
"vars": {
"gp-0": "best-rank",
"s4-0": "score-goals",
"s3-0": "player-scores",
"s5-0": "player-rank-counts"
}
},
"(method 21 gravity-ring)": {
"vars": {
"s4-1": ["s4-1", "rgba"]
}
}
}
File diff suppressed because it is too large. Load diff
+4 -55
View File
@@ -1,58 +1,30 @@
{
"game_version": 4,
"text_version": 40,
"game_name": "jakx",
"expected_elf_name": "SCUS_974.29",
// if you want to filter to only some object names.
// it will make the decompiler much faster.
"allowed_objects": [],
// TODO - these objects currently cause various errors in the decompiler that need to be fixed
// thankfully no header files so hopefully the impact on all-types is minimal
"banned_objects": [
"dma",
"race-line",
"merc-blend-shape",
"foreground",
"generic-effect",
"shadow-cpu",
"collide-mesh",
"collide-shape",
"collide-cache",
"entity",
"task-control",
"net-mgr-medius-cache",
"water-anim",
"editable",
"gstring"
],
"banned_objects": [],
////////////////////////////
// CODE ANALYSIS OPTIONS
////////////////////////////
// set to true to generate plain .asm files with MIPS disassembly, with no fancy decompilation.
// this is fast and should succeed 100% of the time.
"disassemble_code": false,
// Run the decompiler
"decompile_code": true,
"find_functions": true,
////////////////////////////
// DATA ANALYSIS OPTIONS
////////////////////////////
// set to true to generate plain .asm files for data files.
// this will display most data as hex, but will add labels/references/type pointers/strings
// this generates a huge amount of output if you run it on the entire game.
"disassemble_data": false,
// unpack textures to assets folder
"process_tpages": false,
"process_tpages": true,
// write goal imports for tpages and textures
"write_tpage_imports": false,
// unpack game text to assets folder
@@ -64,44 +36,32 @@
// 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
// TODO - rerun this once all objects can be allowed
"dump_art_group_info": false,
// write out a json file containing the joint node mapping, run this with all objects allowed
// TODO - rerun this once all objects can be allowed
"dump_joint_geo_info": false,
// write out a json file containing tpage and texture mappings, run with all objects allowed
// TODO - rerun this once all objects can be allowed
"dump_tex_info": false,
// write out a json file containing the part group table, run with all objects allowed
// TODO - re-run this once particle code has been decomped and once all objects can be allowed
"dump_part_group_table": false,
// set to false to skip adding .STR files to the decompiler database
"read_spools": false,
// write out spool subtitle text, implies read_spools
"process_subtitle_text": false,
// write out spool subtitle images, implies read_spools
"process_subtitle_images": false,
///////////////////////////
// WEIRD OPTIONS
///////////////////////////
// these options are used rarely and should usually be left at false
// generate the symbol_map.json file.
// this is a guess at where each symbol is first defined/used.
"generate_symbol_definition_map": false,
// generate the all-types file
"generate_all_types": false,
// debug option for instruction decoder
"write_hex_near_instructions": false,
// to write out "scripts", which are currently just all the linked lists found. mostly a jak 2/3 thing
"write_scripts": true,
// hex dump of code/data files.
"hexdump_code": false,
"hexdump_data": false,
@@ -109,16 +69,12 @@
"dump_objs": true,
// print control flow graph
"print_cfgs": false,
// set to true for PAL versions. this will forcefully skip files that have some data missing at the end.
"is_pal": false,
"old_all_types_file": "decompiler/config/jak3/all-types.gc",
////////////////////////////
// CONFIG FILES
////////////////////////////
"type_casts_file": "decompiler/config/jakx/ntsc_v1/type_casts.jsonc",
"anonymous_function_types_file": "decompiler/config/jakx/ntsc_v1/anonymous_function_types.jsonc",
"var_names_file": "decompiler/config/jakx/ntsc_v1/var_names.jsonc",
@@ -135,15 +91,12 @@
// "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",
////////////////////////////
// LEVEL EXTRACTION
////////////////////////////
// turn this on to extract level background graphics data as .fr3 files in out/<game>/fr3
"levels_extract": false,
// turn this on if you want extracted levels to be saved out as .glb files in glb_out/<game>
@@ -155,17 +108,13 @@
"rip_collision": false,
// save game textures as .png files to decompiler_out/<game>/textures
"save_texture_pngs": false,
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio
// whether or not to dump out streamed audio files to decompiler_out/<game>/audio/sfx and decompiler_out/<game>/audio/voice_lines
"rip_streamed_audio": false,
////////////////////////////
// PATCHING OPTIONS
////////////////////////////
// these are options related to xdelta3 patches on specific objects
// this allows us to get a more consistent input
// set to true to write new patch files
"write_patches": false,
// set to true to apply patch files
@@ -181,4 +130,4 @@
"object_patches": {}
}
}
}
}
@@ -1,2 +1,483 @@
{
"profile": [[3, "(function profile-segment-array profile-collapse none)"]],
"level-info": [
[0, "(function int)"],
[1, "(function int)"],
[2, "(function int)"],
[3, "(function int)"],
[4, "(function int)"]
],
"vehicle-debris": [[15, "(function collide-shape-prim none)"]],
"title-obs": [
[7, "(function process-tree symbol)"],
[30, "(function external-art-buffer none)"]
],
"gsound": [
[3, "(function sound-id)"],
[5, "(function none)"]
],
"pov-camera": [
[
7,
"(function process int symbol event-message-block object :behavior pov-camera)"
]
],
"debris": [[4, "(function pair)"]],
"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)"]
],
"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 int debug-menu-msg object)"],
[14, "(function object)"],
[15, "(function object)"],
[16, "(function object)"],
[17, "(function object)"],
[18, "(function int debug-menu-msg float object)"],
[19, "(function none)"],
[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 int debug-menu-msg float 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 symbol debug-menu-msg float float object)"],
[208, "(function symbol debug-menu-msg float float object)"],
[209, "(function int debug-menu-msg float object)"],
[210, "(function symbol debug-menu-msg float int object)"],
[211, "(function symbol debug-menu-msg float float object)"],
[212, "(function symbol debug-menu-msg float float object)"],
[213, "(function symbol debug-menu-msg float float object)"],
[214, "(function symbol debug-menu-msg float float object)"],
[215, "(function symbol debug-menu-msg float float object)"],
[216, "(function symbol debug-menu-msg float float object)"],
[217, "(function symbol debug-menu-msg float int 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 debug-menu debug-menu object)"],
[242, "(function debug-menu debug-menu object)"],
[243, "(function debug-menu debug-menu 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)"]
],
"main": [
[17, "(function int none)"],
[15, "(function none)"],
[14, "(function none)"],
[13, "(function none)"],
[5, "(function process-tree symbol)"],
[3, "(function symbol :behavior process)"]
],
"memory-usage": [
[2, "(function process-drawable symbol)"],
[3, "(function basic symbol)"]
],
"intro-scenes2": [
[0, "(function none :behavior scene-player)"],
[1, "(function none :behavior scene-player)"]
],
"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)"],
[40, "(function none :behavior scene-player)"],
[41, "(function none :behavior scene-player)"],
[42, "(function none :behavior scene-player)"],
[43, "(function none :behavior scene-player)"],
[44, "(function none :behavior scene-player)"],
[45, "(function none :behavior scene-player)"]
],
"intro-scenes3": [
[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)"],
[40, "(function none :behavior scene-player)"],
[41, "(function none :behavior scene-player)"],
[42, "(function none :behavior scene-player)"],
[43, "(function none :behavior scene-player)"],
[44, "(function none :behavior scene-player)"],
[45, "(function none :behavior scene-player)"],
[46, "(function none :behavior scene-player)"],
[47, "(function none :behavior scene-player)"],
[48, "(function none :behavior scene-player)"],
[49, "(function none :behavior scene-player)"],
[50, "(function none :behavior scene-player)"],
[51, "(function none :behavior scene-player)"],
[52, "(function none :behavior scene-player)"],
[53, "(function none :behavior scene-player)"],
[54, "(function none :behavior scene-player)"],
[55, "(function none :behavior scene-player)"],
[56, "(function none :behavior scene-player)"],
[57, "(function none :behavior scene-player)"],
[58, "(function none :behavior scene-player)"],
[59, "(function none :behavior scene-player)"],
[60, "(function none :behavior scene-player)"],
[61, "(function none :behavior scene-player)"],
[62, "(function none :behavior scene-player)"],
[63, "(function none :behavior scene-player)"],
[64, "(function none :behavior scene-player)"],
[65, "(function none :behavior scene-player)"],
[66, "(function none :behavior scene-player)"],
[67, "(function none :behavior scene-player)"],
[68, "(function none :behavior scene-player)"],
[69, "(function none :behavior scene-player)"],
[70, "(function none :behavior scene-player)"],
[71, "(function none :behavior scene-player)"],
[72, "(function none :behavior scene-player)"],
[73, "(function none :behavior scene-player)"],
[74, "(function none :behavior scene-player)"],
[75, "(function none :behavior scene-player)"],
[76, "(function none :behavior scene-player)"],
[77, "(function none :behavior scene-player)"],
[78, "(function none :behavior scene-player)"],
[79, "(function none :behavior scene-player)"],
[80, "(function none :behavior scene-player)"],
[81, "(function none :behavior scene-player)"],
[82, "(function none :behavior scene-player)"],
[83, "(function none :behavior scene-player)"],
[84, "(function none :behavior scene-player)"],
[85, "(function none :behavior scene-player)"],
[86, "(function none :behavior scene-player)"],
[87, "(function none :behavior scene-player)"],
[88, "(function none :behavior scene-player)"],
[89, "(function none :behavior scene-player)"],
[90, "(function none :behavior scene-player)"],
[91, "(function none :behavior scene-player)"],
[92, "(function none :behavior scene-player)"],
[93, "(function none :behavior scene-player)"],
[94, "(function none :behavior scene-player)"],
[95, "(function none :behavior scene-player)"],
[96, "(function none :behavior scene-player)"],
[97, "(function none :behavior scene-player)"],
[98, "(function none :behavior scene-player)"],
[99, "(function none :behavior scene-player)"]
],
"editable-player": [
[0, "(function object)"],
[3, "(function object int float object)"],
[4, "(function object int symbol)"],
[32, "(function editable editable-region symbol)"],
[33, "(function editable editable-region symbol)"],
[36, "(function editable symbol)"]
],
"joint-mod": [[21, "(function cspace transformq none)"]],
"merc-death": [[3, "(function time-frame :behavior process-drawable)"]],
"editable": [[101, "(function object editable-filter)"]],
"wvehicle-wheel": [[18, "(function collide-shape-prim none)"]],
"trajectory": [[15, "(function trajectory none)"]],
"settings": [
[13, "(function engine-pers connection-pers object object symbol)"],
[6, "(function engine-pers connection-pers object object symbol)"]
],
"game-info": [
[6, "(function string symbol :behavior process)"],
[
14,
"(function symbol symbol continue-point game-save object :behavior process)"
]
],
"entity": [
[11, "(function process object)"],
[12, "(function process object)"],
[18, "(function process object)"],
[64, "(function process-drawable object)"],
[68, "(function process-drawable handle)"]
],
"target-death": [[1, "(function continue-point target)"]],
"credits-obs": [[7, "(function process symbol)"]]
}
@@ -1 +1 @@
{"adv-event-panel-ag":[[4,"adv-event-panel-exita-ja"],[3,"adv-event-panel-entera-ja"],[2,"adv-event-panel-idle-ja"],[1,"adv-event-panel-lod0-mg"],[0,"adv-event-panel-lod0-jg"]],"antenna-all-ag":[[2,"antenna-all-idle-ja"],[1,"antenna-all-lod0-mg"],[0,"antenna-all-lod0-jg"]],"ash-hr-cred-ag":[[3,"ash-hr-cred-turntable-ja"],[2,"ash-hr-cred-shadow-mg"],[1,"ash-hr-cred-lod0-mg"],[0,"ash-hr-cred-lod0-jg"]],"atoll-dish-ag":[[2,"atoll-dish-idle-ja"],[1,"atoll-dish-lod0-mg"],[0,"atoll-dish-lod0-jg"]],"atoll-rotor-ag":[[2,"atoll-rotor-idle-ja"],[1,"atoll-rotor-lod0-mg"],[0,"atoll-rotor-lod0-jg"]],"body-parts-tab-ag":[[4,"body-parts-tab-exita-ja"],[3,"body-parts-tab-entera-ja"],[2,"body-parts-tab-idle-ja"],[1,"body-parts-tab-lod0-mg"],[0,"body-parts-tab-lod0-jg"]],"bottom-bar-ag":[[6,"bottom-bar-exitb-ja"],[5,"bottom-bar-exita-ja"],[4,"bottom-bar-enterb-ja"],[3,"bottom-bar-entera-ja"],[2,"bottom-bar-idle-ja"],[1,"bottom-bar-lod0-mg"],[0,"bottom-bar-lod0-jg"]],"brd-pool-water-ag":[[2,"brd-pool-water-idle-ja"],[1,"brd-pool-water-lod0-mg"],[0,"brd-pool-water-lod0-jg"]],"car-color-tab-ag":[[4,"car-color-tab-exita-ja"],[3,"car-color-tab-entera-ja"],[2,"car-color-tab-idle-ja"],[1,"car-color-tab-lod0-mg"],[0,"car-color-tab-lod0-jg"]],"car-interior-ag":[[3,"car-interior-idle-ja"],[2,"car-interior-lod1-mg"],[1,"car-interior-lod0-mg"],[0,"car-interior-lod0-jg"]],"car-vert-tab-ag":[[4,"car-vert-tab-exita-ja"],[3,"car-vert-tab-entera-ja"],[2,"car-vert-tab-idle-ja"],[1,"car-vert-tab-lod0-mg"],[0,"car-vert-tab-lod0-jg"]],"cash-bar-ag":[[4,"cash-bar-exita-ja"],[3,"cash-bar-entera-ja"],[2,"cash-bar-idle-ja"],[1,"cash-bar-lod0-mg"],[0,"cash-bar-lod0-jg"]],"character-select-ag":[[4,"character-select-exitrb-ja"],[3,"character-select-entera-ja"],[2,"character-select-idle-ja"],[1,"character-select-lod0-mg"],[0,"character-select-lod0-jg"]],"cliffs-fence-debris-ag":[[7,"cliffs-fence-debris-railc-lod0-mg"],[6,"cliffs-fence-debris-railc-lod0-jg"],[5,"cliffs-fence-debris-railb-lod0-mg"],[4,"cliffs-fence-debris-railb-lod0-jg"],[3,"cliffs-fence-debris-raila-lod0-mg"],[2,"cliffs-fence-debris-raila-lod0-jg"],[1,"cliffs-fence-debris-post-lod0-mg"],[0,"cliffs-fence-debris-post-lod0-jg"]],"cliffs-wood-fence-a-ag":[[2,"cliffs-wood-fence-a-idle-ja"],[1,"cliffs-wood-fence-a-lod0-mg"],[0,"cliffs-wood-fence-a-lod0-jg"]],"cliffs-wood-fence-b-ag":[[2,"cliffs-wood-fence-b-idle-ja"],[1,"cliffs-wood-fence-b-lod0-mg"],[0,"cliffs-wood-fence-b-lod0-jg"]],"cliffs-wood-fence-c-ag":[[2,"cliffs-wood-fence-c-idle-ja"],[1,"cliffs-wood-fence-c-lod0-mg"],[0,"cliffs-wood-fence-c-lod0-jg"]],"cliffs-wood-fence-d-ag":[[2,"cliffs-wood-fence-d-idle-ja"],[1,"cliffs-wood-fence-d-lod0-mg"],[0,"cliffs-wood-fence-d-lod0-jg"]],"coli-atlas-base-ag":[[14,"coli-atlas-base-b-idle-ja"],[13,"coli-atlas-base-b-lod2-mg"],[12,"coli-atlas-base-b-lod1-mg"],[11,"coli-atlas-base-b-lod0-mg"],[10,"coli-atlas-base-b-lod0-jg"],[9,"coli-atlas-base-a-idle-ja"],[8,"coli-atlas-base-a-lod2-mg"],[7,"coli-atlas-base-a-lod1-mg"],[6,"coli-atlas-base-a-lod0-mg"],[5,"coli-atlas-base-a-lod0-jg"],[4,"coli-atlas-base-idle-ja"],[3,"coli-atlas-base-lod2-mg"],[2,"coli-atlas-base-lod1-mg"],[1,"coli-atlas-base-lod0-mg"],[0,"coli-atlas-base-lod0-jg"]],"coli-atlas-break-ag":[[8,"coli-atlas-break-b-idle-ja"],[7,"coli-atlas-break-b-lod0-mg"],[6,"coli-atlas-break-b-lod0-jg"],[5,"coli-atlas-break-a-idle-ja"],[4,"coli-atlas-break-a-lod0-mg"],[3,"coli-atlas-break-a-lod0-jg"],[2,"coli-atlas-break-idle-ja"],[1,"coli-atlas-break-lod0-mg"],[0,"coli-atlas-break-lod0-jg"]],"coli-atlas-globe-ag":[[4,"coli-atlas-globe-idle-ja"],[3,"coli-atlas-globe-lod2-mg"],[2,"coli-atlas-globe-lod1-mg"],[1,"coli-atlas-globe-lod0-mg"],[0,"coli-atlas-globe-lod0-jg"]],"coli-atlas-pillar-ag":[[4,"coli-atlas-pillar-idle-ja"],[3,"coli-atlas-pillar-lod2-mg"],[2,"coli-atlas-pillar-lod1-mg"],[1,"coli-atlas-pillar-lod0-mg"],[0,"coli-atlas-pillar-lod0-jg"]],"coli-atlas-statue-ag":[[4,"coli-atlas-statue-idle-ja"],[3,"coli-atlas-statue-lod2-mg"],[2,"coli-atlas-statue-lod1-mg"],[1,"coli-atlas-statue-lod0-mg"],[0,"coli-atlas-statue-lod0-jg"]],"coli-ball-collision-ag":[[2,"coli-ball-collision-idle-ja"],[1,"coli-ball-collision-lod0-mg"],[0,"coli-ball-collision-lod0-jg"]],"coli-bowl-a-ag":[[4,"coli-bowl-a-idle-ja"],[3,"coli-bowl-a-lod2-mg"],[2,"coli-bowl-a-lod1-mg"],[1,"coli-bowl-a-lod0-mg"],[0,"coli-bowl-a-lod0-jg"]],"coli-bowl-a-debris-ag":[[5,"coli-bowl-a-debris-c-lod0-mg"],[4,"coli-bowl-a-debris-c-lod0-jg"],[3,"coli-bowl-a-debris-b-lod0-mg"],[2,"coli-bowl-a-debris-b-lod0-jg"],[1,"coli-bowl-a-debris-a-lod0-mg"],[0,"coli-bowl-a-debris-a-lod0-jg"]],"coli-bowl-hanger-ag":[[4,"coli-bowl-hanger-idle-ja"],[3,"coli-bowl-hanger-lod2-mg"],[2,"coli-bowl-hanger-lod1-mg"],[1,"coli-bowl-hanger-lod0-mg"],[0,"coli-bowl-hanger-lod0-jg"]],"coli-bowl-hanger-debris-ag":[[5,"coli-bowl-hanger-debris-c-lod0-mg"],[4,"coli-bowl-hanger-debris-c-lod0-jg"],[3,"coli-bowl-hanger-debris-b-lod0-mg"],[2,"coli-bowl-hanger-debris-b-lod0-jg"],[1,"coli-bowl-hanger-debris-a-lod0-mg"],[0,"coli-bowl-Line truncated
{"adv-event-panel-ag":[[0,"adv-event-panel-lod0-jg"],[1,"adv-event-panel-lod0-mg"],[2,"adv-event-panel-idle-ja"],[3,"adv-event-panel-entera-ja"],[4,"adv-event-panel-exita-ja"]],"antenna-all-ag":[[0,"antenna-all-lod0-jg"],[1,"antenna-all-lod0-mg"],[2,"antenna-all-idle-ja"]],"ash-hr-cred-ag":[[0,"ash-hr-cred-lod0-jg"],[1,"ash-hr-cred-lod0-mg"],[2,"ash-hr-cred-shadow-mg"],[3,"ash-hr-cred-turntable-ja"]],"atoll-dish-ag":[[0,"atoll-dish-lod0-jg"],[1,"atoll-dish-lod0-mg"],[2,"atoll-dish-idle-ja"]],"atoll-rotor-ag":[[0,"atoll-rotor-lod0-jg"],[1,"atoll-rotor-lod0-mg"],[2,"atoll-rotor-idle-ja"]],"body-parts-tab-ag":[[0,"body-parts-tab-lod0-jg"],[1,"body-parts-tab-lod0-mg"],[2,"body-parts-tab-idle-ja"],[3,"body-parts-tab-entera-ja"],[4,"body-parts-tab-exita-ja"]],"bottom-bar-ag":[[0,"bottom-bar-lod0-jg"],[1,"bottom-bar-lod0-mg"],[2,"bottom-bar-idle-ja"],[3,"bottom-bar-entera-ja"],[4,"bottom-bar-enterb-ja"],[5,"bottom-bar-exita-ja"],[6,"bottom-bar-exitb-ja"]],"brd-pool-water-ag":[[0,"brd-pool-water-lod0-jg"],[1,"brd-pool-water-lod0-mg"],[2,"brd-pool-water-idle-ja"]],"car-color-tab-ag":[[0,"car-color-tab-lod0-jg"],[1,"car-color-tab-lod0-mg"],[2,"car-color-tab-idle-ja"],[3,"car-color-tab-entera-ja"],[4,"car-color-tab-exita-ja"]],"car-interior-ag":[[0,"car-interior-lod0-jg"],[1,"car-interior-lod0-mg"],[2,"car-interior-lod1-mg"],[3,"car-interior-idle-ja"]],"car-vert-tab-ag":[[0,"car-vert-tab-lod0-jg"],[1,"car-vert-tab-lod0-mg"],[2,"car-vert-tab-idle-ja"],[3,"car-vert-tab-entera-ja"],[4,"car-vert-tab-exita-ja"]],"cash-bar-ag":[[0,"cash-bar-lod0-jg"],[1,"cash-bar-lod0-mg"],[2,"cash-bar-idle-ja"],[3,"cash-bar-entera-ja"],[4,"cash-bar-exita-ja"]],"character-select-ag":[[0,"character-select-lod0-jg"],[1,"character-select-lod0-mg"],[2,"character-select-idle-ja"],[3,"character-select-entera-ja"],[4,"character-select-exitrb-ja"]],"cliffs-fence-debris-ag":[[0,"cliffs-fence-debris-post-lod0-jg"],[1,"cliffs-fence-debris-post-lod0-mg"],[2,"cliffs-fence-debris-raila-lod0-jg"],[3,"cliffs-fence-debris-raila-lod0-mg"],[4,"cliffs-fence-debris-railb-lod0-jg"],[5,"cliffs-fence-debris-railb-lod0-mg"],[6,"cliffs-fence-debris-railc-lod0-jg"],[7,"cliffs-fence-debris-railc-lod0-mg"]],"cliffs-wood-fence-a-ag":[[0,"cliffs-wood-fence-a-lod0-jg"],[1,"cliffs-wood-fence-a-lod0-mg"],[2,"cliffs-wood-fence-a-idle-ja"]],"cliffs-wood-fence-b-ag":[[0,"cliffs-wood-fence-b-lod0-jg"],[1,"cliffs-wood-fence-b-lod0-mg"],[2,"cliffs-wood-fence-b-idle-ja"]],"cliffs-wood-fence-c-ag":[[0,"cliffs-wood-fence-c-lod0-jg"],[1,"cliffs-wood-fence-c-lod0-mg"],[2,"cliffs-wood-fence-c-idle-ja"]],"cliffs-wood-fence-d-ag":[[0,"cliffs-wood-fence-d-lod0-jg"],[1,"cliffs-wood-fence-d-lod0-mg"],[2,"cliffs-wood-fence-d-idle-ja"]],"coli-atlas-base-ag":[[0,"coli-atlas-base-lod0-jg"],[1,"coli-atlas-base-lod0-mg"],[2,"coli-atlas-base-lod1-mg"],[3,"coli-atlas-base-lod2-mg"],[4,"coli-atlas-base-idle-ja"],[5,"coli-atlas-base-a-lod0-jg"],[6,"coli-atlas-base-a-lod0-mg"],[7,"coli-atlas-base-a-lod1-mg"],[8,"coli-atlas-base-a-lod2-mg"],[9,"coli-atlas-base-a-idle-ja"],[10,"coli-atlas-base-b-lod0-jg"],[11,"coli-atlas-base-b-lod0-mg"],[12,"coli-atlas-base-b-lod1-mg"],[13,"coli-atlas-base-b-lod2-mg"],[14,"coli-atlas-base-b-idle-ja"]],"coli-atlas-break-ag":[[0,"coli-atlas-break-lod0-jg"],[1,"coli-atlas-break-lod0-mg"],[2,"coli-atlas-break-idle-ja"],[3,"coli-atlas-break-a-lod0-jg"],[4,"coli-atlas-break-a-lod0-mg"],[5,"coli-atlas-break-a-idle-ja"],[6,"coli-atlas-break-b-lod0-jg"],[7,"coli-atlas-break-b-lod0-mg"],[8,"coli-atlas-break-b-idle-ja"]],"coli-atlas-globe-ag":[[0,"coli-atlas-globe-lod0-jg"],[1,"coli-atlas-globe-lod0-mg"],[2,"coli-atlas-globe-lod1-mg"],[3,"coli-atlas-globe-lod2-mg"],[4,"coli-atlas-globe-idle-ja"]],"coli-atlas-pillar-ag":[[0,"coli-atlas-pillar-lod0-jg"],[1,"coli-atlas-pillar-lod0-mg"],[2,"coli-atlas-pillar-lod1-mg"],[3,"coli-atlas-pillar-lod2-mg"],[4,"coli-atlas-pillar-idle-ja"]],"coli-atlas-statue-ag":[[0,"coli-atlas-statue-lod0-jg"],[1,"coli-atlas-statue-lod0-mg"],[2,"coli-atlas-statue-lod1-mg"],[3,"coli-atlas-statue-lod2-mg"],[4,"coli-atlas-statue-idle-ja"]],"coli-ball-collision-ag":[[0,"coli-ball-collision-lod0-jg"],[1,"coli-ball-collision-lod0-mg"],[2,"coli-ball-collision-idle-ja"]],"coli-bowl-a-ag":[[0,"coli-bowl-a-lod0-jg"],[1,"coli-bowl-a-lod0-mg"],[2,"coli-bowl-a-lod1-mg"],[3,"coli-bowl-a-lod2-mg"],[4,"coli-bowl-a-idle-ja"]],"coli-bowl-a-debris-ag":[[0,"coli-bowl-a-debris-a-lod0-jg"],[1,"coli-bowl-a-debris-a-lod0-mg"],[2,"coli-bowl-a-debris-b-lod0-jg"],[3,"coli-bowl-a-debris-b-lod0-mg"],[4,"coli-bowl-a-debris-c-lod0-jg"],[5,"coli-bowl-a-debris-c-lod0-mg"]],"coli-bowl-hanger-ag":[[0,"coli-bowl-hanger-lod0-jg"],[1,"coli-bowl-hanger-lod0-mg"],[2,"coli-bowl-hanger-lod1-mg"],[3,"coli-bowl-hanger-lod2-mg"],[4,"coli-bowl-hanger-idle-ja"]],"coli-bowl-hanger-debris-ag":[[0,"coli-bowl-hanger-debris-a-lod0-jg"],[1,"coli-bowl-hanger-debris-a-lod0-mg"],[2,"coli-bowl-hanger-debris-b-lod0-jg"],[3,"coli-bowl-hanger-debris-b-lod0-mg"],[4,"coli-bowl-hanger-debris-c-lod0-jg"],[5,"coli-bowl-Line truncated
@@ -8,15 +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": {
},
"type_remap": {},
// remap names for types in an entire file (higher priority)
"file_override": {
},
"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": {
}
"joint_node_hacks": {}
}
+291 -44
View File
@@ -1,66 +1,313 @@
{
////////////////////////////
// HACKS and ASM FUNCTIONS
////////////////////////////
"types_with_bad_inspect_methods": [
],
"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],
["(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": [
"name=",
"water-anim-event-handler",
"(anon-function 55 task-control)",
"(method 22 level)",
"(method 11 medius-cache)",
"(method 13 race-line)",
"adgif-shader<-texture!",
"symlink2",
"(method 17 bounding-box)",
"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",
"memcpy",
"dma-count-until-done",
"test-to-from-spr",
"test-from-spr",
"test-to-spr",
"test-seq-read",
"test-worst-read",
"test-seq-write",
"test-worst-write",
"blerc-a-fragment",
"get-current-room-name-and-info"
],
// these functions use pairs and the decompiler
// will be less picky about types related to pairs.
"pair_functions_by_name": [
"update-time-of-day",
"ref",
"ref&",
"(method 4 pair)",
// "(method 28 editable)",
"execute-select",
// "(method 29 editable)",
// "(method 25 editable)",
"last",
"member",
"display-loop-main",
"nmember",
"cspace-inspect-tree",
"assoc",
"assoce",
"nassoc",
"nassoce",
"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",
"append!",
"delete!",
"delete-car!",
"insert-cons!",
"debug-menu-rebuild",
"(method 8 process-tree)",
"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",
"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,
"~338h~5d~388h~5d~448h~5,,2f": 3,
"~0kspheres = ~d~256hspheres/call = ~f~%": 2,
"~0kfrags = ~d~256hfrags/call = ~f~%": 2,
"~0ktris = ~d~256htris/frag = ~f~%": 2,
"~0koutput = ~d~256houtput/call = ~f~%": 2,
"~0knodes = ~d~256hnodes/call = ~f~%": 2,
"~0K~Name~130HID~+50HVol~+15HPitch~+24HPan~+18HEar~+24HDist~%": 0,
"~130H~5D ~4D ~5D ~4D ~3D ~5,,0M~%": 6,
"music-volume=~220h~f~%": 1,
"dialog-volume=~220h~f~%": 1,
"music-volume-during-speech=~220h~f~%": 1,
"sfx-volume-during-speech=~220h~f~%": 1,
"music-volume-ducked-by-sound=~220h~f~%": 1,
"music-seek-speed=~220h~f~%": 1,
"~%final music-volume: ~220h~f~%": 1,
"final sfx-volume: ~220h~f~%": 1,
"sfx-volume=~220h~f~%": 1
},
"blocks_ending_in_asm_branch": {
"(method 82 vehicle)": [
0, 1, 4, 5, 7, 12, 36, 37, 38, 40, 41, 43, 44, 46, 58, 62, 63, 65, 66, 70,
71, 73, 74, 81, 84, 87, 88, 92, 93, 95, 96, 98, 102, 103, 105, 106, 110,
111, 113, 114, 116, 117, 118, 119, 121, 122, 127
],
"(method 16 sparticle-launch-control)": [
17, 18, 25, 35, 36, 39, 40, 41, 43, 44, 45, 48, 62, 65, 69, 70, 74, 75,
79, 80, 91, 92, 93, 95, 96, 97, 100, 102
],
"(method 13 collide-shape-prim)": [5, 6],
"(method 12 collide-shape-prim-group)": [5, 6],
"(method 40 collide-shape)": [3, 9, 12, 18, 20, 22, 23, 26, 27, 30, 32],
"(method 45 collide-shape)": [33],
"(method 36 collide-shape)": [8, 9],
"(method 15 collide-shape-prim-sphere)": [1, 2, 4],
"(method 18 collide-shape-prim-sphere)": [0, 1, 2, 3, 4],
"upload-vis-bits": [2, 6, 3, 0],
"(method 21 nav-control)": [7, 15, 16, 32, 33, 34, 35, 45, 48],
"(method 19 nav-mesh)": [9, 18, 19, 35, 36, 37, 38, 58, 61, 62, 64, 65, 68],
"(method 41 nav-state)": [8, 9, 10, 11, 18, 19, 21],
"(method 26 grid-hash)": [39, 35, 22, 15],
"(method 16 collide-shape-prim-sphere)": [1, 2],
"(method 17 nav-mesh-editable)": [0, 1, 2, 7, 9, 24, 28, 33],
"load-game-text-info": [20, 21, 22, 24, 25, 26],
"(method 18 mysql-nav-graph)": [0, 1, 2, 3, 4, 7, 9],
"dm-play-task-with-continue": [0, 1, 2, 3, 4, 6],
"(method 18 nav-control)": [11, 12, 19, 20, 31, 34],
"(method 19 nav-control)": [9, 10],
"find-closest-circle-ray-intersection": [0, 4, 15, 16, 17, 18],
"cam-helper-temp": [38, 40],
"level-remap-texture": [2, 3, 4, 5, 6],
"bsp-camera-asm": [1, 2, 3, 4, 6, 7],
"get-car-skel-part": [0, 1, 2, 4],
"(method 9 curve-color-fast)": [0, 1],
"evaluate-color-curve-fast": [0, 1],
"sqlpipe-query": [21],
"find-offending-process-focusable": [16, 19],
"(method 10 simple-sprite-system)": [0],
"(method 9 editable-region)": [63],
"find-nearest-entity": [7, 9],
"(method 49 process-drawable)": [2, 3, 7, 27, 28, 30],
"(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
],
"light-merge!": [1, 2, 3, 5, 7],
"(method 12 collide-shape-prim-mesh)": [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16
],
"(method 12 collide-mesh-cache)": [0, 1, 2, 3, 4, 5],
"(method 10 collide-mesh)": [2],
"add-debug-line-sphere": [0],
"add-debug-box-with-transform": [0, 3],
"unpack-comp-rle": [1, 3, 5, 6],
"should-push-away-test-mesh": [2, 4],
"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, 39, 43, 45
],
"(method 16 level)": [0, 1, 5, 13, 14, 15],
"draw-drawable-tree-instance-shrub": [5, 7, 9, 11],
"get-host-by-name": [17],
"(anon-function 3 game-save)": [15, 16],
"(anon-function 24 game-save)": [5],
"draw-actor-marks": [8],
"(method 13 collide-cache)": [7, 9],
"(method 22 collide-cache)": [11, 12, 27, 28]
},
// 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": {
"(trans auto-idle)": [[265, 1]],
"(trans idle nav-mesh-editor)": [[525, 0]],
"locate-sub": [[68, 3]]
},
"mips2c_functions_by_name": [
"get-string-length-asm",
"draw-string3d-asm",
"draw-string-asm-packed",
"collide-do-primitives",
"moving-sphere-triangle-intersect",
"calc-animation-from-spr",
// "get-string-length", causes mips2c to assert
"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 16 sky-work)", // yes
"(method 17 sky-work)", // yes
"(method 28 sky-work)", // yes
"(method 29 sky-work)", // yes
"(method 30 sky-work)", // yes
"(method 32 sky-work)", // yes
"(method 33 sky-work)", // yes
"(method 11 collide-hash)",
"(method 12 collide-hash)",
"fill-bg-using-box-new",
"fill-bg-using-line-sphere-new",
"(method 11 collide-mesh)",
"(method 14 collide-mesh)",
"cspace<-parented-transformq-joint!",
"(method 13 collide-mesh)",
"draw-large-polygon-ocean",
"render-ocean-quad",
"init-ocean-far-regs",
"(method 15 ocean)",
"(method 20 grid-hash)",
"(method 21 grid-hash)",
"(method 22 grid-hash)",
"(method 24 grid-hash)",
"(method 35 sphere-hash)", // yes
"(method 31 sphere-hash)", // yes
"(method 34 sphere-hash)", // yes
"(method 35 spatial-hash)", // yes
"(method 40 spatial-hash)", // yes
"(method 38 spatial-hash)", // yes
"(method 34 spatial-hash)", // yes
"(method 32 sphere-hash)",
"(method 30 sphere-hash)",
"(method 37 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-state-patch-pointers",
"(method 20 nav-engine)",
"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)", // yes
"setup-blerc-chains-for-one-fragment",
"blerc-execute",
"ripple-create-wave-table",
"ripple-execute-init",
"ripple-apply-wave-table",
"ripple-matrix-scale",
"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?",
"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": [
],
// 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.
"missing_textures": [],
"expected_merged_objs": []
}
+367 -367
View File
@@ -13,373 +13,373 @@
// "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": [],
@@ -1 +1 @@
{"adv-event-panel-lod0-jg":[[8,"bottomright"],[7,"topleft"],[6,"selectscreentype"],[5,"select_screen"],[4,"main"],[3,"cam"],[2,"prejoint"],[1,"align"]],"antenna-all-lod0-jg":[[8,"tail_b"],[7,"tail_a"],[6,"flag_d"],[5,"flag_c"],[4,"flag_b"],[3,"flag_a"],[2,"prejoint"],[1,"align"]],"ash-hr-cred-lod0-jg":[[89,"gun"],[88,"holster"],[87,"RlegDangle1_A"],[86,"RlegDangle2_A"],[85,"RlegDangle3_A"],[84,"Rball"],[83,"LlegDangle3_A"],[82,"LlegDangle2_A"],[81,"LlegDangle1_A"],[80,"Lball"],[79,"rcollar_C"],[78,"rcollar_B"],[77,"rcollar_A"],[76,"lcollar_C"],[75,"lcollar_B"],[74,"lcollar_A"],[73,"rtit_A"],[72,"ltit_A"],[71,"RpinkyC"],[70,"RpinkyB"],[69,"RpinkyA"],[68,"RringC"],[67,"RringB"],[66,"RringA"],[65,"RmiddleC"],[64,"RmiddleB"],[63,"RmiddleA"],[62,"RindexC"],[61,"RindexB"],[60,"RindexA"],[59,"RthumbC"],[58,"RthumbB"],[57,"RthumbA"],[56,"LpinkyC"],[55,"LpinkyB"],[54,"LpinkyA"],[53,"LringC"],[52,"LringB"],[51,"LringA"],[50,"LmiddleC"],[49,"LmiddleB"],[48,"LmiddleA"],[47,"LindexC"],[46,"LindexB"],[45,"LindexA"],[44,"LthumbC"],[43,"LthumbB"],[42,"LthumbA"],[41,"hairM_C"],[40,"hairM_B"],[39,"hairM_A1"],[38,"hairL2_C"],[37,"hairL2_B"],[36,"hairL2_A"],[35,"hairL1_C"],[34,"hairL1_B"],[33,"hairL1_A"],[32,"hairR2_C"],[31,"hairR2_B"],[30,"hairR2_A"],[29,"hairR1_C"],[28,"hairR1_B"],[27,"hairR1_A"],[26,"Rear_C"],[25,"Rear_B"],[24,"Lear_C"],[23,"Lear_B"],[22,"Rankle"],[21,"Rknee"],[20,"Rthigh"],[19,"Lankle"],[18,"Lknee"],[17,"Lthigh"],[16,"hips"],[15,"Rhand"],[14,"Relbow"],[13,"Rshoulder"],[12,"Lhand"],[11,"Lelbow"],[10,"Lshoulder"],[9,"Rear_A"],[8,"Lear_A"],[7,"head"],[6,"neck"],[5,"chest"],[4,"stomach"],[3,"main"],[2,"prejoint"],[1,"align"]],"atoll-dish-lod0-jg":[[4,"Yrotation"],[3,"main"],[2,"prejoint"],[1,"align"]],"atoll-rotor-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"body-parts-tab-lod0-jg":[[9,"bottomright"],[8,"topleft"],[7,"mapscreentype"],[6,"map_screen"],[5,"arm"],[4,"main"],[3,"cam"],[2,"prejoint"],[1,"align"]],"bottom-bar-lod0-jg":[[14,"bottomright3"],[13,"topleft3"],[12,"bottomright2"],[11,"topleft2"],[10,"bottomright1"],[9,"topleft1"],[8,"bottomright"],[7,"topleft"],[6,"bottombartype"],[5,"bottom_bar"],[4,"main"],[3,"cam"],[2,"prejoint"],[1,"align"]],"brd-pool-water-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"car-color-tab-lod0-jg":[[13,"color"],[12,"tri2"],[11,"tri1"],[10,"tri0"],[9,"bottomright"],[8,"topleft"],[7,"mapscreentype"],[6,"map_screen"],[5,"arm"],[4,"main"],[3,"cam"],[2,"prejoint"],[1,"align"]],"car-interior-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"car-vert-tab-lod0-jg":[[9,"bottomright"],[8,"topleft"],[7,"mapscreentype"],[6,"map_screen"],[5,"arm"],[4,"main"],[3,"cam"],[2,"prejoint"],[1,"align"]],"cash-bar-lod0-jg":[[9,"bottomright2"],[8,"topleft2"],[7,"bottomright"],[6,"topleft"],[5,"cash_bar"],[4,"main"],[3,"cam"],[2,"prejoint"],[1,"align"]],"character-select-lod0-jg":[[10,"bottomright_type"],[9,"topleft_type"],[8,"bottomright"],[7,"topleft"],[6,"mapscreentype"],[5,"map_screen"],[4,"main"],[3,"cam"],[2,"prejoint"],[1,"align"]],"cliffs-fence-debris-post-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"cliffs-fence-debris-raila-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"cliffs-fence-debris-railb-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"cliffs-fence-debris-railc-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"cliffs-wood-fence-a-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"cliffs-wood-fence-b-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"cliffs-wood-fence-c-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"cliffs-wood-fence-d-lod0-jg":[[3,"main"],[2,"prejoint"],[1,"align"]],"coli-atlas-base-a-lod0-jg":[[4,"coli_atlas_base_dust"],[3,"main"],[2,"prejoint"],[1,"align"]],"coli-atlas-base-b-lod0-jg":[[4,"coli_atlas_base_dust"],[3,"main"],[2,"prejoint"],[1,"align"]],"coli-atlas-base-lod0-jg":[[4,"coli_atlas_base_dust"],[3,"main"],[2,"prejoint"],[1,"align"]],"coli-atlas-break-a-lod0-jg":[[52,"ax"],[51,"aw"],[50,"av"],[49,"au"],[48,"at"],[47,"as"],[46,"ar"],[45,"aq"],[44,"ap"],[43,"ao"],[42,"an"],[41,"am"],[40,"al"],[39,"ak"],[38,"aj"],[37,"ai"],[36,"ah"],[35,"ag"],[34,"af"],[33,"ae"],[32,"ad"],[31,"ac"],[30,"ab"],[29,"aa"],[28,"z"],[27,"y"],[26,"x"],[25,"w"],[24,"v"],[23,"u"],[22,"t"],[21,"s"],[20,"r"],[19,"q"],[18,"p"],[17,"o"],[16,"n"],[15,"m"],[14,"l"],[13,"k"],[12,"j"],[11,"i"],[10,"h"],[9,"g"],[8,"f"],[7,"e"],[6,"d"],[5,"c"],[4,"b"],[3,"a"],[2,"prejoint"],[1,"align"]],"coli-atlas-break-b-lod0-jg":[[52,"cv"],[51,"cu"],[50,"ct"],[49,"cs"],[48,"cr"],[47,"cq"],[46,"cp"],[45,"co"],[44,"cn"],[43,"cm"],[42,"cl"],[41,"ck"],[40,"cj"],[39,"ci"],[38,"ch"],[37,"cg"],[36,"cf"],[35,"ce"],[34,"cd"],[33,"cc"],[32,"cb"],[31,"ca"],[30,"bz"],[29,"by"],[28,"bx"],[27,"bw"],[26,"bv"],[25,"bu"],[24,"bt"],[23,"bs"],[22,"br"],[21,"bq"],[20,"bp"],[19,"bo"],[18,"bn"],[17,"bm"],[16,"bl"],[15,"bk"],[14,"bj"],[13,"bi"],[12,"bh"],[11,"bg"],[10,"bf"],[9,"be"],[8,"bd"],[7,"bc"],[6,"bb"],[5,"ba"],[4,"az"],[3,"ay"],[2,"prejoint"],[1,"align"]],"coli-atlas-break-lod0-jg":[[94,"atlas_break"Line truncated
{"adv-event-panel-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"cam"],[4,"main"],[5,"select_screen"],[6,"selectscreentype"],[7,"topleft"],[8,"bottomright"]],"antenna-all-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"flag_a"],[4,"flag_b"],[5,"flag_c"],[6,"flag_d"],[7,"tail_a"],[8,"tail_b"]],"ash-hr-cred-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"],[4,"stomach"],[5,"chest"],[6,"neck"],[7,"head"],[8,"Lear_A"],[9,"Rear_A"],[10,"Lshoulder"],[11,"Lelbow"],[12,"Lhand"],[13,"Rshoulder"],[14,"Relbow"],[15,"Rhand"],[16,"hips"],[17,"Lthigh"],[18,"Lknee"],[19,"Lankle"],[20,"Rthigh"],[21,"Rknee"],[22,"Rankle"],[23,"Lear_B"],[24,"Lear_C"],[25,"Rear_B"],[26,"Rear_C"],[27,"hairR1_A"],[28,"hairR1_B"],[29,"hairR1_C"],[30,"hairR2_A"],[31,"hairR2_B"],[32,"hairR2_C"],[33,"hairL1_A"],[34,"hairL1_B"],[35,"hairL1_C"],[36,"hairL2_A"],[37,"hairL2_B"],[38,"hairL2_C"],[39,"hairM_A1"],[40,"hairM_B"],[41,"hairM_C"],[42,"LthumbA"],[43,"LthumbB"],[44,"LthumbC"],[45,"LindexA"],[46,"LindexB"],[47,"LindexC"],[48,"LmiddleA"],[49,"LmiddleB"],[50,"LmiddleC"],[51,"LringA"],[52,"LringB"],[53,"LringC"],[54,"LpinkyA"],[55,"LpinkyB"],[56,"LpinkyC"],[57,"RthumbA"],[58,"RthumbB"],[59,"RthumbC"],[60,"RindexA"],[61,"RindexB"],[62,"RindexC"],[63,"RmiddleA"],[64,"RmiddleB"],[65,"RmiddleC"],[66,"RringA"],[67,"RringB"],[68,"RringC"],[69,"RpinkyA"],[70,"RpinkyB"],[71,"RpinkyC"],[72,"ltit_A"],[73,"rtit_A"],[74,"lcollar_A"],[75,"lcollar_B"],[76,"lcollar_C"],[77,"rcollar_A"],[78,"rcollar_B"],[79,"rcollar_C"],[80,"Lball"],[81,"LlegDangle1_A"],[82,"LlegDangle2_A"],[83,"LlegDangle3_A"],[84,"Rball"],[85,"RlegDangle3_A"],[86,"RlegDangle2_A"],[87,"RlegDangle1_A"],[88,"holster"],[89,"gun"]],"atoll-dish-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"],[4,"Yrotation"]],"atoll-rotor-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"body-parts-tab-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"cam"],[4,"main"],[5,"arm"],[6,"map_screen"],[7,"mapscreentype"],[8,"topleft"],[9,"bottomright"]],"bottom-bar-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"cam"],[4,"main"],[5,"bottom_bar"],[6,"bottombartype"],[7,"topleft"],[8,"bottomright"],[9,"topleft1"],[10,"bottomright1"],[11,"topleft2"],[12,"bottomright2"],[13,"topleft3"],[14,"bottomright3"]],"brd-pool-water-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"car-color-tab-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"cam"],[4,"main"],[5,"arm"],[6,"map_screen"],[7,"mapscreentype"],[8,"topleft"],[9,"bottomright"],[10,"tri0"],[11,"tri1"],[12,"tri2"],[13,"color"]],"car-interior-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"car-vert-tab-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"cam"],[4,"main"],[5,"arm"],[6,"map_screen"],[7,"mapscreentype"],[8,"topleft"],[9,"bottomright"]],"cash-bar-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"cam"],[4,"main"],[5,"cash_bar"],[6,"topleft"],[7,"bottomright"],[8,"topleft2"],[9,"bottomright2"]],"character-select-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"cam"],[4,"main"],[5,"map_screen"],[6,"mapscreentype"],[7,"topleft"],[8,"bottomright"],[9,"topleft_type"],[10,"bottomright_type"]],"cliffs-fence-debris-post-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"cliffs-fence-debris-raila-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"cliffs-fence-debris-railb-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"cliffs-fence-debris-railc-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"cliffs-wood-fence-a-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"cliffs-wood-fence-b-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"cliffs-wood-fence-c-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"cliffs-wood-fence-d-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"]],"coli-atlas-base-a-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"],[4,"coli_atlas_base_dust"]],"coli-atlas-base-b-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"],[4,"coli_atlas_base_dust"]],"coli-atlas-base-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"main"],[4,"coli_atlas_base_dust"]],"coli-atlas-break-a-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"a"],[4,"b"],[5,"c"],[6,"d"],[7,"e"],[8,"f"],[9,"g"],[10,"h"],[11,"i"],[12,"j"],[13,"k"],[14,"l"],[15,"m"],[16,"n"],[17,"o"],[18,"p"],[19,"q"],[20,"r"],[21,"s"],[22,"t"],[23,"u"],[24,"v"],[25,"w"],[26,"x"],[27,"y"],[28,"z"],[29,"aa"],[30,"ab"],[31,"ac"],[32,"ad"],[33,"ae"],[34,"af"],[35,"ag"],[36,"ah"],[37,"ai"],[38,"aj"],[39,"ak"],[40,"al"],[41,"am"],[42,"an"],[43,"ao"],[44,"ap"],[45,"aq"],[46,"ar"],[47,"as"],[48,"at"],[49,"au"],[50,"av"],[51,"aw"],[52,"ax"]],"coli-atlas-break-b-lod0-jg":[[1,"align"],[2,"prejoint"],[3,"ay"],[4,"az"],[5,"ba"],[6,"bb"],[7,"bc"],[8,"bd"],[9,"be"],[10,"bf"],[11,"bg"],[12,"bh"],[13,"bi"],[14,"bj"],[15,"bk"],[16,"bl"],[17,"bm"],[18,"bn"],[19,"bo"],[20,"bp"],[21,"bq"],[22,"br"],[23,"bs"],[24,"bt"],[25,"bu"],[26,"bv"],[27,"bw"],[28,"bx"],[29,"by"],[30,"bz"],[31,"ca"],[32,"cb"],[33,"cc"],[34,"cd"],[35,"ce"],[36,"cf"],[37,"cg"],[38,"ch"],[39,"ci"],[40,"cj"],[41,"ck"],[42,"cl"],[43,"cm"],[44,"cn"],[45,"co"],[46,"cp"],[47,"cq"],[48,"cr"],[49,"cs"],[50,"ct"],[51,"cu"],[52,"cv"]],"coli-atlas-break-lod0-jg":[[1,"align"],[2,"pLine truncated
File diff suppressed because it is too large. Load diff
@@ -0,0 +1 @@
[[65,"group-intro-car-explo-closeup"],[1,"group-rain-screend-drop-real"],[457,"group-sewer-spray"],[66,"group-outro-car-explo-closeup"],[393,"group-ship-fireworks"],[2,"group-stars"],[67,"group-intro-opening-debris-smoke"],[3,"group-sun"],[451,"group-temple-lava-firebelch"],[68,"group-intro-opening-debris-fire"],[387,"group-sewerwater-falls-splash"],[4,"group-green-sun"],[5,"group-moon"],[397,"group-kras-waterfall-casino-splash"],[6,"group-red-eco-strike-ground"],[7,"group-red-eco-spinkick"],[407,"group-docks-drainwater"],[8,"group-eco-blue"],[9,"group-eco-blue-collect"],[401,"group-kras-neon-sign-c"],[10,"group-part-vent-blue-active"],[11,"group-part-vent-blue-inactive"],[395,"group-pump-gas-leak"],[12,"group-eco-red"],[13,"group-eco-red-collect"],[405,"group-docks-sand-dump"],[14,"group-part-vent-red-active"],[15,"group-part-vent-red-inactive"],[415,"group-drome-bridge-night-glow-blinking"],[16,"group-part-vent-yellow-active"],[17,"group-part-vent-yellow-inactive"],[409,"group-docks-red-hangar-light"],[18,"group-eco-yellow"],[19,"group-eco-yellow-collect"],[403,"group-docks-drops-splash"],[20,"group-fuel-cell-starburst"],[21,"group-money-starburst"],[413,"group-drome-mist"],[22,"group-buzzer-effect"],[23,"group-blue-collect"],[487,"group-desert-dust-devil"],[24,"group-yellow-collect"],[25,"group-red-collect"],[26,"group-part-water-splash"],[27,"group-part-water-splash-small"],[411,"group-docks-rig-light-lamp"],[28,"group-blue-hit-ground-effect"],[29,"spartacus-group-glow-steady"],[485,"group-desert-hanging-fire"],[30,"spartacus-group-night-glow-steady"],[31,"spartacus-group-glow-blinking"],[431,"group-peak-blowing-snow-powder"],[32,"spartacus-group-night-glow-blinking"],[33,"spartacus-group-fire-tiny"],[425,"group-snow-icebreak-c"],[34,"spartacus-group-fire-small"],[35,"spartacus-group-fire-medium"],[419,"group-drome-waterfall-mist-medium-fall"],[36,"spartacus-group-fire-large"],[37,"spartacus-group-fire-huge"],[429,"group-snowball-moving"],[38,"spartacus-group-steam"],[39,"spartacus-group-chimney-smoke"],[439,"group-canyon-ocean-splash"],[40,"spartacus-group-chimney-double-smoke"],[41,"spartacus-group-water-splash"],[433,"group-peak-billowing-snow-curl-large"],[42,"group-vehicle-part-fire-trail-wheel"],[43,"group-vehicle-part-fire-trail-panels"],[427,"group-cliffs-fence-dust-small"],[44,"group-vehicle-part-fire-trail-bits"],[45,"group-vehicle-part-fire-trail-chasis"],[437,"group-canyon-leaf-fall"],[46,"group-vehicle-explosion"],[47,"group-vehicle-engine-start"],[447,"group-temple-lavasplash"],[48,"group-forcefield-burst"],[53,"group-jakx-fire"],[445,"group-temple-waterfalls-splash"],[54,"group-jakx-fire-thin"],[55,"group-jakx-huge-explosion"],[391,"group-firework3-burst"],[56,"group-intro-opening-missile-thrust"],[57,"group-intro-opening-missile-smoke"],[385,"group-haven-gen-light"],[58,"group-intro-opening-muzzle-flash"],[59,"group-intro-opening-bullet-sparks"],[443,"group-temple-lamp-light"],[60,"group-intro-opening-bullet-sparks-local"],[61,"group-intro-vehicle-tire-skid"],[389,"group-firework1-burst"],[62,"group-intro-vehicle-tire-skid-stop"],[63,"group-intro-vehicle-tire-skid-brake"],[463,"group-garage-steam"],[64,"group-outro-vehicle-tire-skid"],[69,"group-intro-opening-debris-fire-glow"],[461,"group-sewer-splash"],[70,"group-outro-crash-b-fire"],[71,"group-outro-b-rising-smoke"],[471,"group-garage-screen-small-btm"],[72,"group-outro-b-car-steam"],[73,"group-outro-b-dripping-gas"],[465,"group-garage-panellight-yellow"],[74,"group-outro-b-car-fire"],[75,"group-outro-b-final-explosion"],[459,"group-sewer-drip"],[76,"group-outro-crash-b-wheel"],[77,"group-intro-vehicle-roll-fire"],[469,"group-garage-screen-big"],[78,"group-intro-vehicle-roll-glow"],[79,"group-intro-debris-landing-dust"],[80,"group-intro-debris-landing-sparks"],[81,"group-intro-car-little-explo"],[473,"group-garage-smalltv-glow"],[82,"group-intro-barrel-dust"],[83,"group-intro-vehicle-tunnel-dust"],[467,"group-garage-panellight-purple"],[84,"group-intro-mine-tunnel-burning-car"],[85,"group-intro-mine-tunnel-burning-car-smoke"],[477,"group-desisle-ocean-splash"],[86,"group-intro-mine-tunnel-burning-car-glow"],[87,"group-intro-tunnel-mine-glow"],[88,"group-intro-mine-landing-sparks"],[89,"group-intro-mine-landing-dust"],[90,"group-intro-mine-tunnel-car-explosion"],[91,"group-intro-vehicle-tire-skid-smoke"],[475,"group-kcross-fence-dust"],[92,"group-intro-vehicle-tire-skid-smoke2"],[93,"group-intro-car-explosion-wall"],[94,"group-intro-railing-collision"],[95,"group-intro-car-splash-far"],[495,"group-desert-waterfall-mist-fall"],[96,"group-intro-car-water-splash"],[97,"group-intro-fishtank-bubbles"],[489,"group-desert-palace-fire-beacon"],[98,"group-rustyh-pouring-liquid"],[99,"group-rustyh-pouring-liquid2"],[100,"group-rustyh-splashing-liquid"],[101,"group-rustyh-splashing-liquid-fog"],[493,"group-stronghold-torchfire"],[102,"group-rustyh-flying-liquid"],[103,"group-rustyh-big-splashing-liquid"],[503,"group-fishtank-bubbles"],[104,"grouLine truncated
@@ -1,3 +1,2 @@
// This overrides the stack size for calls to stack-size-set! in given functions.
{
}
{}
@@ -1,2 +1,855 @@
{
"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 9 cubic-curve)": [[16, "trajectory"]],
"(method 10 cubic-curve)": [[16, "trajectory"]],
"(method 11 cubic-curve)": [[16, "trajectory"]],
"(method 12 cubic-curve)": [[16, "trajectory"]],
"(method 13 cubic-curve)": [[16, "trajectory"]],
"matrix<-parented-transformq!": [[16, "vector"]],
"draw-axis": [
[32, "vector"],
[48, "vector"],
[64, "vector"],
[112, "vector"]
],
"(method 10 manipulator)": [
[112, "vector"],
[128, "vector"],
[160, "vector"],
[192, "vector"]
],
"(method 11 manipulator)": [
[64, "vector"],
[96, "vector"],
[144, "vector"],
[192, "vector"]
],
"ptest": [[16, "vector"]],
"check-drop-level-rain": [[16, "vector"]],
"spt-func-rocket": [[16, "vector"]],
"(method 115 wcar-base)": [
[16, "matrix"],
[64, "wcar-added-stack-type1"]
],
"(method 41 nav-mesh)": [
[16, "vector"],
[32, "vector"]
],
"(method 39 nav-mesh)": [
[16, "vector"],
[32, "vector"]
],
"light-trail-tracker-init-by-other": [[16, "vector"]],
"(method 11 impact-control)": [[16, "touching-shapes-entry"]],
"update-view-planes": [
[208, "vector"],
[224, "vector"]
],
"(method 24 mood-control)": [[16, "vector"]],
"add-collide-debug-box": [[16, "bounding-box"]],
"lightning-start": [
[16, "vector"],
[32, "vector"]
],
"joint-mod-look-at-handler": [
[16, "matrix"],
[80, "quaternion"],
[96, "vector"],
[112, "vector"],
[128, "vector"]
],
"joint-mod-ik-callback": [
[16, ["inline-array", "vector", 4]],
[80, "matrix"],
[144, "vector"],
[160, "vector"],
[176, "vector"],
[192, "vector"],
[208, "vector"],
[224, "vector"],
[240, "matrix"],
[272, "vector"],
[256, "vector"],
[288, "vector"],
[304, "vector"],
[320, "quaternion"],
[336, "quaternion"],
[352, "vector"],
[384, "vector"],
[448, "vector"],
[464, "vector"],
[480, "vector"],
[496, "quaternion"],
[512, "matrix"],
[576, "vector"],
[592, "matrix"],
[608, "matrix"],
[656, "matrix"],
[720, "matrix"],
[752, "matrix"]
],
"birth-func-set-pos-vel": [[16, ["inline-array", "vector", 2]]],
"birth-func-rain": [[16, "collide-query"]],
"part-wascitya-fly2-path": [
[16, "vector"],
[80, "vector"]
],
"update-mood-exterior": [[16, "vector"]],
"(method 25 mem-buffer)": [[16, ["inline-array", "quaternion", 1]]],
"joint-mod-joint-set*-world-handler": [[16, "matrix"]],
"add-debug-box": [
[16, "vector"],
[32, "vector"]
],
"add-debug-arc": [
[16, "vector"],
[32, "vector"]
],
"add-debug-points": [[16, "vector"]],
"add-debug-cursor": [[16, "vector"]],
"add-debug-cross": [
[48, "vector"],
[64, "vector"],
[80, "vector"],
[96, "vector"],
[112, "vector"],
[128, "vector"]
],
"internal-draw-debug-line": [[16, ["inline-array", "vector4w", 5]]],
"add-debug-triangle-normal": [[16, ["inline-array", "vector", 2]]],
"add-debug-line-sphere": [
[48, "matrix"],
[112, "matrix"],
[128, "vector"],
[144, "vector"],
[160, "vector"],
[176, "vector"],
[208, "vector"],
[192, "vector"]
],
"(method 11 lightning-bolt)": [[48, "vector"]],
"(method 16 lightning-bolt)": [[144, ["array", "rgba", 1]]],
"(method 12 lightning-bolt)": [
[80, "vector"],
[112, "matrix"],
[176, "vector"],
[192, "vector"],
[16, "vector"],
[32, "matrix"],
[304, "matrix"],
[272, "vector"],
[368, "vector"],
[384, "vector"]
],
"(method 9 plane-volume)": [
[64, "vector"],
[112, "vector"],
[16, "vector"],
[32, "vector"],
[48, "vector"],
[80, "vector"],
[128, "vector"]
],
"powerup-draw-init-by-other": [[16, "vector"]],
"ragdoll-joint-callback": [
[112, "vector"],
[128, "matrix"],
[192, "vector"],
[224, "vector"]
],
"(method 15 ragdoll)": [
[80, "matrix"],
[160, "vector"],
[304, "vector"],
[144, "vector"],
[176, "vector"],
[192, "vector"],
[208, "vector"],
[224, "vector"],
[240, "vector"]
],
"(method 14 ragdoll)": [[144, "vector"]],
"(method 10 ragdoll)": [[16, "vector"]],
"(code get-heap auto-save)": [
[16, ["array", "int32", 2]],
[32, ["array", "int32", 2]]
],
"(method 23 game-info)": [[16, ["array", "int16", 512]]],
"vis-dist-additional-ok?": [[16, ["array", "int32", 1]]],
"(method 30 path-control)": [
[16, ["array", "float", 129]],
[544, "vector"],
[560, "vector"]
],
"(method 28 path-control)": [
[80, "vector"],
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "vector"]
],
"aux-voice-running": [
[64, "medius-world-report"],
[16, ["array", "int32", 2]]
],
"(method 21 load-state)": [
[16, ["inline-array", "level-buffer-state", 18]],
[592, ["inline-array", "level-buffer-state", 18]]
],
"(method 9 level-bounding-box)": [[16, ["inline-array", "vector", 2]]],
"(method 46 process-drawable)": [
[16, "collide-query"],
[560, ["inline-array", "vector", 2]]
],
"(method 9 joint-control)": [[16, "vector"]],
"(anon-function 1 intro-scenes2)": [[16, "vehicle-spawn-params"]],
"(method 91 construction-object)": [[16, "vector"]],
"slave-set-rotation!": [
[96, "vector"],
[112, "matrix"],
[176, "vector"]
],
"(method 18 tracking-spline)": [[16, "tracking-spline-sampler"]],
"master-track-target": [[16, "vector"]],
"(method 10 end-credits-character-viewer)": [[16, "event-message-block"]],
"(code running end-credits-character-viewer)": [
[16, "event-message-block"],
[96, ["array", "symbol", 18]],
[176, "vehicle-spawn-params"]
],
"cam-helper-temp": [[16, ["inline-array", "vector", 3]]],
"draw-grid": [
[16, "vector"],
[32, "vector"],
[48, "vector"]
],
"(code cam-combiner-active)": [[16, "vector"]],
"(method 36 spatial-hash)": [[16, ["inline-array", "vector", 2]]],
"(method 17 sphere-hash)": [[16, "vector"]],
"(method 33 sphere-hash)": [[16, "vector"]],
"lightning-uniform-gen": [[16, "vector"]],
"lightning-trail-uniform-gen": [[16, "vector"]],
"lightning-trail-fractal-gen": [
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "vector"]
],
"target-generic-event-handler": [[16, "event-message-block"]],
"(method 12 nav-engine)": [
[16, "vector"],
[32, "vector"]
],
"debug-nav-validate-current-poly": [[16, "vector"]],
"(method 15 nav-link-search-info)": [[32, "vector"]],
"(method 14 nav-control)": [[16, "vector"]],
"(method 18 nav-control)": [[16, "nav-control-cfs-work"]],
"(method 19 nav-control)": [[16, "nav-control-cfs-work"]],
"circle-tangent-directions": [[48, "vector"]],
"(method 40 nav-state)": [
[128, ["inline-array", "vector", 1]],
[144, ["inline-array", "vector", 2]]
],
"(method 53 nav-state)": [
[16, "vector"],
[32, "nav-route-portal"],
[80, ["inline-array", "vector", 3]],
[192, "matrix"],
[224, "nav-route-portal"]
],
"(method 9 nav-control)": [[16, "vector"]],
"(method 16 debris-group)": [
[64, "vector"],
[32, "vector"]
],
"debris-group-init-by-other": [[16, "vector"]],
"merc-blend-shape": [[16, ["array", "int16", 128]]],
"add-debug-flat-triangle-noclip": [[16, ["inline-array", "vector4w", 9]]],
"(trans idle keyboard-control)": [[16, "symbol"]], // ?
"update-stuff": [[16, "quaternion"]],
"activate-bar": [[16, "vector"]],
"(method 10 collide-mesh)": [[16, "oot-work"]],
"camera-teleport-to-location": [[16, "matrix"]],
"camera-teleport-to-entity": [[16, "matrix"]],
"init-for-transform": [
[16, "matrix"],
[80, "matrix"],
[192, "vector"]
],
"should-push-away-test-mesh": [[16, "oot-work"]],
"(method 115 v-bear)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-bobcat)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-cheetah)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-drone)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-falcon)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"clmf-pos-rot": [[112, "matrix"]],
"(method 9 actor-hash-buckets)": [
[16, ["inline-array", "vector", 2]],
[48, ["inline-array", "vector", 2]]
],
"(method 115 v-wombat)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-wolf)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-tiger)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-snake)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-possum)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-panther)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-mongoose)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-leopard)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-gila)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-daxtermobile)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"(method 115 v-cougar)": [
[16, "quaternion"],
[32, ["inline-array", "quaternion", 2]]
],
"cam-layout-entity-info": [[208, "vector"]],
"(code cam-point-watch)": [[16, "vector"]],
"cam-mouse-input": [[64, "vector"]],
"add-a-bunch": [[16, "vector"]],
"projectile-bounce-falling-post": [[16, "collide-query"]],
"(method 69 projectile)": [[16, "collide-query"]],
"projectile-update-velocity-add-gravity": [[16, "vector"]],
"projectile-update-velocity-space-wars": [
[16, "vector"],
[64, "vector"]
],
"(method 71 construction-object)": [[80, "cquery-with-pad"]],
"(method 18 ragdoll)": [[16, "collide-query"]],
"(event idle can-leaves-floor)": [[16, ["inline-array", "matrix", 1]]],
"(enter dropped ctf-flag)": [
[16, "task-arrow-params"],
[80, "vector"]
],
"flag-fall": [[560, "vector"]],
"(exit carried ctf-flag)": [[16, "event-message-block"]],
"(enter idle ctf-flag)": [[80, "vector"]],
"(method 45 jungle-stone-snake-head)": [
[16, "vector"],
[32, "vector"]
],
"spawn-flame": [[16, "jungle-obs-stack-var0"]],
"(post idle kras-fireworks-ship-a)": [[16, ["inline-array", "vector", 1]]],
"(method 23 mysql-nav-graph)": [[16, ["inline-array", "vector", 5]]],
"(post idle wm-fireworks-ship)": [[16, ["inline-array", "vector", 1]]],
"(code explode peak-snowball)": [[32, "quaternion"]],
"(method 71 peak-snowball)": [
[16, "vector"],
[32, ["inline-array", "collide-query", 1]]
],
"(method 10 visvol-edit-info)": [
[16, "vector"],
[32, "vector"]
],
"(method 9 camera-facing-quad)": [[16, "camera-facing-quad-stackvar0"]],
"(method 16 collide-cache)": [[16, "collide-puls-work"]],
"test-closest-pt-in-triangle": [
[16, "vector"],
[32, "vector"],
[48, "vector"]
],
"(method 14 collide-cache)": [[16, "bounding-box"]],
"(method 20 collide-cache)": [[16, "matrix"]],
"col-rend-draw": [[16, "matrix"]],
"(method 63 collide-shape-moving)": [[48, "vector"]],
"cshape-reaction-default": [[16, "vector"]],
"(method 10 editable-plane)": [[16, ["inline-array", "vector", 4]]],
"(method 13 editable-plane)": [[64, ["inline-array", "vector", 4]]],
"(method 10 editable-face)": [[16, ["inline-array", "vector", 6]]],
"(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"],
[448, "vector"]
],
"(method 13 editable-face)": [[64, ["inline-array", "vector", 6]]],
"(method 37 editable-face)": [[16, ["inline-array", "vector", 6]]],
"(method 13 editable-array)": [
[96, "vector"],
[160, "vector"]
],
"cshape-reaction-update-state": [
[16, "vector"],
[32, "vector"]
],
"(method 70 wvehicle)": [[32, "update-engine-mix-state-work"]],
"find-nearest-focusable": [[48, "vector"]],
"(method 55 joint-exploder)": [[16, "bounding-box"]],
"(method 53 ocean)": [[16, "vector"]],
"(method 47 ocean)": [[16, "vector"]],
"(method 40 ocean)": [[16, "vector"]],
"(method 29 ocean)": [[16, "vector"]],
"(method 30 ocean)": [
[16, "vector"],
[32, "vector"]
],
"(method 54 ocean)": [
[16, "vector"],
[32, "vector"]
],
"(method 55 ocean)": [
[16, "vector"],
[32, "vector"]
],
"(method 56 ocean)": [
[16, "vector"],
[32, "vector"]
],
"(method 57 ocean)": [
[16, "vector"],
[32, "vector"]
],
"(method 13 ocean)": [[16, "vector"]],
"update-camera": [[16, "camera-free-floating-move-info"]],
"(method 92 construction-object)": [[16, "sprite-glow-data"]],
"(code getting-universe-information net-mgr)": [
[16, "medius-server-world-status-response"]
],
"camera-slave-debug": [
[48, "matrix"],
[144, "vector"]
],
"cam-layout-save-interesting": [[16, "vector"]],
"cam-layout-save-align": [[16, "vector"]],
"cam-layout-save-pivot": [[16, "vector"]],
"cam-layout-entity-volume-info-create": [
[32, "vector"],
[48, "vector"],
[64, "vector"],
[80, "vector"],
[96, "vector"],
[128, "vector"],
[144, "vector"]
],
"(method 59 nav-graph-editor)": [[16, "nav-poly"]],
"(method 32 nav-graph-editor)": [[16, ["inline-array", "vector", 4]]],
"(method 33 nav-graph-editor)": [
[16, "vector"],
[32, "vector"]
],
"(method 30 nav-graph-editor)": [
[32, "vector"],
[48, ["inline-array", "vector", 2]],
[112, "vector"],
[128, "vector"],
[144, "vector"]
],
"(method 36 nav-graph-editor)": [[16, ["inline-array", "vector", 4]]],
"(method 38 nav-graph-editor)": [
[80, "vector"],
[656, "nav-poly"],
[880, ["inline-array", "vector", 4]]
],
"(method 50 nav-graph-editor)": [
[16, "vector"],
[32, "vector"]
],
"(method 48 nav-graph-editor)": [
[48, "vector"],
[96, "vector"],
[128, "vector"]
],
"(method 14 nav-mesh-editable)": [
[16, ["inline-array", "vector", 4]],
[80, ["inline-array", "vector", 4]]
],
"(method 34 nav-graph-editor)": [
[16, "vector"],
[48, ["inline-array", "vector", 2]]
],
"(post draw-closest-minimap nav-graph-editor)": [
[64, ["inline-array", "vector", 4]]
],
"update-height": [[16, "vector"]],
"snap-level-navmesh": [
[16, "vector"],
[64, "vector"]
],
"(method 12 nav-mesh-editable)": [[32, "vector"]],
"(method 15 nav-mesh-editable)": [[16, "vector"]],
"(method 16 nav-mesh-editable)": [
[16, "vector"],
[48, "vector"]
],
"(method 10 nav-mesh-poly)": [
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "vector"],
[80, "vector"],
[96, "vector"],
[112, "vector"],
[128, "vector"]
],
"(method 52 nav-mesh-editor)": [[80, "vector"]],
"(trans idle nav-mesh-editor)": [[16, "event-message-block"]],
"(method 25 grid-hash)": [
[16, "grid-hash-box"],
[32, "grid-hash-box"],
[48, "vector"],
[64, "vector"]
],
"(method 26 grid-hash)": [[16, "vector"]],
"(method 11 grid-hash)": [
[16, "vector"],
[32, "vector"]
],
"(method 13 grid-hash)": [[16, "sphere"]],
"(method 22 editable)": [
[16, "vector"],
[32, "vector"]
],
"(method 14 editable-point)": [
[32, "vector"],
[48, "vector"],
[80, ["inline-array", "vector", 4]]
],
"execute-mouse-move": [
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "vector"],
[80, "vector"],
[112, "vector"]
],
"insert-wall": [[32, ["array", "int32", 2]]],
"insert-box": [[32, ["array", "int32", 8]]],
"(method 21 editable-entity)": [[80, "vector"]],
"(method 51 editable-player)": [[16, "vector"]],
"update-manipulator-position": [[16, "vector"]],
"(code playing-playback-game net-mgr)": [
[16, "event-message-block"],
[96, "mem-buffer"]
],
"texture-anim-layer-draw": [
[16, "matrix"],
[80, "matrix"],
[144, "matrix"],
[208, "matrix"]
],
"handle-sys-msg": [[96, "medius-chat-fwd-message"]],
"real-fog-texture-anim-func": [
[16, "vector"],
[32, "vector"]
],
"(method 220 wvehicle)": [
[16, "vector"],
[32, ["inline-array", "vector", 3]]
],
"wv-player-post-move-update": [[16, "event-message-block"]],
"(method 133 wvehicle)": [[16, "vector"]],
"(method 87 vehicle-wheel)": [[16, "rigid-body-move-work"]],
"(method 68 wvehicle)": [
[16, "vector"],
[32, "vector"]
],
"(method 229 wvehicle)": [[16, "matrix"]],
"player-wait-control-hook": [[16, "vehicle-controls"]],
"(enter explode wvehicle)": [
[16, "event-message-block"],
[96, ["inline-array", "vector", 2]]
],
"(post explode wvehicle)": [
[16, "vector"],
[32, "vector"]
],
"(enter explode-into-nothing wvehicle)": [[16, "explosion-init-params"]],
"(method 235 wvehicle)": [[32, ["inline-array", "vector", 3]]],
"(method 234 wvehicle)": [
[32, ["inline-array", "vector", 3]],
[80, "vector"],
[96, "vector4s-3"]
],
"spt-func-birth-on-height-die-drip-sewer": [
[16, "vector"],
[32, "vector"]
],
"spt-func-birth-on-die4": [
[16, "vector"],
[32, "vector"]
],
"spt-func-birth-on-die3": [
[16, "vector"],
[32, "vector"]
],
"spt-func-birth-on-die2": [
[16, "vector"],
[32, "vector"]
],
"spt-func-birth-on-die1": [
[16, "vector"],
[32, "vector"]
],
"spt-func-birth-on-height-die-drops": [
[16, "vector"],
[32, "vector"]
],
"part-jungle-bird10-path": [
[80, "vector"],
[96, "vector"]
],
"part-jungle-bird9-path": [[80, "vector"]],
"spt-func-birth-on-pop": [[16, "vector"]],
"spt-func-birth-on-height-die": [[16, "vector"]],
"spt-func-birth-on-height-die-drip": [
[16, "vector"],
[32, "vector"]
],
"(method 16 nav-link-search-info)": [
[16, "vector"],
[48, "vector"]
],
"(method 41 nav-control)": [
[16, "vector"],
[48, ["inline-array", "vector", 2]]
],
"(method 11 nav-control)": [[16, "nav-poly"]],
"(method 51 nav-state)": [[16, "nav-ray"]],
"(method 54 nav-state)": [[112, "nav-ray"]],
"(method 11 nav-state)": [
[16, "vector"],
[32, "vector"]
],
"(method 24 nav-state)": [[16, ["inline-array", "vector", 2]]],
"(method 28 nav-state)": [[208, "vector"]],
"(method 34 nav-state)": [[16, ["inline-array", "vector", 2]]],
"(method 31 nav-state)": [[112, "nav-ray"]],
"(method 32 nav-state)": [[16, "nav-control-cfs-work"]],
"(method 37 nav-state)": [[16, ["inline-array", "vector", 2]]],
"(anon-function 9 nav-control)": [[16, ["inline-array", "vector", 2]]],
"(anon-function 4 nav-control)": [[16, ["inline-array", "vector", 2]]],
"(method 19 nav-mesh)": [[16, "nav-ray"]],
"(method 21 nav-control)": [[16, "nav-ray"]],
"(post idle peak-snowball)": [
[48, "peak-obs-stackvar0"],
[128, ["inline-array", "vector", 3]]
],
"(method 17 peak-snowball)": [[48, "peak-obs-stackvar0"]],
"(method 71 coli-atlas-globe)": [
[16, ["inline-array", "collide-query", 1]],
[560, ["inline-array", "vector", 3]]
],
"(method 82 coli-atlas-globe)": [
[16, "rigid-body-impact"],
[96, "vector"]
],
"(method 80 coli-atlas-globe)": [[32, "peak-obs-stackvar0"]],
"(method 45 kras-pump-break)": [
[16, "vector"],
[32, "vector"]
],
"(method 52 palm-tree)": [
[16, "vector"],
[32, "desarena-obs-stackvar0"]
],
"(method 55 palm-tree)": [[16, "vector"]],
"(event vibrate palm-tree)": [[16, "vector"]],
"(event idle palm-tree)": [[16, "vector"]],
"part-menumap-bird1-path": [[80, "vector"]],
"part-menumap-bird2-path": [[80, "vector"]],
"part-menumap-bird3-path": [[80, "vector"]],
"part-menumap-bird4-path": [[80, "vector"]],
"part-menumap-bird5-path": [[80, "vector"]],
"part-menumap-bird6-path": [[80, "vector"]],
"part-menumap-bird7-path": [[80, "vector"]],
"part-menumap-bird8-path": [[80, "vector"]],
"part-menumap-bird9-path": [[80, "vector"]],
"part-menumap-bird10-path": [[80, "vector"]],
"spt-func-menumap-rocket": [[16, "vector"]],
"spt-func-menumap-birth-on-die4": [
[16, "vector"],
[32, "vector"]
],
"spt-func-menumap-birth-on-die3": [
[16, "vector"],
[32, "vector"]
],
"spt-func-menumap-birth-on-die2": [
[16, "vector"],
[32, "vector"]
],
"spt-func-menumap-birth-on-die1": [
[16, "vector"],
[32, "vector"]
],
"birth-func-vws-adopt-velocity": [[16, "vector"]],
"check-scorp-shell-level1": [[16, "vector"]],
"check-scorp-shell-level2": [[16, "vector"]],
"update-engine-mix-state": [[32, "vehicle-wheel-init-params"]],
"(method 52 garage-turntable)": [
[32, "vector"],
[48, "vector"],
[64, "vector"],
[80, ["inline-array", "vector", 18]]
],
"(enter explode kras-pump-break-proxy)": [[16, "event-message-block"]],
"(method 249 wvehicle)": [[16, "race-line-query-info"]],
"(method 65 vehicle-debris)": [[16, "vehicle-hardpoint-info"]],
"(method 87 vehicle-debris)": [[16, ["inline-array", "collide-query", 1]]],
"(method 185 vehicle)": [[16, "vector"]],
"(method 136 vehicle)": [[16, ["inline-array", "vector", 2]]],
"test-vehicle-weapon": [[16, "event-message-block"]],
"sound-name->string": [[16, ["array", "uint8", 16]]],
"string->sound-name": [[16, ["array", "sound-name", 1]]],
"vehicle-draw-thruster": [[16, "vehicle-thruster-work"]],
"(method 45 collide-shape)": [[16, "do-push-aways-work"]],
"(method 50 collide-shape)": [
[32, "vector"],
[48, "vector"]
],
"(method 18 collide-shape-prim-mesh)": [[16, "collide-tri-result"]],
"(method 18 collide-shape-prim-sphere)": [
[48, ["inline-array", "vector", 6]]
],
"(method 65 collide-shape-moving)": [[576, ["inline-array", "vector", 2]]],
"(anon-function 5 gsound)": [
[16, ["array", "symbol", 4]],
[32, ["array", "symbol", 4]]
],
"doppler-pitch-shift": [[16, ["inline-array", "vector", 2]]],
"(method 113 vehicle)": [[16, "vehicle-stack-type3"]],
"(code target-intro)": [[16, "vector"]],
"particle-adgif-callback": [[16, ["inline-array", "vector", 4]]],
"sp-adjust-launch": [[16, "matrix"]],
"sp-launch-particles-death": [[16, "matrix"]],
"sp-relaunch-setup-fields": [[16, "matrix"]],
"sparticle-rotate-to-vel-3d": [[16, "vector"]],
"sparticle-respawn-heights": [[16, "vector"]],
"sparticle-respawn-timer": [[16, "vector"]],
"sparticle-3d-rotate-xz-to-camera": [[16, "vector"]],
"spt-func-relative-pos": [
[16, "vector"],
[32, "vector"],
[48, "vector"],
[64, "matrix"],
[128, "matrix"],
[192, "matrix"]
],
"spt-func-turn-to-vel-radial": [[16, "vector"]],
"(method 54 collectoid-draw)": [[16, ["inline-array", "vector", 2]]],
"drop-collectoids": [[16, "net-powerup-spawn-params"]],
"(method 15 sparticle-launch-control)": [[16, "sphere"]],
"execute-part-engine": [[112, "matrix"]],
"(method 17 collide-shape-prim-mesh)": [[16, "collide-tri-result"]],
"update-time-of-day": [[16, "vector"]]
}
@@ -1 +1 @@
[[2147418112,{"idx":0,"name":"placeholder-white","tpage_name":"placeholder"}],[261029888,{"idx":0,"name":"snob-dirt-ground-01","tpage_name":"snobowlx-vis-alpha"}],[260898816,{"idx":0,"name":"kcro-ground-layover-a","tpage_name":"kcross-vis-alpha"}],[260702209,{"idx":1,"name":"snow-ground-overlay-01","tpage_name":"snowx-vis-alpha"}],[260702208,{"idx":0,"name":"snow-ground-overlay-02","tpage_name":"snowx-vis-alpha"}],[260571136,{"idx":0,"name":"peak-ground-snow-overlay-01","tpage_name":"peakb-vis-alpha"}],[260440064,{"idx":0,"name":"ice-snowoverlay-01","tpage_name":"icec-vis-alpha"}],[259981321,{"idx":9,"name":"pecker-yellowfur","tpage_name":"peccred-pris2"}],[259981320,{"idx":8,"name":"pecker-wingtop","tpage_name":"peccred-pris2"}],[259981319,{"idx":7,"name":"pecker-wingbottom","tpage_name":"peccred-pris2"}],[259981318,{"idx":6,"name":"pecker-teeth","tpage_name":"peccred-pris2"}],[259981317,{"idx":5,"name":"pecker-tail","tpage_name":"peccred-pris2"}],[259981316,{"idx":4,"name":"pecker-plume","tpage_name":"peccred-pris2"}],[259981314,{"idx":2,"name":"pecker-eyelid","tpage_name":"peccred-pris2"}],[259784705,{"idx":1,"name":"charHOLD","tpage_name":"thbcred-pris2"}],[259784704,{"idx":0,"name":"bam-eyelight","tpage_name":"thbcred-pris2"}],[259653673,{"idx":41,"name":"bam-eyelight","tpage_name":"ashcred-pris2"}],[259653672,{"idx":40,"name":"ashelin-whitestrap","tpage_name":"ashcred-pris2"}],[259653670,{"idx":38,"name":"ashelin-shortsleg","tpage_name":"ashcred-pris2"}],[259653669,{"idx":37,"name":"ashelin-shortscuff","tpage_name":"ashcred-pris2"}],[259653668,{"idx":36,"name":"ashelin-shortsback","tpage_name":"ashcred-pris2"}],[259653663,{"idx":31,"name":"ashelin-lowerlegging","tpage_name":"ashcred-pris2"}],[259653662,{"idx":30,"name":"ashelin-jacketrt","tpage_name":"ashcred-pris2"}],[259653661,{"idx":29,"name":"ashelin-jacketbody","tpage_name":"ashcred-pris2"}],[259653660,{"idx":28,"name":"ashelin-jacketbelt-end","tpage_name":"ashcred-pris2"}],[259653659,{"idx":27,"name":"ashelin-jacketbelt","tpage_name":"ashcred-pris2"}],[259653658,{"idx":26,"name":"ashelin-jacketback","tpage_name":"ashcred-pris2"}],[259653649,{"idx":17,"name":"ashelin-gunbarrel-01","tpage_name":"ashcred-pris2"}],[259653648,{"idx":16,"name":"ashelin-goggle","tpage_name":"ashcred-pris2"}],[259653647,{"idx":15,"name":"ashelin-glove","tpage_name":"ashcred-pris2"}],[259653646,{"idx":14,"name":"ashelin-face","tpage_name":"ashcred-pris2"}],[259653645,{"idx":13,"name":"ashelin-eyelid","tpage_name":"ashcred-pris2"}],[259653644,{"idx":12,"name":"ashelin-eyebrow","tpage_name":"ashcred-pris2"}],[259653643,{"idx":11,"name":"ashelin-eye","tpage_name":"ashcred-pris2"}],[259653642,{"idx":10,"name":"ashelin-collar","tpage_name":"ashcred-pris2"}],[259653641,{"idx":9,"name":"ashelin-chest","tpage_name":"ashcred-pris2"}],[259653640,{"idx":8,"name":"ashelin-buckle","tpage_name":"ashcred-pris2"}],[259653639,{"idx":7,"name":"ashelin-brownstrap","tpage_name":"ashcred-pris2"}],[259653638,{"idx":6,"name":"ashelin-bra","tpage_name":"ashcred-pris2"}],[259653637,{"idx":5,"name":"ashelin-boottop","tpage_name":"ashcred-pris2"}],[259653633,{"idx":1,"name":"ashelin-beltbuckle","tpage_name":"ashcred-pris2"}],[259457042,{"idx":18,"name":"daxterlense","tpage_name":"daxcred-pris2"}],[259457040,{"idx":16,"name":"daxterheadwidenew","tpage_name":"daxcred-pris2"}],[259457039,{"idx":15,"name":"daxtergoggles","tpage_name":"daxcred-pris2"}],[259457038,{"idx":14,"name":"daxterfoot-bottom","tpage_name":"daxcred-pris2"}],[259457037,{"idx":13,"name":"daxterfoot","tpage_name":"daxcred-pris2"}],[259457036,{"idx":12,"name":"daxterfinger","tpage_name":"daxcred-pris2"}],[259457035,{"idx":11,"name":"daxterear","tpage_name":"daxcred-pris2"}],[259457034,{"idx":10,"name":"daxterbolt","tpage_name":"daxcred-pris2"}],[259457033,{"idx":9,"name":"daxterbodyshort-eix","tpage_name":"daxcred-pris2"}],[259457032,{"idx":8,"name":"daxterarm","tpage_name":"daxcred-pris2"}],[259457031,{"idx":7,"name":"daxter-pants","tpage_name":"daxcred-pris2"}],[259457030,{"idx":6,"name":"daxter-orange","tpage_name":"daxcred-pris2"}],[259457029,{"idx":5,"name":"daxter-furhilite","tpage_name":"daxcred-pris2"}],[259457028,{"idx":4,"name":"daxter-eyelid","tpage_name":"daxcred-pris2"}],[259457027,{"idx":3,"name":"daxter-belt-02","tpage_name":"daxcred-pris2"}],[259457026,{"idx":2,"name":"daxter-belt-01","tpage_name":"daxcred-pris2"}],[259457025,{"idx":1,"name":"bam-hairhilite","tpage_name":"daxcred-pris2"}],[259457024,{"idx":0,"name":"bam-eyelight","tpage_name":"daxcred-pris2"}],[259391510,{"idx":22,"name":"gt-blitz-zipper-01","tpage_name":"gtbcred-pris2"}],[259391504,{"idx":16,"name":"gt-blitz-jacketsleeve","tpage_name":"gtbcred-pris2"}],[259391503,{"idx":15,"name":"gt-blitz-jacketdetails","tpage_name":"gtbcred-pris2"}],[259391502,{"idx":14,"name":"gt-blitz-jacketbody","tpage_name":"gtbcred-pris2"}],[259391501,{"idx":13,"name":"gt-blitz-handpalm","tpage_name":"gtbcred-pris2"}],[259391497,{"idx":9,"name":"gt-blitz-facenew","tpage_name"Line truncated
[[197918735,{"idx":15,"name":"drome-concrete-01","tpage_name":"dromec-vis-tfrag"}],[176816166,{"idx":38,"name":"temple-a-sndstn-dtl03","tpage_name":"templex-vis-tfrag"}],[198770738,{"idx":50,"name":"atoll-sand-patch","tpage_name":"atollx-vis-tfrag"}],[257949719,{"idx":23,"name":"thug-a-maskb-leather-02","tpage_name":"thacred-pris2"}],[261029888,{"idx":0,"name":"snob-dirt-ground-01","tpage_name":"snobowlx-vis-alpha"}],[152174599,{"idx":7,"name":"time-freeze-circle-purple","tpage_name":"sprgstbx-pris"}],[227016705,{"idx":1,"name":"time-freeze-cage-cap","tpage_name":"peaktbox-pris"}],[242810881,{"idx":1,"name":"hud-rank-taryn-02","tpage_name":"tarlev-minimap"}],[172949579,{"idx":75,"name":"ice-snow-drift-01","tpage_name":"iceb-vis-tfrag"}],[111214641,{"idx":49,"name":"city-sideframe-plain","tpage_name":"havenx-vis-tfrag"}],[63111168,{"idx":0,"name":"city-slum-wire","tpage_name":"havena-vis-shrub"}],[186580996,{"idx":4,"name":"time-freeze-circle-purple","tpage_name":"cnsptbox-pris"}],[259457032,{"idx":8,"name":"daxterarm","tpage_name":"daxcred-pris2"}],[2147418112,{"idx":0,"name":"placeholder-white","tpage_name":"placeholder"}],[254148641,{"idx":33,"name":"kras-sign-b-neon-22","tpage_name":"dockkras-alpha"}],[169476150,{"idx":54,"name":"docks-blue-paint-04","tpage_name":"docksb-vis-tfrag"}],[194248727,{"idx":23,"name":"peak-precursor-bot-stuff-01","tpage_name":"icetourw-tfrag"}],[201195533,{"idx":13,"name":"haven-train-turbine-side","tpage_name":"dromdocx-vis-pris"}],[118358033,{"idx":17,"name":"kcro-metal-pipe-02","tpage_name":"kcross-vis-shrub"}],[148111378,{"idx":18,"name":"des-red-rock-01","tpage_name":"canyond-vis-tfrag"}],[111214705,{"idx":113,"name":"city-dirtywood","tpage_name":"havenx-vis-tfrag"}],[179896397,{"idx":77,"name":"peak-precursor-bot-01","tpage_name":"icebergx-vis-tfrag"}],[720925,{"idx":29,"name":"loadsave-screen","tpage_name":"level-default-shrub"}],[259653661,{"idx":29,"name":"ashelin-jacketbody","tpage_name":"ashcred-pris2"}],[173408268,{"idx":12,"name":"train-hanger-arrow-dest","tpage_name":"dockss-water"}],[167968769,{"idx":1,"name":"this-way-arrow-02","tpage_name":"jungles-water"}],[254935079,{"idx":39,"name":"jakx-jacketstraps-01","tpage_name":"jakcred-pris2"}],[155123728,{"idx":16,"name":"sewer-plate-03","tpage_name":"sewerf-vis-tfrag"}],[177799179,{"idx":11,"name":"peak-snow-treesnow","tpage_name":"peakd-vis-tfrag"}],[161546254,{"idx":14,"name":"jungle-bird-15","tpage_name":"havtours-sprite"}],[175570965,{"idx":21,"name":"temple-a-sndstn-trm06","tpage_name":"templeb-vis-tfrag"}],[86114313,{"idx":9,"name":"m-raptor-thigh","tpage_name":"deshunt2-pris"}],[260898816,{"idx":0,"name":"kcro-ground-layover-a","tpage_name":"kcross-vis-alpha"}],[42467354,{"idx":26,"name":"jungle-bark-green","tpage_name":"jungled-vis-tfrag"}],[25559065,{"idx":25,"name":"kras-metal-09","tpage_name":"krasx-vis-tfrag"}],[159776769,{"idx":1,"name":"artifact-blue-glow-01","tpage_name":"kcrosart-tfrag"}],[115605594,{"idx":90,"name":"city-inda-wallbase","tpage_name":"haveny-vis-tfrag"}],[108462081,{"idx":1,"name":"desa-stillwater","tpage_name":"desarenx-vis-water"}],[257949733,{"idx":37,"name":"thug-a-teeth","tpage_name":"thacred-pris2"}],[169214028,{"idx":76,"name":"docks-a-dup-sfalt-03","tpage_name":"docksa-vis-tfrag"}],[179044438,{"idx":86,"name":"peak-fm-rocktosnow-02","tpage_name":"peakx-vis-tfrag"}],[191102987,{"idx":11,"name":"world-map-tracks-02","tpage_name":"menumap-pris"}],[201195521,{"idx":1,"name":"haven-train-brown-bar","tpage_name":"dromdocx-vis-pris"}],[160038971,{"idx":59,"name":"can-cart","tpage_name":"canyonx-vis-tfrag"}],[41943088,{"idx":48,"name":"jungle-stone-block-tunnel-02","tpage_name":"junglee-vis-tfrag"}],[223215619,{"idx":3,"name":"this-way-scan","tpage_name":"temples-water"}],[118030402,{"idx":66,"name":"grg-wall-05","tpage_name":"garageb-tfrag"}],[128450699,{"idx":139,"name":"cty-fence","tpage_name":"havsewy-vis-tfrag"}],[260702209,{"idx":1,"name":"snow-ground-overlay-01","tpage_name":"snowx-vis-alpha"}],[191103010,{"idx":34,"name":"worldmap-kcro-metal-plate-01","tpage_name":"menumap-pris"}],[25559058,{"idx":18,"name":"kras-temp-neon-blue","tpage_name":"krasx-vis-tfrag"}],[142868487,{"idx":7,"name":"iscreen-metal-pipe-04","tpage_name":"garage-pris"}],[180617217,{"idx":1,"name":"artifact-blue-glow-01","tpage_name":"disleart-tfrag"}],[147390466,{"idx":2,"name":"spar-stone-top","tpage_name":"sparguse-vis-tfrag"}],[130482205,{"idx":29,"name":"sew-metal-33","tpage_name":"sewerx-vis-tfrag"}],[199229446,{"idx":6,"name":"atoll-ribbed","tpage_name":"atoll-vis-shrub"}],[260702208,{"idx":0,"name":"snow-ground-overlay-02","tpage_name":"snowx-vis-alpha"}],[50921549,{"idx":77,"name":"wstlander-02-shirt","tpage_name":"rustyh-pris"}],[201195530,{"idx":10,"name":"haven-train-orange-trim","tpage_name":"dromdocx-vis-pris"}],[178192476,{"idx":92,"name":"ice-rock-wall-01","tpage_name":"icex-vis-tfrag"}],[194248704,{"idx":0,"name":"peak-precursor-siding-02","tpage_name":"icetourw-tfrag"}],[104923198,{"idx":Line truncated
Loaded 100 of 11805 files, more files were not shown because too many files have changed in this diff. Show more