Compare commits

...
Author SHA1 Message Date
Tyler Wilding 55204e6996 decomp: ensure out_folder exists before being written to 2024-06-21 22:58:16 -04:00
Tyler Wilding b2cfefb669 decomp/config: simplify enabling streamed audio ripping, string wasn't even in use anymore 2024-06-19 23:43:34 -04:00
Tyler Wilding bc586f0cca lint: formatting 2024-06-15 15:43:04 -04:00
Tyler Wilding 13e7a28c08 decomp: eliminate duplicate code in extractor/decompiler
This allows the extractor's decompilation routine to do all the things the normal decompiler can (ie. extract audio)
2024-06-15 15:42:27 -04:00
Tyler Wilding 17665a4615 decomp: pull out main decompilation process into an isolated function 2024-06-15 15:41:56 -04:00
Tyler Wilding d209766078 util: support get_peak_rss on windows 2024-06-15 15:41:40 -04:00
Matt Dallmeyer 86979e3d06 [jak1] Enforce certain pc-settings in speedrunner mode (#3553)
Currently PS2 Actor Vis and FPS are only enforced when starting a run -
this enforces them on every frame similar to cheats.
In the progress menu, FPS is already disabled in speedrunner mode - this
adds the same restriction for PS2 Actor Vis.

Jak 2 already does this properly, no change needed there
2024-06-15 14:54:53 -04:00
OpenGOAL BotandOpenGOALBot 29849a4fbb CI: Periodic Controller Database Update (#3555)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-06-15 00:13:41 -04:00
RoyalForgotten b0b9fc4311 Jak 2 3rd update subtitle_lines_fr-FR.json (#3546)
Fixed several translation errors
2024-06-05 23:19:10 -04:00
Tyler Wilding c162c66118 g/j1: Cleanup all main issues in the formatter and format all of goal_src/jak1 (#3535)
This PR does two main things:
1. Work through the main low-hanging fruit issues in the formatter
keeping it from feeling mature and usable
2. Iterate and prove that point by formatting all of the Jak 1 code
base. **This has removed around 100K lines in total.**
- The decompiler will now format it's results for jak 1 to keep things
from drifting back to where they were. This is controlled by a new
config flag `format_code`.

How am I confident this hasn't broken anything?:
- I compiled the entire project and stored it's `out/jak1/obj` files
separately
- I then recompiled the project after formatting and wrote a script that
md5's each file and compares it (`compare-compilation-outputs.py`
- The results (eventually) were the same:

![Screenshot 2024-05-25
132900](https://github.com/open-goal/jak-project/assets/13153231/015e6f20-8d19-49b7-9951-97fa88ddc6c2)
> This proves that the only difference before and after is non-critical
whitespace for all code/macros that is actually in use.

I'm still aware of improvements that could be made to the formatter, as
well as general optimization of it's performance. But in general these
are for rare or non-critical situations in my opinion and I'll work
through them before doing Jak 2. The vast majority looks great and is
working properly at this point. Those known issues are the following if
you are curious:

![image](https://github.com/open-goal/jak-project/assets/13153231/0edfaba1-6d36-40f5-ab23-0642209867c4)
2024-06-05 22:17:31 -04:00
ManDude 37762c5fb7 wrap sprite rgba to 0-255 (#3549) 2024-06-04 07:57:52 +01:00
OpenGOAL BotandOpenGOALBot a18d9dd4d0 CI: Periodic Controller Database Update (#3548)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-06-03 23:00:48 -04:00
Tyler Wilding a9bdb0136e New Crowdin updates (#3547)
People seem to be translating lines that aren't in the base english one,
such as `mtn-plat-buried-rocks-a`

This is fine, but Crowdin will continue to remove these every sync PR
because they aren't in the base english file. So some kind of
segregation needs to happen.

If we didn't want these scenes translated, then they should be banned
from being translated via the editor / etc in the first place (shouldn't
have been included in the metadata).
2024-06-03 01:01:58 -04:00
Tyler Wilding eb703ee96e REPL related improvements and fixes (#3545)
Motivated by - https://github.com/open-goal/opengoal-vscode/pull/358

This addresses the following:
- Fixes #2939 spam edge-case
- Stop picking a different nREPL port based on the game mode by default,
this causes friction for tools in the average usecase (having a REPL
open for a single game, and wanting to connect to it). `goalc` spins up
fine even if the port is already bound to.
- For people that need/want this behaviour, adding per-game
configuration to the `repl-config.json` is on my todo list.
- Allows `goalc` to permit redefining symbols, including functions. This
is defaulted to off via the `repl-config.json` but it allows you to for
example, change the definition of a function without having to restart
and rebuild the entire game.
![Screenshot 2024-06-02
124558](https://github.com/open-goal/jak-project/assets/13153231/28f81f6e-b7b8-4172-9787-f96e4ab1305b)
- Updates the welcome message to include a bunch of useful metadata
up-front. Cleaned up all the startup logs that appear when starting
goalc, many of whom's information is now included in the welcome
message.
  - Before:

![image](https://github.com/open-goal/jak-project/assets/13153231/814c2374-4808-408e-9ed6-67114902a1d9)

  - After:
![Screenshot 2024-06-01
235954](https://github.com/open-goal/jak-project/assets/13153231/f3f459fb-2cbb-46ba-a90f-318243d4b3b3)
2024-06-03 00:14:52 -04:00
ManDude 39786482a1 jak3: airlock speed hacks + make cutscenes skip properly (#3543) 2024-06-02 15:03:58 +01:00
ManDude f586cb9af2 fix nav mesh debugging crash (#3542) 2024-06-01 00:50:14 +01:00
ManDude ea1271cfd0 [jak3] implement autocollect and city turbo board cheats, fix actor heap and level flags (#3541) 2024-05-31 16:41:35 +01:00
AloqasandTyler Wilding cefb371681 [jak2] new subtitle speakers (#3536)
for specific cutscene scenarios

---------

Co-authored-by: Tyler Wilding <[email protected]>
2024-05-30 22:02:44 -04:00
Matt Dallmeyer 70ea2a1f67 jak3 - fill out some text-id entries (#3494)
Slam Dozer > Ram Rod
2024-05-30 21:49:10 -04:00
Hat Kid c64eea6337 [buildactor] support generating collide-meshes for custom models (#3540)
This adds support for generating collide meshes when importing custom
models. A couple of things to keep in mind:

- A single `collide-mesh` may only have up to 255 vertices.
- When exporting a GLTF file in Blender, a `collide-mesh` will be
generated for every mesh object that has collision properties applied
(ideally, you would set all visual meshes to `ignore` and your collision
meshes to `invisible` in the OpenGOAL plugin's custom properties).
- Ensure that your actor using the model properly allocates enough
`collide-shape-prim-mesh`es for each `collide-mesh` ([example from the
original game that uses multiple
meshes](https://github.com/open-goal/jak-project/blob/f6688659f2ef85f5ceaacea6271580c9f4d91ed1/goal_src/jak1/levels/finalboss/robotboss.gc#L2628-L2806)).

~One annoying problem that I haven't fully figured out yet (unrelated to
the actual functionality):
`collide-mesh`es are stored in art groups as an `(array collide-mesh)`
in the `art-joint-geo`'s `extra`, so I had to add a new `Res` type to
support this. The way that `array`s are stored in `res-lump`s is a bit
of a hack right now. The lump only stores a pointer to the array, so the
size of that is 4 bytes, but because we have to generate all the actual
array data too, the current `ResLump` code in C++ doesn't handle this
case well and would assert, so I decided to omit the asserts if an
`array` tag is present and "fake" the size so the object file is
generated more closely to how the game expects it until we figure out
something better.~
This was fixed by generating the array data beforehand and creating a
`ResRef` class that takes the pointer to the array data and adds it to
the lump.
2024-05-29 06:09:20 +02:00
Tyler Wilding f1de2c9bc5 g/j2: add some debug menu options to unlock things and give orbs/gems/ammo (#3539)
Adds some debug options that make it easier to quickly complete the
game, get orbs, unlock cheats, etc.


![image](https://github.com/open-goal/jak-project/assets/13153231/8854dc42-084a-457e-ae9b-e9ba2dd7917c)
2024-05-27 22:58:52 -04:00
Tyler Wilding f6688659f2 game: fix the path the--portable flag determines (#3537)
`--portable` was using the path to the executable's file, instead of the
directory that contains the executable
2024-05-26 00:40:33 -04:00
OpenGOAL BotandOpenGOALBot 12ce274226 CI: Periodic Controller Database Update (#3528)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-05-25 10:51:09 -04:00
Matthew Wells bd2db7b15a Add periods to lines in code_status.md for consistency (#3521) 2024-05-25 10:51:01 -04:00
ManDude 645e649a9c jak3: shadow culling hack + finish region debugging tools + fix bigmap crashes (#3532) 2024-05-23 23:43:38 +01:00
ManDude dd765b41cb jak 3 shadows (#3530)
![image](https://github.com/open-goal/jak-project/assets/7569514/e48dbbb8-82d9-4b9d-8ae4-3f48f7c35ced)
2024-05-23 18:29:42 +01:00
ManDude 0db7be55e6 jak3: sprite limit increase + add bsphere toggle for region faces (#3529) 2024-05-22 16:27:00 +01:00
Hat Kid 62ef9fe49d [wip] build actor tool (#3266)
This does a couple of things:

- The `custom_levels` folder was renamed to `custom_assets` and contains
`levels`, `models` and `texture_replacements` folders for Jak 1, 2 and 3
in order to keep everything regarding custom stuff in one place.
- With this, texture replacements now use separate folders for all games
- A build actor tool was added that generates art groups for custom
actors
- Custom levels can now specify what custom models from the `models`
folder they want to import, this will add them to the level's FR3.
- A `test-zone-obs.gc` file was added, containing a `test-actor` process
that uses a custom model as an example.

The build actor tool is still very WIP, the joints and the default
animation are hardcoded, but it allows for importing any GLB file as a
merc model.
2024-05-18 18:18:25 +02:00
water111 271007e552 Start setting up texture animation for jak 3. (#3524)
For now, this just adds sky (clouds and fog), darkjak, and skull gem.

There are some unknown issues with drawing the skull gems still, but I
think it's unrelated to texture animations.

Also fixes https://github.com/open-goal/jak-project/issues/3523
2024-05-18 11:23:48 -04:00
Hat Kid a61f24a168 jak3: custom level support (#3522) 2024-05-16 21:15:54 +02:00
Hat Kid c12a5d777c decomp3: decompile remaining mission code (#3515)
This should make all missions playable with the exception of the end of
`precursor-destroy-ship` because `precurd` asserts on level extraction.

- `trail`
- `trail-graph`
- `wastrail-graph`
- `cty-protect`
- `protect-gunship`
- `protect-path`
- `protect-script`
- `assault-cams`
- `assault-enemies`
- `assault-path`
- `assault-script`
- `assault-shared`
- `assault-task`
- `hover-nav-precura`
- `precura-mood`
- `precura-obs`
- `precura-obs2`
- `precura-part`
- `precurc-mood`
- `precurc-obs`
- `precurc-part`
- `precurd-obs`
- `precurd-part`
- `precurd-scenes`
2024-05-16 16:21:44 +02:00
Tyler Wilding 456d1ba536 goalc: add a performance report feature (#3519)
Adds a quick perf report feature to `goalc` that lets you compare how
much faster / slower it takes to compile the projects, with some simple
features like filtering the files, adjusting for how large of a margin
of error in the speeds you care about, and which test iteration you want
to compare against.

This is something I plan to use as I work more in `goalc` as an easy way
to track / show the results.


![image](https://github.com/open-goal/jak-project/assets/13153231/26f140c7-66d7-4162-994a-a71061e22857)
2024-05-15 22:52:16 -04:00
OpenGOAL BotandOpenGOALBot 4aafab2fc9 CI: Periodic Controller Database Update (#3517)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-05-13 20:37:21 -04:00
ManDude ebbbedabc5 jak3: fix hud sprite crash + add entity debugger (#3516) 2024-05-13 04:09:25 +01:00
Tyler Wilding d1ece445d4 Dependency graph work - Part 1 - Preliminary work (#3505)
Relates to #1353 

This adds no new functionality or overhead to the compiler, yet. This is
the preliminary work that has:
- added code to the compiler in several spots to flag when something is
used without being properly required/imported/whatever (disabled by
default)
- that was used to generate project wide file dependencies (some
circulars were manually fixed)
- then that graph underwent a transitive reduction and the result was
written to all `jak1` source files.

The next step will be making this actually produce and use a dependency
graph. Some of the reasons why I'm working on this:
- eliminates more `game.gp` boilerplate. This includes the `.gd` files
to some extent (`*-ag` files and `tpage` files will still need to be
handled) this is the point of the new `bundles` form. This should make
it even easier to add a new file into the source tree.
- a build order that is actually informed from something real and
compiler warnings that tell you when you are using something that won't
be available at build time.
- narrows the search space for doing LSP actions -- like searching for
references. Since it would be way too much work to store in the compiler
every location where every symbol/function/etc is used, I have to do
ad-hoc searches. By having a dependency graph i can significantly reduce
that search space.
- opens the doors for common shared code with a legitimate pattern.
Right now jak 2 shares code from the jak 1 folder. This is basically a
hack -- but by having an explicit require syntax, it would be possible
to reference arbitrary file paths, such as a `common` folder.

Some stats:
- Jak 1 has about 2500 edges between files, including transitives
- With transitives reduced at the source code level, each file seems to
have a modest amount of explicit requirements.

Known issues:
- Tracking the location for where `defmacro`s and virtual state
definitions were defined (and therefore the file) is still problematic.
Because those forms are in a macro environment, the reader does not
track them. I'm wondering if a workaround could be to search the
reader's text_db by not just the `goos::Object` but by the text
position. But for the purposes of finishing this work, I just statically
analyzed and searched the code with throwaway python code.
2024-05-12 12:37:59 -04:00
water111 e0b1d8c21e Jak3 sky (#3514) 2024-05-12 09:36:50 -04:00
Hat Kid 6b3844bf99 decomp3: more misc files (#3513)
4 missions to go!

- `ctygenb-part`
- `power-game`
- `vinroom-part`
- `vinroom-scenes`
- `gungame-part`
- `gungame-scenes`
- `hiphog-obs`
- `hiphog-part`
- `hiphog-scenes`
- `hover-nav-lpattack`
- `king-rider`
- `rubble-attack`
- `rubble-obs`
- `rubble-part`
- `rubblea-init`
- `rublcst-scenes`
- `mood-funcs2`
- `gun-dummy-art`
- `gun-dummy-part`
- `gun-dummy`
- `gungame-data`
- `gungame-manager`
- `gungame-obs`
- `blow-tower-data`
- `blow-tower-extra`
- `blow-tower-obs2`
- `blow-tower-obs`
- `blow-tower-part`
- `blow-tower-script`
- `blow-tower-shared`
- `blow-tower-speech`
- `cty-blow-tower`
2024-05-11 17:57:26 -04:00
BreakPoints 24490c042e Intro palace DGOs (#3512)
Now needed to extract and compile from scratch
2024-05-11 10:21:45 -04:00
Hat Kid 4dd2bab06e jak3: fix local space particle info crash (#3511) 2024-05-10 16:14:50 +02:00
water111 5b04be2fa0 Add hfrag, clean up some background renderer stuff (#3509)
This adds hfrag, but with a few remaining issues:
- The textures aren't animated. Instead, it just uses one texture.
- The texture filtering isn't as good as at it could be.

I also cleaned up a few issues with the background renderers:
- Cleaned up some stuff that is common to hfrag, tie, tfrag, shrub
- Moved time-of-day color packing stuff to FR3 creation, rather than at
level load. This appears to reduce the frame time spikes when a level is
first drawn by about 5 or 6 ms in big levels.
- Cleaned up the x86 specific stuff used in time of day. Now there's
only one place where we have an `ifdef`, rather than spreading it all
over the rendering code.
2024-05-09 20:11:43 -04:00
Hat Kid 949508d0ed decomp3: traffic/citizen/faction code, desert-rescue (#3506)
- `cty-faction-h`
- `nav-graph`
- `citizen-h`
- `citizen`
- `civilian`
- `traffic-engine`
- `traffic-manager`
- `cty-attack-controller`
- `cty-faction`
- `formation-object`
- `formations`
- `squad-control-city-h`
- `squad-control-city`
- `traffic-util`
- `wlander-female`
- `wlander-h`
- `wlander-male`
- `speech-manager`
- `desert-rescue`
- `desresc-path`
- `neo-satellite`
- `rope-prim-system-h`
- `rope-prim-system`
- `rope-system`
- `wland-passenger`
- `cty-guard-projectile`
- `ctywide-init`
- `ff-squad-control`
- `guard-grenade`
- `guard-rifle`
- `guard-states`
- `guard-tazer`
- `ctywide-speech`
- `citizen-chick`
- `citizen-fat`
- `citizen-norm`
- `guard`
- `bike`
- `car`
- `test-bike`
- `vehicle-rider`
- `desert-rescue-bbush`
- `ff-squad-control-h`
- `flee-info`
- `guard-h`
- `mission-squad-control`
- `kg-squad-control`
- `kg-squad-member-h`
- `kg-squad-member`
- `mh-squad-control`
- `mh-squad-member-h`
- `mh-squad-member`
- `ctywide-obs-h`
- `ctywide-obs`
- `ctywide-part`
- `ctywide-scenes`
- `ctywide-tasks`
- `ctywide-texture`
- `billiards`
- `guide-arrow`
- `kg-vehicles`
- `flying-turret`
- `roboguard-city`
- `citizen-enemy`
- `metalhead-flitter`
- `metalhead-grunt`
- `metalhead-predator`
- `spydroid`
- `kg-squad-control-h`
- `mh-squad-control-h`
- `krimson-wall`
- `ctyport-obs`
- `ctyinda-obs`
- `ctyinda-part`
- `ctyindb-obs`
- `ctyindb-part`
- `ctyport-attack`
- `h-torpedo`
- `ctyport-part`
- `ctyport-scenes`
- `external-player-control`
- `desert-chase-path-h`
- `desert-chase-path`
- `desert-chase`
- `desert-jump`
- `wcar-catapult`
- `bombbot-h`
- `bombbot`
- `bombbot-path`
- `cty-hijack-missile`
- `cty-hijack`
- `ctyport-attack-bbush`
- `ctysluma-part`
- `ctyslumb-part`
- `ctyslumc-obs`
- `ctyslumc-part`
- `searchlight`
- `cty-destroy-grid`
- `ctyfarm-obs`
- `ctyfarma-part`
- `ctyfarmb-part`
- `freehq-part`
- `freehq-scenes`
- `onintent-scenes`
- `onintent-part`
- `cty-sniper-battery`
- `cty-sniper-turret`
- `intro-obs`
- `intro-part`
- `intro-scenes`
- `palcab-part`
- `palroof-part`
2024-05-09 19:18:55 -04:00
OpenGOAL BotandOpenGOALBot f479cef939 CI: Periodic Controller Database Update (#3507)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-05-06 14:22:45 -04:00
water111andManDude 807ca7465f fix c++ compiler warnings, extract_merc assert (#3488)
Co-authored-by: ManDude <[email protected]>
2024-05-03 17:29:18 +01:00
ManDude cf79ca04e9 fix another jak 1 level name (#3503) 2024-05-03 08:34:36 +01:00
Tyler Wilding 6569636abf ci: pin to avx for macos (#3502)
Related to #3439

Will see after a few weeks if the problem resurfaces. All macos related
caches have been purged to eliminate that as a possibility.
2024-05-01 22:00:56 -04:00
Hat Kid f9e0aa82bc jak3: fix mirage shot (#3501) 2024-05-01 21:57:13 +02:00
dependabot[bot]andTyler Wilding 39f3549640 build(deps): bump hendrikmuhs/ccache-action from 1.2.12 to 1.2.13 (#3497)
Bumps
[hendrikmuhs/ccache-action](https://github.com/hendrikmuhs/ccache-action)
from 1.2.12 to 1.2.13.
<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.13</h2>
<h2>What's Changed</h2>
<ul>
<li>add emscripten to the compiler list by <a
href="https://github.com/mmomtchev"><code>@​mmomtchev</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/187">hendrikmuhs/ccache-action#187</a></li>
<li>Bump <code>@​actions/cache</code> from 3.2.3 to 3.2.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/183">hendrikmuhs/ccache-action#183</a></li>
<li>Bump typescript from 5.3.3 to 5.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/190">hendrikmuhs/ccache-action#190</a></li>
<li>Bump typescript from 5.4.2 to 5.4.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/191">hendrikmuhs/ccache-action#191</a></li>
<li>fix: early exit process so node doesn't wait for hanging promises by
<a
href="https://github.com/chirag-droid"><code>@​chirag-droid</code></a>
in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/182">hendrikmuhs/ccache-action#182</a></li>
<li>Bump typescript from 5.4.3 to 5.4.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/193">hendrikmuhs/ccache-action#193</a></li>
<li>Update windows by <a
href="https://github.com/virtuald"><code>@​virtuald</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/180">hendrikmuhs/ccache-action#180</a></li>
<li>Bump <code>@​types/node</code> from 20.11.10 to 20.12.7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/194">hendrikmuhs/ccache-action#194</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/mmomtchev"><code>@​mmomtchev</code></a>
made their first contribution in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/187">hendrikmuhs/ccache-action#187</a></li>
<li><a
href="https://github.com/chirag-droid"><code>@​chirag-droid</code></a>
made their first contribution in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/182">hendrikmuhs/ccache-action#182</a></li>
<li><a href="https://github.com/virtuald"><code>@​virtuald</code></a>
made their first contribution in <a
href="https://redirect.github.com/hendrikmuhs/ccache-action/pull/180">hendrikmuhs/ccache-action#180</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/hendrikmuhs/ccache-action/compare/v1.2.12...v1.2.13">https://github.com/hendrikmuhs/ccache-action/compare/v1.2.12...v1.2.13</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/c92f40bee50034e84c763e33b317c77adaa81c92"><code>c92f40b</code></a>
Bump <code>@​types/node</code> from 20.11.10 to 20.12.7 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/194">#194</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/ff9f6cc67d49b9acaa9e102f80d1ea8a0c86a6dd"><code>ff9f6cc</code></a>
update checksum</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/985163732c9a0ab6be742a4db87bb36d07d6ca9f"><code>9851637</code></a>
update code</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/40738ee8f3bcf20e438d29f613fb2ef1b5cff79d"><code>40738ee</code></a>
Update windows (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/180">#180</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/ba6e323cc10f37a14582696e025efe365df0b125"><code>ba6e323</code></a>
Bump typescript from 5.4.3 to 5.4.5 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/193">#193</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/550708f4f24caa1472defc821c356d0e72d45643"><code>550708f</code></a>
fix: early exit process so node doesn't wait for hanging promises (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/182">#182</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/259dcb3149e7662420f6b796600eac9008bb2d4e"><code>259dcb3</code></a>
Bump typescript from 5.4.2 to 5.4.3 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/191">#191</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/a16392ef06bb17357c33855e071f12873d87b163"><code>a16392e</code></a>
update code</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/3818c2034d1b62be7cc5e8e097c7c3996d94a068"><code>3818c20</code></a>
Bump typescript from 5.3.3 to 5.4.2 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/190">#190</a>)</li>
<li><a
href="https://github.com/hendrikmuhs/ccache-action/commit/b647aa998265c7332fbcd30509be75d7ed682458"><code>b647aa9</code></a>
Bump <code>@​actions/cache</code> from 3.2.3 to 3.2.4 (<a
href="https://redirect.github.com/hendrikmuhs/ccache-action/issues/183">#183</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/hendrikmuhs/ccache-action/compare/v1.2.12...v1.2.13">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.12&new-version=1.2.13)](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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
Co-authored-by: Tyler Wilding <[email protected]>
2024-05-01 15:53:40 -04:00
Hat Kid 3ff3760621 jak3: add discord rpc and fix some decomp (#3500) 2024-05-01 13:49:26 +02:00
ManDude 5705359df9 [jak3] fix some flag names and a wcar crash (#3498) 2024-05-01 08:44:26 +01:00
Hat Kid cbf75a96f7 custom levels: don't uppercase FR3 filename (#3496) 2024-04-30 22:51:36 +02:00
ManDude 8344ac6963 use only the real level name in the Loader (#3495)
This fixes issues with certain Jak 3 levels not rendering because there
is a mismatch between the DGO name, nickname and real level name (bsp
name).

FR3s use a different filename, so you can delete the ones you have after
this is merged.

This affects custom levels, but I don't have that toolchain set up so
someone else will have to test that.
2024-04-30 17:12:57 +01:00
OpenGOAL BotandOpenGOALBot a527afdc5a CI: Periodic Controller Database Update (#3491)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-04-29 19:21:43 -04:00
Matt Dallmeyer 0d4e3928eb decomp3 title-obs, credits-h (#3476) 2024-04-29 20:23:31 +02:00
ManDude e4c57d6ac9 more debug information when RPC buffers exhaust (#3490) 2024-04-29 16:37:04 +01:00
Tyler Wilding a021c392ec game: allow overriding the config directory location (#3477)
This is primarily driven for proper mod-support. Mods would like to
isolate their settings and saves (potentially) and that is currently
done by find-and-replacing code before building. Bad!

Additionally, this has the side-effect of allowing for portable
installations of the game so, win-win.

Testing in progress, i'll merge once it is ready.
2024-04-28 15:29:20 -04:00
Tyler Wilding fee0a435fc extractor: support extracting using a folder path (#3422)
Patching up the extractor while working on the launcher, fixes:
- makes it so you can compile successfully given a folder path
(currently assumes your project path contains `iso_data`)
- ignore `buildinfo.json` from validation code.
- fixes an edge-case that could recursively fill up your entire
hard-drive!
- allows overriding the decompilation configuration via flag
- adds a way to specify where the ISO should be extracted to
2024-04-28 15:02:29 -04:00
Hat Kid e2e5289788 decomp3: font widescreen and shadow hacks, generic renderer, misc files (#3483)
- `pecker-ingame`
- `des-bbush-tasks`
- `des-burning-bush`
- `des-bush-part`
- `des-bush`
- `mh-centipede`
- `mh-centipede-part`
- `mh-wasp`
- `mh-wasp-part`
- `needle-fish`
- `des-bush-time-chase`
- `timer-path`
- `mission-squad-control-h`
- `mh-bat`
- `hover-nav-factoryd`
- `hover-nav-factoryc`
- `conveyor`
- `fac-part`
- `factory-part`
- `factoryc-mood`
- `factoryc-obs`
- `factoryc-obs2`
- `lfaccar-init`
- `factory-boss-part`
- `factory-boss-scenes`
- `factory-boss-setup`
- `factory-boss-states`
- `factory-mood`
- `factoryc-manager`
- `lfacrm1-mood`
- `lfacrm2-mood`
- `missile-bot`
- `sew-laser-turret`
- `ai-task-h`
- `ash-h`
- `ash-shot`
- `ash-states`
- `ash-task`
- `ash`
- `bot-h`
- `bot-states`
- `bot`
- `ash-oasis-course`
- `oasis-defense`
- `comb-field`
- `comb-mood`
- `comb-obs`
- `comb-part`
- `comb-scenes`
- `comb-sentry`
- `comb-travel`
- `comba-init`
- `combx-scenes`
- `h-sled`
- `destroy-dark-eco`
- `fac-gunturret`
- `fac-robotank-turret`
- `fac-robotank`
- `fac-tower`
- `factory-h`
- `factory-hud`
- `factory-manager`
- `factorya-init`
- `ffight-projectile`
- `ftank-projectile`
- `fturret-projectile`
- `h-warf`
- `warf-projectile`
2024-04-28 08:59:46 -04:00
ManDude 1a058b418a jak3: hack level heap sizes (#3487) 2024-04-27 21:48:49 +01:00
Matt Dallmeyer 86d770aeeb Fix "logical not is only applied to the left hand side of comparison" warnings (#3484) 2024-04-26 16:27:11 +01:00
ManDude 889fdcd79c jak3: fix some collide decomp + fix projectiles aiming at intangible objects (#3485)
Say goodbye to half of the laser needle shots spinning around doing
nothing. This is toggleable with `fix-projectile-focus` in the pc
settings.
2024-04-26 16:22:26 +01:00
ManDude 667553850d jak2/3: re-implement screenshot system through goal (#3482) 2024-04-25 01:46:18 +01:00
ManDude d9d4cc5405 fix minimap icon misalign (#3481) 2024-04-23 18:20:31 +01:00
ManDude 728cb4b6c9 jak3 pc: math-camera, letterbox, led and auto-save (#3479) 2024-04-22 22:57:09 +01:00
Hat Kid 9d359ed84a jak3: fix type (#3478) 2024-04-22 19:53:04 +02:00
Hat Kid 58a5440c8a decomp3: more misc files (#3466)
Makes a bunch of missions mostly playable, including:
- `arena-training-1`
- `arena-fight-1`
- `wascity-chase`
- `arena-fight-2`
- `arena-fight-3`
- `volcano-darkeco`
- `desert-hover`
- `nest-eggs`
- `temple-climb`
- `temple-oracle`
- `temple-tests`
- `desert-beast-battle`
- `desert-turtle-training`
- `desert-course-race`
- `desert-artifact-race1`
- `wascity-leaper-race`
- `wascity-pre-game`
- `sewer-met-hum`
- `forest-kill-plants`
- `forest-ring-chase`
- `temple-defend`
- `tower-destroy`
- `desert-glide`

---
Files:

- `ripple`
- `waswide-mood`
- `sig-rider`
- `nst-tasks`
- `nst-part`
- `nst-gas`
- `nst-eggs-h`
- `nst-obs`
- `nst-mood`
- `egg-spider`
- `wasdoors-init`
- `wasall-tasks`
- `wvehicle-race`
- `wcar-marauder`
- `wcar-marauder-b`
- `turret-control`
- `was-squad-control`
- `turtle-training`
- `kleever-rider`
- `course-race`
- `artifact-race`
- `desert-hover`
- `desbeast-path-h`
- `des-beast`
- `desertg-obs`
- `desertf-obs`
- `desertd-obs`
- `desert-dust-storm`
- `des-cactus`
- `race-hud`
- `race-info`
- `race-manager`
- `tizard`
- `flyingsaw`
- `hover-training`
- `temple-mood`
- `temple-obs`
- `temple-obs2`
- `temple-part`
- `temple-scenes`
- `templex-mood`
- `templex-obs`
- `templex-part`
- `tomb-baby-spider`
- `target-turret-shot`
- `target-turret`
- `beast-battle-path`
- `des-beast-2`
- `mh-flyer`
- `scorpion-gun`
- `hover-enemy-h`
- `hover-enemy`
- `hover-formation-h`
- `hover-formation`
- `hover-nav-control-h`
- `hover-nav-control`
- `flamer-hover`
- `hover-nav-templea`
- `robo-hover`
- `hover-nav-sewb`
- `hover-nav-sewg`
- `hover-nav-sewj`
- `hover-nav-sewl`
- `hover-nav-sewo`
- `hover-nav-towera`
- `tower-mood`
- `tower-obs`
- `tower-scenes`
- `tower-part`
- `eco-green-collider`
- `forest-bridges`
- `forest-kill-plants`
- `forest-mood`
- `forest-ring-chase`
- `forest-tasks`
- `forest-part`
- `foresta-obs`
- `hover-nav-foresta`
- `mh-plant`
- `dp-bipedal-part`
- `dp-bipedal-shot`
- `dp-bipedal`
- `neo-spawner`
- `for-turret`
- `for-turret-shot`
- `neo-wasp`
- `neo-wasp-part`
- `volcanox-scenes`
- `volcanox-mood`
- `volcano-scenes`
- `volcano-mood`
- `volcano-obs`
- `volcano-obs2`
- `chain-physics`
- `rigid-body-plat`
- `volcano-part`
- `flamer-lava`
- `flitter`
- `spiky-frog`
- `flut-wild`
- `target-indax`
- `target-indax-hang`
- `mantis`
- `volcanox-obs`
- `spyder`
- `wcar-faccar`
- `mhcity-obs2`
- `mhcity-part`
- `mhcity-obs`
- `dm-mine-spider`
- `rapid-gunner`
- `stadium-mood`
- `stadium-scenes`
- `stadiuma-mood`
- `stadiuma-part`
- `kanga-lizard`
- `marauder`
- `arena-scenes`
- `wasstada-mood`
- `wasstada-obs`
- `wasstada-part`
- `wasstadb-obs`
- `wasstadc-obs`
- `dm-flyer`
- `maker-part`
- `maker-projectile`
- `skeet-part`
- `wascity-turret`
- `wasgun-h`
- `wasgun-hud`
- `wasgun-manager`
- `nav-graph-h`
- `traffic-engine-h`
- `waswide-init`
- `cty-borrow-manager-h`
- `cty-borrow-manager`
- `desert-part`
- `height-map-h`
- `height-map`
- `traffic-height-map`
- `vehicle-control`
- `hvehicle-h`
- `hvehicle`
- `hvehicle-effects`
- `hvehicle-physics`
- `hvehicle-util`
- `glider-h`
- `glider-hud`
- `glider-manager`
- `glider-ring`
- `glider-ring-part`
- `h-glider`
- `hanga-init`
- `was-pre-game`
- `was-leaper-race`
- `flut-racer`
- `desert-scenes`
- `desert-lizard-h`
- `desert-lizard-task`
- `desert-lizard`
- `throne-scenes`
- `waspal-mood`
- `waspala-obs`
- `waspala-part`
- `deswalk-obs`
- `deswalk-part`
- `terraformer-drone`
- `terraformer-head`
- `terraformer-part`
- `terraformer-setup`
2024-04-22 18:43:51 +02:00
OpenGOAL BotandOpenGOALBot 6da5225afc CI: Periodic Controller Database Update (#3471)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-04-19 23:12:31 -04:00
ManDude bcab625864 debugger: reverse the order the backtrace is printed (#3474) 2024-04-16 05:22:31 +01:00
ManDude 8e5830321c [jak3] fix process stack overflow + collision renderer (#3473) 2024-04-16 04:26:01 +01:00
ManDude e601a3dcb3 [jak3] implement pckernel (#3472)
Most debug features do not work, but that's fine.
2024-04-15 19:26:48 +01:00
ManDude 20b76e318d [jak3] remove some stubs and fix health bar (#3468) 2024-04-15 16:24:29 +01:00
Matt Dallmeyer ccd2c9eaf1 Fix bad speedrun Select pause behavior (#3464)
fixes this crap - happens if you use the Select variation of the
speedrun menu combo (hold L1+R1+X) during movies


https://github.com/open-goal/jak-project/assets/2515356/52ffe700-0662-42d5-aa7d-1d9d71bb94fb

With the changes in this PR, it now behaves as you'd expect - the same
as a normal Select pause

For reference, original changes adding the combo on Select -
https://github.com/open-goal/jak-project/pull/2196/files
2024-04-14 15:51:30 -04:00
OpenGOAL BotandOpenGOALBot d596afcf13 CI: Periodic Controller Database Update (#3462)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-04-14 15:08:47 -04:00
water111 dd4f255260 [jak3] Minimap texture fix (#3465) 2024-04-13 09:47:23 -04:00
Hat Kid 36f1592b90 decomp3: lightning renderer, nav code, texture remap, fix progress menu crash (#3461)
Also adds:

- BLERC
- Minimap (with missing texture for the map, sprites work)
- Eco Mine files
- Precursor robot boss files
- Sewer files
- Vehicle files
2024-04-12 18:44:38 -04:00
water111 5299bc441f [jak3] Fix defskelgroup (#3460)
Fixes https://github.com/open-goal/jak-project/issues/3459
2024-04-07 13:07:30 -04:00
water111 1394c5c00d fix typo (#3458) 2024-04-07 11:31:05 -04:00
water111 0124a0b9a1 [jak3] Support jaextern.str, stub for blue fog fix (#3455) 2024-04-07 11:09:56 -04:00
Hat Kid ae0f139667 decomp3: eye renderer and more files (#3457)
- `eye`
- `collision-editor`
- `simple-nav-sphere`
- `mech-part`
- `mech-states`
- `mech`
- `target-mech`
- `target-tube`
- `flut-part`
- `flut`
- `target-flut`
2024-04-07 10:49:45 -04:00
water111 cc8801a27b [goalc] speed up jak3 compilation (#3454)
I noticed that jak 3's compilation was spending a lot of time accessing
the `unordered_map`s we use to store constants and symbol types.

 
I repurposed the `EnvironmentMap` originally made for GOOS for this. It
turns out that we were copying the entire constant map whenever we
encountered a `deftype`, and fixed that too.

This speeds up jak3 compiles from ~16 to 11 seconds for me.
2024-04-06 16:01:17 -04:00
water111 376194a3e7 Jak 3, fixes for animation issues, rm debug print (#3453) 2024-04-06 15:09:02 -04:00
Hat Kid 23aeda1664 decomp3: add background data to pc renderers, get mood and time of day stuff running (#3450) 2024-04-06 14:27:36 -04:00
ZedB0T c5357f7ccd Add fall back condition (#3452) 2024-04-06 12:39:02 -04:00
Hat Kidandwater 93afb02cf4 decomp3: spawn target, add merc and particle buckets and some temporary hacks (#3445)
This includes all the collision stuff needed to spawn `target`,
decompiles the sparticle code and adds some of the PC hacks needed for
merc to run (it doesn't work quite right and looks bad, likely due to a
combination of code copied from Jak 2 and the time of day hacks).

There are a bunch of temporary hacks (see commits) in place to prevent
the game from crashing quite as much, but it is still extremely prone to
doing so due to lots of missing functions/potentially bad decomp.

---------

Co-authored-by: water <[email protected]>
2024-04-05 00:07:39 -04:00
Tyler Wilding a7efd59919 goalc: add some nullptr checks around symbol map lookups (#3447) 2024-04-03 19:45:44 -04:00
dependabot[bot] 6ea8dfb032 build(deps): bump mathieudutour/github-tag-action from 6.1 to 6.2 (#3442)
Bumps
[mathieudutour/github-tag-action](https://github.com/mathieudutour/github-tag-action)
from 6.1 to 6.2.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/a22cf08638b34d5badda920f9daf6e72c477b07b"><code>a22cf08</code></a>
check in prod dependencies</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/f36074fe49d589315ac97253c23ce83ccbd6fbb9"><code>f36074f</code></a>
version 6.2</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/f40d7eefd8aa8e0422116f3fb945bbd96dfb7691"><code>f40d7ee</code></a>
match latest tag regex (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/171">#171</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/1bf7977a3da165de50510f793132286574222465"><code>1bf7977</code></a>
fix: add previous_version to action.yml (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/183">#183</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/5a16d1443262c7f1a1addb0de22dea8a784acdbe"><code>5a16d14</code></a>
Bump tough-cookie from 4.0.0 to 4.1.3 (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/184">#184</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/71c368965901c31849458bb74c4ffa22b48172c7"><code>71c3689</code></a>
Update README.md (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/205">#205</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/a079ba461db5f184f53dcd8d6031a82478b788f5"><code>a079ba4</code></a>
Update Node version to 20 (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/202">#202</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/86301c823dac64d427711dd6b99d7ffdd894d2dd"><code>86301c8</code></a>
Revert &quot;Use <code>${{github.token}}</code> as default&quot; (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/167">#167</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/5bd9038fd1cc379dfe97904dda3a4b5b3af5d606"><code>5bd9038</code></a>
Bump minimatch from 3.0.4 to 3.1.2 (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/162">#162</a>)</li>
<li><a
href="https://github.com/mathieudutour/github-tag-action/commit/ac8cb388384294d1215aed7911d7b7e57b3d0f0a"><code>ac8cb38</code></a>
getValidTags() should exclude tags that do not match the prefixRegex (<a
href="https://redirect.github.com/mathieudutour/github-tag-action/issues/158">#158</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/mathieudutour/github-tag-action/compare/v6.1...v6.2">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.1&new-version=6.2)](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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
2024-04-03 17:25:16 -04:00
Hat Kid 1f1498f2ad decompiler: allow overriding dgo inputs (#3446) 2024-04-03 18:55:51 +02:00
OpenGOAL BotandOpenGOALBot 55f18dd3d1 CI: Periodic Controller Database Update (#3444)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-04-02 01:03:15 -04:00
Tyler Wilding 0a15ac1669 goalc: Fix new symbol trie's performance inefficiencies (#3443)
I believe this brings things back in line to where it was before:
Here are the first handful of files before the changes:
```
0.014 | gcommon.gc
0.006 | gkernel-h.gc
0.025 | gkernel.gc
0.002 | pskernel.gc
0.01 | gstring.gc
0.004 | gstate.gc
0.001 | kernel.gd
0.001 | types-h.gc
0.002 | vu1-macros.gc
0.003 | math.gc
0.01 | vector-h.gc
0.001 | gravity-h.gc
0.001 | bounding-box-h.gc
0.001 | matrix-h.gc
0.001 | quaternion-h.gc
0.001 | euler-h.gc
```
> first compile
```
0.161 | gcommon.gc
0.126 | gkernel-h.gc
0.174 | gkernel.gc
0.046 | pskernel.gc
0.08 | gstring.gc
0.048 | gstate.gc
0.001 | kernel.gd
0.052 | types-h.gc
0.009 | vu1-macros.gc
0.059 | math.gc
0.228 | vector-h.gc
0.026 | gravity-h.gc
0.006 | bounding-box-h.gc
0.002 | matrix-h.gc
0.028 | quaternion-h.gc
0.026 | euler-h.gc
```
> make a change in gcommon and recompile

With the changes:
```
0.015 | gcommon.gc
0.018 | gkernel-h.gc
0.039 | gkernel.gc
0.006 | pskernel.gc
0.015 | gstring.gc
0.009 | gstate.gc
0.005 | kernel.gd
0.006 | types-h.gc
0.006 | vu1-macros.gc
0.008 | math.gc
0.017 | vector-h.gc
0.004 | gravity-h.gc
0.004 | bounding-box-h.gc
0.005 | matrix-h.gc
0.005 | quaternion-h.gc
0.003 | euler-h.gc
```
> First compile, no difference expected

```
0.016 | gcommon.gc
0.008 | gkernel-h.gc
0.023 | gkernel.gc
0.002 | pskernel.gc
0.01 | gstring.gc
0.043 | gstate.gc
0.001 | kernel.gd
0.002 | types-h.gc
0.002 | vu1-macros.gc
0.003 | math.gc
0.013 | vector-h.gc
0.001 | gravity-h.gc
0.002 | bounding-box-h.gc
0.002 | matrix-h.gc
0.001 | quaternion-h.gc
0.001 | euler-h.gc
```
> Compile times seem to be back within margin of error -- some are
faster than the first compilation time.
2024-04-01 18:56:55 -04:00
Hat Kid c96e44ab30 decomp3: support for virtual states inheriting from their own type's virtual states, gun-yellow-shot, gun-red-shot, gun-dark-shot (#3438) 2024-03-31 11:14:14 -04:00
Tyler Wilding afea4f7694 g/j1: remove the redundant graphics menu (#3421)
This was hiding options for people that only had 60hz monitors since the
two menus drifted -- it is not necessary for an entire separate menu,
just disable the option if applicable.

Don't merge this without testing it throughly
2024-03-30 20:00:53 -04:00
Tyler WildingandHat Kid 53277a65ad LSP: A bunch of new OpenGOAL language features (#3437)
- Integrate the AST into the LSP, this makes parsing and tokenizing the
files much easier
- Consolidate most of the symbol info tracking in `goalc` to a single
map. Fixed some issues where the old map would never evict symbols when
re-compiling files. There is still some more to cleanup, but this now
can be used as an incrementally updated source-of-truth for the LSP
- re-compile files when they are saved. Ideally this would be done
everytime they are changed but that:
  - may be too aggressive
- goalc doesn't compile incrementally yet so it likely would be a worse
UX

Features added, see
https://github.com/open-goal/opengoal-vscode/issues/256
- Hover

![image](https://github.com/open-goal/jak-project/assets/13153231/58dadb5d-582c-4c1f-9ffe-eaa4c85a0255)

![image](https://github.com/open-goal/jak-project/assets/13153231/b383adde-57fc-462c-a256-b2de5c30ca9a)
- LSP Status fixed
- Type Hierarchy

![image](https://github.com/open-goal/jak-project/assets/13153231/8e681377-1d4e-4336-ad70-1695a4607340)
- Document Color

![image](https://github.com/open-goal/jak-project/assets/13153231/4e48ccd8-0ed1-4459-a133-5277561e4201)
- Document Symbols
![Screenshot 2024-03-27
004105](https://github.com/open-goal/jak-project/assets/13153231/8e655034-43c4-4261-b6e0-85de00cbfc7f)
- Completions
![Screenshot 2024-03-30
004504](https://github.com/open-goal/jak-project/assets/13153231/d123a187-af90-466b-9eb7-561b2ee97cd1)

---------

Co-authored-by: Hat Kid <[email protected]>
2024-03-30 19:49:07 -04:00
Hat Kid dacb704ef6 decomp3: more engine stuff, fix ja macro detection for jak 2/3, unmerged let matcher, part-tracker-spawn macro (#3436)
- `aligner`
- `effect-control`
- `pov-camera`
- `powerups`
- `los-control-h`
- `airlock`
- `water-anim`
- `blocking-plane`
- `proc-focusable-spawner`
- `idle-control`
- `enemy-h`
- `nav-enemy-h`
- `enemy`
- `enemy-states`
- `particle-curves`
- `base-plat`
- `plat`
- `bouncer`
- `elevator`
- `rigid-body`
- `rigid-body-queue`
- `process-taskable`
- `scene-actor`
- `warp-gate`
- `guard-projectile`
- `metalhead-projectile`
- `los-control`
- `joint-exploder`
- `ragdoll-test`
- `debris`
- `shield-sphere`
- `text`
- `target-launch`
2024-03-30 10:28:02 -04:00
water111 ee015e3b22 [jak3] A bunch of small fixes to get game.cgo to load (#3435)
The `test-play` macro is back, though it doesn't call `play` yet. We can
at least load all of `game.cgo`, which involves loading a lot of the
code we've decompiled, loading/linking objects files compiled by
OpenGOAL (like dir-tpages), and loading/linking Jak's art-groups (for
jak 3 they are stored v5 format that I added to the linker).

There were no major issues - just a few forgotten mips2c entries and
minor bugs/functions that needed stubs. Most of the work was updating
the linker. Hopefully I'll never have to touch that code again - I think
it supports everything we need for jak 3!
2024-03-24 16:30:28 -04:00
water111 9b4b54978a decomp drawable, main (#3434) 2024-03-24 12:27:04 -04:00
water111 ffe01a352d Decompile level (#3433) 2024-03-23 13:03:01 -04:00
Hat Kid 99866cec88 decomp3: more engine files, get-texture macro, use print method in autogenerated inspect, fix bitfield float print (#3432)
- `fma-sphere`
- `prim-beam-h`
- `cam-start`
- `ragdoll`
- `light-trails-h`
- `light-trails`
- `menu`
- `water`
- `water-flow`
- `hud`
- `hud-classes`
- `progress`
- `progress-draw`

---

The `get-texture` macro replaces calls to `lookup-texture-by-id` and
`lookup-texture-by-id-fast`. The `defpart` macro detection was modified
to print a pair like `(texture-name tpage-name)` for the texture field
that gets turned into a `texture-id` constant. Only used in Jak 3 at the
moment, I'll probably go through the other games at a later point.
2024-03-23 09:25:11 -04:00
OpenGOAL BotandOpenGOALBot 9a9f203d8b CI: Periodic Controller Database Update (#3430)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-03-23 09:10:55 -04:00
water111 ea4820356c Decompile tfrag, tie, prim (#3429)
These still need to be ported to PC.
2024-03-17 13:32:05 -04:00
water111 f7bfc8cab1 Decompile font, decomp, background, shrubbery (#3428) 2024-03-16 20:25:30 -04:00
water111 13def9a8b2 Decompile foreground and bones (#3427)
Small fix to decompiler when the original compiler uses `ra` register.
This seems to happen in "normal" code very rarely - perhaps they
manually specified this in an `rlet`.

Start figuring out buckets/textures for Jak 3.

The foreground code is not yet modified for PC - I want to wait until
the game is running, since it is too hard to do it now.
2024-03-16 14:50:41 -04:00
Brent Hickey df2f3da321 [goal] Add labels, break, and continue to loops (#3426)
Uses (block) and (return-from) to support (break) and (continue) with
labeling

Supports `(while) (until) (dotimes) (countdown) (loop) (doarray)`

Test cases:
``` lisp
(dotimes (i 5)
    (when (= i 2)
        (break)
    )
    (format #t "i: ~D~%" i)
)
;; Output:
;; i: 0
;; i: 1

(dotimes (i 5)
    (when (= i 2)
        (continue)
    )
    (format #t "i: ~D~%" i)
)
;; Output:
;; i: 0
;; i: 1
;; i: 3
;; i: 4

(dotimes (i 3)
    (when (= i 2)
        (continue)
    )
    (format #t "outer: ~D~%" i)
    (dotimes (i 3)
        (when (= i 0)
            (continue)
        )
        (format #t "inner: ~D~%" i)
    )
)
;; Output:
;; outer: 0
;; inner: 1
;; inner: 2
;; outer: 1
;; inner: 1
;; inner: 2

(dotimes (i 5) :label outer
    (when (= i 2)
        (continue :from outer)
    )
    (format #t "outer: ~D~%" i)
    (dotimes (i 3)
        (when (= i 1)
            (continue :from outer)
        )
        (format #t "inner: ~D~%" i)
    )
)
;; Output:
;; outer: 0
;; inner: 0
;; outer: 1
;; inner: 0
;; outer: 3
;; inner: 0
;; outer: 4
;; inner: 0

(dotimes (i 5) :label outer
    (when (= i 2)
        (continue :from outer)
    )
    (format #t "outer: ~D~%" i)
    (dotimes (i 3)
        (when (= i 0)
            (break :from outer)
        )
        (format #t "inner: ~D~%" i)
    )
)
;; Output:
;; outer: 0

(dotimes (i 5) :label outer
    (when (= i 2)
        (continue :from outer)
    )
    (format #t "outer2: ~D~%" i)
    (dotimes (i 3)
        (when (= i 1)
            (break)
        )
        (format #t "inner2: ~D~%" i)
    )
)
;; Output:
;; outer2: 0
;; inner2: 0
;; outer2: 1
;; inner2: 0
;; outer2: 3
;; inner2: 0
;; outer2: 4
;; inner2: 0

(countdown (i 5)
    (when (= i 2)
        (continue)
    )
    (format #t "i: ~D~%" i)
)
;; Output: 
;; i: 4
;; i: 3
;; i: 1
;; i: 0

(let ((i 0))
    (while (< i 5)
        (when (= i 1)
            (break)
        )
        (format #t "i: ~D~%" i)
        (1+! i)
    )
)
;; Output: 
;; i: 0

(let ((i 0))
    (until (> i 5) :label outer
        (loop
            (break :from outer)
        )
        (format #t "i: ~D~%" i)
        (1+! i)
    )
)
;; Output:
;; nothing

(define *array* (new 'global 'boxed-array uint32 3))
(doarray (i *array*)
   (break)
   (format #t "doarray")
)
;; Output:
;; nothing

(doarray (i *array*) :label arrayloop
    (dotimes (i 5)
        (when (= i 2)
            (continue :from arrayloop)
        )
        (format #t "i: ~D~%" i)
    )
    (format #t "doarray~%")
)
;; Output:
;; i: 0
;; i: 1
;; i: 0
;; i: 1
;; i: 0
;; i: 1
```
2024-03-16 14:47:36 -04:00
water111 82fb2cc26a Port bones.gc math to GOAL (#3425)
Reverse engineer the skinning matrix calculation and port to GOAL. This
is about 3x faster than the MIPS2c version.

As usual, there is a `*use-new-bones*` flag to go back to the old
version.

Fix for a bug in the compiler's `.div.vf` implementation (only happens
if src/dst are the same), and fix for a typo in the register allocator
that would sometimes cause it not to consider xmm8-xmm15.
2024-03-15 20:31:11 -04:00
Hat Kid 5a8b4e81f9 decomp3: more engine stuff, support boxed stack arrays in compiler (#3424)
- `sync-info`
- `trajectory`
- `camera`
- `cam-update`
- `cam-states`
- `cam-states-dbg`
- `cam-master`
- `cam-layout`
- `cam-interface`
- `cam-combiner`

Closes #2016
2024-03-15 20:28:26 -04:00
OpenGOAL BotandOpenGOALBot f30b6927b7 CI: Periodic Controller Database Update (#3423)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-03-11 23:39:01 -04:00
water111 fae20a19fc [jak3] Decompile sprite and debug files (#3420) 2024-03-10 21:11:41 -04:00
Tyler Wilding 937af7984f g/j2: workaround intermittent lifeseed DMA crash (#3418)
This is not a fix, but it temporarily works around the potential crash
discussed here https://github.com/open-goal/jak-project/issues/2988

As long as this doesn't impact other things, this feels like a good
interim fix, as having a broken cutscene is better than a fatal crash
and it might be some time before this is properly identified and fixed.
2024-03-09 19:31:00 -05:00
Tyler Wilding d9d09a8bc2 g/j2: Update some vehicle related naming (#3419)
While looking into https://github.com/open-goal/jak-project/issues/3289
I renamed a few things
2024-03-09 19:30:44 -05:00
Tyler Wilding 4ca84f9a97 d/j3: ensure type-tests pass (#3414)
Make this test run in CI as the game is not done yet, CI in master is
failing because something was missed (forward declaration)
2024-03-09 14:45:57 -05:00
Tyler Wilding 62fa9d80e1 Fix minor issues related to the speedrunner mode menu, also stop saving the pc-settings every frame when sr mode is on (#3413)
Fixes #3209
2024-03-09 14:45:49 -05:00
water111 390a511055 [jak3] Decompile sprite (#3412)
Decompile `sprite.gc`. Also update the DMA macro for a small change in
Jak 3: a check to see if nothing was added to the bucket.
2024-03-09 12:14:12 -05:00
Tyler Wilding 0626862a8c Fix issues with camera movement with controller when mouse tracking is also enabled (#3409)
Fixes #3408
2024-03-07 23:35:38 -05:00
Tyler Wilding a80f4e7cca ci: move to macos-12 (#3407)
macos-11 is end of life, it has been for 5 months
https://endoflife.date/macos, it will be removed as a runner on github
in Q2 2024. Next release will require atleast macOS 12.


![300882082-ac6ef1f1-8e18-4af1-a97f-d38cf82885df](https://github.com/open-goal/jak-project/assets/13153231/88bed2ae-8059-4d01-b4a6-8994af131c89)
2024-03-06 23:40:00 -05:00
Tyler Wilding 5b9106302d ci: move to sccache (#3404)
The original buildcache action has been archived, and buildcache itself
has also moved to github.

I forked the action and was updating it to work, but then the latest
buildcache release once again breaks support for older runners (in our
case, macos-12 is the lowest, which is acceptable as 11 is EOL).

Either way, switching to sccache is not only a way cleaner solution but
it is also well maintained (and works!)
2024-03-06 22:21:36 -05:00
Tyler Wilding ecd6091d7f deps: SDL update to 2.30.0 (#3384)
In the hopes that some things have been fixed in the last year
(GAME_CONTROLLER init time, etc)

Make sure this does not regress #2691
2024-03-05 22:12:13 -05:00
Tyler Wilding 60db0e5ef9 deps: update fmt to latest version (#3403)
This updates `fmt` to the latest version and moves to just being a copy
of their repo to make updating easier (no editing their cmake / figuring
out which files to minimally include).

The motivation for this is now that we switched to C++ 20, there were a
ton of deprecated function usages that is going away in future compiler
versions. This gets rid of all those warnings.
2024-03-05 22:11:52 -05:00
OpenGOAL BotandOpenGOALBot b819f852b6 CI: Periodic Controller Database Update (#3397)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-03-04 20:06:14 -08:00
ManDude 7b926b5283 jak2 pckernel: save pc-settings on cheat progress and regular auto-saves (#3396)
Fixes #3392
2024-03-04 02:10:03 +00:00
Tyler Wilding 258fd75cd6 decomp: update naming across jak2/3 (#3395) 2024-03-03 20:49:40 -05:00
water111 9f55e41146 [joint] fix missing matrix interpolation (#3394)
I was missing one of the ways that the joint animation was interpolated.
In particular - the `matrix` that defines the root position of the
object.
2024-03-03 15:15:37 -05:00
Hat Kid 2969833b2d decomp3: more engine stuff, detect non-virtual state inheritance (#3377)
- `speech`
- `ambient`
- `water-h`
- `vol-h`
- `generic-obs`
- `carry-h`
- `pilot-h`
- `board-h`
- `gun-h`
- `flut-h`
- `indax-h`
- `lightjak-h`
- `darkjak-h`
- `target-util`
- `history`
- `collide-reaction-target`
- `logic-target`
- `sidekick`
- `projectile`
- `voicebox`
- `ragdoll-edit`
- most of `ragdoll` (not added to gsrc yet)
- `curves`
- `find-nearest`
- `lightjak-wings`
- `target-handler`
- `target-anim`
- `target`
- `target2`
- `target-swim`
- `target-lightjak`
- `target-invisible`
- `target-death`
- `target-gun`
- `gun-util`
- `board-util`
- `target-board`
- `board-states`
- `mech-h`
- `vol`
- `vent`
- `viewer`
- `gem-pool`
- `collectables`
- `crates`
- `secrets-menu`

Additionally:

- Detection of non-virtual state inheritance
- Added a config file that allows overriding the process stack size set
by `stack-size-set!` calls
- Fix for integer multiplication with `r0`
- Fixed detection for the following macros:
	- `static-attack-info`
- `defpart` and `defpartgroup` (probably still needs adjustments, uses
Jak 2 implementation at the moment)
- `sound-play` (Jak 3 seems to always call `sound-play-by-name` with a
`sound-group` of 0, so the macro has been temporarily defaulted to use
that)

One somewhat significant change made here that should be noted is that
the return type of `process::init-from-entity!` was changed to `object`.
I've been thinking about this for a while, since it looks a bit nicer
without the `(none)` at the end and I have recently encountered init
methods that early return `0`.
2024-03-03 15:15:27 -05:00
ZedB0T 6822e5cc71 Fix (-> *autosplit-info-jak1* training-num-orbs) when blacked out (#3297)
When loading a save, these values are temporarily 0, and it messes with
the autosplitter so we want to ignore them then.
2024-02-28 19:14:50 -05:00
Tyler Wilding ccd47f8465 formatter: Format deftype correctly (#3391)
New configuration options to format column widths in deftype field
definitions. Also force each field/method/state to be inlined.
2024-02-27 20:12:44 -05:00
OpenGOAL BotandOpenGOALBot 8f1aba639c CI: Periodic Controller Database Update (#3389)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-02-26 13:32:08 -05:00
Tyler Wilding 5eeaffcde0 scripts: new linter script to detect goal_src files with trailing whitespace (#3387)
Removes trailing whitespace from goal_src files, eventually the
formatter will do this as well but it's not ready yet so this is a
decent interim solution.

A competent text editor will also do this / flag it for you.
2024-02-24 14:27:56 -05:00
Luminar LightandTyler Wilding 0ae0938965 Only remove -vis from name if it is part of the name. (#3257)
During level extraction, the last 4 characters of the level name are
always removed, because it is assumed that '-vis' is there. But it isn't
always there. This is especially true in post-TPL games.

This causes multiple problems:
- There can be levels in the extraction that will miss their last 4
characters from their name, which is sad, and may make it harder to
identify them.
- If there are '-vis'-less levels whose names are identical apart from
the last 4 characters, the extractor will only get the last one (it
probably extracts all but overwrites everything but the last one). For
example 'ctyasha' and 'ctykora'.

This issue affects the glb extraction and the entities json extraction.

I personally think that just keeping the -vis in the name would be the
best solution, but I guess there was a reason why it was decided that it
should be removed from the name. So to adapt to this, my implementation
will still remove '-vis' from the name, but only if it is actually in
the name - otherwise it won't remove anything.

I hope my changes didn't break anything. Extraction seemed to run fine
after my changes, and I was able to see both ctyasha and ctykora json
files. And didn't see any '-vis', so it is still properly removed.

---------

Co-authored-by: Tyler Wilding <[email protected]>
2024-02-24 14:13:48 -05:00
Tyler Wildinganddallmeyer db66ae4627 g/j2: Dynamic speedrun mode categories and implement a significant amount of a practice mode (#3378)
For example, `AppData/OpenGOAL/jak2/features/speedrun-categories.json`
is defined as such:
```json
[
  {
    "cheats": 0,
    "completed_task": 0,
    "continue_point_name": "",
    "features": 0,
    "forbidden_features": 992,
    "name": "Gunless",
    "secrets": 0
  },
  {
    "cheats": 1,
    "completed_task": 29,
    "continue_point_name": "ctypal-shaft",
    "features": 1024,
    "forbidden_features": 0,
    "name": "Turbo Jetboard - After Praxis 1",
    "secrets": 0
  }
]
```
> These entries can be created using the in-game menu as well.


https://github.com/open-goal/jak-project/assets/13153231/9b17a116-4aa9-40ad-b9f5-02b04e0ad4f3

---------

Co-authored-by: dallmeyer <[email protected]>
2024-02-23 19:04:44 -05:00
Brent HickeyandTyler Wilding 685ff2cf1c [high fps] Increase input buffer size and fix cloud scroll speed (#3178)
The game stores the last 3 frames of input (50ms of time at 60fps) and
often checks if a button was pressed within those 3 saved frames as a
condition.

When transitioning states, it often checks if some input was received
during the previous state (within those 3 frames) in order to quickly
transition out. A good example of this is when transitioning to
standing, it checks if you can jump this frame and if you had pressed X
recently, and if so, transition immediately to jump. This allows
transitions between states to feel more smooth/forgiving by letting you
jump at a later time when you are transitioning from falling->standing
than if you were only falling.

At 165fps the last 3 frames is only 18ms of time so the input windows
for these smooth transitions are almost 3x shorter.

This PR saves 15 input frames (enough to cover 50ms of time at 300fps)
for each controller and adds a (recently-pressed?) macro that checks all
15 frames. However, it only updates the necessary frames in history
based on the current frame rate. This way, 60fps continues to only check
against 3 input frames, 165fps checks against 9, 240fps checks against
12, and 300fps checks all 15.

---------

Co-authored-by: Tyler Wilding <[email protected]>
2024-02-23 18:58:45 -05:00
Tyler Wilding d1a6c60eb8 game: disable keyboard input by default, give users a way to enable it via the imgui menu (#3295)
It was narrowed down recently that a lot of people have issues with the
controller input because of Steam Input working as intended. Steam Input
can be configured to replicate controller inputs as keyboard inputs (for
example, pressing X on your controller presses Enter on the keyboard).

This results in the problem of "jumping pauses the game" and similar
issues. This is a consequence of the intended behaviour of the game
listening to all input sources at the same time.

Since the vast majority of players are using controllers over keyboards,
it makes sense to disable the keyboard input by default to solve this
problem. However that makes things awkward for users that want to use
the keyboard (how do they enable the setting). The solution is a new
imgui option in the settings menu:
![Screenshot 2024-01-07
141224](https://github.com/open-goal/jak-project/assets/13153231/6f9ffa2d-be7a-433d-b698-15b70210e97e)

**Known issue that I don't care about** -- in Jak 1's menu code, since
the flags are controlled by pointers to values instead of a lambda like
in jak 2, the menu won't update live with the imgui option. This has no
functional impact and I don't care enough to fix it.

I also made the pc-settings.gc file persist on first load if the file
wasn't found. Hopefully this helps diagnose the support issues related
to the black screen.

# Why not just ignore the keyboard inputs for a period of time?

This won't work, the keyboard is polled every frame. Therefore if you
hold down the X button on your controller, steam is continuously
signaling that `Enter` is held down on the keyboard.

Yes it would be possible to completely disable the keyboard while the
controller is being used, but this defeats the purpose of creating an
input system that allows multiple input sources at the same time.

With an explicit option, not only can the user decide the behaviour they
want (do they want the keyboard ignored or simultaneously listened to)
but we avoid breaking strange edge-cases in usage leading to never
ending complexity:
- ie. imagine steam input sends events to the mouse, well you can't
disable the mouse while using the keyboard because most times people are
using mouse and keyboard
- ie. a user that wants to hold a direction with the keyboard and press
buttons on the controller in tandem (something i frequently do while
TAS'ing, to move in a perfect straight line)
2024-02-23 18:19:07 -05:00
Matt Dallmeyer d5f92efcda Rename bigmap-id enum entries (#3380)
also fixed some docstrings that were swapped
2024-02-23 14:46:57 -05:00
Tyler Wilding 7c223b1873 g/j2: allow customizing the speedrunner menu bind (#3386)
The bind carried forward from Jak 1 is annoying -- R1 shoots the gun.
Allow the user to use whatever button combination they want by modifying
it in the `pc-settings` file.

```clj
  (controller-led-status? 1360729)
  (speedrunner-mode-custom-bind 4098)
```
2024-02-23 14:45:25 -05:00
Tyler Wilding 7ae1b4bf1c g/j2: properly wireup mouse settings, properly detect when the mouse has stopped moving (#3383)
- Wired up the menu settings to change the settings in game, not just on
boot
- Removed all the duplication in the game options menu code
- Fixed the mouse code so that it properly brings the virtual analog
stick back to neutral when the mouse stops
- Extended the sensitivity min/max for those that want to ensure the
slightest movement maxes out virtual analog stick.
2024-02-23 14:44:40 -05:00
Tyler Wilding 1cc20508e9 tracing: add some more startup related events and a new --profile-until-event flag (#3385)
While trying to narrow down why sometimes SDL takes 20-40seconds to
initialize I built up some more profiling features.

TLDR - I still don't know why SDL is taking a long time but I've
narrowed it down to it initializing the `GAME_CONTROLLER` subsystem.
This isn't unprecedented, I found numerous github issues and articles
suggesting this is the problem:

![image](https://github.com/open-goal/jak-project/assets/13153231/1853326b-7a40-458e-87a0-f7a9f44781e3)

I imagine it is hardware/OS related on some level, there are even some
recent commits in SDL that have made it worse on certain platforms. I've
had this problem myself so I will hope to get it again soon so i can
debug where in the SDL code the delay occurs and make a proper bug
report. Hopefully this helps but it's not yet confirmed -
https://github.com/open-goal/jak-project/pull/3384
2024-02-23 14:44:17 -05:00
Tyler Wilding 1af6503784 New Crowdin updates (#3382) 2024-02-19 23:17:29 -05:00
Tyler Wilding ee2880b985 lsp: revert unnamed variable labelling (#3381)
This didn't really pan out as I hoped since files can have thousands of
these and there is a limit to how many diagnostics are shown (starting
from the top of the file). This also may have caused the recent
instability in the LSP, disabling this i wasn't able to reproduce an LSP
crash cycling through 50-100 files.
2024-02-19 21:17:20 -05:00
OpenGOAL BotandOpenGOALBot c4d3027d04 CI: Periodic Controller Database Update (#3379)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-02-19 14:01:34 -05:00
Ziemas 4e569f0115 Switch to std::span (#3376)
Now that we have cpp20 we can ditch nonstd::span.

Depends on #3375
2024-02-18 13:23:19 -05:00
Ziemas 0011fb4b2b Fix remaining cpp20 issues (#3375) 2024-02-17 20:16:46 -05:00
ZiemasandTyler Wilding 4afefc5a82 Update to C++20 (#3193)
Just putting this here for consideration, I'm personally not in a big
rush to get it.

---------

Co-authored-by: Tyler Wilding <[email protected]>
2024-02-17 14:14:23 -05:00
OpenGOAL BotandOpenGOALBot 269c19548b CI: Periodic Controller Database Update (#3368)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-02-17 13:30:09 -05:00
Hat Kid 406441038b decomp3: game-info, game-task, game-save, level-info, process-drawable and more (#3374)
- `settings`
- `generic-vu1`
- `generic-vu0`
2024-02-15 11:16:07 +00:00
ManDude c99f9a4834 decomp loader (#3373)
fixes `defskelgroup` being broken in jak 2

switches jak 3 to the jak 3 font (currently identical to jak 2)
2024-02-13 16:38:58 +00:00
water111 d8181fb169 [jak3] joint-mod, subdivide, bsp (#3371) 2024-02-11 13:53:29 -05:00
water111 79d14af0b5 Decompile joint, collide-func, clean up joint decompression code for all games (#3369)
I finally read through all the joint code and wrote up some
documentation. I think this will be really helpful when we try to
understand all the functions in `process-drawable`, or if somebody ever
wants to import/export animations.

This switches all three games to using a new faster GOAL joint
decompressor. It is on by default, but you can go back to the old
version by setting `*use-new-decompressor*` to false.

Also fix the log-related crash, fix the clock speed used in timer math.
2024-02-11 09:50:07 -05:00
Hat Kid a4e629ebf9 decompiler: defskelgroup macro detection for jak 3, fix art group dumping for jak 3 and some more decomp work (#3370)
- `transformq`
- `wind-work`
- `progress-static`
- `merc-vu1`
- `emerc-vu1`
- `merc`
- `emerc`
- `cloth-h`
- Most of `cloth`, not added to gsrc yet

Art group dumps were incorrect for Jak 3 because the master art group
fields were at different offsets.
2024-02-11 09:32:06 -05:00
Tyler Wilding 18903f0561 decomp: Copy over new docstrings back to jak 2's common code, write some scripts to help automate this (#3366) 2024-02-04 13:53:06 -05:00
Tyler Wilding 314f488377 d/j3: do a few mood related files and fix some issues along the way (#3365) 2024-02-04 08:40:43 -05:00
water111 221360270a [jak3] decomp gsound (#3364)
Decompile `gsound.gc`
2024-02-03 17:16:23 -05:00
water111 8b1c7759ea [jak3] More headers, up to load-dgo (#3363)
path-h, sparticle-h, load-dgo, nav-control-h, nav-mesh-h, rigid-body-h,
actor-hash-h, spatial-hash-h
2024-02-03 15:03:10 -05:00
water111 af2fa6acbc [jak3] More headers again again (#3359)
collide-cache-h, collide-h, projectile-h, background-h, subdivide-h,
hfrag-h, shrubbery-h, tfrag-h, tie-h
2024-02-03 12:15:51 -05:00
Hat Kid 9e8bee5b42 decomp3: more headers (again) (#3362)
- `entity-h`
- `eye-h`
- `simple-sprite-h`
- `sprite-h`
- `cam-debug-h`
- `cam-update-h`
- `cam-interface-h`
- `hud-h`
- `actor-link-h`
- `camera-h`
- `progress-h`

Also fills out a lot of the `text-id` enum. `progress-static` is also
very close to ready, only being blocked by #3361.
2024-02-03 11:39:29 -05:00
Tyler Wilding 94585e7f87 game: fix intermittent sprite_distort related crash (#3357)
Apparently a long standing bug, with
https://github.com/open-goal/jak-project/pull/3194 making it more likely
to occur.
2024-02-02 17:51:21 -05:00
ManDude bc32e635ee seriously fix music player in title screen (#3358) 2024-02-02 12:24:57 +00:00
water111 b1b5cbb143 [jak3] More headers again (#3352)
joint-mod-h
collide-frag-h
projectile-h
stats-h
bsp-h
chain-physics-h
ragdoll-h
collide-hash-h
2024-02-01 18:46:54 -05:00
Hat Kid 7e5541d793 decomp3: more headers (#3356)
- `pov-camera-h`
- `sync-info-h`
- `trajectory-h`
- `collide-target-h` (`control-info` just padded out for now)
- `water-info-h`
- `process-drawable-h`
- `process-focusable`
- `focus`
- `effect-control-h`
- `process-taskable-h`
- `generic-obs-h`
- `target-h`
2024-02-01 17:58:10 -05:00
ManDude d67b441dac Change important printfs to lg::print (#3355)
This allows them to be logged into a file, useful for debugging.

With this, GOAL `format` and C-kernel `Msg` (and its variants) will be
logged.
2024-02-01 18:01:41 +00:00
dependabot[bot] b331d16bcc build(deps): bump peter-evans/create-pull-request from 5 to 6 (#3353)
Bumps
[peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request)
from 5 to 6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/create-pull-request/releases">peter-evans/create-pull-request's
releases</a>.</em></p>
<blockquote>
<h2>Create Pull Request v6.0.0</h2>
<h2>Behaviour changes</h2>
<ul>
<li>The default values for <code>author</code> and
<code>committer</code> have changed. See &quot;What's new&quot; below
for details. If you are overriding the default values you will not be
affected by this change.</li>
<li>On completion, the action now removes the temporary git remote
configuration it adds when using <code>push-to-fork</code>. This should
not affect you unless you were using the temporary configuration for
some other purpose after the action completes.</li>
</ul>
<h2>What's new</h2>
<ul>
<li>Updated runtime to Node.js 20
<ul>
<li>The action now requires a minimum version of <a
href="https://github.com/actions/runner/releases/tag/v2.308.0">v2.308.0</a>
for the Actions runner. Update self-hosted runners to v2.308.0 or later
to ensure compatibility.</li>
</ul>
</li>
<li>The default value for <code>author</code> has been changed to
<code>${{ github.actor }} &lt;${{ github.actor_id }}+${{ github.actor
}}@users.noreply.github.com&gt;</code>. The change adds the <code>${{
github.actor_id }}+</code> prefix to the email address to align with
GitHub's standard format for the author email address.</li>
<li>The default value for <code>committer</code> has been changed to
<code>github-actions[bot]
&lt;41898282+github-actions[bot]@users.noreply.github.com&gt;</code>.
This is to align with the default GitHub Actions bot user account.</li>
<li>Adds input <code>git-token</code>, the <a
href="https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token">Personal
Access Token (PAT)</a> that the action will use for git operations. This
input defaults to the value of <code>token</code>. Use this input if you
would like the action to use a different token for git operations than
the one used for the GitHub API.</li>
<li><code>push-to-fork</code> now supports pushing to sibling
repositories in the same network.</li>
<li>Previously, when using <code>push-to-fork</code>, the action did not
remove temporary git remote configuration it adds during execution. This
has been fixed and the configuration is now removed when the action
completes.</li>
<li>If the pull request body is truncated due to exceeding the maximum
length, the action will now suffix the body with the message
&quot;...<em>[Pull request body truncated]</em>&quot; to indicate that
the body has been truncated.</li>
<li>The action now uses <code>--unshallow</code> only when necessary,
rather than as a default argument of <code>git fetch</code>. This should
improve performance, particularly for large git repositories with
extensive commit history.</li>
<li>The action can now be executed on one GitHub server and create pull
requests on a <em>different</em> GitHub server. Server products include
GitHub hosted (github.com), GitHub Enterprise Server (GHES), and GitHub
Enterprise Cloud (GHEC). For example, the action can be executed on
GitHub hosted and create pull requests on a GHES or GHEC instance.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Update distribution by <a
href="https://github.com/actions-bot"><code>@​actions-bot</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2086">peter-evans/create-pull-request#2086</a></li>
<li>fix crazy-max/ghaction-import-gp parameters by <a
href="https://github.com/fharper"><code>@​fharper</code></a> in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2177">peter-evans/create-pull-request#2177</a></li>
<li>Update distribution by <a
href="https://github.com/actions-bot"><code>@​actions-bot</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2364">peter-evans/create-pull-request#2364</a></li>
<li>Use checkout v4 by <a
href="https://github.com/okuramasafumi"><code>@​okuramasafumi</code></a>
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2521">peter-evans/create-pull-request#2521</a></li>
<li>Note about <code>delete-branch</code> by <a
href="https://github.com/dezren39"><code>@​dezren39</code></a> in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2631">peter-evans/create-pull-request#2631</a></li>
<li>98 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/fharper"><code>@​fharper</code></a> made
their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2177">peter-evans/create-pull-request#2177</a></li>
<li><a
href="https://github.com/okuramasafumi"><code>@​okuramasafumi</code></a>
made their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2521">peter-evans/create-pull-request#2521</a></li>
<li><a href="https://github.com/dezren39"><code>@​dezren39</code></a>
made their first contribution in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2631">peter-evans/create-pull-request#2631</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v5.0.2...v6.0.0">https://github.com/peter-evans/create-pull-request/compare/v5.0.2...v6.0.0</a></p>
<h2>Create Pull Request v5.0.2</h2>
<p>⚙️ Fixes an issue that occurs when using <code>push-to-fork</code>
and both base and head repositories are in the same org/user
account.</p>
<h2>What's Changed</h2>
<ul>
<li>fix: specify head repo by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/2044">peter-evans/create-pull-request#2044</a></li>
<li>20 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v5.0.1...v5.0.2">https://github.com/peter-evans/create-pull-request/compare/v5.0.1...v5.0.2</a></p>
<h2>Create Pull Request v5.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: truncate body if exceeds max length by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/1915">peter-evans/create-pull-request#1915</a></li>
<li>12 dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v5.0.0...v5.0.1">https://github.com/peter-evans/create-pull-request/compare/v5.0.0...v5.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/b1ddad2c994a25fbc81a28b3ec0e368bb2021c50"><code>b1ddad2</code></a>
feat: v6 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2717">#2717</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/bb809027fda03cc267431a7d36a88148eb9f3846"><code>bb80902</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.8 to 18.19.10
(<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2712">#2712</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/e0037d470cdeb1c8133acfba89af08639bb69eb3"><code>e0037d4</code></a>
build(deps): bump peter-evans/create-or-update-comment from 3 to 4 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2702">#2702</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/94b1f99e3a73880074d0e669c3b69d376cc8ceae"><code>94b1f99</code></a>
build(deps): bump peter-evans/find-comment from 2 to 3 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2703">#2703</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/69c27eaf4a14a67b5362a51e681f83d3d5e0f96b"><code>69c27ea</code></a>
build(deps-dev): bump ts-jest from 29.1.1 to 29.1.2 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2685">#2685</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/7ea722a0f6286a45eb3005280d83575a74bc8fef"><code>7ea722a</code></a>
build(deps-dev): bump prettier from 3.2.2 to 3.2.4 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2684">#2684</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/5ee839affd4c87811108724370a2819a40e2e5d3"><code>5ee839a</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.7 to 18.19.8
(<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2683">#2683</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/60fc256c678e6ed78d0d42e09675c9beba09cb94"><code>60fc256</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2660">#2660</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/0c677233614c017442253060c74fd2cb7ff349fc"><code>0c67723</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.5 to 18.19.7
(<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2661">#2661</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/4e288e851b95bd1362e281a255094fcc47ada675"><code>4e288e8</code></a>
build(deps-dev): bump prettier from 3.1.1 to 3.2.2 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/2659">#2659</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/peter-evans/create-pull-request/compare/v5...v6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peter-evans/create-pull-request&package-manager=github_actions&previous-version=5&new-version=6)](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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
2024-01-31 23:19:52 -05:00
dependabot[bot] c909eef8ea build(deps): bump peter-evans/repository-dispatch from 2 to 3 (#3354)
Bumps
[peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch)
from 2 to 3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/repository-dispatch/releases">peter-evans/repository-dispatch's
releases</a>.</em></p>
<blockquote>
<h2>Repository Dispatch v3.0.0</h2>
<p>⚙️  Updated runtime to Node.js 20</p>
<ul>
<li>The action now requires a minimum version of <a
href="https://github.com/actions/runner/releases/tag/v2.308.0">v2.308.0</a>
for the Actions runner. Update self-hosted runners to v2.308.0 or later
to ensure compatibility.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Bump prettier to fix deps by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/255">peter-evans/repository-dispatch#255</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.17.12 to
18.17.14 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/257">peter-evans/repository-dispatch#257</a></li>
<li>build(deps-dev): bump <code>@​vercel/ncc</code> from 0.36.1 to
0.38.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/258">peter-evans/repository-dispatch#258</a></li>
<li>build(deps): bump actions/checkout from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/259">peter-evans/repository-dispatch#259</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.17.14 to
18.17.16 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/261">peter-evans/repository-dispatch#261</a></li>
<li>build(deps): bump <code>@​actions/core</code> from 1.10.0 to 1.10.1
by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>
in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/262">peter-evans/repository-dispatch#262</a></li>
<li>build(deps-dev): bump jest-circus from 29.6.4 to 29.7.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/263">peter-evans/repository-dispatch#263</a></li>
<li>build(deps-dev): bump eslint from 8.48.0 to 8.49.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/264">peter-evans/repository-dispatch#264</a></li>
<li>Update distribution by <a
href="https://github.com/actions-bot"><code>@​actions-bot</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/265">peter-evans/repository-dispatch#265</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.17.16 to
18.17.18 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/266">peter-evans/repository-dispatch#266</a></li>
<li>build(deps-dev): bump eslint-plugin-github from 4.10.0 to 4.10.1 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/267">peter-evans/repository-dispatch#267</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.17.18 to
18.18.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/268">peter-evans/repository-dispatch#268</a></li>
<li>build(deps-dev): bump eslint from 8.49.0 to 8.50.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/269">peter-evans/repository-dispatch#269</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.0 to
18.18.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/271">peter-evans/repository-dispatch#271</a></li>
<li>build(deps-dev): bump eslint-plugin-prettier from 5.0.0 to 5.0.1 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/275">peter-evans/repository-dispatch#275</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.3 to
18.18.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/274">peter-evans/repository-dispatch#274</a></li>
<li>build(deps-dev): bump eslint from 8.50.0 to 8.51.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/276">peter-evans/repository-dispatch#276</a></li>
<li>build(deps-dev): bump <code>@​babel/traverse</code> from 7.16.3 to
7.23.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/278">peter-evans/repository-dispatch#278</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.5 to
18.18.6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/279">peter-evans/repository-dispatch#279</a></li>
<li>build(deps-dev): bump <code>@​vercel/ncc</code> from 0.38.0 to
0.38.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/280">peter-evans/repository-dispatch#280</a></li>
<li>build(deps-dev): bump eslint from 8.51.0 to 8.52.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/281">peter-evans/repository-dispatch#281</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.6 to
18.18.7 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/282">peter-evans/repository-dispatch#282</a></li>
<li>build(deps): bump actions/setup-node from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/283">peter-evans/repository-dispatch#283</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.7 to
18.18.8 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/284">peter-evans/repository-dispatch#284</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.8 to
18.18.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/285">peter-evans/repository-dispatch#285</a></li>
<li>build(deps-dev): bump eslint from 8.52.0 to 8.53.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/286">peter-evans/repository-dispatch#286</a></li>
<li>build(deps-dev): bump prettier from 3.0.3 to 3.1.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/287">peter-evans/repository-dispatch#287</a></li>
<li>build(deps-dev): bump eslint from 8.53.0 to 8.54.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/289">peter-evans/repository-dispatch#289</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.9 to
18.18.13 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/290">peter-evans/repository-dispatch#290</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.18.13 to
18.19.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/291">peter-evans/repository-dispatch#291</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.0 to
18.19.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/292">peter-evans/repository-dispatch#292</a></li>
<li>build(deps-dev): bump eslint from 8.54.0 to 8.55.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/293">peter-evans/repository-dispatch#293</a></li>
<li>build(deps-dev): bump prettier from 3.1.0 to 3.1.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/296">peter-evans/repository-dispatch#296</a></li>
<li>build(deps): bump actions/upload-artifact from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/295">peter-evans/repository-dispatch#295</a></li>
<li>build(deps-dev): bump eslint from 8.55.0 to 8.56.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/297">peter-evans/repository-dispatch#297</a></li>
<li>build(deps-dev): bump eslint-plugin-prettier from 5.0.1 to 5.1.1 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/298">peter-evans/repository-dispatch#298</a></li>
<li>build(deps-dev): bump eslint-plugin-prettier from 5.1.1 to 5.1.2 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/299">peter-evans/repository-dispatch#299</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.3 to
18.19.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/300">peter-evans/repository-dispatch#300</a></li>
<li>build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 by
<a href="https://github.com/dependabot"><code>@​dependabot</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/301">peter-evans/repository-dispatch#301</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.4 to
18.19.6 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/302">peter-evans/repository-dispatch#302</a></li>
<li>build(deps-dev): bump prettier from 3.1.1 to 3.2.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/303">peter-evans/repository-dispatch#303</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.6 to
18.19.8 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/304">peter-evans/repository-dispatch#304</a></li>
<li>feat: update runtime to node 20 by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/305">peter-evans/repository-dispatch#305</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/ff45666b9427631e3450c54a1bcbee4d9ff4d7c0"><code>ff45666</code></a>
feat: update runtime to node 20 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/305">#305</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/a4a90276d01e3a2ae44fa10a0247287f045afd59"><code>a4a9027</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.6 to 18.19.8
(<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/304">#304</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/26052532834cf5d789f5606e8b98cd0bfab56380"><code>2605253</code></a>
build(deps-dev): bump prettier from 3.1.1 to 3.2.4 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/303">#303</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/ab3258eeeffae29c708cb86edfc514542da16621"><code>ab3258e</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.4 to 18.19.6
(<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/302">#302</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/240bc731931727c20e5294c098f79936917bb2ab"><code>240bc73</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.1.2 to 5.1.3 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/301">#301</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/8aa15c54a0775550e589f6e5a1c10d5a7944fa61"><code>8aa15c5</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.3 to 18.19.4
(<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/300">#300</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/22aa07cf23211217f2f281db8f96d64aaf773db3"><code>22aa07c</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.1.1 to 5.1.2 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/299">#299</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/ba0298574b6decfde4790aeded048a3b996a9ba0"><code>ba02985</code></a>
build(deps-dev): bump eslint-plugin-prettier from 5.0.1 to 5.1.1 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/298">#298</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/accfd7b5bfd02b2977592bd723e73cab236409e4"><code>accfd7b</code></a>
build(deps-dev): bump eslint from 8.55.0 to 8.56.0 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/297">#297</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/3c7d964ae9f0b74896fbe6e607a12437ba01ca21"><code>3c7d964</code></a>
build(deps): bump actions/upload-artifact from 3 to 4 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/295">#295</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/peter-evans/repository-dispatch/compare/v2...v3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=peter-evans/repository-dispatch&package-manager=github_actions&previous-version=2&new-version=3)](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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
2024-01-31 23:19:43 -05:00
water111 1cccfbbf78 [jak3] More headers! (#3351)
Decomp aligner-h, joint-h, prim-h, debug-h, game-h, penetrate-h,
bones-h, foreground-h, scene-h, script-h.

Also, has a little bit of the joint-mod-h file, but it's not finished
yet.
2024-01-31 19:05:12 -05:00
Hat Kid ea93d32acc decomp3: more misc files (#3349)
- `pat-h`
- `engines`
- `res-h`
- `res`
- `fact-h`
- `game-info-h`
- `wind-h`
- `merc-h`
- `shadow-vu1-h`
- `shadow-cpu-h`
- `dynamics-h`
- `memcard-h`
- `surface-h`
- part of `gui-h`
- `ambient-h`
- `speech-h`
- `prototype-h`
- `smush-control-h`
- `generic-merc-h`
- `generic-work-h`
- `collide-func-h`
- `collide-mesh-h`
- `collide-shape-h` (only missing the `new` method for `collide-shape`
because we don't have `process-drawable` yet and that also needs joint
stuff etc.)
- `collide-touch-h`
- `collide-edge-grab-h`
- `lightning-h`

This also adds argument name remaps for the `relocate` and `mem-usage`
methods (Jak 1 and 2 ref tests were updated, but not the gsrc).
2024-01-31 18:25:06 -05:00
Matt Dallmeyer 1979f94e45 Rip collision based on config flag (#3348)
Added a new `rip_collision` flag to the decompiler config and wired it
up. Cleaned up the comments around these fields in the JSON too for
clarity

Also refactored a bunch of the related extract functions to read from
`config` object rather than pass down a bunch of booleans
2024-01-29 22:15:42 +01:00
water111 ba8d4c2903 [jak3] Drawable header decomp (#3347) 2024-01-28 14:23:41 -05:00
water111 bfe0a72ae7 [jak3] decompile (but not port) texture (#3346)
For now - just a plain decompilation, with no PC port changes. I think
it'll be easier to do those once we have a little bit more decompiled.
2024-01-27 16:30:18 -05:00
water111 8d0d05717f [jak3] misc. headers (#3345)
trail-h, minimap-h, bigmap-h, capture, memory-usage-h, blit-displays-h,
sky-h, rest of ocean-h
2024-01-27 14:06:21 -05:00
Ziemas 398d2ee5e1 cmake: Remove -Wmissing-include-dir (#3343)
I'm tired of it spamming and I couldn't figure out what adds to
non-existent fmt/include dir.
2024-01-27 13:10:00 -05:00
water111 5fe4d12f70 [jak3] dma-disasm, time-of-day-h, texture-anim-h, level-h (#3344) 2024-01-27 13:09:37 -05:00
water111 4bd5111280 [jak3] dma, dma-bucket, dma-buffer (#3331) 2024-01-27 11:44:08 -05:00
Hat Kid f045e6cef1 decomp3: font-h, display, profile, settings-h, camera-defs-h, text-h (#3335) 2024-01-27 11:27:34 -05:00
Hat Kid 17f5f74238 jak3: dump of all vu programs (#3340)
With the exception of `sprite` and the new `hfrag` renderer, everything
appears to be identical to Jak 2.
2024-01-27 11:38:03 +01:00
ManDude 9aa291313b fix custom screenshots and change screenshot directory (#3339) 2024-01-26 04:49:35 +00:00
OpenGOAL BotandOpenGOALBot 6f0d0fa417 CI: Periodic Controller Database Update (#3327)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2024-01-25 21:28:58 -05:00
Tyler Wilding 7ef2c2fac3 decomp: add a new config flag to disable var-name casts (#3338)
This is handy when you want to try comparing the decompiler's output
across games (ie. for checking if only naming differs)
2024-01-25 21:28:47 -05:00
Hat Kid 3eb6cfcb17 custom levels: add support for symbol, type, and string lumps (#3337) 2024-01-25 23:20:32 +01:00
Tyler Wilding 0236e36a53 formatter: fix multi-line form consolidation (#3336) 2024-01-25 16:46:15 -05:00
Hat Kid 0ea718a5ee decomp3: loader-h, capture-h, math-camera-h, math-camera, connect, gs, texture-h (#3333) 2024-01-25 15:44:26 +01:00
Hat Kid 3a2c57c091 decomp3: timer, display-h, decomp-h, file-io, pad (#3332) 2024-01-23 23:52:15 -05:00
water111 b130c2f439 [jak3] A few early files (#3330)
types-h, vu1-macros, gsound-h, dma-h, video-h, vu1-user-h, profile-h

The `gsound-h` is very simple, but the rest have decent docs and all the
macros we had from jak 2.

So far, barely any differences! (there's a few in gsound-h)
2024-01-22 21:09:48 -05:00
Ziemas 3dc27e37e5 decompiler: Extract Jak3 VAGs (#3328) 2024-01-22 20:47:06 -05:00
Hat Kid d4c21c784f decomp3: geometry, vector, timer-h, ocean table files and game-task related enums (#3329) 2024-01-22 20:45:53 -05:00
water111 01d5fc2bbb [jak3] Decomp for gkernel, gkernel-h, gstate, gstring (#3326)
I ported the kernel test from jak1/jak2 to jak 3, and it's passing!
2024-01-21 18:08:05 -05:00
water111 638bf1d3d9 [gltf] Support either u16 or float for colors (#3322)
It seems like this depends on the version of blender, so we should
support both.
2024-01-21 11:03:26 -05:00
Tyler Wilding 5ddf1e4b4d lsp: flag unnamed variables in IR files (#3325)
![image](https://github.com/open-goal/jak-project/assets/13153231/a020fbf6-65b9-4317-8a9d-5991f2d15e32)
2024-01-21 01:05:41 -05:00
Hat Kid 2bb1d53752 custom levels: cell-info and buzzer-info lumps (#3324)
Adds two new lump types: `cell-info` and `buzzer-info`.

`cell-info` takes a `game-task` enum value and defines an `eco-info`
lump for power cells.

`buzzer-info` takes a `game-task` enum value and an integer and
automatically calculates the required value for the buzzer task with the
formula `task + buzzer * (1 << 16)`.
2024-01-21 03:49:55 +01:00
ManDude 076f8aa6dd [jak2] fix music player option (#3323) 2024-01-20 23:28:21 +00:00
water111 1c0038294f [jak3] Decompile gcommon (#3321)
Decompile `gcommon`. I adjusted the spacing of docstring comments, and
removed some spammy decompiler warning prints.

I also added some random notes I had on VU programs from jak1/jak2. They
are not polished, but I think it's still worth including since we'll
have to go through them again for jak 3.
2024-01-20 12:33:39 -05:00
Hat Kid 9a4929ac0c decomp3: some engine files (#3319)
- `vector-h`
- `gravity-h`
- `bounding-box-h`
- `matrix-h`
- `quaternion-h`
- `euler-h`
- `transform-h`
- `geometry-h`
- `trigonometry-h`
- `transformq-h`
- `bounding-box`
- `matrix`
- `matrix-compose`
- `transform`
- `quaternion`
- `euler`
- `trigonometry`

Not a whole lot of changes, just a couple of new functions and one new
file (`matrix-compose`).
2024-01-20 10:42:51 -05:00
Ziemas 25c74f1740 j2-overlord: Fix typo (#3320) 2024-01-20 14:43:52 +01:00
Tyler Wilding 272cb32a45 lsp: handle line-endings appropriately (#3318) 2024-01-18 20:32:30 -05:00
Tyler Wilding c3e4baf697 formatter: support for a few more forms and fix some bugs, update tree-sitter grammar (#3317) 2024-01-18 20:09:40 -05:00
Hat Kid 85039fe2d6 jak3: fix all-types file order (#3316)
In #3300, `per_object` in `ObjectFileDB::ir2_analyze_all_types()` was
changed to an `unordered_map`, which messed with the object file order
in `all-types`. This fixes the issue by going through each object file
in order and then looking up the type info from the map instead of
iterating through the map.

This also removes the method IDs from the old method comments and adds a
stub for the `new` method if there is an old method comment for it, in
order to stay consistent with the rest of the method list.
2024-01-18 14:57:10 +01:00
Hat Kid b06d63ba83 custom levels: sort actors by aid and check for duplicates (#3315)
When giving entities custom actor IDs in your level JSON, it is possible
to break entity lookups by actor ID if the actors are not sorted by ID
because `entity-by-aid` expects them to be in order.

This sorts the actor list by ID before generating the level file and
also checks for any duplicates.
2024-01-18 10:29:30 +01:00
ManDude 13f1aa1785 [jak2] fully implement PLAYER set-param for VAG streams + fix regression (#3314)
At last...
2024-01-18 01:59:04 +00:00
ManDude ba7b0397b1 [pckernel] fix settings not being applied if file isn't found (#3313) 2024-01-17 15:43:53 +00:00
water111 4f537d4a71 [jak3] Set up ckernel (#3308)
This sets up the C Kernel for Jak 3, and makes it possible to build and
load code built with `goalc --jak3`.

There's not too much interesting here, other than they switched to a
system where symbol IDs (unique numbers less than 2^14) are generated at
compile time, and those get included in the object file itself.

This is kind of annoying, since it means all tools that produce a GOAL
object file need to work together to assign unique symbol IDs. And since
the symbol IDs can't conflict, and are only a number between 0 and 2^14,
you can't just hash and hope for no collisions.

We work around this by ignoring the IDs and re-assigning our own. I
think this is very similar to what the C Kernel did on early builds of
Jak 3 which supported loading old format level files, which didn't have
the IDs included.

As far as I can tell, this shouldn't cause any problems. It defeats all
of their fancy tricks to save memory by not storing the symbol string,
but we don't care.
2024-01-16 19:24:02 -05:00
James AldridgeandJamesAldridge ed6639ee60 fix zydis alignment issue during build for intel macs (#3312)
Fix zydis alignment issues when building on Intel macOS builds was
discussed with zydis devs https://github.com/zyantific/zydis/issues/474

Verified locally that I can run open goal with the change.

Co-authored-by: JamesAldridge <[email protected]>
2024-01-16 19:01:55 -05:00
ManDude 1dba36c614 fix jak3 jp strings (#3311) 2024-01-16 11:09:17 +00:00
Tyler Wilding 4101d5d80e tests: add jak3 typeconsistency test and ensure offline tests are working (#3310) 2024-01-16 00:15:33 -05:00
jabermonyandTyler Wilding 07427799a6 Jak3 Build Environment (#3098)
This sets out the bones of a Jak 3 build, many things are stubbed out,
guessed, or copied from Jak 2 but it should at least be good enough to:
run `task set-game-jak3`
launch the repl
run builds from the repl

build outputs themselves are untested but the build itself runs without
errors

---------

Co-authored-by: Tyler Wilding <[email protected]>
2024-01-15 20:37:16 -05:00
Tyler Wilding 637b043293 deps: update zydis to latest commit (#3306)
Updates Zydis to it's latest commit, this should fix building the
project on intel macs with a more recent version of macOS. This likely
needs some sanity checks that the debugger stuff still works as
expected.
2024-01-15 16:56:14 -05:00
ManDude 46db6a36da [pckernel] use pc-get-resolution to fetch initial fullscreen resolution (#3307)
This is the more correct way of doing what that code is trying to do.
Fixes #3296

Also fixed some type inconsistencies with related code, probably wasn't
causing issues though.

May also fix the "black screen on startup" issues people keep having,
but that would simply be a nice bonus and isn't the aim of this PR.
2024-01-15 18:53:49 +00:00
Hat Kid 619f39d3b7 custom levels: enum lump support (#3305)
This adds support for using enums in lumps using the new lump types
`enum-int32` and `enum-uint32`. Also adds these other new lump types:

- `water-height` (takes 3 meter floats, an enum and another optional
meter float)
- `eco-info` (takes an enum and an int)
- `vector3m` (3 meter floats + `w` set to 1.0)
2024-01-15 12:46:42 +01:00
Matt Dallmeyer 2071c98b55 Fix cases of string formatting with non string literals (#3304)
The logger used in `goalc` tries to print an already-formatted string
`message` using `fmt::print(message);` Usually this doesn't cause
problems, but if you try to print, for example, an exception that has
special characters (notably `{`) it will try to do another round of
formatting/replacements, despite not having any args to replace with,
which ends up throwing another exception. This is why errors when
parsing custom level JSON cause the REPL to exit.

I've hopefully identified all the various instances of this across the
codebase
2024-01-14 12:02:08 +00:00
ManDude 7a8aa71204 [jak2] implement statistics tracker (#3288)
Currently only tracks enemy kills, and how they were killed. There is
currently no menu for this, but I've already added most of the text for
it. Also did a bunch of misc decompilation fixes and renamed some
methods.

Fixes #3277 
Fixes #3278
2024-01-11 22:49:41 +00:00
Tyler Wilding a80cff9a4c game: Fix issues related to remapping with SDL axii's (ie. triggers) (#3294)
This was just not implemented end to end. There are still two notable
issues, one that I can live with, one I need to narrow down eventually:
1. Rebinding confirm buttons with trigger (ie. X) behaviour is not 100%
as it should be. I fixed it enough that I can live with it but it's
still not proper. The difficulty is that unlike a button it will
re-trigger the pressed state on the journey back to neutral (aka
unpressed).
2. If you change the bind for the confirm button, then reset your
bindings, the next confirm input is eaten. This is unrelated to these
changes but I briefly looked into it and was unable to find the root
cause.
2024-01-09 16:50:58 -05:00
Tyler Wilding 4cccaf2645 d/j3: all-types: guess at associated process for non-virtual states and fix some issues along the way (#3300)
This will make a best effort attempt at guessing which process a
non-virtual state belongs to:
![Screenshot 2024-01-08
195309](https://github.com/open-goal/jak-project/assets/13153231/69132f10-823d-4df5-b2d6-662d4dd754a0)

I also noticed some issues while working on this, mainly around how
virtual states were being output. They were being duplicated, for
example:
![Screenshot 2024-01-08
184733](https://github.com/open-goal/jak-project/assets/13153231/1edb0f1a-3ac7-46cb-96cd-cf93d42fb01f)
or
![Screenshot 2024-01-08
193730](https://github.com/open-goal/jak-project/assets/13153231/45673653-4000-45bb-af00-9baa6e2a70ae)

I think I've fixed that, but @Hat-Kid I defer to you to see if i've done
something terrible.
![Screenshot 2024-01-08
194513](https://github.com/open-goal/jak-project/assets/13153231/75543d2e-69da-4bbd-b143-2f824b9d8dde)
2024-01-09 16:50:05 -05:00
Matt Dallmeyer 9d680a0aba Support extracting collision to obj for jak2/3 formats (#3292)
![image](https://github.com/open-goal/jak-project/assets/2515356/b4d43254-4fc4-4f66-92d1-0d61e471b90e)

![image](https://github.com/open-goal/jak-project/assets/2515356/d2fa9fb8-5f51-43c5-8e0e-b51b64499b72)
2024-01-05 09:36:09 +01:00
dependabot[bot] b0713641e7 build(deps): bump actions/download-artifact from 3 to 4 (#3283)
Bumps
[actions/download-artifact](https://github.com/actions/download-artifact)
from 3 to 4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/download-artifact/releases">actions/download-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.0</h2>
<h2>What's Changed</h2>
<p>The release of upload-artifact@v4 and download-artifact@v4 are major
changes to the backend architecture of Artifacts. They have numerous
performance and behavioral improvements.</p>
<p>For more information, see the <a
href="https://github.com/actions/toolkit/tree/main/packages/artifact"><code>@​actions/artifact</code></a>
documentation.</p>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/bflad"><code>@​bflad</code></a> made
their first contribution in <a
href="https://redirect.github.com/actions/download-artifact/pull/194">actions/download-artifact#194</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/download-artifact/compare/v3...v4.0.0">https://github.com/actions/download-artifact/compare/v3...v4.0.0</a></p>
<h2>v3.0.2</h2>
<ul>
<li>Bump <code>@actions/artifact</code> to v1.1.1 - <a
href="https://redirect.github.com/actions/download-artifact/pull/195">actions/download-artifact#195</a></li>
<li>Fixed a bug in Node16 where if an HTTP download finished too quickly
(&lt;1ms, e.g. when it's mocked) we attempt to delete a temp file that
has not been created yet <a
href="hhttps://redirect.github.com/actions/toolkit/pull/1278">actions/toolkit#1278</a></li>
</ul>
<h2>v3.0.1</h2>
<ul>
<li><a
href="https://redirect.github.com/actions/download-artifact/pull/178">Bump
<code>@​actions/core</code> to 1.10.0</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/download-artifact/commit/f44cd7b40bfd40b6aa1cc1b9b5b7bf03d3c67110"><code>f44cd7b</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/259">#259</a>
from actions/robherley/glob-downloads</li>
<li><a
href="https://github.com/actions/download-artifact/commit/3181fe853d2c9a606cd326853bf4c5b8ced5df02"><code>3181fe8</code></a>
add some migration docs</li>
<li><a
href="https://github.com/actions/download-artifact/commit/aaaac7b403f278b6b7eebdca69ca1658616f1c57"><code>aaaac7b</code></a>
licensed cache</li>
<li><a
href="https://github.com/actions/download-artifact/commit/7c9182f0e18dadedfbca3189ab7a22a416aa6714"><code>7c9182f</code></a>
update readme</li>
<li><a
href="https://github.com/actions/download-artifact/commit/b94e7015566b40b2de5eeeda514f239968da2dd7"><code>b94e701</code></a>
licensed cache</li>
<li><a
href="https://github.com/actions/download-artifact/commit/0b55470e40ab7435f445813ebc18b1107ecf7e32"><code>0b55470</code></a>
add test case for globbed downloads to same directory</li>
<li><a
href="https://github.com/actions/download-artifact/commit/0b51c2ef9042b581aded9711127e4a6d5f71c550"><code>0b51c2e</code></a>
update prettier/eslint versions</li>
<li><a
href="https://github.com/actions/download-artifact/commit/c4c6db724f9510b2b3cff5ebcc417c87a2b2fa97"><code>c4c6db7</code></a>
support globbing artifact list &amp; merging download directory</li>
<li><a
href="https://github.com/actions/download-artifact/commit/1bd0606e08fcaa4c28afc1fc7d45830ab5482dac"><code>1bd0606</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/download-artifact/issues/252">#252</a>
from stchr/patch-1</li>
<li><a
href="https://github.com/actions/download-artifact/commit/eff4d42b1f6ff704c7a0f37152ed8793673560ef"><code>eff4d42</code></a>
fix default for run-id</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/download-artifact/compare/v3...v4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/download-artifact&package-manager=github_actions&previous-version=3&new-version=4)](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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
2024-01-04 01:32:49 -05:00
dependabot[bot] aa68b80da2 build(deps): bump actions/upload-artifact from 3 to 4 (#3284)
Bumps
[actions/upload-artifact](https://github.com/actions/upload-artifact)
from 3 to 4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/upload-artifact/releases">actions/upload-artifact's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.0</h2>
<h2>What's Changed</h2>
<p>The release of upload-artifact@v4 and download-artifact@v4 are major
changes to the backend architecture of Artifacts. They have numerous
performance and behavioral improvements.</p>
<p>For more information, see the <a
href="https://github.com/actions/toolkit/tree/main/packages/artifact"><code>@​actions/artifact</code></a>
documentation.</p>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/vmjoseph"><code>@​vmjoseph</code></a>
made their first contribution in <a
href="https://redirect.github.com/actions/upload-artifact/pull/464">actions/upload-artifact#464</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/upload-artifact/compare/v3...v4.0.0">https://github.com/actions/upload-artifact/compare/v3...v4.0.0</a></p>
<h2>v3.1.3</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(github): remove trailing whitespaces by <a
href="https://github.com/ljmf00"><code>@​ljmf00</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/313">actions/upload-artifact#313</a></li>
<li>Bump <code>@​actions/artifact</code> version to v1.1.2 by <a
href="https://github.com/bethanyj28"><code>@​bethanyj28</code></a> in <a
href="https://redirect.github.com/actions/upload-artifact/pull/436">actions/upload-artifact#436</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/upload-artifact/compare/v3...v3.1.3">https://github.com/actions/upload-artifact/compare/v3...v3.1.3</a></p>
<h2>v3.1.2</h2>
<ul>
<li>Update all <code>@actions/*</code> NPM packages to their latest
versions- <a
href="https://redirect.github.com/actions/upload-artifact/issues/374">#374</a></li>
<li>Update all dev dependencies to their most recent versions - <a
href="https://redirect.github.com/actions/upload-artifact/issues/375">#375</a></li>
</ul>
<h2>v3.1.1</h2>
<ul>
<li>Update actions/core package to latest version to remove
<code>set-output</code> deprecation warning <a
href="https://redirect.github.com/actions/upload-artifact/issues/351">#351</a></li>
</ul>
<h2>v3.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump <code>@​actions/artifact</code> to v1.1.0 (<a
href="https://redirect.github.com/actions/upload-artifact/pull/327">actions/upload-artifact#327</a>)
<ul>
<li>Adds checksum headers on artifact upload (<a
href="https://redirect.github.com/actions/toolkit/pull/1095">actions/toolkit#1095</a>)
(<a
href="https://redirect.github.com/actions/toolkit/pull/1063">actions/toolkit#1063</a>)</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/upload-artifact/commit/c7d193f32edcb7bfad88892161225aeda64e9392"><code>c7d193f</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/466">#466</a>
from actions/v4-beta</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/13131bb095770b4070a7477c3cd2d96e1c16d9f4"><code>13131bb</code></a>
licensed cache</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/4a6c273b9834f66a1d05c170dc3f80f9cdb9def1"><code>4a6c273</code></a>
Merge branch 'main' into v4-beta</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/f391bb91a3d3118aeca171c365bb319ece276b37"><code>f391bb9</code></a>
Merge pull request <a
href="https://redirect.github.com/actions/upload-artifact/issues/465">#465</a>
from actions/robherley/v4-documentation</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/9653d03c4b74c32144e02dae644fea70e079d4b3"><code>9653d03</code></a>
Apply suggestions from code review</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/875b63076402f25ef9d52c294c86ba4f97810575"><code>875b630</code></a>
add limitations section</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/ecb21463e93740a6be75c3116242169bfdbcb15a"><code>ecb2146</code></a>
add compression example</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/5e7604f84a055838f64ed68bb9904751523081ae"><code>5e7604f</code></a>
trim some repeated info</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/d6437d07581fe318a364512e6cf6b1dca6b4f92c"><code>d6437d0</code></a>
naming</li>
<li><a
href="https://github.com/actions/upload-artifact/commit/1b561557037b4957d7d184e9aac02bec86c771eb"><code>1b56155</code></a>
s/v4-beta/v4/g</li>
<li>Additional commits viewable in <a
href="https://github.com/actions/upload-artifact/compare/v3...v4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/upload-artifact&package-manager=github_actions&previous-version=3&new-version=4)](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 merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@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>
2024-01-04 01:32:40 -05:00
Ziemas 6901e80e7f j2-overlord: Clean up some VAG functions (#3287)
Some cleanup of vag related functions in overlord.
2024-01-02 16:30:56 +00:00
EvelynTSMG 12118e57cb Impr: Make mesh extract compatible with gLTF 2.0 (and Blender 4.0) (#3268)
:3
2024-01-01 16:30:48 -05:00
ManDude 349919f788 [jak2] implement pc cheats in menu (#3275)
Adds the opengoal cheats to the secrets menu. Only cheats that are fully
functional and unlockable are there right now, which is eight cheats.

This update will reset most Jak 2 settings.

Also fixes #3274 .
2023-12-28 11:14:10 +00:00
ManDude a01d78c7d4 [jak2] fix shadow origin using wrong joint (#3271)
Copypasta. Fixes #3269
2023-12-22 16:52:53 +00:00
Tyler Wilding 708c15788b g/j2: switch to OpenGOAL speedrun.com leaderboards (#3265)
Boards that have no runs yet look kinda awkward but i'd rather just wait
until those fill out (won't take long) rather than add another string to
be translated.
2023-12-19 19:06:55 -05:00
Tyler Wilding 6cfb89a78a g/j2: fix interleaving of local and external highscores (#3264)
Local scores weren't going above external scores even if they were
higher, a few test cases:

![Screenshot 2023-12-19
182412](https://github.com/open-goal/jak-project/assets/13153231/bf3c700d-0f23-441e-b537-88794532523b)
![Screenshot 2023-12-19
182446](https://github.com/open-goal/jak-project/assets/13153231/18d5d6eb-54b1-466e-8302-ca629677344f)
![Screenshot 2023-12-19
182442](https://github.com/open-goal/jak-project/assets/13153231/7de763a5-3587-416f-8755-1868049b92ed)
![Screenshot 2023-12-19
182421](https://github.com/open-goal/jak-project/assets/13153231/d44c1b5b-5f4f-4151-a1f0-e28d7612ed9d)
2023-12-19 18:58:25 -05:00
Tyler Wilding 99da5da441 g/j2: save window-size to pc-settings when it's changed (#3263)
Fixes #3262
2023-12-19 18:56:49 -05:00
RoyalForgottenandTyler Wilding c7af284c6b French subtitle_lines_fr-FR.json (#3259)
French subtitles complete + fixed some wrong texts

---------

Co-authored-by: Tyler Wilding <[email protected]>
2023-12-19 18:55:51 -05:00
Matt Dallmeyer 3e568cb95d Disable save_texture_pngs by default [jak1] (#3256) 2023-12-18 18:25:51 -05:00
tripp 4b9c1dde70 add ms to loader output (#3261) 2023-12-18 18:17:27 -05:00
OpenGOAL BotandOpenGOALBot 35daebcce7 CI: Periodic Controller Database Update (#3255)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2023-12-18 18:17:10 -05:00
ManDude 897e9c588b fix weird potential initialization bug with the music log (#3258) 2023-12-12 23:34:14 +00:00
water111 f17427bc26 [jak2] Fix unicode issue with GAME.CGO load (#3254)
Fix for https://github.com/open-goal/jak-project/issues/3244
2023-12-09 18:11:24 -05:00
Ziemas 168afa0e2e 989snd: sound bank loading overhaul (#3185) 2023-12-07 20:22:54 -05:00
Hat Kid 9b6f16f561 jak2: 90 fps menu option (#3245)
Closes #3223
2023-12-03 21:32:21 +01:00
ManDude 1808596679 save & load game territory setting (#3243) 2023-12-03 18:19:38 +00:00
ManDude 94b984326f [jak2] add game territory menu option (#3242) 2023-12-03 16:16:05 +00:00
ManDude 2795d3aa67 [jak2] fix health bar color fading (#3241)
Fixes #3237
2023-12-03 09:42:01 +00:00
ManDude be6a6dead4 [jak2] fix use-after-free bug in nav enemies (#3240)
Fixes #3153
2023-12-03 09:24:34 +00:00
ManDude 974f5931de [jak2] add resolutions menu (#3238) 2023-12-03 08:11:18 +00:00
Brent Hickey e119a66788 [jak2] Support STICK_DEADZONE (#3239)
fixes #3235
2023-12-03 08:11:10 +00:00
SuperSamusandMartino Fontana 37069e2f8e [jak2] Fix "Select controller" (#3191)
Co-authored-by: Martino Fontana <[email protected]>
2023-12-02 15:20:26 -05:00
Hat KidandTyler Wilding dfa6622544 jak2: add vehicle hijack lines PC cheat (#3205)
Co-authored-by: Tyler Wilding <[email protected]>
2023-12-02 15:17:54 -05:00
Luminar Light a3af37989b Allow replacing all instances of a texture with one texture (#3234)
There are art groups that are present in multiple levels, and that means
that also their textures are present in multiple levels. With texture
replacement, currently we need to make replacements for all instances if
we want it replaced everywhere, but this is not ideal, especially when
you make changes to your replacement texture and now you have to put it
in each folder again.

I added a way to replace all instances of a texture, by letting
texture-replacer people put their replacements into an '_all' folder. I
set up the logic in such a way that if you have a replacement for the
texture in its corresponding folder, it will take priority over a
replacement that you placed into the '_all' folder.

I personally found this very useful for replacing guard textures. The
guards appear in a lot of levels. But ideally you want them to look the
same everywhere. And that is why I looked into this and made a PR.

Oh and I changed what is printed in the 'Replacing ' part because it was
printing the path to our replacement, which didn't look nicely when
several textures got replaced by the same replacement from the '_all'
folder. So now it will print the original texture's page and name, I
think this information is more useful anyway.
2023-12-02 12:17:47 -05:00
water111 a01182315b [jak2] Support per-proto shrub visibility (#3228)
Fixes the issue reported in
https://github.com/open-goal/jak-project/issues/3168,
https://github.com/open-goal/jak-project/issues/3189,
https://github.com/open-goal/jak-project/issues/3166,
https://github.com/open-goal/jak-project/issues/3152,
https://github.com/open-goal/jak-project/issues/3224 where a small part
of the pipes in the `strip-grenade` mission appear, but shouldn't.
2023-12-02 12:16:14 -05:00
ManDude e38fe70ac4 [jak2] split language and text language (#3233) 2023-11-29 23:28:53 +00:00
ManDude 956645bdb9 [jak2] adjust progress generic item sizes + add scrolling effect (#3231)
Makes most of the options larger to reduce the amount of dead space and
adds a smooth scrolling effect instead of having "pages".


![imagem](https://github.com/open-goal/jak-project/assets/7569514/fc483dea-226c-44ff-96e0-680e89a6df81)

Button remap menu has no scrolling. Fixes #2984
2023-11-29 18:27:02 +00:00
water111 72ee35ada2 [Loader] Unload less stuff per frame (#3227)
This should avoid the stuttering due to slow unloading on some drivers.

I also turned up the amount of stuff we load per frame since nobody has
been complaining about stutters there, but there has been a few cases of
levels loading in too slowly.

(this only changes graphics, not actual GOAL level load times).
2023-11-27 19:22:34 -05:00
OpenGOAL BotandOpenGOALBot 1400fef13e CI: Periodic Controller Database Update (#3226)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2023-11-27 18:00:08 -05:00
Tyler Wilding e6f9909101 i18n: add back crowdin config change (i think things got into a bad state) 2023-11-22 19:13:54 -05:00
Tyler Wilding 3c74434211 Update Crowdin configuration file 2023-11-22 19:11:16 -05:00
OpenGOAL BotandOpenGOALBot 1bbf616e3b CI: Periodic Controller Database Update (#3215)
Co-authored-by: OpenGOALBot <[email protected]>
2023-11-22 18:45:43 -05:00
Tyler Wilding b43a5d45d7 New Crowdin updates (#3218) 2023-11-22 18:45:08 -05:00
Tyler Wilding 7909119c64 i18n: fix filepath for jak 2 subtitle translation file (#3217) 2023-11-22 18:04:38 -05:00
ManDude a7f2776782 fix dark jak punch sound and some samos sounds (#3214) 2023-11-19 11:35:07 +00:00
ManDude 7f1bf1f892 [jak2] extended shadows hack + add/fix progress options (#3213) 2023-11-19 10:57:56 +00:00
Tyler Wilding 8258c409d5 New Crowdin updates (#3211) 2023-11-18 14:52:49 -05:00
Radu13 74e90a84d5 Update subtitle_lines_it-IT.json (#3208) 2023-11-18 14:06:29 -05:00
014cbb04da i18n: transcribe missing english subtitles (#3199)
Co-authored-by: Hat Kid <[email protected]>
Co-authored-by: ManDude <[email protected]>
Co-authored-by: blahpy <[email protected]>
2023-11-18 14:06:01 -05:00
ZiemasandHat Kid cca829aecd j2: fix enemy-method-135 (#3206)
Co-authored-by: Hat Kid <[email protected]>
2023-11-15 22:29:51 +01:00
RoyalForgotten 6abfc9d129 Update subtitle_lines_fr-FR.json (#3201) 2023-11-13 20:01:09 -05:00
OpenGOAL BotandOpenGOALBot 22bb01205e CI: Periodic Controller Database Update (#3200)
Co-authored-by: OpenGOALBot <[email protected]>
2023-11-13 15:59:26 -05:00
ManDude 0b1639c8c0 fix forest youngsamos crash when he runs out of health (#3197)
Thought this may have been a regression but apparently we never patched
this one.

Fixes #3196
2023-11-12 18:35:58 +00:00
ManDude 42f995b059 reduce glow renderer vram usage + raise glow sprite limit (#3194)
Makes the glow sprite renderer flush when full capacity is reached,
instead of at the end. Also allows us to reduce the textures used for it
(finally). Worst case scenario there's 4-5 flushes per frame.

Fixes incessant flickering in the dig.
2023-11-12 00:11:50 +00:00
Tyler Wilding 2b1876f862 formatter: Add support for a few common functions and fix an LSP startup issue (#3190) 2023-11-11 17:51:55 -05:00
ManDude 288624b90f fix mistakes in projectiles.gc (#3187)
Fixes #3184
2023-11-11 11:40:29 +00:00
Tyler Wilding 55611169ee g/j2: Speedrunner mode improvements for Jak 2 (#3182) 2023-11-10 18:25:55 -05:00
ManDude a150e59e38 automatically re-enable autosave safely when starting a speedrun (#3181) 2023-11-09 17:48:47 +00:00
Hat Kid b2453fe23b jak2: add missing pc options to progress menu (#3167) 2023-11-09 17:24:50 +01:00
Hat Kid a80b4f1b97 jak2: some high fps fixes (#3177) 2023-11-08 23:34:58 +01:00
Hat Kid 4e3d35e97c jak2: fix discord rpc mission images in retail (#3176) 2023-11-07 00:39:58 +01:00
ManDude 299a25b997 [jak2] better handling of invalid formats (#3171)
see #3143
2023-11-06 22:05:51 +00:00
ManDude 8179d0aee3 [jak2] Localize board trick names (#3161)
It also looks like this now which I think is a bit cleaner:


![image](https://github.com/open-goal/jak-project/assets/7569514/0bed1d82-3407-4ca5-be1f-712ca8f96bcc)
2023-11-06 04:14:28 +00:00
Tyler Wilding c415d28270 cmake: use static OpenSSL libraries on linux (#3162) 2023-11-05 16:30:25 -05:00
Tyler Wilding f44f4dbe49 g/j2: use the large font for the jetboard trick combo display (#3157) 2023-11-05 01:32:01 -04:00
Tyler Wilding 595bc83105 g/j2: Add ending condition checks to the autosplitter struct (#3155) 2023-11-04 22:16:48 -04:00
water111 6067c25f67 [jak2] Pass 0x01 through format (#3143) 2023-11-04 20:02:28 -04:00
water111 2a7016be6a [jak2] Fix palace rotation at high fps (#3147) 2023-11-04 20:02:13 -04:00
ManDude 8d1fec34b4 allow per-file override of type-to-artgroup map + use correct divide by zero handler in civilian.gc (#3148) 2023-11-04 18:25:13 +00:00
Tyler Wilding de4b3d272d New Crowdin updates (#3146) 2023-11-04 13:58:38 -04:00
water111 ae4ee9c0c6 [jak2] Try to fix glow again (#3144)
Maybe fix https://github.com/open-goal/jak-project/issues/3065?
2023-11-04 13:30:22 -04:00
Tyler Wilding 959921e988 i18n: Add jak 2 custom text to Crowdin (#3141) 2023-11-04 13:14:14 -04:00
water111 85725401d2 [jak2] Hopefully improve sky performance (#3130)
Switches the slime look up table to be a texture, since I guess intel
drivers are terrible and putting the array in the shader makes it
extremely slow.

Also, a few minor changes:
- removed art-groups from the test-zone levels since this causes the
compiler to re-decompile the game, and makes the launcher slower. (left
it in commented out)
- Switched `decompile_code` to false by default in jak 2, in case people
run the decompiler and don't want to wait forever
- Fixed build warnings
2023-11-04 09:33:16 -04:00
ManDude adada4751d [jak2]do not force UK english on PAL (#3142) 2023-11-04 11:17:40 +00:00
BlqncandTyler Wilding d96f0524ea Jak 2 French Game Text (#3138)
Co-authored-by: Tyler Wilding <[email protected]>
2023-11-03 22:20:16 -04:00
Xavier Siguero Mora 43e0f11be5 Translated Jak 2 Game Texts to Spanish (#3139) 2023-11-03 22:02:29 -04:00
ZedB0T c1e81e1b4b Add fallback text functionality to Jak 2 (#3128) 2023-11-03 21:45:10 -04:00
Tyler Wilding cca2897e3e g/jak2: disable speech volume when starting a new speedrun (#3132) 2023-11-02 23:35:52 -04:00
Tyler Wilding fff3a85531 g/jak2: allow L1 + R1 + Start to open speedrun menu as well (#3131) 2023-11-02 20:42:51 -04:00
Tyler Wilding a0e998afb3 ci: properly statically link on macOS (#3127) 2023-11-02 19:57:34 -04:00
Tyler Wilding 385b8e6e6a docs: Re-order root README a bit and add new link to new tutorial (#3119) 2023-11-02 13:19:11 -04:00
Tyler Wilding 4fbc9258a1 ci/windows: stop Strawberry perl from changing resulting built artifacts in CI (#3114) 2023-11-02 02:29:19 -04:00
Tyler Wilding ae35b546e4 New Crowdin updates (#3113) 2023-11-02 01:03:15 -04:00
ManDude a949dada93 rename joint node and art element macros (#3111) 2023-11-01 23:16:00 +00:00
ManDude 5587593204 fps selection fixes i missed (#3109) 2023-10-30 19:55:16 +00:00
ManDude 99cb51ff57 [jak2] simplify fps disclaimer (#3108) 2023-10-30 18:17:11 +00:00
ManDudeandHat Kid cd68cb671e deftype and defmethod syntax major changes (#3094)
Major change to how `deftype` shows up in our code:
- the decompiler will no longer emit the `offset-assert`,
`method-count-assert`, `size-assert` and `flag-assert` parameters. There
are extremely few cases where having this in the decompiled code is
helpful, as the types there come from `all-types` which already has
those parameters. This also doesn't break type consistency because:
  - the asserts aren't compared.
- the first step of the test uses `all-types`, which has the asserts,
which will throw an error if they're bad.
- the decompiler won't emit the `heap-base` parameter unless necessary
now.
- the decompiler will try its hardest to turn a fixed-offset field into
an `overlay-at` field. It falls back to the old offset if all else
fails.
- `overlay-at` now supports field "dereferencing" to specify the offset
that's within a field that's a structure, e.g.:
```lisp
(deftype foobar (structure)
  ((vec    vector  :inline)
   (flags  int32   :overlay-at (-> vec w))
   )
  )
```
in this structure, the offset of `flags` will be 12 because that is the
final offset of `vec`'s `w` field within this structure.
- **removed ID from all method declarations.** IDs are only ever
automatically assigned now. Fixes #3068.
- added an `:overlay` parameter to method declarations, in order to
declare a new method that goes on top of a previously-defined method.
Syntax is `:overlay <method-name>`. Please do not ever use this.
- added `state-methods` list parameter. This lets you quickly specify a
list of states to be put in the method table. Same syntax as the
`states` list parameter. The decompiler will try to put as many states
in this as it can without messing with the method ID order.

Also changes `defmethod` to make the first type definition (before the
arguments) optional. The type can now be inferred from the first
argument. Fixes #3093.

---------

Co-authored-by: Hat Kid <[email protected]>
2023-10-30 03:20:02 +00:00
ManDude 09536c68ac [compiler] asm-only disasm output + fix spacing bug (#3104) 2023-10-29 10:16:14 +00:00
Matt Dallmeyer 7c74b0c999 Fix starting continue point for Hub 2/3 category extensions (#3103) 2023-10-29 02:17:32 +01:00
OpenGOAL BotandOpenGOALBot 2ce7b36568 CI: Periodic Controller Database Update (#3101)
Co-authored-by: OpenGOALBot <[email protected]>
2023-10-24 18:43:00 -04:00
Hat Kidandwater c7c615a043 custom levels: refactor level building code and jak 2 support (#3090)
Co-authored-by: water <[email protected]>
2023-10-21 06:07:43 +02:00
Tyler Wilding dccc3da1b3 formatter: rewrite and refactor, address more edge-cases, begin documenting my work (#3096) 2023-10-20 21:24:31 -04:00
Tyler Wilding 94603bce49 ci: Workaround CMake/Perl regression in recent windows-2022 images (#3097) 2023-10-20 21:06:12 -04:00
jabermony cdf13a92ec Add label_types file merge for PAL version (#3086) 2023-10-20 01:40:24 -04:00
OpenGOAL BotandOpenGOALBot fcebf977f8 CI: Periodic Controller Database Update (#3091)
Co-authored-by: OpenGOALBot <[email protected]>
2023-10-20 01:29:29 -04:00
Hat Kid 2c825ab7bf jak2: add warning text when changing frame rate for the first time (#3092) 2023-10-17 18:29:02 +02:00
jabermony 95dca764fc Fix build failure at llvm-rc on windows due to codepage error on zydis (#3088)
This fix is for the following error when building with llvm on windows

```
[build] llvm-rc: Error in VERSIONINFO statement (ID 1): 
[proc] The command: "C:\Program Files\CMake\bin\cmake.exe" --build C:/.../git/jak-project-test/out/build/Release --parallel 8 exited with code: 1
[build] Non-ASCII 8-bit codepoint (´┐¢) can't be interpreted in the current codepage
[build] ninja: build stopped: subcommand failed.
```

It's caused by llvm-rc not handling non 8-bit characters.
The same issue is discussed in the curl project here
https://github.com/curl/curl/issues/7765

This commit copies the fix from curl, replacing '©' with '(C)'.
2023-10-15 10:38:14 -04:00
Hat Kid e6b73f1058 custom levels: support for packing textures (#3089) 2023-10-15 16:36:14 +02:00
water111 ec23e6c5d9 [glb export] Export bones. (#3087)
![image](https://github.com/open-goal/jak-project/assets/48171810/0f26e77b-af68-4450-882e-762a501bdef4)
2023-10-14 16:49:23 -04:00
ManDude ae45037489 fix *jak1-full-game* being flipped (#3085) 2023-10-13 03:41:55 +01:00
Tyler Wilding 60eaac8051 decompiler: add texture merging feature (#3083) 2023-10-12 19:02:36 -04:00
Hat Kid 598ba1aaa3 jak3: add missing files and implement pexcw (#3084)
Some files were in the `banned_objects` list and were thus excluded from
the `all_objs` file.

Also implements the `pexcw` instruction which is only used in `hfrag`
code.
2023-10-12 18:07:37 -04:00
AloqasandTyler Wilding ce1c2eb7c2 [jak1] Finnish base game strings (#3058)
Finnish translations for the remaining UI texts

---------

Co-authored-by: Tyler Wilding <[email protected]>
2023-10-12 18:05:40 -04:00
Tyler Wilding 8b3b96761d g/j2: Integrate highscores with Speedrun.com/JakSpeedruns.com when speedrunner mode is enabled (#3037) 2023-10-11 20:43:55 -04:00
water111 97e04a7612 [jak2] Fix collision renderer extract (#3081)
Fixes missing collision geometry reported in
https://github.com/open-goal/jak-project/issues/3011

The issue happens when there are 256 polygons. In this case `num-polys`
is 0 (it's a u8). There are actual cases where there are 0 polygons, so
we have to do a more complicated check to get the real count. I should
have done this in the first place, but it seemed to work...
2023-10-11 19:32:25 -04:00
Hat Kid 5be46c9852 decompiler: allow jak 3 texture and model extraction (#3080)
Added some hacks and stubs to allow extracting textures and models.
2023-10-11 19:32:12 -04:00
Hat Kid 6285c61662 decompiler: fix for v5 art group info dump, update taskfile for jak 3 (#3077) 2023-10-11 10:17:46 +02:00
water111 cfce5e5916 [decompiler] Support v5 data file link data (#3076)
Fix the implementation of `link_v5` so it works on "data" files for jak
3.
2023-10-10 21:56:03 -04:00
Hat Kid 5a6aab4fab jak3: add goal_src skeleton (#3069) 2023-10-10 15:41:05 +02:00
Tyler Wilding 2adf440e3e github: add issue template for jak 2 (#3073) 2023-10-09 19:41:41 -04:00
ManDude 27980218aa [jak2] fix minor original game visual bugs (#3072)
Fixes #2994 the underport and consite icons being green (same color as
the goal, likely copy-pasta).

Fixes the hundredths timer in the race timer actually being a 60ths
timer.
2023-10-09 22:39:35 +01:00
ManDude 884f0ef6e3 [glow] potentially fix bad glow texture (#3071)
Might fix #3065 

fixes #3070
2023-10-09 14:16:13 +01:00
Hat Kidandwater bf961a36f4 decompiler: some hacks to allow running decompiler on jak 3 v5 code files, improve all-types generation (#2526)
Co-authored-by: water <[email protected]>
2023-10-07 22:14:12 +02:00
water111 5f8415320b [jak2] new glow fix (#3067)
Fix a typo in the shader. (fixes
https://github.com/open-goal/jak-project/issues/3045, and fixes fadeout
when glows move offscreen on the bottom).

Also, try a different format for the depth blit, in an attempt to fix
this issue https://github.com/open-goal/jak-project/issues/3065.
2023-10-07 12:37:06 -04:00
water111 395c98db19 [goalc] Cleaned up speedups (#3066)
Started at 349,880,038 allocations and 42s

- Switched to making `Symbol` in GOOS be a "fixed type", just a wrapper
around a `const char*` pointing to the string in the symbol table. This
is a step toward making a lot of things better, but by itself not a huge
improvement. Some things may be worse due to more temp `std::string`
allocations, but one day all these can be removed. On linux it saved
allocations (347,685,429), and saved a second or two (41 s).
- cache `#t` and `#f` in interpreter, better lookup for special
forms/builtins (hashtable of pointers instead of strings, vector for the
small special form list). Dropped time to 38s.
- special-case in quasiquote when splicing is the last thing in a list.
Allocation dropped to 340,603,082
- custom hash table for environment lookups (lexical vars). Dropped to
36s and 314,637,194
- less allocation in `read_list` 311,613,616. Time about the same.
- `let` and `let*` in Interpreter.cpp 191,988,083, time down to 28s.
2023-10-07 10:48:17 -04:00
water111andManDude af6f489657 [jak2] Set up extractor (#3042)
This sets up the extractor for jak 2. I was expecting that I'd have to
make some more significant changes to the decompiler/compiler path
stuff, but this was not the case!

The only real change is that you can now provide multiple ISO hashes for
an entry in `ISOMetadata`. This is needed for the two different NTSC
versions, which have the same configs, serials, and ELF hashes, but
slightly different contents.

I also didn't add the korean version because I don't have the info for
it.

---------

Co-authored-by: ManDude <[email protected]>
2023-10-06 23:09:09 -04:00
Hat Kid 3c27b3942b decompiler: better automatic detection of art groups and joint-node-index macro detection (#3061) 2023-10-06 16:42:16 +02:00
OpenGOAL BotandOpenGOALBot 2d480a6df6 CI: Periodic Controller Database Update (#3060)
Co-authored-by: OpenGOALBot <[email protected]>
2023-10-03 13:55:31 -04:00
ManDude 1338fed9c9 fix eco pickup time bug (#3056) 2023-10-02 01:22:05 +01:00
Tyler Wilding 42e3b7f89c g/j2: don't force auto-save on in jak 2 when starting a speedrun (#3048) 2023-09-30 23:40:00 -04:00
dependabot[bot] 4731ae6e22 Bump actions/checkout from 3 to 4 (#3047)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-30 23:36:22 -04:00
ManDude dfeb88b35d [jak2] fully implement *user* (#3046)
Fixes #1918
2023-10-01 04:28:30 +01:00
Matt Dallmeyer d149838485 fix draw-string-xy-scaled cropping (#3041)
fixes #3038 


https://github.com/open-goal/jak-project/assets/2515356/5b7a490f-e1fb-4a12-a3d9-b576a2c1d574
2023-10-01 00:17:50 +01:00
ManDude e130244271 [jak2] scalable debug font + fix debug menu widescreen bugs (#3044)
also hides empty (no commands) regions from the viewers by default now.
2023-09-30 21:19:47 +01:00
water111 0e31a9c407 [decompiler] Handle find-parent-method (#3018)
This change adds a few new features:
- Decompiler automatically knows the type of `find-parent-method` use in
jak 1 and jak2 when used in a method or virtual state handler.
- Decompiler inserts a call to `call-parent-method` or
`find-parent-state`
- Removed most casts related to these functions

There are still a few minor issues around this:
- There are still some casts needed when using `post` methods, as `post`
is just a `function`, and needs a cast to `(function none)` or similar.
It didn't seem easy to change the type of `post`, so I'm not going to
worry about it for this PR. It only shows up in like 3 places in jak 2.
(and 0 in jak 1)
- If "call the handler if it's not #f" logic should probably be another
macro.

Fixes #805
2023-09-30 11:06:09 -04:00
Matt Dallmeyer 0f3782128f Remove dupe line in discord-rpc .clang-format (#3039) 2023-09-30 00:10:51 +01:00
ManDude 15fb677f5f [jak2] un-mips2c draw-string (#3040)
It's not an asm function.
2023-09-30 00:07:55 +01:00
ManDude 1f4044b9ff Jak 2 controller LED implementation (#3035)
Adds controller LED features to Jak 2:
- progressive flickering denoting health
- copies tomb simon says puzzle colors
- unique colors for each gun
- orange color for being indax
- yellow color for being in mech
- purple color for being darkjak
- blue color for being in board
- red flash when wanted.

May add more features later?

Also did some minor clean-up on some types.
2023-09-28 02:47:09 +01:00
ManDude 170cbd7e6c misc low hanging fruit fixes (#3034)
Fixes #2235 
Fixes #2236 
Fixes #2963 
Fixes #3027
2023-09-27 00:59:07 +01:00
ManDude a662150327 [decompiler] do not use time-elapsed? on unsigned comps (#3031) 2023-09-26 18:48:13 +01:00
Hat Kid fc43870d85 decompiler: obj -> this, set-time! and time-elapsed? macros (#3026)
This renames the method object in `defmethod`s to `this` and adds
detection for the `set-time!` and `time-elapsed?` macros.

Definitely my biggest PR yet...
2023-09-26 15:17:00 +01:00
ManDude 9b60afe6e6 [compiler] fix compile_condition not attempting macro expansion (#3030)
Ancient bug! Resulted in a 1%-2% decrease in code object file size (and
more importantly the asm is more readable).

Fixes #3029
2023-09-25 23:49:12 +01:00
OpenGOAL BotandOpenGOALBot c695ef1393 CI: Periodic Controller Database Update (#3028)
Co-authored-by: OpenGOALBot <[email protected]>
2023-09-25 17:44:21 -04:00
ManDude 1ff55d5015 fix (font-flags left) name + fix right flag not reflecting in debug text box (#3020)
Fixes #3016 
Fixes #3017
2023-09-24 03:00:09 +01:00
Tyler Wilding 592c5f88f3 New Crowdin updates (#3025) 2023-09-23 21:47:59 -04:00
Tyler Wilding 35c0ca235d scripts: remove unused code_retention script code (#3019) 2023-09-23 16:05:29 -04:00
Tyler Wilding 10910400fa g/j2: Fill out game options menu (#3003) 2023-09-23 15:08:13 -04:00
ManDude 4871f5dfc7 [jak2] also allow analog for play select fast scroll (#3015) 2023-09-23 16:46:21 +01:00
Tyler Wilding 2e43e18e1d g/j2: speed up level-select menu scrolling (#3013) 2023-09-23 09:54:18 -04:00
ManDude ff924f6b00 improve decomp of state handlers and art groups (#3014)
- state handlers that are not inlined lambdas have smarter type
checking, getting rid of 99.9% of the casts emitted (they were not
useful)
- art groups were not being properly linked to their "master" groups.
- `max` in `ja` in Jak 2 was not being detected.

Another huge PR...
2023-09-23 09:53:50 -04:00
OpenGOAL BotandOpenGOALBot f86be3df62 CI: Periodic Controller Database Update (#3006)
Co-authored-by: OpenGOALBot <[email protected]>
2023-09-22 23:06:59 -04:00
ManDude 61c4fc4b91 [jak2] fully implement collide mesh renderer (#3010)
Fixes #2983
2023-09-22 15:50:16 +01:00
ManDude fe491c2b5e [opengoal] make none a child of object (#3001)
Previously, `object` and `none` were both top-level types. This made
decompilation rather messy as they have no LCA and resulted in a lot of
variables coming out as type `none` which is very very wrong and
additionally there were plenty of casts to `object`. This changes it so
`none` becomes a child of `object` (it is still represented by
`NullType` which remains unusable in compilation).

This change makes `object` the sole top-level type, and the type that
can represent *any* GOAL object. I believe this matches the original
GOAL built-in type structure. A function that has a return type of
`object` can now return an integer or a `none` at the same time.
However, keep in mind that the return value of `(none)` is still
undefined, just as before. This also makes a cast to `object`
meaningless in 90% of the situations it showed up in (as every single
thing is already an `object`) and the decompiler will no longer emit
them. Casts to `none` are also reduced. Yay!

Additionally, state handlers also don't get the final `(none)` printed
out anymore. The return type of a state handler is completely
meaningless outside the event handler (which is return type `object`
anyway) so there are no limitations on what the last form needs to be. I
did this instead of making them return `object` to trick the decompiler
into not trying to output a variable to be used as a return value
(internally, in the decompiler they still have return type `none`, but
they have `object` elsewhere).

Fixes #1703 
Fixes #830 
Fixes #928
2023-09-22 10:54:49 +01:00
Hat Kid 697b07abd5 decomp: fix some enemy decomp (#3008) 2023-09-20 11:46:48 +02:00
Hat Kid cbbbd661d9 [jak2] ckernel: implement loado and load_and_link (#3005) 2023-09-18 12:21:18 +02:00
Tyler Wilding 049a8057a8 ci: separate lint checks into a required and optional workflow (#3002) 2023-09-17 21:47:26 -04:00
Hat Kid bfb03d4934 goalc: add macro-expand form (#3000) 2023-09-17 22:55:25 +02:00
Hat Kid 36213aaedb jak2: fix metalkor regression (#2999) 2023-09-17 07:57:25 +02:00
rafalekkB a7056c2704 Update game_base_text_pl-PL.json (#2997) 2023-09-16 23:23:54 -04:00
Tyler Wilding d701a54c43 g/j2: Implement speedrunner mode in jak 2 (#2976) 2023-09-16 23:23:29 -04:00
Hat Kid d784561d43 gsrc: add more og:preserve-this comments (#2996) 2023-09-16 13:39:51 +02:00
ManDude 6352ef2a4d [jak2] fix task-arrow-spawn decomp (#2995) 2023-09-15 23:09:38 +01:00
ManDude 87be9ebd14 [decompiler] decomp jak2 static-attack-info (#2992)
Fixes #2993
2023-09-15 19:32:57 +01:00
ManDude a03413d4ca [jak2] placeholder subtitle files (#2986)
fixes #2985
2023-09-14 14:27:46 +01:00
Tyler Wilding 3252136c1f CI: check for removed goal_src code that we want or need to perserve (#2987) 2023-09-14 01:31:08 -04:00
rafalekkB ed6782d11b Polish translation for Jak 1 (#2961) 2023-09-11 22:05:42 -04:00
OpenGOAL BotandOpenGOALBot 6ed2bda933 CI: Periodic Controller Database Update (#2980)
Co-authored-by: OpenGOALBot <[email protected]>
2023-09-11 21:59:33 -04:00
Tyler Wilding 0a45f50522 g/j1: resolve memory leak around display/input dynamic strings from C++ (#2979) 2023-09-11 23:09:42 +01:00
water111 9b9fe7a7af [jak 2] Export the collision mesh (#2977)
![image](https://github.com/open-goal/jak-project/assets/48171810/266d014b-f6c5-440f-9c3e-ab7c5eafe771)
2023-09-10 17:32:18 -04:00
Tyler WildingandHat Kid 1bd30bce84 g/j2: revert signature changes to cam-setting-data, fix camera regressions (#2975)
Co-authored-by: Hat Kid <[email protected]>
2023-09-10 16:15:22 -04:00
Hat Kidandwater 49e798f88c jak2: macro detection for launch-particles and seconds-per-frame, add og:preserve-this comments for manual patches (#2974)
This PR adds detection of the `launch-particles` and `seconds-per-frame`
macros to the decompiler, removing a lot of bloat and hiding many
process register uses.

I also added `og:preserve-this` comments to as many manual patches and
comments as I could, which will soon be used in conjunction with CI to
hopefully catch any regressions in future big decomp update PRs.

I have some concerns about the `launch-particles` macro (more details in
`sparticle-launcher.gc`) , but thus far, I have not seen anything break
yet.

---------

Co-authored-by: water <[email protected]>
2023-09-10 11:48:56 -04:00
water111 74250a22f7 Save entities to JSON, and make custom level building a little faster (#2973)
This will create a folder like `decompiler_out/jak1/entities` and save a
JSON file per level with all the actors.

Also, it should hopefully make custom level building a little faster.
2023-09-09 17:06:39 -04:00
Tyler Wilding 8154c4659d g/j2: Start adding game options to jak 2's menu (#2968) 2023-09-09 15:58:57 -04:00
water111 ec058221b5 [jak1] Fix duplicated tie extract (#2972)
Fix a bug where meshes are extracted too many times.
2023-09-09 11:56:18 -04:00
water111 6d46a22d21 [jak2] Fix hover-formation decomp (#2971)
I think this is very likely to fix
https://github.com/open-goal/jak-project/issues/2970

We had somebody report a stacktrace from the debugger, and it was
immediately after calling `gen-perms`.
I found that `gen-perms` writes past the end of a stack array during
this mission, and at the same time as the reported freezes.

I was unable to recreate the original freeze after making this change.
2023-09-09 11:18:21 -04:00
Hat Kid 572efbf9cb jak2: add frame rate option to graphics menu (#2962)
This PR adds a frame rate option to the graphics menu for some of the
most common refresh rates.

Jak 2 has much better support for variable frame rates than Jak 1 out of
the box, but there are still some edge cases, most prominently the fact
that sprites are still limited to the 300 tick system, which is most
noticeable on glow sprites. For this, I abused the glow boost debug
setting to scale the glow based on the frame rate.

While testing, I noticed two other cases that I have also patched,
there's likely to be many more that are yet to be found, but aside from
that, the game is playable as normal.



https://github.com/open-goal/jak-project/assets/6624576/ad4db24f-cd27-4237-a155-0db7008160f3
2023-09-09 10:59:00 -04:00
Tyler Wilding 0a7caf1d10 decomp: handle dumping jak 2 VAG file assets (#2969)
There are potentially still some minor issues with the resulting files.
Some of them appear to have minor artifacts that playing through the
actual game do not -- but this is a much better starting point for
someone to iterate from if they are interested in improving things.
2023-09-09 10:33:41 -04:00
Tyler Wilding d048f420a0 g/j2: Some more work on the SQL editor - dump and seed light data (#2954) 2023-09-08 21:21:02 -04:00
6b4600355b Update subtitle_en-US.json (#2763)
Co-authored-by: ManDude <[email protected]>
Co-authored-by: Tyler Wilding <[email protected]>
2023-09-08 20:54:55 -04:00
Luminar Light 2d8b65accf entity-debug: Show path and volume data. (#2942) 2023-09-08 20:44:58 -04:00
OpenGOAL BotandOpenGOALBot 37e2343a1c CI: Periodic Controller Database Update (#2926)
Co-authored-by: OpenGOALBot <[email protected]>
2023-09-06 00:41:07 -04:00
water111 46c634686c [gltf export] Export TIE wind models (#2960)
Export models with "wind".  The levels with wind models are:
firecanyon (9), beach (5), village1 (7), lavatube (2).

Sometimes a single object is made up of multiple models - for example
the tree in sandover is actually several meshes.
2023-09-04 10:29:10 -04:00
Tyler Wilding 07d97bce8c goalc: use iso_data build_info to inform custom level build process (#2959) 2023-09-03 18:17:35 -04:00
ManDude 46bdd109dd rewrite sp-get-particle and fix some jak 2 region decomp (#2955) 2023-09-03 22:25:59 +01:00
ZedB0T bb530a5162 Make cloud_lookup return float (#2958) 2023-09-03 17:55:29 +01:00
water111 5a80be213c [sprite] Adjust allocation randomization (#2953)
This tries to match the original behavior of the sprite allocation
"randomness", which should reduce the number of very empty sprite blocks
sent to C++.
2023-09-02 09:39:19 -04:00
ManDude 7475e356b5 [jak2] higher resolution cloud textures (#2951)
Adds a new "hires" sky texture animation that makes the sky use 512x512
textures instead of 128x128. The clouds have higher detail, are slightly
more noisy, and are considerably less blocky. There is also a less
noticeable "dot crawl" effect.


![image](https://cdn.discordapp.com/attachments/995787558816595968/1146960820320878643/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1146960819750449264/image.png)
2023-09-02 09:26:36 -04:00
ManDude d96dce2714 [jak2] fix bug in outro-port script (#2952) 2023-09-01 17:10:59 +01:00
ManDude 970af8d100 [sprite3] fix max sprite number being wrong (#2949)
I don't think this fixes anything, but the number was wrong so might as
well fix it.
2023-08-31 02:38:19 +01:00
ManDude 6e8b0e57c7 [extractor] fix territory being set to wrong value (#2946)
Also fixes a minor issue where the JP sound bank wouldn't work (Jak 1).

Fixes #2793
2023-08-30 18:36:10 +01:00
ManDude f85ed7457d Placeholder strings for future Jak 2 features + minor subtitle editor fixes (#2943) 2023-08-30 16:58:06 +01:00
Tyler Wilding 34ed88376c New Crowdin updates (#2945) 2023-08-29 22:28:25 -04:00
Tyler Wilding 6e0d3d681c ci: macOS build with big sur to increase compatibility (#2944) 2023-08-29 21:12:27 -04:00
ManDude 8bb5fa7f04 various subtitle editor fixes (#2941)
- fix speaker names and time frames being uneditable in Jak 1
- added toggle to auto-selected a newly created scene as current
- changed the subtitle summary format slightly.
- current scene's name now appears in the UI
2023-08-28 17:51:09 +01:00
ManDude de086ff64b [jak2] fix bugs with incorrect music playing sometimes (#2938)
- fixes flava and mode not being correct after a new music starts
playback by setting them every frame (there is at most 1 frame where
it's wrong).
- fixes city pursuit theme not playing if the city alarm was triggered
while the music wasn't playing yet.
2023-08-28 00:23:17 +01:00
Hat Kid dc7c71c07d custom levels: add support for packing models and textures into the FR3 file (#2936) 2023-08-27 22:34:46 +02:00
Hat Kid 74b9ad5a05 ckernel: fix file paths for art groups and tpages (#2932) 2023-08-25 18:33:26 +02:00
Tyler Wilding 5538993ff2 g/j1: add support for missing polish alphabet characters (#2931) 2023-08-24 17:57:54 -04:00
ManDude 329f13b610 [jak2] minimap improvements (#2929)
Smoothens minimap icon motion and fixes the target icon being squished
depending on the angle it's facing.
2023-08-22 18:14:03 +01:00
ManDude 04269ffa86 [jak2] fill in a lot of flags for decomp + mouse macros (#2927)
Also changed the default type of enums to `int64` (same as `int`).
2023-08-22 16:39:52 +01:00
ManDude 16af1837d1 [jak2] a few more subtitles + L1/R1 to move *much* faster through debug menu (#2925) 2023-08-21 00:19:54 +01:00
water111 1e6fdbee6f [jak2] Fix depth testing issues on glow sprites (#2923)
https://github.com/open-goal/jak-project/assets/48171810/0d3064f9-3f27-4be1-b6a4-55fdfb681313

Fixes https://github.com/open-goal/jak-project/issues/2328
2023-08-20 11:51:49 -04:00
water111 5de738aacb [jak2] Toxic Slime texture animations (#2922)
https://github.com/open-goal/jak-project/assets/48171810/85e68808-09bf-4f74-a16a-6310e2b81cd3
2023-08-19 14:22:30 -04:00
water111 3b29da919b [jak 2] Clouds V2, Clean up texture animator (#2921)
Some general improvements for the texture animator:
- Clouds are special cased, saving about 1 ms per frame
- Adjusting the amount of clouds now actually works.
- Fixed an issue with the brightness of clouds, and the way that they
fade out around the edges.
2023-08-19 12:50:59 -04:00
Tyler WildingandManDude 66e48195cb jak1: Consolidate art-elts into a single file as is done in jak 2 (#2887)
Fixes #2167

Reduces test flakiness if ran on multiple threads and gets rid of a few
hundred files from the source tree

I believe this also makes #1434 irrelevant and it can be closed.

---------

Co-authored-by: ManDude <[email protected]>
2023-08-18 11:07:24 -04:00
water111 959dffa427 [jak2] fix a few silly texture bugs (#2917)
Fix an issue where the commit sha would not use the right blending mode
if `draw-raw-image` is running at the same time.
Fix an issue where japanese subtitles would accidentally overwrite other
textures, leading to random textures missing. (in particular, glows
would disappear after watching a cutscene with the subtitles on)
2023-08-18 11:04:31 -04:00
ManDude d6e08df094 [jak2] widescreen fix for splash/jp subtitles (#2916) 2023-08-18 03:25:21 +01:00
water111 eeb3292ff0 [jak2] Support draw-raw-image (#2915)
![image](https://github.com/open-goal/jak-project/assets/48171810/9a94ea6e-99b8-4589-8210-86e63df31dd6)


![image](https://github.com/open-goal/jak-project/assets/48171810/e441225b-214c-46b9-ad01-0160590d30ba)
2023-08-17 20:23:17 -04:00
water111 b16daae310 [jak2] Support Japanese Subtitles (#2914)
![image](https://github.com/open-goal/jak-project/assets/48171810/7b5edd00-4193-47ab-92f6-8f270edbcafe)
2023-08-17 19:40:02 -04:00
water111 f3f8ccc9ff Fix alpha test > vs >= (minimap arrow fix) (#2913)
Fixes https://github.com/open-goal/jak-project/issues/2814

Previously we didn't handle `GREATER` vs `GEQUAL` correctly. I just left
this as a TODO by accident.


![image](https://github.com/open-goal/jak-project/assets/48171810/bfa7bd98-e40e-4850-af9c-ed6954c00958)
2023-08-17 19:13:15 -04:00
water111 5c00f1abe1 [jak2] fix glow sprite flickering (#2912)
oops, forgot to set `glDepthMask`, so sometimes it was enabled, and the
drawing for the clear was writing into the depth buffer.
Fixes https://github.com/open-goal/jak-project/issues/2735
2023-08-16 20:42:52 -04:00
water111 df1b0a341c handle texture of 0 in extract_tie (#2911)
Fixes texture difference shown in issue
https://github.com/open-goal/jak-project/issues/2908
2023-08-16 19:40:28 -04:00
water111 22c12c54ca [jak2] fix bug in direct in texture handler (#2910) 2023-08-16 18:31:40 -04:00
ManDude f5b771174e [jak2] small minor fixes (#2909)
- fix deci2 hang when closing the game in retail mode.
- change bigmap to always filter because the pixels look really ugly.
- don't start the game in fullscreen by default if we're debugging.
2023-08-16 18:31:27 -04:00
ManDude e7f2f2ad49 [jak2] music player cheat menu (#2900) 2023-08-16 17:53:38 +01:00
water111 bf7a2161b3 [jak2] fix bad blerc on objects with warp (#2907)
fixes the weird mirror offset stuff

![image](https://github.com/open-goal/jak-project/assets/48171810/9a36c0bd-7350-46d7-b14f-d2f876582b03)
2023-08-15 22:10:33 -04:00
water111 0c5e01643e [jak 2] bigmap, fix texture filtering on map icons (#2906)
![image](https://github.com/open-goal/jak-project/assets/48171810/4c285f31-c874-424a-8510-d181ba0f88d5)


![image](https://github.com/open-goal/jak-project/assets/48171810/6baa29ef-df92-435e-ad2f-9a42d56e6f17)

and the minimap has filtering now:

![image](https://github.com/open-goal/jak-project/assets/48171810/7cb2b0c9-5c86-426e-b028-dddcc3d649f7)

It's mostly implemented in C++ using the texture animator.
2023-08-15 21:53:06 -04:00
Ziemas 5343b5172e 989snd: implement SetVolPan for midi sounds (#2905)
Fixes #2820
2023-08-15 20:26:11 -04:00
Tyler Wilding 2c669b7f5a log: ensure the log/ directory exists (#2904) 2023-08-14 22:19:10 -04:00
water111 a0da98a367 [glow] fix clipping bug (#2902)
Now you can be blinded by the sun:

![image](https://github.com/open-goal/jak-project/assets/48171810/caf3903c-8333-4daa-89ba-ff83ca7d6b2f)
2023-08-14 18:52:25 -04:00
water111 ac52be1a6c [shrub] Fix bug with gs-prim settings (#2899)
Fix the bug described in
https://github.com/open-goal/jak-project/issues/2882 where some shrubs
are transparent when they shouldn't be. The problem was that we never
carefully looked at the settings in `gs-prim`, which has a bit to
enable/disable alpha blending entirely. Now it should be correct for
both jak 1 and jak 2. To see this change, you'll need to re-extract.

Also adds a setting to disable saving texture .pngs, to speed up
decompilation. I left it on for jak 1 (to avoid confusion for texture
swapping(, but off for jak 2 for now.
2023-08-13 16:06:59 -04:00
water111 7abfeb4aa7 [jak1] Fix texture-related custom level crash (#2898)
Force FR3 file name for custom levels to be uppercase, fixes the crash
described in
https://github.com/open-goal/jak-project/issues/2534
and 
https://github.com/open-goal/jak-project/issues/2897
2023-08-13 15:22:40 -04:00
Matt Dallmeyer 1b08b54443 Update test-zone.jsonc to use lowercase for nickname (#2896) 2023-08-12 20:31:10 +02:00
Tyler Wilding 8ce31e5a4c input: fix double press issue when assigning a bind (#2895) 2023-08-09 22:50:02 -04:00
Tyler Wilding 3923f68fae cmake: fix regression for building SDL statically (#2894) 2023-08-08 22:00:26 -04:00
Tyler Wilding a06a6c6416 cleanup our cmake and build warnings (#2876) 2023-08-08 20:53:16 -04:00
Tyler Wilding 59ac52721c log: don't recursively iterate when rotating log files (#2892) 2023-08-08 20:49:01 -04:00
Hat Kid 6061f39728 custom levels: fix crash when more than one ambient is present (#2891) 2023-08-08 20:24:13 +02:00
Tyler WildingandManDude 5d7aa7cea1 log: rotate log files with timestamps and add flag to disable ANSI colors (#2886)
Rotates the log files with a timestamp instead of copying all files and
incrementing an integer. Increases the amount of info you have when
looking at user's log files (ie. when looking at all the files, the file
creation dates are accurate).


![image](https://github.com/open-goal/jak-project/assets/13153231/61bcdf51-f0f6-4eee-b1e5-140aede5d19e)

Also simplifies the API for setting the log file, and `gk` logs are now
game specific with `jak1` or `jak2`. Which should be useful going
forward.

Lastly, added a flag to all CLIs to disable ansi colors for people that
want to do so. Though at the same time, there is finally a workaround in
jenkins to fix ANSI colors in the truncated log view -- so I'm not sure
why anyone would want to get rid of the color information. You can even
setup text editors to display the color info making log parsing much
easier. Fixes #1917

---------

Co-authored-by: ManDude <[email protected]>
2023-08-08 17:59:37 +01:00
ManDude 39d989cfcc [jak2] prepare scf-get-territory usage (#2890) 2023-08-08 17:21:29 +01:00
OpenGOAL BotandOpenGOALBot 988fdfb5b0 CI: Periodic Controller Database Update (#2889)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2023-08-07 19:21:40 +01:00
ManDude 7757483f01 [jak2] progress: make custom aspect ratio menu (#2888)
New menu for setting a custom aspect ratio.


![image](https://github.com/open-goal/jak-project/assets/7569514/33f81bc4-0219-4aba-b4ed-81394e4e4ceb)

![image](https://github.com/open-goal/jak-project/assets/7569514/9ddc3059-3ddf-4b35-afa5-11b9005e087c)

![image](https://github.com/open-goal/jak-project/assets/7569514/f3a16342-b38d-4082-ac18-1f82db349191)

![image](https://github.com/open-goal/jak-project/assets/7569514/69963cfe-2963-44f8-bde9-c0205c467d6c)
2023-08-07 16:32:28 +01:00
ManDude 9aa9b9d8e0 [jak2] get new cheats working (#2885) 2023-08-07 00:15:53 +01:00
Tyler Wilding a7cf66fda6 formatter: support formatting bindings, for example in a let (#2883) 2023-08-05 15:23:09 -04:00
Tyler Wilding bb8b39a5e8 jak1: start a new game correctly when speedrunner mode is enabled (#2873) 2023-08-02 19:44:54 -04:00
Tyler Wilding 5f4dfcdfb6 github: update issue templates, move general feature requests to discussions preferably (#2879) 2023-08-02 19:44:02 -04:00
Brent HickeyandTyler Wilding b88552a35d Basic hash table and jump table (#1837)
Co-authored-by: Tyler Wilding <[email protected]>
2023-08-01 17:09:14 -04:00
a8ae15139b Anim Tester X - Quality of Life improvements (#2682)
Co-authored-by: Tyler Wilding <[email protected]>
Co-authored-by: ManDude <[email protected]>
2023-08-01 17:06:20 -04:00
water111andManDude bdf28ec528 [goalc] Sign extend objects when loading them (#2863)
Co-authored-by: ManDude <[email protected]>
2023-07-31 21:49:20 -04:00
ManDude 0adbe42995 fix collision renderer filters not working (#2872)
fixes #2867
2023-07-31 11:13:44 +01:00
water111 426851720f fix texture anim shader on macOS (#2870) 2023-07-30 19:59:44 -04:00
Tyler Wilding 0ee20a255e New Crowdin updates (#2869) 2023-07-30 19:14:04 -04:00
Tyler Wilding 71225ec577 ci: strip binaries in their respective runners (#2868) 2023-07-30 18:50:24 -04:00
water111 a918e2d9de [gfx] Clean up background renderer matrices, fix "hole covers" (#2866)
The way we got/stored background matrices is a bit weird and full of
leftovers from the first attempts at porting renderers. This doesn't
work well with the Jak 2 "other camera" system where some stuff is
rendered with a different camera matrix.

This cleans most of it up. The exception is that the collide mesh
renderer and the additional sprite culling I added still need to peek at
some cached camera matrices.

This fixes the problem where etie uses the wrong matrices for "other
camera" levels. Now the "hole covers" go in the holes in the background
of the throne room.

![image](https://github.com/open-goal/jak-project/assets/48171810/73a88f7b-05d4-4e9c-bb34-5b45efffcb69)
2023-07-29 20:34:42 -04:00
water111 50c15f1a47 [jak2] disable envmap when it should be (#2864)
In jak 2, there's an option to disable envmap. It's used on krew
holograms, hiphog trophies, and baron bosses in palace/tomb.
2023-07-29 19:01:55 -04:00
water111 9662cd0228 [jak2] use current buffer for blit-displays (#2855)
This changes how `BlitDisplays.cpp` works so it looks at the current
render buffer, rather than the back buffer.

This approach is a bit faster because we avoid copying the back buffer
on every single frame.
It also removes the black frames when the transition starts/stops.

The remaining issues are:
- there's still a single frame of weirdness with the sprite glow
renderer.
- when changing resolutions, it doesn't work super well.
2023-07-29 18:14:31 -04:00
water111 a48df0683f [jak2] fix compile error (#2862)
not sure how this passed tests....
2023-07-29 17:41:11 -04:00
water111 89e52e3114 [jak2] Fix ocean culling when using camera-other (#2858)
When drawing the spinning palace, there's a terrible hack that lets some
stuff be drawn with different camera matrices.

The ocean is drawn with camera-other (which spins), but was being culled
with camera (doesn't spin). This changes ocean to use the right camera
matrix.

Note that the ocean is special when it comes to camera-other - it always
uses camera-other if there is one. Other uses are set per-level and
should already be handled correctly.
2023-07-29 17:02:57 -04:00
water111 f477127bf7 [jak2] fix transparent shrub blending (#2853)
![image](https://github.com/open-goal/jak-project/assets/48171810/ae4d40bf-b061-45af-ba20-c546fc935f11)

Should probably wait until the release just in case. But I'm 99% sure
this line was just a mistake in the original implementation.
2023-07-29 15:57:49 -04:00
water111 b1a1117a55 [jak2] workaround for missing yakow textures (#2854)
The yakow texture is actually missing from the real game too. 

This adds a special case in the extractor to replace it with a
similar-ish fur texture:

![image](https://github.com/open-goal/jak-project/assets/48171810/db429e70-e5c5-4302-824a-238e94cf3d69)
2023-07-29 14:44:09 -04:00
ManDude 6161acdf83 force-actors? -> ps2-actor-vis? (#2852)
supersedes #2839
2023-07-29 18:30:37 +01:00
ManDude a626b6b60d [jak2] graphic options menu proof of concept (#2849)
![imagem](https://github.com/open-goal/jak-project/assets/7569514/b8eaa0b6-7c51-4bd8-96ac-5fb2e0d08c4a)

![imagem](https://github.com/open-goal/jak-project/assets/7569514/d2742cef-98d4-43e4-a48d-cc1996e41612)

(The "Custom" option does not do anything right now.)
2023-07-29 18:08:44 +01:00
water111 748a9f3b41 [jak1] Fix ice walking animation bug and crash (#2851)
This should fix a crash and animation bug in snowy. The way to trigger
the bug:
- go on ice
- move forward slowly
- stop moving forward. Reach zero speed when the frame number isn't
between 30 and 35 of the ice walking animation
- Due to this bug, the animation gets stuck at frame 60
- Take damage (due to normal lurker or ice lurker)
- Sidekick eye animation crashes because a frame number is NaN.
2023-07-29 12:20:09 -04:00
water111 608dd4ab57 Fix possible crash when loading files (#2850)
There was a single static path buffer being shared between multiple file
i/o threads. So sometimes you would end up using the wrong path for the
file, and getting size/data for the wrong file.

I think the original reason to have this buffer was just me being lazy
when we changed how project paths works a long time ago. It was a bad
idea in the first place.
2023-07-29 11:38:23 -04:00
water111 7220f5680e [jak2] More texture animations, and fixes (#2847) 2023-07-29 11:10:26 -04:00
ManDude a9e0e36e64 fix stad-samos regression from refactor (#2796) + change imgui toggle to left-alt and make it customizable (#2848) 2023-07-29 02:26:42 +01:00
ManDude 6599eb1c91 Fix small buzz motor not vibrating correctly (#2846) 2023-07-27 10:46:40 +01:00
ManDude 05b7b571c8 [jak2] make progress menu work for widescreen + various other fixes (#2843)
Lots of manual fixes to make the text and other UI elements in the
progress fit within the small 4x3 view.


![image](https://cdn.discordapp.com/attachments/995787558816595968/1132986451664056423/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133064077460131840/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133074288564510780/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133117633898762280/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133117633470922842/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133135949610627225/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133146823968706621/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133153504417042593/image.png)

I've also changed the select start menus to not have that giant space in
each option. It's behind a toggle in the code right now.

![image](https://cdn.discordapp.com/attachments/995787558816595968/1133146382006489138/image.png)

Additionally:
- fixed city billboard particles
- fix stadium crash from original game
- fix an accidental regression
2023-07-26 17:20:22 +01:00
water111andManDude f327e67182 [jak2] Fix dark jak anim and low res skull gems (#2842)
Fixes skull gems using a low resolution texture.

Fixes issue where jak in cutscenes is dark after watching oracle-level-1
(and likely other bugs with texture animations getting stuck)

---------

Co-authored-by: ManDude <[email protected]>
2023-07-25 01:29:20 +01:00
Tyler Wilding 9376557834 game: add a clear text label for how to hide the top bar (#2845) 2023-07-24 20:06:09 -04:00
water111 50230e05fa [jak2] Add static textures for the progress menu (#2838)
The progress menu loads its icon textures from a .STR file that we were
previously ignoring.

This change:
- updates the decompiler so it can process a .STR file containing a
texture
- adds a feature to force an entire page to always be loaded in the PC
renderer by putting all textures in the GAME.FR3 file.
- regenerates the texture offset map file for jak 2 with these new
textures

For now, I've just put the icon textures in GAME.FR3. The downside is
that these will always stay on the GPU, using up VRAM even when they
aren't needed. But the entire GAME.FR3 file is under 3 MB so I think
it's ok.


![image](https://github.com/open-goal/jak-project/assets/48171810/39f075b5-7cc5-4168-872a-33026342afab)
2023-07-23 12:35:59 -04:00
water111 673d2a13ae [jak2] More progress on texture animations (#2835)
- Add security wall animation
- Add waterfall animations
- Add lava animations
- Update layer values from the game to fix the security wall
- Remove leftover debug in `level.gc` that would break level-specific
animations on the second time you visited the level
- Optionally load animated slot textures to the pool so generic can use
them (fixes skull gems in UI)
2023-07-21 15:04:28 -04:00
water111 5165a828a5 [jak2] Fix overlord related crash (#2834)
This fixes the crash reported in
https://github.com/open-goal/jak-project/issues/2833

There was a memory bug here for a long time where our array of `VagCmd`
in `iso_queue.cpp` was too small. This caused GetVagCommand to return
bogus pointers, and sound code would write over other parts of memory.
2023-07-21 11:25:08 -04:00
OpenGOAL BotandOpenGOALBot ec6b191334 CI: Periodic Controller Database Update (#2832)
Co-authored-by: OpenGOALBot <[email protected]>
2023-07-17 20:27:46 -04:00
water111 72c27a6eaa [jak2] More texture animations (#2831)
Added framework to do texture animations entirely in C++. Currently only
works on relatively simple ones, and doesn't handle updating all
parameters - only the speeds.

Connected texture animations to merc and tfrag for skull gems, dark
bomb, and scrolling conveyors.

Cleaned up Tfragment/Tfrag3, which used to be two classes. This was one
of the first C++ renderers, so it had a weird design.
2023-07-16 13:02:53 -04:00
Tyler Wilding e0bc7ce732 Get the project compiling on Apple Silicon macOS natively (arm64) (#2827)
I havn't tested it yet, but I can almost guarantee that atleast `goalc`
will not work in the slightest!

But the project is atleast fully compiling. My hope is to start
translating some AVX to NEON next / get `goalc` working...eventually.
2023-07-16 11:13:48 -04:00
animalstyletacoandanimalstyletaco 54b2c5dcbd Added bound check for blend vertex count (#2830)
Co-authored-by: animalstyletaco <[email protected]>
2023-07-16 10:55:46 -04:00
water111 d80b1b8119 [jak2] speed up the sky texture animation (#2829)
This saved about 1.6 ms per frame in the city for me (~1.3 saved from
not doing sky twice, 0.3 saved in format lookup tables).

The big texture animator is about 1.0 ms.

![image](https://github.com/open-goal/jak-project/assets/48171810/c7bc7743-308c-4425-ad14-118e2d483fad)
2023-07-15 11:06:32 -04:00
water111 6f244b11ef [jak2] Work-in-progress texture animations (#2819) 2023-07-14 18:17:54 -04:00
ManDude e546fce370 improve send-event for jak 2 (#2828)
Fixes #2825
2023-07-14 18:01:09 -04:00
ManDude 33858cbae6 increase max minimap icons 64 -> 256 (#2826)
Some missions add way too many icons so the limit is reached. It seems
safe to increase by a large amount.

Fixes #2779
2023-07-11 22:14:42 +01:00
ManDude 95d706e339 fix subtitle console spam + font shadow offseting (#2822) 2023-07-10 07:32:35 +01:00
Tyler WildingandManDude c87db7e670 i18n: subtitle code cleanup and update new subtitle JSON files to be compatible with Crowdin (#2802)
The main thing that was done here was to slightly modify the new
subtitle-v2 JSON schema to be more similar to the existing one so that
it can properly be used in Crowdin.

Draft while I double-check the diff myself

Along the way the following was also done (among other things):
- got rid of as much duplication as was feasible in the serialization
and editor code
- separated the text serialization code from the subtitle code for
better organization
- simplified "base language" in the editor. The new subtitle format has
built-in support for defining a base language so the editor doesn't have
to be used as a crutch. Also, cutscenes only defined in the base come
first in the list now as that is generally the order you'd work from
(what you havn't done first)
- got rid of the GOAL subtitle format code completely
- switched jak 2 text translations to the JSON format as well
- found a few mistakes in the jak 1 subtitle metadata files
- added a couple minor features to the editor
- consolidate and removed complexity, ie. recently all jak 1 hints were
forced to the `named` type, so I got rid of the two types as there isn't
a need anymore.
- removed subtitle editor groups for jak 1, the only reason they existed
was so when the GOAL file was manually written out they were somewhat
organized, the editor has a decent filter control, there's no need for
them.
- removed the GOAL -> JSON python script helper, it's been a month or so
and no one has come forward with existing translations that they need
help with migrating. If they do need it, the script will be in the git
history.

I did some reasonably through testing in Jak1/Jak 2 and everything
seemed to work. But more testing is always a good idea.

---------

Co-authored-by: ManDude <[email protected]>
2023-07-09 02:53:39 +01:00
Fabian Bergström d8ca594ee3 add (Intel) macOS job and artifacts to release pipeline (#2817) 2023-07-08 18:09:41 -04:00
ManDude 4185123bd8 fix mouse mispositioning when letterboxed (#2818)
Not sure if this is the best way to go about it.

Fixes #2259
2023-07-08 23:05:03 +01:00
Fabian Bergström 40e2f113e6 Make Jak1 playable on macOS (intel) (#2811)
## Problem

OpenGOAL uses OpenGL 4.3.

Apple stopped upgrading OpenGL after 4.1, so the way OpenGOAL currently
works will never be playable on Macs using OpenGL.

## Solution

Luckily, downgrading to OpenGL 4.1 is not a huge change (at least it
doesn't seem like it to my untrained eyes).

## Changes

* set hints for OpenGL 4.1 instead of 4.3 for __APPLE__
* skip the OpenGL debugging callback setup for macOS (requires 4.3)
* bump down the version string for all shaders
* stop using the `binding` layout qualifier in shader code
* move the `flat` qualifier first (not sure if this is a 4.1 thing or
just Macs being more strict)
* don't mix signed and unsigned ints in shaders (not sure if this is a
4.1 thing or just Macs being more strict)
* add some hacky CPP to the Shader constructor for binding texture units
and bones buffers based on variable names in the shader code

## Results


![image](https://github.com/open-goal/jak-project/assets/33322/dd487c2a-61ac-4e36-a595-976204302977)
![Skärmavbild 2023-07-07 kl 13 10
30](https://github.com/open-goal/jak-project/assets/33322/7976d411-0604-4046-9e8a-123106cedf57)
![Skärmavbild 2023-07-07 kl 13 13
48](https://github.com/open-goal/jak-project/assets/33322/78db4f0c-da31-4889-995c-8f54e56deb5c)
2023-07-08 11:53:43 -04:00
Tyler Wilding 6faa7530f9 input: Hopefully make keyboard/mouse handling more consistent (#2807)
The current event-based approach is very difficult to get right, and it
depends on no events ever being missed. This changes the keyboard/mouse
handling code to a polling-based approach.

Other fixes:
- an issue where modifier keys were not able to be successfully bound
(like Left Shift to `X`)
- improves cursor hiding (except when you use the start menu, this seems
like an SDL issue, see comment)
- Better discarding of kb/mouse inputs when imgui intercepts input
- properly swap bindings when an already set key is assigned, even if it
crosses the distinction of an analog vs normal button

Fixes #2800
2023-07-08 10:45:56 -04:00
Hat Kid c9330a6951 jak2: fix race crash (#2816) 2023-07-08 10:55:43 +02:00
ManDude da3caf7b28 [decompiler] fix in-place ops not getting detected sometimes (#2810) 2023-07-08 07:34:38 +01:00
ManDude 31cc69d7f6 fix some rare enum detection bugs (#2808) 2023-07-06 18:32:42 +01:00
ManDude ebd8643d28 rework jak 2 goal file structure (#2806)
Changes the DGO build order so that the city gets compiled first, and a
random guess at an "order" of which levels people might edit more often.
Most of the data-only borrow files are moved to the end as well.

Also moves around files in the `goal_src` tree to a structure that makes
a bit more sense, some files were either in the completely wrong place,
their folders had strange names, were too deep for no reason or were
just too far away from other relevant files. This structure should make
it easier to guess a file's location.
2023-07-06 15:23:25 +01:00
Hat Kid d24fb965d4 repl: separate history by game version (#2805) 2023-07-05 20:15:46 +02:00
water111 8806a0006e [jak1] Merc for title - fixes blerc (#2801)
Removes a leftover case for falling to back to generic-merc in jak 1.
This should fix the bug where daxter's face wasn't animated in the intro
after floating-point blerc was added.
2023-07-04 19:28:40 -04:00
water111 6c77f51653 [jak2] add some missing lambdas (#2799)
Should fix the eye problem in
https://github.com/open-goal/jak-project/issues/2797
2023-07-04 18:19:51 -04:00
Fabian Bergström 34f49469ec Make setup_cpu_info work on (Intel) Macs (#2798)
## Problem

OpenGOAL incorrectly identifies Intel Macs a not supporting AVX.

## Solution

Use the CPUID instruction for x86_64 Macs as well as Linux.
2023-07-04 18:19:34 -04:00
ManDude b50b9eadb2 [decompiler] new features + fixes, + other jak2 fixes (#2796)
Fixes empty boxed arrays of strings breaking some decomp
(`ctywide-speech` and `race-info`).

Adds `decomp-as` tag to decompiler types so that the static data
decompiler can use macros like `meters` and `seconds` on fields that
aren't of type `meters` or `time-frame`.

Adds `override` tag to decompiler types which overrides the type of
field with that name. The type must be a child type of the original
field's type (or the same type, but why would you do this?).

Fixes the camera being offset for `drillmtn` after loading `palout`
once.

This is a huge refactor sadly.
2023-07-04 17:23:24 -04:00
ManDude 71b4ab5122 change imgui toggle key from leftalt to f12 (#2794) 2023-07-03 17:49:27 +01:00
Fabian Bergström cf295952b6 Make all project targets compile on Intel MacOS (#2780) 2023-07-01 13:30:11 -04:00
Tyler Wilding 98bb40d618 ci: ensure linux runners have the proper OpenGL headers (#2790) 2023-07-01 02:09:09 -04:00
Tyler Wilding 436bac83ec game: Improve OpenGL version detection and make requirement errors more obvious to the user (#2787) 2023-06-30 21:05:58 -04:00
ManDude 5f8c21b1de fix vag player not really working (#2788)
There was a regression recently that caused this.
2023-06-30 21:01:47 +01:00
ManDude f25f26362d faster progress toggle (off by default) (#2785)
I set it to 150% speed, going much higher made it feel very strange.
2023-06-30 06:34:29 +01:00
Tyler Wilding bafa8f6b34 New Crowdin updates (#2786) 2023-06-30 00:00:37 -04:00
Fabian Bergström 7300678c46 [jak1] Improve the Swedish translations (#2770) 2023-06-29 23:07:24 -04:00
HimhamandManDude e3fb7c9467 Typo fix LTT_MSG_INSEPCT (#2778)
Co-authored-by: ManDude <[email protected]>
2023-06-29 16:45:53 -04:00
OpenGOAL BotandOpenGOALBot 7570978c4b CI: Periodic Controller Database Update (#2777)
Co-authored-by: OpenGOALBot <[email protected]>
2023-06-29 16:33:58 -04:00
Tyler Wilding 84cd1a5c18 repl: update replxx and some configuration for bracketed paste (#2784) 2023-06-29 16:32:48 -04:00
ManDude 4643129948 fix stadium particles + save game after winning a race (#2783) 2023-06-28 20:14:24 +01:00
ManDude b3e3f9379e fix some jak 1 hint subtitles not showing up (#2782)
There is one instance of the same hint being played for different IDs
which was breaking things.
2023-06-28 14:13:47 +01:00
ManDude 1351cb6c9c fix more orb softlocks i forgot (#2781)
I forgot these.
2023-06-28 04:08:38 +01:00
Hat Kid 76aaa2fb10 jak2: add .gd files and level info for some ps3 test levels (#2776) 2023-06-27 23:52:19 +02:00
ManDude f8d4489361 fix more orb softlocks (#2767)
Fixes orb softlocks during races and other side missions.

The side mission tasks will now not count as completed until the
precursor orb has been picked up.

Races will not let you advance (or even pause the game) until the
precursor orb has been picked up.
2023-06-27 22:02:21 +01:00
Tyler Wilding 10934f6746 d/j2: Some work on the SQL editors (#2771) 2023-06-25 16:51:46 -04:00
Tyler Wilding 25e7c9bc5d New Crowdin updates (#2775) 2023-06-25 16:17:18 -04:00
Tyler Wilding 4018d15fde ci/translations: Add a linter to check for invalid characters, fix current issues (#2774) 2023-06-25 15:13:32 -04:00
Ziemas cb895d4ba0 overlord: perform file operations on a thread pool (#2749)
Avoids blocking other IOP threads on IO. 

Idk if it'll really help anything, but at least theoretically it might
stop some pathologically slow IO case from blocking the VAG buffer
switching.
2023-06-24 10:19:35 -04:00
water111 2fc943977f [jak2] GOAL side texture animation stuff (#2766)
It turns out we didn't decompile any of this stuff yet.
2023-06-24 10:11:47 -04:00
ManDude 97fd6a6e8d fix subtitle mispositioning when unpausing and other situations (#2769) 2023-06-24 05:47:24 +01:00
Tyler Wilding 679986e79f sdl: safer code to resolve intermittent controller crashes related to disconnections (#2755) 2023-06-23 15:35:32 -04:00
Tyler Wilding 533d2f6f2b formatter: new approach for indentation that doesn't depend on original formatting (#2764) 2023-06-22 00:16:18 -04:00
Tyler Wilding f980c733b2 cmake: properly statically link SDL when applicable (#2762) 2023-06-20 23:25:47 -04:00
ManDude d3e7a48639 jak2: fix rigid-body-object-event-handler type (#2761)
Fixes #2760
2023-06-21 02:06:28 +01:00
ManDude b350525294 increase airlock open and post-close speed (#2758)
open: 150% -> 175%
post-close: 100% -> 175%
2023-06-20 19:31:20 +01:00
ManDude 15ef95e036 fix orb in sewers being unobtainable after starting sewer escort (+ some more type fixes) (#2757)
Total hack but it does seem to work correctly.

Fixes #2756
2023-06-20 04:25:03 +01:00
OpenGOAL BotandOpenGOALBot 0c729437bb CI: Periodic Controller Database Update (#2751)
Co-authored-by: OpenGOALBot <[email protected]>
2023-06-19 16:33:24 -04:00
Tyler WildingandManDude 95904903a6 sdl: only call SDL video functions from the gfx thread (#2748)
Co-authored-by: ManDude <[email protected]>
2023-06-19 16:32:39 -04:00
ManDude 53050fabc1 [jak2] allow going to metal head nest after winning game (#2753)
This is a major deviation from the original game, which did not have any
way to access the nest after beating Metal Kor as the air train gets
hidden when he is beaten. This was mostly annoying because there are
precursor orbs in that level that you might miss.

This makes it so the air train can once again be used to enter the nest
even after beating Metal Kor. The rest of the level remains mostly the
same, except the Rift Ring does not spawn and an invisible wall is added
to the Metal Kor arena to prevent you from entering it as you are
normally unable to leave it anyway.
2023-06-19 19:58:01 +01:00
ManDude 910681bde8 fix windowed screenshots capturing the last window buffer instead of current one (#2750) 2023-06-19 15:33:51 +01:00
ManDude 572e63f4a9 opengl: better handling of the draw region setting (#2746)
This fixes screenshots and a bunch of weird scissoring bugs. Fixes #2630
and fixes #2631
2023-06-19 04:15:33 +01:00
Tyler Wilding a8a5f1e745 formatter: support comments better (including block comments) and constant pair formatting (#2745) 2023-06-18 17:19:35 -04:00
ManDude c41a66829f Make screenshots copy to clipboard (#2739)
Fixes #2728
2023-06-17 23:42:52 +01:00
water111 01cb9efccc [jak2] fge=0 at the start of warp (#2740)
The warp giftags don't set PRE and seem to rely on fogging being
disabled at the start.
2023-06-17 18:29:55 -04:00
water111 6e779d1f1c [jak2] faster startup (#2738)
Trying to make up for some of the startup speed lost in the SDL
transition. This saves about 1s from start (from ~3s), and about 500 MB
of RAM.

- Faster TIE unpack by merging matrix groups, more efficient vertex
transforms, and skipping normal transforms on groups with no normals.
- Refactor generic merc and merc to use a single renderer with multiple
interfaces, rather than many renderers. Removed "LightningRenderer" as a
special thing, but Warp is still special
- Add more profiling stuff to startup and the loader.
- Remove `SDL_INIT_HAPTIC` - this turned out to be needed for
force-feedback steering wheels, and not needed for controller vibration
- Switched `vag-player` to use quicksort instead of the default GOAL
sort (very slow)
2023-06-17 17:23:25 -04:00
BreakPointsandManDude 1512c6bd9c sdl: Directly use Windows DPI scaling hint, not SDL (#2730)
Co-authored-by: ManDude <[email protected]>
2023-06-17 12:40:25 -04:00
Hat KidandManDude d8cca2bf83 game: refactor discord code and improve jak 2 support (#2714)
The Discord RPC code has been cleaned up and split up between game
versions.

For Jak 2, the Discord integration now shows large images for all levels
(with corresponding day and nighttime variants if required) and small
images for time of day and various states like being on the jetboard,
driving a zoomer, playing as Daxter, etc.

TODO:
- [x] mission specific images and detection
- [x] detect side missions properly
- [x] `onin-game` detection


![image](https://github.com/open-goal/jak-project/assets/6624576/35ec273f-404c-4475-a7c7-06121a17b1a5)

![image](https://github.com/open-goal/jak-project/assets/6624576/8456f5e2-4f96-4c72-ae9e-d930d76c93af)

![image](https://github.com/open-goal/jak-project/assets/6624576/9a17a0ec-c9bd-40fa-8556-f139712d8f07)

---------

Co-authored-by: ManDude <[email protected]>
2023-06-17 05:16:40 +01:00
Matt Dallmeyer 2624934e72 Camera debug menu - reuse enum instead of strange indexing/magic numbers (#2717) 2023-06-15 20:28:54 +01:00
Matt Dallmeyer ccaa1f41e5 Rename collide-action enum values for readability (#2712)
```lisp
(defenum collide-action
  :type uint32
  :bitfield #t
  (solid 0)              ;; used for solid things
  (rider-plat-sticky 1)  ;; used for platforms in rider/platform interactions
  (rider-target 2)       ;; used for target in rider/platform interactions
  (edgegrab-active 3)    ;; set/cleared when entering/exiting edgegrab states
  (rider-plat 4)         ;; used for platforms in rider/platform interactions
  (unused 5)             ;; totally unused?
  (edgegrab-possible 6)  ;; used when edge grab checks should be done
  (edgegrab-cam 7)       ;; set/cleared when entering/exiting edgegrab states
  (swingpole-active 8)   ;; set/cleared when entering/exiting swingpole states
  (racer 9)              ;; set/cleared when entering/exiting racer states
  (attackable 10)        ;; used for something to do with attacking/damaging
  (attackable-unused 11) ;; seems to relate to attacking - set in several places but never tested for?
  (snowball 12)          ;; set/cleared when entering/exiting snowball states
  (tube 13)              ;; set/cleared when entering/exiting tube states
  (flut 14)              ;; set/cleared when entering/exiting flutflut states
  (racer-grounded 15)    ;; set/cleared when entering/exiting certain racer states w/ extra conditions
  (racer-unused 16)      ;; seems to relate to racer - never set, only cleared in one place?
  )
```
2023-06-15 19:59:54 +01:00
ManDude f0fb6f422d fix some enter-states and sound-id fields (#2727)
Supersedes #2525
2023-06-14 22:04:00 +01:00
OpenGOAL BotandOpenGOALBot 45bbefafde CI: Periodic Controller Database Update (#2718)
Co-authored-by: OpenGOALBot <[email protected]>
2023-06-13 21:46:23 -04:00
BreakPoints 756fcc3e4d SDL: Hint to Windows that we handle DPI scaling (#2729) 2023-06-13 21:45:57 -04:00
ManDude e2c84d7635 revamp controller LED in jak 1 + reorganize some pc-settings things + fix some jak 2 decomp (#2719) 2023-06-13 19:26:44 +01:00
Ziemas 1eec021593 989snd: properly update children with new state (#2720) 2023-06-13 00:48:09 +01:00
water111 ad5cec1bb4 [jak2] Floating point blerc (#2715)
This moves the blerc math from mips2c to the Merc2 renderer, and uses
floats instead.

We could potentially do this on the GPU, which would be even faster, but
this isn't that slow in the first place.
2023-06-11 12:35:08 -04:00
Matt DallmeyerandTyler Wilding a88c2d2460 Replace hardcoded pickup-type ints with enum name (#2704)
For reference:
jak1
```lisp
(defenum pickup-type
  (none) ;; 0
  (eco-yellow) ;; 1
  (eco-red) ;; 2
  (eco-blue) ;; 3
  (eco-green) ;; 4
  (money) ;; 5
  (fuel-cell) ;; 6
  (eco-pill) ;; 7
  (buzzer) ;; 8
  (eco-pill-random) ;; 9
  )
```

jak2
```lisp
(defenum pickup-type
  :bitfield #f
  :type int32
  (none            0)
  (eco-yellow      1)
  (eco-red         2)
  (eco-blue        3)
  (eco-dark        4)
  (eco-green       5)
  (eco-pill-green  6)
  (eco-pill-dark   7)
  (eco-pill-random 8)
  (money           9)
  (fuel-cell      10)
  (buzzer         11)
  (darkjak        12)
  (ammo-yellow    13)
  (ammo-red       14)
  (ammo-blue      15)
  (ammo-dark      16)
  (shield         17)
  (health         18)
  (trick-point    19)
  (trick-judge    20)
  (gem            21)
  (skill          22)
  (karma          23)
  (gun-red        24)
  (gun-yellow     25)
  (gun-blue       26)
  (gun-dark       27)
  (board          28)
  (pass-red       29)
  (pass-green     30)
  (pass-yellow    31)
  (pass-blue      32)
  (ammo-random    33)
  )
```

Co-authored-by: Tyler Wilding <[email protected]>
2023-06-10 01:39:13 +01:00
Tyler Wilding 1dbfd0e238 ci: fix chocolately, version number doesn't have a v prefix (#2711) 2023-06-09 13:55:50 -04:00
ManDude a17c78cdd1 don't use gender for citizen names + small minor stuff (#2708)
It's ultimately not useful information and kind of clutters the text.
2023-06-09 05:56:46 +01:00
Tyler Wilding 7f377000dc nREPL: fix some logs and some spots where it could get stuck (#2709) 2023-06-09 00:02:07 -04:00
Tyler Wilding 33bf73636b ci: update chocolately syntax and update nasm to 2.16.1 (#2710) 2023-06-09 00:01:50 -04:00
ManDude f5ad85b4cd workaround for spyder warp hack and fix battle bugs (#2707)
Fixes #2705 
Fixes #2706
2023-06-08 06:47:44 +01:00
ManDudeandHat Kid 18ddd1613c Jak 2 pc subtitle support (#2672)
Adds support for adding custom subtitles to Jak 2 audio. Comes with a
new editor for the new system and format. Compared to the Jak 1 system,
this is much simpler to make an editor for.

Comes with a few subtitles already made as an example.
Cutscenes are not officially supported but you can technically subtitle
those with editor, so please don't right now.

This new system supports multiple subtitles playing at once (even from a
single source!) and will smartly push the subtitles up if there's a
message already playing:

![image](https://github.com/open-goal/jak-project/assets/7569514/033e6374-a05a-4c31-b029-51868153a932)

![image](https://github.com/open-goal/jak-project/assets/7569514/5298aa6d-a183-446e-bdb6-61c4682df917)

Unlike in Jak 1, it will not hide the bottom HUD when subtitles are
active:

![image](https://github.com/open-goal/jak-project/assets/7569514/d466bfc0-55d0-4689-a6e1-b7784b9fff59)

Sadly this leaves us with not much space for the subtitle region (and
the subtitles are shrunk when the minimap is enabled) but when you have
guards and citizens talking all the time, hiding the HUD every time
anyone spoke would get really frustrating.

The subtitle speaker is also color-coded now, because I thought that
would be fun to do.

TODO:
- [x] proper cutscene support.
- [x] merge mode for cutscenes so we don't have to rewrite the script?

---------

Co-authored-by: Hat Kid <[email protected]>
2023-06-08 01:04:16 +01:00
Tyler Wilding 3dbaee1ecc formatter: handle top level blank lines and better handle comments (#2702) 2023-06-06 20:34:50 -04:00
Tyler Wilding 3ecb3e4bc8 ci: don't run CI builds on non master branch pushes (#2703) 2023-06-06 20:05:35 -04:00
water111 b1e753740c [jak2] joint to bone nan fix (#2698)
Fixes https://github.com/open-goal/jak-project/issues/2477
(and any other case of bad bones/cspaces when a bone's scale is very
small/negative)
2023-06-05 22:02:17 -04:00
water111 3bb6bd0e3a [jak2] fix missing drill crane center part (#2692)
We were forcing the drill crane to draw at lod 0, but we should have
listened to the game and drawn it at lod 1.
2023-06-05 18:56:26 -04:00
Tyler Wilding e9f9869849 input: fix some mistakes in the default keyboard binds (#2697) 2023-06-05 18:26:29 -04:00
Hat Kid c677b716b9 readme: add mesa-libGL-devel dependency for fedora users (#2696) 2023-06-05 12:43:23 +02:00
ZedB0T 4bb5491d38 sdl: Fix target-fps add debug toggle for speedrun mode (#2694) 2023-06-04 20:42:09 -04:00
Tyler Wilding 2dead49019 sdl2: add back x11 window code fix (#2691) 2023-06-04 20:29:16 -04:00
Tyler WildingandHat Kid bdaf088d4b game: Migrate from GLFW to SDL2 & attempt to rewrite / simplify display and input code (#2397)
Co-authored-by: Hat Kid <[email protected]>
2023-06-04 15:34:37 -04:00
water111 08741f0a42 [jak2] float patch for bogus collide frags (#2686)
Should fix https://github.com/open-goal/jak-project/issues/2679

Here's a test program that will trigger the bug when near these guards:
```lisp
(define *cquery* (new 'global 'collide-query))

(defun test-bad-collide ()
  (let ((lower (new 'static 'vector  :x 1681893.8750  :y 61314.2031 :z 345208.6562 :w 1.))
        (upper (new 'static 'vector :x 1701603.8750 :y  67624.0625 :z 357881.0312 :w 1.))
        ;(cquery (new 'stack-no-clear 'collide-query))
        )
    (set! (-> *cquery* collide-with) (the-as collide-spec 1))
    (set! (-> *cquery* ignore-process0) #f)
    (set! (-> *cquery* ignore-process1) #f)
    (set! (-> *cquery* ignore-pat) (new 'static 'pat-surface :noentity #x1 :nojak #x1 :probe #x1 :noendlessfall #x1))
    (set! (-> *cquery* action-mask) (collide-action solid))
    (set! (-> *cquery* bbox min quad) (-> lower quad))
    (set! (-> *cquery* bbox max quad) (-> upper quad))
    (format 0 "doing collide...~%")
    (fill-using-bounding-box *collide-cache* *cquery*)
    (format 0 "have ~d and ~d~%" (-> *collide-cache* num-tris) (-> *collide-cache* num-prims))
    )
  (none)
  )
```

As far as I can tell, there's a totally invalid collide-hash with an
inside `axis-scale.z`. On the PS2, it gets ignore because of how
float->int works for floats that are too big. On PC, it ends up using a
negative value and loop forever.
2023-06-04 15:19:08 -04:00
Tyler Wilding 6eaa95608e ci: bump timeouts on builds, mostly for cache misses (#2690) 2023-06-04 14:08:35 -04:00
Tyler Wilding 6d620a9289 formatter: extract formatting into a rules abstraction, add inner formatting (body vs argument functions) (#2684) 2023-06-04 13:19:29 -04:00
ZedB0T d41858c61c Show the git commit version in screenshots/videos [Jak 2] (#2677)
With issues/screenshots becoming more common its probably time to turn
this on for debugging reasons.
2023-06-04 11:02:51 -04:00
Matt Dallmeyer 45b83ad5d5 Add race-bike-d/e debug options, some comments (#2683) 2023-06-04 10:57:53 -04:00
water111 fee91d2240 [IOP] revert change that ran the iop way too much (#2681)
This caused the IOP thread to use a full core always, just spinning on
this. I didn't mean to leave this in.
2023-06-04 10:57:34 -04:00
Hat Kid c23bef45bb jak2: fix race crash (#2680) 2023-05-31 19:49:23 +02:00
Hat Kid 48141bee6f jak2: fix pegasus crash (#2676) 2023-05-30 01:31:07 +02:00
Tyler Wilding 4c6982b0ec formatter: initial and basic indentation/alignment and expose the formatting via the LSP (#2673) 2023-05-28 13:22:00 -04:00
Dimitri (__) ad0b3297ca fix: add unicode tree-sitter include directory (#2674) 2023-05-28 13:21:25 -04:00
Ziemas 691af17bbd overlord: Some cleanup (#2669)
Started cleaning up some of the lower hanging fruit.
2023-05-26 17:55:10 -04:00
ManDude 25fd007233 Update font-color enum (#2670)
Gives proper names to almost every color. It is very apparent that some
colors are context-sensitive/made for a specific purpose, so those
colors were named after that purpose instead of a generic color name.
2023-05-24 06:57:05 +01:00
Tyler Wilding 057ae361bf LSP: OpenGOAL Feature Support - Part 1 (#2668) 2023-05-21 17:24:23 -04:00
water111 d5951c2b11 [jak 2] Fix possible stereo desync in overlord (#2663)
Normally, when they allocate a VagCmd, they do a bunch of stuff to clear
all the status bits and reset things
in particular the InitVAGCmd function does a lot


![image](https://github.com/open-goal/jak-project/assets/48171810/9b355020-ad37-496c-9438-2f8d34f24e0a)

but for the stereo command, they do a lot less:

![image](https://github.com/open-goal/jak-project/assets/48171810/12a36712-0e68-4377-a6be-3bde82c2aa15)

Which means that the new_stereo_command can just have random status bits
left over from whatever the last user had.
we seem to end up in a state where byte21 is set, and this causes
everything else to be wrong and off-by-one dma transfer. My guess is
that the original game avoided this bug due to lucky timing that I don't
understand.

I think the fix of just clearing byte21 is ok because there's no way
that the old value of the byte is useful after the command is
repurposed.
2023-05-19 21:17:11 -04:00
Tyler Wilding a033119f1d i18n: add MysticGamer23's swedish subtitles (#2667) 2023-05-19 21:06:24 -04:00
Tyler Wilding 18f162fcdf New Crowdin updates (#2666) 2023-05-18 21:43:00 -04:00
Tyler Wilding 288c093913 i18n: Create a JSON subtitle format for translating via Crowdin (#2644) 2023-05-18 20:54:59 -04:00
Luminar Light 70cb7e3171 Hungarian Custom Text JSON Disappearance fix, and translating new speedrun text (#2665) 2023-05-18 19:36:19 -04:00
ManDude 7c9c956808 vag player + skill tracker debug tools and fix some decomp (#2664)
Also fixed an original game bug in `loader.gc` on a method that's called
quite often, though I have no clue what erroneous behavior it could have
even caused.
2023-05-18 23:12:23 +01:00
Hat KidandManDude 8d28bb3480 jak2: add current-time macro for process clocks (#2662)
Closes #1872

---------

Co-authored-by: ManDude <[email protected]>
2023-05-18 21:33:46 +01:00
Ziemas 0fcd9da639 Fix GCC13 build (#2641) 2023-05-17 19:08:25 -04:00
ManDude 79b6e12d68 fix stadium-obs regression (#2661) 2023-05-17 01:03:18 +01:00
Hat Kid ebc90d57ed jak2: fill out names for text-id enum (#2640) 2023-05-17 00:48:44 +01:00
ManDude 0dccd048ef better decomp of set-subtask-hook!, sub-task-list array and *-setting! macros (#2654)
Improves code readability considerably.
2023-05-16 23:08:35 +01:00
OpenGOAL BotandOpenGOALBot 263f4caaf9 CI: Periodic Controller Database Update (#2651)
Co-authored-by: OpenGOALBot <[email protected]>
2023-05-16 01:03:43 -04:00
Matt DallmeyerandManDude 6478fdb97c Support multiline text (e.g. credits) override with JSON format (#2629)
Ported over the logic from parsing credits in GOAL game text file over
to the JSON parser.

minor notes:
- didn't bother replicating the logic for skipping empty lines
- didn't need to handle multiple languages in one file


https://github.com/open-goal/jak-project/blob/40b2e93be7ec24a597017e04b117a58162840016/common/serialization/subtitles/subtitles_ser.cpp#L92-L142

Using the sample multiline credits override from my comment in the code:

![image](https://user-images.githubusercontent.com/2515356/236648360-b12951dc-20aa-4435-8349-08e2c254187a.png)

---------

Co-authored-by: ManDude <[email protected]>
2023-05-15 21:19:07 +01:00
ManDude cf048a9e37 small cleanup to progress-draw.gc and set-font-color (#2653) 2023-05-15 20:45:28 +01:00
ManDude e30ecb361f small jak 2 bug fixes (#2649)
- elec gates now always render at max quality if you have PS2 lods
disabled. the original render distances are so low that the one in
caspad is impossible to see in normal gameplay.
- `fort-entry-gate-11` and `com-airlock-outer-13` are specifically
banned from the all actors hack because they are placed in a bad spot
and Naughty Dog did not program the airlocks very well.
- fixed NPC talk distance being bad for 1 frame.
- fix `sew-scare-grunt` erroneously keeping its spool anim active if you
killed the enemy.
2023-05-15 17:26:25 +01:00
Hat Kid 2e9aa1f962 jak1: add back money starburst (#2650) 2023-05-15 13:06:49 +02:00
ManDude 01aa67798f fix racer hud regression (#2648)
Fixes #2643
2023-05-15 03:18:02 +01:00
ManDude ecf590f30e fix shadow colors in jak 1 and jak 2 shadow crash (#2647)
Fixes Jak 1 shadow color. Old behavior is subtractive blend with a
hardcoded value, which often times look way too dark, but it looks like
the actual game uses some sort of multiplicative blend and a
customizable shadow color (for all shadows at once).

Before vs after:

![image](https://github.com/open-goal/jak-project/assets/7569514/a409a403-9ddf-40dd-a74f-a29bd9b98323)

![20230514234953763_gk_HxercNamqn](https://github.com/open-goal/jak-project/assets/7569514/211565ae-405f-4056-96e5-ec188d2c0a30)


![image](https://github.com/open-goal/jak-project/assets/7569514/f84244a6-153c-4f7d-84d0-dae57147e4ae)

![20230514235005037_gk_jGjwKFhnLE](https://github.com/open-goal/jak-project/assets/7569514/4262d136-3130-4791-ae70-14d4369ba8d4)


Also fixes #2646
2023-05-15 01:01:49 +01:00
Tyler Wilding 08b9a631dc New Crowdin updates (#2645) 2023-05-14 01:28:13 -04:00
Tyler Wilding 88517ef0c3 i18n: Lookup untranslated strings from a fallback language (english) instead of displaying Unknown... (#2637) 2023-05-14 00:53:27 -04:00
Hat Kid 8f742471a6 jak1: fix regression with npc NaNs (#2642) 2023-05-11 19:17:26 +02:00
OpenGOAL BotandOpenGOALBot 4f19f79e99 CI: Periodic Controller Database Update (#2639)
Co-authored-by: OpenGOALBot <[email protected]>
2023-05-08 21:32:53 -04:00
Tyler Wilding 0e0d7ba833 cmake: sort game/CMakeLists.txt files (#2633)
I sorted the list of sources on my SDL PR to reduce future merge
conflicts, but in the meantime everytime something gets added to it I
have a pretty rough set of conflicts to resolve. Committing this early
to preserve my sanity
2023-05-07 18:54:33 +01:00
water111andHat Kid b79f28fe07 [jak2] combined shadow work PR (#2632)
This PR is a combination of
https://github.com/open-goal/jak-project/pull/2507 and some additional
changes to port Shadow VU1 to OpenGL. As far as I can tell, it's
working.

---------

Co-authored-by: Hat Kid <[email protected]>
2023-05-07 12:12:21 -04:00
ManDude 40b2e93be7 pack tfrag normals into 10 bits (#2625)
Saves 16 bits and lets us align the `color_index` field properly.

This shouldn't improve or decrease performance by any noticeable amount
except maybe in really low end systems.
2023-05-06 02:08:33 +01:00
ManDude acae62c919 fix blit size being wrong most of the time (#2620) 2023-05-05 02:31:27 +01:00
ManDude 6884b0f73e start blit-displays decomp & renderer + improve decompilation of some DMA macros (#2616)
Adds sprite distort, fixes buggy sprite rendering in progress, adds
scissoring support (used in various scrolling menus) and a very basic
implementation of `blit-displays`. This is enough to make the fade
effect in the progress menu work, along with all the menus working
properly without needing to use the REPL. This does not make screen
flipping and the filter when failing a mission work.

Added support in the decompiler for detecting `dma-buffer-add-gs-set`
and `dma-buffer-add-gs-set-flusha` and updated all of the Jak 2 code to
use it. Readability improved!

Fixes decompiler issue with `with-dma-buffer-add-bucket` not inlining
forms which broke syntax. Fixes store error warnings showing up for
non-existent stores, there is now a dedicated pass for this at the end.

I started work on making `BITBLTBUF` stuff work in the DirectRenderer,
but stopped for now because it wasn't strictly necessary. It will still
assert like before.
2023-05-04 18:34:09 -04:00
Tyler Wilding ae3b76e465 New Crowdin updates (#2614) 2023-05-03 21:04:36 -04:00
Tyler Wilding e0cba064b2 i18n: allow for multiple file sources per language (#2613) 2023-05-03 20:04:52 -04:00
Hat Kid 3ce2edf4b6 decomp: ctywide-speech (#2612) 2023-05-03 09:09:39 +02:00
OpenGOAL BotandOpenGOALBot 8a59adffd5 CI: Periodic Controller Database Update (#2610)
Co-authored-by: OpenGOALBot <[email protected]>
2023-05-01 19:08:50 -04:00
dependabot[bot] 63e9e6724b Bump peter-evans/create-pull-request from 4 to 5 (#2609)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-30 23:13:52 -04:00
Tyler Wilding 28a5a417bc game: don't exit prematurely when rebooting in debug (#2608)
I'm not sure what has changed here...but rebooting in debug mode now
hangs.

- It seems to exit the GFX loop prematurely because `MasterExit` is
still set to `RESTART_IN_DEBUG`
https://github.com/open-goal/jak-project/blob/master/game/runtime.cpp#L431
- And then it gets stuck waiting for the DECI thread to close

This works, but im not sure if it's the right fix / what has changed to
require this.
2023-04-30 23:06:11 -04:00
water111 ef23fecd90 [goalc] default to non-immediate lambdas if not requested (#2604)
This fixes a long time issue with `lambda`. The `lambda` is a bit
overloaded in OpenGOAL: it's used in the implementation of `let`, and
also to define local anonymous functions.

```
(defmacro let (bindings &rest body)
  `((lambda :inline #t ,(apply first bindings) ,@body)
    ,@(apply second bindings)))
```

```
(defmacro defun (name bindings &rest body)
  (let ((docstring ""))
    (when (and (> (length body) 1) (string? (first body)))
      (set! docstring (first body))
      (set! body (cdr body)))
    `(define ,name ,docstring (lambda :name ,name ,bindings ,@body))))
```

In the first case of a `let`, a `return` from inside the `let` should
return from the functioning containing the `let`, not the scope of the
`lambda`. In the second case, we should return from the lambda. The way
we told the different between these cases was if the `lambda` was used
"immeidately", in the head of an expression (like it would be for the
`let` macro). But, this falsely triggers when an anonymous function is
used immediately: eg
```
((lambda () (return #f)))
```
should generate and call a real x86 function that returns immediately.

This should fix some death/mission failed stuff in jak 2.
2023-04-30 19:00:27 -04:00
ManDude 34b4020569 alternate method for scaling screen warp effects with aspect ratio (#2603)
Changes the scaling method used for the fort turret cam and under cam
effects. It should be more "accurate" now while not getting nauseating.
2023-04-30 23:12:20 +01:00
9bed693533 Initial Jak 2 Autosplit Support (#2239)
Co-authored-by: Tyler Wilding <[email protected]>
Co-authored-by: Tyler Wilding <[email protected]>
2023-04-30 17:38:05 -04:00
Tyler Wilding 6d52e002b9 i18n: init translation files that can be used by crowdin (#1760) 2023-04-30 17:22:56 -04:00
Tyler Wildingandwater111 728ef59477 ci: speed up unit-test execution (#2586)
Co-authored-by: water111 <[email protected]>
2023-04-30 14:27:08 -04:00
Tyler Wilding cc878c1055 settings: handle corrupted json settings files (#2600)
Fixes #2597
2023-04-30 14:14:40 -04:00
water111 5c9aa3facd [jak2] try to speed up compile a bit (#2596) 2023-04-30 14:13:52 -04:00
Tyler Wilding cb1daa032c g/j2: remove temporary hack to allow the avalanche to play (#2599)
No longer needed after the latest changes in the overlord PR that
recently merged.

Fixes #2509
2023-04-30 18:58:45 +01:00
ManDude 19899f6e5a [jak2] Fix temp stacks being created outside process stack (#2595)
Somehow this was only causing issues (afaik) with
`draw-decoration-load-save` getting corrupted, perhaps because other
processes either use the shared dram stack or the gigantic spr stack.
2023-04-30 12:17:42 -04:00
ManDude b37f255066 fix minimap stretch (#2593) 2023-04-30 04:23:56 +01:00
ManDude d67b95c68f allow quoting :key symbols + further optimize defpart (#2592)
This should hopefully improve build times in general, especially for
files with `defpart`.
2023-04-30 02:46:14 +01:00
ManDude 44193caef0 [jak2] more specific cutscene detection (#2590)
Fixes some instances of the camera entering cutscene mode when we don't
want that.
2023-04-30 01:23:53 +01:00
ManDude bc30e00b2f attempting to slightly optimize defpart (#2587) 2023-04-29 22:28:07 +01:00
5e987cc0e2 jak2: overlord rework (#2544)
Fixes #2545
Fixes #2546
Fixes #2547
Fixes #2548
Fixes #2549
Fixes #2550
Fixes #2551
Fixes #2552
Fixes #2553
Fixes #2554
Fixes #2555
Fixes #2556
Fixes #2557
Fixes #2558
Fixes #2559
Fixes #2560
Fixes #2561
Fixes #2562
Fixes #2563
Fixes #2564
Fixes #2565
Fixes #2567
Fixes #2566
Fixes #2568
Fixes #2569
Fixes #2570
Fixes #2522
Fixes #2571

---------

Co-authored-by: water <[email protected]>
Co-authored-by: Hat Kid <[email protected]>
Co-authored-by: ManDude <[email protected]>
2023-04-29 16:13:57 -04:00
ManDude 2feb231105 less branches for division + fix divide by zeros (#2585)
Slight change to float divide operations (again). Now it only turns into
inverse multiplication if the float is a power of 2 (positive or
negative). Non-zero immediate divisors will be compiled as regular float
divisions but will forgo the extra branches and checks for divide by
zero.

Also fixes #2584
2023-04-29 21:10:51 +01:00
ManDude 0d3e272876 fix many instances of bad bone data being used (#2580)
Fixes cutscenes starting way too early and various cutscene softlocks.

Fixes #2579
Fixes #2577 

Supersedes #2578
2023-04-29 11:13:56 -04:00
Hat Kid aff67d6bb7 jak2: fix warp effect for robotank and underb on other aspect ratios (#2574) 2023-04-29 11:03:13 -04:00
Tyler Wilding 8260920c2d subtitles-editor: Allow removing lines and fix some issues (#2573)
Allows for removing a line in the subtitle editor finally, also fixed
the following:

- The path the editor used didn't include the game name
- Loading the subtitle project is too slow to do on startup now
(4-5seconds in a debug build), do it on demand now
2023-04-29 11:02:18 -04:00
ManDude 0ce5835818 Create a new format for particle definitions (defpart) (#2572)
Updates the decompiler for the new format and there's new macros. This
new format should be easier to read/parse.

Also rewrote `sp-init-fields!` (both jak 1 and 2) from assembly to GOAL.

Hopefully I did not miss any regressions in Jak 1/2 while updating the
files, it's a lot.
2023-04-29 11:01:47 -04:00
Hat Kid 77123652b9 jak2: fix 3d hud elements not drawing (#2527)
The skull gem is not moving, but I'm assuming that's a texture
animation.

![image](https://user-images.githubusercontent.com/6624576/232855762-6c296419-a8b3-47b6-a02f-ab7079f145c6.png)
2023-04-25 18:57:38 -04:00
Tyler Wilding 0ffb912a04 formatter: add tree-sitter dependency and commit early draft work on a proper code formatter (#2536) 2023-04-24 23:46:55 -04:00
Tyler Wilding 83f43b7153 scripts: support new jak 2 decompiler config versions via task (#2543) 2023-04-24 20:14:59 -04:00
OpenGOAL BotandOpenGOALBot 4ca697b81a CI: Periodic Controller Database Update (#2542)
Co-authored-by: OpenGOALBot <[email protected]>
2023-04-24 17:12:48 -04:00
ManDude d84859e431 Fix bad lsack level borrow (#2540)
Fixes crash when completing city side missions with
`city-krew-collection-introduction` open.

Fixes #2539
2023-04-24 15:49:30 +01:00
ManDude 21b902cddf Do not swap between clocks for airlocks speed (#2537)
Fixes crash at the end of various missions.

Fixes #2456
2023-04-24 01:53:40 +01:00
ManDude 4cc3430073 fix some decomp types and get rid of in-game frame time perception (#2535) 2023-04-24 00:21:12 +01:00
ManDude c44256144e [jak2] bring other version fixes to source (#2528)
- [x] compare NTSC-K
- [x] compare NTSC-J
- [x] compare PAL
- [x] figure out version order
- [x] ~~write delta patch for spanish text~~ no need for now

Fixes #2530
2023-04-23 20:11:08 +01:00
Tyler Wilding a264b6539b game: Remove temporary CLI arg shim in gk (#2532) 2023-04-22 14:13:57 -04:00
Tyler Wilding 47d85f896e d/jak2: temp fix for rewarding orbs from talker speeches (#2523) 2023-04-17 23:04:16 -04:00
Tyler Wilding 57508009df d/jak2: decompile missing function in whack (#2521) 2023-04-17 22:26:46 -04:00
Tyler Wilding 138b1729ad d/jak2: fix dig-sinking-plats in dig3 (#2519) 2023-04-17 21:20:54 -04:00
water111 9ba86c8b6a more generic fixes (#2515)
Fixes issue where warp effect looks wrong near the edge of the screen -
there was an unhandled `REGION_CLAMP` texture setting.

Fixes a potential bug where "warp page" things wouldn't be drawn at all
because there is no PC warp bucket. Unclear if anything actually fits
this category, but it doesn't hurt.

Turn on PC-format texture uploads for the water page so the precursor
guy uses the right texture. It has to use generic because it abuses the
generic death query thing to spawn particles.

Workaround for some issues with rebuilding level files after changing
engine files. Not a perfect solution, but probably good enough.
2023-04-17 13:53:38 -04:00
OpenGOAL BotandOpenGOALBot 633b5cd53c CI: Periodic Controller Database Update (#2514)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2023-04-17 13:53:08 -04:00
Tyler Wilding bacacc0f99 g/j2: temporarily disable some gui-control code to fix rock avalanche (#2510)
Related to https://github.com/open-goal/jak-project/issues/2509
2023-04-17 13:52:49 -04:00
ManDude 7a0048872a [jak2] Disable envmap hack if warp effect is enabled (#2511) 2023-04-17 06:10:51 +01:00
ManDude 50d93a3f79 update collision renderer for jak 2 (#2508)
Doesn't actually do anything in Jak 2 because the collide mesh isn't
extracted, but the functionality is all there. Also updated the renderer
a bit to keep the colors more readable.
2023-04-16 22:56:19 -04:00
water111 40c30cc0ab [jak2] fix generic crashes (#2505)
Fixes crashes when killing the big spider, killing predator metal heads,
and watching the end cutscene. The presursor guy is the wrong color, but
I don't have time to look into this today.
2023-04-16 22:55:18 -04:00
water111 a27083f4ee [jak 2] Add generic and warp (#2495) 2023-04-16 18:05:35 -04:00
ManDude 99fe918a1a fix viewport not being set for probe draw (#2489) 2023-04-15 03:09:39 +01:00
water111 c7f2a23abf [jak2] misc fixes to renderers (#2488)
Fixes decal on tfrag:

![image](https://user-images.githubusercontent.com/48171810/232174352-11153941-e1f9-4472-becb-f266c2a309e5.png)

Sets up jak 2 alpha shrub test settings. They are still too dark, but
there's no longer incorrect alpha test:

![image](https://user-images.githubusercontent.com/48171810/232174590-f9caa6c5-f190-4c78-b720-5f4055490d47.png)

Fix decal on shrub, a feature used in exactly one place in jak 1:

![image](https://user-images.githubusercontent.com/48171810/232174614-8ea65ca5-a183-45f7-ae79-6bf06a937007.png)

Fixed issue with u16 overflow in castle on the alpha channel, causing
flickering. It barely overflowed, which made me suspicious that we had
some error somewhere. But I think that there code is robust against
overflows.
2023-04-14 21:13:45 -04:00
ManDude ba12d804f7 jak 2 memcard support (#2482) 2023-04-14 20:39:58 +01:00
ManDude e004780f73 add a toggle for faster airlocks and elevators and enable by default (#2478) 2023-04-14 07:53:14 +01:00
ManDude 7d11c6e100 fix jak 2 text encoding/decoding + minor decomp type fixes (#2476)
Now all text in all non-Korean languages is built correctly.
2023-04-14 02:09:12 +01:00
water111 1f4872b25d [jak2] fix hitting enemies after they die (#2475)
Closes #2473 

The return type of a method was wrong.
2023-04-12 20:43:04 -04:00
water111 6b6a565d1a [jak2] more nav-related nan fixes (#2472)
Fixes citizens that disappear (permanently) when being pushed into a
"wall" which is the border of a nav mesh that is exactly aligned with
coordinate axes.
2023-04-12 19:43:31 -04:00
water111 7b2322777a [jak2] fix disappearing guard (#2470)
This bug feels very similar to punch glitch, where code worked on PS2
only because some value didn't reach exactly 1.0 or 0.0 with ps2-style
floating rounding. It might be better to track down the source of the
"only 1.0 on PC" value, rather than patching downstream code to handle
it, but I can't easily find it in this case - there's a lot of code that
touches this heading value. (it's also possible this bug happens on ps2,
but the result is the guard appears to face the wrong direction, rather
than disappearing).

Detailed debug notes:
Ran a process that just calls this function:
```
(defun print-guard-info ()
  (let ((proc (process-by-name "crimson-guard-level-42" *active-pool*)))
    (when proc
      (format *stdcon* "PROC: ~A~%" (-> proc state))
      (let* ((pd (the process-drawable proc))
             (css (-> pd node-list))
             (cs (-> css data 15))
             )
        (format *stdcon* "joint: ~A~%" (-> cs joint))
        (format *stdcon* "pos: ~`vector`P~%" (-> cs bone position))
        )
      )
    )
  )
```
it prints out the state, and the bone position for some bone that
happens to be on the upper body. It goes to NaN when the upper half
disappears, in the state `tazer-hostile`.

Modified the code in this state to call this function in a bunch of
places:
```
(defun guard-nan-debug ((guard process-drawable) (info string))
  (when (string= (-> guard name) "crimson-guard-level-42")
    (format 0 "[guard-nan] ~S : ~`vector`P~%" info (-> guard node-list data 15 bone position))
    )
  )
```
which prints the bone position to stdout.

This shows that the problem happens after `post`, but before `trans`:
```
[guard-nan] post-end : #<vector 2723306.0000  269921.0312  388825.2187       1.0000 @ #x1f1350>
[guard-nan] trans-start : #<vector          NaN          NaN          NaN          NaN @ #x1f1350>
```
this is probably as part of the bone math.

To check, I added some prints to `execute-math-engine`, before and after
the call to `do-joint-math`:
```
[guard-nan-math] pre-math : #<vector 2722236.5000  268609.5312  385339.9062       1.0000 @ #x1f1350>
[guard-nan-math] post-math : #<vector          NaN          NaN          NaN          NaN @ #x1f1350>
```

The first part of `do-joint-math` is calling the
`generate-frame-function`, which does animation blending to compute a
bunch of joint transforms. I dumped these:
```
              (let ((jaf (the-as joint-anim-frame (+ 2400 (scratchpad-object int)))))
                (format 0 "generate frame:~%")
                (format 0 "~`matrix`I~%" (-> jaf matrices 0))
                (format 0 "~`matrix`I~%" (-> jaf matrices 1))
                (dotimes (i (-> obj mgeo num-joints))
                  (format 0 "~`transformq`P~%" (-> jaf data i))
                  )
                )
```
and confirmed that they always look good.

The next part is "prebind", which allows something to modify the
`joint-anim-frame`. Nothing does this on the guard.

The next part is what I've named the "root bind", which computes the
transform of the root bone based on the process-drawable root's
position.

```
                (when (the-as (function cspace transformq none) t9-3)
                    (when *djm-debug* (format 0 "djm: first bind func ptrs #x~X #x~X~%" cspace<-transformq! t9-3))
                    (when *djm-debug* (format 0 "djm: first bind func input: ~`transformq`P~%" (-> v1-20 param1)))

                    ((the-as (function object object object none) t9-3) v1-20 (-> v1-20 param1) (-> v1-20 param2))
                    (when *djm-debug* (format 0 "djm: first bind func result:~%~`matrix`I~%" (-> v1-20 bone transform)))

                    )
```
in this case, the first print confirms that we're using
`cspace<-transformq!` as the root binding function.

When the guard entirely disappears, it is caused by the root of the
process drawable having NaNs as its `quat`:
```
djm: first bind func input: #<transformq @ #x1f04f0
		trans:2724817.7500  262144.0000  388891.1875       1.0000 
		quat:           NaN          NaN          NaN          NaN 
		scale:      1.0000       1.0000       1.0000       1.0000>
djm: first bind func result:
[001f0e70] matrix
	[         NaN] [         NaN] [         NaN] [         NaN]
	[         NaN] [         NaN] [         NaN] [         NaN]
	[         NaN] [         NaN] [         NaN] [         NaN]
	[2724817.7500] [ 262144.0000] [ 388891.1875] [      1.0000]
```

After this, it's possible to get the lower half of the guard to return,
but I believe the real problem is this first `quat` being NaN. Then the
nans probably spread everywhere.

So now we now to look for the `(-> guard root quat)` becoming NaN:
```
(defun guard-nan-debug ((guard process-drawable) (info string))
  (when (string= (-> guard name) "crimson-guard-level-42")
    (format 0 "[guard-nan] ~S : ~`vector`P~%" info (-> guard root quat))
    )
  )
```

and we see this happens in post somewhere
```
[guard-nan] post-start : #<vector       0.0000      -1.0000       0.0000       0.0000 @ #x1f0500>
[guard-nan] post-end : #<vector          NaN          NaN          NaN          NaN @ #x1f0500>
```

Looking at individual methods
```
[guard-nan] before-142 : #<vector       0.0000      -1.0000       0.0000       0.0000 @ #x1f0500>
            heading: #<vector       0.0000       0.0000      -1.0000       0.0000 @ #x3432670>
[guard-nan] before-143 : #<vector          NaN          NaN          NaN          NaN @ #x1f0500>
            heading: #<vector       0.0000       0.0000      -1.0000       0.0000 @ #x3432670>
```
It looks like the problem is converting this heading to a quaternion.
2023-04-11 20:03:40 -04:00
Tyler Wilding 909190b9a7 gk: fix "reboot in debug" option not working properly when gk has no args (#2469) 2023-04-11 17:58:19 -04:00
OpenGOAL BotandOpenGOALBot 86dfd92f00 CI: Periodic Controller Database Update (#2466)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2023-04-11 17:58:00 -04:00
Tyler Wilding 2a227699fe cli: ensure an overridden project path is absolute (#2464)
Fixes #1771

Probably want to do some testing with the launcher to ensure no breaking
changes

before/after:

![image](https://user-images.githubusercontent.com/13153231/230793111-f3217ef7-5932-4dcd-83ee-d5f2c8d245fd.png)
2023-04-11 17:57:47 -04:00
Tyler Wilding 10ac78200b repl: add gameVersionFolder to repl-config for running the non-default version (#2463)
Adds a decent way to customize the folders the project file expects the
iso data and decompiler data to be in. When you run any version other
than the default, for example Jak 1 PAL, it uses the `gameName`
decompiler config to consume and output it's results.

However the project file will assume `jak1` unless you hard-code it
differently -- basically, it needs to be explicitly told just the
decompiler is told what version to use.

We now have a per-user REPL Config json file, so that can be used to
override the default `jak1` behaviour.

Fixes #1993
2023-04-11 17:57:20 -04:00
ManDude fb62a1fb87 Update README.md (#2468) 2023-04-11 18:37:18 +01:00
Tyler Wilding c8f0f7a8b2 docs/issues: attempt to clarify what version is for the game/OpenGOAL (#2467) 2023-04-10 13:03:53 -04:00
Tyler Wilding 028153d48e d/jak2: cleaning up some old decomp issues (#2462) 2023-04-08 23:29:33 -04:00
Tyler Wilding 3dbbbd37d4 ci: check for incorrect assert usage in C++ files (#2461) 2023-04-08 16:19:37 -04:00
ManDude 59e0c5e264 decomp bigmap (#2460)
Probably the last major missing file.

The bigmap fetches the correct level and map info, but doesn't actually
render anything right now.


![image](https://user-images.githubusercontent.com/7569514/230701921-e3fde09e-9faa-4725-b7e6-5a02a77346bd.png)

![image](https://user-images.githubusercontent.com/7569514/230701928-fbe0847b-b79a-4275-83ec-b9c1d847d17d.png)
2023-04-08 20:30:27 +01:00
ManDude 332326268a make directrenderer in sprite work + rename game-text-id to text-id + move pc debug settings (#2459) 2023-04-08 04:32:35 +01:00
water111 15ab5d704d fix alpha blend bit for jak 1 merc (#2458)
This fixes the sculptor's face shield and red rings on final boss.
2023-04-05 18:56:48 -04:00
Hat Kid f4085a4362 jak1: clean up all dummy methods (#2457)
Cleans up every `dummy-*` and `TODO-RENAME-*` method up with either
proper names or by renaming them to `[type-name]-method-[method-id]`
similar to Jak 2's `all-types`.

Also fixes the bad format string in `collide-cache` and adds the event
handler hack to Jak 1.

The game boots and runs fine, but I might have missed a PAL patch or
other manual patches here and there, please double-check if possible.
2023-04-05 18:41:05 -04:00
ZedB0T 366808d2f9 add a temporary gui-control hack to make boulder chase mission completable (#2455)
add a temporary gui-control hack to make boulder chase mission
completable
2023-04-05 18:23:55 -04:00
Luminar Light c0fdd12626 Translate new Jak 1 speedrunning text to Hungarian, plus some minor adjustments (#2242)
I saw that some new speedrunning-related text was added to the English
language, so I decided to translate them. Meanwhile I also made some
minor adjustments/fixes to existing translations.

BUT I have a question...
Do we really need all this text?

![image](https://user-images.githubusercontent.com/18116946/221017680-cae74597-6627-4be3-a548-44f6c005b6a2.png)
They are displayed in a menu that is called 'NEW INDIVIDUAL LEVEL RUN'.
So adding IL after the level names is kind of redundant in my opinion -
the existing level name text entries could be used instead. And the
reason why I care so much is because it is hard to come up with a
"translation" for IL. But if I am forced to, I will come up with
something.

I will keep this PR a draft until I know what the main jak-project
people think about this "IL" issue. And I will adjust my branch
accordingly.
2023-04-05 18:23:22 -04:00
OpenGOAL BotandOpenGOALBot d686638a6e CI: Periodic Controller Database Update (#2452)
Co-authored-by: OpenGOALBot <[email protected]>
2023-04-03 22:45:00 -04:00
Hat Kid 37af812785 jak2: add some temporary gui-control hacks to make missions completable (#2454) 2023-04-03 23:02:38 +02:00
ManDude 6f1cb2a0a9 fix repl buffer overrun + use a different port for each game version (#2449)
Fixes #2313
2023-04-02 05:57:21 +01:00
Tyler Wilding 57a3254668 lsp: fix route handling json error (#2448) 2023-04-01 19:40:21 -04:00
ManDude b141871bd1 Fix typo (#2447) 2023-03-31 20:27:25 -04:00
Tyler Wildingandwater 3c22eb061f d/jak2: helldog (#2445)
The last of the missions that had a missing file.

I manually fixed some casting related to a `handle->process`, since this
is the last file...whatever not worth stressing about. But probably an
issue that will crop up in the future.

Co-authored-by: water <[email protected]>
2023-03-31 18:38:34 -04:00
2c98c5a6e0 Italian subtitles (WIP) (#1568)
Draft until all the english subtitles are finished.
Many things still in WIP and everything is subject to change.

TODO:

* [x]  intro
* [x]  sidekick
* [x]  oracle
* [x]  training
* [x]  village1
* [x]  beach
* [x]  jungle
* [x]  misty
* [x]  firecanyon
* [x]  village2
* [x]  swamp
* [x]  rolling
* [x]  sunken
* [x]  ogre
* [x]  village3
* [x]  snowy
* [x]  spidercave
* [x]  lavatube
* [x]  citadel
* [x]  finalboss
_____________
* [x]  default
_____________
* [x]  timings
* [x]  game_text_it.gs

---------

Co-authored-by: pex93 <[email protected]>
Co-authored-by: OngakuGH <[email protected]>
Co-authored-by: Vas0sky <[email protected]>
Co-authored-by: XedoIT <[email protected]>
Co-authored-by: XedoIT <[email protected]>
Co-authored-by: ManDude <[email protected]>
2023-03-31 18:34:19 -04:00
Hat Kid 318c76775c decomp: shuttle (#2444) 2023-03-31 18:17:47 -04:00
water111 57b5117cae [jak2] decomp neon-baron-part, fix merc fog disable (#2443)
- decompile `neon-baron-part`, which also has the hideout door for some
reason
- improve a few error messages in static data decompilation
- fix bug with disabling fog in merc
2023-03-31 17:47:38 -04:00
Xavier Siguero Mora 1b27257e8a Updated Spanish translation (#2322) 2023-03-31 16:43:48 -04:00
ManDude 577382ad34 minor cleanup + update fmt + fix some jak 2 visual anomalies (#2442)
Disables the fog hack for Jak 2, where it's not useful and kind of
breaks in most levels which rely on dark vertices that aren't underwater
(e.g. city windows).
2023-03-30 17:49:07 -04:00
water111 976e08fe97 [jak2] add vortex renderer (#2441)
Add the vortex renderer. The vortex texture isn't there yet (it uses the
same texture as clouds), so it uses a checkerboard. But the
colors/vertices seem right.
2023-03-29 20:28:48 -04:00
Dillon Pentz 4f6b6e4c82 [jak1] deduplicate jak1_pal label_types entries (#2435)
Removes entries from the jak1/pal/label_types.jsonc file that are exact
matches in the ntsc_v1 file.
2023-03-29 18:25:28 -04:00
OpenGOAL BotandOpenGOALBot 651003dcf2 CI: Periodic Controller Database Update (#2436)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2023-03-29 18:24:48 -04:00
ZedB0T f04083d997 Dont overwrite profile data (#2440)
This way a user can take multiple data samples from one/multiple play
sessions quickly. Creates a directory called profile_data that is added
to gitignore to place the data in, and checks to see if a file is there
and if so it creates prof1.json prof2.json prof3.json and so on...
2023-03-29 18:24:28 -04:00
Dillon Pentz d6c5d32cd3 [jak2] add pal decomp support (#2434)
Unsure what hacks or type casts might eventually be needed for the PAL
version, but these changes are enough to get things to extract and run
the game (though the extract phase requires iso_data to be in a jak2_pal
folder, but the build still looks for jak2 in iso_data and
decompiler_out).
2023-03-27 00:11:10 -05:00
ManDude 013a4f4612 [jak2] entity debug improvements and add a hack to make airlocks faster because we can + fix defend stadium (#2432) 2023-03-27 02:55:16 +01:00
water111 0b021d1be1 [jak2] fix nav typo (#2430)
add -> multiply.

Fixes https://github.com/open-goal/jak-project/issues/2429
2023-03-26 18:41:59 -04:00
water111 d208ceddce [jak2] fix enter-state and sprite crash (#2428)
Fixes https://github.com/open-goal/jak-project/issues/2426 and other
sprite crashes with the `HUD` address assert.
Doesn't fix the other sprite issues.

Fixes https://github.com/open-goal/jak-project/issues/2427

Also removes the old sprite renderer, which doesn't work.
2023-03-26 15:41:10 -04:00
water111 9e087cbfcb [jak2] a few small graphics fixes (#2424)
- better handling of the `disable-fog` settings for merc, should fix the
spotlights. There's a setting in the merc effect, and also a runtime
flag for the draw-control. I'm not actually sure what reads these, but
the draw-control one is definitely used to disable fog on the
spotlights.
- increase merc draw limit to try to fix the issue about partially drawn
citizens in the city
- remove useless debug prints (it's okay to die in init, and the medium
load buffer size mode is understood now)
2023-03-26 12:30:35 -04:00
ManDude 7170db51ea fix bad defpartgroup decomp and improve entity debug display a bit (#2423)
- Makes very nasty bugs fixed in #2402 print onscreen when detected
instead of to the console.

![image](https://user-images.githubusercontent.com/7569514/227754516-d508376e-8b23-4af6-bc44-e4d33d586e17.png)
- Fixes `valid?` decomp
- Moves `entity-debug.gc` to the end of `COMMON.CGO` so we can check for
keys in a few more commonly-used actor types.
- Entity debug display (jak 2) now properly parses the `art-name` tag of
part spawners, which gets overwritten at runtime.
- Fixes #2422 . Decompiler was writing out part group rotation for the
scale part, so all of those part groups had a zero in one (or all) of
the axes. This "only" affected 38 groups, including all of the flame
pots in tomb, jetpack guard, wasp, onin tent seal of mar, dark eco pill
and a few other things.

![image](https://cdn.discordapp.com/attachments/995787558816595968/1089395776880390174/image.png)

![image](https://cdn.discordapp.com/attachments/995787558816595968/1089395777253671013/image.png)
2023-03-26 05:13:54 +01:00
water111 d82ce11e9b [jak2] update sprite to check matrix == -1 (#2415)
Fixes an issue where glow sprites are drawn twice, sometimes causing the
weird black outlines
2023-03-25 19:46:07 -04:00
water111 58654ce60b [jak2] Fix degrees conversion for particle rotation (#2413)
Hopefully this will fix all the rotated particles
2023-03-25 18:01:43 -04:00
water111 cbb07fb287 [jak2] Fix texture page dir offset for jak 2 (#2412)
Accidentally used Jak 1's tpage dir size...
2023-03-25 16:34:03 -04:00
water111 0a511da2ce [jak2] fix flickering and depth writes (#2406)
Fixes some mistakes with merc draw modes. The glass in the palace level
no longer writes to the depth buffer (it's "water"):

![image](https://user-images.githubusercontent.com/48171810/227727825-d6726621-88a8-45a8-9cf3-8d6e9edc3d54.png)

Also fixes the one-frame flickers when level draw orders change. We
might be able to make this more efficient in the future, but this will
at least fix the frame with nothing drawn.
2023-03-25 14:00:54 -04:00
Tyler Wilding ebdb0ecadd scripts: fix edge-case in gsrc skeleton creation script (#2404) 2023-03-24 13:41:50 -04:00
ManDude cc16f62428 [jak2] fix bad actors using unloaded types (#2402)
Actors that use types from a level that got unloaded should now get
killed immediately instead of continuing to exist and eventually crash
the game.

NOTE: Will spam the console whenever a bad actor tries to spawn. I would
like to document all instances of where this happens!
2023-03-24 07:18:43 +00:00
ManDude f56e807d75 [jak2] fix speed for spool anim hack (#2401)
Recent subtraction compiler bug fix exposed this.
2023-03-23 20:01:13 +00:00
water111andManDude 56eeb20e4c [goalc] fix bug in subtraction (#2399)
fixes the turrets pointing down in fortress dump mission

Co-authored-by: ManDude <[email protected]>
2023-03-23 18:09:27 +00:00
ManDude 2e34514ee5 [jak2] increase size of DMA buffers + potentially fix print buffer bug (#2398)
The actor heap size was increased but not the DMA buffer because I
forgot.
2023-03-23 01:15:07 +00:00
ManDude 3b666beae2 [jak2] implement abandon-thread (#2396)
implements `abandon-thread` for when we want to return from a thread,
but are in a `post` thread which normally disallows this.
2023-03-23 00:41:51 +00:00
water111 b7fc7383b7 [jak2] fix dark things (#2393) 2023-03-22 20:09:50 -04:00
ManDude dbaf93dc73 Update jak2_config.jsonc (#2392) 2023-03-22 23:48:23 +00:00
ManDude 3b7be01af1 [decompiler] fix crash when no spools are loaded (#2391)
agh
2023-03-22 18:53:05 -04:00
ManDude 217a979048 [decompiler] jak 2 cutscene file support (#2390)
fixes #2332 

also fills out the japanese character set
2023-03-22 21:31:13 +00:00
water111 b18198e655 [jak2] fix atest flag in tfrag (#2381)
Support the weird `tfrag-gs-test` and `texture-page-flag` stuff added in
jak 2. Solves some issues with partially invisible tfrags.
2023-03-21 20:40:29 -04:00
water111 df646282ab [jak 2] fix texture lookup problem (#2373)
This should fix a bunch of texture-related issues by generating a table
of overlapping textures and just... adjusting them slightly so they
don't overlap. It's not the most elegant solution in the world, but I
think it's no worse than the existing hard-coded tpage dir stuff.
2023-03-21 19:41:14 -04:00
water111 f276251a3a [jak1] use etie (#2329)
Use Jak 2's etie to render shiny background things.

To switch back to the old one:
```
(set! *use-etie* #f)
```
and also uncheck this box

![image](https://user-images.githubusercontent.com/48171810/226119270-8d1b8233-bc5f-4bc1-a09b-a6d3183ba2a4.png)
(same for `l1`)
2023-03-20 19:12:33 -04:00
ManDude d1260a0c0b [jak2] double load dgo workaround (#2331)
fixes #2282
2023-03-19 20:30:23 +00:00
ManDude d46f790973 [jak2] un-hardcode level-related code a bit (#2330)
Makes it less of a headache to change level amounts.
2023-03-19 05:33:04 +00:00
ManDude 198c8e1946 [jak2] improve debugging tools for entity lights and regions (#2327)
also fixes some other random bugs
2023-03-18 06:29:40 +00:00
water111 2fa4a23ea1 [jak 2] ETIE (#2326)
Definitely needs a clean up pass, but I think the functionality is very
close.

There's a few "hacks" still:
- I am using the emerc logic for environment mapping, which doesn't care
about the length of the normals. I can't figure out how the normal
scaling worked in etie. I want to do a little bit more experimentation
with this before merging.
- There is some part about adgifs for TIE and ETIE that I don't
understand. The clearly correct behavior of TIE/ETIE is that the alpha
settings from the adgif shader are overwritten by the settings from the
renderer. But I can't figure out how this happens in all cases.
- Fade out is completely disabled. I think this is fine because the
performance difference isn't bad. But if you are comparing screenshots
with PCSX2, it will make things look a tiny bit different.
2023-03-17 20:35:26 -04:00
ManDude 6670124296 [jak2] use loop to make bucket renderers (less error-prone) (#2324) 2023-03-17 20:10:06 +00:00
Hat Kid a857061e96 jak2: focus-test? macro, fix (zero? (logand ...)) -> (not (logtest? ...)) detection (#2321)
There are *a lot* of file changes and while I have carefully gone
through every gsrc change to fix up manual patches, there might still be
spots that I missed.
2023-03-14 22:57:31 -04:00
ZedB0T 9a28cc5a79 Add a autosplit-flag-task-complete! macro (#2317)
Cuts out a little bit of repetition in the autosplit code. Also adds
some labels to the VS configurations.


https://github.com/Zedb0T/jak-project/blob/090c4977993dd41546615d3da9dc4937d89ca243/goal_src/jak1/pc/features/autosplit-h.gc#L167-L169
2023-03-14 17:56:58 -04:00
OpenGOAL BotandOpenGOALBot 5b8644ea20 CI: Periodic Controller Database Update (#2323)
Co-authored-by: OpenGOALBot <[email protected]>
2023-03-13 18:51:49 -04:00
Tyler Wilding 94a32dfd8a ci: stop emitting event to the launcher repo (#2320) 2023-03-12 21:39:48 -04:00
ManDude 0cf285ef99 [jak2] decomp cleanup of traffic things + fix stadium crash (#2319) 2023-03-11 22:45:14 +00:00
ManDude 0c64d48b0d [jak2] force-envmap? hack (#2316)
Also affects texscroll and ripple, but I'm not sure what would be good
places to test those.
2023-03-11 22:13:55 +00:00
Hat Kidandwater a1dee19d0d decomp: finish stadium-obs (#2294)
Co-authored-by: water <[email protected]>
2023-03-11 15:55:39 -05:00
ManDude 77242bd12e [jak2] script-eval macro (#2315)
turns
```lisp
      (eval! (new 'stack 'script-context (process->ppointer self) self (the-as vector #f)) '(teleport))
      (eval! (new 'stack 'script-context (process->ppointer self) self (the-as vector #f)) (-> arg0 on-goto))
```
into
```lisp
      (script-eval '(teleport))
      (script-eval (-> arg0 on-goto))
```
2023-03-11 10:45:16 -05:00
ManDude 70452a753f [jak1] fix game-save debug printing (#2314) 2023-03-10 22:02:04 +00:00
ManDude 93992795f9 [jak1] disable auto-save-check (#2312)
Fixes unnecessary performance degradation when auto-save is enabled.
2023-03-10 05:22:50 +00:00
Tyler Wilding 630388229e cleanup gk CLI and fix issue that caused revert (#2310)
My mistake -- testing focused too much on preserving the existing
behaviour I clearly forgot to make sure the new stuff worked properly.

Just had to early out and not modify the args if they were in the new
format.
2023-03-09 23:13:01 -05:00
ManDude 3ce7f59989 [jak1] fix concerning game-save bug (#2311)
Not really sure if this actually caused any issues in-game, but better
safe thatn sorry.
2023-03-10 03:47:35 +00:00
ManDude 9cb2963cde add debug joint renderer (#2309) 2023-03-10 03:12:44 +00:00
ManDude 88179d14d7 remove unused batch files (#2308) 2023-03-10 02:56:41 +00:00
water111 9c7b86c595 [jak2] fix blerc profile bar issue (#2307)
Fix so the profile bar doesn't do something silly when
`merc-blend-shape` returns early, skipping the part where `end-time` is
set.
2023-03-10 02:10:43 +00:00
water111 15bf281377 Revert "game: cleanup gk's CLI documentation" (#2306)
Reverts open-goal/jak-project#2189

can't figure out how to use the new options yet
2023-03-09 20:24:43 -05:00
Tyler Wilding 021bae08ec d/jak2: fix elevator issues and cleanup script-context new method (#2304)
This fixes the issue where elevators leave you behind (stack structure
related)

At the same time I cleaned up some things I found along the way, most
notably changing `script-context`'s `basic` field to `object` as
non-basics use this method as well.

Fixes #2305
2023-03-09 20:03:43 -05:00
Tyler Wilding 2f6bfd2e64 game: cleanup gk's CLI documentation (#2189)
An attempt to cleanup the last CLI interface we have left to cleanup. 
- `gk` args now follow the typical convention ie. `--proj-path` instead
of `-proj-path`.
- args that are passed through to the rest of the application / the
game's runtime use the typical convention of following a `--`
- I'm thinking some args shouldn't be handled at this level ie
(`-nodisplay`, `-vm`, `-novm` or `-jak2`) These could be better
documented as legitimate flags and passed in via a nice struct. They
don't seem to be used in `InitParams` but I'll triple check.

There's a temporary shim here so there is no coupled release with the
launcher (right now it executes `gk` with a few args). So I just change
the old args into the new format. After one release cycle, I can change
it in the launcher and delete it here.

I am unsure if this will break the bash shellscript usages -- not sure
which args were usually passed into `$@`


![image](https://user-images.githubusercontent.com/13153231/222035309-b6601719-cdc9-40ee-b36e-e4b135d3f128.png)
2023-03-09 20:02:25 -05:00
water111 0db9b288e4 [merc2] Support texscroll, use in jak 1 in more places, fix envmap bug (#2303)
Three main changes:

- Adds support for the texture scrolling effect used on conveyor belts,
and turn it on for jak 2.
- Use merc instead of generic in jak 1 for ripple/water/texscroll stuff
(non-ocean water, lava, dark eco, etc). This is a pretty big speedup in
a lot of places.
- Fix a really old bug with blending mode used to draw environment maps.
The effect is that envmaps were half as bright as they should have been.

As usual, there's a flag to go back to the old behavior on jak 1. Set
these to `#t` to use generic like we used to.
```
*texscroll-force-generic*
*ripple-force-generic*
```

The format has changed, and everything must be rebuilt (C++, FR3's, GOAL
code)
2023-03-09 20:01:22 -05:00
Tyler Wilding 6d99f1bfc1 d/config: re-organize decompiler/config and eliminate most of the duplication (#2185)
Reasons for doing so include:
1. This should stop the confusion around editing the wrong config file's
flags -- when for example, extracting a level. Common settings can be in
one central place, with bespoke overrides being provided for each
version
2. Less verbose way of supporting multiple game versions. You don't have
to duplicate the entire `type_casts` file for example, just add or
override the json objects required.
3. Makes the folder structure consistent, Jak 1's `all-types` is now in
a `jak1` folder, etc.
2023-03-08 20:07:26 -05:00
water111 0b8b927315 [merc] support eyes through merc (#2300)
Support rendering eyes with merc for both jak 1 and jak 2.

For jak 1, everything should look the same, but merc will be used to
draw eyes. This means that jak is now fully drawn with merc!

For jak 2, eyes should draw, but there are still a few issues:
- the tbp/clut ptr trick is used a lot for these eye textures, so
there's a lot that use the wrong texture
- I had to enable a bunch more "texture uploads" (basically emulating
the ps2 texture system) in order to get the eyes to upload. It would be
much better if the eye renderer could somehow grab the texture from the
merc model info, skipping the vram addressing stuff entirely. I plan to
return to this.
- I disabled some sky draws in `sky-tng`. After turning on pris2
uploads, the sky flashed in a really annoying way.
2023-03-08 18:18:35 -05:00
Tyler Wilding 00d7065790 goalc: remove deprecated CLI args from goalc and remove empty repo folders (#2301)
This gets rid of the `auto-lt` and `auto-dbg` CLI args to `goalc` that
have been marked deprecated for a month or so at this point. The
behaviour can be replicated via the `startup.gc` file.

I also removed `decompiler_out/` and `log/` from the repo, as our C++
code is smart enough to create these directories if they are missing now
so they are superfluous
2023-03-08 18:18:24 -05:00
OpenGOAL BotandOpenGOALBot 0424cd1f7f CI: Periodic Controller Database Update (#2302)
Co-authored-by: OpenGOALBot <[email protected]>
2023-03-06 16:55:37 -05:00
Tyler Wilding bc40fc5d2f util/file: cleanup log initialization and some file-util functions (#2299)
Fixes both issues mentioned in #2297
2023-03-01 17:52:33 -05:00
ZedB0T 43da4088e6 Fix Bombbot crash (#2296) 2023-02-28 20:39:57 +01:00
water111 d6bd437ea1 [merc] support up to 64 effects (#2292) 2023-02-27 21:02:47 -05:00
water111 2c12a4e00b [jak2] WIP minimap (#2280)
Work in progress minimap. Known issues:
- "path finding" doesn't appear to work - it gets stuck forever in many
cases
- some nasty patches around timer-based code
- jak arrow blending issues
- would be nice to make it higher resolution

if the search is forced to terminate due to iteration/time limits, the
icon is not in the right place

![image](https://user-images.githubusercontent.com/48171810/221432792-678d6124-a6a6-4875-a91f-7eceedbfec98.png)
2023-02-27 19:51:14 -05:00
ManDude 1d0a5ade8d [jak2] minor decomp cleanup + add force actors and sprite pc hacks (#2291)
I didn't actually visually notice much of a difference with these hacks
unlike in Jak 1, but I also avoided checking the missions thoroughly
since the game crashes very often right now.
2023-02-28 00:35:57 +00:00
Tyler Wilding c3310e1833 docs: fix method docstrings and grab @file comment blocks to use as a file description (#2289) 2023-02-27 18:58:01 -05:00
Tyler Wilding 87ff182332 dbgr: allow dumping the backtrace to a file (#2284)
Some backtraces are quite large, an option is to increase your terminal
buffer -- but dumping to a file is also useful if you want to share the
crash.

I'm not crazy about the way I hacked this in, but it felt like the least
invasive way for now and I don't want to cause a regression with the
debugger. It's also nice that it dumps with ansi colors as then you can
view the backtrace with the original coloring:


![image](https://user-images.githubusercontent.com/13153231/221460358-991916ad-90f0-445d-ba81-7bc3dbc42eb4.png)

Usage:
```clj
(:di "./stacktrace.log")
```
2023-02-27 18:54:23 -05:00
Hat Kid adf929d18d decomp: ruf-*, jinx-*, mog-*, grim-*, hosehead-* files, gun-buoy (#2279) 2023-02-27 18:53:57 -05:00
ManDude e1e6695e92 [jak2] merc lod hacks + region debugger + make level heap less massive (#2285) 2023-02-27 18:45:32 +00:00
OpenGOAL BotandOpenGOALBot 3c6446f641 CI: Periodic Controller Database Update (#2287)
Co-authored-by: OpenGOALBot <[email protected]>
2023-02-27 13:08:25 -05:00
ManDude fb20bf34df rotate log files (#2283)
Fixes #1228 (wow only took 1 year)
2023-02-26 22:56:25 +00:00
Hat Kid 736a3a8b7c jak2: fix jellyfish crash and temporarily disable underwater warp (#2270)
Fix crash when the game tries to spawn `jellyfish` in Underport and
temporarily disable the rendering of the warp effect until it's properly
implemented.
2023-02-26 17:24:05 -05:00
ManDude 63ff337169 [jak2] fix crash with *print-column* loading the wrong memory (#2281)
`inspect` also prints with the correct indent now as a result.
2023-02-26 21:04:05 +00:00
Matt Dallmeyer 9b80bca589 Add Speedrun Category Extensions (#2195) 2023-02-26 13:42:24 -05:00
water111 e48ae247c4 [jak2] fix palace rotation and sprite glow depth test (#2269)
- Disable depth test for sprite glow (VU1 programs only `sq.xy` and
leaves `z` alone, which has Z_MAX from the template)
- Fix tfrag/tie/shrub issues when `use-camera-other` is set.
2023-02-26 09:52:04 -05:00
Tyler Wilding 90d5e83d9e d/jak2: finish forest-obs (#2266) 2023-02-26 09:49:16 -05:00
ManDude 190fa4bbe8 [windows] make the games start up in the user's preferred system UI language (#2267)
Where applicable, of course.

My system language is set to English so I actually can't test this. If
anyone has their Windows language (NOT LOCALE) set to Spanish, German,
French, Italian or Japanese please test this.

Fixes #1734 

Also fixes the opengoal debugger on Windows and fixes the decomp for
`menu` which was causing some crashes related to input handling.
2023-02-26 09:46:57 -05:00
water111 928dbebee4 [jak2] fix highly aggressive guard zoomer ambush (#2264)
`*alert-level-settings*` was actually an inline array and we were
indexing past the end of it.
I think this will fix some of the strange on-foot guard behavior too.
2023-02-26 01:31:21 -05:00
water111andManDude 41fabd43f7 [sprite glow] fix crashes (#2256)
Co-authored-by: ManDude <[email protected]>
2023-02-25 20:21:42 -05:00
ManDude 618455500d Fix Jak 2 scissoring (#2257)
fixes #2255 and hopefully didn't break Jak 1
2023-02-26 00:09:35 +00:00
water111 8a363c2fc9 [jak2] fix foreground light calculation (#2254)
Fixes the abrupt change in lighting when walking around here

![image](https://user-images.githubusercontent.com/48171810/221382856-17f0ec18-1ce8-40f9-b65c-a59cf2d7d93f.png)
2023-02-25 17:55:55 -05:00
water111 3f1f443d58 [jak 2] fix boot, increase level heap sizes (#2252)
Increase level heaps and borrow heaps. The level heap increase was
likely not needed, but better safe than sorry. We allocate the 128 MB
main heap anyway so there's no harm.

Also fix the crash when using `-boot`. As I thought it was just a
one-line typo in the kernel.
2023-02-25 15:20:17 -05:00
ManDudeandwater ad9a532ff9 [jak2] text aspect ratio fixes (#2251)
Fixes the aspect ratio of the font renderer (Jak 2 does not need the
same hacks as Jak 1), the custom letterbox/pillarbox sizes and fixes the
heap display.

---------

Co-authored-by: water <[email protected]>
2023-02-25 19:27:58 +00:00
water111 909da024fc [decomp] ctywide-obs (#2250)
finish this up
2023-02-25 14:00:16 -05:00
ManDude 4b8b2abbed port pckernel to Jak 2 (#2248)
Adds the `pckernel` system to Jak 2, allowing you to do the PC-specific
things that Jak 1 lets you do like change game resolution, etc.

In other to reduce the amount of code duplication for something that
we're gonna be changing a lot over time, I split it into a few more code
files. In this new system, `pckernel-h.gc`, `pckernel-common.gc`
(previously `pckernel.gc`) and `pc-debug-common.gc` are the files that
should be shared across all games (I hacked the Jak 2 project to pull
these files from the Jak 1 folder), while `pckernel-impl.gc`,
`pckernel.gc` and `pc-debug-methods.gc` are their respective
game-specific counterparts that should be loaded after. I'm not fully
happy with this, I think it's slightly messy, but it cleanly separates
code that should be game-specific and not accidentally copied around and
code that should be the same for all games anyway.
2023-02-25 10:19:32 -05:00
water111 e2b7e5c001 [goalc] reduce compiler memory usage (#2247) 2023-02-24 18:32:30 -05:00
Tyler Wilding e10ca97891 repl: prevent REPL crash when running (reload) (#2243)
Stops the REPL crashing with `device or resource busy` when running
`(reload)`

However I think this is indicative of a bigger problem where either the
`Compiler` or prompt is not ready to handle input immediately after
creation and setting the status to `OK`.
2023-02-24 18:04:10 -05:00
Matt Dallmeyer e89f0770dc Fix Jak 2 warp gates (#2244) 2023-02-24 19:33:27 +01:00
Hat Kid 2d8ad39fea jak2: add back some pc port debugging tools and add palace-scenes to gsrc (#2240)
Ports some of the custom PC port debugging code from Jak 1, such as the
entity debugger, Anim Tester X and part tester, to Jak 2 and gives the
PC menu code the same treatment Jak 1 received recently in #2216.
Some adjustments have been made to make things work in Jak 2 and some
stuff is still incomplete.
The majority of the default PC menu code has been left commented out in
preparation for @ManDude's plan to port the rest of the Jak 1 `pckernel`
features to Jak 2.

Also adds the code for `palace-scenes` to gsrc as that seems to have
been missed.
2023-02-23 21:39:02 +00:00
Dillon Pentz 66c680e8a3 [jak2] fix rare civilian flee crash (#2230)
Fixes a rare crash that can sometimes happen when civilians are picking
a direction to flee in, where a branch count may be 0, causing a divide
by 0 MATH_EXCEPTION.
2023-02-21 01:30:09 -05:00
Tyler Wilding a76f558537 ci: gen-docs propagate the runId since thats the best we can do (#2238) 2023-02-20 22:52:33 -05:00
Tyler Wilding 3c3d45d497 ci: set cmake preset in informing workflow (#2237) 2023-02-20 22:14:47 -05:00
water111 08ce65fd9b [jak2] add sprite glow renderer (#2232)
Adds the "sprite glow" renderer, which is responsible for the glowing
lights.
2023-02-20 20:25:45 -05:00
Matt Dallmeyer f388898d7b Speedrun verification text cleanup (#2229)
We only draw this text to the screen if we're in speedrunner mode
anyway, so the `#t` flag on this line doesn't really add any value imo

https://github.com/open-goal/jak-project/blob/b130b2eac27966c43f6816ee604a3a93a67e82fa/goal_src/jak1/pc/features/speedruns.gc#L248-L255


![image](https://user-images.githubusercontent.com/2515356/220177466-4ecb8376-7953-4161-a6ca-a300b6978d3e.png)
2023-02-20 19:49:57 -05:00
Tyler Wilding 39658dfd71 docs: Automatically generate documentation from goal_src code (#2214)
This automatically generates documentation from goal_src docstrings,
think doxygen/java-docs/rust docs/etc. It mostly supports everything
already, but here are the following things that aren't yet complete:
- file descriptions
- high-level documentation to go along with this (think pure markdown
docs describing overall systems that would be co-located in goal_src for
organizational purposes)
- enums
- states
- std-lib functions (all have empty strings right now for docs anyway)

The job of the new `gen-docs` function is solely to generate a bunch of
JSON data which should give you everything you need to generate some
decent documentation (outputting markdown/html/pdf/etc). It is not it's
responsibility to do that nice formatting -- this is by design to
intentionally delegate that responsibility elsewhere. Side-note, this is
about 12-15MB of minified json for jak 2 so far :)

In our normal "goal_src has changed" action -- we will generate this
data, and the website can download it -- use the information to generate
the documentation at build time -- and it will be included in the site.
Likewise, if we wanted to include docs along with releases for offline
viewing, we could do so in a similar fashion (just write a formatting
script to generate said documentation).

Lastly this work somewhat paves the way for doing more interesting
things in the LSP like:
- whats the docstring for this symbol?
- autocompleting function arguments
- type checking function arguments
- where is this symbol defined?
- etc

Fixes #2215
2023-02-20 19:49:37 -05:00
OpenGOAL BotandOpenGOALBot 65f2146d73 CI: Periodic Controller Database Update (#2231)
Co-authored-by: OpenGOALBot <[email protected]>
2023-02-20 16:39:41 -05:00
Matt Dallmeyer b130b2eac2 Redundant (declare-file (debug)) (#2226)
Just noticed this while looking into #2225 , this line is repeated a few
lines later

https://github.com/open-goal/jak-project/blob/b9cd17b20a29a4674d8515e53bf937a92f331b6c/goal_src/jak1/engine/camera/cam-layout.gc#L8-L13
2023-02-18 17:26:33 -05:00
water111 b9cd17b20a [jak1] fix crash on startup (#2225) 2023-02-18 17:19:22 -05:00
Hat Kidandwater d946a09a99 decomp: palcab-obs (#2222)
Co-authored-by: water <[email protected]>
2023-02-18 15:59:34 -05:00
water111 b7cfd80b14 set up fog for jak 2 (#2223)
![image](https://user-images.githubusercontent.com/48171810/219878142-8ad7c154-9f52-4ad8-a315-1c932e24cd4b.png)
2023-02-18 15:45:13 -05:00
Hat Kid f452a504e6 decomp: race-* files (#2224) 2023-02-18 15:45:00 -05:00
OpenGOAL BotandOpenGOALBot 466ef6af3d CI: Periodic Controller Database Update (#2217)
Updating Controller Database

Co-authored-by: OpenGOALBot <[email protected]>
2023-02-18 11:01:47 -05:00
Hat Kidandwater d65d6233d9 decomp: kidesc-*|crocesc-* files, ash4-course (#2219)
Co-authored-by: water <[email protected]>
2023-02-18 11:01:24 -05:00
Hat Kid 7a2575fd23 decomp: meet-brutter (#2218) 2023-02-18 10:30:29 -05:00
Matt Dallmeyer 4c812658f1 Easier combo for Speedrun Options (#2196)
Some people have complained about the button combo for entering the
speedrun menu, saying it's awkward to press Start.

This change lets you press Select instead (while holding L1+R1+X). The
old combo (pressing Start) still works as well.
2023-02-18 09:51:26 -05:00
ManDude ee3bc182e1 [jak1] force credits to use audio language instead of text language (#2220) 2023-02-14 20:12:45 +00:00
ManDude 324def1303 split new pc features in some files into their own code files + address some old issues + ripple graphics improvements (#2216)
Moves PC-specific entity and debug menu things to `entity-debug.gc` and
`default-menu-pc.gc` respectively and makes `(declare-file (debug))`
work as it should (no need to wrap the entire file in `(when
*debug-segment*` now!).

Also changes the DGO descriptor format so that it's less verbose. It
might break custom levels, but the format change is very simple so it
should not be difficult for anyone to update to the new format. Sadly,
you lose the completely useless ability to use DGO object names that
don't match the source file name. The horror!

I've also gone ahead and expanded the force envmap option to also force
the ripple effect to be active. I did not notice any performance or
visual drawbacks from this. Gets rid of some distracting LOD and some
water pools appearing super flat (and pitch back for dark eco).

Fixes #1424
2023-02-13 21:39:14 +00:00
water111 ed38adc2a7 [tie] support per-proto visibility flags (#2212)
Jak 2 adds a feature to disable protos in TIE. It's used to hide things
like steps for a future mission in ruins, and also to hide the static
version of the tower when it switches to the merc version for the
cutscene:


![image](https://user-images.githubusercontent.com/48171810/218270077-d8c52235-ddbf-4194-80f6-b8aa1eeeb7ec.png)
2023-02-11 12:00:05 -05:00
Hat Kidandwater 7afa583bff decomp: metalkor-* files (#2211)
Manual patches:

- `metalkor-egg-reaction`: Rewrote `(.mula.s)`

---------

Co-authored-by: water <[email protected]>
2023-02-11 09:34:31 -05:00
Hat Kidandwater 3f5898b5c2 decomp: castle-baron (#2208)
Manual patches:

`(trans idle krew-boss)`: `collide-shape` array created on the stack
changed to `(pointer collide-shape)`

---------

Co-authored-by: water <[email protected]>
2023-02-11 09:24:40 -05:00
Hat Kid cd655ea916 jak2: fix drill-eggs crash (#2209)
Closes #2210
2023-02-11 09:08:08 -05:00
water111 c249dbc437 [jak2] improve loader for jak 2 levels (#2206)
Add a debug window for the loader to show levels and fix an issue with
jak 2 level unloading. I never really thought about how this works for >
2 levels, and there is a chance that you could unload the wrong level in
some cases.

The problem is some combination of merc-only levels not counting toward
the "in use" detection, and the unloader ignoring what the game wants to
load.

I don't remember why using merc models doesn't contribute to "in use"
but I'm afraid to change this for jak 1. Instead, we can have the
unloader avoid unloading levels that the game is telling us are loaded.
This is what we should have done originally, but there was a time when
Jak 1 didn't tell the loader anything, and we had this stupid detection
thing.

I think this is the first step toward just getting rid of the "in use"
detection and trusting the game for everything.
2023-02-09 20:44:33 -05:00
water111 e41ca8903e [jak2] fix alpha test in lightning (#2204)
fixes the lightning fade out effect seen when jak touches the electric
gate.
2023-02-09 19:51:28 -05:00
Tyler WildingandOpenGOALBot a02a75525d CI: Periodic Controller Database Update (#2202)
Co-authored-by: OpenGOALBot <[email protected]>
2023-02-09 19:50:07 -05:00
water111 e26efcc4f3 [jak 2] add lightning renderer (#2203)
Implements the jak 2 lightning renderer as an alternate path through
Generic2. Also set up some generic stuff in the goal code.

There is a problem with the texture pool, which doesn't support the case
where two textures have the same tbp, but different cluts. So lightning
is often the wrong color (usually red).
2023-02-09 19:11:13 -05:00
Tyler Wilding 722ffa3f19 ci: switch to a pull request instead of a direct commit for updating controller db (#2201)
The direct commit option doesn't work as there is no way to bypass
required status checks -- this makes the merge queue less useful. Switch
to a PR instead.
2023-02-09 18:42:09 -05:00
Tyler Wildingandwater 65812f722c d/jak2: seal-at-waterslums working, and do a pass through all missions (#2199)
I did a pass through all missions, fixing issues as they came up. Also
got `seal-at-waterslums` working -- the best mission in the game 🥳

Co-authored-by: water <[email protected]>
2023-02-09 18:40:01 -05:00
Hat Kid 67d4eda169 decomp: hover-* files, wasp, crimson-guard-hover, flamer, target-turret, drill-turret, jellyfish (#2198)
Manual patches:

- `drill-turret`: The static data for `*turret-13-path*`,
`*turret-14-path*` and `*turret-15-path*` was decompiled by hand and the
integers in the `set-speed-mult` events have been replaced with boxed
integer arrays that contain only that integer in order to make the
compiler happy. To that effect, the event handler in `target-turret` was
changed to access that array instead of just accessing the int.
- `hover-nav-control`: In `hover-nav-control::10`, `arg2` is usually a
`vector`, but there are some places where it is called with `#t` as
`arg2` and, subsequently, crashes the game because it tries to access
the `quad` of `arg2` if `arg2` is truthy. To mitigate this, the
condition `arg2` has been replaced with `(and (!= arg2 #t) arg2)` (in
this case, it would jump to the `else` that just resets the `dest-vel`
and `transv` `quad`s)
- `drill-baron`: The static data for `*drill-ship-turret-speed-event*`
has been decompiled by hand.

TODOs:
- Jellyfish crash the game
- Destroying the metalhead eggs that are on the breakable wall crashes
the game (already happened with the Peacemaker before)
- Figure out why static data of type `turret-path-event` doesn't
decompile

The docs for all the hover-nav and nav-network code could use some love
in the future, I'm not smart enough to figure out what any of that code
actually means, but it seems to work...

Also threw in the fix for the ▲ that was accidentally left commented
out.
2023-02-09 18:22:56 -05:00
Tyler Wilding 0e3d93dd13 ci: allow manually updating the controller db (#2200)
Noticed this has been failing for a while for reasons. I think I fixed
them but can't re-run the current job (out of date from master). This
this gives me a way to manually re-run it.
2023-02-09 22:18:57 +00:00
Hat Kid 4ee402984f decomp: citizen-* files, metalhead-* files, civilian, guard, hal3-course (#2194)
No more ghost town!

Manual patches:

- `hal3-course`: In `(anon-function 17 hal3-course)`, the decompiler is
doing something strange with `s3-0` that fails to compile, so I just
removed the `set!` and inlined the condition in the `when`.
- `guard`: Rewrote `(.mula.s)` stuff
2023-02-07 19:56:06 -05:00
Matt Dallmeyer fc5c75534d Autosplitter - add per-level fly & orb counts (#2192)
Adds fields to the autosplit struct for the number of orbs and scout
flies collected in each level. This can be used for autosplitting on
orb/fly counts

Tested together with https://github.com/open-goal/speedrunning/pull/8


[autosplit_orbs.mp4](https://user-images.githubusercontent.com/2515356/216900730-92b7b947-cc4a-4629-b7f2-1dc10248c9e9.mp4)

[autosplit_fly.mp4](https://user-images.githubusercontent.com/2515356/216900759-e3042426-7cb0-4cb9-ae05-9c44827df6a0.mp4)


![image](https://user-images.githubusercontent.com/2515356/216901323-ffae97c8-3557-45f8-91db-cd86d76dd498.png)

![image](https://user-images.githubusercontent.com/2515356/216901026-59eb3fb6-281d-489d-a50c-010760246072.png)
2023-02-07 19:41:48 -05:00
water111 45f7770ca2 [decomp] finish up nav-graph, traffic-engine, traffic-manager, height-map (#2191)
Some of these were almost done, just needed a few more types.
2023-02-05 18:16:58 -05:00
Tyler Wilding a83bd49426 d/jak2: finish onin-game and resolve type-hinting (array object) elements (#2188)
Fixes https://github.com/open-goal/jak-project/issues/2047
2023-02-04 20:36:30 -05:00
ChillyPepperandTyler Wilding fd6d59cd88 Jak2 decomp/hover formation (#2028)
This is a WIP while I'm learning the ins and outs of decompilation, but
putting up what I have for 2 reasons:

- Hoping someone can double check I'm on the right path (all functions
have signatures, all reasonably safe guesses for types have been put in,
using "object" for type where they're not)
- Might be blocked by not being able to run the offline-tests as a PAL
scrub

I'm going to look at what might be involved in making tests work for
PAL, but wouldn't be surprised if I have to wait to get a black label
version and come back to this after :(

---------

Co-authored-by: Tyler Wilding <[email protected]>
2023-02-04 20:03:46 -05:00
Luminar Light 89feb5d0f1 Create Hungarian translation of game text for Jak 1 (#2141)
This will probably take a while, since we also have to translate all the
text of the base game - Naughty Dog never translated this game to
Hungarian. This PR will stay a draft until it is complete.

We realized that every letter in our alphabet was already working, apart
from two: Ő and Ű (they are unique sounds, so leaving their marks
wouldn't be okay).
Since I did not find that double accent thing in the jak font, I decided
to use ~ (see my change in FontUtils.cpp). It is good enough, and my
memory tells me that I already saw this exact same "solution"
(workaround) somewhere in the past. If anyone knows a better solution,
please let us know.

We chose ID 14 for the Hungarian language, as it was the lowest free ID.

**Progress tracker**
A tick here means that everything was translated. It does not mean that
everything is perfect yet. We will review everything multiple times, to
have the best translations possible.

Game text:
- [x] base game text
- [x] pc port text
- [ ] credits text ?

[Sziloyoo](https://github.com/Sziloyoo) helped with reviewing my
changes, and gave advice/suggestions for some complicated translations.

Subtitles will be done in the future, not in this PR.
2023-02-04 20:01:22 -05:00
Matt Dallmeyer 2c5e456571 Minor fix for Rock Village IL speedrun (#2187) 2023-02-02 21:51:28 -05:00
water111 65eef8ff26 [jak2] pc-hook for pris texture upload (#2184)
Fixes a bunch of hud textures:


![image](https://user-images.githubusercontent.com/48171810/215919174-b6ff9af7-0408-4e97-b142-0fbbeafa196a.png)
2023-01-31 20:36:07 -05:00
BreakPoints 1be8110557 More DGOs in Jak2 inputs.jsonc (#2182) 2023-01-31 18:43:38 -05:00
Tyler Wildingandwater b72383964f d/jak2: cleaning up the remainder of unblocked / unclaimed files (#2171)
Co-authored-by: water <[email protected]>
2023-01-31 18:32:50 -05:00
water111 71cb1aef6f [merc2] support vertex updates, use this for blerc in jak 1 and jak 2 (#2179)
This PR adds a feature to merc2 to update vertices. This will be needed
to efficient do effects like blerc/ripple/texture scroll. It's enabled
for blerc in jak 1 and jak 2, but with a few disclaimers:
- currently we still use the mips2c blerc implementation, which is slow
and has some "jittering" because of integer precision. When porting to
PC, there was an additional synchronization problem because blerc
overwrites the merc data as its being read by the renderers. I _think_
this wasn't an issue on PS2 because the blerc dma is higher priority
than the VIF1 DMA, but I'm not certain. Either way, I had to add a mutex
for this on PC to avoid very slight flickering/gaps. This isn't ideal
for performance, but still beats generic by a significant amount in
every place I tested. If you see merc taking 2ms to draw, it is likely
because it is stuck waiting on blerc to finish. This will go away once
blerc itself is ported to C++.
- in jak 1, we end up using generic in some cases where we could use
merc. In particular maia in village3 hut. This will be fixed later once
we can use merc in more places. I don't want to mess with the
merc/generic selection logic when we're hopefully going to get rid of it
soon.
- There is no support for ripple or texture scroll. These use generic on
jak 1, and remain broken on jak 2.
- Like with `emerc`, jak 1 has a toggle to go back to the old behavior
`*blerc-hack*`.
- In most cases, toggling this causes no visual differences. One
exception is Gol's teeth. I believe this is caused by texture coordinate
rounding issues, where generic has an additional float -> int -> float
compared to PC merc. It is very hard to notice so I'm not going to worry
about it.
2023-01-31 18:23:39 -05:00
Tyler Wilding 22bae7fbe0 g/jak2: Add missing DGO files to game.gp lost in the shuffle (#2178)
When I cleaned up the `game.gp` some DGOs were no longer referenced
because my first dependency script omitted them -- thinking they weren't
required. From the perspective of the source files they indeed weren't
required but we still have to produce the DGO file.

also works around #2177
2023-01-30 20:45:45 -05:00
Tyler Wilding ae219f257d repl: support game-specific startup.gc files (#2176) 2023-01-30 20:45:03 -05:00
Hat Kid 7914c723dc custom levels: add initial support for ambients (#2173) 2023-01-30 19:21:26 -05:00
water111andTyler Wilding fff3a2d872 [extractor] create debug_out (#2159)
Co-authored-by: Tyler Wilding <[email protected]>
2023-01-30 19:20:29 -05:00
Matt Dallmeyer 2645fed47a Jak 1 Checkpoint Select / IL Speedrun support (#2162) 2023-01-30 19:11:57 -05:00
BreakPoints 23c1f3019b Update Jak2 inputs.jsonc for first time compiles (#2172) 2023-01-29 13:17:34 -05:00
Tyler Wilding 3d097e69e1 jak2: significantly reduce the verbosity of the game.gp file (#2103) 2023-01-28 20:15:58 -05:00
Tyler Wilding 18507bc78e d/jak2: get portrun working and decompile a bunch of miscellaneous files (#2169) 2023-01-28 19:36:57 -05:00
Tyler Wilding 4876b6af21 g/jak2: cleanup target-board a bit, add a new feature (#2154) 2023-01-28 18:44:29 -05:00
Hat KidandTyler Wilding be035181f0 decomp: squid-* files (#2170)
Co-authored-by: Tyler Wilding <[email protected]>
2023-01-28 18:44:10 -05:00
Tyler Wilding e6f55b9b55 d/jak2: decompile all *-texture files except castle-texture (#2149)
Fixes https://github.com/open-goal/jak-project/issues/2051
2023-01-28 17:37:37 -05:00
Hat KidandTyler Wilding 8b21a55906 decomp: blerc, ripple, under-* files (#2163)
Co-authored-by: Tyler Wilding <[email protected]>
2023-01-28 16:02:58 -05:00
Hat KidandTyler Wilding e0ee9b6a81 decomp: drill-obs, drill-obs2, drillmid-obs, drill-panel, drill-spool (#2152)
Co-authored-by: Tyler Wilding <[email protected]>
2023-01-28 15:41:48 -05:00
Hat Kid fa8c789dcd decomp: eye (#2148) 2023-01-28 15:17:49 -05:00
Tyler Wilding fc3f4da370 scripts: update gsrc files with modifications using git merge (#2164) 2023-01-28 14:19:04 -05:00
ZedB0T 3b1e99cd3f Hook Jak 1 into ImGUI actor filter (#2157) 2023-01-28 14:17:43 -05:00
ManDude 42780e8f8c Fix a few errors in the entity debugger (#2166) 2023-01-27 22:50:54 +00:00
ManDude 213f3bad20 Add extended environment mapping option to progress and enable it by default + other bug fixes (#2161)
![image](https://user-images.githubusercontent.com/7569514/214192592-d584e955-9d54-4092-94ee-1cbe12b071e8.png)

Note: if you had the option disabled, it will be enabled when you first
start the game again. You will have to turn it off again if you want it
disabled.

Also fixes #2150 and fixes #1738 and fixes #2145
2023-01-24 20:22:47 +00:00
ManDude fdcd67b095 Fix F2 screenshots (#2160)
Fixes #2155
2023-01-24 00:38:21 +00:00
water111 f3526652ee disable emerc for title effect (#2156) 2023-01-22 18:55:06 -05:00
water111 0fcc7eb8e9 [merc2] Support emerc (#2147)
This adds environment mapping support to `Merc2`, and turns it on for
Jak 1 and Jak 2.

- The performance is much better
- Jak 1 can be toggled back to the old behavior with `(set! *emerc-hack*
#f)`. The new environment mapping is identical to the old one everywhere
I checked.
- Jak 1 still falls back to generic for ripple/texscroll/blerc/eyes -
there's still no dynamic texture or vertex updating support. The eye
detection stuff will sometimes flag stuff as eyes which is not eyes,
which is fine, but means that generic will be used in some places where
emerc could be used. For example, the shiny plates on jak's arm will be
drawn with generic because jak has eyes.
- Jak 2 hasn't been checked super carefully against PCSX2 yet.
- Jak 2 still isn't technically using emerc, but instead putting emerc
models in the merc bucket.
- The interface to merc is a lot different now and totally custom
OpenGOAL DMA code. The original merc drawing asm doesn't run anymore.
- The FR3 format changed
- Something funky going on with foreground lighting in escape, but
doesn't seem to be related to this change?

Performance comparison, jak 1, in likely the most generic-merc heavy
spot:

![image](https://user-images.githubusercontent.com/48171810/213882718-feb2ab59-95a9-44a2-b0e5-95fba860c7b0.png)

![image](https://user-images.githubusercontent.com/48171810/213882736-8dbbf4c9-6bbf-4d0b-96ce-78d63274660c.png)
2023-01-22 18:30:31 -05:00
Tyler Wilding 50c57e23be d/jak2: "finish" traffic-manager, vehicle-util and citizen-h (#2144)
Some more progress on vehicle code, the following files still remain:
- vehicle-guard (annoying stack types)
- traffic-engine (many issues, some which already have issues made for
them, other entirely new confusing things!)
2023-01-22 18:16:24 -05:00
Hat Kid 3d08d079c9 jak2: ocean renderer (#2142)
Initial implementation of the `ocean-mid`, `ocean-far` and `ocean-near`
renderers for Jak 2.

There's still a few things to sort out, mainly:

- [x] ~Backwards compatibility with Jak 1. The only thing that currently
stands in the way of that is figuring out a clean way to "un-hardcode"
the texture base pointer in C++ without creating a completely separate
`OceanTexture` class for Jak 2. One thing I thought of would be
modifying `BucketRenderer`'s virtual `init_textures` method to also pass
the `GameVersion`, but I'm not sure if there's a better way.~
- [x] ~The sudden transition from `ocean-near` to `ocean-mid`. Not sure
why it's happening or how to fix it.~
- [x] The ocean has two new methods in Jak 2, `ocean::89` and
`ocean::79`, one of which seems to be related to time of day sky colors.
~Even without them implemented, the end result looks quite close, so we
may be able to skip them?~ `ocean::89` generates `ocean-mid` envmap
textures, so it will likely be required, but will not be handled right
now.

Reverted the VU prologue removals because it made the tests fail.
2023-01-22 18:07:46 -05:00
water111 40867fc086 Update target-h ref (#2153) 2023-01-22 16:46:06 +00:00
Tyler Wilding 2ba07eb058 d/jak2: finish consite-obs and get almost all side-missions working (#2143)
Some side missions require cars, they don't work yet. Also the
ring-races and collection ones do not grant orbs. The hoaming beacon
collection one causes a `hud` crash
2023-01-22 09:31:39 -05:00
Tyler Wildingandwater 98393c6f4c goalc: support static arrays of types (#2140)
draft because using the array is a little weird still, don't feel like
dealing with window's slow debugging builds today.

I get the following weird error:
```clj
(define test-array (new 'static 'boxed-array :type type vector))
gr> (-> test-array 0)
1538004        #x1777d4              0.0000        vector
gr> (type? (-> test-array 0) type)
1342757        #x147d25              0.0000        #t
gr> (new 'static (-> test-array 0))
-- Compilation Error! --
Got 3 arguments, but expected 2
Form:
(-> test-array 0)
Location:
Program string:1
(new 'static (-> test-array 0))
^
Code:
(new 'static (-> test-array 0))
```

Maybe this is expected though and the `new` method wants a symbol, not a
type?

Fixes #2060

Co-authored-by: water <[email protected]>
2023-01-21 21:40:39 -05:00
Tyler Wildingandwater abf61a94fb docs: add support for :override-doc in method declarations as well as documenting state handlers (#2139)
Adding support for better child-type method docstrings. This is a
problem unique to methods.

Usually, a child-type will have the same signature and a common name
will apply, but the implementation is different. This means, you
probably want a different docstring to describe what is happening.

Currently this is possible to do via `:replace`. The problem with
replace is two fold:
- a replaced method ends up in the generated `deftype`...because you
usually change the signature!
- we don't put docstrings in the `deftype` in normal GOAL, this is just
something we do for the `all-types` file (they go in the `defmethod`
instead)
- more importantly, this means anytime you now want to change the
parent's name/args/return type -- you have to apply that change
everywhere.

So this is a better design you can now just declare the method like so:
```clj
(:override-doc "my new docstring" <method_id>)
```

And internally a pseudo-replaced method will be added, but it will
inherit everything from the parent (except the docstring of course)

Unrelated - I also made all the keyword args for declaring methods not
depend on ordering

This also adds support for documenting virtual and non-virtual state
handlers. For example:

```clj
  (:states
    (part-tester-idle (:event "test") symbol))
```

or

```clj
(idle () _type_ :state (:event "test") 20)
```

I will probably add the ability to give some sort of over-view docstring
at a later date.

Co-authored-by: water <[email protected]>
2023-01-21 20:45:45 -05:00
Tyler Wildingandwater e5d6ac1c41 d/jak2: second documentation PR and finish forest-scenes and palace-scenes (#2136)
Also fixes #2135

Co-authored-by: water <[email protected]>
2023-01-21 20:26:51 -05:00
EvelynTSMG 7ac22e8449 Fix test crash on space in filepath (#2138)
Should be only one commit. I broke git if it shows more, whoops
2023-01-21 19:51:13 -05:00
Hat Kid 1d868a2bd9 decomp: kor-*|kid-*|widow-*|hal-*|atoll-* files, spyder, sniper, juicer and more (#2134)
Full list:

- `atoll-obs`
- `atoll-tank`
- `juicer`
- `sniper`
- `transport`
- `yakow`
- `kid-h`
- `kid-states`
- `kid-task`
- `kid3-course`
- `kid`
- `kor-h`
- `kor-states`
- `kor-task`
- `kor3-course`
- `kor`
- `spyder`
- `spydroid`
- `widow-baron`
- `widow-extras`
- `widow-more-extras`
- `widow2`
- `widow`
- `flying-spider`
- `mammoth`
- `mantis`
- `nest-obs`
- `hal-task`
- `hal`
- `hal3-course`

Manual patches:
- `widow`: `handle->process` stack var
- `nestb-scenes`: Commented out `nav-network` stuff, was causing crashes
in `nest`

Also fixes `ginsu` crash (`blade-part` had the wrong type)
2023-01-21 19:50:48 -05:00
Hat Kid 9889b638b3 jak2: tomb fixes (#2137) 2023-01-17 03:18:01 +01:00
water111 7d7625f4f8 [jak2] workaround for cutscene playing (#2131) 2023-01-16 13:37:29 -05:00
Luminar Light 7fdef1c509 Fix 'Load... border-mode' in default-menu (#2132)
This one was forgotten when the other similar menu entries were fixed.
So I fixed this now.
2023-01-16 13:37:16 -05:00
Tyler Wilding dd0a8a17b2 docs - first chunk of work documenting the files I glossed over (#2130)
- started documenting the files I glossed over, some are totally done,
others are just partially done
- I changed the decompiler to automatically initialize the
art-group-info from the json file. This makes updating gsrc, even a
single file at a time, have consistent naming
- Though I disabled this functionality for jak 1, as I have no idea if
using the ntsc art groups will cause a regression for different versions
- fix indentation for docstrings -- it still doesn't look great, but
this is now a formatting concern, rather than the docstring having a
bunch of happen-stance leading whitespace.
2023-01-15 11:33:39 -05:00
BreakPoints 3b81a4e447 Fix for needed .DGO files (#2129) 2023-01-15 01:38:41 -05:00
water111 a0d2bce27b Minor bug fixes (#2128)
- make sure bsp is processed on `l` levels in extraction (caused missing
remaps)
- clean up a few prints in extraction
- handle the <15 byte differences in art group files automatically (no
more errors about file naming)
- fix potential exception thrown by merc2 in a few ways: fixed bad data
in FR3's, check texture index just in case, and handle exceptions a
little bit better (still a crash, but at least you get a print)
- fix mips2 ocean stuff causing ocean far crashes
2023-01-14 16:26:17 -05:00
Hat Kid 8a82c2225e decomp: ai-task-h, whack, bot, sig, ash files (#2127)
`whack` is missing a single function (`birth-func-whack-score`) that I
couldn't figure out the right args for.

I was not able to test any of this code because I cannot get `atoll` to
extract.
2023-01-14 16:12:03 -05:00
Hat Kidandwater 459d83f755 decomp: tomb-* files, target-indax, grunt-mech, breakable-wall, pillar-collapse, mechtest-obs, ruins-obs (#2114)
Manual patches in:

- `tomb-boulder`: a few `ppointer->handle`s (I think) were not being
decompiled properly (all used in combination with `clone-anim-once`)
- `ruins-obs`, `pillar-collapse`: `art-joint-anim` casts
- `tomb-beetle`: commented out a call to `shadow-control-method-14` that
was crashing the game when spawning the beetles
- `grunt-mech`: commented out `(.mula.s)` instruction

Notes:
- `enemy-info`'s `idle-anim-script` is most likely a `(pointer
idle-control-frame)`, however, some `nav-enemy-info` labels set it to
`#f` (first encountered in `tomb-beetle`, but also present in `hal`,
`roboguard` and `metalkor-setup`), which crashes the decompiler. This
may become a problem in the future when we eventually get to these
files. For this PR, I made `tomb-beetle` decompile with
`idle-anim-script` set to `#f` and have not noticed any issues/crashes
with that.
- `tomb-boulder` compiles and doesn't crash, but when trying to play the
Daxter chase sequence, the boulder sometimes either spawns at the origin
or spawns in the correct place, but doesn't move.

Co-authored-by: water <[email protected]>
2023-01-14 13:53:31 -05:00
Tyler Wilding b072126764 d/jak2: some minor fixes and workarounds to make debugging easier (#2116)
- worked around audio code for gungame, the tutorials now function
- auto-exit cutscenes upon entry. This doesn't always work nicely (i
didnt want to cause any side-effects due to messing with load states)
but it atleast stops jak from being stuck forever waiting for the
cutscene to load
2023-01-14 12:36:41 -05:00
Tyler Wildingandwater 8b12553d15 d/jak2: first pass at decompiling the core vehicle/traffic code (#2058)
Effects the following files:
- [x] vehicle-rider
- [x] vehicle-control
- [x] vehicle-effects
- [x] vehicle
~~- [ ] vehicle-util~~
- [x] vehicle-physics
- [x] vehicle-states
~~- [ ] vehicle-guard~~
~~- [ ] traffic-engine~~
~~- [ ] traffic-manager~~

With the exception of traffic-engine, most of these files are either
done or have 1-3 stubborn functions remaining. Draft while I try to
resolve as many as possible / cleanup names and such.

Co-authored-by: water <[email protected]>
2023-01-14 12:01:33 -05:00
Tyler Wildingandwater d6f9af7a20 d/jak2: finish strip mine files (#2111)
The level crashes similarly to drill-platform though, unclear what is
the root cause of it.

Co-authored-by: water <[email protected]>
2023-01-14 11:30:58 -05:00
Tyler Wildingandwater 88c39217e1 d/jak2: finish the remaining mountain temple related files (#2110)
There's some minor issues remaining, almost all of which pertain to
cutscene playing though.

Co-authored-by: water <[email protected]>
2023-01-14 11:16:53 -05:00
water111 d65a1c365a some bug fixes (#2125) 2023-01-14 11:04:15 -05:00
Tyler Wilding a75f4c187b d/jak2: mostly complete sewer-enemy and sewer-board missions (#2108)
Finishes the following files:
- `sewer-scenes`
- `sewgun-turret`
- `fordumpc-part`
- `sewer-obs`
- `sewer-obs2`
- `gator`

Fixes #2052
2023-01-14 10:54:39 -05:00
Inirdin fa0f386bf0 Font colors comments (#2122) 2023-01-13 14:02:47 -05:00
Tyler Wilding b03e2a8a3a build: add a file thats now needed (#2121) 2023-01-11 20:56:33 -05:00
water111 bd209bf460 More vmodes (#2120) 2023-01-11 20:44:45 -05:00
water111 cb8cafa40a [decomp] minimap (#2118) 2023-01-11 19:42:39 -05:00
Tyler Wilding f162d5ac31 d/jak2: finish wren and fish (#2106)
finish the forest's ambiance
2023-01-11 19:24:44 -05:00
animalstyletacoandanimalstyletaco fd5191bb9a Fixed bug where mouse position offset(s) would always return a 0 (#2109)
Co-authored-by: animalstyletaco <[email protected]>
2023-01-11 19:21:07 -05:00
water111 8dedfb682e dig obs small fix (#2119)
was already right, goal src just needed updating.
2023-01-11 19:09:48 -05:00
Tyler Wilding e0d31a33bd d/jak2 - initial crimson-guard-level decomp and also the dig missions (#2092)
Finishes a bunch of files related to crimson guards / early missions:
- `crimson-guard-level`
- `dig-digger`
- `fordumpa-obs`
- `fort-robotank`
- `fort-robotank-turret`
- `fort-turret`
- `transport-level`
- `fordumpb-obs`
- `fort-floor-spike`
- `fordumpc-obs`
2023-01-11 19:07:35 -05:00
EvelynTSMG 22adecc222 Make jungle mirrors respect first person camera settings (#2112)
QoL, I suppose
2023-01-11 18:16:27 -05:00
Ziemas 416950a166 Fix sound bank allocation (#2107)
And correctly initialize the volume group for sfx
2023-01-08 11:23:59 -05:00
Hat Kid bdee98323d decomp: add a bunch of enemy files (#2101)
Adds the following files:

- `amphibian`
- `centurion`
- `ginsu`
- `grenadier`
- `hopper`
- `metalmonk`
- `monster-frog`
- `predator-graph`
- `predator-h`
- `predator`
- `rapid-gunner`
- `rhino`
- `rhino-wall`
- `tomb-baby-spider`

Also adds the DGOs for the following levels:

- Mar's Tomb
- Mountain Temple
- Drill Platform
- Sacred Site (Sage Hut)

Manual patches:

- The decompiler emits `(b! #t cfg-17)` in `(trans hostile hopper)`
without putting a `(label cfg-17)` anywhere
- Added cast to `art-joint-anim` in `(code broken rhino-wall)` and
`(code hit rhino-wall)`

Other notes:

- `amphibian` seems to occasionally crash when using its tongue attack.
Haven't investigated this yet
- `ginsu` crashes after being killed somewhere in the `deactivate`
method, possibly because of its `part-spawner`
- Predators aren't spawning in the forest hunt mission, not sure if
`forest-obs` might be needed for that or if it's something else
- The `rhino-wall` STR animation seems to load (albeit a bit broken due
to missing VAG stream playback), but causes the viewport to shrink as
soon as it's played
- I added `pegasus::74` to the `event_handler_hack` bool in
`variable_naming.cpp` because I got a `none` cast after changing the
return value of `enemy::74`
2023-01-07 17:14:12 -05:00
Tyler Wildingandwater 00ac12094e goalc/repl: cleanup of goalc/REPL code and some QoL improvements (#2104)
- lets you split up your `startup.gc` file into two sections
  - one that runs on initial startup / reloads
  - the other that runs when you listen to a target
- allows for customization of the keybinds added a month or so ago
- removes a useless flag (--startup-cmd) and marks others for
deprecation.
- added another help prompt that lists all the keybinds and what they do

Co-authored-by: water <[email protected]>
2023-01-07 11:24:02 -05:00
Tyler Wilding 2f4146d469 tests: make the offline tests aware of the current terminals row count (#2105)
This fixes the hideous output when your terminal would be too small to
hold all the threads.
2023-01-07 10:35:12 -05:00
Tyler Wilding f699675ede g/jak2: initial Discord RPC implementation (#2100)
Notable things:
- This assert is hit when trying to save the pc-settings file, NYI
https://github.com/open-goal/jak-project/blob/e630b506903d7f7028dff89702be7f586c2120e7/game/kernel/common/Symbol4.h#L14
so right now settings aren't persisted. But RPC defaults to on
- The existing functions can probably be made generic based off the game
version, but I didn't spend time refactoring them yet as they aren't
really ready to be used in jak 2 yet (we have no screenshots for the
levels for example)
2023-01-07 10:34:01 -05:00
water111 bf10f1edd4 add a weird field to target-h for mech ik (#2099) 2023-01-07 10:32:24 -05:00
water111 f50c0e56e9 [jak2] use art constants (#2097) 2023-01-07 10:32:03 -05:00
Tyler Wilding 5095b867b0 d/jak2: finish jetboard training mission (mostly) and scouts mission (#2090)
The things that aren't working right now:
- returning the board (maybe cutscene related?)
  - draft until i see if this can be sorted out
- seems to need streaming audio as well, the `scene-player` gets
properly initialized from what i can tell
- had to hack around the streaming audio parts.
2023-01-04 20:43:34 -05:00
Tyler Wilding 22ec32ce94 tools: add a flag to just dump all types from all-types via type searcher (#2098) 2023-01-04 20:27:51 -05:00
Hat Kidandwater 09d555b4a0 decomp: mech, mech-states, target-mech (#2091)
Everything relating to IK in `target-mech` was commented out as I
couldn't get a lambda to decompile properly, but the mech still seems to
work fine without it.

Co-authored-by: water <[email protected]>
2023-01-04 19:42:26 -05:00
Ziemas dfcd203aad Overlord: Jak2 stream loading (#2096)
Untested lazy copy-paste job from jak1

Pretty confident it's the same logic with a new StrFileHeader struct.
2023-01-04 18:29:50 -05:00
Tyler Wilding c24cdca380 offline-tests: fail on comparison in offline-tests (#2095)
Two main problems fixed here:
- offline tests will fail on a comparison failure (a mistake from the
re-write)
- art-group-info is committed to the repo and shared with every thread
(running the tests with 1 thread, for example on the CI, and locally
were producing different results)

art files are still not provided to the jak2 offline tests:
- `*-ag` files are not being output
- `art-elts.gc` is not complete, as a handful of files claim to be
missing stuff

lastly, in jak1's offline tests we were also running `tpage` and `*-vis`
files through the decompiler. This omits that (they came from the
`all_objs.json` file) -- is this an issue?
2023-01-04 18:26:59 -05:00
Ziemas f0ca0cbe6a Overlord: mirror sound RPC command (#2094)
And replace the previous mechanism for mirroring the sound.
2023-01-04 18:22:18 -05:00
Tyler Wilding 8f4dfa27dd scripts: adjust scripts to ensure better decompiling consistency (#2093) 2023-01-04 18:21:27 -05:00
ManDude 15a8a9c8ef add ja zero func (#2074)
fixes #2071
2023-01-02 18:23:33 +00:00
water111 77a3e4125c [jak2] don't ignore disable-draw bits (#2089)
Same idea as what I did for jak 1, but now there's a mask that can be
set by the user. It's used on the gun course dummies, for example.
2023-01-02 13:09:30 -05:00
water111 20a6839e07 [jak2] fix hud and some particles (#2088)
Fixes:
- a very old bug in depth in DirectRenderer, probably from the original
tfrag stuff. Looked at PCSX2 source code to see how 32/24 bit depths are
handled. This fixes hud sprites being drawn behind level geometry.
- saturate `vftoi4` like the ps2 does when the float is too large,
fixing hidden text in `hud`. For now it's only using this in the font
code because this saturation is actually kinda slow and hasn't been a
problem in other places.
- fix crazy particle spawning issue with blue gun and dripping stuff.
This would happen if particles kill themselves while being processed
(through a callback)
2023-01-02 12:13:19 -05:00
water111 0e43c96e52 [decomp] hud, hud-classes, add some new basic alignment options, fix type bug (#2084) 2023-01-02 10:05:22 -05:00
Tyler Wilding 9f53edae7a game/debugging: Add a new imgui menu to filter debug text and adjust imgui config settings (#2085)
This adds a new ImGUI menu to help filter out the clutter on screen.


https://user-images.githubusercontent.com/13153231/210192912-b1c28319-bacb-449c-ad7f-e7308fb75f50.mp4

This also:
- moves the imgui display bool into a game specific config file (you can
hide it in jak1, and not in jak2)
- the config file also persists the settings from this menu (except the
filters for now, future TODO)
- there is a new `ignore_imgui_hide_keybind` in this file to ignore
hiding it when you press Alt
2023-01-02 09:45:38 -05:00
Ziemas bb94c84d4b Ame fixes (#2087) 2023-01-02 09:40:30 -05:00
Tyler Wilding f06fd9b9c5 lint: remove some debugging logs (#2086) 2023-01-02 01:11:05 -05:00
Tyler Wilding 284fb09997 d/jak2: decompile fodder and nav-enemy (#2080)
fixes #1983 

First functioning enemy!


https://user-images.githubusercontent.com/13153231/210184845-f1d93491-11f5-4a64-b69c-41e535992ebc.mp4
2023-01-01 21:03:07 -05:00
Ziemas a77d9fac01 Sound fixes (#2083) 2023-01-01 21:02:38 -05:00
water111 308038a20f [decomp] collectables, fix float bug in a few files (#2082)
Fixes https://github.com/open-goal/jak-project/issues/1931
Also decompile collectables.gc
2023-01-01 18:05:31 -05:00
Tyler Wilding 5333aa3fb2 d/jak2: finish decompiling gungame files and tomb-scenes (#2076) 2023-01-01 16:22:44 -05:00
Tyler Wilding 73d38bd9ff game/debugger: handle uncaught loader thread exceptions and better handle that situation on the windows debugger (#2075) 2023-01-01 12:31:12 -05:00
water111andTyler Wilding 0cddf6b6a5 W/nav debugging (#2077)
Co-authored-by: Tyler Wilding <[email protected]>
2023-01-01 12:11:18 -05:00
ZedB0T 08ad352e94 Add base_id for custom levels. (#2079)
It used to automatically assign actor IDs, but reset in between custom
levels, so it was possible for actors to share the same actor id with a
actor in another level. With this the user can now specify a base_id to
make sure that the custom levels never match! (or fix it if they do!)
2023-01-01 00:18:26 -05:00
Tyler Wilding 6aa15c897f decomp: don't mutate allowed/banned object lists (#2073)
oops, leads to some very confusing behaviour
2022-12-30 23:57:01 -05:00
Ziemas 749611d47c Prevent putting nullptr into child sound list (#2072)
CreateChildSound did not check for nullptr return from
soundbank::make_handler, which would happen for sounds with no grains.

Prevent further problems with this by switching to optional instead of
passing nullptr.
2022-12-30 23:15:43 -05:00
water111 602765db6e [decomp] drawable, memory-usage (#2070) 2022-12-30 18:23:53 -05:00
Tyler Wilding 6406ba05a6 d/jak2: finish atoll-scenes (#2069) 2022-12-30 18:23:45 -05:00
water111 d454dfbcd8 add target-board-handler (#2068) 2022-12-30 15:23:46 -05:00
water111 f6c5504f6f [decomp] fix up gun decomp (#2067)
I did some manual modifications in a few places to work around some
truly mysterious control flow, and some unsupported stack array stuff.

Also fixes a bug in decompiling static improper lists.

As far as I can tell, guns work, other than some graphical issues and
the crazy particle spawning issue, but I strongly suspect these are
problems with the sparticle/graphics side.
2022-12-30 14:07:32 -05:00
Tyler Wilding 997c1ab60a decomp: add explicit failures for common config mistakes related to allowed_objs (#2062)
A common thing that can be forgotten about / confusing to new people is
that:
1. if you add an object to the `allowed_objs` list but it's also in the
`banned_objs` list -- the ban still takes precedence with no failure
2. if you add an object to the `allowed_objs` list but have not allowed
the DGO in `inputs.jsonc` it will also silently log a failure and
continue.

This PR turns both situations into an explicit error with advice/a
reminder on what to do to fix it.
2022-12-30 14:01:55 -05:00
water111 e49e6548e0 [jak2] split up big dgos, some minor cleanup (#2066)
- Split up DGOs between threads in the multithreaded offline test
- fix some random warnings
- make the sig paths decompile a bit nicer to make some files smaller
2022-12-30 13:33:29 -05:00
Tyler Wilding 2eca614870 d/jak2: finish remaining *-h files that aren't in progress or spoken for (#2059)
This finishes off all the remaining "header" files that someone isn't
already working on.
2022-12-30 12:09:04 -05:00
Tyler Wilding 6181c6c997 decomp: output mips2c method/function declarations to the _disasm.gc file (#2054)
When working with mips2c recently, I noticed adding the
`defmethod-mips2c` or `def-mips2c` code was a manual step. This is a bit
tedious to have to go and do yourself, but more importantly you have to
manually go and find the right spot in the source file else you might be
declaring it too early or too late.

This will automatically output the declaration for methods, and a
half-finished comment for the functions. I wasn't able to fully output
the function one because it seems the signature info from `all-types`
doesn't make it all the way through -- but maybe I'm wrong or this is an
easy fix?
2022-12-30 12:03:06 -05:00
Tyler Wilding fb11c162c1 jak1: fix debug menu regression around lambdas (#2065) 2022-12-27 23:04:26 -05:00
Tyler Wilding 216e73b61f CI: Add a macOS Github runner (#2064) 2022-12-22 18:12:59 -05:00
water111 73561f10a3 support c++ tools on macos (#2063)
Running reference tests/decompiler should now be possible on macos
(arm). Most of the changes were just cleaning up places where we were
sloppy with ifdefs, but there were two interesting ones:
- `Printer.cpp` was updated to not use a recursive function for printing
lists, to avoid stack overflow
- I replaced xxhash with another version of the same library that
supports arm (the one that comes in zstd). The interface is C instead of
C++ but it's not bad to use. I confirmed that the extractor succeeds on
jak 1 iso so it looks like this gives us the same results as the old
library.
2022-12-22 17:12:05 -05:00
Hat Kid 98c2291102 jak2: misc fixes (#2050)
- Stub `target-board-handler` to prevent jetboard crash
- Increase stack size for `target` to fix dark bomb crash
- Uncomment some code in `target-darkjak` to make Dark Jak work (texture
morph still crashes, so it's commented out)
- Increase stack size for a `process-spawn-function` in
`target-send-attack` to fix a crash with giant Dark Jak
2022-12-22 13:59:24 -05:00
Ziemas 4edec2730f Fix EarTrans assignment (#2057)
and some slight cleaning
2022-12-22 13:58:37 -05:00
Tyler Wilding 1b2db09f51 d/jak2: pass through all simple / non-blocked *-part, *-ocean and *-scenes files (#2048)
A big one...

I figure even if we would like to change the way the particle/scene code
is output -- it'd be easier to find patterns with it all decompiled.

I've updated my script so it can easily be used to mass update these
files:
```bash
task update-gsrc-glob GLOB="**/*-part*.gc"
```
> for example will update gsrc files with `part` in their name -- if
they are in ref tests (so uncompleted ones aren't touched)

I found a few issues along the way that I'll have to make issues for
soon.
2022-12-22 13:57:57 -05:00
Tyler Wilding 9c631e11fe offline-test: Partition by DGO and colorize/condense output (#2045)
This solves two main problems:
- the looming threat of running out of memory since every thread would
consume duplicate (and probably not needed) resources
- though I will point out, jak 2's offline tests seem to hardly use any
memory even with 400+ files, duplicated across many threads. Where as
jak 1 does indeed use tons more memory. So I think there is something
going on besides just the source files
- condense the output so it's much easier to see what is happening / how
close the test is to completing.
- one annoying thing about the multiple thread change was errors were
typically buried far in the middle of the output, this fixes that
- refactors the offline test code in general to be a lot more modular

The pretty printing is not enabled by default, run with `-p` or
`--pretty-print` if you want to use it


https://user-images.githubusercontent.com/13153231/205513212-a65c20d4-ce36-44f6-826a-cd475505dbf9.mp4
2022-12-22 13:41:33 -05:00
Tyler Wilding 74d1074eef d/jak2: add missing ref tests for files that can be added to ref tests (#2061) 2022-12-15 01:27:07 -05:00
Ziemas 2bf663dccf Assorted sound fixes (#2049)
fixes https://github.com/open-goal/jak-project/issues/2046
2022-12-05 23:43:14 -05:00
water111 7a62e9cf4f format, fix decompiler crash (#2044)
quick fix for decompiler crash
2022-12-02 18:10:18 -05:00
Ziemas 5b99929394 989snd: Support version >= 2 sound effects (#1991)
Supports most of the grain types now while maintaining compatibility
with the old stuff (at least the subset of things jak1 uses)

Would benefit from some testing in Jak 1 to make sure I didn't break
anything.

Sorry the git history is a mess, I'll do something about it later.
2022-12-02 18:08:44 -05:00
water111 80e9528e4e lights, death, and rotation fix (#2042)
- decompile `lights.gc`
- decompile remaining `target-death` function, you can die now
- fix float issue with `matrix-from-two-vectors-smooth!` making jak face
the wrong way in the slide thing
2022-12-02 10:02:13 -05:00
Tyler Wilding 728b2689b6 d/jak2: decomp a bunch of files related to the beginning of the game (#2043)
Mostly easy / particle def files. I did a bit in `ruins` but CFG
failures and missing `drawable` functions make it untestable for now so
I've put that on pause.
2022-12-01 21:26:49 -05:00
water111 70e231fa72 [jak 2] merc (#2039) 2022-11-30 22:36:09 -05:00
Hat Kid ceebe3f7eb decomp: target-tube (#2041) 2022-11-30 19:52:42 -05:00
water111 c983475751 [jak2] tiny fix to grunt (#2040) 2022-11-29 21:11:36 -05:00
Tyler Wilding ac3c4e59b0 goalc/repl: Allow hot-loading files via ml with just the object name (#2036)
This allows you to not have to define the entire file path to a source
file to re-compile and load it. Technically a stop-gap until editor
tools are developed around writing OpenGOAL.


![image](https://user-images.githubusercontent.com/13153231/203196148-de61cf4b-42c8-43dc-a7fd-80e6ba6f5ac2.png)

As opposed to `(ml "goal_src/jak2/engine/game/main.gc")` (which still
works)

This is accomplished via the following config (connection attempts is
irrelevant):
```json
{
  "numConnectToTargetAttempts": 1,
  "jak2": {
    "asmFileSearchDirs": [
      "goal_src/jak2"
    ]
  }
}
```

This also provides a way to make game-specific configurations for the
REPL fairly easily.
2022-11-29 19:22:22 -05:00
Tyler Wilding cdb61f69f8 d/jak2: finish decompiling enemy-h | enemy | grunt and flitter (#2023) 2022-11-29 19:19:05 -05:00
XedoITandTyler Wilding 378a4e6f33 Added "it" voice to game_text (#2038)
Co-authored-by: Tyler Wilding <[email protected]>
2022-11-26 19:10:21 -05:00
Misagi c77925a8ad French Subtitles & Game Text (#2024) 2022-11-26 18:49:23 -05:00
XedoIT 568609794f Italian language for game's texts. (#2037) 2022-11-26 18:45:50 -05:00
water111 7a1a64acba target code bugfixes (#2034) 2022-11-21 20:25:20 -05:00
Tyler Wilding a0a85eb60a repl: Add a few new quality of life improvements (#2030)
- You can define a `startup.gc` in your user folder, each line will be
executed on startup (deprecates the usefulness of some cli flags)
- You can define a `repl-config.json` file to override REPL settings.
Long-term this is a better approach than a bunch of CLI flags as well
- Via this, you can override the amount of time the repl will attempt to
listen for the target
- At the same time, I think i may have found why on Windows it can
sometimes take forever to timeout when the game dies, will dig into this
later
- Added some keybinds for common operations, shown here


https://user-images.githubusercontent.com/13153231/202890278-1ff2bb06-dddf-4bde-9178-aa0883799167.mp4
> builds the game, connects to it, attaches a debugger and continues,
launches it, gets the backtrace, stops the target -- all with only
keybinds.

If you want these keybinds to work inside VSCode's integrated terminal,
you need to add the following to your settings file
```json
"terminal.integrated.commandsToSkipShell": [
    "-workbench.action.quickOpen",
    "-workbench.action.quickOpenView"
  ]
```
2022-11-20 14:28:41 -05:00
water111 6298533eaa [decomp] collide cache, other minor fixes (#2031) 2022-11-20 11:32:29 -05:00
water111 e0ebc5a68e [decomp] target-handler (#2027) 2022-11-20 09:21:25 -05:00
Tyler Wilding bf83f2442d d/jak2: cleanup more of editable and editable-player (#2029)
- Rough start of the SQLite integration to facilitate the SQL queries
- Cleanup and disable a little bit of code so the game no longer crashes
when entering the editor
- Implement some of the mouse data stuff


![image](https://user-images.githubusercontent.com/13153231/202881481-95bc0a2a-ac3d-4f65-aff1-b9f7ee5ee345.png)


https://user-images.githubusercontent.com/13153231/202881484-399747e7-dcdb-4e09-93e9-b561a45c8a18.mp4

This is a very old branch so best to get it merged now that it's at a
decent point so it can be iterated on.
2022-11-19 23:28:20 -05:00
water111 928b18f01c clean up to target-handler (#2026) 2022-11-19 17:58:51 -05:00
water111 029983270e [decomp] target cleanup (#2021)
everything up to collide-reaction-target (which is mostly done, but
could use a few more names)

Fixes issues with gun-part and target-part
2022-11-13 19:09:34 -05:00
water111 3c393845c7 [decomp] finish lightning-draw (#2019) 2022-11-13 12:05:49 -05:00
water111 611e59a679 format json (#2018) 2022-11-13 11:44:02 -05:00
Tyler Wilding c8abafcb7a d/jak2: partial cleanup pass from main -> gun-part (#2017) 2022-11-13 11:38:25 -05:00
water111 f39b993f79 [decommp] generic-obs (#2013) 2022-11-12 17:56:07 -05:00
Tyler Wilding 84ef64398e d/jak2: finish process-drawable, collide-reaction-target, target-anim, almost target-part and gun-part (#2012)
- target-part
- ;; ERROR: Failed to convert to atomic ops: Variable could not be
constructed from register r0 in `process-drawable-shock-wall-effect`
- gun-part
  - missing sparticle decompiling case it seems related to `L155`

This is pretty rough but...im excited to see it working :)
2022-11-12 11:19:04 -05:00
water111 3909a251cc [decomp] clean up some names/types (#2011)
cutting down on some of the most common `unknown` methods, before we add
too much gameplay code
2022-11-11 20:18:13 -05:00
water111 b90b6c9aff small cleanup on camera code (#2010)
fixes https://github.com/open-goal/jak-project/issues/1960 and patches
scratchpad use in cam-debug
2022-11-11 17:27:09 -05:00
water111 b2b47eec5c [decomp] spatial-hash (#2009) 2022-11-11 16:23:26 -05:00
water111 136136e498 [decomp] start work on collide (#2008)
Adds `collide-shape` and a few other related ones.
2022-11-11 12:01:45 -05:00
Tyler Wilding 190fe6968f d/jak2: finish guard-projectile | metalhead-projectile | guard-conversation and start crimson-guard-level (#2006)
Related issue - https://github.com/open-goal/jak-project/issues/2005
2022-11-06 14:30:43 -05:00
Ziemas fc3488fa8b Properly update VAG volume (#2002) 2022-11-03 22:28:12 +00:00
dependabot[bot] 21ad7904c0 build(deps): bump mathieudutour/github-tag-action from 6.0 to 6.1 (#2000)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-02 00:38:48 -04:00
dependabot[bot] 1b7e3966ce build(deps): bump mikehardy/buildcache-action from 1.3.0 to 2.1.0 (#2001)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-02 00:22:10 -04:00
Hat Kid 88eb45ab52 decomp: ocean, ocean-mid, ocean-near, ocean-texture, ocean-transition, ocean-vu0 (#1994)
The VU programs for the ocean renderer have changed a bit and
`ocean-texture` has a bunch of new stuff, otherwise things are
relatively similar to Jak 1.

This is the first time I used mips2c and I'm not sure I did it 100%
right, so that should be double-checked.
2022-10-30 19:09:35 -04:00
water111 811b5de6cb [decomp] collide-mesh (#1999) 2022-10-30 15:54:10 -04:00
water111 8ae4829f48 [decomp] collide-hash, collide-frag, collide-probe (#1998)
The only interesting one is `collide-hash`, which is untested.
The other two are very likely unused. I skipped the annoying code in
`collide-probe` because it's not used and the same as jak 1.
2022-10-29 20:32:03 -04:00
Tyler Wilding 50076537b7 d/jak2: finish sidekick, target-carry and battle. Close to finishing target-death and warp-gate (#1990) 2022-10-29 18:27:31 -04:00
Tyler Wilding 92105bb696 ci: update buildcache back now that things have stabilized (#1997)
My changes for allowing an explicit tag have now been merged to the
original action, so no need to use my fork.

Additionally, buildcache itself reverted to using ubuntu 20.04 to fix
this issue, but we'll leave the explicit tag there anyway to avoid
sudden breakage in the future.
2022-10-29 18:22:02 -04:00
Tyler Wilding e8c723c265 tests: don't strip comments from the dumped failures code (#1996)
Offline tests ignore comments in their comparison, but there's no reason
to strip them from the file that goes into the reference test folder
when doing the typical update routine.

This just generates superfluous diffs for all the files already done
prior to this change and is meaningless (the lines are dropped anyway)
2022-10-29 18:21:51 -04:00
Tyler Wildingandwater 760e11a087 d/jak2: finish scene-actor, scene-looper, race-part, rigid-body-plat, debug-part, voicebox (#1987)
Co-authored-by: water <[email protected]>
2022-10-29 16:42:57 -04:00
Tyler Wildingandwater d13155bfd0 d/jak2: Decompile palace-ocean, ctysluma-part, nav-enemy-h and a bunch of work on enemy and nav-mesh related files (#1984)
Couldn't finish any of the enemy/nav-enemy related files for one reason
or another, but quite a bit of work that will be easier to merge and
iterate on instead of keeping track of the branch.

enemy/idle-control has some very weird focus related code.

nav-mesh/nav-control still has a bunch of CFG resolution problems that
need to be manually resolved.

Co-authored-by: water <[email protected]>
2022-10-29 16:28:52 -04:00
ManDude b0e8cba6f1 [decomp2] game-save (#1988)
memory card code was not done!
2022-10-29 16:08:04 -04:00
Ziemas 3b3ed9efbe Fix GCC build (#1992)
Not sure why but using the static members here caused a linker error,
but they're only used in one place so I just passed them as constants.
2022-10-29 15:25:21 -04:00
ChillyPepper b9924e5501 Adding notes for building non black label versions (#1995) 2022-10-29 15:25:03 -04:00
Tyler Wilding 84497712ff d/jak2: finish task-arrow | carry-h | projectile | gun-[red|yellow|blue]-shot (#1864) 2022-10-29 15:22:57 -04:00
Xavier Siguero Mora 43b93cc204 Spanish Game Text (#1980)
Spanish subtitles are already merged, so this should be the only text
still missing for the language. The game compiles and it's playable
without problem

![imagen](https://user-images.githubusercontent.com/32161135/196548800-8eaad76d-6a16-4451-b22d-f2cb87fae6fe.png)
2022-10-22 13:26:50 -04:00
Tyler Wilding 41c3423767 d/jak2: finish viewer, texture-finish, process-taskable, main-collide, prototype and los-control (#1975) 2022-10-22 13:26:28 -04:00
Tyler Wilding b602b83d17 ci: rollback to previous buildcache version (#1981)
buildcache's latest release changes to be built on Ubuntu22.04, which
breaks our 20.04 runners
2022-10-20 09:07:50 -04:00
water111 ddd60fca48 [decompiler] handle pointer to symbol value, clean up prints on offline test (#1978)
- fix issue described in
https://github.com/open-goal/jak-project/issues/1939
- fix `text`, which was manually patched with the wrong offset (was
reading the symbol value off by one byte)
- clean up some random useless prints
- make the offline tests keep trying if there's a comparison error,
clean up the output a bit so the diffs are all at the end.
2022-10-16 18:19:59 -04:00
Tyler Wilding e7bb0fb68d d/jak2: decompile ambient | speech and bigmap-data (#1954)
fma-sphere not completed due to #1888
2022-10-16 18:09:15 -04:00
Tyler Wilding d402ad8918 tests: parallelize offline-test execution (#1974)
The offline-tests are going to end up taking too long for jak 2, I did
some rough math and by the end of it we'll be spending almost 2 minutes
for a full offline test on my machine.

These changes allow us to throw hardware at the problem

Still some work to do to make the output nicer, but seems to be fairly
reliable. By default it still uses 1 thread, use `num_threads` to change
this.
2022-10-16 17:20:44 -04:00
water111 0712e6d4db remove casts that were only needed to prevent hangs (#1977) 2022-10-16 17:14:35 -04:00
water111 46f11b1b47 add level ref test (#1973)
There's a few functions that have to be excluded, but I think it's still
useful to have this.
2022-10-15 18:36:32 -04:00
water111 e443676889 [decomp] sky-tng (#1972)
https://www.youtube.com/watch?v=fkAMvEYXOGc
2022-10-15 18:21:17 -04:00
Tyler Wilding fd7d9c3df5 d/jak2: finish scene (#1971)
`scene-player-init` has some weird `rtype-of` usage (mostly in the
`pair` clause)
2022-10-15 17:43:02 -04:00
water111 a10d60c42c [decompiler] nicer static giftags (#1970)
```
      :gif0 (new 'static 'gif-tag64
        :nloop #x4
        :eop #x1
        :pre #x1
        :prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1 :abe #x1)
        :nreg #x3
        )
      :gif1 (new 'static 'gif-tag-regs :regs0 (gif-reg-id st) :regs1 (gif-reg-id rgbaq) :regs2 (gif-reg-id xyzf2))
```
instead of
```
:gif (new 'static 'array uint64 2 #x303e400000008004 #x412)
```
2022-10-15 10:59:09 -04:00
water111 b6f0ef52b3 [decomp] fixes for loader and game-info (#1968)
Fixes for the functions that weren't decompiled. `initialize` in
`game-info.gc` was fixed manually.
2022-10-14 20:47:59 -04:00
Hat Kid da5aef8d60 decomp: finish target-[util|darkjak|swim|gun] | water | water-anim | crates | dark-eco-pool, fix skelgroup detection, add failed store/load warnings and clean up jak 3 config (#1958)
Almost done:
- `target-handler` (`(none)` event handler casts and CFG error)
- `target2` (`(none)` event handler casts)
- `powerups` (`cloud-track` does some weird stuff with `handle`s)
- `gun-states` (CFG error)

Some progress in:
- `water-flow`

Additionally:

- Clean up the two year old Jak 3 config file and add a config skeleton
(disassembling seems to not have worked, but I was able to dump obj
files and the `all_scripts` file)
- Fix automatic skelgroup detection and `defskelgroup` macro for Jak 2
(closes #1950)
- When a function decompiles without any major errors, a warning is
generated with the op id for each unresolved load and store that will
likely fail to compile (closes #1933)
2022-10-14 19:35:57 -04:00
Tyler Wilding 7dd716ded5 vscode: add snippets for supported ;; og:... comments (#1963)
Better documentation on what is supported / makes it faster to type them
without making mistakes.


![image](https://user-images.githubusercontent.com/13153231/195737915-1ed0fc15-e91d-4b35-a7df-0c31ebdc07d1.png)
2022-10-14 19:10:57 -04:00
Tyler Wilding da82cb87e7 tools: add the ability to search by method id (#1964)
Useful when you are trying to find a type with atleast a method at a
given id.
2022-10-14 19:10:38 -04:00
Tyler Wilding 9c390e1461 scripts: add a script to generate game.gp code, comment out generated code for now (#1966)
Generates the `game.gp` code for all DGOs, code added to the project
file has been commented out for now.

In my opinion, this is way too much in a single file -- it would be nice
if this code would live directly inside the `.gd` files themselves, then
everything is nicely organized. But this approach might have issues I'm
not aware of.
2022-10-14 19:10:05 -04:00
Matt Dallmeyer 17a854b148 allow daxter/naughtydog intro cutscene skip (#1965)
I think this got removed awhile back, not sure if it was intentional,
but thought it was nice to have. Feel free to close if it's not
supported for a good reason 👍
2022-10-14 19:06:41 -04:00
Tyler Wilding c95a9a0a5a tests: run tests in gcc runner again (#1962) 2022-10-12 19:53:02 -04:00
Tyler Wilding e3473c1902 d/jak2: finish cty-guard-turret-button | race-h | height-map-h and a lot of rigid-body (#1957)
Also cleaned up `data_decompiler.cpp` to make it a lot less verbose to
add a special case for an array field.
2022-10-11 23:20:36 -04:00
Brent HickeyandTyler Wilding f7e1e73809 Decompile los-control-h (#1844)
Co-authored-by: Tyler Wilding <[email protected]>
2022-10-11 19:39:45 -04:00
water111 8827af5efd add workaround for menu-option-list weirdness (#1961)
The type makes no sense when compared to the actual data there. This
modifies the type slightly, which I think is better than spending a
bunch of effort to special case this in the compiler/decompiler.

If we try this, and it turns out it doesn't work, we can always revisit
it. But I think this will work.
2022-10-11 19:21:10 -04:00
Tyler Wilding f6bdc07990 d/jak2: finish progress menu code and initialize the camera (#1945)
This PR does a few main things:
- finish decompiling the progress related code
- implemented changes necessary to load the text files end-to-end
   - japanese/korean character encodings were not added
- finish more camera code, which is required to spawn the progress menu
/ init the default language settings needed for text
  - initialized the camera as well

Still havn't opened the menu as there are a lot of checks around
`*target*` which I havn't yet gone through and attempted to comment out.
2022-10-11 18:30:26 -04:00
himham-jak 18fa543621 Ignore backups from OpenMaya (#1955)
For the level builder, I use .bak files whenever I modify a core file in
the project. These let you undo changes, but they don't need to be
pushed. I also couldn't find a nice way to do this, but we should also
ignore all contents of custom_levels besides test-zone.
2022-10-11 18:18:19 -04:00
water111 9a04c7e311 [decomp] sparticle, sparticle-launcher, set up sprite (#1949)
- fix crash with unhandled sparticle definition (happens with the weird
array int32s that I don't understand yet)
- update mips2c stuff
- add part-tester
- fix some issues around texture uploads
 

![image](https://user-images.githubusercontent.com/48171810/194784675-54e3dc58-7846-450d-a1e9-cefd841dda94.png)
2022-10-09 19:56:07 -04:00
ManDude af5009a29e [decomp] make defpart and defpartgroup work in jak 2 (#1947) 2022-10-09 12:53:44 -04:00
Tyler Wilding 1d1ea907c9 scripts: prevent infinite loop when preserved block can't be found (#1946) 2022-10-08 21:53:23 -04:00
water111 405a144815 [decomp] finish up debug.gc, get boundary rendering working (#1944)
![image](https://user-images.githubusercontent.com/48171810/194726152-74167185-0297-4982-8ed9-42936ad80fe7.png)
2022-10-08 17:02:40 -04:00
water111 3d4dfb2077 [decomp] Decompile some time-of-day stuff, support new style Jak 2 time of day (#1943)
- Add "tfrag-water" tfrag tree support (may just be the same as Jak 1's
'dirt' for the settings)
- Add "tfrag-trans" tfrag tree support, reusing "trans-tfrag" from jak
1.
- Add a hack to `LinkedObjectFileCreation` to handle `oracle`, which is
accidentally multiply defined as a type leftover from jak 1 (an entity
in village1), and level info for jak 2.
- Add `VI1.DGO`
- add `time-of-day.gc`, and a few other stub functions so it works
- Set up some time of day stuff in GOAL for jak 2/PC renderers
- Clean up time of day in c++ renderers, support the more complicated
weight system used by jak 2 (backward compatible with jak 1, thankfully)

The mood functions now run, so this could cause problems if they rely on
stuff we don't have yet. But it seems fine for ctysluma and prison for
now.


![image](https://user-images.githubusercontent.com/48171810/194719441-d185f59c-19dc-4cd3-a5c4-00b0cfe1d6c3.png)


![image](https://user-images.githubusercontent.com/48171810/194719449-6e051bf3-0750-42e5-a654-901313dbe479.png)


![image](https://user-images.githubusercontent.com/48171810/194719455-3ca6793e-873a-449a-8e85-9c20ffeb4da3.png)


![image](https://user-images.githubusercontent.com/48171810/194719461-8f27af17-4434-4492-96cd-8c5eec6eafdf.png)


![image](https://user-images.githubusercontent.com/48171810/194719468-720715b9-985a-4acf-928c-eab948cfcb03.png)


![image](https://user-images.githubusercontent.com/48171810/194719486-bfb91e83-f6ca-4585-80ad-3b2c0cbbd5af.png)


![image](https://user-images.githubusercontent.com/48171810/194719492-df065d2f-cb5a-47e3-a248-f5317c42082f.png)


![image](https://user-images.githubusercontent.com/48171810/194719507-91e1f477-ecfe-4d6c-b744-5f24646255ca.png)
2022-10-08 13:33:03 -04:00
Tyler Wildingandwater be1e40a041 d/jak2: decompile conveyor | elevator | plat | bouncer | basebutton | base-plat | most of sampler | simple-nav-sphere | simple-focus | elec-gate and blocking-plane (#1942)
Most of these have been atleast partially documented / named / cleaned
up as well.

Co-authored-by: water <[email protected]>
2022-10-08 12:42:52 -04:00
Tyler Wilding 2d1b5fa57c d/jak2: finish region as well as some typedef files - ctywide-obs-h | vehicle-h | rigid-body-h (#1935) 2022-10-08 11:45:41 -04:00
water111 f1682867af [graphics] hook up visibility data for jak 2 (#1938)
It works!

Visibility off:

![image](https://user-images.githubusercontent.com/48171810/193422627-c5560519-6d20-4645-baa5-5236c7969d6e.png)

On:

![image](https://user-images.githubusercontent.com/48171810/193422631-716fff10-9ad7-486f-ad35-9ddcddf2c4eb.png)

Overall the visibility data looks a lot better than in jak 1.
2022-10-01 17:12:12 -04:00
water111 d52739226c [decomp] decompile decomp.gc (#1936)
A few issues:
- lwidea's fr3 is getting loaded and unloaded all the time
- the debug line drawing clipping is wrong (doesn't seem wrong in pcsx2,
so I think this is on us)
- nothing actually using vis data yet
- at a large distance, our view frustum culling seems slightly too
aggressive (might be that viewport scissoring is wrong)
- in the city, things seem darker as you move away. unclear how this is
happening (fog?)
2022-10-01 13:39:56 -04:00
water111 6bd4649fd0 fix deadlock on shutdown (#1937) 2022-10-01 12:29:08 -04:00
Tyler Wilding 4d751af38e logs: replace every fmt::print with a lg call instead (#1368)
Favors the `lg` namespace over `fmt` directly, as this will output the
logs to a file / has log levels.

I also made assertion errors go to a file, this unfortunately means
importing `lg` and hence `fmt` which was attempted to be avoided before.
But I'm not sure how else to do this aspect without re-inventing the
file logging.

We have a lot of commented out prints as well that we should probably
cleanup at some point / switch them to trace level and default to `info`
level.

I noticed the pattern of disabling debug logs behind some boolean,
something to consider cleaning up in the future -- if our logs were more
structured (knowing where they are coming from) then a lot this
boilerplate could be eliminated.

Closes #1358
2022-10-01 11:58:36 -04:00
ManDude 4e48ba21c1 [decompiler] make (not (logtest? work (#1934) 2022-09-30 18:26:52 -04:00
ManDude 11ec9d5d14 write a function that outputs a dot graph of the jak 2 tasks (#1932) 2022-09-29 19:10:58 +01:00
ManDude 9351bf782e [decomp2] game-info, game-task and task-control (#1884)
And everything else needed for them!

A couple functions are bad currently.

- fixes #1929 - untested on linux
- fixes #1924 - now you need to type `,` before a lambda you want to put
in a pair.
- fix debugger symbol table in jak 2
- made the decompiler output `(meters 2)` instead of `(meters 2.0)`
- fixed a bug with the bitfield enum special -1 case
- made bad game text decomp not exit the decompiler
- added `editable-player` and `script`
2022-09-27 19:44:20 -04:00
water111 e3a4627eeb [decompiler] recognize jak 2 vector-float*!, fix some vector inline casting bugs (#1926) 2022-09-26 20:57:44 -04:00
water111 bdf63b9048 [decomp] sync-info, fix some looping type pass bugs (#1925) 2022-09-26 19:40:46 -04:00
water111 a22d49ab11 [decompiler] fix rare bug with casts (#1920) 2022-09-26 18:14:54 -04:00
water111 5c7a3384e5 [jak2] static sound macro (#1919)
eg
```
(set! (-> obj sound-pre-open) (static-sound-spec "airlock-slider"))
```
it is the same as jak 1, but the `fo-curve` option is set to 1
sometimes.
2022-09-25 16:19:06 -04:00
water111 b5705bde96 [decomp] Partial implementation of tie (#1916)
Some stuff isn't working fully yet:
- fog color
- time of day
- draw order for multiple passes (currently all draws in the default tie
bucket)
- possibly settings for transparent stuff (untested, but might work)
- the "vanish" effect (we might not want this anyway?)
- environment mapping/etie completely not implemented.


![image](https://user-images.githubusercontent.com/48171810/192154314-2cc8ac51-9dad-474f-a84b-3a1d98973215.png)

![image](https://user-images.githubusercontent.com/48171810/192154316-457a7ee0-b5a4-4a40-b48e-8863114da735.png)
2022-09-25 12:50:51 -04:00
Hat Kid a53c06fe2b decomp: target, target-board, board-states (#1915)
Just missing `target-board-handler` because it errored with `Bad delay
slot in clean_up_cond_no_else_final` and I wasn't able to figure out
where the asm branch was.

Commented out `target-board-clone-anim` because it crashes even after
adding `clone-anim` and `clone-anim-once`.
2022-09-25 12:07:37 -04:00
Hat Kid e8b1aee24d decomp: majority of progress (#1904)
Gets through ~90% of `progress`, wasn't able to figure out some stuff.
2022-09-25 10:15:32 -04:00
water111 edecac9f09 [decomp] add shrubbery renderer (#1914)
as with last time, fog and time of day are still garbage, but it still
works:


![image](https://user-images.githubusercontent.com/48171810/192119423-91b80500-a161-42ce-b734-0c528cc721cf.png)

The shrub near render is just falling back to generic again.
2022-09-24 17:46:13 -04:00
water111 6227c6d6a8 More array special cases (#1913)
also make jak 1 and jak 2 behave the same way, to reduce confusion. It
wasn't too bad to update jak 1.
2022-09-24 16:10:13 -04:00
Tyler Wilding 332f0b2f2b tools: add a tool to search for types based on size / type chain / fields (#1906)
Just a small simple tool that can search through `all-types` for a type
based on a bunch of criteria.

For example:

![image](https://user-images.githubusercontent.com/13153231/192043561-181e5c5d-d5b1-41a9-8891-5cc3ed1a0efa.png)

The results are printed to stdout, as well as output to a json file so
they can be consumed by another tool (in my plans, the VSCode extension)
2022-09-24 16:04:52 -04:00
Tyler Wilding 7dd8053697 fix test failure and stop running manual tests in CI (#1912) 2022-09-24 15:56:53 -04:00
water111 903450b878 [decompiler] recognize mfc nop (#1911)
Forgot to include in previous PR.
2022-09-24 14:56:22 -04:00
Tyler Wilding 123e7fd87b d/jak2: some work in memory-usage | nav-graph-h and finish pov-camera and aligner (#1901) 2022-09-24 14:47:03 -04:00
water111 80cefb9575 [decomp] background and tfrag (#1909) 2022-09-24 14:30:44 -04:00
Tyler Wilding d00ebe5397 tests: allow for a single file to be tested in the offline-tests at a time (#1907)
A small quality of life increase that is more impactful since jak 2 has
double the file count.

I often use the offline-tests to find compiler errors / automatically
resolve them when i am finalizing a file. As more and more files are
completed this becomes increasingly more inefficient. When I know that
only 1 file needs to be decompiled / compared / compiled, I'd prefer to
have a feature like this.
2022-09-24 13:04:52 -04:00
Matt Dallmeyer d30c635089 Fix infinite pause buffer bug (#1900)
Fixes #1886 which was introduced in #1756 
 
Changed to only read the dpad inputs for hud toggle if L2/R2 were
considered held (they're not read during a pause buffer)
2022-09-24 12:27:44 -04:00
Tyler Wilding e64414d9d0 d/jak2: finish drawable-group | drawable-inline-array | drawable-tree and path (#1899) 2022-09-24 12:27:02 -04:00
tripp 66b19296ef add project path option to the compiler (#1826) 2022-09-24 12:06:26 -04:00
Ethan Lafrenais dc5dc9c76c [decomp] jak2: shrubbery (#1898)
Some notes:
- `draw-prototype-inline-array-shrub` can probably be decompiled but I'm
not comfortable doing this function myself. It's got a ton of inline
assembly (or at least I think it's inline assembly) and is very long. I
left this marked as asm for now but I am confident in the function
definition.
- The VU program is identical to Jak 1 (yay)
- There's some new `dma-test` stuff at the end of the file, not really
sure what it's doing but it runs in the top-level.
2022-09-18 12:19:16 -04:00
water111 1b45aab3cc [decompile] subdivide, wind-work, tie-work, bsp, focus (#1897)
- decompile `subdivide`, `wind-work`, `tie-work`, `bsp`, `focus`
- support `ppacb` in compiler
- don't assert when bitfield stuff fails due to constant propgataion
weirdness
- finish up history
- div/mod unsigned assert fix in decompiler
- empty assert fix in decompiler for failed `add` type prop
- make jak 1 performance counters "work" (just measure time)
- fix cast/typos on pcgtb/vftoi15
2022-09-17 14:58:25 -04:00
water111 80526dfca0 [decompiler] fix local_vars assert on static lambda (#1895)
Fixes a crash when there's a `(new 'static 'something :field <some
anonymous function with a particular set of errors in the decompler>)`.
The output will now be
```
 (set! *duck-mods* (new 'static 'surface
                      :name 'duck
...
                      :mult-hook <lambda at L615>
                      :flags (surface-flag duck)
                      )
```

fixes https://github.com/open-goal/jak-project/issues/1882
2022-09-16 23:40:16 -04:00
water111 6a1bde4168 [decomp] fix up debug menu rendering, add a few others (#1892)
![image](https://user-images.githubusercontent.com/48171810/190832869-e609d346-9c4a-43fb-ad94-2a9690521adc.png)
actor vis boxes for PRI.DGO
2022-09-16 20:42:33 -04:00
Tyler Wilding d95ff2d2fb lsp: improve LSP IR2 hovers (#1891)
Some new hover features:

docstrings (`@param/@return` syntax is not yet supported, nor is a
syntax-highlighted preview, will do later)

![image](https://user-images.githubusercontent.com/13153231/190830490-d0ef774c-e7e5-4bb9-8007-b366be0f491e.png)

better MIPs instruction descriptions

![image](https://user-images.githubusercontent.com/13153231/190830507-0bb35c13-7e88-4b74-a63b-b7fb3587b82e.png)

numeric hovers convert to different bases / tell you the OpenGOAL method
id (i can't tell you the amount of times ive done -16 / 4 manually
myself...)

![image](https://user-images.githubusercontent.com/13153231/190830674-f66ed15a-f983-48ff-b251-259374dfbcac.png)

Closes https://github.com/open-goal/opengoal-vscode/issues/33
Closes https://github.com/open-goal/opengoal-vscode/issues/31
Related to https://github.com/open-goal/opengoal-vscode/issues/29
2022-09-16 20:28:44 -04:00
Tyler Wilding 4e3c44294e lsp: re-process all-types file when it changes (#1889)
Found the reason why this wasn't happening -- the path included by the
decompiler isn't a proper URL encoded URI -- so I have to convert it
appropriately so when vscode sends it's "this file with this URI has
changed" event it actually matches the tracked all-types file.

This will make jump-to-defs not drift as the file changes, and new
uncommented symbols will actually get picked up
2022-09-16 20:28:09 -04:00
Tyler Wilding 0f4f70e66d logs: prefer exceptions over stdout logs around defenums (#1887)
This was causing an issue in the LSP because the `fmt::print`s clash
with the transport over stdin/out
2022-09-16 20:27:22 -04:00
Tyler Wilding 82e0517275 d/jak2: get script decompiling, no ref tests yet (#1877)
Has boxed array accessing that prevents me from adding anything to ref
tests (the entire file is lambdas so the access pattern that i would
like to ignore happens at the top-level, can't ignore it.

This code actually already has quite a bit of original docstrings so
it's not too bad in that regard considering a `script-context` can have
16 arbitrary objects. It seems they rarely put more than a single object
in the context and the types are usually obvious / are actually type
checked!
2022-09-14 19:37:12 -04:00
Tyler Wilding 8117ed3bc7 scripts: make update_decomp_ref.py respect the game we are operating on (#1880) 2022-09-13 20:03:00 -04:00
Tyler Wilding 4620f96574 d/jak2: mostly finish mysql-nav-graph and fix docstring handling around with-pp/local-vars (#1869) 2022-09-13 18:15:02 -04:00
Alexis Lefebvre b2f7f15cb5 README: fix a typo (#1881) 2022-09-13 17:37:10 -04:00
Alexis Lefebvre ef22563d36 README: update the Docker part (#1870)
It was written:

> If you the build directory you'll need…

I tried to fix it, hopefully I found the correct wording. Otherwise
please let me know what was missing.
2022-09-12 18:08:03 -04:00
water111 4eea31c3e9 [jak 2] texture (#1866)
- Decompile and patch `texture.gc` for PC
- Improve decompiler when offset doesn't fit in immediate (for types
larger than 8k and some scratchpad accesses)
- Fix symbol->string issues in both jak 1 and 2
- Fix bug with VIF interrupt used to profile VU code (hooked up to
OpenGLRenderer BucketRenderers in PC port)
- Support `~o` in `format`.
- Uncomment stuff in `merc.gc` that now works!

![image](https://user-images.githubusercontent.com/48171810/189505469-941b4a3e-23c7-4740-aa1b-2e461ed19fa9.png)

fixes https://github.com/open-goal/jak-project/issues/1850
2022-09-11 14:17:55 -04:00
Tyler Wilding 017070525a d/jak2: finish vol | cam-layout | menu | default-menu and start working on nav code (#1867)
I also added font-color names since this PR adds quite a few:

![image](https://user-images.githubusercontent.com/13153231/189508209-c8849672-fac5-47cb-9652-f1d4648f0af8.png)
2022-09-11 13:42:46 -04:00
animalstyletacoandanimalstyletaco 813611e0b2 Fixed typo in gfx.cpp (#1868)
Co-authored-by: animalstyletaco <[email protected]>
2022-09-11 18:31:41 +01:00
Hat Kid 7339b2b965 decomp: merc, merc-vu1 (#1865)
The merc VU1 program is identical to Jak 1. Jak 2's merc is doing some
new texture login stuff and the DMA buffer setup is a bit different, but
overall very similar.
2022-09-10 19:02:58 -04:00
Tyler Wilding 81b6d5fe08 d/jak2: finish find-nearest | trajectory | editable-h and most of editable and editable-player (#1847)
Also made a first-pass of their SQL schema in preparation for getting
that working.
2022-09-10 18:03:17 -04:00
Tyler Wilding 7baf253a1a jak1: fix the flickering driller-lurkers on >60 fps (#1862) 2022-09-08 18:34:53 -04:00
Hat Kid bb777e4bac decomp: logic-target (#1861)
Also adds all names for `focus-status`.

Closes #1859 and updates ref tests for Jak 1 for this edge case.
2022-09-08 18:26:33 -04:00
water111 f3c63f26bb fix let* format, new on stack guessing case, type failure, handle casts (#1860)
Fixes https://github.com/open-goal/jak-project/issues/1821 by adding a
special case for `new` method calls where the argument with type
`symbol` is actually an address to uninitialized structure on the stack.

Fixes https://github.com/open-goal/jak-project/issues/1849 (or at least
the cause of the issue Vaser gave in chat, and one random one I found in
`debug-sphere`)

Fixes https://github.com/open-goal/jak-project/issues/1853

Fixes https://github.com/open-goal/jak-project/issues/1857 by moving the
cast into the cond if the body is a single form and the destination type
is a bitfield/enum which is likely to work well. Seems to work on the
examples we could find in jak 1 and jak 2.

Also fixes an issue with casts on the result of `handle->process` (a
common place to use casts)

the output of process->handle is a plain process. Most of the time, you
end up casting this to a more specific. If you add a cast on every use
of the variable, the decompiler will decide to change the type of that
variable to the more specific type, and this breaks the handle cast.

so previously it was impossible to get code like
```
    (let* ((s2-0 (the-as swingpole (handle->process (-> self control hack))))
           (gp-0 (-> s2-0 dir))
           )
```
But now it will work
2022-09-07 21:58:09 -04:00
ManDude cfb6abb24d [decompiler] rewrite set lets as just sets (#1858)
Rewrites specific kinds of lets where the return value of the `set!`
itself is meant to be used to just be `set!`s. Implemented at the let
rewrite level. Seems to work for Jak 2 so far.

Fixes #1854 .
2022-09-07 18:28:01 -04:00
ZedB0TandTyler Wilding 97c12ebaf4 [speedrun] Show speedrun information at start of run (#1848)
This shows the current settings needed to help provide information when
verifying a run, also it removes the two calls to show the version in
main.gc and instead does it within the speedrun/auto splitting scope.

- Shows Version
- Shows if Speedrunner mode is on (technically pointless since the text
only displays when it is enabled this more just serves to show that
there IS a speedrunner mode to viewers and stuff (josh) So hopefully it
may cut down on submissions with the mode off)
- Shows if cutscene skips is enabled/disabled.

Tested on 16x9 4x3 the really weird one and borderless/fullscreen

[![IMAGE ALT TEXT
HERE](https://img.youtube.com/vi/qDC-beEg5Es/0.jpg)](https://www.youtube.com/watch?v=qDC-beEg5Es)

Co-authored-by: Tyler Wilding <[email protected]>
2022-09-07 18:18:37 -04:00
Ethan Lafrenais 22982d2750 [decomp] jak2: debug, debug-sphere (#1846)
I wasn't able to 100% complete `debug` due to a bunch of level boundary
debug stuff I couldn't figure out. But, I added a ref test and
documented/copied over everything else into goal_src.

Most of the functions that existed in Jak 1 are identical, others got an
extra param or 2 and some now make copies of arguments instead of
modifying them. There's a bunch of new functions, including all of the
debug functions that used to be in `level-boundary` are now in `debug`.
At the very end of `debug` there's also some weird asm functions
checking for some EE memory controller bug (not sure what's up with
that)?
2022-09-07 18:14:34 -04:00
Tyler Wilding 44d59e6b33 d/jak2: finish mood-funcs | mood-funcs2 | almost all of mood and airlock (#1842) 2022-09-06 20:35:00 -04:00
water111 b5d21be9c5 W/misc fixes (#1838)
* temp

* temp

* before cleaning up

* cleanup merge

* fix warnings

* merge fix

* clang format
2022-09-05 20:29:12 -04:00
Tyler Wilding 80d0137dba d/jak2: finish the majority of sparticle and sparticle-launcher (#1840)
* sparticle-launcher

* d/jak2: large amount of `sparticle-launcher` done

* d/jak2: finish the majority of `sparticle`

* decomp: improve format code ignoring

* d/jak2: make bits unique in `sp-cpuinfo-flag`

* d/jak1: revert config change
2022-09-05 18:03:46 -04:00
Tyler Wilding 71871595da lsp: re-analyze IR2 files when they change (#1841)
* lsp: re-analyze IR2 files when they change

* tests: update ref tests
2022-09-05 17:45:41 -04:00
ManDude 9f90a7c2db small jak1 decomp cleanup (#1843)
small cleanup
2022-09-05 17:43:59 -04:00
OpenGOALBot 7177cb5bdc Updating Controller Database 2022-09-05 16:23:09 +00:00
Matt Dallmeyer 6c52905860 Fix crash in light jak cutscene skip (#1839) 2022-09-03 14:53:56 -04:00
Hat Kid 2a1dc7bd2b decomp: emerc, emerc-vu1 (#1833)
* decompiler: add support for `MADDq` in VU disassembler, add `emerc-vu1` program

* decomp: `emerc`, `emerc-vu1`
2022-09-02 18:29:30 -04:00
ZedB0T 59617c2ee0 Make the citadel elevator come up when cutscene is skipped (#1832)
Still comes up from the bottom, but its probably the "correct" way to do it?

The other alternative would be killing Jak when the cutscene is skipped instead of `(start 'play (get-continue-by-name *game-info* "citadel-elevator"))` This would make the elevator at the top instantly, however it might mess with hp values and stored levels.

Credit to Barg/dallmeyer
2022-09-02 18:26:10 -04:00
Tyler Wilding 0896bef2bf jak1/speedruns: Some final touches for speedrunning in jak 1 (#1830)
* jak1: put common speedrunning code into it's own file

* jak1: enforce `60` fps while in speedrunning mode

* jak1: when speedrunning, display the version until you get the first powercell

* jak1: add an explicit option for skipping cutscenes

* jak1: extend `game-option` to allow any menu option to be disabled

* tests/jak1: allow whitelisting types to be redefined to satisfy typeconsistency checks

* jak1: add file headers

* jak1: cleanup bool checking

* test: delete the es substitle file

* test: add it back

* jak1: missed one cleanup spot related to bool comparisons
2022-09-02 18:15:42 -04:00
ManDude f1f18e7e05 [decomp2] joint-mod, chain-physics, loader (#1816)
* prep

* Update repo-settings-mark.bat

* Update repo-settings-unmark.bat

* decomp `joint-mod`

* add `joint-mod-ik-callback` to ref exceptions

* `chain-physics`

* Update jak2_ntsc_v1.jsonc

* update bat scripts

* `loader`

* pretty

* refs

* support `process->handle` (and `ppointer->handle`?)

* refs

* source and fixes

* fix `ja` detect

* `ja` macro implement

* fix a method

* update source

* merge fixes

* annoying fixes

* format

* arg

* hack

* fix test
2022-09-02 18:13:38 -04:00
water111 909bde8b1e add menu option for ptbr (#1835) 2022-09-02 11:50:10 -04:00
water111 97637d7902 fix for windows newlines (#1834) 2022-09-01 22:44:43 -04:00
13829 changed files with 6680878 additions and 833579 deletions

No files matched your search

+1 -1
View File
@@ -10,7 +10,7 @@ IncludeCategories:
Priority: 2
- Regex: '^(<|")common.*'
Priority: 3
- Regex: '^"third-party.*'
- Regex: '^"(third-party|fmt|curl).*'
Priority: 4
SortPriority: 5
- Regex: '.*'
-81
View File
@@ -1,81 +0,0 @@
name: "\U0001F41B Bug Report"
description: Create a bug report.
labels: ["bug"]
body:
- type: checkboxes
attributes:
label: Acknowledgements
description: Take a couple minutes to help our maintainers work faster.
options:
- label: I have [searched](https://github.com/open-goal/jak-project/issues?q=is%3Aissue+is%3Aopen+label%3Abug+sort%3Aupdated-desc) for duplicate or closed bug reports
required: true
- label: I understand that I am supposed to provide my own legitimately obtained copy of the game
required: true
- type: textarea
attributes:
label: Describe the Bug
description: A clear and concise description of what the bug is. You may post screenshots or videos of the bug here.
validations:
required: true
- type: textarea
attributes:
label: How To Reproduce
description: Steps to reproduce the behavior. You can also post a video of it here.
validations:
required: true
- type: dropdown
attributes:
label: Does this problem occur on original hardware or PCSX2?
description: Some things that may seem like bugs are actually exactly how the original game behaved.
options:
- Yes, it's unique to OpenGOAL
- Didn't check
- Not needed, bug is obvious
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A clear and concise description of the expected behavior.
placeholder: When I do X, Y should happen.
validations:
required: true
- type: input
attributes:
label: Operating System
description: Windows version, Linux distribution, etc.
validations:
required: true
- type: input
attributes:
label: OpenGOAL Version
description: Either the release version (vX.X.X) or the commit sha if you've built from source
validations:
required: true
- type: dropdown
attributes:
label: Game Version
options:
- NTSC 1.0 (black label)
- NTSC Greatest Hits version (red label)
- PAL
- JP
validations:
required: true
- type: dropdown
attributes:
label: Are you using a high refresh-rate monitor (>60Hz)
options:
- "No"
- "Yes"
validations:
required: true
+7
View File
@@ -1 +1,8 @@
blank_issues_enabled: true
contact_links:
- 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).
- name: Discord Help Channel
url: https://discord.gg/dPRCfsju3N
about: The best place for general help and asking questions.
@@ -1,24 +0,0 @@
name: "\U0001F680 Enhancement Request"
description: Suggest an improvement for an existing feature.
labels: ["enhancement"]
body:
- type: textarea
attributes:
label: What feature is your idea related to?
description: A clear and concise description of what the problem is.
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like.
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Any other context or screenshots about the enhancement request here.
validations:
required: false
@@ -1,24 +0,0 @@
name: "\U0001F3AE Game Feature Request"
description: Suggest an idea for the game
labels: ["game"]
body:
- type: textarea
attributes:
label: Is your feature request related to a problem?
description: A clear and concise description of what the problem is.
validations:
required: true
- type: textarea
attributes:
label: Describe the solution you'd like.
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Add any other context or screenshots about the feature request here.
validations:
required: false
@@ -0,0 +1,74 @@
name: "\U0001F41B Jak 1 Bug Report"
description: Create a bug report for Jak 1.
labels: ["bug", "jak1"]
body:
- type: checkboxes
attributes:
label: Acknowledgements
description: Take a couple minutes to help our maintainers work faster.
options:
- label: I have [searched](https://github.com/open-goal/jak-project/issues?q=is%3Aissue+is%3Aopen+label%3Abug+label%3Ajak1+sort%3Aupdated-desc+) for duplicate or closed bug reports
required: true
- label: I understand that I am supposed to provide my own legitimately obtained copy of the game
required: true
- type: textarea
attributes:
label: Describe the Bug
description: A clear and concise description of what the bug is. You may post screenshots or videos of the bug here.
validations:
required: true
- type: textarea
attributes:
label: How To Reproduce
description: Steps to reproduce the behavior. You can also post a video of it here.
validations:
required: true
- type: dropdown
attributes:
label: Does this problem occur on original hardware or PCSX2?
description: Some things that may seem like bugs are actually exactly how the original game behaved.
options:
- Yes, it's unique to OpenGOAL
- Didn't check
- Not needed, bug is obvious
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A clear and concise description of the expected behavior.
placeholder: When I do X, Y should happen.
validations:
required: true
- type: textarea
attributes:
label: Environment Information
description: "You can upload the [Support Package](https://github.com/open-goal/launcher#asking-for-help) provided by the Launcher here, or you can provide the following information: CPU, GPU, OS Version, OpenGOAL Version (found in the window's title bar)"
validations:
required: true
- type: dropdown
attributes:
label: Game Version
options:
- NTSC 1.0 (black label)
- NTSC Greatest Hits version (red label)
- PAL
- JP
validations:
required: true
- type: dropdown
attributes:
label: Have you set the game to something other than `60fps`?
options:
- "No"
- "Yes"
validations:
required: true
@@ -0,0 +1,74 @@
name: "\U0001F41B Jak 2 Bug Report"
description: Create a bug report for Jak 2.
labels: ["bug", "jak2"]
body:
- type: checkboxes
attributes:
label: Acknowledgements
description: Take a couple minutes to help our maintainers work faster.
options:
- label: I have [searched](https://github.com/open-goal/jak-project/issues?q=is%3Aissue+is%3Aopen+label%3Abug+label%3Ajak2+sort%3Aupdated-desc+) for duplicate or closed bug reports
required: true
- label: I understand that I am supposed to provide my own legitimately obtained copy of the game
required: true
- type: textarea
attributes:
label: Describe the Bug
description: A clear and concise description of what the bug is. You may post screenshots or videos of the bug here.
validations:
required: true
- type: textarea
attributes:
label: How To Reproduce
description: Steps to reproduce the behavior. You can also post a video of it here.
validations:
required: true
- type: dropdown
attributes:
label: Does this problem occur on original hardware or PCSX2?
description: Some things that may seem like bugs are actually exactly how the original game behaved.
options:
- Yes, it's unique to OpenGOAL
- Didn't check
- Not needed, bug is obvious
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: A clear and concise description of the expected behavior.
placeholder: When I do X, Y should happen.
validations:
required: true
- type: textarea
attributes:
label: Environment Information
description: "You can upload the [Support Package](https://github.com/open-goal/launcher#asking-for-help) provided by the Launcher here, or you can provide the following information: CPU, GPU, OS Version, OpenGOAL Version (found in the window's title bar)"
validations:
required: true
- type: dropdown
attributes:
label: Game Version
options:
- NTSC 1.0 (black label)
- NTSC Greatest Hits version (red label)
- PAL
- JP
validations:
required: true
- type: dropdown
attributes:
label: Have you set the game to something other than `60fps`?
options:
- "No"
- "Yes"
validations:
required: true
@@ -1,40 +0,0 @@
#!/usr/bin/env bash
set -e
DEST=${1}
BIN_SOURCE=${2}
SOURCE=${3}
mkdir -p $DEST
PREP_BIN="${PREP_BIN:-true}"
if [ "$PREP_BIN" = "true" ]; then
cp $BIN_SOURCE/game/gk $DEST
cp $BIN_SOURCE/goalc/goalc $DEST
cp $BIN_SOURCE/decompiler/extractor $DEST
strip $DEST/gk
strip $DEST/goalc
strip $DEST/extractor
chmod +x $DEST/gk
chmod +x $DEST/goalc
chmod +x $DEST/extractor
fi
mkdir -p $DEST/data
mkdir -p $DEST/data/launcher/
mkdir -p $DEST/data/decompiler/
mkdir -p $DEST/data/assets
mkdir -p $DEST/data/game
mkdir -p $DEST/data/log
mkdir -p $DEST/data/game/graphics/opengl_renderer/
cp -r $SOURCE/.github/scripts/releases/error-code-metadata.json $DEST/data/launcher/error-code-metadata.json
cp -r $SOURCE/decompiler/config $DEST/data/decompiler/
cp -r $SOURCE/goal_src $DEST/data
cp -r $SOURCE/game/assets $DEST/data/game/
cp -r $SOURCE/game/graphics/opengl_renderer/shaders $DEST/data/game/graphics/opengl_renderer
cp -r $SOURCE/custom_levels $DEST/data
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -e
DEST=${1}
BIN_SOURCE=${2}
SOURCE=${3}
mkdir -p $DEST
PREP_BIN="${PREP_BIN:-true}"
if [ "$PREP_BIN" = "true" ]; then
cp $BIN_SOURCE/game/gk $DEST
cp $BIN_SOURCE/goalc/goalc $DEST
cp $BIN_SOURCE/decompiler/extractor $DEST
chmod +x $DEST/gk
chmod +x $DEST/goalc
chmod +x $DEST/extractor
fi
mkdir -p $DEST/data
mkdir -p $DEST/data/launcher/
mkdir -p $DEST/data/decompiler/
mkdir -p $DEST/data/game
mkdir -p $DEST/data/log
mkdir -p $DEST/data/game/graphics/opengl_renderer/
cp -r $SOURCE/.github/scripts/releases/error-code-metadata.json $DEST/data/launcher/error-code-metadata.json
cp -r $SOURCE/decompiler/config $DEST/data/decompiler/
cp -r $SOURCE/goal_src $DEST/data
cp -r $SOURCE/game/assets $DEST/data/game/
cp -r $SOURCE/game/graphics/opengl_renderer/shaders $DEST/data/game/graphics/opengl_renderer
cp -r $SOURCE/custom_assets $DEST/data
@@ -15,7 +15,6 @@ cp $BIN_SOURCE/extractor.exe $DEST
mkdir -p $DEST/data
mkdir -p $DEST/data/launcher/
mkdir -p $DEST/data/decompiler/
mkdir -p $DEST/data/assets
mkdir -p $DEST/data/game
mkdir -p $DEST/data/log
mkdir -p $DEST/data/game/graphics/opengl_renderer/
@@ -25,4 +24,4 @@ cp -r $SOURCE/decompiler/config $DEST/data/decompiler/
cp -r $SOURCE/goal_src $DEST/data
cp -r $SOURCE/game/assets $DEST/data/game/
cp -r $SOURCE/game/graphics/opengl_renderer/shaders $DEST/data/game/graphics/opengl_renderer
cp -r $SOURCE/custom_levels $DEST/data
cp -r $SOURCE/custom_assets $DEST/data
-35
View File
@@ -1,35 +0,0 @@
import glob
src_files = glob.glob("./goal_src/**/*.g[cs]", recursive=True)
# Find how many of each have been started
src_files_started = 0
src_files_finished = 0
data_files_started = 0
for f in src_files:
with open(f, "r") as temp_file:
lines = temp_file.readlines()
line_count = len(lines)
if line_count > 7:
# Check to see if there are any TODOs
if any("TODO" in string for string in lines):
src_files_finished = src_files_finished + 1
else:
src_files_started = src_files_started + 1
import json
with open('./docs/gh-pages-proj/src/config/progress.json', 'r+', encoding='utf-8') as f:
data = {
'jak1': {
'fileProgress': {
'src_files_total': len(src_files),
'src_files_finished': src_files_finished,
'src_files_started': src_files_started
}
}
}
f.seek(0)
json.dump(data, f, ensure_ascii=False, indent=2)
f.truncate()
-63
View File
@@ -1,63 +0,0 @@
import glob
import os
from pathlib import Path
import json
galleryLinks = {
'jak1': {
'name': "Jak 1",
'media': [],
},
'jak2': {
'name': "Jak 2",
'media': [],
},
'jak3': {
'name': "Jak 3",
'media': [],
},
'jakx': {
'name': "Jak X",
'media': [],
},
'misc': {
'name': "Miscellaneous",
'media': [],
}
}
def get_links(key, folder_to_search):
if os.path.isdir(folder_to_search):
files = glob.glob(folder_to_search + "/*.png", recursive=True)
files.extend(glob.glob(folder_to_search + "/*.jpg", recursive=True))
files.extend(glob.glob(folder_to_search + "/*.jpeg", recursive=True))
for f in files:
galleryLinks[key]["media"].append({
'fileName': os.path.basename(f),
'timestamp': Path(f).stem.split("_")[1],
'caption': Path(f).stem.split("_")[0].replace("-", " ").title(),
'video': False
})
# get videos potentially
if os.path.exists("{}/videos.json".format(folder_to_search)):
with open("{}/videos.json".format(folder_to_search), 'r') as f:
data = json.load(f)
for video in data:
galleryLinks[key]["media"].append({
'link': video["link"].replace("watch?v=", "embed/"),
'timestamp': video["timestamp"],
'video': True
})
# sort by timestamp
galleryLinks[key]["media"].sort(key=lambda x: x["timestamp"], reverse=True)
get_links('jak1', './docs/gh-pages-proj/src/assets/gallery/jak1')
get_links('jak2', './docs/gh-pages-proj/src/assets/gallery/jak2')
get_links('jak3', './docs/gh-pages-proj/src/assets/gallery/jak3')
get_links('jakx', './docs/gh-pages-proj/src/assets/gallery/jakx')
get_links('misc', './docs/gh-pages-proj/src/assets/gallery/misc')
with open('./docs/gh-pages-proj/src/config/gallery.json', 'r+', encoding='utf-8') as f:
f.seek(0)
json.dump(galleryLinks, f, ensure_ascii=False, indent=2)
f.truncate()
+19 -1
View File
@@ -3,10 +3,11 @@ name: Build
on:
push:
branches:
- '*'
- master
pull_request:
branches:
- master
merge_group: {}
jobs:
# Windows
@@ -42,3 +43,20 @@ jobs:
cmakePreset: "Release-linux-gcc"
cachePrefix: ""
secrets: inherit
# MacOS
build_macos_intel:
name: "🍎 MacOS"
uses: ./.github/workflows/macos-build.yaml
with:
cmakePreset: "Release-macos-clang"
cachePrefix: ""
# Q4 2023 there will hopefully be native arm64 runners
# https://github.com/github/roadmap/issues/528
# build_macos_arm:
# name: "🍎 MacOS"
# uses: ./.github/workflows/macos-build-arm.yaml
# with:
# cmakePreset: "Release-macos-clang"
# cachePrefix: ""
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
- name: Bump Version and Push Tag
if: github.repository == 'open-goal/jak-project'
id: tag_version
uses: mathieudutour/github-tag-action@v6.0
uses: mathieudutour/github-tag-action@v6.2
with:
github_token: ${{ secrets.BOT_PAT }}
tag_prefix: v
+70 -5
View File
@@ -6,17 +6,82 @@ on:
- master
paths:
- 'goal_src/**'
workflow_dispatch: {}
jobs:
inform:
name: Inform Pages Repo
gen-docs:
name: Generate Documentation
if: github.repository == 'open-goal/jak-project'
runs-on: ubuntu-latest
timeout-minutes: 10
runs-on: ubuntu-20.04
timeout-minutes: 45
env: # overrides: https://github.com/mbitsnbites/buildcache/blob/master/doc/configuration.md
BUILDCACHE_MAX_CACHE_SIZE: 1000000000 # 1gb
BUILDCACHE_COMPRESS_FORMAT: ZSTD
BUILDCACHE_COMPRESS_LEVEL: 19
BUILDCACHE_DIRECT_MODE: true
BUILDCACHE_LOG_FILE: ${{ github.workspace }}/buildcache.log
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install Package Dependencies
run: |
sudo apt update
sudo apt install build-essential cmake \
clang gcc g++ lcov make nasm libxrandr-dev \
libxinerama-dev libxcursor-dev libpulse-dev \
libxi-dev zip ninja-build libgl1-mesa-dev
- name: Setup Buildcache
uses: mikehardy/[email protected]
with:
cache_key: linux-ubuntu-20.04--Release-linux-clang
buildcache_tag: v0.28.1
- name: CMake Generation
env:
CC: clang
CXX: clang++
run: |
cmake -B build --preset=Release-linux-clang \
-DCMAKE_C_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache \
-DCMAKE_CXX_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache
- name: Build Project
run: cmake --build build --parallel $((`nproc`)) --target goalc
- name: Generate Docs For Jak 1
run: |
./build/goalc/goalc --cmd "(begin (make-group \"all-code\") (gen-docs \"${PWD}\"))" --game jak1
- name: Generate Docs For Jak 2
run: |
./build/goalc/goalc --cmd "(begin (make-group \"all-code\") (gen-docs \"${PWD}\"))" --game jak2
- name: Generate Docs For Jak 3
run: |
./build/goalc/goalc --cmd "(begin (make-group \"all-code\") (gen-docs \"${PWD}\"))" --game jak3
- name: Append File Docstrings
run: |
python ./scripts/ci/docs/append-file-docs.py
- name: Upload Docs Artifact
uses: actions/upload-artifact@v4
with:
name: opengoal-docs
if-no-files-found: error
path: |
./jak1*.json
./jak2*.json
- name: Log Run ID
run: echo ${{ github.run_id }}
- name: Send Dispatch
uses: peter-evans/repository-dispatch@v2
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.BOT_PAT }}
repository: 'open-goal/open-goal.github.io'
event-type: updateProgress
client-payload: '{"docGenRunId": "${{ github.run_id }}"}'
+48 -4
View File
@@ -3,26 +3,70 @@ name: Lint
on:
push:
branches:
- '*'
- master
pull_request:
branches:
- master
merge_group: {}
jobs:
lint:
formatting:
name: 📝 Formatting
runs-on: ubuntu-20.04
timeout-minutes: 10
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
# wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
# sudo add-apt-repository 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main'
# sudo apt install clang-format-15
# --clang-format-executable $(which clang-format-15)
- name: Get Package Dependencies
run: |
sudo apt install clang-format clang-tidy
sudo apt update
sudo apt install clang-format
clang-format -version
- name: Check Clang-Formatting
run: |
chmod +x ./third-party/run-clang-format/run-clang-format.py
./third-party/run-clang-format/run-clang-format.py -r common decompiler game goalc test tools lsp --color always
required-checks:
name: 📝 Required Checks
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- 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
- name: Check for Incorrect Asserts
run: python ./scripts/ci/check-for-asserts.py
- name: Check for Invalid Translation Characters
run: python ./scripts/ci/lint-characters.py
optional-checks:
name: 📝 Optional Checks
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install Python Dependencies
run: pip install unidiff colorama
- name: Check for Removed goal_src/ Code
# FYI - if you run this `git diff` on windows, it creates a utf-16 LE file
run: |
git fetch origin
git diff origin/master > lint-changes.diff
python ./scripts/ci/lint-gsrc-removals.py
+31 -21
View File
@@ -9,35 +9,36 @@ on:
cachePrefix:
required: true
type: string
uploadArtifacts:
required: false
type: boolean
default: false
jobs:
build:
name: Clang
runs-on: ubuntu-20.04
timeout-minutes: 45
env: # overrides: https://github.com/mbitsnbites/buildcache/blob/master/doc/configuration.md
BUILDCACHE_MAX_CACHE_SIZE: 1000000000 # 1gb
BUILDCACHE_COMPRESS_FORMAT: ZSTD
BUILDCACHE_COMPRESS_LEVEL: 19
BUILDCACHE_DIRECT_MODE: true
BUILDCACHE_LOG_FILE: ${{ github.workspace }}/buildcache.log
timeout-minutes: 60
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Package Dependencies
run: >
sudo apt install build-essential cmake
clang gcc g++ lcov make nasm libxrandr-dev
libxinerama-dev libxcursor-dev libpulse-dev
libxi-dev zip ninja-build
run: |
sudo apt update
sudo apt install build-essential cmake \
clang gcc g++ lcov make nasm libxrandr-dev \
libxinerama-dev libxcursor-dev libpulse-dev \
libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev
- name: Setup Buildcache
uses: mikehardy/buildcache-action@v1.3.0
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.13
with:
cache_key: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
variant: sccache
key: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
restore-keys: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
max-size: 1000M
- name: CMake Generation
env:
@@ -45,19 +46,28 @@ jobs:
CXX: clang++
run: |
cmake -B build --preset=${{ inputs.cmakePreset }} \
-DCMAKE_C_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache \
-DCMAKE_CXX_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build Project
run: cmake --build build -j$((`nproc`+1))
run: cmake --build build --parallel $((`nproc`))
- name: Run Tests
env:
GTEST_OUTPUT: "xml:opengoal-test-report.xml"
run: ./test.sh
- name: Prepare artifacts
if: ${{ inputs.uploadArtifacts }}
run: |
strip ./build/goalc/goalc
strip ./build/decompiler/extractor
strip ./build/game/gk
strip ./build/lsp/lsp
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: ${{ inputs.uploadArtifacts }}
with:
name: opengoal-linux-${{ inputs.cachePrefix }}
if-no-files-found: error
+25 -33
View File
@@ -14,30 +14,32 @@ jobs:
build:
name: GCC
runs-on: ubuntu-20.04
timeout-minutes: 45
env: # overrides: https://github.com/mbitsnbites/buildcache/blob/master/doc/configuration.md
BUILDCACHE_MAX_CACHE_SIZE: 1000000000 # 1gb
BUILDCACHE_COMPRESS_FORMAT: ZSTD
BUILDCACHE_COMPRESS_LEVEL: 19
BUILDCACHE_DIRECT_MODE: true
BUILDCACHE_LOG_FILE: ${{ github.workspace }}/buildcache.log
timeout-minutes: 60
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Package Dependencies
run: >
sudo apt install build-essential cmake
clang gcc g++ lcov make nasm libxrandr-dev
libxinerama-dev libxcursor-dev libpulse-dev
libxi-dev zip ninja-build
run: |
sudo apt update
sudo apt install build-essential cmake \
clang gcc-10 g++-10 lcov make nasm libxrandr-dev \
libxinerama-dev libxcursor-dev libpulse-dev \
libxi-dev zip ninja-build libgl1-mesa-dev libssl-dev
- name: Setup Buildcache
uses: mikehardy/[email protected]
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100
sudo update-alternatives --set gcc /usr/bin/gcc-10
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 100
sudo update-alternatives --set g++ /usr/bin/g++-10
- name: Setup sccache
uses: hendrikmuhs/[email protected]
with:
cache_key: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
variant: sccache
key: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
restore-keys: linux-ubuntu-20.04-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
max-size: 1000M
- name: CMake Generation
env:
@@ -45,22 +47,12 @@ jobs:
CXX: g++
run: |
cmake -B build --preset=${{ inputs.cmakePreset }} \
-DCODE_COVERAGE=ON \
-DCMAKE_C_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache \
-DCMAKE_CXX_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache
-DCODE_COVERAGE=OFF \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build Project
run: cmake --build build -j$((`nproc`+1)) -- -w dupbuild=warn
run: cmake --build build --parallel $((`nproc`)) -- -w dupbuild=warn
- name: Run Tests - With Coverage
working-directory: ./build
env:
GTEST_OUTPUT: "xml:opengoal-test-report.xml"
run: ninja goalc-test_coverage -w dupbuild=warn
- name: Submit Coverage Report to Codacy
uses: codacy/codacy-coverage-reporter-action@v1
continue-on-error: true
with:
project-token: ${{ secrets.CODACY_PROJECT_KEY }}
coverage-reports: ./build/goalc-test_coverage.info
- name: Run Tests
run: ./test.sh
+61
View File
@@ -0,0 +1,61 @@
name: MacOS Build
on:
workflow_call:
inputs:
cmakePreset:
required: true
type: string
cachePrefix:
required: true
type: string
jobs:
build:
name: ARM
runs-on: macos-12
timeout-minutes: 120
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up ARM64 environment
run: sudo softwareupdate --install-rosetta --agree-to-license
- name: Install Package Dependencies
run: arch -arm64 brew install cmake ninja
- name: Setup sccache
uses: hendrikmuhs/[email protected]
with:
variant: sccache
key: macos-12-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
restore-keys: macos-12-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
max-size: 1000M
- name: CMake Generation
env:
CC: clang
CXX: clang++
run: |
cmake -B build --preset=${{ inputs.cmakePreset }} \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build Project
run: cmake --build build --parallel $((`sysctl -n hw.logicalcpu`))
- name: Run Tests
run: ./test.sh
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: opengoal-macos-${{ inputs.cachePrefix }}
if-no-files-found: error
path: |
./build/goalc/goalc
./build/decompiler/extractor
./build/game/gk
./build/lsp/lsp
+71
View File
@@ -0,0 +1,71 @@
name: MacOS Build
on:
workflow_call:
inputs:
cmakePreset:
required: true
type: string
cachePrefix:
required: true
type: string
uploadArtifacts:
required: false
type: boolean
default: false
jobs:
build:
name: Intel
runs-on: macos-12
timeout-minutes: 120
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Install Package Dependencies
run: brew install cmake nasm ninja
- name: Setup sccache
uses: hendrikmuhs/[email protected]
with:
variant: sccache
key: macos-12-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
restore-keys: macos-12-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
max-size: 1000M
- name: CMake Generation
env:
CC: clang
CXX: clang++
run: |
cmake -B build --preset=${{ inputs.cmakePreset }} \
-DCMAKE_C_COMPILER_LAUNCHER=sccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache
- name: Build Project
run: cmake --build build --parallel $((`sysctl -n hw.logicalcpu`))
- name: Run Tests
run: ./test.sh
- name: Prepare artifacts
if: ${{ inputs.uploadArtifacts }}
run: |
strip ./build/goalc/goalc
strip ./build/decompiler/extractor
strip ./build/game/gk
strip ./build/lsp/lsp
- name: Upload artifact
uses: actions/upload-artifact@v4
if: ${{ inputs.uploadArtifacts }}
with:
name: opengoal-macos-${{ inputs.cachePrefix }}
if-no-files-found: error
path: |
./build/goalc/goalc
./build/decompiler/extractor
./build/game/gk
./build/lsp/lsp
+27 -11
View File
@@ -13,6 +13,7 @@ jobs:
with:
cmakePreset: "Release-windows-clang-static"
cachePrefix: "static"
uploadArtifacts: true
secrets: inherit
# Linux
@@ -22,6 +23,17 @@ jobs:
with:
cmakePreset: "Release-linux-clang-static"
cachePrefix: "static"
uploadArtifacts: true
secrets: inherit
# macOS
build_macos_intel:
name: "🍎 MacOS"
uses: ./.github/workflows/macos-build.yaml
with:
cmakePreset: "Release-macos-clang-static"
cachePrefix: "static"
uploadArtifacts: true
secrets: inherit
# Upload the Artifacts
@@ -30,15 +42,16 @@ jobs:
needs:
- build_windows_clang
- build_linux_clang
- build_macos_intel
name: "Upload Artifacts"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Prepare Artifact Folder
run: mkdir -p ./ci-artifacts/final
- uses: actions/download-artifact@v3
- uses: actions/download-artifact@v4
name: Download all Artifacts
with:
path: ./ci-artifacts/
@@ -49,12 +62,11 @@ jobs:
- name: Prepare Linux Release Assets
run: |
mkdir -p ./ci-artifacts/linux
./.github/scripts/releases/extract_build_linux.sh ./ci-artifacts/linux ./ci-artifacts/opengoal-linux-static ./
./.github/scripts/releases/extract_build_unix.sh ./ci-artifacts/linux ./ci-artifacts/opengoal-linux-static ./
pushd ci-artifacts/linux
TAG_VAL=$(echo ${{ github.REF }} | awk -F'refs/tags/' '{print $2}')
tar czf ../final/opengoal-linux-${TAG_VAL}.tar.gz .
popd
strip ./ci-artifacts/opengoal-linux-static/lsp/lsp
chmod +x ./ci-artifacts/opengoal-linux-static/lsp/lsp
cp ./ci-artifacts/opengoal-linux-static/lsp/lsp ./ci-artifacts/final/opengoal-lsp-linux-${TAG_VAL}.bin
@@ -66,6 +78,17 @@ jobs:
7z a -tzip ./ci-artifacts/final/opengoal-windows-${TAG_VAL}.zip ./ci-artifacts/windows/*
cp ./ci-artifacts/opengoal-windows-static/lsp.exe ./ci-artifacts/final/opengoal-lsp-windows-${TAG_VAL}.exe
- name: Prepare macOS Build Assets
run: |
mkdir -p ./ci-artifacts/macos
./.github/scripts/releases/extract_build_unix.sh ./ci-artifacts/macos ./ci-artifacts/opengoal-macos-static ./
pushd ci-artifacts/macos
TAG_VAL=$(echo ${{ github.REF }} | awk -F'refs/tags/' '{print $2}')
tar czf ../final/opengoal-macos-intel-${TAG_VAL}.tar.gz .
popd
chmod +x ./ci-artifacts/opengoal-macos-static/lsp/lsp
cp ./ci-artifacts/opengoal-macos-static/lsp/lsp ./ci-artifacts/final/opengoal-lsp-macos-intel-${TAG_VAL}.bin
- name: Upload Assets
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -79,10 +102,3 @@ jobs:
run: |
TAG_VAL=$(echo ${{ github.REF }} | awk -F'refs/tags/' '{print $2}')
gh release edit ${TAG_VAL} --draft=false --repo open-goal/jak-project
- name: Consume Release in the Launcher
uses: peter-evans/repository-dispatch@v2
with:
token: ${{ secrets.BOT_PAT }}
repository: 'open-goal/launcher'
event-type: releaseLauncher
+12 -7
View File
@@ -3,13 +3,14 @@ name: Update Controller Database
on:
schedule:
- cron: "0 16 * * 1" # every monday @ 12pm EST - https://crontab.guru/#0_16_*_*_1
workflow_dispatch: {}
jobs:
update-controller-db:
if: github.repository == 'open-goal/jak-project'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
token: ${{ secrets.BOT_PAT }}
@@ -17,10 +18,14 @@ jobs:
run: |
wget -O ./game/assets/sdl_controller_db.txt https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt
- name: commit version bump
uses: EndBug/add-and-commit@v9
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
default_author: github_actor
author_name: 'OpenGOALBot'
author_email: '[email protected]'
message: "Updating Controller Database"
token: ${{ secrets.BOT_PAT }}
author: 'OpenGOALBot <[email protected]>'
committer: 'OpenGOALBot <OpenGOALBot@users.noreply.github.com>'
branch: 'bot/update-controller-db'
base: "master"
body: "Updating Controller Database"
commit-message: "ci: updated controller database"
title: "CI: Periodic Controller Database Update"
+32 -18
View File
@@ -9,51 +9,65 @@ on:
cachePrefix:
required: true
type: string
uploadArtifacts:
required: false
type: boolean
default: false
jobs:
build:
name: Clang
runs-on: windows-2022
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
timeout-minutes: 45
env: # overrides: https://github.com/mbitsnbites/buildcache/blob/master/doc/configuration.md
BUILDCACHE_MAX_CACHE_SIZE: 1000000000 # 1gb
BUILDCACHE_COMPRESS_FORMAT: ZSTD
BUILDCACHE_COMPRESS_LEVEL: 19
BUILDCACHE_DIRECT_MODE: true
BUILDCACHE_LOG_FILE: ${{ github.workspace }}/buildcache.log
timeout-minutes: 60
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install NASM
run: choco install ${{ github.workspace }}/third-party/nasm/nasm.2.15.05.nupkg
# TODO - Simplify this with just the first command once choco 2.0 rolls out everywhere
run: |
$chocoVersion = choco --version
if ($chocoVersion.StartsWith("2.")) {
choco install nasm --source="${{ github.workspace }}/third-party/nasm"
} else {
choco install ${{ github.workspace }}/third-party/nasm/old/nasm.2.15.05.nupkg
}
- name: Setup Buildcache
uses: mikehardy/buildcache-action@v1.3.0
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.13
with:
cache_key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
variant: sccache
key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
restore-keys: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
max-size: 1000M
- uses: ilammy/msvc-dev-cmd@v1
# https://github.com/actions/runner-images/issues/5459
# Causes binaries to be built differently, get rid of this garbage
- name: Remove Strawberry Perl from PATH
run: |
$env:PATH = $env:PATH -replace "C:\\Strawberry\\c\\bin;", ""
"PATH=$env:PATH" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: CMake Generation
shell: cmd
run: cmake -B build --preset=${{ inputs.cmakePreset }} -DCMAKE_C_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache.exe -DCMAKE_CXX_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache.exe .
run: cmake -B build --preset=${{ inputs.cmakePreset }} -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache .
- name: Build Project
shell: cmd
run: cmake --build build -j 2
run: cmake --build build --parallel %NUMBER_OF_PROCESSORS%
- name: Run Tests
timeout-minutes: 10
env:
GTEST_OUTPUT: "xml:opengoal-test-report.xml"
run: ./build/bin/goalc-test.exe --gtest_color=yes --gtest_brief=1 --gtest_filter="-*MANUAL_TEST*"
run: ./build/bin/goalc-test.exe --gtest_color=yes --gtest_brief=0 --gtest_filter="-*MANUAL_TEST*"
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: ${{ inputs.uploadArtifacts }}
with:
name: opengoal-windows-${{ inputs.cachePrefix }}
if-no-files-found: error
+25 -16
View File
@@ -14,43 +14,52 @@ jobs:
build:
name: MSVC
runs-on: windows-2022
timeout-minutes: 45
env: # overrides: https://github.com/mbitsnbites/buildcache/blob/master/doc/configuration.md
BUILDCACHE_MAX_CACHE_SIZE: 1000000000 # 1gb
BUILDCACHE_COMPRESS_FORMAT: ZSTD
BUILDCACHE_COMPRESS_LEVEL: 19
BUILDCACHE_DIRECT_MODE: true
BUILDCACHE_LOG_FILE: ${{ github.workspace }}/buildcache.log
timeout-minutes: 60
steps:
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install NASM
run: choco install ${{ github.workspace }}/third-party/nasm/nasm.2.15.05.nupkg
# TODO - Simplify this with just the first command once choco 2.0 rolls out everywhere
run: |
$chocoVersion = choco --version
if ($chocoVersion.StartsWith("2.")) {
choco install nasm --source="${{ github.workspace }}/third-party/nasm"
} else {
choco install ${{ github.workspace }}/third-party/nasm/old/nasm.2.15.05.nupkg
}
- name: Setup Buildcache
uses: mikehardy/buildcache-action@v1.3.0
- name: Setup sccache
uses: hendrikmuhs/ccache-action@v1.2.13
with:
cache_key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
variant: sccache
key: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}-${{ github.sha }}
restore-keys: windows-2022-${{ inputs.cachePrefix }}-${{ inputs.cmakePreset }}
max-size: 1000M
- uses: ilammy/msvc-dev-cmd@v1
# Fixes an issue with the image causing builds to fail - https://github.com/actions/runner-images/issues/8598
- name: Remove Strawberry Perl from PATH
run: |
$env:PATH = $env:PATH -replace "C:\\Strawberry\\c\\bin;", ""
"PATH=$env:PATH" | Out-File -FilePath $env:GITHUB_ENV -Append
- name: CMake Generation - MSVC
shell: cmd
run: cmake -B build --preset=${{ inputs.cmakePreset }} -DCMAKE_C_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache.exe -DCMAKE_CXX_COMPILER_LAUNCHER=${{ github.workspace }}/buildcache/bin/buildcache.exe .
run: cmake -B build --preset=${{ inputs.cmakePreset }} -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache .
- name: Build Project
shell: cmd
run: |
set CL=/MP
cmake --build build -j 2
cmake --build build --parallel %NUMBER_OF_PROCESSORS%
- name: Run Tests
timeout-minutes: 10
env:
GTEST_OUTPUT: "xml:opengoal-test-report.xml"
run: |
./build/bin/goalc-test.exe --gtest_color=yes --gtest_brief=1 --gtest_filter="-*MANUAL_TEST*"
./build/bin/goalc-test.exe --gtest_color=yes --gtest_brief=0 --gtest_filter="-*MANUAL_TEST*"
+36 -6
View File
@@ -1,13 +1,22 @@
# logs
/log
prof.json
# for CMake
/Testing
# for clion
cmake-build-debug/*
cmake-build-debug--o0/*
.idea/*
build/*
decompiler_out/*
decompiler_out2/*
/decompiler_out*
logs/*
profile_data/*
# for vscode/clangd
.cache/*
.DS_Store
# wsl apparently builds to here?
linux-default/
@@ -27,12 +36,15 @@ savestate-out/
savestate_out/
failures/
ee-results*.json
search-results.json
.env
/search-results.json
# graphics debug
debug_out/*
gfx_dumps/*
screenshots/*
debug_out/
glb_out/
gfx_dumps/
screenshots/
# game stuff
game_config/*
@@ -42,10 +54,28 @@ imgui.ini
node_modules/
# texture replacements
texture_replacements/*
custom_assets/jak1/texture_replacements/*
custom_assets/jak2/texture_replacements/*
custom_assets/jak3/texture_replacements/*
# generated cmake files
svnrev.h
common/versions/revision.h
ci-artifacts/
out/build/
__pycache__/
# sqlite stuff
*.db
*.db-journal
# backup files from OpenMaya
*.bak
# docs
/jak1-*.json
/jak2-*.json
/TODO.md
unifont-15.0.03.ttf
*.diff
goalc-report.html
+11
View File
@@ -0,0 +1,11 @@
{
"endOfLine": "auto",
"overrides": [
{
"files": ["**/*.jsonc"],
"options": {
"parser": "json"
}
}
]
}
+280 -40
View File
@@ -7,42 +7,58 @@
"project": "CMakeLists.txt",
"projectTarget": "goalc-test.exe (bin\\goalc-test.exe)",
"name": "Tests - Unit-Tests - Summary",
"args": ["--gtest_brief=1"]
"args": [
"--gtest_brief=1"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc-test.exe (bin\\goalc-test.exe)",
"name": "Tests - Unit-Tests - Verbose",
"args": ["--gtest_brief=0"]
"args": [
"--gtest_brief=0"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc-test.exe (bin\\goalc-test.exe)",
"name": "Tests - Draft Tests - Verbose",
"args": ["--gtest_brief=0", "--gtest_filter=\"*Draft*\""]
"args": [
"--gtest_brief=0",
"--gtest_filter=\"*Draft*\""
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc-test.exe (bin\\goalc-test.exe)",
"name": "Tests - TypeConsistency - Verbose",
"args": ["--gtest_brief=0", "--gtest_filter=\"*TypeConsistency*\""]
"args": [
"--gtest_brief=0",
"--gtest_filter=\"*TypeConsistency*\""
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc-test.exe (bin\\goalc-test.exe)",
"name": "Tests - TypeConsistency - Jak 2 - Verbose",
"args": ["--gtest_brief=0", "--gtest_filter=\"*Jak2TypeConsistency*\""]
"args": [
"--gtest_brief=0",
"--gtest_filter=\"*Jak2TypeConsistency*\""
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc-test.exe (bin\\goalc-test.exe)",
"name": "Tests - WithGameTests - Verbose",
"args": ["--gtest_brief=0", "--gtest_filter=\"*WithGameTests*\""]
"args": [
"--gtest_brief=0",
"--gtest_filter=\"*WithGameTests*\""
]
},
{
"type": "default",
@@ -59,51 +75,164 @@
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Runtime (no kernel)",
"args": ["-fakeiso", "-debug", "-nokernel", "-v", "-nodisplay"]
"projectTarget": "offline-test.exe (bin\\offline-test.exe)",
"name": "Tests - Offline Tests - Jak 2",
"args": [
"--iso_data_path",
"${workspaceRoot}/iso_data/jak2",
"--game",
"jak2"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "offline-test.exe (bin\\offline-test.exe)",
"name": "Tests - Offline Tests - Jak 3",
"args": [
"--iso_data_path",
"${workspaceRoot}/iso_data/jak3",
"--game",
"jak3"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "offline-test.exe (bin\\offline-test.exe)",
"name": "Tests - Offline Tests - Jak 1 - Specific File",
"args": [
"--iso_data_path",
"${workspaceRoot}/iso_data/jak1",
"--game",
"jak1",
"--file",
"euler-h"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "offline-test.exe (bin\\offline-test.exe)",
"name": "Tests - Offline Tests - Jak 2 - Specific File",
"args": [
"--iso_data_path",
"${workspaceRoot}/iso_data/jak2",
"--game",
"jak2",
"--file",
"oracle-texture"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Runtime (with kernel)",
"args": ["-fakeiso", "-debug", "-v"]
"name": "Game - Jak 1 - Runtime",
"args": [
"-v",
"--game",
"jak1",
"--",
"-fakeiso",
"-debug"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Runtime (boot)",
"args": ["-boot", "-fakeiso", "-debug", "-v"]
"name": "Game - Jak 1 - Runtime (boot)",
"args": [
"-v",
"--portable",
"--game",
"jak1",
"--",
"-boot",
"-fakeiso",
"-debug"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Runtime (boot no debug)",
"args": ["-boot", "-fakeiso", "-v"]
"name": "Game - Jak 2 - Runtime (no boot)",
"args": [
"-v",
"--game",
"jak2",
"--",
"-fakeiso",
"-debug"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Jak 2 - Runtime (boot)",
"args": [
"-v",
"--game",
"jak2",
"--",
"-boot",
"-fakeiso",
"-debug"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Jak 2 - Runtime (release)",
"args": [
"-v",
"--game",
"jak2",
"--",
"-boot",
"-fakeiso"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "gk.exe (bin\\gk.exe)",
"name": "Game - Jak 3 - Runtime (boot)",
"args": [
"-v",
"--game",
"jak3",
"--",
"-boot",
"-fakeiso",
"-debug"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc.exe (bin\\goalc.exe)",
"name": "REPL",
"args": ["--user-auto"]
"name": "REPL - Jak 1",
"args": [
"--user-auto",
"--game",
"jak1"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc.exe (bin\\goalc.exe)",
"name": "REPL - Jak 2",
"args": ["--user-auto", "--game", "jak2"]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc.exe (bin\\goalc.exe)",
"name": "REPL - Auto Listen",
"args": ["--user-auto", "--auto-lt"]
"args": [
"--user-auto",
"--game",
"jak2"
]
},
{
"type": "default",
@@ -111,9 +240,24 @@
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
"name": "Decompiler - Jak 1",
"args": [
"${workspaceRoot}/decompiler/config/jak1_ntsc_black_label.jsonc",
"${workspaceRoot}/decompiler/config/jak1/jak1_config.jsonc",
"${workspaceRoot}/iso_data",
"${workspaceRoot}/decompiler_out"
"${workspaceRoot}/decompiler_out",
"--version",
"ntsc_v1"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
"name": "Decompiler - Jak 1 NTSC-U v2",
"args": [
"${workspaceRoot}/decompiler/config/jak1/jak1_config.jsonc",
"${workspaceRoot}/iso_data",
"${workspaceRoot}/decompiler_out",
"--version",
"ntsc_v2"
]
},
{
@@ -122,9 +266,11 @@
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
"name": "Decompiler - Jak 1 PAL",
"args": [
"${workspaceRoot}/decompiler/config/jak1_pal.jsonc",
"${workspaceRoot}/decompiler/config/jak1/jak1_config.jsonc",
"${workspaceRoot}/iso_data",
"${workspaceRoot}/decompiler_out"
"${workspaceRoot}/decompiler_out",
"--version",
"pal"
]
},
{
@@ -133,9 +279,52 @@
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
"name": "Decompiler - Jak 2",
"args": [
"${workspaceRoot}/decompiler/config/jak2_ntsc_v1.jsonc",
"${workspaceRoot}/decompiler/config/jak2/jak2_config.jsonc",
"${workspaceRoot}/iso_data",
"${workspaceRoot}/decompiler_out"
"${workspaceRoot}/decompiler_out",
"--version",
"ntsc_v1"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
"name": "Decompiler - Jak 2 - Extract",
"args": [
"${workspaceRoot}/decompiler/config/jak2/jak2_config.jsonc",
"${workspaceRoot}/iso_data",
"${workspaceRoot}/decompiler_out",
"--version",
"ntsc_v1",
"--config-override \"{\\\"decompile_code\\\": false, \\\"levels_extract\\\": true, \\\"allowed_objects\\\": []}\""
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
"name": "Decompiler - Jak 3",
"args": [
"${workspaceRoot}/decompiler/config/jak3/jak3_config.jsonc",
"${workspaceRoot}/iso_data",
"${workspaceRoot}/decompiler_out",
"--version",
"ntsc_v1"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "decompiler.exe (bin\\decompiler.exe)",
"name": "Decompiler - Jak 3 - Extract",
"args": [
"${workspaceRoot}/decompiler/config/jak3/jak3_config.jsonc",
"${workspaceRoot}/iso_data",
"${workspaceRoot}/decompiler_out",
"--version",
"ntsc_v1",
"--config-override \"{\\\"decompile_code\\\": false, \\\"levels_extract\\\": true, \\\"allowed_objects\\\": []}\""
]
},
{
@@ -143,14 +332,26 @@
"project": "CMakeLists.txt",
"projectTarget": "memory_dump_tool.exe (bin\\memory_dump_tool.exe)",
"name": "Tools - EE Memory Analyze - Jak 1",
"args": ["\"${workspaceRoot}/eeMemory.bin\"", "--output-path", "\"${workspaceRoot}\"", "--game", "jak1"]
"args": [
"\"${workspaceRoot}/eeMemory.bin\"",
"--output-path",
"\"${workspaceRoot}\"",
"--game",
"jak1"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "memory_dump_tool.exe (bin\\memory_dump_tool.exe)",
"name": "Tools - EE Memory Analyze - Jak 2",
"args": ["\"${workspaceRoot}/eeMemory.bin\"", "--output-path", "\"${workspaceRoot}\"", "--game", "jak2"]
"args": [
"\"${workspaceRoot}/eeMemory.bin\"",
"--output-path",
"\"${workspaceRoot}\"",
"--game",
"jak2"
]
},
{
"type": "default",
@@ -167,14 +368,53 @@
"project": "CMakeLists.txt",
"projectTarget": "extractor.exe (bin\\extractor.exe)",
"name": "Tools - Extractor - Full",
"args": ["\"E:\\ISOs\\Jak\\Jak 1.iso\""]
"args": [
"\"E:\\ISOs\\Jak\\Jak 1.iso\""
]
},
{
"type" : "default",
"project" : "CMakeLists.txt",
"projectTarget" : "lsp.exe (bin\\lsp.exe)",
"name" : "Run - LSP",
"args" : []
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "lsp.exe (bin\\lsp.exe)",
"name": "Tools - LSP",
"args": []
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "type_searcher.exe (bin\\type_searcher.exe)",
"name": "Tools - Type Searcher",
"args": [
"--game",
"jak2",
"--output-path",
"./search-results.json",
"--size",
255,
"--fields",
"[{\\\"type\\\":\\\"quaternion\\\",\\\"offset\\\":48}]"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "formatter.exe (bin\\formatter.exe)",
"name": "Tools - Formatter - Inplace",
"args": [
"--write",
"--file",
"C:\\Users\\xtvas\\Repositories\\opengoal\\jak-project\\goal_src\\jak1\\engine\\camera\\cam-states.gc"
]
},
{
"type": "default",
"project": "CMakeLists.txt",
"projectTarget": "goalc-test.exe (bin\\goalc-test.exe)",
"name": "Tests - Formatter",
"args": [
"--gtest_brief=0",
"--gtest_filter=\"*FormatterTests*\""
]
}
]
}
}
+9
View File
@@ -0,0 +1,9 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": ["opengoal.opengoal"],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []
}
+3 -3
View File
@@ -5,13 +5,13 @@
"version": "0.2.0",
"configurations": [
{
"name": "Python",
"name": "run python script",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/scripts/gsrc/update-from-decomp.py",
"program": "${workspaceFolder}/scripts/gsrc/compare-compilation-outputs.py",
"console": "integratedTerminal",
"cwd": "${workspaceFolder}",
"args": ["--game", "jak2", "--file", "sky-data"]
"args": []
},
]
}
+26
View File
@@ -0,0 +1,26 @@
{
"og:ignore-from-loc": {
"scope": "opengoal",
"prefix": ["og:ignore-from-loc"],
"body": [";; og:ignore-from-loc"],
"description": "Marks the file to be excluded from the LoC count"
},
"og:ignore-errors": {
"scope": "opengoal",
"prefix": ["og:ignore-errors"],
"body": [";; og:ignore-errors"],
"description": "Ignore lines beginning with ';; ERROR:' or ';; WARN:' when copying decompiled code into it"
},
"og:ignore-form": {
"scope": "opengoal",
"prefix": ["og:ignore-form"],
"body": [";; og:ignore-form:${1:substr}"],
"description": "If the provided substr is found in the starting line of a form, the entire form will be omitted when copying decompiled code into the file"
},
"og:preserve-this": {
"scope": "opengoal",
"prefix": ["og:preserve-this"],
"body": [";; og:preserve-this"],
"description": "When updating GOAL source files from decomp, CI will pick up if this comment is deleted in the diff. Use this to keep track of manually patched sections of code."
},
}
+10 -2
View File
@@ -1,4 +1,12 @@
{
"terminal.integrated.scrollback": 32000,
"python.formatting.provider": "black",
"[opengoal]": {
"editor.quickSuggestions": {
"other": true,
"comments": true,
"strings": true
},
"editor.wordBasedSuggestions": "matchingDocuments",
"editor.snippetSuggestions": "top"
},
"cmake.configureOnOpen": false
}
+119 -39
View File
@@ -1,7 +1,7 @@
# Top Level CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
project(jak)
include(CTest)
@@ -18,14 +18,20 @@ option(STATICALLY_LINK "Build for release purposes (statically link everything)"
message(STATUS "Statically Link? ${STATICALLY_LINK}")
if(STATICALLY_LINK)
set(BUILD_SHARED_LIBS OFF)
set(BUILD_STATIC_LIBS ON)
else()
set(BUILD_SHARED_LIBS ON)
set(BUILD_STATIC_LIBS OFF)
endif()
# For clangd
if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json" )
configure_file(
"${CMAKE_CURRENT_BINARY_DIR}/compile_commands.json"
"${PROJECT_SOURCE_DIR}/build/compile_commands.json")
endif()
# Setup compiler flags
# TODO - consider moving most of the configuration into presets
# - https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html
# - requires atleast CMake 3.19
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
message(STATUS "Clang Detected - Setting Defaults")
set(CMAKE_CXX_FLAGS
@@ -33,18 +39,17 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
-fcxx-exceptions \
-fexceptions \
-fdiagnostics-color=always \
-std=c++17 \
-mavx \
-Wall \
-Wno-c++11-narrowing \
-Wno-c++98-compat \
-O3")
-O3 \
-D_CRT_SECURE_NO_WARNINGS")
# Increase stack size for windows, who's default is too low
if(WIN32)
# Increase the reserved stack size for all threads to 16MB
# Note: this is only _reserved_ memory, not necessarily _committed_ memory
# TODO - test with add_link_options instead
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LDFLAGS} -Xlinker /STACK:16000000")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb -g -Wextra")
@@ -56,7 +61,6 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
endif()
if(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
# TODO - test with add_link_options instead
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LDFLAGS} -Xlinker /debug")
endif()
@@ -81,7 +85,6 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-Wdisabled-optimization \
-Wformat \
-Wextra \
-Wmissing-include-dirs \
-Woverloaded-virtual \
-Wredundant-decls \
-Wshadow \
@@ -94,6 +97,38 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
set(THIRDPARTY_IGNORED_WARNINGS "-w")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
message(STATUS "AppleClang detected - Setting Defaults")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} \
-Wall \
-Winit-self \
-ggdb \
-Wextra \
-Wno-cast-align \
-Wcast-qual \
-Wdisabled-optimization \
-Wformat \
-Wextra \
-Woverloaded-virtual \
-Wredundant-decls \
-Wshadow \
-Wsign-promo \
-fdiagnostics-color=always"
)
# pin to AVX for macOS, hopefully all macOS runners have atleast this architecture
# technically speaking, SSE4 is the cutoff for Apple Silicon so...only a matter of time!
if(NOT CMAKE_CXX_COMPILER_TARGET STREQUAL "arm64-apple-darwin")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx")
endif()
# additional c++ flags for release mode for our projects
if(CMAKE_BUILD_TYPE MATCHES "Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif()
set(THIRDPARTY_IGNORED_WARNINGS "-w")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-stack_size -Wl,0x20000000")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
message(STATUS "MSVC detected - Setting Defaults")
@@ -122,8 +157,6 @@ if(WIN32)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION 7.1.7600.0.30514) # win7.1, supports xp
message("Windows SDK version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
endif()
# Code Coverage
@@ -135,17 +168,67 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CODE_COVERAGE)
message(STATUS "Code Coverage build is enabled!")
endif()
function(build_third_party_lib dir_name target_name)
add_subdirectory(third-party/${dir_name} EXCLUDE_FROM_ALL)
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
# For Microsoft Visual C++ Compiler (MSVC)
target_compile_options(${target_name} PRIVATE /w)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# For GNU Compiler Collection (GCC) or Clang
target_compile_options(${target_name} PRIVATE -w)
endif()
endfunction()
# Dependencies and Libraries
# includes relative to top level jak-project folder
include_directories(./)
# build templating engine library
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${THIRDPARTY_IGNORED_WARNINGS} ")
include_directories(SYSTEM third-party/inja)
# libcurl for HTTP requests
# 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)
set(CURL_ZLIB OFF)
if(WIN32)
set(CURL_USE_SCHANNEL ON) # native Windows SSL support
elseif(APPLE)
set(CURL_USE_SECTRANSP ON) # native macOS SSL support
else()
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
endif()
include_directories(third-party/curl/include)
if(STATICALLY_LINK)
build_third_party_lib(curl libcurl_static)
else()
build_third_party_lib(curl libcurl_shared)
endif()
# build repl library
add_subdirectory(third-party/replxx EXCLUDE_FROM_ALL)
string(REPLACE " ${THIRDPARTY_IGNORED_WARNINGS} " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
build_third_party_lib(replxx replxx)
# SQLite - Jak 2/3's built in editor
add_definitions(-DHAVE_USLEEP=1)
add_definitions(-DSQLITE_THREADSAFE=1)
add_definitions(-DSQLITE_ENABLE_JSON1)
add_definitions(-DSQLITE_ENABLE_RTREE)
build_third_party_lib(sqlite3 sqlite3)
# build tree-sitter parser
include_directories(third-party/tree-sitter/tree-sitter/lib/include)
build_third_party_lib(tree-sitter tree-sitter)
# native OS dialogs for error messages
build_third_party_lib(libtinyfiledialogs libtinyfiledialogs)
# build format library
include_directories(third-party/fmt/include)
build_third_party_lib(fmt fmt)
# build common library
add_subdirectory(common)
@@ -153,24 +236,28 @@ add_subdirectory(common)
# build decompiler
add_subdirectory(decompiler)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${THIRDPARTY_IGNORED_WARNINGS} ")
add_subdirectory(third-party/cubeb EXCLUDE_FROM_ALL)
# cubeb - audio
build_third_party_lib(cubeb cubeb)
# build LSP
add_subdirectory(lsp)
# build libco
add_subdirectory(third-party/libco)
# build libco and zstd
build_third_party_lib(libco libco)
build_third_party_lib(zstd libzstd_static)
# build glfw library
add_subdirectory(third-party/glfw EXCLUDE_FROM_ALL)
add_subdirectory(third-party/zstd EXCLUDE_FROM_ALL)
# build SDL
include(SDLOptions)
if(STATICALLY_LINK)
build_third_party_lib(SDL SDL2-static)
else()
build_third_party_lib(SDL SDL2)
endif()
# build imgui
include_directories(third-party/glad/include)
include_directories(third-party/glfw/include)
add_subdirectory(third-party/imgui EXCLUDE_FROM_ALL)
string(REPLACE " ${THIRDPARTY_IGNORED_WARNINGS} " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
include_directories(third-party/SDL/include)
build_third_party_lib(imgui imgui)
# build the game code in C++
add_subdirectory(game)
@@ -186,28 +273,22 @@ if(WIN32)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${THIRDPARTY_IGNORED_WARNINGS} ")
add_subdirectory(third-party/googletest EXCLUDE_FROM_ALL)
build_third_party_lib(googletest gtest)
include(GoogleTest)
string(REPLACE " ${THIRDPARTY_IGNORED_WARNINGS} " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# build tests
include(test/CMakeLists.txt)
# build lzokay library
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${THIRDPARTY_IGNORED_WARNINGS} ")
add_subdirectory(third-party/lzokay EXCLUDE_FROM_ALL)
build_third_party_lib(lzokay lzokay)
# build format library
add_subdirectory(third-party/fmt EXCLUDE_FROM_ALL)
add_subdirectory(third-party/stb_image EXCLUDE_FROM_ALL)
add_subdirectory(third-party/tiny_gltf EXCLUDE_FROM_ALL)
add_subdirectory(third-party/xdelta3 EXCLUDE_FROM_ALL)
build_third_party_lib(stb_image stb_image)
build_third_party_lib(tiny_gltf tiny_gltf)
build_third_party_lib(xdelta3 xdelta3)
# discord rich presence
include_directories(third-party/discord-rpc/include)
add_subdirectory(third-party/discord-rpc EXCLUDE_FROM_ALL)
build_third_party_lib(discord-rpc discord-rpc)
# build zydis third party library for disassembling x86
# TODO - Once under CMake 3.13's policy CMP0077, override with `set()` instead
@@ -222,10 +303,9 @@ else()
option(ZYDIS_BUILD_SHARED_LIB "Zydis: Build shared library" ON)
endif()
add_subdirectory(third-party/zydis EXCLUDE_FROM_ALL)
build_third_party_lib(zydis Zydis)
# windows memory management lib
if(WIN32)
add_subdirectory(third-party/mman)
build_third_party_lib(mman mman)
endif()
string(REPLACE " ${THIRDPARTY_IGNORED_WARNINGS} " "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+59 -2
View File
@@ -14,7 +14,8 @@
"ASAN_BUILD": "OFF",
"STATICALLY_LINK": "OFF",
"ZYDIS_BUILD_SHARED_LIB": "ON",
"CODE_COVERAGE": "OFF"
"CODE_COVERAGE": "OFF",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
@@ -57,6 +58,26 @@
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install/${presetName}"
}
},
{
"name": "base-linux-debug",
"hidden": true,
"inherits": "base",
"binaryDir": "${sourceDir}/build/Release/bin",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install/${presetName}"
}
},
{
"name": "base-macos-release",
"hidden": true,
"inherits": "base",
"binaryDir": "${sourceDir}/build/Release/bin",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/build/install/${presetName}"
}
},
{
"name": "base-clang",
"hidden": true,
@@ -87,6 +108,16 @@
"description": "Build with Clang with Debug Symbols",
"inherits": ["base-windows-debug", "base-clang"]
},
{
"name": "Debug-windows-clang-static",
"displayName": "Windows Static Debug (clang)",
"description": "Build with Clang as Debug but statically linked",
"inherits": ["base-windows-debug", "base-clang"],
"cacheVariables": {
"STATICALLY_LINK": "true",
"ZYDIS_BUILD_SHARED_LIB": "OFF"
}
},
{
"name": "RelWithDebInfo-windows-clang",
"displayName": "Windows RelWithDebInfo (clang)",
@@ -127,13 +158,29 @@
"description": "Build with Clang as Release without Debug Symbols",
"inherits": ["base-linux-release", "base-clang"]
},
{
"name": "Release-macos-clang",
"displayName": "MacOS Release (clang)",
"description": "Build with Clang as Release without Debug Symbols",
"inherits": ["base-macos-release", "base-clang"]
},
{
"name": "Release-macos-clang-static",
"displayName": "MacOS Static Release (clang)",
"description": "Build with Clang as Release without Debug Symbols but statically linked",
"inherits": ["base-macos-release", "base-clang"],
"cacheVariables": {
"STATICALLY_LINK": "true",
"ZYDIS_BUILD_SHARED_LIB": "OFF"
}
},
{
"name": "Release-linux-clang-asan",
"displayName": "Linux Release (clang-asan)",
"description": "Build with Clang as Release without Debug Symbols and ASAN Fuzzing",
"inherits": ["base-linux-release", "base-clang"],
"cacheVariables": {
"ASAN_BUILD": "ON"
"ASAN_BUILD": "OFF"
}
},
{
@@ -146,6 +193,16 @@
"ZYDIS_BUILD_SHARED_LIB": "OFF"
}
},
{
"name": "Debug-linux-clang-static",
"displayName": "Linux Static Release (clang)",
"description": "Build with Clang as Release without Debug Symbols but statically linked",
"inherits": ["base-linux-debug", "base-clang"],
"cacheVariables": {
"STATICALLY_LINK": "true",
"ZYDIS_BUILD_SHARED_LIB": "OFF"
}
},
{
"name": "Release-linux-gcc",
"displayName": "Linux Release (gcc)",
+87 -29
View File
@@ -4,15 +4,26 @@
<p align="center">
<a href="https://opengoal.dev/docs/intro" rel="nofollow"><img src="https://img.shields.io/badge/Documentation-Here-informational" alt="Documentation Badge" style="max-width:100%;"></a>
<a target="_blank" rel="noopener noreferrer" href="https://github.com/open-goal/jak-project/workflows/Build/badge.svg"><img src="https://github.com/open-goal/jak-project/workflows/Build/badge.svg" alt="Linux and Windows Build" style="max-width:100%;"></a>
<a href="https://www.codacy.com/gh/open-goal/jak-project/dashboard?utm_source=github.com&utm_medium=referral&utm_content=open-goal/jak-project&utm_campaign=Badge_Coverage" rel="nofollow"><img src="https://app.codacy.com/project/badge/Coverage/29316d04a1644aa390c33be07289f3f5" alt="Codacy Badge" style="max-width:100%;"></a>
<a title="Crowdin" target="_blank" href="https://crowdin.com/project/opengoal"><img src="https://badges.crowdin.net/opengoal/localized.svg"></a>
<a target="_blank" rel="noopener noreferrer" href="https://github.com/open-goal/jak-project/actions/workflows/build-matrix.yaml"><img src="https://github.com/open-goal/jak-project/actions/workflows/build-matrix.yaml/badge.svg" alt="Linux and Windows Build" style="max-width:100%;"></a>
<a href="https://www.codacy.com/gh/open-goal/jak-project/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=open-goal/jak-project&amp;utm_campaign=Badge_Grade" rel="nofollow"><img src="https://app.codacy.com/project/badge/Grade/29316d04a1644aa390c33be07289f3f5" alt="Codacy Badge" style="max-width:100%;"></a>
<a href="https://discord.gg/VZbXMHXzWv"><img src="https://img.shields.io/discord/756287461377703987" alt="Discord"></a>
<a href="https://makeapullrequest.com"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square" alt=PRs Welcome></a>
</p>
- [Please read first](#please-read-first)
- [Quick Start](#quick-start)
## Please read first <!-- omit from toc -->
> [!IMPORTANT]
> Our repositories on GitHub are primarily for development of the project and tracking active issues. Most of the information you will find here pertains to setting up the project for development purposes and is not relevant to the end-user.
For a setup guide on how to install and play the game there is the following video that you can check out: https://youtu.be/K84UUMnkJc4
For questions or additional information pertaining to the project, we have a Discord for discussion here: https://discord.gg/VZbXMHXzWv
Additionally, you can find further documentation and answers to **frequently asked questions** on the project's main website: https://opengoal.dev
> [!WARNING]
> **Do not use this decompilation project without providing your own legally purchased copy of the game.** We do not distribute any assets from the game - you must use your own legitimately obtained PS2 copy of the game. We support every retail PAL, NTSC, and NTSC-J build, including Greatest Hits copies.
- [Project Description](#project-description)
- [Current Status](#current-status)
- [Methodology](#methodology)
@@ -25,6 +36,11 @@
- [Windows](#windows)
- [Required Software](#required-software)
- [Using Visual Studio](#using-visual-studio)
- [MacOS](#macos)
- [Intel Based](#intel-based)
- [Apple Silicon](#apple-silicon)
- [VSCode](#vscode)
- [Building and Debugging](#building-and-debugging)
- [Building and Running the Game](#building-and-running-the-game)
- [Extract Assets](#extract-assets)
- [Build the Game](#build-the-game)
@@ -40,25 +56,9 @@
- [`goal_src/`](#goal_src)
- [`game` runtime](#game-runtime)
## Please read first
Our repositories on GitHub are primarily for development of the project and tracking active issues. Most of the information you will find here pertains to setting up the project for development purposes and is not relevant to the end-user.
For questions or additional information pertaining to the project, we have a Discord for discussion here: https://discord.gg/VZbXMHXzWv
Additionally, you can find further documentation and answers to **frequently asked questions** on the project's main website: https://opengoal.dev
**Do not use this decompilation project without providing your own legally purchased copy of the game.**
### Quick Start
If you just want to play the game, you can follow the steps in this video: https://www.youtube.com/watch?v=p8I9NfuZOgE
We do not distribute any assets from the game - you must use your own legitimately obtained PS2 copy of the game. We support every retail PAL, NTSC, and NTSC-J build, including Greatest Hits copies.
## Project Description
This project is to port Jak 1 (NTSC, "black label" version) to PC. Over 98% of this game is written in GOAL, a custom Lisp language developed by Naughty Dog. Our strategy is:
This project is to port the original Jak and Daxter and Jak II to PC. Over 98% of the games are 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 game code for x86-64
- create a tool to extract game assets into formats that can be easily viewed or modified
@@ -76,7 +76,7 @@ We support both Linux and Windows on x86-64.
### Current Status
Jak 1 is largely playable from start to finish with a handful of bugs that are continually being ironed out.
Jak 1 is largely playable from start to finish with a handful of bugs that are continually being ironed out. Jak 2 is in development.
![](./docs/img/promosmall1.png)
![](./docs/img/promosmall2.png)
@@ -112,13 +112,13 @@ This will create an image with all required dependencies and already built.
docker run -v "$(pwd)"/build:/home/jak/jak-project/build -it jak bash
```
Note: If you the build directory you'll need to rerun the build command. Alteratively you can get the build via `docker cp`
Note: If you change the content of the `build/` directory you'll need to rerun the `build` command. Alternatively you can get the build via `docker cp`.
This will link your build folder to the images so can validate your build or test it on an external device.
This will link your `build/` folder to the images so can validate your build or test it on an external device.
Docker images can be linked into your IDE (e.g. CLion) to help with codesniffing, static analysis, run tests and continuous build.
Unfortently you'll still need task runner on your local machine to run the game or instead, manually run the game via the commands found in `Taskfile.yml`
Unfortunately you'll still need task runner on your local machine to run the game or instead, manually run the game via the commands found in `Taskfile.yml`.
### Linux
@@ -127,7 +127,7 @@ Unfortently you'll still need task runner on your local machine to run the game
Install packages and init repository:
```sh
sudo apt install gcc make cmake build-essential g++ nasm clang-format libxrandr-dev libxinerama-dev libxcursor-dev libpulse-dev libxi-dev python
sudo apt install gcc make cmake build-essential g++ nasm clang-format libxrandr-dev libxinerama-dev libxcursor-dev libpulse-dev libxi-dev python libgl1-mesa-dev libssl-dev
sudo sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
```
@@ -183,7 +183,7 @@ Run tests:
Install packages and init repository:
```sh
sudo dnf install cmake python lld clang nasm libX11-devel libXrandr-devel libXinerama-devel libXcursor-devel libXi-devel pulseaudio-libs-devel
sudo dnf install cmake python lld clang nasm libX11-devel libXrandr-devel libXinerama-devel libXcursor-devel libXi-devel pulseaudio-libs-devel mesa-libGL-devel
sudo sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
```
@@ -233,6 +233,51 @@ Then build the entire project as `Windows Release (clang)`. You can also press C
![](./docs/img/windows/release-build.png)
![](./docs/img/windows/build-all.png)
### MacOS
> NOTE: At this time you can only run the game on macOS if you have an Intel processor.
Ensure that you have Xcode command line tools installed (this installs things like Apple Clang). If you don't, you can run the following command:
```bash
xcode-select --install
```
#### Intel Based
```bash
brew install go-task/tap/go-task
brew install cmake nasm ninja go-task clang-format
cmake -B build --preset=Release-macos-clang
cmake --build build --parallel $((`sysctl -n hw.logicalcpu`))
```
#### Apple Silicon
**Not Supported at This Time**
```bash
brew install go-task/tap/go-task
brew install cmake ninja go-task clang-format
cmake -B build --preset=Release-macos-clang
cmake --build build --parallel $((`sysctl -n hw.logicalcpu`))
```
You may have to add the MacOS SDK to your `LIBRARY_PATH`:
- `export LIBRARY_PATH="$LIBRARY_PATH:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib"`
### VSCode
If you either don't want to or cannot use Visual Studio for working with the C++ project, VSCode is a good alternatively.
The `clangd` extension is [recommended](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) and requires `clangd` to be on your `$PATH`. If you can run `clangd` in a terminal successfully then you should be good to go.
Once you generate your CMake for the first time the clangd LSP should be able to index the project and give you intellisense.
#### Building and Debugging
TODO - Consider Contributing Documentation :)
### Building and Running the Game
Getting a running game involves 4 steps:
@@ -244,13 +289,20 @@ Getting a running game involves 4 steps:
#### Extract Assets
First, setup your settings so the following scripts know which game you are using, and which version. In a terminal, run the following:
First, setup your settings so the following scripts know which game you are using, and which version. For the black label version of the game, run the following in a terminal:
```sh
task set-game-jak1
task set-decomp-ntscv1
```
For other versions of the game, you will need to use a different `-set-decomp-<VERSION>` command. An example for the PAL version:
```sh
task set-game-jak1
task set-decomp-pal
```
> Run `task --list` to see the other available options
> At the time of writing, only Jak 1 is expected to work end-to-end!
@@ -292,6 +344,12 @@ Run the following to build the game:
g > (mi)
```
> IMPORTANT NOTE! If you're not using the non-default version of the game, you may hit issues trying to run `(mi)` in this step. An example error might include something like:
>
> `Input file iso_data/jak1/MUS/TWEAKVAL.MUS does not exist.`
>
> This is because the decompiler inputs/outputs using the `gameName` JSON field in the decompiler config. For example if you are using Jak 1 PAL, it will assume `iso_data/jak1_pal` and `decompiler_out/jak1_pal`. Therefore, you can inform the REPL/compiler of this via the `gameVersionFolder` config field described [here](./goal_src/user/README.md)
#### Run the Game
Finally the game can be ran. Open a second terminal from the `jak-project` directory and run the following:
+101 -33
View File
@@ -1,4 +1,4 @@
version: "3.13"
version: 3
includes:
build: ./scripts/tasks/Taskfile_{{OS}}.yml
@@ -15,6 +15,8 @@ tasks:
- 'python ./scripts/tasks/update-env.py --game jak1'
set-game-jak2:
- 'python ./scripts/tasks/update-env.py --game jak2'
set-game-jak3:
- 'python ./scripts/tasks/update-env.py --game jak3'
set-decomp-ntscv1:
desc: "aka black label"
cmds:
@@ -24,9 +26,17 @@ tasks:
cmds:
- 'python ./scripts/tasks/update-env.py --decomp_config ntscv2'
set-decomp-pal:
- 'python ./scripts/tasks/update-env.py --decomp_config pal'
desc: "PAL region version"
cmds:
- 'python ./scripts/tasks/update-env.py --decomp_config pal'
set-decomp-ntscjp:
- 'python ./scripts/tasks/update-env.py --decomp_config ntscjp'
desc: "NTSC-J region version"
cmds:
- 'python ./scripts/tasks/update-env.py --decomp_config ntscjp'
set-decomp-ntscko:
desc: "NTSC-K region version"
cmds:
- 'python ./scripts/tasks/update-env.py --decomp_config ntscko'
# GENERAL
extract:
desc: "Extracts the game's assets from './iso_data' with the set decompiler config"
@@ -34,28 +44,28 @@ tasks:
- sh: test -f {{.DECOMP_BIN_RELEASE_DIR}}/decompiler{{.EXE_FILE_EXTENSION}}
msg: "Couldn't locate decompiler executable in '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler'"
cmds:
- '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler "./decompiler/config/{{.DECOMP_CONFIG}}" ./iso_data ./decompiler_out --config-override "{\\\"decompile_code\\\": false}"'
- "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler \"./decompiler/config/{{.DECOMP_CONFIG}}\" \"./iso_data\" \"./decompiler_out\" --version \"{{.DECOMP_CONFIG_VERSION}}\" --config-override '{\"decompile_code\": false, \"levels_extract\": true, \"allowed_objects\": []}'"
boot-game:
desc: "Boots the game, it will fail if it's not already compiled!"
preconditions:
- sh: test -f {{.GK_BIN_RELEASE_DIR}}/gk{{.EXE_FILE_EXTENSION}}
msg: "Couldn't locate runtime executable in '{{.GK_BIN_RELEASE_DIR}}/gk'"
cmds:
- "{{.GK_BIN_RELEASE_DIR}}/gk -boot -fakeiso -debug -v"
- "{{.GK_BIN_RELEASE_DIR}}/gk -v --game {{.GAME}} -- -boot -fakeiso -debug"
boot-game-retail:
desc: "Boots the game without debug mode, it will fail if it's not already compiled!"
preconditions:
- sh: test -f {{.GK_BIN_RELEASE_DIR}}/gk{{.EXE_FILE_EXTENSION}}
msg: "Couldn't locate runtime executable in '{{.GK_BIN_RELEASE_DIR}}/gk'"
cmds:
- "{{.GK_BIN_RELEASE_DIR}}/gk -boot -fakeiso -v"
- "{{.GK_BIN_RELEASE_DIR}}/gk -v --game {{.GAME}} -- -boot -fakeiso"
run-game:
desc: "Start the game's runtime, to start the game itself the REPL is required"
preconditions:
- sh: test -f {{.GK_BIN_RELEASE_DIR}}/gk{{.EXE_FILE_EXTENSION}}
msg: "Couldn't locate runtime executable in '{{.GK_BIN_RELEASE_DIR}}/gk'"
cmds:
- "{{.GK_BIN_RELEASE_DIR}}/gk -fakeiso -debug -v"
- "{{.GK_BIN_RELEASE_DIR}}/gk -v --game {{.GAME}} -- -fakeiso -debug"
# DEVELOPMENT
repl:
desc: "Start the REPL"
@@ -63,64 +73,122 @@ tasks:
- sh: test -f {{.GOALC_BIN_RELEASE_DIR}}/goalc{{.EXE_FILE_EXTENSION}}
msg: "Couldn't locate compiler executable in '{{.GOALC_BIN_RELEASE_DIR}}/goalc'"
cmds:
- "{{.GOALC_BIN_RELEASE_DIR}}/goalc --game {{.GAME}}"
repl-lt:
- "{{.GOALC_BIN_RELEASE_DIR}}/goalc --user-auto --game {{.GAME}}"
format-json:
desc: "Format code"
cmds:
- "{{.GOALC_BIN_RELEASE_DIR}}/goalc --auto-lt --game {{.GAME}}"
# npm install -g prettier
- cmd: npx prettier --write ./decompiler/config/jak*/**/*.jsonc
ignore_error: true
format:
desc: "Format code"
cmds:
- cmd: python ./scripts/cpp/format-includes.py
- cmd: python ./scripts/ci/lint-trailing-whitespace.py --fix
- cmd: python ./third-party/run-clang-format/run-clang-format.py -r common decompiler game goalc test tools lsp -i
# npm install -g prettier
- cmd: npx prettier --write ./decompiler/config/jak1_ntsc_black_label/*.jsonc
ignore_error: true
- cmd: npx prettier --write ./decompiler/config/jak2/*.jsonc
ignore_error: true
run-game-headless:
- task: format-json
format-gsrc:
desc: "Run formatter on gsrc file"
preconditions:
- sh: test -f {{.FORMATTER_BIN_RELEASE_DIR}}/formatter{{.EXE_FILE_EXTENSION}}
msg: "Couldn't locate formatter executable in '{{.FORMATTER_BIN_RELEASE_DIR}}/formatter'"
cmds:
- "{{.GK_BIN_RELEASE_DIR}}/gk -fakeiso -debug -nodisplay"
- "{{.FORMATTER_BIN_RELEASE_DIR}}/formatter --write --file '{{.FILE}}'"
# DECOMPILING
decomp:
cmds:
- '{{.DECOMP_BIN_RELEASE_DIR}}/decompiler "./decompiler/config/{{.DECOMP_CONFIG}}" "./iso_data" "./decompiler_out"'
- "{{.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}'"
decomp-file:
cmds:
- "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler \"./decompiler/config/{{.DECOMP_CONFIG}}\" \"./iso_data\" \"./decompiler_out\" --config-override '{\"allowed_objects\": [\"{{.FILE}}\"]}'"
- "{{.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-clean:
cmds:
- python ./scripts/tasks/clean-decomp.py --game "{{.GAME}}"
lint-gsrc-file:
cmds:
- python ./scripts/gsrc/lint-gsrc-file.py --game {{.GAME}} --file "{{.FILE}}"
update-gsrc:
cmds:
- python ./scripts/gsrc/update-gsrc-via-refs.py --game "{{.GAME}}" --decompiler "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler" --decompiler_config {{.DECOMP_CONFIG}}
- python ./scripts/gsrc/update-gsrc-via-refs.py --game "{{.GAME}}" --decompiler "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler" --decompiler_config {{.DECOMP_CONFIG}} --version {{.DECOMP_CONFIG_VERSION}}
update-gsrc-glob:
cmds:
- python ./scripts/gsrc/update-gsrc-via-refs.py --game "{{.GAME}}" --file_pattern "{{.GLOB}}" --decompiler "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler" --decompiler_config {{.DECOMP_CONFIG}} --version {{.DECOMP_CONFIG_VERSION}}
update-gsrc-file:
cmds:
- task: decomp-file
- python ./scripts/gsrc/update-from-decomp.py --game "{{.GAME}}" --file {{.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:
- "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler \"./decompiler/config/{{.DECOMP_CONFIG}}\" \"./iso_data\" \"./decompiler_out\" --version \"{{.DECOMP_CONFIG_VERSION}}\" --config-override '{\"decompile_code\": false, \"levels_extract\": true, \"save_texture_pngs\": true}'"
rip-levels:
cmds:
- "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler \"./decompiler/config/{{.DECOMP_CONFIG}}\" \"./iso_data\" \"./decompiler_out\" --version \"{{.DECOMP_CONFIG_VERSION}}\" --config-override '{\"decompile_code\": false, \"levels_extract\": true, \"rip_levels\": true}'"
rip-collision:
cmds:
- "{{.DECOMP_BIN_RELEASE_DIR}}/decompiler \"./decompiler/config/{{.DECOMP_CONFIG}}\" \"./iso_data\" \"./decompiler_out\" --version \"{{.DECOMP_CONFIG_VERSION}}\" --config-override '{\"decompile_code\": false, \"levels_extract\": true, \"extract_collision\": true, \"rip_collision\": true}'"
# TOOLS
analyze-ee-memory:
cmds:
- python ./scripts/tasks/extract-zip.py --file "{{.FILE}}" --out ./savestate_out/
- '{{.MEMDUMP_BIN_RELEASE_DIR}}/memory_dump_tool ./savestate_out/eeMemory.bin --output-path ./ --game {{.GAME}} > ee-analysis.log'
watch-pcsx2:
# python -m pip install -U "watchdog[watchmedo]"
cmds:
- watchmedo shell-command --drop --patterns="*.p2s" --recursive --command='task analyze-ee-memory FILE="${watch_src_path}"' "{{.SAVESTATE_DIR}}"
vars:
SAVESTATE_DIR: '{{default "." .SAVESTATE_DIR}}'
# TESTS
offline-tests:
type-search:
desc: Just an example to show it running
cmds:
- '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}}'
- "{{.TYPESEARCH_BIN_RELEASE_DIR}}/type_searcher --output-path ./search-results.json --game {{.GAME}} --fields '[{\"type\":\"int16\",\"offset\":2},{\"type\":\"int16\",\"offset\":4}]'"
update-treesitter:
desc: Updates locally built tree-sitter rules
cmds:
- cd ../tree-sitter-opengoal && yarn gen
- python ./scripts/tasks/cp.py --src "../tree-sitter-opengoal/src/*" --dest "./third-party/tree-sitter/tree-sitter-opengoal"
- python ./scripts/tasks/cp.py --src "../tree-sitter-opengoal/grammar.js" --dest "./third-party/tree-sitter/tree-sitter-opengoal"
fix-translations:
desc: Finds and tries to fix invalid translation Characters
cmds:
- python ./scripts/ci/lint-characters.py --fix
lint:
cmds:
- python ./scripts/ci/lint-trailing-whitespace.py
# TESTS
offline-tests: # ran by jenkins
cmds:
- '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --fail-on-cmp'
offline-test-file:
cmds:
- '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --file {{.FILE}}'
offline-tests-fast:
cmds:
- '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --pretty-print --num_threads 32 --dump_current_output --fail-on-cmp'
# TODO - amalgamate offline-tests and this task, run twice if the previous step fails
update-ref-tests:
cmds:
- cmd: python ./scripts/tasks/default-file-or-folder.py --path failures
- cmd: '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --dump_current_output'
- cmd: python ./scripts/tasks/delete-file-or-folder.py --path failures
- cmd: '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --game {{.GAME}} --pretty-print --num_threads 32 --dump_current_output --fail-on-cmp'
ignore_error: true
- python ./scripts/update_decomp_reference.py ./failures ./test/decompiler/reference/
- task: offline-tests
# check-gsrc-file:
# cmds:
# - python ./scripts/check-gsrc-file.py --files "{{.FILES}}"
- python ./scripts/update_decomp_reference.py ./failures ./test/decompiler/reference/ --game {{.GAME}}
- task: offline-tests-fast
update-ref-file:
cmds:
- cmd: python ./scripts/tasks/delete-file-or-folder.py --path failures
- cmd: '{{.OFFLINETEST_BIN_RELEASE_DIR}}/offline-test --iso_data_path "./iso_data/{{.GAME}}" --file {{.FILE}} --game {{.GAME}} --dump_current_output --fail-on-cmp'
ignore_error: true
- python ./scripts/update_decomp_reference.py ./failures ./test/decompiler/reference/ --game {{.GAME}}
- task: offline-test-file
type-test:
cmds:
- cmd: '{{.GOALCTEST_BIN_RELEASE_DIR}}/goalc-test --gtest_brief=0 --gtest_filter="*Jak2TypeConsistency*"'
ignore_error: true
- cmd: '{{.GOALCTEST_BIN_RELEASE_DIR}}/goalc-test --gtest_brief=0 --gtest_filter="*{{.TYPE_CONSISTENCY_TEST_FILTER}}*" --gtest_break_on_failure'
+58 -17
View File
@@ -1,29 +1,63 @@
function(write_revision_h)
find_package(Git)
set(GIT_SHORT_SHA "")
set(GIT_TAG "")
if(NOT GIT_FOUND)
MESSAGE(STATUS "write_revision_h(): git was not found")
endif()
MESSAGE(STATUS "write_revision_h(): ${CMAKE_SOURCE_DIR}")
if (GIT_FOUND AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
MESSAGE(STATUS "Git found, using it to get revision info")
EXECUTE_PROCESS(WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
OUTPUT_VARIABLE GIT_SHORT_SHA
OUTPUT_STRIP_TRAILING_WHITESPACE)
EXECUTE_PROCESS(WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} COMMAND ${GIT_EXECUTABLE} tag --points-at HEAD
OUTPUT_VARIABLE GIT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
endif()
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/versions/revision.h "#define BUILT_TAG \"${GIT_TAG}\"\n#define BUILT_SHA \"${GIT_SHORT_SHA}\"\n")
endfunction()
write_revision_h()
add_library(common
versions.cpp
audio/audio_formats.cpp
cross_os_debug/xdbg.cpp
cross_sockets/XSocket.cpp
cross_sockets/XSocketServer.cpp
cross_sockets/XSocketClient.cpp
cross_sockets/XSocketServer.cpp
custom_data/pack_helpers.cpp
custom_data/TFrag3Data.cpp
dma/dma.cpp
dma/dma_copy.cpp
dma/dma.cpp
dma/gs.cpp
formatter/formatter_tree.cpp
formatter/formatter.cpp
formatter/formatter_tree.cpp
formatter/rules/formatting_rules.cpp
formatter/rules/rule_config.cpp
global_profiler/GlobalProfiler.cpp
goos/Interpreter.cpp
goos/Object.cpp
goos/ParseHelpers.cpp
goos/Printer.cpp
goos/PrettyPrinter.cpp
goos/PrettyPrinter2.cpp
goos/Printer.cpp
goos/Reader.cpp
goos/TextDB.cpp
goos/ReplUtils.cpp
log/log.cpp
math/geometry.cpp
nrepl/ReplClient.cpp
nrepl/ReplServer.cpp
repl/config.cpp
repl/nrepl/ReplClient.cpp
repl/nrepl/ReplServer.cpp
repl/repl_wrapper.cpp
serialization/subtitles/subtitles_v1.cpp
serialization/subtitles/subtitles_v2.cpp
serialization/subtitles/subtitles.cpp
serialization/text/text_ser.cpp
sqlite/sqlite.cpp
texture/texture_slots.cpp
type_system/defenum.cpp
type_system/deftype.cpp
type_system/state.cpp
@@ -31,31 +65,38 @@ add_library(common
type_system/TypeFieldLookup.cpp
type_system/TypeSpec.cpp
type_system/TypeSystem.cpp
serialization/subtitles/subtitles_ser.cpp
serialization/subtitles/subtitles_deser.cpp
util/Assert.cpp
util/ast_util.cpp
util/BitUtils.cpp
util/compress.cpp
util/crc32.cpp
util/dgo_util.cpp
util/DgoReader.cpp
util/DgoWriter.cpp
util/dialogs.cpp
util/diff.cpp
util/FileUtil.cpp
util/json_util.cpp
util/read_iso_file.cpp
util/SimpleThreadGroup.cpp
util/Timer.cpp
util/os.cpp
util/print_float.cpp
util/FontUtils.cpp
util/FrameLimiter.cpp
util/unicode_util.cpp)
util/json_util.cpp
util/os.cpp
util/print_float.cpp
util/read_iso_file.cpp
util/SimpleThreadGroup.cpp
util/string_util.cpp
util/term_util.cpp
util/Timer.cpp
util/unicode_util.cpp
util/gltf_util.cpp
versions/versions.cpp
)
target_link_libraries(common fmt lzokay replxx libzstd_static)
target_link_libraries(common fmt lzokay replxx libzstd_static tree-sitter sqlite3 libtinyfiledialogs tiny_gltf)
if(WIN32)
target_link_libraries(common wsock32 ws2_32 windowsapp)
elseif(APPLE)
# don't need anything special
else()
target_link_libraries(common stdc++fs)
endif()
+101 -41
View File
@@ -1,68 +1,111 @@
#include "audio_formats.h"
#include "common/log/log.h"
#include "common/util/BinaryWriter.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
/*!
* Write a wave file from a vector of samples.
*/
void write_wave_file_mono(const std::vector<s16>& samples, s32 sample_rate, const fs::path& name) {
void write_wave_file(const std::vector<s16>& left_samples,
const std::vector<s16>& right_samples,
s32 sample_rate,
const fs::path& name) {
WaveFileHeader header;
memcpy(header.chunk_id, "RIFF", 4);
header.chunk_size = 36 + samples.size() * sizeof(s16);
header.chunk_size = 36 + ((left_samples.size() + right_samples.size()) * sizeof(s16));
memcpy(header.format, "WAVE", 4);
// now the format
memcpy(header.subchunk1_id, "fmt ", 4);
header.subchunk1_size = 16;
header.aud_format = 1;
header.num_channels = 1; // mono
if (right_samples.empty()) {
header.num_channels = 1; // mono
} else {
header.num_channels = 2; // stereo
}
header.sample_rate = sample_rate;
header.byte_rate = sample_rate * header.num_channels * sizeof(s16);
header.block_align = header.num_channels * sizeof(s16);
header.bits_per_sample = 16;
memcpy(header.subchunk2_id, "data", 4);
header.subchunk2_size = samples.size() * sizeof(s16);
header.subchunk2_size = (left_samples.size() + right_samples.size()) * sizeof(s16);
BinaryWriter writer;
writer.add(header);
for (auto& samp : samples) {
writer.add(samp);
if (right_samples.empty()) {
for (const auto& sample : left_samples) {
writer.add(sample);
}
} else {
for (size_t i = 0; i < left_samples.size(); i++) {
writer.add(left_samples.at(i));
if (i < right_samples.size()) {
writer.add(right_samples.at(i));
} else {
writer.add(0);
}
}
}
writer.write_to_file(name);
}
std::vector<s16> decode_adpcm(BinaryReader& reader) {
std::vector<s16> decoded_samples;
s32 sample_prev[2] = {0, 0};
std::pair<std::vector<s16>, std::vector<s16>> decode_adpcm(BinaryReader& reader,
const bool stereo) {
std::vector<s16> left_samples;
std::vector<s16> right_samples;
s32 left_sample_prev[2] = {0, 0};
s32 right_sample_prev[2] = {0, 0};
bool first_left = true;
bool first_right = true;
constexpr s32 f1[5] = {0, 60, 115, 98, 122};
constexpr s32 f2[5] = {0, 0, -52, -55, -60};
int block_idx = 0;
[[maybe_unused]] int block_idx = 0;
// 16 byte blocks
int bytes_read = reader.get_seek(); // we've already read n bytes into the file
// Jak VAG's don't interleave the samples because of course they don't
// instead they are partitioned into contiguous 8kb (thats 8192 bytes) chunks
// alternating left/right
bool processing_left_chunk = true;
// We need to skip the vag header for each channel
if (first_left) {
reader.ffwd(48);
bytes_read += 48;
first_left = false;
}
while (true) {
if (!reader.bytes_left()) {
break;
}
if (stereo && bytes_read == 0x2000) {
// switch streams
processing_left_chunk = !processing_left_chunk;
bytes_read = 0;
// We need to skip the vag header for each channel
if (first_right) {
// skip the header
reader.ffwd(48);
bytes_read += 48;
first_right = false;
}
}
u8 shift_filter = reader.read<u8>();
u8 flags = reader.read<u8>();
u8 shift = shift_filter & 0b1111;
u8 filter = shift_filter >> 4;
u8 flags = reader.read<u8>();
(void)flags;
if (shift > 12) {
ASSERT(false);
}
if (filter > 4) {
ASSERT(false);
}
if (flags == 7) {
break;
}
// removed assertions here (and that's probably why the audio doesn't sound right)
u8 input_buffer[14];
@@ -80,25 +123,42 @@ std::vector<s16> decode_adpcm(BinaryReader& reader) {
s32 sample = (s32)(s16)(nibble << 12);
sample >>= shift;
sample += (sample_prev[0] * f1[filter] + sample_prev[1] * f2[filter] + 32) / 64;
if (sample > 0x7fff) {
sample = 0x7fff;
if (!stereo || processing_left_chunk) {
sample += (left_sample_prev[0] * f1[filter] + left_sample_prev[1] * f2[filter] + 32) / 64;
if (sample > 0x7fff) {
sample = 0x7fff;
}
if (sample < -0x8000) {
sample = -0x8000;
}
left_sample_prev[1] = left_sample_prev[0];
left_sample_prev[0] = sample;
left_samples.push_back(sample);
} else {
sample += (right_sample_prev[0] * f1[filter] + right_sample_prev[1] * f2[filter] + 32) / 64;
if (sample > 0x7fff) {
sample = 0x7fff;
}
if (sample < -0x8000) {
sample = -0x8000;
}
right_sample_prev[1] = right_sample_prev[0];
right_sample_prev[0] = sample;
right_samples.push_back(sample);
}
if (sample < -0x8000) {
sample = -0x8000;
}
sample_prev[1] = sample_prev[0];
sample_prev[0] = sample;
decoded_samples.push_back(sample);
}
bytes_read += 16;
block_idx++;
}
return decoded_samples;
return {left_samples, right_samples};
}
// I attempted to write an encoder below, which works, but has some limitations.
@@ -254,7 +314,7 @@ void test_encode_adpcm(const std::vector<s16>& samples,
}
if (debug) {
fmt::print("Range: {}\n", max_sample - min_sample);
lg::debug("Range: {}", max_sample - min_sample);
}
// see how many bits we need and pick shift.
@@ -283,11 +343,11 @@ void test_encode_adpcm(const std::vector<s16>& samples,
if (filter_errors[best_filter] || best_filter != filter_debug[block_idx] ||
best_shift != shift_debug[block_idx]) {
fmt::print("Block {} me {}, {} : answer {} {}: ERR {}\n", block_idx, best_filter, best_shift,
filter_debug[block_idx], shift_debug[block_idx], filter_errors[best_filter]);
fmt::print("filter errors:\n");
lg::error("Block {} me {}, {} : answer {} {}: ERR {}", block_idx, best_filter, best_shift,
filter_debug[block_idx], shift_debug[block_idx], filter_errors[best_filter]);
lg::error("filter errors:");
for (int i = 0; i < 5; i++) {
fmt::print(" [{}] {} {}\n", i, filter_errors[i], filter_shifts[i]);
lg::error(" [{}] {} {}", i, filter_errors[i], filter_shifts[i]);
}
ASSERT_MSG(false, fmt::format("prev: {} {}", prev_block_samples[0], prev_block_samples[1]));
}
+5 -2
View File
@@ -29,8 +29,11 @@ struct WaveFileHeader {
s32 subchunk2_size;
};
void write_wave_file_mono(const std::vector<s16>& samples, s32 sample_rate, const fs::path& name);
void write_wave_file(const std::vector<s16>& left_samples,
const std::vector<s16>& right_samples,
s32 sample_rate,
const fs::path& name);
std::vector<s16> decode_adpcm(BinaryReader& reader);
std::pair<std::vector<s16>, std::vector<s16>> decode_adpcm(BinaryReader& reader, const bool mono);
std::vector<u8> encode_adpcm(const std::vector<s16>& samples);
+4
View File
@@ -30,3 +30,7 @@ struct u128 {
};
};
static_assert(sizeof(u128) == 16, "u128");
#if defined __linux || defined __linux__ || defined __APPLE__
#define OS_POSIX
#endif
+71 -22
View File
@@ -11,7 +11,7 @@
#include "common/goal_constants.h"
#include "common/util/Timer.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
#ifdef __linux
#include <fcntl.h>
@@ -392,7 +392,7 @@ bool cont_now(const ThreadID& tid) {
DEBUG_EVENT debugEvent;
void ignore_debug_event() {
if (!ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE)) {
win_print_last_error("ContinueDebugEvent");
win_print_last_error("ContinueDebugEvent ignore_debug_event");
}
cont_status = -1;
}
@@ -456,7 +456,7 @@ bool check_stopped(const ThreadID& tid, SignalInfo* out) {
if (cont_status != -1) {
cv.wait(lk, [&] { return cont_status == 1; });
if (!ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE)) {
win_print_last_error("ContinueDebugEvent");
win_print_last_error("ContinueDebugEvent check_stopped");
}
cont_status = -1;
}
@@ -505,18 +505,12 @@ bool check_stopped(const ThreadID& tid, SignalInfo* out) {
}
}
} break;
case CREATE_THREAD_DEBUG_EVENT: // 2
case CREATE_PROCESS_DEBUG_EVENT: // 3
if (debugEvent.u.CreateProcessInfo.hProcess != NULL &&
GetProcessId(debugEvent.u.CreateProcessInfo.hProcess) == debugEvent.dwProcessId) {
}
// out->kind = SignalInfo::NOTHING;
ignore_debug_event();
break;
case CREATE_THREAD_DEBUG_EVENT: // 2
case EXIT_THREAD_DEBUG_EVENT: // 4
case LOAD_DLL_DEBUG_EVENT: // 6
case UNLOAD_DLL_DEBUG_EVENT: // 7
case OUTPUT_DEBUG_STRING_EVENT: // 8
case EXIT_THREAD_DEBUG_EVENT: // 4
case LOAD_DLL_DEBUG_EVENT: // 6
case UNLOAD_DLL_DEBUG_EVENT: // 7
case OUTPUT_DEBUG_STRING_EVENT: // 8
// don't care about these
// out->kind = SignalInfo::NOTHING;
ignore_debug_event();
@@ -554,7 +548,7 @@ bool read_goal_memory(u8* dest_buffer,
HANDLE hProc = OpenProcess(PROCESS_VM_READ, FALSE, context.tid.pid);
if (hProc == NULL) {
win_print_last_error("OpenProcess");
win_print_last_error("OpenProcess read_goal_memory");
return false;
}
@@ -579,7 +573,7 @@ bool write_goal_memory(const u8* src_buffer,
HANDLE hProc = OpenProcess(PROCESS_VM_WRITE, FALSE, context.tid.pid);
if (hProc == NULL) {
win_print_last_error("OpenProcess");
win_print_last_error("OpenProcess write_goal_memory");
return false;
}
@@ -601,7 +595,7 @@ bool get_regs_now(const ThreadID& tid, Regs* out) {
HANDLE hThr = OpenThread(THREAD_GET_CONTEXT, FALSE, tid.tid);
if (hThr == NULL) {
win_print_last_error("OpenThread");
win_print_last_error("OpenThread get_regs_now");
return false;
}
@@ -609,7 +603,7 @@ bool get_regs_now(const ThreadID& tid, Regs* out) {
CloseHandle(hThr);
if (!result) {
win_print_last_error("GetThreadContext");
win_print_last_error("GetThreadContext get_regs_now");
return false;
}
@@ -641,7 +635,7 @@ bool set_regs_now(const ThreadID& tid, const Regs& out) {
HANDLE hThr = OpenThread(THREAD_GET_CONTEXT, FALSE, tid.tid);
if (hThr == NULL) {
win_print_last_error("OpenThread");
win_print_last_error("OpenThread set_regs_now");
return false;
}
@@ -649,7 +643,7 @@ bool set_regs_now(const ThreadID& tid, const Regs& out) {
CloseHandle(hThr);
if (!result) {
win_print_last_error("GetThreadContext");
win_print_last_error("GetThreadContext set_regs_now");
return false;
}
@@ -674,7 +668,7 @@ bool set_regs_now(const ThreadID& tid, const Regs& out) {
hThr = OpenThread(THREAD_SET_CONTEXT, FALSE, tid.tid);
if (hThr == NULL) {
win_print_last_error("OpenThread");
win_print_last_error("OpenThread set_regs_now set");
return false;
}
@@ -682,12 +676,67 @@ bool set_regs_now(const ThreadID& tid, const Regs& out) {
CloseHandle(hThr);
if (!result) {
win_print_last_error("SetThreadContext");
win_print_last_error("SetThreadContext set_regs_now set");
return false;
}
// todo, set fprs.
return true;
}
#elif __APPLE__
ThreadID::ThreadID(const std::string& str) {}
std::string ThreadID::to_string() const {
return "invalid";
}
ThreadID get_current_thread_id() {
return ThreadID("not implemented on macOS");
}
bool attach_and_break(const ThreadID& tid);
void allow_debugging() {
printf("allow_debugging not implemented on macOS\n");
}
bool detach_and_resume(const ThreadID& tid) {
return false;
}
bool get_regs_now(const ThreadID& tid, Regs* out) {
return false;
}
bool set_regs_now(const ThreadID& tid, const Regs& in) {
return false;
}
bool break_now(const ThreadID& tid) {
return false;
}
bool cont_now(const ThreadID& tid) {
return false;
}
bool open_memory(const ThreadID& tid, MemoryHandle* out);
bool close_memory(const ThreadID& tid, MemoryHandle* handle) {
return false;
}
bool read_goal_memory(u8* dest_buffer,
int size,
u32 goal_addr,
const DebugContext& context,
const MemoryHandle& mem) {
return false;
}
bool write_goal_memory(const u8* src_buffer,
int size,
u32 goal_addr,
const DebugContext& context,
const MemoryHandle& mem) {
return false;
}
bool check_stopped(const ThreadID& tid, SignalInfo* out) {
return false;
}
#endif
const char* gpr_names[] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+1 -1
View File
@@ -20,7 +20,7 @@
#endif
namespace xdbg {
#ifdef __linux
#ifdef OS_POSIX
/*!
* Identification for a thread.
+30 -15
View File
@@ -4,7 +4,9 @@
*/
// clang-format off
#ifdef __linux
#include "common/common_types.h"
#ifdef OS_POSIX
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <unistd.h>
@@ -17,11 +19,12 @@
#include <stdio.h>
#include <string.h>
#include "third-party/fmt/core.h"
#include "fmt/core.h"
#include "common/log/log.h"
// clang-format on
int open_socket(int af, int type, int protocol) {
#ifdef __linux
#ifdef OS_POSIX
return socket(af, type, protocol);
#elif _WIN32
WSADATA wsaData = {0};
@@ -29,7 +32,7 @@ int open_socket(int af, int type, int protocol) {
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
lg::error("WSAStartup failed: {}", iResult);
return 1;
}
return socket(af, type, protocol);
@@ -44,7 +47,7 @@ int connect_socket(int socket, sockaddr* addr, int nameLen) {
return result;
}
#ifdef __linux
#ifdef OS_POSIX
int accept_socket(int socket, sockaddr* addr, socklen_t* addrLen) {
return accept(socket, addr, addrLen);
}
@@ -71,7 +74,7 @@ int accept_socket(int socket, sockaddr* addr, int* addrLen) {
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
lg::error("WSAStartup failed: {}", iResult);
return 1;
}
return accept(socket, addr, addrLen);
@@ -105,7 +108,7 @@ void close_socket(int sock) {
if (sock < 0) {
return;
}
#ifdef __linux
#ifdef OS_POSIX
close(sock);
#elif _WIN32
closesocket(sock);
@@ -116,20 +119,20 @@ void close_socket(int sock) {
int set_socket_option(int socket, int level, int optname, const void* optval, int optlen) {
int ret = setsockopt(socket, level, optname, (const char*)optval, optlen);
if (ret < 0) {
printf("Failed to setsockopt(%d, %d, %d, _, _) - Error: %s\n", socket, level, optname,
strerror(errno));
lg::error("Failed to setsockopt({},{}, {}, _, _) - Error: {}", socket, level, optname,
strerror(errno));
}
#ifdef _WIN32
if (ret < 0) {
int err = WSAGetLastError();
printf("WSAGetLastError: %d\n", err);
lg::error("WSAGetLastError: {}", err);
}
#endif
return ret;
}
int set_socket_timeout(int socket, long microSeconds) {
#ifdef __linux
#ifdef OS_POSIX
struct timeval timeout = {};
timeout.tv_sec = 0;
timeout.tv_usec = microSeconds;
@@ -141,25 +144,27 @@ int set_socket_timeout(int socket, long microSeconds) {
return ret;
#elif _WIN32
DWORD timeout = microSeconds / 1000; // milliseconds
// TODO - NOTE this might be bad / unreliable if the socket ends up being in a bad state
// select() instead should be used, will do so if ends up being an issue in practice
return set_socket_option(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
#endif
}
int write_to_socket(int socket, const char* buf, int len) {
int bytes_wrote = 0;
#ifdef __linux
#ifdef OS_POSIX
bytes_wrote = send(socket, buf, len, MSG_NOSIGNAL);
#elif _WIN32
bytes_wrote = send(socket, buf, len, 0);
#endif
if (bytes_wrote < 0) {
fmt::print(stderr, "[XSocket:{}] Error writing to socket\n", socket);
lg::error("[XSocket:{}] Error writing to socket", socket);
}
return bytes_wrote;
}
int read_from_socket(int socket, char* buf, int len) {
#ifdef __linux
#ifdef OS_POSIX
return read(socket, buf, len);
#elif _WIN32
return recv(socket, buf, len, 0);
@@ -167,10 +172,20 @@ int read_from_socket(int socket, char* buf, int len) {
}
bool socket_timed_out() {
#ifdef __linux
#ifdef OS_POSIX
return errno == EAGAIN;
#elif _WIN32
auto err = WSAGetLastError();
return err == WSAETIMEDOUT;
#endif
}
std::string address_to_string(const sockaddr_in& addr) {
char ip_str[INET_ADDRSTRLEN]; // Buffer to hold the IP address string
// Convert binary IP address to human-readable string using inet_ntop
if (inet_ntop(AF_INET, &(addr.sin_addr), ip_str, INET_ADDRSTRLEN) == nullptr) {
// Handle the error (e.g., log, throw an exception, etc.)
return "Error: Unable to convert IP address";
}
return ip_str;
}
+6 -2
View File
@@ -6,7 +6,8 @@
*/
// clang-format off
#ifdef __linux
#include "common/common_types.h"
#ifdef OS_POSIX
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
@@ -24,11 +25,13 @@
const int TCP_SOCKET_LEVEL = SOL_TCP;
#elif _WIN32
const int TCP_SOCKET_LEVEL = IPPROTO_TCP;
#elif __APPLE__
const int TCP_SOCKET_LEVEL = IPPROTO_TCP;
#endif
int open_socket(int af, int type, int protocol);
int connect_socket(int socket, sockaddr* addr, int nameLen);
#ifdef __linux
#ifdef OS_POSIX
int accept_socket(int socket, sockaddr* addr, socklen_t* addrLen);
int select_and_accept_socket(int socket, sockaddr* addr, socklen_t* addrLen, int microSeconds);
#elif _WIN32
@@ -41,3 +44,4 @@ int set_socket_timeout(int socket, long microSeconds);
int write_to_socket(int socket, const char* buf, int len);
int read_from_socket(int socket, char* buf, int len);
bool socket_timed_out();
std::string address_to_string(const sockaddr_in& addr);
+8 -3
View File
@@ -3,6 +3,9 @@
#include <string>
#include "common/cross_sockets/XSocket.h"
#include "common/log/log.h"
#include "fmt/core.h"
// clang-format off
#ifdef _WIN32
@@ -12,9 +15,7 @@
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif
#include "common/nrepl/ReplServer.h"
#include "third-party/fmt/core.h"
// clang-format on
XSocketClient::XSocketClient(int _tcp_port) {
@@ -41,7 +42,11 @@ bool XSocketClient::connect() {
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
// Convert IP address from text to binary form using inet_pton()
if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0) {
lg::error("inet_pton() failed");
return false;
}
addr.sin_port = htons(tcp_port);
// Connect to server
+30 -13
View File
@@ -2,8 +2,9 @@
#include "XSocketServer.h"
#include "common/cross_sockets/XSocket.h"
#include "common/common_types.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
#ifdef _WIN32
#define NOMINMAX
@@ -12,6 +13,7 @@
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif
#include "common/log/log.h"
// clang-format on
XSocketServer::XSocketServer(std::function<bool()> shutdown_callback,
@@ -33,26 +35,33 @@ void XSocketServer::shutdown_server() {
close_server_socket();
}
bool XSocketServer::init_server() {
bool XSocketServer::init_server(bool failure_may_occur) {
listening_socket = open_socket(AF_INET, SOCK_STREAM, 0);
if (listening_socket < 0) {
listening_socket = -1;
return false;
}
#ifdef __linux
int server_socket_opt = SO_REUSEADDR | SO_REUSEPORT;
#elif _WIN32
int server_socket_opt = SO_EXCLUSIVEADDRUSE;
#endif
int yes = 1;
int opt = 1;
if (set_socket_option(listening_socket, SOL_SOCKET, server_socket_opt, &opt, sizeof(opt)) < 0) {
#ifdef OS_POSIX
if (set_socket_option(listening_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
close_server_socket();
return false;
}
// macOS doesn't support setting multiple options at once, so we have to do this separately.
if (set_socket_option(listening_socket, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes)) < 0) {
close_server_socket();
return false;
}
#elif _WIN32
if (set_socket_option(listening_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &yes, sizeof(yes)) < 0) {
close_server_socket();
return false;
};
#endif
if (set_socket_option(listening_socket, TCP_SOCKET_LEVEL, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
if (set_socket_option(listening_socket, TCP_SOCKET_LEVEL, TCP_NODELAY, &yes, sizeof(yes)) < 0) {
close_server_socket();
return false;
}
@@ -67,19 +76,27 @@ bool XSocketServer::init_server() {
addr.sin_port = htons(tcp_port);
if (bind(listening_socket, (sockaddr*)&addr, sizeof(addr)) < 0) {
fmt::print("[XSocketServer:{}] failed to bind\n", tcp_port);
if (failure_may_occur) {
lg::debug("[XSocketServer:{}] failed to bind", tcp_port);
} else {
lg::error("[XSocketServer:{}] failed to bind", tcp_port);
}
close_server_socket();
return false;
}
if (listen(listening_socket, 0) < 0) {
fmt::print("[XSocketServer:{}] failed to listen\n", tcp_port);
if (failure_may_occur) {
lg::debug("[XSocketServer:{}] failed to listen", tcp_port);
} else {
lg::error("[XSocketServer:{}] failed to listen", tcp_port);
}
close_server_socket();
return false;
}
server_initialized = true;
fmt::print("[XSocketServer:{}] initialized\n", tcp_port);
lg::debug("[XSocketServer:{}] initialized", tcp_port);
post_init();
return true;
}
+2 -1
View File
@@ -3,6 +3,7 @@
#include <functional>
#include <mutex>
#include <thread>
#include <vector>
#include "common/common_types.h"
#include "common/cross_sockets/XSocket.h"
@@ -19,7 +20,7 @@ class XSocketServer {
XSocketServer(const XSocketServer&) = delete;
XSocketServer& operator=(const XSocketServer&) = delete;
bool init_server();
bool init_server(bool failure_may_occur = false);
void shutdown_server();
void close_server_socket();
+483 -112
View File
@@ -3,10 +3,22 @@
#include <algorithm>
#include <functional>
#ifndef __aarch64__
#include "xmmintrin.h"
#else
#include "third-party/sse2neon/sse2neon.h"
#endif
#include "common/log/log.h"
#include "common/util/Assert.h"
namespace tfrag3 {
void PackedTimeOfDay::serialize(Serializer& ser) {
ser.from_pod_vector(&data);
ser.from_ptr(&color_count);
}
void PackedTieVertices::serialize(Serializer& ser) {
ser.from_pod_vector(&color_indices);
ser.from_pod_vector(&matrices);
@@ -36,6 +48,7 @@ void ShrubDraw::serialize(Serializer& ser) {
ser.from_ptr(&num_triangles);
ser.from_ptr(&first_index_index);
ser.from_ptr(&num_indices);
ser.from_ptr(&proto_idx);
}
void InstancedStripDraw::serialize(Serializer& ser) {
@@ -64,14 +77,157 @@ void TfragTree::serialize(Serializer& ser) {
draw.serialize(ser);
}
// ser.from_pod_vector(&vertices);
ser.from_pod_vector(&packed_vertices.vertices);
ser.from_pod_vector(&packed_vertices.cluster_origins);
ser.from_pod_vector(&colors);
colors.serialize(ser);
bvh.serialize(ser);
ser.from_ptr(&use_strips);
}
math::Vector3f vopmula(math::Vector3f a, math::Vector3f b) {
return math::Vector3f(a.y() * b.z(), a.z() * b.x(), a.x() * b.y());
}
math::Vector3f vopmsub(math::Vector3f acc, math::Vector3f a, math::Vector3f b) {
return acc - vopmula(a, b);
}
/*!
* Compute the normal transformation for a TIE from the TIE matrix.
* Note that this isn't identical to the original game - we're missing the vf14 scaling factor
* For now, I just set this to 1, then normalize in the shader. Though I think we could avoid
* this by figuring out the value of vf14 here (I am just too lazy right now).
*/
std::array<math::Vector3f, 3> tie_normal_transform_v2(const std::array<math::Vector4f, 4>& m) {
// let:
// vf10, vf11, vf12, vf13 be the input matrix m
std::array<math::Vector3f, 3> result;
auto& vf10 = m[0];
auto& vf11 = m[1];
// auto& vf12 = m[2];
// lui t6, 16256
// mtc1 f1, t6 ;; 1.0
//
// qmfc2.i s1, vf10
// mtc1 f12, s1
float f12 = vf10.x();
// dsra32 s2, s1, 0
// mtc1 f13, s2
float f13 = vf10.y();
// pextuw s2, r0, s2
// mtc1 f14, s2
float f14 = vf10.z();
// mula.s f12, f12
// madda.s f13, f13
// madd.s f15, f14, f14
float f15 = f12 * f12 + f13 * f13 + f14 * f14;
float scale = 1.f / sqrtf(f15);
// rsqrt.s f15, f1, f15
// mfc1 s1, f15
// qmtc2.i vf14, s1
// vmulx.xyz vf16, vf10, vf14
// vmulx.xyz vf16, vf10, vf14
math::Vector3f vf16 = vf10.xyz() * scale;
// vopmula.xyz acc, vf11, vf16
math::Vector3f acc = vopmula(vf11.xyz(), vf16);
// vopmsub.xyz vf17, vf16, vf11
math::Vector3f vf17 = vopmsub(acc, vf16, vf11.xyz());
// vopmula.xyz acc, vf16, vf17
acc = vopmula(vf16, vf17);
// vopmsub.xyz vf17, vf17, vf16
vf17 = vopmsub(acc, vf17, vf16);
// vmul.xyz vf14, vf17, vf17
math::Vector3f vf14 = vf17.elementwise_multiply(vf17);
// vmulax.w acc, vf0, vf14
// vmadday.w acc, vf0, vf14
// vmaddz.w vf14, vf0, vf14
float sum = vf14.x() + vf14.y() + vf14.z();
// vrsqrt Q, vf0.w, vf14.w
float Q = 1.f / std::sqrt(sum);
// vmulax.xyzw acc, vf24, vf16
// vmadday.xyzw acc, vf25, vf16
// vmaddz.xyzw vf10, vf26, vf16
// vf10 = vf16; // assume cam is identity here.
result[0] = vf16;
// vwaitq
// vmulq.xyz vf17, vf17, Q
vf17 *= Q;
// vopmula.xyz acc, vf16, vf17
acc = vopmula(vf16, vf17);
// vopmsub.xyz vf18, vf17, vf16
math::Vector3f vf18 = vopmsub(acc, vf17, vf16);
// vmulax.xyzw acc, vf24, vf17
// vmadday.xyzw acc, vf25, vf17
// vmaddz.xyzw vf11, vf26, vf17
result[1] = vf17;
// vmulax.xyzw acc, vf24, vf18
// vmadday.xyzw acc, vf25, vf18
// vmaddz.xyzw vf12, vf26, vf18
result[2] = vf18;
return result;
//
// sqc2 vf10, -112(t8)
// sqc2 vf11, -96(t8)
// sqc2 vf12, -80(t8)
}
u32 pack_to_gl_normal(s16 nx, s16 ny, s16 nz) {
ASSERT(nx >= -512 && nx <= 511);
ASSERT(ny >= -512 && ny <= 511);
ASSERT(nz >= -512 && nz <= 511);
return (nx & 0x3ff) | ((ny & 0x3ff) << 10) | ((nz & 0x3ff) << 20);
}
/*!
* Unpack tie normal by transforming and converting to s16 for OpenGL.
*/
u32 unpack_tie_normal(const std::array<math::Vector3f, 3>& mat, s8 nx, s8 ny, s8 nz) {
// rotate the normal
math::Vector3f nrm = math::Vector3f::zero();
nrm += mat[0] * nx;
nrm += mat[1] * ny;
nrm += mat[2] * nz;
// convert to s16 for OpenGL renderer
// nrm /= 0x100; // number from EE asm
// nrm *= 0x200; // for normalized s10 -> float conversion by OpenGL.
nrm *= 2; // for normalized s10 -> float conversion by OpenGL.
auto as_int = nrm.cast<s16>();
return pack_to_gl_normal(as_int.x(), as_int.y(), as_int.z());
}
/*
void tie_normal_v3(__m128* out, const std::array<math::Vector4f, 4>& in) {
math::Vector3f x_row = in[0].xyz();
math::Vector3f y_row = in[1].xyz();
math::Vector3f z_row = in[2].xyz();
x_row.normalize();
y_row = x_row.cross(y_row.cross(x_row)).normalized();
z_row = x_row.cross(y_row);
out[0] = _mm_setr_ps(x_row[0], x_row[1], x_row[2], 0);
out[1] = _mm_setr_ps(y_row[0], y_row[1], y_row[2], 0);
out[2] = _mm_setr_ps(z_row[0], z_row[1], z_row[2], 0);
}
*/
void TieTree::unpack() {
unpacked.vertices.resize(packed_vertices.color_indices.size());
size_t i = 0;
@@ -84,25 +240,64 @@ void TieTree::unpack() {
vtx.x = proto_vtx.x;
vtx.y = proto_vtx.y;
vtx.z = proto_vtx.z;
vtx.q_unused = 1.f;
vtx.s = proto_vtx.s;
vtx.t = proto_vtx.t;
vtx.nor = pack_to_gl_normal(proto_vtx.nx << 1, proto_vtx.ny << 1, proto_vtx.nz << 1);
vtx.r = proto_vtx.r;
vtx.g = proto_vtx.g;
vtx.b = proto_vtx.b;
vtx.a = proto_vtx.a;
i++;
}
} else {
const auto& mat = packed_vertices.matrices[grp.matrix_idx];
for (u32 src_idx = grp.start_vert; src_idx < grp.end_vert; src_idx++) {
auto& vtx = unpacked.vertices[i];
vtx.color_index = packed_vertices.color_indices[i];
const auto& proto_vtx = packed_vertices.vertices[src_idx];
auto temp = mat[0] * proto_vtx.x + mat[1] * proto_vtx.y + mat[2] * proto_vtx.z + mat[3];
vtx.x = temp.x();
vtx.y = temp.y();
vtx.z = temp.z();
vtx.q_unused = 1.f;
vtx.s = proto_vtx.s;
vtx.t = proto_vtx.t;
i++;
__m128 mat0 = _mm_loadu_ps(mat[0].data());
__m128 mat1 = _mm_loadu_ps(mat[1].data());
__m128 mat2 = _mm_loadu_ps(mat[2].data());
__m128 mat3 = _mm_loadu_ps(mat[3].data());
if (grp.has_normals) {
auto nmat = tie_normal_transform_v2(mat);
for (u32 src_idx = grp.start_vert; src_idx < grp.end_vert; src_idx++) {
auto& vtx = unpacked.vertices[i];
vtx.color_index = packed_vertices.color_indices[i];
const auto& proto_vtx = packed_vertices.vertices[src_idx];
// auto temp = mat[0] * proto_vtx.x + mat[1] * proto_vtx.y + mat[2] * proto_vtx.z +
// mat[3];
__m128 transformed = mat3;
transformed = _mm_add_ps(transformed, _mm_mul_ps(_mm_set1_ps(proto_vtx.x), mat0));
transformed = _mm_add_ps(transformed, _mm_mul_ps(_mm_set1_ps(proto_vtx.y), mat1));
transformed = _mm_add_ps(transformed, _mm_mul_ps(_mm_set1_ps(proto_vtx.z), mat2));
_mm_storeu_ps(&vtx.x, transformed);
vtx.s = proto_vtx.s;
vtx.t = proto_vtx.t;
vtx.nor = unpack_tie_normal(nmat, proto_vtx.nx, proto_vtx.ny, proto_vtx.nz);
vtx.r = proto_vtx.r;
vtx.g = proto_vtx.g;
vtx.b = proto_vtx.b;
vtx.a = proto_vtx.a;
i++;
}
} else {
for (u32 src_idx = grp.start_vert; src_idx < grp.end_vert; src_idx++) {
auto& vtx = unpacked.vertices[i];
vtx.color_index = packed_vertices.color_indices[i];
const auto& proto_vtx = packed_vertices.vertices[src_idx];
__m128 transformed = mat3;
transformed = _mm_add_ps(transformed, _mm_mul_ps(_mm_set1_ps(proto_vtx.x), mat0));
transformed = _mm_add_ps(transformed, _mm_mul_ps(_mm_set1_ps(proto_vtx.y), mat1));
transformed = _mm_add_ps(transformed, _mm_mul_ps(_mm_set1_ps(proto_vtx.z), mat2));
_mm_storeu_ps(&vtx.x, transformed);
vtx.s = proto_vtx.s;
vtx.t = proto_vtx.t;
vtx.nor = 0;
vtx.r = proto_vtx.r;
vtx.g = proto_vtx.g;
vtx.b = proto_vtx.b;
vtx.a = proto_vtx.a;
i++;
}
}
}
}
@@ -159,7 +354,6 @@ void TfragTree::unpack() {
o.z = cz + in.zoff * rescale;
o.s = in.s / (1024.f);
o.t = in.t / (1024.f);
o.q_unused = 1.f;
o.color_index = in.color_index;
}
@@ -188,6 +382,8 @@ void TieTree::serialize(Serializer& ser) {
draw.serialize(ser);
}
ser.from_ptr(&category_draw_indices);
if (ser.is_saving()) {
ser.save<size_t>(instanced_wind_draws.size());
} else {
@@ -207,12 +403,15 @@ void TieTree::serialize(Serializer& ser) {
}
packed_vertices.serialize(ser);
ser.from_pod_vector(&colors);
colors.serialize(ser);
bvh.serialize(ser);
ser.from_ptr(&has_per_proto_visibility_toggle);
ser.from_string_vector(&proto_names);
}
void ShrubTree::serialize(Serializer& ser) {
ser.from_pod_vector(&time_of_day_colors);
time_of_day_colors.serialize(ser);
ser.from_pod_vector(&indices);
packed_vertices.serialize(ser);
if (ser.is_saving()) {
@@ -223,6 +422,33 @@ void ShrubTree::serialize(Serializer& ser) {
for (auto& draw : static_draws) {
draw.serialize(ser);
}
ser.from_ptr(&has_per_proto_visibility_toggle);
ser.from_string_vector(&proto_names);
}
void HfragmentBucket::serialize(Serializer& ser) {
ser.from_pod_vector(&corners);
ser.from_ptr(&montage_table);
}
void Hfragment::serialize(Serializer& ser) {
ser.from_pod_vector(&vertices);
ser.from_pod_vector(&indices);
ser.from_pod_vector(&corners);
if (ser.is_saving()) {
ser.save<size_t>(buckets.size());
} else {
buckets.resize(ser.load<size_t>());
}
for (auto& x : buckets) {
x.serialize(ser);
}
time_of_day_colors.serialize(ser);
ser.from_ptr(&wang_tree_tex_id);
ser.from_ptr(&draw_mode);
ser.from_ptr(&occlusion_offset);
}
void BVH::serialize(Serializer& ser) {
@@ -244,6 +470,17 @@ void Texture::serialize(Serializer& ser) {
ser.from_ptr(&load_to_pool);
}
void IndexTexture::serialize(Serializer& ser) {
ser.from_ptr(&w);
ser.from_ptr(&h);
ser.from_ptr(&combo_id);
ser.from_pod_vector(&index_data);
ser.from_ptr(&color_table);
ser.from_str(&name);
ser.from_str(&tpage_name);
ser.from_string_vector(&level_names);
}
void CollisionMesh::serialize(Serializer& ser) {
ser.from_pod_vector(&vertices);
}
@@ -251,20 +488,60 @@ void CollisionMesh::serialize(Serializer& ser) {
void MercDraw::serialize(Serializer& ser) {
ser.from_ptr(&mode);
ser.from_ptr(&tree_tex_id);
ser.from_ptr(&eye_id);
ser.from_ptr(&first_index);
ser.from_ptr(&index_count);
ser.from_ptr(&num_triangles);
ser.from_ptr(&no_strip);
}
void Blerc::serialize(Serializer& ser) {
ser.from_pod_vector(&float_data);
ser.from_pod_vector(&int_data);
}
void MercModifiableDrawGroup::serialize(Serializer& ser) {
if (ser.is_saving()) {
ser.save<size_t>(mod_draw.size());
} else {
mod_draw.resize(ser.load<size_t>());
}
for (auto& draw : mod_draw) {
draw.serialize(ser);
}
if (ser.is_saving()) {
ser.save<size_t>(fix_draw.size());
} else {
fix_draw.resize(ser.load<size_t>());
}
for (auto& draw : fix_draw) {
draw.serialize(ser);
}
ser.from_pod_vector(&vertices);
ser.from_pod_vector(&vertex_lump4_addr);
ser.from_pod_vector(&fragment_mask);
ser.from_ptr(&expect_vidx_end);
blerc.serialize(ser);
}
void MercEffect::serialize(Serializer& ser) {
if (ser.is_saving()) {
ser.save<size_t>(draws.size());
ser.save<size_t>(all_draws.size());
} else {
draws.resize(ser.load<size_t>());
all_draws.resize(ser.load<size_t>());
}
for (auto& draw : draws) {
for (auto& draw : all_draws) {
draw.serialize(ser);
}
mod.serialize(ser);
ser.from_ptr(&envmap_mode);
ser.from_ptr(&envmap_texture);
ser.from_ptr(&has_envmap);
ser.from_ptr(&has_mod_draw);
}
void MercModel::serialize(Serializer& ser) {
@@ -279,6 +556,9 @@ void MercModel::serialize(Serializer& ser) {
}
ser.from_ptr(&max_draws);
ser.from_ptr(&max_bones);
ser.from_ptr(&st_vif_add);
ser.from_ptr(&xyz_scale);
ser.from_ptr(&st_magic);
}
void MercModelGroup::serialize(Serializer& ser) {
@@ -314,6 +594,15 @@ void Level::serialize(Serializer& ser) {
tex.serialize(ser);
}
if (ser.is_saving()) {
ser.save<size_t>(index_textures.size());
} else {
index_textures.resize(ser.load<size_t>());
}
for (auto& tex : index_textures) {
tex.serialize(ser);
}
for (int geom = 0; geom < 3; ++geom) {
if (ser.is_saving()) {
ser.save<size_t>(tfrag_trees[geom].size());
@@ -345,6 +634,8 @@ void Level::serialize(Serializer& ser) {
tree.serialize(ser);
}
hfrag.serialize(ser);
collision.serialize(ser);
merc_data.serialize(ser);
@@ -356,109 +647,187 @@ void Level::serialize(Serializer& ser) {
}
}
std::array<int, MemoryUsageCategory::NUM_CATEGORIES> Level::get_memory_usage() const {
std::array<int, MemoryUsageCategory::NUM_CATEGORIES> result;
result.fill(0);
void MercModifiableDrawGroup::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::MERC_MOD_VERT, sizeof(MercVertex) * vertices.size());
tracker->add(MemoryUsageCategory::MERC_MOD_DRAW_1, sizeof(MercDraw) * fix_draw.size());
tracker->add(MemoryUsageCategory::MERC_MOD_DRAW_2, sizeof(MercDraw) * mod_draw.size());
tracker->add(MemoryUsageCategory::MERC_MOD_TABLE, sizeof(u16) * vertex_lump4_addr.size());
tracker->add(MemoryUsageCategory::BLERC, sizeof(BlercFloatData) * blerc.float_data.size());
tracker->add(MemoryUsageCategory::BLERC, sizeof(u32) * blerc.int_data.size());
}
// textures
for (const auto& tex : textures) {
result[TEXTURE] += tex.data.size() * sizeof(u32);
void MercEffect::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::MERC_DRAW, sizeof(MercDraw) * all_draws.size());
mod.memory_usage(tracker);
}
void MercModel::memory_usage(MemoryUsageTracker* tracker) const {
for (auto& effect : effects) {
effect.memory_usage(tracker);
}
}
// tfrag
for (const auto& tfrag_tree_geoms : tfrag_trees) {
for (const auto& tfrag_tree : tfrag_tree_geoms) {
for (const auto& draw : tfrag_tree.draws) {
result[TFRAG_INDEX] += draw.runs.size() * sizeof(StripDraw::VertexRun);
result[TFRAG_INDEX] += draw.plain_indices.size() * sizeof(u32);
result[TFRAG_VIS] += draw.vis_groups.size() * sizeof(StripDraw::VisGroup);
}
result[TFRAG_VERTS] +=
tfrag_tree.packed_vertices.vertices.size() * sizeof(PackedTfragVertices::Vertex);
result[TFRAG_CLUSTER] +=
tfrag_tree.packed_vertices.cluster_origins.size() * sizeof(math::Vector<u16, 3>);
result[TFRAG_TIME_OF_DAY] += tfrag_tree.colors.size() * sizeof(TimeOfDayColor);
result[TFRAG_BVH] += tfrag_tree.bvh.vis_nodes.size() * sizeof(VisNode);
void MercModelGroup::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::MERC_VERT, sizeof(MercVertex) * vertices.size());
tracker->add(MemoryUsageCategory::MERC_INDEX, sizeof(u32) * indices.size());
for (auto& model : models) {
model.memory_usage(tracker);
}
}
void CollisionMesh::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::COLLISION, sizeof(Vertex) * vertices.size());
}
void PackedShrubVertices::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::SHRUB_VERT, 64 * matrices.size());
tracker->add(MemoryUsageCategory::SHRUB_VERT, sizeof(InstanceGroup) * instance_groups.size());
tracker->add(MemoryUsageCategory::SHRUB_VERT, sizeof(Vertex) * vertices.size());
}
void ShrubTree::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::SHRUB_TIME_OF_DAY, sizeof(u8) * time_of_day_colors.data.size());
packed_vertices.memory_usage(tracker);
tracker->add(MemoryUsageCategory::SHRUB_DRAW, sizeof(ShrubDraw) * static_draws.size());
tracker->add(MemoryUsageCategory::SHRUB_IND, sizeof(u32) * indices.size());
}
void InstancedStripDraw::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::TIE_INST_INDEX, sizeof(u32) * vertex_index_stream.size());
tracker->add(MemoryUsageCategory::TIE_INST_VIS, sizeof(InstanceGroup) * instance_groups.size());
}
void PackedTieVertices::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::TIE_CIDX, sizeof(u16) * color_indices.size());
tracker->add(MemoryUsageCategory::TIE_MATRICES, 64 * matrices.size());
tracker->add(MemoryUsageCategory::TIE_GRPS, sizeof(MatrixGroup) * matrix_groups.size());
tracker->add(MemoryUsageCategory::TIE_VERTS, sizeof(Vertex) * vertices.size());
}
void TieTree::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::TIE_BVH, sizeof(VisNode) * bvh.vis_nodes.size());
for (auto& draw : static_draws) {
tracker->add(MemoryUsageCategory::TIE_DEINST_INDEX,
draw.runs.size() * sizeof(StripDraw::VertexRun));
tracker->add(MemoryUsageCategory::TIE_DEINST_INDEX, draw.plain_indices.size() * sizeof(u32));
tracker->add(MemoryUsageCategory::TIE_DEINST_VIS,
draw.vis_groups.size() * sizeof(StripDraw::VisGroup));
}
packed_vertices.memory_usage(tracker);
tracker->add(MemoryUsageCategory::TIE_TIME_OF_DAY, sizeof(u8) * colors.data.size());
for (auto& draw : instanced_wind_draws) {
draw.memory_usage(tracker);
}
tracker->add(MemoryUsageCategory::TIE_WIND_INSTANCE_INFO,
sizeof(TieWindInstance) * wind_instance_info.size());
}
void PackedTfragVertices::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::TFRAG_VERTS,
sizeof(PackedTfragVertices::Vertex) * vertices.size());
tracker->add(MemoryUsageCategory::TFRAG_CLUSTER,
sizeof(math::Vector<u16, 3>) * cluster_origins.size());
}
void TfragTree::memory_usage(MemoryUsageTracker* tracker) const {
for (auto& draw : draws) {
tracker->add(MemoryUsageCategory::TFRAG_INDEX, draw.runs.size() * sizeof(StripDraw::VertexRun));
tracker->add(MemoryUsageCategory::TFRAG_INDEX, draw.plain_indices.size() * sizeof(u32));
tracker->add(MemoryUsageCategory::TFRAG_VIS,
draw.vis_groups.size() * sizeof(StripDraw::VisGroup));
}
packed_vertices.memory_usage(tracker);
tracker->add(MemoryUsageCategory::TFRAG_TIME_OF_DAY, sizeof(u8) * colors.data.size());
tracker->add(MemoryUsageCategory::TFRAG_BVH, sizeof(VisNode) * bvh.vis_nodes.size());
}
void Texture::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::TEXTURE, data.size() * sizeof(u32));
}
void IndexTexture::memory_usage(MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::SPECIAL_TEXTURE, index_data.size());
tracker->add(MemoryUsageCategory::SPECIAL_TEXTURE, 256 * 4); // clut
}
void Hfragment::memory_usage(tfrag3::MemoryUsageTracker* tracker) const {
tracker->add(MemoryUsageCategory::HFRAG_VERTS, vertices.size() * sizeof(HfragmentVertex));
tracker->add(MemoryUsageCategory::HFRAG_INDEX, indices.size() * sizeof(u32));
tracker->add(MemoryUsageCategory::HFRAG_TIME_OF_DAY, time_of_day_colors.data.size() * sizeof(u8));
tracker->add(MemoryUsageCategory::HFRAG_CORNERS, corners.size() * sizeof(HfragmentCorner));
}
void Level::memory_usage(MemoryUsageTracker* tracker) const {
for (const auto& texture : textures) {
texture.memory_usage(tracker);
}
for (const auto& texture : index_textures) {
texture.memory_usage(tracker);
}
for (const auto& tftk : tfrag_trees) {
for (const auto& tree : tftk) {
tree.memory_usage(tracker);
}
}
// tie
for (const auto& tie_tree_geoms : tie_trees) {
for (const auto& tie_tree : tie_tree_geoms) {
result[TIE_BVH] += tie_tree.bvh.vis_nodes.size();
for (const auto& draw : tie_tree.static_draws) {
result[TIE_DEINST_INDEX] += draw.runs.size() * sizeof(StripDraw::VertexRun);
result[TIE_DEINST_VIS] += draw.vis_groups.size() * sizeof(StripDraw::VisGroup);
}
result[TIE_VERTS] +=
tie_tree.packed_vertices.vertices.size() * sizeof(PackedTieVertices::Vertex);
result[TIE_CIDX] += tie_tree.packed_vertices.color_indices.size() * sizeof(u16);
result[TIE_MATRICES] += tie_tree.packed_vertices.matrices.size() * 4 * 4 * 4;
result[TIE_GRPS] +=
tie_tree.packed_vertices.matrix_groups.size() * sizeof(PackedTieVertices::MatrixGroup);
result[TIE_TIME_OF_DAY] += tie_tree.colors.size() * sizeof(TimeOfDayColor);
for (const auto& draw : tie_tree.instanced_wind_draws) {
result[TIE_INST_INDEX] += draw.vertex_index_stream.size() * sizeof(u32);
result[TIE_INST_VIS] +=
draw.instance_groups.size() * sizeof(InstancedStripDraw::InstanceGroup);
}
result[TIE_WIND_INSTANCE_INFO] +=
tie_tree.wind_instance_info.size() * sizeof(TieWindInstance);
for (const auto& ttk : tie_trees) {
for (const auto& tree : ttk) {
tree.memory_usage(tracker);
}
}
// shrub
for (const auto& shrub_tree : shrub_trees) {
result[SHRUB_TIME_OF_DAY] += shrub_tree.time_of_day_colors.size() * sizeof(TimeOfDayColor);
result[SHRUB_VERT] += shrub_tree.packed_vertices.matrices.size() * 4 * 4 * 4;
result[SHRUB_VERT] +=
shrub_tree.packed_vertices.vertices.size() * sizeof(PackedShrubVertices::Vertex);
result[SHRUB_VERT] += shrub_tree.packed_vertices.instance_groups.size() *
sizeof(PackedShrubVertices::InstanceGroup);
result[SHRUB_IND] += sizeof(u32) * shrub_tree.indices.size();
for (const auto& tree : shrub_trees) {
tree.memory_usage(tracker);
}
// merc
result[MERC_INDEX] += merc_data.indices.size() * sizeof(u32);
result[MERC_VERT] += merc_data.vertices.size() * sizeof(MercVertex);
// collision
result[COLLISION] += sizeof(CollisionMesh::Vertex) * collision.vertices.size();
return result;
hfrag.memory_usage(tracker);
collision.memory_usage(tracker);
merc_data.memory_usage(tracker);
}
void print_memory_usage(const tfrag3::Level& lev, int uncompressed_data_size) {
int total_accounted = 0;
auto memory_use_by_category = lev.get_memory_usage();
MemoryUsageTracker mem_use;
lev.memory_usage(&mem_use);
std::vector<std::pair<std::string, int>> known_categories = {
{"texture", memory_use_by_category[tfrag3::MemoryUsageCategory::TEXTURE]},
{"tie-deinst-vis", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_DEINST_VIS]},
{"tie-deinst-idx", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_DEINST_INDEX]},
{"tie-inst-vis", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_INST_VIS]},
{"tie-inst-idx", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_INST_INDEX]},
{"tie-bvh", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_BVH]},
{"tie-verts", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_VERTS]},
{"tie-colors", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_TIME_OF_DAY]},
{"tie-wind-inst-info",
memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_WIND_INSTANCE_INFO]},
{"tie-cidx", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_CIDX]},
{"tie-mats", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_MATRICES]},
{"tie-grps", memory_use_by_category[tfrag3::MemoryUsageCategory::TIE_GRPS]},
{"tfrag-vis", memory_use_by_category[tfrag3::MemoryUsageCategory::TFRAG_VIS]},
{"tfrag-idx", memory_use_by_category[tfrag3::MemoryUsageCategory::TFRAG_INDEX]},
{"tfrag-vert", memory_use_by_category[tfrag3::MemoryUsageCategory::TFRAG_VERTS]},
{"tfrag-colors", memory_use_by_category[tfrag3::MemoryUsageCategory::TFRAG_TIME_OF_DAY]},
{"tfrag-cluster", memory_use_by_category[tfrag3::MemoryUsageCategory::TFRAG_CLUSTER]},
{"tfrag-bvh", memory_use_by_category[tfrag3::MemoryUsageCategory::TFRAG_BVH]},
{"shrub-colors", memory_use_by_category[tfrag3::MemoryUsageCategory::SHRUB_TIME_OF_DAY]},
{"shrub-vert", memory_use_by_category[tfrag3::MemoryUsageCategory::SHRUB_VERT]},
{"shrub-ind", memory_use_by_category[tfrag3::MemoryUsageCategory::SHRUB_IND]},
{"collision", memory_use_by_category[tfrag3::MemoryUsageCategory::COLLISION]},
{"merc-vert", memory_use_by_category[tfrag3::MemoryUsageCategory::MERC_VERT]},
{"merc-idx", memory_use_by_category[tfrag3::MemoryUsageCategory::MERC_INDEX]}};
{"texture", mem_use.data[tfrag3::MemoryUsageCategory::TEXTURE]},
{"special-texture", mem_use.data[tfrag3::MemoryUsageCategory::SPECIAL_TEXTURE]},
{"tie-deinst-vis", mem_use.data[tfrag3::MemoryUsageCategory::TIE_DEINST_VIS]},
{"tie-deinst-idx", mem_use.data[tfrag3::MemoryUsageCategory::TIE_DEINST_INDEX]},
{"tie-inst-vis", mem_use.data[tfrag3::MemoryUsageCategory::TIE_INST_VIS]},
{"tie-inst-idx", mem_use.data[tfrag3::MemoryUsageCategory::TIE_INST_INDEX]},
{"tie-bvh", mem_use.data[tfrag3::MemoryUsageCategory::TIE_BVH]},
{"tie-verts", mem_use.data[tfrag3::MemoryUsageCategory::TIE_VERTS]},
{"tie-colors", mem_use.data[tfrag3::MemoryUsageCategory::TIE_TIME_OF_DAY]},
{"tie-wind-inst-info", mem_use.data[tfrag3::MemoryUsageCategory::TIE_WIND_INSTANCE_INFO]},
{"tie-cidx", mem_use.data[tfrag3::MemoryUsageCategory::TIE_CIDX]},
{"tie-mats", mem_use.data[tfrag3::MemoryUsageCategory::TIE_MATRICES]},
{"tie-grps", mem_use.data[tfrag3::MemoryUsageCategory::TIE_GRPS]},
{"tfrag-vis", mem_use.data[tfrag3::MemoryUsageCategory::TFRAG_VIS]},
{"tfrag-idx", mem_use.data[tfrag3::MemoryUsageCategory::TFRAG_INDEX]},
{"tfrag-vert", mem_use.data[tfrag3::MemoryUsageCategory::TFRAG_VERTS]},
{"tfrag-colors", mem_use.data[tfrag3::MemoryUsageCategory::TFRAG_TIME_OF_DAY]},
{"tfrag-cluster", mem_use.data[tfrag3::MemoryUsageCategory::TFRAG_CLUSTER]},
{"tfrag-bvh", mem_use.data[tfrag3::MemoryUsageCategory::TFRAG_BVH]},
{"shrub-colors", mem_use.data[tfrag3::MemoryUsageCategory::SHRUB_TIME_OF_DAY]},
{"shrub-vert", mem_use.data[tfrag3::MemoryUsageCategory::SHRUB_VERT]},
{"shrub-ind", mem_use.data[tfrag3::MemoryUsageCategory::SHRUB_IND]},
{"shrub-draw", mem_use.data[tfrag3::MemoryUsageCategory::SHRUB_DRAW]},
{"collision", mem_use.data[tfrag3::MemoryUsageCategory::COLLISION]},
{"merc-vert", mem_use.data[tfrag3::MemoryUsageCategory::MERC_VERT]},
{"merc-idx", mem_use.data[tfrag3::MemoryUsageCategory::MERC_INDEX]},
{"merc-draw", mem_use.data[tfrag3::MemoryUsageCategory::MERC_DRAW]},
{"merc-mod-vert", mem_use.data[tfrag3::MemoryUsageCategory::MERC_MOD_VERT]},
{"merc-mod-ind", mem_use.data[tfrag3::MemoryUsageCategory::MERC_MOD_IND]},
{"merc-mod-table", mem_use.data[tfrag3::MemoryUsageCategory::MERC_MOD_TABLE]},
{"merc-mod-draw-1", mem_use.data[tfrag3::MemoryUsageCategory::MERC_MOD_DRAW_1]},
{"merc-mod-draw-2", mem_use.data[tfrag3::MemoryUsageCategory::MERC_MOD_DRAW_2]},
{"blerc", mem_use.data[tfrag3::MemoryUsageCategory::BLERC]},
{"hfrag-verts", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_VERTS]},
{"hfrag-index", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_INDEX]},
{"hfrag-time-of-day", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_TIME_OF_DAY]},
{"hfrag-corners", mem_use.data[tfrag3::MemoryUsageCategory::HFRAG_CORNERS]}
};
for (auto& known : known_categories) {
total_accounted += known.second;
}
@@ -469,8 +838,10 @@ void print_memory_usage(const tfrag3::Level& lev, int uncompressed_data_size) {
[](const auto& a, const auto& b) { return a.second > b.second; });
for (const auto& x : known_categories) {
fmt::print("{:30s} : {:6d} kB {:3.1f}%\n", x.first, x.second / 1024,
100.f * (float)x.second / uncompressed_data_size);
if (x.second) {
lg::print("{:30s} : {:6d} kB {:3.1f}%\n", x.first, x.second / 1024,
100.f * (float)x.second / uncompressed_data_size);
}
}
}
+250 -35
View File
@@ -18,9 +18,13 @@ namespace tfrag3 {
// - if changing any large things (vertices, vis, bvh, colors, textures) update get_memory_usage
// - if adding a new category to the memory usage, update extract_level to print it.
constexpr int TFRAG3_VERSION = 41;
enum MemoryUsageCategory {
TEXTURE,
SPECIAL_TEXTURE,
TIE_DEINST_VIS,
TIE_DEINST_INDEX,
TIE_INST_VIS,
@@ -44,26 +48,56 @@ enum MemoryUsageCategory {
SHRUB_TIME_OF_DAY,
SHRUB_VERT,
SHRUB_IND,
SHRUB_DRAW,
MERC_VERT,
MERC_INDEX,
MERC_DRAW,
MERC_MOD_DRAW_1,
MERC_MOD_DRAW_2,
MERC_MOD_VERT,
MERC_MOD_IND,
MERC_MOD_TABLE,
BLERC,
HFRAG_VERTS,
HFRAG_INDEX,
HFRAG_TIME_OF_DAY,
HFRAG_CORNERS,
COLLISION,
NUM_CATEGORIES
};
constexpr int TFRAG3_VERSION = 21;
struct MemoryUsageTracker {
u32 data[MemoryUsageCategory::NUM_CATEGORIES];
MemoryUsageTracker() {
for (auto& x : data) {
x = 0;
}
}
void add(MemoryUsageCategory category, u32 size_bytes) { data[category] += size_bytes; }
};
// These vertices should be uploaded to the GPU at load time and don't change
struct PreloadedVertex {
// the vertex position
float x, y, z;
float x = 0, y = 0, z = 0;
// envmap tint color, not used in == or hash.
u8 r = 0, g = 0, b = 0, a = 0;
// texture coordinates
float s, t, q_unused;
float s = 0, t = 0;
// not used in == or hash!!
// note that this is a 10-bit 3-element field packed into 32-bits.
u32 nor = 0;
// color table index
u16 color_index;
u16 pad[3];
u16 color_index = 0;
struct hash {
std::size_t operator()(const PreloadedVertex& x) const;
@@ -80,12 +114,15 @@ struct PackedTieVertices {
struct Vertex {
float x, y, z;
float s, t;
s8 nx, ny, nz;
u8 r, g, b, a;
};
struct MatrixGroup {
s32 matrix_idx;
u32 start_vert;
u32 end_vert;
bool has_normals = false;
};
std::vector<u16> color_indices;
@@ -93,6 +130,7 @@ struct PackedTieVertices {
std::vector<MatrixGroup> matrix_groups; // todo pack
std::vector<Vertex> vertices;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
struct PackedTfragVertices {
@@ -102,7 +140,7 @@ struct PackedTfragVertices {
s16 s, t;
u16 color_index;
};
void memory_usage(MemoryUsageTracker* tracker) const;
std::vector<Vertex> vertices;
std::vector<math::Vector<u16, 3>> cluster_origins;
};
@@ -135,7 +173,7 @@ struct PackedShrubVertices {
std::vector<InstanceGroup> instance_groups; // todo pack
std::vector<Vertex> vertices;
u32 total_vertex_count;
void memory_usage(MemoryUsageTracker* tracker) const;
void serialize(Serializer& ser);
};
@@ -147,7 +185,7 @@ struct PackedShrubVertices {
// check visibility.
struct StripDraw {
DrawMode mode; // the OpenGL draw settings.
u32 tree_tex_id = 0; // the texture that should be bound for the draw
s32 tree_tex_id = 0; // the texture that should be bound for the draw (negative for anim slot)
struct {
u32 idx_of_first_idx_in_full_buffer = 0;
@@ -167,7 +205,8 @@ struct StripDraw {
struct VisGroup {
u32 num_inds = 0; // number of vertex indices in this group
u32 num_tris = 0; // number of triangles
u32 vis_idx_in_pc_bvh = 0; // the visibility group they belong to (in BVH)
u16 vis_idx_in_pc_bvh = 0; // the visibility group they belong to (in BVH)
u16 tie_proto_idx = 0; // index of tie proto (tie only)
};
std::vector<VisGroup> vis_groups;
@@ -185,6 +224,8 @@ struct ShrubDraw {
// for debug counting.
u32 num_triangles = 0;
u16 proto_idx = 0;
void serialize(Serializer& ser);
};
@@ -207,6 +248,7 @@ struct InstancedStripDraw {
// for debug counting.
u32 num_triangles = 0;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
// node in the BVH.
@@ -232,18 +274,23 @@ struct BVH {
void serialize(Serializer& ser);
};
// A time-of-day color. Each stores 8 colors. At a given "time of day", they are interpolated
// to find a single color which goes into a color palette.
struct TimeOfDayColor {
math::Vector<u8, 4> rgba[8];
// This is split into groups of 4 colors.
// The data in these groups is stored first by palette, then color, then channel.
struct PackedTimeOfDay {
std::vector<u8> data;
u32 color_count = 0;
void serialize(Serializer& ser);
bool operator==(const TimeOfDayColor& other) const {
for (size_t i = 0; i < 8; i++) {
if (rgba[i] != other.rgba[i]) {
return false;
}
}
return true;
u8 read(int color, int palette, int channel) const {
const int color_quad = color / 4;
const int color_in_quad = color % 4;
return data[color_quad * 4 * 4 * 8 + palette * 4 * 4 + color_in_quad * 4 + channel];
}
u8& read(int color, int palette, int channel) {
const int color_quad = color / 4;
const int color_in_quad = color % 4;
return data[color_quad * 4 * 4 * 8 + palette * 4 * 4 + color_in_quad * 4 + channel];
}
};
@@ -256,21 +303,34 @@ struct Texture {
std::string debug_tpage_name;
bool load_to_pool = false;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
struct IndexTexture {
u16 w, h;
u32 combo_id = 0;
std::vector<u8> index_data;
std::vector<std::string> level_names;
std::string name;
std::string tpage_name;
std::array<math::Vector4<u8>, 256> color_table;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
// Tfrag trees have several kinds:
enum class TFragmentTreeKind { NORMAL, TRANS, DIRT, ICE, LOWRES, LOWRES_TRANS, INVALID };
enum class TFragmentTreeKind { NORMAL, TRANS, DIRT, ICE, LOWRES, LOWRES_TRANS, WATER, INVALID };
constexpr const char* tfrag_tree_names[] = {"normal", "trans", "dirt", "ice",
"lowres", "lowres-trans", "invalid"};
constexpr const char* tfrag_tree_names[] = {"normal", "trans", "dirt", "ice",
"lowres", "lowres-trans", "water", "invalid"};
// A tfrag model
struct TfragTree {
TFragmentTreeKind kind; // our tfrag kind
std::vector<StripDraw> draws; // the actual topology and settings
PackedTfragVertices packed_vertices;
std::vector<TimeOfDayColor> colors; // vertex colors (pre-interpolation)
BVH bvh; // the bvh for frustum culling
PackedTimeOfDay colors; // vertex colors (pre-interpolation)
BVH bvh; // the bvh for frustum culling
bool use_strips = true;
struct {
@@ -279,6 +339,7 @@ struct TfragTree {
} unpacked;
void unpack();
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
struct TieWindInstance {
@@ -288,29 +349,90 @@ struct TieWindInstance {
void serialize(Serializer& ser);
};
// Tie draws are split into categories.
enum class TieCategory {
// normal tie buckets
NORMAL,
TRANS, // also called alpha
WATER,
// first draw (normal base draw) for envmapped stuff
NORMAL_ENVMAP,
TRANS_ENVMAP,
WATER_ENVMAP,
// second draw (shiny) for envmapped ties.
NORMAL_ENVMAP_SECOND_DRAW,
TRANS_ENVMAP_SECOND_DRAW,
WATER_ENVMAP_SECOND_DRAW,
};
constexpr int kNumTieCategories = 9;
constexpr bool is_envmap_first_draw_category(tfrag3::TieCategory category) {
switch (category) {
case tfrag3::TieCategory::NORMAL_ENVMAP:
case tfrag3::TieCategory::WATER_ENVMAP:
case tfrag3::TieCategory::TRANS_ENVMAP:
return true;
default:
return false;
}
}
constexpr bool is_envmap_second_draw_category(tfrag3::TieCategory category) {
switch (category) {
case tfrag3::TieCategory::NORMAL_ENVMAP_SECOND_DRAW:
case tfrag3::TieCategory::WATER_ENVMAP_SECOND_DRAW:
case tfrag3::TieCategory::TRANS_ENVMAP_SECOND_DRAW:
return true;
default:
return false;
}
}
constexpr TieCategory get_second_draw_category(tfrag3::TieCategory category) {
switch (category) {
case TieCategory::NORMAL_ENVMAP:
return TieCategory::NORMAL_ENVMAP_SECOND_DRAW;
case TieCategory::TRANS_ENVMAP:
return TieCategory::TRANS_ENVMAP_SECOND_DRAW;
case TieCategory::WATER_ENVMAP:
return TieCategory::WATER_ENVMAP_SECOND_DRAW;
default:
return TieCategory::NORMAL_ENVMAP;
}
}
// A tie model
struct TieTree {
BVH bvh;
std::vector<StripDraw> static_draws; // the actual topology and settings
std::vector<StripDraw> static_draws;
// Category n uses draws: static_draws[cdi[n]] to static_draws[cdi[n + 1]]
std::array<u32, kNumTieCategories + 1> category_draw_indices;
PackedTieVertices packed_vertices;
std::vector<TimeOfDayColor> colors; // vertex colors (pre-interpolation)
PackedTimeOfDay colors; // vertex colors (pre-interpolation)
std::vector<InstancedStripDraw> instanced_wind_draws;
std::vector<TieWindInstance> wind_instance_info;
// jak 2 and later can toggle on and off visibility per proto by name
bool has_per_proto_visibility_toggle = false;
std::vector<std::string> proto_names;
struct {
std::vector<PreloadedVertex> vertices; // mesh vertices
std::vector<u32> indices;
} unpacked;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
void unpack();
};
struct ShrubTree {
// todo some visibility structure
std::vector<TimeOfDayColor> time_of_day_colors; // multiplier colors
PackedTimeOfDay time_of_day_colors; // multiplier colors
PackedShrubVertices packed_vertices;
std::vector<ShrubDraw> static_draws; // the actual topology and settings
@@ -320,10 +442,52 @@ struct ShrubTree {
std::vector<ShrubGpuVertex> vertices; // mesh vertices
} unpacked;
// jak 2 and later can toggle on and off visibility per proto by name
bool has_per_proto_visibility_toggle = false;
std::vector<std::string> proto_names;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
void unpack();
};
struct HfragmentVertex {
float height = 0;
u32 vi = 0;
u16 color_index = 0;
u8 u = 0, v = 0;
u32 pad = 0;
};
struct HfragmentCorner {
math::Vector<float, 4> bsphere;
u32 vis_id = 0;
u32 index_start = 0;
u32 index_length = 0;
u32 num_tris = 0;
};
struct HfragmentBucket {
std::vector<u32> corners;
std::array<u16, 16> montage_table;
void serialize(Serializer& ser);
};
struct Hfragment {
std::vector<HfragmentVertex> vertices;
std::vector<u32> indices;
std::vector<HfragmentCorner> corners;
std::vector<HfragmentBucket> buckets;
PackedTimeOfDay time_of_day_colors;
std::array<s32, 4> wang_tree_tex_id;
DrawMode draw_mode;
u32 occlusion_offset;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
struct CollisionMesh {
struct Vertex {
float x, y, z;
@@ -336,12 +500,13 @@ struct CollisionMesh {
static_assert(sizeof(Vertex) == 32);
std::vector<Vertex> vertices;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
// MERC
struct MercVertex {
float pos[3];
alignas(32) float pos[3];
float pad0;
float normal[3];
@@ -360,17 +525,61 @@ static_assert(sizeof(MercVertex) == 64);
struct MercDraw {
DrawMode mode;
u32 tree_tex_id = 0; // the texture that should be bound for the draw
s32 tree_tex_id = 0; // the texture that should be bound for the draw (negative for anim slot)
u8 eye_id = 0xff; // 0xff if not eyes, (slot << 1) | (is_r)
u32 first_index;
u32 index_count;
u32 num_triangles;
// no strip hack for custom models
bool no_strip = false;
void serialize(Serializer& ser);
};
struct MercEffect {
std::vector<MercDraw> draws;
struct BlercFloatData {
// [x, y, z, pad, nx, ny, nz, pad]
// note that this should match the layout of the merc vertex above
alignas(32) float v[8];
};
/*!
* Data to modify vertices based on blend shapes.
*/
struct Blerc {
std::vector<BlercFloatData> float_data;
std::vector<u32> int_data;
static constexpr u32 kTargetIdxTerminator = UINT32_MAX;
void serialize(Serializer& ser);
// int data, per vertex:
// [tgt0_idx, tgt1_idx, ..., terminator, dest]
// float data, per vertex:
// [base, tgt0, tgt1, ...]
// final vertex position is:
// base + sum(tgtn * weights[tgtn_idx])
};
struct MercModifiableDrawGroup {
std::vector<MercVertex> vertices;
std::vector<u16> vertex_lump4_addr;
std::vector<MercDraw> fix_draw, mod_draw;
std::vector<u8> fragment_mask;
Blerc blerc;
u32 expect_vidx_end = 0;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
struct MercEffect {
std::vector<MercDraw> all_draws;
MercModifiableDrawGroup mod;
DrawMode envmap_mode;
u32 envmap_texture;
bool has_envmap = false;
bool has_mod_draw = false;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
struct MercModel {
@@ -378,7 +587,11 @@ struct MercModel {
std::vector<MercEffect> effects;
u32 max_draws;
u32 max_bones;
u32 st_vif_add;
float xyz_scale;
float st_magic;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
struct MercModelGroup {
@@ -386,6 +599,7 @@ struct MercModelGroup {
std::vector<u32> indices;
std::vector<MercModel> models;
void serialize(Serializer& ser);
void memory_usage(MemoryUsageTracker* tracker) const;
};
//
@@ -397,15 +611,16 @@ struct Level {
u16 version = TFRAG3_VERSION;
std::string level_name;
std::vector<Texture> textures;
std::vector<IndexTexture> index_textures;
std::array<std::vector<TfragTree>, TFRAG_GEOS> tfrag_trees;
std::array<std::vector<TieTree>, TIE_GEOS> tie_trees;
std::vector<ShrubTree> shrub_trees;
Hfragment hfrag;
CollisionMesh collision;
MercModelGroup merc_data;
u16 version2 = TFRAG3_VERSION;
void serialize(Serializer& ser);
std::array<int, MemoryUsageCategory::NUM_CATEGORIES> get_memory_usage() const;
void memory_usage(MemoryUsageTracker* tracker) const;
};
void print_memory_usage(const tfrag3::Level& lev, int uncompressed_data_size);
+4 -2
View File
@@ -2,13 +2,15 @@
#include <map>
#include "common/log/log.h"
constexpr float kClusterSize = 4096 * 40; // 100 in-game meters
constexpr float kMasterOffset = 12000 * 4096;
std::pair<u64, u16> position_to_cluster_and_offset(float in) {
in += kMasterOffset;
if (in < 0) {
fmt::print("negative: {}\n", in);
lg::print("negative: {}\n", in);
}
ASSERT(in >= 0);
int cluster_cell = (in / kClusterSize);
@@ -69,4 +71,4 @@ void pack_tfrag_vertices(tfrag3::PackedTfragVertices* result,
}
ASSERT(next_cluster_idx < UINT16_MAX);
}
}
+1 -1
View File
@@ -2,7 +2,7 @@
#include "common/util/Assert.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
std::string DmaTag::print() {
std::string result;
+2 -1
View File
@@ -11,7 +11,7 @@
#include "common/common_types.h"
#include "common/util/Assert.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
struct DmaStats {
double sync_time_ms = 0;
@@ -113,6 +113,7 @@ struct VifCode {
ITOP = 0b100,
STMOD = 0b101,
PC_PORT = 0b1000, // not a valid PS2 VIF code, but we use this to signal PC-PORT specific stuff
PC_PORT2 = 0b1001,
MSK3PATH = 0b110,
MARK = 0b111,
FLUSHE = 0b10000,
+11
View File
@@ -106,6 +106,17 @@ class DmaFollower {
return result;
}
DmaTransfer advance_and_print_dma(DmaFollower& dma) {
auto data = dma.read_and_advance();
printf(
"dma transfer:\n%ssize: %d\nvif0: %s, data: %d\nvif1: %s, data: %d, imm: "
"%d\n\n",
dma.current_tag().print().c_str(), data.size_bytes, data.vifcode0().print().c_str(),
data.vif0(), data.vifcode1().print().c_str(), data.vifcode1().num,
data.vifcode1().immediate);
return data;
}
DmaTag current_tag() const { return DmaTag(read_val<u64>(m_tag_offset)); }
u32 current_tag_vif0() const { return read_val<u32>(m_tag_offset + 8); }
u32 current_tag_vif1() const { return read_val<u32>(m_tag_offset + 12); }
+13 -12
View File
@@ -3,9 +3,10 @@
#include "common/dma/dma_chain_read.h"
#include "common/goal_constants.h"
#include "common/log/log.h"
#include "common/util/Timer.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
/*!
* Convert a DMA chain to an array of bytes that can be directly fed to VIF.
@@ -36,11 +37,11 @@ void diff_dma_chains(DmaFollower ref, DmaFollower dma) {
auto ref_tag = ref.current_tag();
auto dma_tag = dma.current_tag();
if (ref_tag.kind != dma_tag.kind) {
fmt::print("Bad dma tag kinds\n");
lg::warn("Bad dma tag kinds");
}
if (ref_tag.qwc != dma_tag.qwc) {
fmt::print("Bad dma tag qwc: {} {}\n", ref_tag.qwc, dma_tag.qwc);
lg::warn("Bad dma tag qwc: {} {}", ref_tag.qwc, dma_tag.qwc);
}
auto ref_result = ref.read_and_advance();
@@ -48,19 +49,19 @@ void diff_dma_chains(DmaFollower ref, DmaFollower dma) {
for (int i = 0; i < (int)ref_result.size_bytes; i++) {
if (ref_result.data[i] != dma_result.data[i]) {
fmt::print("Bad data ({} vs {}) at {} into transfer: {} {}\n", ref_result.data[i],
dma_result.data[i], i, ref_tag.print(), dma_tag.print());
lg::error("Bad data ({} vs {}) at {} into transfer: {} {}", ref_result.data[i],
dma_result.data[i], i, ref_tag.print(), dma_tag.print());
return;
}
}
}
if (!ref.ended()) {
fmt::print("dma ended early\n");
lg::warn("dma ended early");
}
if (!dma.ended()) {
fmt::print("dma had extra data\n");
lg::warn("dma had extra data");
}
}
@@ -175,12 +176,12 @@ const DmaData& FixedChunkDmaCopier::run(const void* memory, u32 offset, bool ver
auto v2 = flatten_dma(DmaFollower(m_result.data.data(), m_result.start_offset));
if (ref != v2) {
fmt::print("Verification has failed.\n");
fmt::print("size diff: {} {}\n", ref.size(), v2.size());
lg::error("Verification has failed.");
lg::error("size diff: {} {}", ref.size(), v2.size());
for (size_t i = 0; i < std::min(ref.size(), v2.size()); i++) {
if (ref[i] != v2[i]) {
fmt::print("first diff at {}\n", i);
lg::error("first diff at {}", i);
break;
}
}
@@ -188,10 +189,10 @@ const DmaData& FixedChunkDmaCopier::run(const void* memory, u32 offset, bool ver
DmaFollower(m_result.data.data(), m_result.start_offset));
ASSERT(false);
} else {
fmt::print("verification ok: {} bytes\n", ref.size());
lg::debug("verification ok: {} bytes", ref.size());
}
}
m_result.stats.sync_time_ms = timer.getMs();
return m_result;
}
}
+8 -4
View File
@@ -2,7 +2,8 @@
#include "common/util/Assert.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
#include "fmt/format.h"
std::string reg_descriptor_name(GifTag::RegisterDescriptor reg) {
switch (reg) {
@@ -275,6 +276,7 @@ std::string GsTest::print() const {
ASSERT(false);
}
}
result += '\n';
return result;
}
@@ -352,15 +354,17 @@ std::string GsTexa::print() const {
std::string GsTex0::print() const {
return fmt::format(
"tbp0: {} tbw: {} psm: {} tw: {} th: {} tcc: {} tfx: {} cbp: {} cpsm: {} csm: {}\n", tbp0(),
tbw(), psm(), tw(), th(), tcc(), tfx(), cbp(), cpsm(), csm());
tbw(), fmt::underlying(psm()), tw(), th(), tcc(), fmt::underlying(tfx()), cbp(), cpsm(),
csm());
}
std::string GsPrim::print() const {
return fmt::format("0x{:x}, kind {}\n", data, kind());
return fmt::format("0x{:x}, kind {}\n", data, fmt::underlying(kind()));
}
std::string GsFrame::print() const {
return fmt::format("fbp: {} fbw: {} psm: {} fbmsk: {:x}\n", fbp(), fbw(), psm(), fbmsk());
return fmt::format("fbp: {} fbw: {} psm: {} fbmsk: {:x}\n", fbp(), fbw(), fmt::underlying(psm()),
fbmsk());
}
std::string GsXYOffset::print() const {
+1 -1
View File
@@ -424,7 +424,7 @@ class DrawMode {
SRC_DST_FIX_DST = 4, // fix = 64
ZERO_SRC_SRC_DST = 5,
SRC_SRC_SRC_SRC = 6,
SRC_0_DST_DST = 7
SRC_0_DST_DST = 7 // Note: requires color_mult tricks
};
enum class AlphaTest {
+185
View File
@@ -0,0 +1,185 @@
# OpenGOAL Formatter Documentation
> [!IMPORTANT]
> This is still in a highly experimental state, adjust your expectations accordingly.
Despite LISP being very simple, and taking the stance of a highly opinionated formatter that doesn't concern itself with line-length in most situations writing a code formatter is still an incredibly annoying and difficult thing to do. This documentation serves as a place for me to collect my thoughts and explain how it works (or more likely, how it does not).
Also in general I found it _really_ hard to find modern and easy to understand articles on how to get started (with the exception of zprint's usage docs, but that doesn't really cover implementation ideas). This area is either dominated by 40 year old journal articles, or discussions around really difficult formatting projects. There isn't a whole lot in the vain of _here's how I made a decent, simple formatter_, so maybe it'll help someone else (even if it's teaching them potentially what not to do!)
## Architecture / Overview
Atleast for me, it helps to understand the path code takes as it flows through the formatting process. Originally I tried to do as much at once for sake of efficiency but this just makes things incredibly hard to reason about and fix bugs. So like any problem that is complex, break it down, the formatter goes through many distinct phases chipping away at the problem:
```mermaid
flowchart TB
subgraph top1 [Build a Formatting Tree]
direction TB
a1(AST Parse) --> a2(Consolidate AST Nodes)
a1 --> a3(Collect Metadata)
end
subgraph top2 [Apply Formatting Configuration]
direction TB
b1(Recursively Iterate each Node) --> b2{Form head has\na predefined config?}
b2 --> |yes|b3(Fetch it and set the config on the node)
b2 --> |no|b4(Apply a default configuration)
end
subgraph top3 [Apply Formatting]
direction TB
c1(For each node, recursively build up a\nlist of source code lines, no indentation) --> c2(Consolidate the first two lines if hanging\nor if the config demands it)
c2 --> c3(Append indentation to each line as appropriate\nand surround each form with relevant parens)
end
subgraph top4 [Finalize Lines]
direction TB
d1(Concatenate all lines with whatever\nfile ending the file started with) --> d2(If we're formatting a file append a trailing new-line\n otherwise we are done)
end
top1-->|FormatterTree|top2
top2-->|FormatterTree with Configurations|top3
top3-->|String List|top4
```
### Build a Formatting Tree
At the end of the day, formatting is about changing the location and amounts of white-space in a file. Meaning it would be ideal if we could start with a representation that is whitespace-agnostic. Some formatters (like cljfmt) choose to use the original whitespace as an input into the formatting process, essentially meaning that your code should already be somewhat-formatted. This is somewhat advantageous as it can simplify the formatter's implementation or be a bit more flexible as to what the original programmer intended (assuming they knew what they were doing). But of course it has one fatal flaw -- the code has to already be well formatted.
For our formatter I wanted it to be able to take in horribly, ugly, minified code and output an optimal result -- especially since so much of our code gets spat out by another tool. To do that, we need to be able to format the code without any existing whitespace helping us, adding in the whitespace from the ground up.
The easiest way to do this is to construct an AST of the language which has a lot of other benefits for building language features but for here all we care about is getting rid of the whitespace and having some basic interpretation of the source code structure. The easiest way now-a-days to make an AST for a language is to create a [treesitter grammar](https://github.com/open-goal/tree-sitter-opengoal).
#### Consolidate AST Nodes and Collect Metadata
One downside with using an AST, atleast with the way the grammar is currently implemented is it creates a somewhat difficult tree to work with from a formatting perspective. For example in a LISP, everything is a list. In our AST it does not look like how you may intuitively expect:
`(+ 1 2)`
```mermaid
flowchart TB
a("source\n(+ 1 2)") --> b("list_lit\n")
b --> c("(") --> ca("(")
b --> d("sym_lit\n+") --> da("+")
b --> e("sym_lit\n1") --> ea("1")
b --> f("sym_lit\n2") --> fa("2")
b --> g(")") --> ga(")")
```
vs what you would probably prefer:
```mermaid
flowchart TB
a("top-level") --> b("list\n- surrounded in ()")
b --> da("+")
b --> ea("1")
b --> fa("2")
```
As you can see from even this simple example, the AST representation can be very verbose and in a sense has duplication. Each node is aware of it's original location in the parsed source-code, but it's the leaf-node tokens that we care about for formatting and perhaps the form types they were a part of (ie. were they comments or in a list, etc).
So to keep things brief, the AST representation is a bit too cumbersome and superfluous to use for formatting directly. So the first step is recurse through it and optimize it, removing unneeded height and capturing crucial metadata that is actually relevant for formatting.
We build a `FormatterTree` which consists of `FormatterNode`s. Each `FormatterNode` has either a single token, or a list of `refs`. A `ref` is just another `FormatterNode`. Each node also has a bunch of metadata and configuration on how it should be formatted (just initialized for now).
Having a dead-simple representation of the code like this is really only possible because it's a LISP, but it's also future proofed for us. If OpenGOAL ever decides to support different brackets -- for example in Clojure a vector uses `[]` or a map uses `{}` it would be easy for update the formatter to wrap each list node in the right bracket type.
### Applying Formatting Configuration
Now that we have our simplified tree, we can get to actually formatting. The first step is to figure out _how_ we intend to format things. By separating this from the actual formatting it's a lot easier to reason about and find bugs. You can also do potentially interesting things, where you do a full traversal of your source-code tree to figure out an optimal decision without trying to build up the final formatted string at the same time.
It is lists, or `form`s that we care about figuring out how to format. Each `form` has a head element (unless it's empty) that we can use to specify how it would be formatted. For example we cannot specify the formatting for every single function name, but we can format a `defun` or a `let` in a special way. With this mechanism, the formatter is easily extensible and configurable. There is even the ability to specify formatting configuration for a list's children by index -- for example you may want to format the first element in a `let` (the binding list) differently than the rest of the code.
There are also some forms that don't have a head-item, that we still identify and set some default formatting rules:
- The top-level node - indentation is disabled
- Lists of only literals, called `constant lists` - These are indented with `1` space instead of the default `2` for a `flow`'d form.
- If these lists literals are paired with keywords we call these `constant pairs` - We strive to put the pairs on the same line, if they are too long we spill to the next with `2` space indentation
- TODO - cond/case pairs (similar to constant pairs)
This brings up two important terms that you will see in the formatter implementation a lot -- `flow` and `hang`. The difference is as such:
```clj
(println "this"
"form"
"is"
"hung / hanged")
```
```clj
(println
"this"
"form"
"is"
"flowed")
```
The difference between the two other than visually is that hanging always results in 1 less line spent _because we don't care about line-length_. This is great because it means we can always default to hanging unless overridden. Flowing trades off that 1 vertical line for horizontal space and looks great for block-style forms. Like the top-level of a `defun` or the content of a `let`.
### Applying Formatting
The final real-step in the process, actually using the configuration and generating the formatting code. This phase is actually broken up into 3 sub-phases as we recurse through the `FormatterTree`
#### Build Lines
First we build the source code lines without indentation, it's a lot easier to figure out the indentation after all tokens are on the correct lines instead of doing it in tandem. Most tokens are given their own line, but in the case of a hung form we combine the first two elements on the first line. Other forms are formatted in even more complicated ways, or comments that were originally inline should remain next to that token.
Secondly, once we have all our consolidated lines we can apply the indentation. This is most often based on the configuration of the list node itself. For example a `hung` form must be indented the width of a `(` and the length of the head-form, plus the whitespace separator -- conversely a `flowed` form only needs to be indented by `2` spaces, regardless of token length. Because all of these algorithms are recursive we can hyper-focus on getting the indentation and formatting correct from the bottom-up. In otherwords, we don't care if a form is 200 spaces indented into a function, once the lines are returned recursively, they will get another layer of indentation added on until we hit the top-level node.
### Finalize Lines
Finally, we concatenate our list of strings, respecting the original file's line-endings.
As it is best practice, if we are formatting an entire file we should terminate with a trailing new-line.
Both of these items are technically a TODO.
## Configuration
TODO
## Reference
This formatter is highly influenced by a lot of other existing formatters and writings. The most significant of which is Clojure's [zprint](https://github.com/kkinnear/zprint/tree/main/doc/options) which has incredible documentation around it's capabilities and why it chooses what to do.
The formatter I've built basically copies zprint in terms of basic functionality, but simplifies things by being even more opinionated (for example, doing far less in terms of trying to adhere to a line-length limit).
### Other references
- [The Hardest Program I’ve Ever Written - Dart Formatter](https://journal.stuffwithstuff.com/2015/09/08/the-hardest-program-ive-ever-written/)
- [cljfmt](https://github.com/weavejester/cljfmt)
### Why not respect a line-length limit
The OpenGOAL formatter will respect line-length in only very specific situations:
- When determining if a form can be fit entirely on a single line
- Probably in the future for multi-line comments
Besides it adding a massive amount of complexity, even zprint explains that a line-length limit won't always be followed
> zprint will work very hard to fit the formatted output into this width, though there are limits to its effort. For instance, it will not reduce the minimum indents in order to satisfy a particular width requirement.
Let's illustrate with an example:
```clj
(defun some-func
(+ 123
456
(+ 123
456
;; imagine this form exceeds our width, how can you "fix" this without
;; messing up the indentation levels of the entire expression
;; - you can't inline it (you're already past the width)
;; - you can't insert a line break because it'll still be at the same horizontal level
(+ 123
456
789))))
```
In LISP code, we don't have many ideal options to deal with this, all options are syntactically correct, but in terms of conventional readability they are bad because when reading LISP code you want to use the indentation as a guide (which is why new-line parens are considered ugly by basically all LISP style guides)
The other reason which is equally relevant is it is hard, it means the formatter would have to try to find an optimal solution by exploring different solutions until it finds the one that minimizes lines.
But with an opinionated formatting style you can avoid this complexity, if you want your code to look nice don't write code like the decompiler sometimes outputs when it encounters something truly cursed:
![](./docs/triangle-of-death.png)
> `game-save.gc` about 200+ nested `let`s!
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

+510
View File
@@ -0,0 +1,510 @@
#include "formatter.h"
#include "formatter_tree.h"
#include "common/formatter/rules/formatting_rules.h"
#include "common/formatter/rules/rule_config.h"
#include "common/log/log.h"
#include "common/util/FileUtil.h"
#include "common/util/ast_util.h"
#include "common/util/string_util.h"
#include "tree_sitter/api.h"
#include "fmt/core.h"
// Declare the `tree_sitter_opengoal` function, which is
// implemented by the `tree-sitter-opengoal` library.
extern "C" {
extern const TSLanguage* tree_sitter_opengoal();
}
int hang_indentation_width(const FormatterTreeNode& curr_node) {
if (curr_node.token || curr_node.refs.empty()) {
return 0;
}
// Get the first element of the form
const auto& first_elt = curr_node.refs.at(0);
if (first_elt.token) {
return first_elt.token->length() +
2; // +2 because the opening paren and then the following space
}
// Otherwise, continue nesting
return 1 + hang_indentation_width(first_elt);
}
int get_total_form_inlined_width(const FormatterTreeNode& curr_node) {
if (curr_node.token) {
return curr_node.token->length();
}
int width = 1;
for (int i = 0; i < curr_node.refs.size(); i++) {
width += get_total_form_inlined_width(curr_node.refs.at(i));
if (i != curr_node.refs.size() - 1) {
width += 1; // add the space between elements
}
}
return width + 1;
}
// TODO - compute length of each node and store it AOT
void apply_formatting_config(
FormatterTreeNode& curr_node,
std::optional<std::shared_ptr<formatter_rules::config::FormFormattingConfig>>
config_from_parent = {},
std::optional<std::shared_ptr<formatter_rules::config::FormFormattingConfig>>
config_merge_from_parent = {}) {
using namespace formatter_rules;
// node is empty, base-case
if (curr_node.token || curr_node.refs.empty()) {
return;
}
// first, check to see if this form already has a predefined formatting configuration
// if it does, that simplifies things because there is only 1 way of formatting the form
std::optional<formatter_rules::config::FormFormattingConfig> predefined_config;
if (!config_from_parent && !curr_node.refs.empty() && curr_node.refs.at(0).token) {
const auto& form_head = curr_node.refs.at(0).token;
if (form_head && config::opengoal_form_config.find(form_head.value()) !=
config::opengoal_form_config.end()) {
predefined_config = config::opengoal_form_config.at(form_head.value());
curr_node.formatting_config = predefined_config.value();
}
if (config_merge_from_parent) {
const auto& merge_config = *config_merge_from_parent.value();
curr_node.formatting_config.parent_mutable_extra_indent +=
merge_config.parent_mutable_extra_indent;
curr_node.formatting_config.prevent_inlining = merge_config.prevent_inlining;
}
} else if (config_from_parent) {
// TODO - doesn't merge just replaces, a bit inflexible
predefined_config = *config_from_parent.value();
curr_node.formatting_config = predefined_config.value();
}
// In order to keep things simple, as well as because its ineffectual in lisp code (you can only
// enforce it so much without making things unreadable), line width will not matter for deciding
// whether or not to hang or flow the form
//
// This means that a hang would ALWAYS win, because it's 1 less line break. Therefore this
// simplifies our approach there is no need to explore both braches to see which one would be
// preferred.
//
// Instead, we either use the predefined configuration (obviously) or we do some checks for some
// outlier conditions to see if things should be formatted differently
//
// Otherwise, we always default to a hang.
//
// NOTE - any modifications here to child elements could be superseeded later in the recursion!
// In order to maintain your sanity, only modify things here that _arent_ touched by default
// configurations. These are explicitly prepended with `parent_mutable_`
if (!predefined_config && !curr_node.formatting_config.config_set) {
if (curr_node.metadata.is_top_level) {
curr_node.formatting_config.indentation_width = 0;
curr_node.formatting_config.hang_forms = false;
} else if (constant_list::is_constant_list(curr_node)) {
// - Check if the form is a constant list (ie. a list of numbers)
curr_node.formatting_config.indentation_width = 1;
curr_node.formatting_config.hang_forms = false;
curr_node.formatting_config.has_constant_pairs =
constant_pairs::form_should_be_constant_paired(curr_node);
// If applicable, iterate through the constant pairs, since we can potentially pair up
// non-constant second elements in a pair (like a function call), there is the potential that
// they need to spill to the next line and get indented in extra. This is an exceptional
// circumstance, we do NOT do this sort of thing when formatting normal forms (cond/case pairs
// are another similar situation)
if (curr_node.formatting_config.has_constant_pairs) {
for (int i = 0; i < (int)curr_node.refs.size(); i++) {
auto& child_ref = curr_node.refs.at(i);
const auto& type = child_ref.metadata.node_type;
if (constant_types.find(type) == constant_types.end() &&
constant_pairs::is_element_second_in_constant_pair(curr_node, child_ref, i)) {
child_ref.formatting_config.parent_mutable_extra_indent = 2;
}
}
}
} else if (curr_node.formatting_config.hang_forms && curr_node.refs.size() > 1 &&
curr_node.refs.at(1).metadata.is_comment) {
// - Check if the second argument is a comment, it looks better if we flow instead
curr_node.formatting_config.hang_forms = false;
}
}
// If we are hanging, lets determine the indentation width since it is based on the form itself
if (curr_node.formatting_config.hang_forms) {
// TODO - this isn't being calculated for a pre-defined config
// TODO - another idea is to do this during consolidation
curr_node.formatting_config.indentation_width = hang_indentation_width(curr_node);
}
// iterate through the refs
for (int i = 0; i < (int)curr_node.refs.size(); i++) {
auto& ref = curr_node.refs.at(i);
if (!ref.token) {
// If the child has a pre-defined configuration at that index, we pass it along
if (predefined_config && predefined_config->index_config_override.find(i) !=
predefined_config->index_config_override.end()) {
apply_formatting_config(ref, {}, predefined_config->index_config_override.at(i));
} else if (predefined_config && predefined_config->index_configs.find(i) !=
predefined_config->index_configs.end()) {
apply_formatting_config(ref, predefined_config->index_configs.at(i), {});
} else if (predefined_config && predefined_config->default_index_config) {
apply_formatting_config(ref, predefined_config->default_index_config, {});
} else {
apply_formatting_config(ref, {}, {});
}
}
}
// Precompute the column widths for things like deftype fields
if (curr_node.formatting_config.determine_column_widths_for_list_elements) {
// iterate through each ref and find the max length of each index (may be a token, may not be!)
// then store that info in each list element's `list_element_column_widths` to be used when
// printing out the tokens (pad width)
// Find the maximum number of columns
int max_columns = 0;
for (const auto& field : curr_node.refs) {
if ((int)field.refs.size() > max_columns) {
max_columns = field.refs.size();
}
}
// if only one field has a value in the max col position, it looks weird for it to be indented
bool ignore_final_column_width = true;
int fields_with_atleast_max_col = 0;
for (const auto& field : curr_node.refs) {
if ((int)field.refs.size() == max_columns) {
fields_with_atleast_max_col++;
if (fields_with_atleast_max_col > 1) {
ignore_final_column_width = false;
break;
}
}
}
// Now find the column max widths
std::vector<int> column_max_widths = {};
for (int col = 0; col < max_columns; col++) {
column_max_widths.push_back(0);
// -2 because its the indentation before the final column that we want to skip
if (col >= curr_node.formatting_config.num_columns_to_compute_widths ||
(ignore_final_column_width && col == max_columns - 2)) {
continue;
}
for (const auto& field : curr_node.refs) {
if ((int)field.refs.size() > col) {
const auto width = get_total_form_inlined_width(field.refs.at(col));
if (width > column_max_widths.at(col)) {
column_max_widths[col] = width;
}
}
}
}
// Apply column info to every list
for (auto& field : curr_node.refs) {
field.formatting_config.list_element_column_widths = column_max_widths;
field.formatting_config.config_set = true;
}
}
}
bool form_contains_comment(const FormatterTreeNode& curr_node) {
if (curr_node.metadata.is_comment) {
return true;
}
for (const auto& ref : curr_node.refs) {
const auto contains_comment = form_contains_comment(ref);
if (contains_comment) {
return true;
}
}
return false;
}
bool form_contains_node_that_prevents_inlining(const FormatterTreeNode& curr_node) {
if (curr_node.formatting_config.should_prevent_inlining(curr_node.formatting_config,
curr_node.refs.size())) {
return true;
}
for (const auto& ref : curr_node.refs) {
const auto prevents_inlining = form_contains_node_that_prevents_inlining(ref);
if (prevents_inlining) {
return true;
}
}
return false;
}
bool can_node_be_inlined(const FormatterTreeNode& curr_node, int cursor_pos) {
using namespace formatter_rules;
if (curr_node.formatting_config.force_inline) {
// Ensure there are no comments, this still trumps this
if (form_contains_comment(curr_node)) {
return false;
}
return true;
}
// First off, we cannot inline the top level
if (curr_node.metadata.is_top_level) {
return false;
}
// If the config explicitly prevents inlining, or it contains a sub-node that prevents inlining
if (curr_node.formatting_config.prevent_inlining ||
form_contains_node_that_prevents_inlining(curr_node)) {
return false;
}
// nor can we inline something that contains a comment in the middle
if (form_contains_comment(curr_node)) {
return false;
}
// constant pairs are not inlined!
if (curr_node.formatting_config.has_constant_pairs) {
return false;
}
// If this is set in the config, then the form is intended to be partially inlined
if (curr_node.formatting_config.inline_until_index({})) {
return false;
}
// let's see if we can inline the form all on one line to do that, we recursively explore
// the form to find the total width
int line_width = cursor_pos + get_total_form_inlined_width(curr_node);
return line_width <= indent::line_width_target; // TODO - comments
}
std::vector<std::string> apply_formatting(const FormatterTreeNode& curr_node,
std::vector<std::string> /*output*/ = {},
int cursor_pos = 0) {
using namespace formatter_rules;
if (!curr_node.token && curr_node.refs.empty()) {
// special case to handle an empty list
if (curr_node.node_prefix) {
return {fmt::format("{}()", curr_node.node_prefix.value())};
}
return {"()"};
}
// If its a token, just print the token and move on
if (curr_node.token) {
return {curr_node.token_str()};
}
bool inline_form = can_node_be_inlined(curr_node, cursor_pos);
// TODO - also if the form is inlinable, we can skip all the complication below and just...inline
// it!
// TODO - should figure out the inlining here as well, instead of the bool above
// Iterate the form, building up a list of the final lines but don't worry about indentation
// at this stage. Once the lines are finalized, it's easy to add the indentation later
//
// This means we may combine elements onto the same line in this step.
std::vector<std::string> form_lines = {};
for (int i = 0; i < (int)curr_node.refs.size(); i++) {
const auto& ref = curr_node.refs.at(i);
// Add new line entry
if (ref.token) {
// Cleanup block-comments
if (ref.metadata.node_type == "block_comment") {
const auto comment_lines = comments::format_block_comment(ref.token_str());
for (const auto& line : comment_lines) {
form_lines.push_back(line);
}
} else {
form_lines.push_back(ref.token_str());
}
if (!curr_node.metadata.is_top_level && i == (int)curr_node.refs.size() - 1 &&
(ref.metadata.is_comment)) {
// if there's an inline comment at the end of a form, we have to force the paren to the next
// line and do a new-line paren this is ugly, but we have no choice!
form_lines.push_back("");
}
} else {
// If it's not a token, we have to recursively build up the form
// TODO - add the cursor_pos here
const auto& lines = apply_formatting(ref, {}, cursor_pos);
for (int i = 0; i < (int)lines.size(); i++) {
const auto& line = lines.at(i);
form_lines.push_back(fmt::format(
"{}{}", str_util::repeat(ref.formatting_config.parent_mutable_extra_indent, " "),
line));
}
}
// If we are hanging forms, combine the first two forms onto the same line
if (i == (int)curr_node.refs.size() - 1 && form_lines.size() > 1 &&
(curr_node.formatting_config.hang_forms ||
curr_node.formatting_config.combine_first_two_lines)) {
form_lines.at(0) += fmt::format(" {}", str_util::ltrim(form_lines.at(1)));
form_lines.erase(form_lines.begin() + 1);
} else if ((i + 1) < (int)curr_node.refs.size()) {
const auto& next_ref = curr_node.refs.at(i + 1);
// combine the next inline comment or constant pair
if ((next_ref.metadata.node_type == "comment" && next_ref.metadata.is_inline) ||
(curr_node.formatting_config.has_constant_pairs &&
constant_pairs::is_element_second_in_constant_pair(curr_node, next_ref, i + 1)) ||
constant_pairs::is_element_second_in_constant_pair_new(curr_node.refs.at(i), next_ref)) {
// TODO
// has issues with not consolidating first lines, this should probably just be moved to
// outside this loop for simplicity, do it later
if (next_ref.token) {
form_lines.at(form_lines.size() - 1) += fmt::format(" {}", next_ref.token_str());
i++;
// We have to handle hang-consolidation here or else it will never be reached above!
if (i == (int)curr_node.refs.size() - 1 && form_lines.size() > 1 &&
(curr_node.formatting_config.hang_forms ||
curr_node.formatting_config.combine_first_two_lines)) {
form_lines.at(0) += fmt::format(" {}", form_lines.at(1));
form_lines.erase(form_lines.begin() + 1);
}
} else if (can_node_be_inlined(next_ref, cursor_pos)) {
const auto& lines = apply_formatting(next_ref, {}, cursor_pos); // TODO - cursor pos
for (const auto& line : lines) {
form_lines.at(form_lines.size() - 1) += fmt::format(" {}", line);
}
i++;
// We have to handle hang-consolidation here or else it will never be reached above!
if (i == (int)curr_node.refs.size() - 1 && form_lines.size() > 1 &&
(curr_node.formatting_config.hang_forms ||
curr_node.formatting_config.combine_first_two_lines)) {
form_lines.at(0) += fmt::format(" {}", form_lines.at(1));
form_lines.erase(form_lines.begin() + 1);
}
}
if (!curr_node.metadata.is_top_level && next_ref.metadata.node_type == "comment" &&
(i + 1) == (int)curr_node.refs.size()) {
form_lines.push_back("");
}
}
}
// If we are at the top level, potential separate with a new line
if (blank_lines::should_insert_blank_line(curr_node, ref, i)) {
form_lines.at(form_lines.size() - 1) += "\n";
}
}
// Consolidate any lines if the configuration requires it
// TODO there is a hack here so that multi-line forms that are consolidated still line up properly
// i have to make consolidate a more first-class feature of the config
// TODO - hacky, but prevents a bad situation, clean up
if (curr_node.formatting_config.inline_until_index(form_lines) &&
!str_util::contains(form_lines.at(0), ";")) {
std::vector<std::string> new_form_lines = {};
const auto original_form_head_width = str_util::split(form_lines.at(0), '\n').at(0).length();
bool consolidating_lines = true;
for (int i = 0; i < (int)form_lines.size(); i++) {
if (i < curr_node.formatting_config.inline_until_index(form_lines)) {
if (new_form_lines.empty()) {
new_form_lines.push_back(form_lines.at(i));
} else {
new_form_lines.at(0) += fmt::format(" {}", form_lines.at(i));
}
} else {
if (str_util::starts_with(form_lines.at(i), " ") && consolidating_lines) {
new_form_lines.push_back(fmt::format(
"{}{}", str_util::repeat(original_form_head_width, " "), form_lines.at(i)));
} else {
consolidating_lines = false;
new_form_lines.push_back(form_lines.at(i));
}
}
}
form_lines = new_form_lines;
}
// Add any column padding
if (!curr_node.formatting_config.list_element_column_widths.empty()) {
for (int i = 0; i < (int)form_lines.size(); i++) {
const auto& token = form_lines.at(i);
if (i < (int)form_lines.size() - 1) {
form_lines[i] = str_util::pad_right(
token, curr_node.formatting_config.list_element_column_widths.at(i), ' ');
}
}
}
// Apply necessary indentation to each line and add parens
if (!curr_node.metadata.is_top_level) {
std::string form_surround_start = "(";
if (curr_node.node_prefix) {
form_surround_start = fmt::format("{}(", curr_node.node_prefix.value());
}
std::string form_surround_end = ")";
form_lines[0] = fmt::format("{}{}", form_surround_start, form_lines[0]);
form_lines[form_lines.size() - 1] =
fmt::format("{}{}", form_lines[form_lines.size() - 1], form_surround_end);
}
if (inline_form) {
// NOTE - not sure about this, if we are inlining a form, it always makes sense to eliminate
// trailing whitespace the only issue i can foresee is related to strings that span multiple
// lines.
std::vector<std::string> new_form_lines = {};
for (const auto& form_line : form_lines) {
new_form_lines.push_back(str_util::ltrim(form_line));
}
form_lines = {fmt::format("{}", fmt::join(new_form_lines, " "))};
} else {
bool currently_in_block_comment = false;
for (int i = 0; i < (int)form_lines.size(); i++) {
auto& line = form_lines.at(i);
if (str_util::contains(line, "|#")) {
currently_in_block_comment = false;
}
if (i > 0 && !currently_in_block_comment) {
line = fmt::format("{}{}",
str_util::repeat(curr_node.formatting_config.indentation_width_for_index(
curr_node.formatting_config, i),
" "),
line);
}
if (str_util::contains(line, "#|") && !str_util::contains(line, "|#")) {
currently_in_block_comment = true;
}
}
}
return form_lines;
}
std::string join_formatted_lines(const std::vector<std::string>& lines,
const std::string& line_ending) {
return fmt::format("{}", fmt::join(lines, line_ending));
}
std::optional<std::string> formatter::format_code(const std::string& source) {
// Create a parser.
std::shared_ptr<TSParser> parser(ts_parser_new(), TreeSitterParserDeleter());
ts_parser_set_language(parser.get(), tree_sitter_opengoal());
// Build a syntax tree based on source code stored in a string.
std::shared_ptr<TSTree> tree(
ts_parser_parse_string(parser.get(), NULL, source.c_str(), source.length()),
TreeSitterTreeDeleter());
// Get the root node of the syntax tree.
TSNode root_node = ts_tree_root_node(tree.get());
if (ts_node_is_null(root_node)) {
lg::error("null root node");
return std::nullopt;
} else if (ts_node_has_error(root_node)) {
lg::error("grammar parsing error, go figure it out!");
return std::nullopt;
}
try {
// There are three phases of formatting
// 1. Simplify the AST down to something that is easier to work on from a formatting perspective
// this also gathers basic metadata that can be done at this stage, like if the token is a
// comment or if the form is on the top-level
auto formatting_tree = FormatterTree(source, root_node);
// 2. Recursively iterate through this simplified FormatterTree and figure out what rules
// need to be applied to produce an optimal result
apply_formatting_config(formatting_tree.root);
// 3. Use this updated FormatterTree to print out the final source-code, while doing so
// we may deviate from the optimal result to produce something even more optimal by inlining
// forms that can fit within the line width.
const auto formatted_lines = apply_formatting(formatting_tree.root);
// 4. Now we joint he lines together, it's easier when formatting to leave all lines independent
// so adding indentation is easier
const auto formatted_source =
join_formatted_lines(formatted_lines, file_util::get_majority_file_line_endings(source));
return formatted_source;
} catch (std::exception& e) {
lg::error("Unable to format code - {}", e.what());
}
return std::nullopt;
}
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <optional>
#include <string>
#include "tree_sitter/api.h"
namespace formatter {
struct TreeSitterParserDeleter {
void operator()(TSParser* ptr) const { ts_parser_delete(ptr); }
};
struct TreeSitterTreeDeleter {
void operator()(TSTree* ptr) const { ts_tree_delete(ptr); }
};
std::optional<std::string> format_code(const std::string& source);
} // namespace formatter
+177
View File
@@ -0,0 +1,177 @@
#include "formatter_tree.h"
#include "common/util/string_util.h"
#include "fmt/core.h"
std::string get_source_code(const std::string& source, const TSNode& node) {
uint32_t start = ts_node_start_byte(node);
uint32_t end = ts_node_end_byte(node);
return source.substr(start, end - start);
}
int num_blank_lines_following_node(const std::string& source, const TSNode& node) {
int num_lines = -1; // The first new-line encountered is not a blank line
uint32_t cursor = ts_node_end_byte(node);
// TODO - this breaks on lines with whitespace as well, should probably seek past that!
while (cursor < source.length() && source.at(cursor) == '\n') {
num_lines++;
cursor++;
}
return num_lines;
}
// Check if the original source only has whitespace up to a new-line before it's token
bool node_preceeded_by_only_whitespace(const std::string& source, const TSNode& node) {
// NOTE - this returns incorrectly because we skip brackets in lists, we'll see if that matters
int32_t pos = ts_node_start_byte(node) - 1;
while (pos > 0) {
const auto& c = source.at(pos);
if (c == '\n') {
return true;
} else if (c == ' ' || c == '\t') {
pos--;
continue;
}
return false;
}
return true;
}
FormatterTreeNode::FormatterTreeNode(const std::string& source, const TSNode& node)
: token(get_source_code(source, node)) {
metadata.node_type = ts_node_type(node);
metadata.is_comment = str_util::starts_with(str_util::ltrim(token.value()), ";") ||
str_util::starts_with(str_util::ltrim(token.value()), "#|");
// Set any metadata based on the value of the token
metadata.num_blank_lines_following = num_blank_lines_following_node(source, node);
metadata.is_inline = !node_preceeded_by_only_whitespace(source, node);
};
// Check if the original source only has whitespace up to a new-line after it's token
bool node_followed_by_only_whitespace(const std::string& source, const TSNode& node) {
uint32_t pos = ts_node_end_byte(node);
while (pos < source.length()) {
const auto& c = source.at(pos);
if (c == '\n') {
return true;
} else if (c == ' ' || c == '\t') {
pos++;
continue;
}
return false;
}
return true;
}
bool nodes_on_same_line(const std::string& source, const TSNode& n1, const TSNode& n2) {
// Get the source between the two lines, if there are any new-lines, the answer is NO
uint32_t start = ts_node_start_byte(n1);
uint32_t end = ts_node_end_byte(n2);
const auto code_between = source.substr(start, end - start);
return !str_util::contains(code_between, "\n");
}
FormatterTree::FormatterTree(const std::string& source, const TSNode& root_node) {
root = FormatterTreeNode();
root.metadata.is_top_level = true;
construct_formatter_tree_recursive(source, root_node, root);
}
const std::unordered_map<std::string, std::vector<std::string>> node_type_ignorable_contents = {
{"list_lit", {"(", ")"}}};
// TODO make an imperative version eventually
// TODO - cleanup duplication
void FormatterTree::construct_formatter_tree_recursive(const std::string& source,
TSNode curr_node,
FormatterTreeNode& tree_node,
std::optional<std::string> node_prefix) {
if (ts_node_child_count(curr_node) == 0) {
auto new_node = FormatterTreeNode(source, curr_node);
new_node.node_prefix = node_prefix;
tree_node.refs.push_back(new_node);
return;
}
const std::string curr_node_type = ts_node_type(curr_node);
FormatterTreeNode list_node;
std::optional<std::string> next_node_prefix;
if (curr_node_type == "list_lit") {
list_node = FormatterTreeNode();
} else if (curr_node_type == "str_lit") {
// Strings are a special case, they are literals and essentially tokens but the grammar can
// detect formatter identifiers, this is useful for semantic highlighting but doesn't matter for
// formatting So for strings, we treat them as if they should be a single token
tree_node.refs.push_back(FormatterTreeNode(source, curr_node));
return;
} else if (curr_node_type == "quoting_lit") {
if (node_prefix) {
node_prefix.value() += "'";
} else {
node_prefix = "'";
}
construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix);
return;
} else if (curr_node_type == "unquoting_lit") {
if (node_prefix) {
node_prefix.value() += ",";
} else {
node_prefix = ",";
}
construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix);
return;
} else if (curr_node_type == "quasi_quoting_lit") {
if (node_prefix) {
node_prefix.value() += "`";
} else {
node_prefix = "`";
}
construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix);
return;
} else if (curr_node_type == "unquote_splicing_lit") {
if (node_prefix) {
node_prefix.value() += ",@";
} else {
node_prefix = ",@";
}
construct_formatter_tree_recursive(source, ts_node_child(curr_node, 1), tree_node, node_prefix);
return;
}
std::vector<std::string> skippable_nodes = {};
if (node_type_ignorable_contents.find(curr_node_type) != node_type_ignorable_contents.end()) {
skippable_nodes = node_type_ignorable_contents.at(curr_node_type);
}
for (size_t i = 0; i < ts_node_child_count(curr_node); i++) {
const auto child_node = ts_node_child(curr_node, i);
auto debug_child = ts_node_string(child_node);
const auto contents = get_source_code(source, child_node);
bool skip_node = false;
for (const auto& skippable_content : skippable_nodes) {
if (skippable_content == contents) {
skip_node = true;
break;
}
}
if (skip_node) {
continue;
}
if (curr_node_type == "list_lit") {
construct_formatter_tree_recursive(source, child_node, list_node, {});
if (node_prefix) {
list_node.node_prefix = node_prefix;
}
} else {
construct_formatter_tree_recursive(source, child_node, tree_node, node_prefix);
if (node_prefix && !tree_node.refs.empty()) {
tree_node.refs.at(tree_node.refs.size() - 1).node_prefix = node_prefix;
}
}
}
if (curr_node_type == "list_lit") {
// special case for empty lists
if (node_prefix && !list_node.node_prefix) {
list_node.node_prefix = node_prefix;
}
tree_node.refs.push_back(list_node);
}
}
+78
View File
@@ -0,0 +1,78 @@
#pragma once
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "rules/rule_config.h"
#include "tree_sitter/api.h"
// Treesitter is fantastic for validating and parsing our code into a structured tree format without
// whitespace so we can do that ourselves (formatting) However, the treesitter AST is a bit too
// detailed for purposes of formatting.
//
// When formatting there is no need to know things like are we
// in a function, or a symbol, etc. This extra information is fantastic for parsing or manipulating
// the language, but becomes burdensome when just trying to write elegant formatting code when all
// we really care about is:
// - getting all the text tokens for the source code
// - having them in a proper, nested format
//
// TLDR - The treesitter format is complicated and highly nested, leading to some very hard to
// understand code. So my solution is atleast a 2-pass format.
//
// Pass 1 - convert the AST into a simplified FormatterTree
// Pass 2 - use the simplified tree to output the final code
class FormatterTreeNode {
public:
struct Metadata {
std::string node_type;
bool is_top_level = false;
bool is_comment = false;
bool is_inline = false;
int num_blank_lines_following = 0;
bool is_binding_list = false; // TODO set this
};
std::vector<FormatterTreeNode> refs;
Metadata metadata;
// The token is optional because list nodes do not contain a token, they just contain a bunch of
// eventually-containing token node refs
std::optional<std::string> token;
std::optional<std::string> node_prefix;
formatter_rules::config::FormFormattingConfig formatting_config;
FormatterTreeNode() = default;
FormatterTreeNode(const std::string& source, const TSNode& node);
FormatterTreeNode(const Metadata& _metadata) : metadata(_metadata){};
bool is_list() const { return !token.has_value(); }
std::string token_str() const {
if (node_prefix && token) {
return node_prefix.value() + token.value();
}
if (token) {
return token.value();
}
return "";
}
};
// A FormatterTree has a very simple and crude tree structure where:
// - Nodes are essentially forms, which contain in-order tokens or references to nested forms
// - Nodes can have associated metadata, often related to their context in the original code
// - Nodes can also have multiple formatting rules associated with them. Often this is the default
// rule or based on pre-configured overrides due to the head of the form, ex. 'defun'
class FormatterTree {
public:
FormatterTree(const std::string& source, const TSNode& root_node);
FormatterTreeNode root;
private:
void construct_formatter_tree_recursive(const std::string& source,
TSNode curr_node,
FormatterTreeNode& tree_node,
std::optional<std::string> node_prefix = {});
};
+191
View File
@@ -0,0 +1,191 @@
#include "formatting_rules.h"
#include <set>
#include "common/util/string_util.h"
#include "fmt/core.h"
namespace formatter_rules {
// TODO - probably need to include quoted literals as well, though the grammar currently does not
// differentiate between a quoted symbol and a quoted form
const std::set<std::string> constant_types = {"kwd_lit", "num_lit", "str_lit",
"char_lit", "null_lit", "bool_lit"};
const std::set<std::string> constant_type_forms = {"meters", "seconds", "degrees"};
namespace constant_list {
bool is_constant_list(const FormatterTreeNode& node) {
if (!node.is_list() || node.refs.empty()) {
return false;
}
if (!node.refs.at(0).token) {
return true;
}
const auto& type = node.refs.at(0).metadata.node_type;
return constant_types.find(type) != constant_types.end();
}
} // namespace constant_list
namespace blank_lines {
bool should_insert_blank_line(const FormatterTreeNode& containing_node,
const FormatterTreeNode& node,
const int index) {
// We only do this at the top level and don't leave a trailing new-line
if (!containing_node.metadata.is_top_level || index >= (int)containing_node.refs.size() - 1) {
return false;
}
// If it's a comment, but has no following blank lines, dont insert a blank line
if (node.metadata.is_comment && node.metadata.num_blank_lines_following == 0) {
return false;
}
// If the next form is a comment and is inline, don't insert a new line
if ((index + 1) < (int)containing_node.refs.size() &&
containing_node.refs.at(index + 1).metadata.is_comment &&
containing_node.refs.at(index + 1).metadata.is_inline) {
return false;
}
if (node.formatting_config.elide_top_level_newline) {
if ((index + 1) < (int)containing_node.refs.size() &&
containing_node.refs.at(index + 1).metadata.is_comment) {
return true;
}
return false;
}
return true;
}
} // namespace blank_lines
namespace comments {
std::vector<std::string> format_block_comment(const std::string& comment) {
// Normalize block comments, remove any trailing or leading whitespace
// Only allow annotations on the first line, like #|@file
// Don't mess with internal indentation as the user might intend it to be a certain way.
std::string new_comment = "";
std::string comment_contents = "";
bool seek_until_whitespace = str_util::starts_with(comment, "#|@");
int chars_seeked = 0;
for (const auto& c : comment) {
if (c == '\n' || (seek_until_whitespace && (c == ' ' || c == '\t')) ||
(!seek_until_whitespace && (c != '#' && c != '|'))) {
break;
}
chars_seeked++;
new_comment += c;
}
// Remove the first line content and any leading whitespace
comment_contents = str_util::ltrim_newlines(comment.substr(chars_seeked));
// Remove trailing whitespace
comment_contents = str_util::rtrim(comment_contents);
// remove |#
if (str_util::ends_with(comment_contents, "|#")) {
comment_contents.pop_back();
comment_contents.pop_back();
}
comment_contents = str_util::rtrim(comment_contents);
std::vector<std::string> lines = {new_comment};
const auto contents_as_lines = str_util::split_string(comment_contents, "\n");
if (contents_as_lines.size() > 1) {
for (const auto& line : contents_as_lines) {
lines.push_back(line);
}
lines.push_back("|#");
} else {
lines.at(0) = fmt::format("{} {} |#", new_comment, str_util::trim(contents_as_lines.at(0)));
}
return lines;
}
} // namespace comments
namespace constant_pairs {
// TODO - remove index, not needed, could just pass in the previous node
bool is_element_second_in_constant_pair(const FormatterTreeNode& containing_node,
const FormatterTreeNode& node,
const int index) {
if (containing_node.refs.empty() || index == 0) {
return false;
}
// Ensure that a keyword came before hand
if (containing_node.refs.at(index - 1).metadata.node_type != "kwd_lit") {
return false;
} else if (node.metadata.node_type == "kwd_lit") {
// NOTE - there is ambiugity here which cannot be totally solved (i think?)
// if the element itself is also a keyword, assume this is two adjacent keywords and they should
// not be paired
return false;
}
return true;
}
// TODO - potentially remove the above
bool is_element_second_in_constant_pair_new(const FormatterTreeNode& prev_node,
const FormatterTreeNode& curr_node) {
if (prev_node.metadata.node_type == "kwd_lit") {
// Handle standard constant types
// TODO - pair up sym_names as well
if (constant_types.find(curr_node.metadata.node_type) != constant_types.end()) {
if (curr_node.metadata.node_type != "kwd_lit") {
// NOTE - there is ambiugity here which cannot be totally solved (i think?)
// if the element itself is also a keyword, assume this is two adjacent keywords and they
// should not be paired
return true;
}
}
// Quoted symbols
if (curr_node.metadata.node_type == "sym_name" && curr_node.node_prefix &&
(curr_node.node_prefix.value() == "'" || curr_node.node_prefix.value() == ",")) {
return true;
}
if (!curr_node.refs.empty()) {
// Constant forms special cases (ie. meters)
if (constant_type_forms.find(curr_node.refs.at(0).token_str()) != constant_type_forms.end()) {
return true;
}
// If they are just a list of symbol names (enum or simple method call)
bool all_symbols = true;
for (const auto& ref : curr_node.refs) {
if (ref.metadata.node_type != "sym_name") {
all_symbols = false;
break;
}
}
if (all_symbols) {
return true;
}
}
}
return false;
}
bool form_should_be_constant_paired(const FormatterTreeNode& node) {
// Criteria for a list to be constant paired:
// - needs to start with a non-symbol
// - needs atleast the minimum amount of pairs, so 2 pairs can still be inlined
if (node.refs.empty()) {
return false;
}
int num_pairs = 0;
for (int i = 0; i < (int)node.refs.size() - 1; i++) {
const auto& ref = node.refs.at(i);
const auto& next_ref = node.refs.at(i + 1);
if (ref.token && next_ref.token) {
// If the first element a keyword and the following item is a constant, it's a pair
// move forward one extra index
if (ref.metadata.node_type == "kwd_lit" &&
constant_types.find(next_ref.metadata.node_type) != constant_types.end()) {
num_pairs++;
i++;
}
}
}
return num_pairs >= min_pair_amount;
}
} // namespace constant_pairs
} // namespace formatter_rules
+121
View File
@@ -0,0 +1,121 @@
#pragma once
#include <set>
#include <string>
#include "common/formatter/formatter_tree.h"
namespace formatter_rules {
extern const std::set<std::string> constant_types;
namespace constant_list {
bool is_constant_list(const FormatterTreeNode& node);
}
// The formatter will try to collapse as much space as possible in the top-level, this means
// separating forms by a single empty blank line
//
// The exception are comments, top level comments will retain their following blank lines from the
// original source
// - this could be none, in the case where a comment is directly next to a form (like this one!)
// - you don't want them to be separated!
// - or this could be top level comments / comment blocks documenting things but not being
// associated with a form
// - in this case, you want them to remain separated
//
// Reference - https://github.com/kkinnear/zprint/blob/main/doc/options/blank.md
namespace blank_lines {
bool should_insert_blank_line(const FormatterTreeNode& containing_node,
const FormatterTreeNode& node,
const int index);
} // namespace blank_lines
// TODO:
// - align consecutive comment lines
// - if/when the formatter is concerned with line length, there are implications here
//
// Reference - https://github.com/kkinnear/zprint/blob/main/doc/options/comments.md
namespace comments {
std::vector<std::string> format_block_comment(const std::string& comment);
}
// Paired elements in a list will be kept in-line rather than the default new-line indentation
// For example:
// (:msg "hello world" :delay 100 :fn (lambda () (+ 1 1)))
// Would typically become:
// (:msg
// "hello world"
// :delay
// 100
// :fn
// (lambda ()
// (+ 1 1)))
// But with constant pairs:
// (:msg "hello world"
// :delay 100
// :fn
// (lambda ()
// (+ 1 1)))
//
// Reference - https://github.com/kkinnear/zprint/blob/main/doc/options/constantpairs.md
namespace constant_pairs {
const static int min_pair_amount = 4;
// Determines if the given element is the second element in a constant pair, if it is then we would
// usually want to elide the new-line in whatever code that applies it
//
// This is true if:
// - the element is in a list
// - the element is preceeded by a keyword
// - the element is a:
// - keyword, symbol, string, number, or boolean
bool is_element_second_in_constant_pair(const FormatterTreeNode& containing_node,
const FormatterTreeNode& node,
const int index);
bool is_element_second_in_constant_pair_new(const FormatterTreeNode& prev_node,
const FormatterTreeNode& curr_node);
bool form_should_be_constant_paired(const FormatterTreeNode& node);
} // namespace constant_pairs
// There are two main types of indentations "flow"s and "hang"s
// (this is
// a
// hang)
// (this
// is
// a
// flow)
//
// `flow` is the default indentation mode and right now the determination between the two is down to
// manual configuration based on the head of the form. In general, we only `flow` or `hang` if the
// form cannot fit on the current line.
//
// Additionally, if the head of the form is a constant we `flow` with an indent of `1` instead of
// `2`
//
// By default, we always hang unless:
// - the head-form overrides the configuration
// - TODO it will use more lines than the flow approach
//
// Reference - https://github.com/kkinnear/zprint/blob/main/doc/options/indent.md
namespace indent {
const static int line_width_target = 120;
} // namespace indent
// Let forms fall into two main categories
// - Ones that can be entirely inlined
// - Ones that cannot
//
// Single line let forms:
// - If there is a single binding, let it continue to be one line
// - otherwise, flow it just as a multi-line let would be done
//
// For multi-line let forms, the difficulty is how to format the binding:
// - align the bindings to within the binding list (single indent space)
// - always format the binding value on the same line as the binding, no new lines
// - forms inside the let binding are flowed
//
// Reference - https://github.com/kkinnear/zprint/blob/main/doc/options/let.md
namespace let {} // namespace let
} // namespace formatter_rules
+303
View File
@@ -0,0 +1,303 @@
#include "rule_config.h"
#include "common/util/string_util.h"
namespace formatter_rules {
namespace config {
static FormFormattingConfig new_inlinable_simple_flow_rule() {
return {.config_set = true, .hang_forms = false};
}
static FormFormattingConfig new_permissive_flow_rule() {
return {.config_set = true, .hang_forms = false, .combine_first_two_lines = true};
}
static FormFormattingConfig new_flow_rule(int start_index, bool has_constant_pairs = false) {
return {.config_set = true,
.hang_forms = false,
.inline_until_index =
[start_index](const std::vector<std::string>& /*curr_lines*/) { return start_index; },
.has_constant_pairs = has_constant_pairs};
}
static FormFormattingConfig new_function_rule(int start_index, bool has_constant_pairs = false) {
FormFormattingConfig cfg = {
.config_set = true,
.hang_forms = false,
.inline_until_index =
[start_index](const std::vector<std::string>& /*curr_lines*/) { return start_index; },
.has_constant_pairs = has_constant_pairs};
auto arg_list_config = std::make_shared<FormFormattingConfig>();
arg_list_config->force_inline = true;
arg_list_config->hang_forms = false;
cfg.index_configs.emplace(2, arg_list_config);
return cfg;
}
static FormFormattingConfig new_inlineable_flow_rule(int start_index,
bool has_constant_pairs = false) {
return {.config_set = true,
.hang_forms = false,
.inline_until_index =
[start_index](const std::vector<std::string>& curr_lines) {
int total_width = 0;
for (const auto& line : curr_lines) {
// Check for comments
// TODO - this shows how this isn't really the best strategy but it holds up
if (str_util::contains(line, ";")) {
// Can't inline, there's a comment!
return start_index;
}
total_width += line.length();
// an empty line implies a new-line was forced, this is bleeding implementation
// details, but fine for now
if (line.empty()) {
return start_index;
}
}
if (total_width <= 120) {
return (int)curr_lines.size();
}
return start_index;
},
.has_constant_pairs = has_constant_pairs};
}
static FormFormattingConfig new_defstate_rule(int start_index, bool has_constant_pairs = false) {
FormFormattingConfig cfg = {
.config_set = true,
.hang_forms = false,
.inline_until_index =
[start_index](const std::vector<std::string>& /*curr_lines*/) { return start_index; },
.has_constant_pairs = has_constant_pairs};
std::vector<int> state_handler_indexes = {4, 6, 8, 10,
12, 14}; // NOTE - not all of these have to be defined
for (const auto& index : state_handler_indexes) {
auto temp_config = std::make_shared<FormFormattingConfig>();
temp_config->prevent_inlining = true;
temp_config->parent_mutable_extra_indent = 2;
cfg.index_config_override.emplace(index, temp_config);
}
return cfg;
}
static FormFormattingConfig new_defmethod_rule(int start_index, bool has_constant_pairs = false) {
// TODO - might be nice to have a function that returns a config based on a given index, instead
// of hardcoding them!
// Right now this only works for non-`new` methods (else we may bleed into the body of a normal
// method)
auto arg_list_config = std::make_shared<FormFormattingConfig>();
arg_list_config->force_inline = true;
arg_list_config->hang_forms = false;
FormFormattingConfig cfg = {.config_set = true,
.hang_forms = false,
.inline_until_index =
[start_index](const std::vector<std::string>& curr_lines) {
if (curr_lines.size() >= 2 && curr_lines.at(1) == "new") {
// defmethod was changed to omit the type name for everything
// except the `new` method, so special case.
return start_index + 1;
}
return start_index;
},
.has_constant_pairs = has_constant_pairs};
cfg.index_configs.emplace(2, arg_list_config);
return cfg;
}
static FormFormattingConfig new_lambda_rule(int start_index, bool has_constant_pairs = false) {
FormFormattingConfig cfg = {.config_set = true,
.hang_forms = false,
.inline_until_index =
[start_index](const std::vector<std::string>& curr_lines) {
if (curr_lines.size() >= 2 && curr_lines.at(1) == ":behavior") {
// defmethod was changed to omit the type name for everything
// except the `new` method, so special case.
return start_index + 2;
}
return start_index;
},
.has_constant_pairs = has_constant_pairs};
return cfg;
}
static FormFormattingConfig new_defenum_rule() {
auto temp_list_config = std::make_shared<FormFormattingConfig>();
temp_list_config->force_inline = true;
temp_list_config->hang_forms = false;
return {
.config_set = true,
.hang_forms = false,
.inline_until_index = [](const std::vector<std::string>& /*curr_lines*/) { return 2; },
.has_constant_pairs = true,
.default_index_config = temp_list_config,
};
}
static FormFormattingConfig new_deftype_rule(
int start_index,
int num_columns_to_compute_widths,
const std::vector<int>& inlining_preventation_indices) {
FormFormattingConfig cfg;
cfg.has_constant_pairs = true;
cfg.config_set = true;
cfg.hang_forms = false;
cfg.inline_until_index = [start_index](std::vector<std::string> curr_lines) {
if (curr_lines.size() >= 4 && curr_lines.at(3) == "()") {
return 4;
}
return start_index;
};
for (const auto& index : inlining_preventation_indices) {
auto temp_config = std::make_shared<FormFormattingConfig>();
temp_config->config_set = true;
temp_config->prevent_inlining = true;
temp_config->hang_forms = false;
temp_config->indentation_width = 1;
auto temp_list_config = std::make_shared<FormFormattingConfig>();
temp_list_config->force_inline = true;
temp_list_config->hang_forms = false;
temp_config->default_index_config = temp_list_config;
if (index == 3) {
temp_config->determine_column_widths_for_list_elements = true;
temp_config->num_columns_to_compute_widths = num_columns_to_compute_widths;
}
cfg.index_configs.emplace(index, temp_config);
}
return cfg;
}
static FormFormattingConfig new_binding_rule(int form_head_width) {
FormFormattingConfig cfg;
cfg.config_set = true;
cfg.hang_forms = false;
cfg.combine_first_two_lines = true;
auto binding_list_config = std::make_shared<FormFormattingConfig>();
binding_list_config->config_set = true;
binding_list_config->hang_forms = false;
binding_list_config->indentation_width = 1;
binding_list_config->indentation_width_for_index = [form_head_width](FormFormattingConfig /*cfg*/,
int index) {
if (index == 0) {
return 0;
}
return form_head_width;
};
binding_list_config->should_prevent_inlining = [](FormFormattingConfig /*config*/, int num_refs) {
// Only prevent inlining a binding list, if there are more than 1 bindings
if (num_refs > 1) {
return true;
}
return false;
};
binding_list_config->prevent_inlining =
true; // TODO - we only want to prevent inlining if there are more than 2 elements
cfg.index_configs.emplace(1, binding_list_config);
return cfg;
}
static FormFormattingConfig new_inline_binding_rule(int form_head_width) {
FormFormattingConfig cfg;
cfg.config_set = true;
cfg.hang_forms = false;
cfg.combine_first_two_lines = true;
auto binding_list_config = std::make_shared<FormFormattingConfig>();
binding_list_config->config_set = true;
binding_list_config->hang_forms = false;
binding_list_config->indentation_width = 1;
binding_list_config->indentation_width_for_index = [form_head_width](FormFormattingConfig /*cfg*/,
int index) {
if (index == 0) {
return 0;
}
return form_head_width;
};
binding_list_config->should_prevent_inlining = [](FormFormattingConfig /*config*/, int num_refs) {
return false;
};
cfg.index_configs.emplace(1, binding_list_config);
return cfg;
}
static FormFormattingConfig new_pair_rule(bool combine_first_two_expr) {
FormFormattingConfig cfg;
cfg.config_set = true;
cfg.hang_forms = false;
cfg.prevent_inlining = true;
cfg.combine_first_two_lines = combine_first_two_expr;
auto pair_config = std::make_shared<FormFormattingConfig>();
pair_config->config_set = true;
pair_config->hang_forms = false;
pair_config->indentation_width = 1;
cfg.default_index_config = pair_config;
return cfg;
}
static FormFormattingConfig new_top_level_inline_form(bool elide_new_line) {
return {.force_inline = true, .elide_top_level_newline = elide_new_line};
}
const std::unordered_map<std::string, FormFormattingConfig> opengoal_form_config = {
{"case", new_pair_rule(true)},
{"cond", new_pair_rule(false)},
{"#cond", new_pair_rule(false)},
{"in-package", new_top_level_inline_form(true)},
{"bundles", new_top_level_inline_form(true)},
{"require", new_top_level_inline_form(true)},
{"def-art-elt", new_top_level_inline_form(true)},
{"def-joint-node", new_top_level_inline_form(true)},
{"declare-file", new_top_level_inline_form(false)},
{"defenum", new_defenum_rule()},
{"defmethod", new_defmethod_rule(3)},
{"lambda", new_lambda_rule(2)},
{"deftype", new_deftype_rule(3, 1, {3, 4, 5, 6})},
{"defun", new_flow_rule(3)},
{"defun-recursive", new_flow_rule(4)},
{"defun-debug-recursive", new_flow_rule(4)},
{"defun-debug", new_flow_rule(3)},
{"defbehavior", new_flow_rule(4)},
{"if", new_inlineable_flow_rule(2)},
{"#if", new_inlineable_flow_rule(2)},
{"define", new_permissive_flow_rule()},
{"def-mips2c", new_permissive_flow_rule()},
{"defconstant", new_permissive_flow_rule()},
{"defglobalconstant", new_permissive_flow_rule()},
{"defmethod-mips2c", new_permissive_flow_rule()},
{"define-extern", new_permissive_flow_rule()},
{"declare-type", new_permissive_flow_rule()},
{"defmacro", new_function_rule(3)},
{"desfun", new_function_rule(3)},
{"defskelgroup", new_flow_rule(2, true)},
{"defpartgroup", new_flow_rule(2, true)},
{"defpart", new_flow_rule(2, true)},
{"defstate", new_defstate_rule(3, true)},
{"behavior", new_flow_rule(2)},
{"dotimes", new_flow_rule(2)},
{"dolist", new_flow_rule(2)},
{"process-spawn-function", new_flow_rule(2)},
{"let", new_binding_rule(4)},
{"protect", new_binding_rule(4)},
{"let*", new_binding_rule(5)},
{"rlet", new_binding_rule(5)},
{"when", new_flow_rule(2)},
{"unless", new_flow_rule(2)},
{"with-profiler", new_flow_rule(2)},
{"with-pc", new_flow_rule(0)},
{"#unless", new_flow_rule(2)},
{"#when", new_flow_rule(2)},
{"countdown", new_flow_rule(2)},
{"until", new_flow_rule(2)},
{"loop", new_flow_rule(0)},
{"while", new_flow_rule(2)},
{"begin", new_flow_rule(0)},
{"seval", new_flow_rule(0)},
{"with-pp", new_flow_rule(0)},
{"with-gensyms", new_flow_rule(2)},
{"with-vf0", new_flow_rule(0)},
{"with-vf", new_inline_binding_rule(8)},
{"with-cnt-vif-block", new_inline_binding_rule(19)},
{"local-vars", new_inlinable_simple_flow_rule()},
{"with-dma-buffer-add-bucket", new_flow_rule(2)}};
} // namespace config
} // namespace formatter_rules
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
namespace formatter_rules {
namespace config {
struct FormFormattingConfig {
bool config_set = false;
bool force_inline = false;
bool hang_forms =
true; // TODO - remove this eventually, it's only involved in setting the
// indentation width, which we can do via the new indentation_width function
int indentation_width =
2; // 2 for a flow // TODO - also remove this, prefer storing the first node's width in the
// metadata on the first pass, that's basically all this does
std::function<int(FormFormattingConfig, int)> indentation_width_for_index =
[](FormFormattingConfig config, int /*index*/) { return config.indentation_width; };
bool combine_first_two_lines =
false; // NOTE - basically hang, but will probably stick around after hang is gone, may be
// redundant (inline_until_index!)
std::function<std::optional<int>(const std::vector<std::string>& /*curr_lines*/)>
inline_until_index = [](std::vector<std::string> /*curr_lines*/) { return std::nullopt; };
bool has_constant_pairs = false;
bool prevent_inlining = false; // TODO - duplicate of below
std::function<bool(FormFormattingConfig, int num_refs)> should_prevent_inlining =
[](FormFormattingConfig config, int /*num_refs*/) { return config.prevent_inlining; };
int parent_mutable_extra_indent = 0;
std::optional<std::shared_ptr<FormFormattingConfig>> default_index_config;
std::unordered_map<int, std::shared_ptr<FormFormattingConfig>> index_configs = {};
// TODO / NOTe - not fully implemented, only doing `parent_mutable_extra_indent` right now
std::unordered_map<int, std::shared_ptr<FormFormattingConfig>> index_config_override = {};
bool determine_column_widths_for_list_elements = false;
int num_columns_to_compute_widths = 0;
std::vector<int> list_element_column_widths = {};
bool elide_top_level_newline = false;
};
extern const std::unordered_map<std::string, FormFormattingConfig> opengoal_form_config;
} // namespace config
} // namespace formatter_rules
+29 -15
View File
@@ -7,23 +7,25 @@
#include "common/util/Assert.h"
#include "common/util/FileUtil.h"
#include "common/common_types.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
#include "third-party/json.hpp"
#ifdef __linux__
u32 get_current_tid() {
return (u32)pthread_self();
#ifdef OS_POSIX
u64 get_current_tid() {
return (u64)pthread_self();
}
#else
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "Processthreadsapi.h"
u32 get_current_tid() {
return (u32)GetCurrentThreadId();
u64 get_current_tid() {
return (u64)GetCurrentThreadId();
}
#endif
#include "common/log/log.h"
// clang-format on
u64 get_current_ts() {
@@ -40,8 +42,17 @@ void GlobalProfiler::set_max_events(size_t event_count) {
m_nodes.resize(event_count);
}
void GlobalProfiler::set_waiting_for_event(const std::string& event_name) {
if (!event_name.empty()) {
m_waiting_for_event = event_name;
}
}
void GlobalProfiler::event(const char* name, ProfNode::Kind kind) {
if (!m_enabled) {
if (m_waiting_for_event && m_waiting_for_event.value() == name) {
m_ignore_events = true;
}
if (!m_enabled || m_ignore_events) {
return;
}
size_t my_idx = (m_next_idx++ % m_nodes.size());
@@ -57,12 +68,16 @@ void GlobalProfiler::instant_event(const char* name) {
event(name, ProfNode::INSTANT);
}
void GlobalProfiler::root_event() {
instant_event("ROOT");
}
void GlobalProfiler::begin_event(const char* name) {
event(name, ProfNode::BEGIN);
}
void GlobalProfiler::end_event() {
if (!m_enabled) {
if (!m_enabled || m_ignore_events) {
return;
}
size_t my_idx = (m_next_idx++ % m_nodes.size());
@@ -157,18 +172,17 @@ void GlobalProfiler::dump_to_json(const std::string& path) {
// ts
json_event["ts"] = (event.ts - lowest_ts) / 1000.f;
if (event.ts < info.debug) {
fmt::print("out of order: {} {} {} ms\n", event.ts / 1000.f, info.debug / 1000.f,
(info.debug - event.ts) / 1000000.f);
fmt::print(" idx: {}, range {} {}\n", event_idx, info.lowest_at_target,
info.highest_at_target);
fmt::print(" now: {}\n", m_next_idx);
lg::debug("out of order: {} {} {} ms", event.ts / 1000.f, info.debug / 1000.f,
(info.debug - event.ts) / 1000000.f);
lg::debug(" idx: {}, range {} {}", event_idx, info.lowest_at_target, info.highest_at_target);
lg::debug(" now: {}", m_next_idx.load());
}
info.debug = event.ts;
}
for (auto& t : info_per_thread) {
fmt::print("thread: {}: {} -> {}\n", t.first, t.second.lowest_at_target,
t.second.highest_at_target);
lg::debug("thread: {}: {} -> {}", t.first, t.second.lowest_at_target,
t.second.highest_at_target);
}
file_util::write_text_file(path, json.dump());
+11 -2
View File
@@ -1,6 +1,7 @@
#pragma once
#include <atomic>
#include <optional>
#include <string>
#include <vector>
@@ -8,15 +9,16 @@
struct ProfNode {
u64 ts;
char name[32];
u64 tid;
char name[128];
enum Kind : u8 { BEGIN, END, INSTANT, UNUSED } kind = UNUSED;
u32 tid;
};
class GlobalProfiler {
public:
GlobalProfiler();
void set_max_events(size_t event_count);
void set_waiting_for_event(const std::string& event_name);
void instant_event(const char* name);
void begin_event(const char* name);
void event(const char* name, ProfNode::Kind kind);
@@ -24,15 +26,22 @@ class GlobalProfiler {
void clear();
void set_enable(bool en);
void dump_to_json(const std::string& path);
void root_event();
private:
std::atomic_bool m_enabled = false;
u64 m_t0 = 0;
std::atomic_size_t m_next_idx = 0;
std::vector<ProfNode> m_nodes;
// this is very niche, but sometimes you want to capture up to a given event (ie. long startup)
// instead of having to make the user quit and record as fast as possible, we can instead just
// stop capturing events once we have received what we are looking for
std::optional<std::string> m_waiting_for_event = {};
bool m_ignore_events = false;
};
struct ScopedEvent {
ScopedEvent(GlobalProfiler* _prof) : prof(_prof){};
ScopedEvent(const ScopedEvent&) = delete;
ScopedEvent& operator=(const ScopedEvent&) = delete;
GlobalProfiler* prof = nullptr;
+23 -2
View File
@@ -1,7 +1,7 @@
#pragma once
#include "common/common_types.h"
#include "common/versions.h"
#include "common/versions/versions.h"
constexpr s32 BINTEGER_OFFSET = 0;
constexpr s32 PAIR_OFFSET = 2;
@@ -41,6 +41,11 @@ constexpr int bits_for_sym() {
return b + 1;
}
static_assert(bits_for_sym() != -1, "symbol table invalid length");
// amount of levels in level heap
constexpr int LEVEL_MAX = 2;
// total amount of levels, including ones outside level heap (default-level)
constexpr int LEVEL_TOTAL = LEVEL_MAX + 1;
} // namespace jak1
namespace jak2 {
@@ -50,18 +55,34 @@ constexpr s32 SYM_TABLE_MEM_SIZE = 0x30000;
// from the "off-by-one" symbol pointer
constexpr int SYM_TO_STRING_OFFSET = 0xff37;
constexpr int SYM_TO_HASH_OFFSET = 0x1fe6f;
// amount of levels in level heap
constexpr int LEVEL_MAX = 6;
// total amount of levels, including ones outside level heap (default-level)
constexpr int LEVEL_TOTAL = LEVEL_MAX + 1;
} // namespace jak2
namespace jak3 {
// for now, we don't have the ability to extend the size of the symbol table
constexpr s32 GOAL_MAX_SYMBOLS = 0x4000;
// amount of levels in level heap
constexpr int LEVEL_MAX = 10;
// total amount of levels, including ones outside level heap (default-level)
constexpr int LEVEL_TOTAL = LEVEL_MAX + 1;
} // namespace jak3
constexpr s32 max_symbols(GameVersion version) {
switch (version) {
case GameVersion::Jak1:
return jak1::GOAL_MAX_SYMBOLS;
case GameVersion::Jak2:
return jak2::GOAL_MAX_SYMBOLS;
case GameVersion::Jak3:
return jak3::GOAL_MAX_SYMBOLS;
}
}
enum class RegClass { GPR_64, FLOAT, INT_128, VECTOR_FLOAT, INVALID };
enum class RegClass : u8 { GPR_64, FLOAT, INT_128, VECTOR_FLOAT, INVALID };
constexpr u32 GOAL_NEW_METHOD = 0; // method ID of GOAL new
constexpr u32 GOAL_DEL_METHOD = 1; // method ID of GOAL delete
File diff suppressed because it is too large. Load diff
+67 -14
View File
@@ -16,21 +16,23 @@ class Interpreter {
public:
Interpreter(const std::string& user_profile = "#f");
~Interpreter();
void execute_repl(ReplWrapper& repl);
void execute_repl(REPL::Wrapper& repl);
void throw_eval_error(const Object& o, const std::string& err);
Object eval_with_rewind(const Object& obj, const std::shared_ptr<EnvironmentObject>& env);
bool get_global_variable_by_name(const std::string& name, Object* dest);
void set_global_variable_by_name(const std::string& name, const Object& value);
void set_global_variable_to_symbol(const std::string& name, const std::string& value);
void set_global_variable_to_int(const std::string& name, int value);
Object eval(Object obj, const std::shared_ptr<EnvironmentObject>& env);
Object intern(const std::string& name);
HeapObject* intern_ptr(const std::string& name);
InternedSymbolPtr intern_ptr(const std::string& name);
void disable_printfs();
Object eval_symbol(const Object& sym, const std::shared_ptr<EnvironmentObject>& env);
bool eval_symbol(const Object& sym,
const std::shared_ptr<EnvironmentObject>& env,
Object* result);
Arguments get_args(const Object& form, const Object& rest, const ArgumentSpec& spec);
Arguments get_args_no_named(const Object& form, const Object& rest, const ArgumentSpec& spec);
void set_args_in_env(const Object& form,
const Arguments& args,
const ArgumentSpec& arg_spec,
@@ -53,7 +55,7 @@ class Interpreter {
private:
friend class Goal;
void load_goos_library();
void define_var_in_env(Object& env, Object& var, const std::string& name);
void define_var_in_env(Object& env, const Object& var, const std::string& name);
void expect_env(const Object& form, const Object& o);
void vararg_check(
const Object& form,
@@ -62,8 +64,11 @@ class Interpreter {
const std::unordered_map<std::string, std::pair<bool, std::optional<ObjectType>>>& named);
Object eval_pair(const Object& o, const std::shared_ptr<EnvironmentObject>& env);
public:
ArgumentSpec parse_arg_spec(const Object& form, Object& rest);
private:
Object quasiquote_helper(const Object& form, const std::shared_ptr<EnvironmentObject>& env);
IntType number_to_integer(const Object& obj);
@@ -116,6 +121,9 @@ class Interpreter {
Object eval_read(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_read_data_file(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_read_file(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
@@ -197,6 +205,18 @@ class Interpreter {
Object eval_string_append(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_string_starts_with(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_string_ends_with(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_string_split(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_string_substr(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_ash(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
@@ -206,6 +226,9 @@ class Interpreter {
Object eval_string_to_symbol(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_int_to_string(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_get_env(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
@@ -241,6 +264,16 @@ class Interpreter {
Object eval_while(const Object& form,
const Object& rest,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_let(const Object& form,
const Object& rest,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_let_star(const Object& form,
const Object& rest,
const std::shared_ptr<EnvironmentObject>& env);
Object eval_let_common(const Object& form,
const Object& rest,
const std::shared_ptr<EnvironmentObject>& env,
bool star);
Object eval_make_string_hash_table(const Object& form,
Arguments& args,
@@ -252,26 +285,46 @@ class Interpreter {
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env);
const Object& true_or_false(bool val);
void init_special_forms(
const std::unordered_map<std::string,
Object (Interpreter::*)(const Object&,
const Object&,
const std::shared_ptr<EnvironmentObject>&)>&
forms);
void init_builtin_forms(
const std::unordered_map<std::string,
Object (Interpreter::*)(const Object&,
Arguments&,
const std::shared_ptr<EnvironmentObject>&)>&
forms);
bool want_exit = false;
bool disable_printing = false;
std::unordered_map<std::string,
Object (Interpreter::*)(const Object& form,
Arguments& args,
const std::shared_ptr<EnvironmentObject>& env)>
std::unordered_map<
void*,
Object (Interpreter::*)(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>
builtin_forms;
std::unordered_map<
std::string,
std::function<Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>>
std::vector<std::pair<
void*,
std::function<Object(const Object&, Arguments&, const std::shared_ptr<EnvironmentObject>&)>>>
m_custom_forms;
std::unordered_map<std::string,
Object (Interpreter::*)(const Object& form,
const Object& rest,
const std::shared_ptr<EnvironmentObject>& env)>
std::vector<std::pair<void*,
Object (Interpreter::*)(const Object& form,
const Object& rest,
const std::shared_ptr<EnvironmentObject>& env)>>
special_forms;
int64_t gensym_id = 0;
std::unordered_map<std::string, ObjectType> string_to_type;
const char* m_false_sym = nullptr;
const char* m_true_sym = nullptr;
Object m_false_object, m_true_object;
};
} // namespace goos
+103 -12
View File
@@ -41,14 +41,92 @@
#include "Object.h"
#include <cinttypes>
#include <cstring>
#include "common/util/FileUtil.h"
#include "common/util/crc32.h"
#include "common/util/print_float.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
namespace goos {
SymbolTable::SymbolTable() {
m_power_of_two_size = 1; // 2 ^ 1 = 2
m_entries.resize(2);
m_used_entries = 0;
m_next_resize = (m_entries.size() * kMaxUsed);
m_mask = 0b1;
}
SymbolTable::~SymbolTable() {
for (auto& e : m_entries) {
delete[] e.name;
}
}
InternedSymbolPtr SymbolTable::intern(const char* str) {
size_t string_len = strlen(str);
u32 hash = crc32((const u8*)str, string_len);
// probe
for (u32 i = 0; i < m_entries.size(); i++) {
u32 slot_addr = (hash + i) & m_mask;
auto& slot = m_entries[slot_addr];
if (!slot.name) {
// not found, insert!
slot.hash = hash;
auto* name = new char[string_len + 1];
memcpy(name, str, string_len + 1);
slot.name = name;
m_used_entries++;
if (m_used_entries >= m_next_resize) {
resize();
return intern(str);
}
return {name};
} else {
if (slot.hash != hash) {
continue; // bad hash
}
if (strcmp(slot.name, str) != 0) {
continue; // bad name
}
return {slot.name};
}
}
// should be impossible to reach.
ASSERT_NOT_REACHED();
}
void SymbolTable::resize() {
m_power_of_two_size++;
m_mask = (1U << m_power_of_two_size) - 1;
std::vector<Entry> new_entries(m_entries.size() * 2);
for (const auto& old_entry : m_entries) {
if (old_entry.name) {
bool done = false;
for (u32 i = 0; i < new_entries.size(); i++) {
u32 slot_addr = (old_entry.hash + i) & m_mask;
auto& slot = new_entries[slot_addr];
if (!slot.name) {
slot.name = old_entry.name;
slot.hash = old_entry.hash;
done = true;
break;
}
}
ASSERT(done);
}
}
m_entries = std::move(new_entries);
m_next_resize = kMaxUsed * m_entries.size();
}
/*!
* Convert type to string (name in brackets)
*/
@@ -136,14 +214,9 @@ std::string fixed_to_string(char x) {
return {buff};
}
/*!
* Create a new symbol object by interning
*/
Object SymbolObject::make_new(SymbolTable& st, const std::string& name) {
Object obj;
obj.type = ObjectType::SYMBOL;
obj.heap_obj = st.intern(name);
return obj;
template <>
std::string fixed_to_string(InternedSymbolPtr x) {
return x.name_ptr;
}
/*!
@@ -203,10 +276,23 @@ Object build_list(std::vector<Object>&& objects) {
Object result;
result.type = ObjectType::PAIR;
result.heap_obj = head;
result.heap_obj = std::move(head);
return result;
}
/*!
* Is this a float object that's a power of two?
* NOTE: assumes 64-bit float.
*/
bool Object::is_power_of_2_float() const {
FloatType val = as_float();
u64 val_i = -1;
memcpy(&val_i, &val, sizeof(val));
u64 mantissa = val_i & ((1LL << 52) - 1);
u64 exponent = (val_i >> 52) & ((1LL << 11) - 1);
return mantissa == 0 && exponent != 0 && exponent != ((1LL << 11) - 1);
}
/*!
* Compare two objects for equality.
* Does "expensive" checking.
@@ -224,8 +310,9 @@ bool Object::operator==(const Object& other) const {
return float_obj == other.float_obj;
case ObjectType::CHAR:
return char_obj == other.char_obj;
case ObjectType::SYMBOL:
return symbol_obj == other.symbol_obj;
case ObjectType::ENVIRONMENT:
case ObjectType::LAMBDA:
case ObjectType::MACRO:
@@ -257,7 +344,11 @@ bool Object::operator==(const Object& other) const {
}
bool Object::is_symbol(const std::string& name) const {
return is_symbol() && as_symbol()->name == name;
return is_symbol() && name == as_symbol().name_ptr;
}
bool Object::is_string(const std::string& val) const {
return is_string() && as_string()->data == val;
}
template <>
+199 -72
View File
@@ -43,6 +43,7 @@
*
*/
#include <cstring>
#include <map>
#include <memory>
#include <stdexcept>
@@ -54,12 +55,10 @@
#include "common/common_types.h"
#include "common/util/Assert.h"
#include "common/util/crc32.h"
namespace goos {
using FloatType = double;
using IntType = s64;
/*!
* All objects have one of these kinds
*/
@@ -71,9 +70,9 @@ enum class ObjectType : u8 {
INTEGER,
FLOAT,
CHAR,
SYMBOL,
// allocated
SYMBOL,
STRING,
PAIR,
ARRAY,
@@ -87,6 +86,29 @@ enum class ObjectType : u8 {
std::string object_type_to_string(ObjectType kind);
// Some objects are "fixed", meaning they are stored inline in the Object, and not heap allocated.
// These use value semantics and are copied on object assignment.
// For int/float, these are simply double/int64_t
using FloatType = double;
using IntType = s64;
// For symbols, we simply store a pointer to the symbol's name string.
// this is wrapped in a type just to avoid confusion with normal const char*.
struct InternedSymbolPtr {
const char* name_ptr;
struct hash {
auto operator()(const InternedSymbolPtr& x) const {
return std::hash<const void*>()((const void*)x.name_ptr);
}
};
bool operator==(const char* msg) const { return strcmp(msg, name_ptr) == 0; }
bool operator!=(const char* msg) const { return strcmp(msg, name_ptr) != 0; }
bool operator==(const std::string& str) const { return str == name_ptr; }
bool operator!=(const std::string& str) const { return str != name_ptr; }
bool operator==(const InternedSymbolPtr& other) const { return other.name_ptr == name_ptr; }
bool operator!=(const InternedSymbolPtr& other) const { return other.name_ptr != name_ptr; }
};
/*!
* By default, convert a fixed object data to string with std::to_string.
@@ -115,6 +137,31 @@ std::string fixed_to_string<char>(char);
template <>
std::string fixed_to_string<IntType>(IntType);
template <>
std::string fixed_to_string<InternedSymbolPtr>(InternedSymbolPtr);
class SymbolTable {
public:
SymbolTable(const SymbolTable&) = delete;
SymbolTable& operator=(const SymbolTable&) = delete;
SymbolTable();
~SymbolTable();
InternedSymbolPtr intern(const char* str);
private:
void resize();
int m_power_of_two_size = 0;
struct Entry {
u32 hash = 0;
const char* name = nullptr;
};
std::vector<Entry> m_entries;
int m_used_entries = 0;
int m_next_resize = 0;
u32 m_mask = 0;
static constexpr float kMaxUsed = 0.7;
};
/*!
* Common implementation for a fixed object
*/
@@ -139,6 +186,8 @@ class FixedObject {
return object_type_to_string(ObjectType::INTEGER);
if (std::is_same<T, char>())
return object_type_to_string(ObjectType::CHAR);
if (std::is_same<T, InternedSymbolPtr>())
return object_type_to_string(ObjectType::SYMBOL);
throw std::runtime_error("Unsupported FixedObject type");
}
};
@@ -149,6 +198,7 @@ class FixedObject {
using IntegerObject = FixedObject<int64_t>;
using FloatObject = FixedObject<double>;
using CharObject = FixedObject<char>;
using SymbolObject = FixedObject<InternedSymbolPtr>;
// Other objects are separate allocated on the heap. These objects should be HeapObjects.
@@ -162,7 +212,6 @@ class HeapObject {
// forward declare all HeapObjects
class PairObject;
class EnvironmentObject;
class SymbolObject;
class StringObject;
class LambdaObject;
class MacroObject;
@@ -180,6 +229,7 @@ class Object {
IntegerObject integer_obj;
FloatObject float_obj;
CharObject char_obj;
SymbolObject symbol_obj;
};
ObjectType type = ObjectType::INVALID;
@@ -192,6 +242,8 @@ class Object {
return float_obj.print();
case ObjectType::CHAR:
return char_obj.print();
case ObjectType::SYMBOL:
return symbol_obj.print();
case ObjectType::EMPTY_LIST:
return "()";
default:
@@ -207,6 +259,8 @@ class Object {
return float_obj.inspect();
case ObjectType::CHAR:
return char_obj.inspect();
case ObjectType::SYMBOL:
return symbol_obj.inspect();
case ObjectType::EMPTY_LIST:
return "[empty list] ()\n";
default:
@@ -244,16 +298,30 @@ class Object {
return o;
}
static Object make_symbol(SymbolTable* table, const char* name) {
Object o;
o.type = ObjectType::SYMBOL;
o.symbol_obj.value = table->intern(name);
return o;
}
PairObject* as_pair() const;
EnvironmentObject* as_env() const;
std::shared_ptr<EnvironmentObject> as_env_ptr() const;
SymbolObject* as_symbol() const;
StringObject* as_string() const;
LambdaObject* as_lambda() const;
MacroObject* as_macro() const;
ArrayObject* as_array() const;
StringHashTableObject* as_string_hash_table() const;
const InternedSymbolPtr& as_symbol() const {
if (type != ObjectType::SYMBOL) {
throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " +
print());
}
return symbol_obj.value;
}
IntType& as_int() {
if (type != ObjectType::INTEGER) {
throw std::runtime_error("as_int called on a " + object_type_to_string(type) + " " + print());
@@ -302,66 +370,19 @@ class Object {
bool is_symbol() const { return type == ObjectType::SYMBOL; }
bool is_symbol(const std::string& name) const;
bool is_string() const { return type == ObjectType::STRING; }
bool is_string(const std::string& val) const;
bool is_pair() const { return type == ObjectType::PAIR; }
bool is_array() const { return type == ObjectType::ARRAY; }
bool is_env() const { return type == ObjectType::ENVIRONMENT; }
bool is_macro() const { return type == ObjectType::MACRO; }
bool is_string_hash_table() const { return type == ObjectType::STRING_HASH_TABLE; }
bool is_power_of_2_float() const;
bool operator==(const Object& other) const;
bool operator!=(const Object& other) const { return !((*this) == other); }
};
class SymbolTable;
/*!
* A Symbol Object, which is just a wrapper around a string.
* The make_new function will correctly
*/
class SymbolObject : public HeapObject {
public:
std::string name;
explicit SymbolObject(std::string _name) : name(std::move(_name)) {}
static Object make_new(SymbolTable& st, const std::string& name);
std::string print() const override { return name; }
std::string inspect() const override { return "[symbol] " + name + "\n"; }
~SymbolObject() = default;
};
/*!
* A Symbol Table, which holds all symbols.
*/
class SymbolTable {
public:
std::shared_ptr<HeapObject> intern(const std::string& name) {
const auto& kv = table.find(name);
if (kv == table.end()) {
auto iter = table.insert({name, std::make_shared<SymbolObject>(name)});
return (*iter.first).second;
} else {
return kv->second;
}
}
HeapObject* intern_ptr(const std::string& name) {
const auto& kv = table.find(name);
if (kv == table.end()) {
auto iter = table.insert({name, std::make_shared<SymbolObject>(name)});
return (*iter.first).second.get();
} else {
return kv->second.get();
}
}
~SymbolTable() = default;
private:
std::unordered_map<std::string, std::shared_ptr<HeapObject>> table;
};
class StringObject : public HeapObject {
public:
std::string data;
@@ -436,14 +457,131 @@ class PairObject : public HeapObject {
~PairObject() = default;
};
template <typename T>
class InternedPtrMap {
public:
InternedPtrMap(const InternedPtrMap&) = delete;
InternedPtrMap& operator=(const InternedPtrMap&) = delete;
InternedPtrMap() { clear(); }
T* lookup(InternedSymbolPtr str) {
if (m_entries.size() < 10) {
for (auto& e : m_entries) {
if (e.key == str.name_ptr) {
return &e.value;
}
}
return nullptr;
}
u32 hash = crc32((const u8*)&str.name_ptr, sizeof(const char*));
// probe
for (u32 i = 0; i < m_entries.size(); i++) {
u32 slot_addr = (hash + i) & m_mask;
auto& slot = m_entries[slot_addr];
if (!slot.key) {
return nullptr;
} else {
if (slot.key != str.name_ptr) {
continue; // bad hash
}
return &slot.value;
}
}
// should be impossible to reach.
ASSERT_NOT_REACHED();
}
void set(InternedSymbolPtr ptr, const T& obj) {
u32 hash = crc32((const u8*)&ptr.name_ptr, sizeof(const char*));
// probe
for (u32 i = 0; i < m_entries.size(); i++) {
u32 slot_addr = (hash + i) & m_mask;
auto& slot = m_entries[slot_addr];
if (!slot.key) {
// not found, insert!
slot.key = ptr.name_ptr;
slot.value = obj;
m_used_entries++;
if (m_used_entries >= m_next_resize) {
resize();
}
return;
} else {
if (slot.key == ptr.name_ptr) {
slot.value = obj;
return;
}
}
}
// should be impossible to reach.
ASSERT_NOT_REACHED();
}
void clear() {
m_entries.clear();
m_power_of_two_size = 3; // 2 ^ 3 = 8
m_entries.resize(8);
m_used_entries = 0;
m_next_resize = (m_entries.size() * kMaxUsed);
m_mask = 0b111;
}
private:
struct Entry {
const char* key = nullptr;
T value;
};
std::vector<Entry> m_entries;
void resize() {
m_power_of_two_size++;
m_mask = (1U << m_power_of_two_size) - 1;
std::vector<Entry> new_entries(m_entries.size() * 2);
for (const auto& old_entry : m_entries) {
if (old_entry.key) {
bool done = false;
u32 hash = crc32((const u8*)&old_entry.key, sizeof(const char*));
for (u32 i = 0; i < new_entries.size(); i++) {
u32 slot_addr = (hash + i) & m_mask;
auto& slot = new_entries[slot_addr];
if (!slot.key) {
slot.key = old_entry.key;
slot.value = std::move(old_entry.value);
done = true;
break;
}
}
ASSERT(done);
}
}
m_entries = std::move(new_entries);
m_next_resize = kMaxUsed * m_entries.size();
}
int m_power_of_two_size = 0;
int m_used_entries = 0;
int m_next_resize = 0;
u32 m_mask = 0;
static constexpr float kMaxUsed = 0.7;
};
using EnvironmentMap = InternedPtrMap<Object>;
class EnvironmentObject : public HeapObject {
public:
std::string name;
std::shared_ptr<EnvironmentObject> parent_env;
// the symbols will be stored in the symbol table and never removed, so we don't need shared
// pointers here.
std::unordered_map<HeapObject*, Object> vars;
// note: this is keyed on the address in the symbol table.
EnvironmentMap vars;
// this find work by any name string
Object* find(const char* n, SymbolTable* st) { return vars.lookup(st->intern(n)); }
Object* find(InternedSymbolPtr ptr) { return vars.lookup(ptr); }
EnvironmentObject() = default;
@@ -475,11 +613,8 @@ class EnvironmentObject : public HeapObject {
std::string inspect() const override {
std::string result = "[environment]\n name: " + name +
"\n parent: " + (parent_env ? parent_env->print() : "NONE") +
"\n vars:\n";
for (const auto& kv : vars) {
result += " " + kv.first->print() + ": " + kv.second.print() + "\n";
}
"\n parent: " + (parent_env ? parent_env->print() : "NONE") + "\n";
return result;
}
};
@@ -659,14 +794,6 @@ inline std::shared_ptr<EnvironmentObject> Object::as_env_ptr() const {
return std::dynamic_pointer_cast<EnvironmentObject>(heap_obj);
}
inline SymbolObject* Object::as_symbol() const {
if (type != ObjectType::SYMBOL) {
throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " +
print());
}
return static_cast<SymbolObject*>(heap_obj.get());
}
inline StringObject* Object::as_string() const {
if (type != ObjectType::STRING) {
throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " +
+16 -4
View File
@@ -1,6 +1,6 @@
#include "ParseHelpers.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
namespace goos {
@@ -12,12 +12,12 @@ bool get_va(const goos::Object& rest, std::string* err_string, goos::Arguments*
auto arg = current.as_pair()->car;
// did we get a ":keyword"
if (arg.is_symbol() && arg.as_symbol()->name.at(0) == ':') {
auto key_name = arg.as_symbol()->name.substr(1);
if (arg.is_symbol() && arg.as_symbol().name_ptr[0] == ':') {
auto key_name = arg.as_symbol().name_ptr + 1;
// check for multiple definition of key
if (args.named.find(key_name) != args.named.end()) {
*err_string = "Key argument " + key_name + " multiply defined";
*err_string = fmt::format("Key argument {} multiply defined", key_name);
return false;
}
@@ -39,6 +39,17 @@ bool get_va(const goos::Object& rest, std::string* err_string, goos::Arguments*
return true;
}
void get_va_no_named(const goos::Object& rest, goos::Arguments* result) {
goos::Arguments args;
// loop over forms in list
goos::Object current = rest;
while (!current.is_empty_list()) {
args.unnamed.push_back(current.as_pair()->car);
current = current.as_pair()->cdr;
}
*result = args;
}
bool va_check(
const goos::Arguments& args,
const std::vector<std::optional<goos::ObjectType>>& unnamed,
@@ -53,6 +64,7 @@ bool va_check(
for (size_t i = 0; i < unnamed.size(); i++) {
if (unnamed[i].has_value() && unnamed[i] != args.unnamed[i].type) {
// special case -- an empty list is a valid pair
*err_string = fmt::format("Argument {} has type {} but {} was expected\nArgument is: {}", i,
object_type_to_string(args.unnamed[i].type),
object_type_to_string(unnamed[i].value()), args.unnamed[i].print());
+2 -1
View File
@@ -9,6 +9,7 @@
namespace goos {
bool get_va(const goos::Object& rest, std::string* err_string, goos::Arguments* result);
void get_va_no_named(const goos::Object& rest, goos::Arguments* result);
bool va_check(
const goos::Arguments& args,
const std::vector<std::optional<goos::ObjectType>>& unnamed,
@@ -28,4 +29,4 @@ void for_each_in_list(const goos::Object& list, T f) {
}
int list_length(const goos::Object& list);
} // namespace goos
} // namespace goos
+2 -3
View File
@@ -13,10 +13,9 @@
#include "Reader.h"
#include "common/goos/PrettyPrinter2.h"
#include "common/log/log.h"
#include "common/util/Assert.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
namespace pretty_print {
@@ -99,7 +98,7 @@ void add_to_token_list(const goos::Object& obj, std::vector<FormToken>* tokens)
// look for a (quote x) to print as 'x
auto& first = obj.as_pair()->car;
if (first.is_symbol() && first.as_symbol()->name == "quote") {
if (first.is_symbol() && first.as_symbol() == "quote") {
auto& second = obj.as_pair()->cdr;
if (second.is_pair() && second.as_pair()->cdr.is_empty_list()) {
tokens->emplace_back(FormToken::TokenKind::QUOTE);
+86 -19
View File
@@ -3,7 +3,8 @@
#include "common/common_types.h"
#include "common/util/Assert.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
#include "fmt/format.h"
namespace pretty_print {
@@ -29,11 +30,14 @@ struct Node {
std::string atom_str;
// number of quotes this is wrapped in.
u32 quoted = 0;
enum class QuoteKind { QUOTE, UNQUOTE, QUASIQUOTE, UNQUOTE_SPLICING };
std::vector<QuoteKind> quotes;
Node* parent = nullptr;
u32 my_depth = 0;
int get_quote_length() const;
void link(Node* this_parent, std::vector<Node*>* bfs_order, u32 depth) {
parent = this_parent;
my_depth = depth;
@@ -86,6 +90,30 @@ struct Node {
u8 sub_elt_indent = 0;
};
inline const std::string quote_symbol(Node::QuoteKind kind) {
switch (kind) {
case Node::QuoteKind::QUOTE:
return "'";
case Node::QuoteKind::QUASIQUOTE:
return "`";
case Node::QuoteKind::UNQUOTE:
return ",";
case Node::QuoteKind::UNQUOTE_SPLICING:
return ",@";
default:
ASSERT_MSG(false, fmt::format("invalid quote kind {}", fmt::underlying(kind)));
return "[invalid]";
}
}
int Node::get_quote_length() const {
int out = 0;
for (auto& q : quotes) {
out += quote_symbol(q).length();
}
return out;
}
Node to_node(const goos::Object& obj) {
switch (obj.type) {
case goos::ObjectType::EMPTY_LIST:
@@ -100,13 +128,22 @@ Node to_node(const goos::Object& obj) {
return Node(obj.print());
case goos::ObjectType::PAIR: {
// we've got three cases: quoted thing, proper list, improper list.
// we've got four cases: quoted thing, unquoted thing, proper list, improper list.
// there's probably a better way to do this but i am lazy
auto& first = obj.as_pair()->car;
if (first.is_symbol() && first.as_symbol()->name == "quote") {
if (first.is_symbol("quote")) {
auto& second = obj.as_pair()->cdr;
if (second.is_pair() && second.as_pair()->cdr.is_empty_list()) {
Node result = to_node(second.as_pair()->car);
result.quoted++;
result.quotes.push_back(Node::QuoteKind::QUOTE);
return result;
}
} else if (first.is_symbol("unquote")) {
auto& second = obj.as_pair()->cdr;
if (second.is_pair() && second.as_pair()->cdr.is_empty_list()) {
Node result = to_node(second.as_pair()->car);
result.quotes.push_back(Node::QuoteKind::UNQUOTE);
return result;
}
}
@@ -148,13 +185,13 @@ void recompute_lengths(const std::vector<Node*>& bfs_order) {
Node* node = *it;
switch (node->kind) {
case Node::Kind::ATOM:
node->text_len = node->atom_str.length() + node->quoted;
node->text_len = node->atom_str.length() + node->get_quote_length();
break;
case Node::Kind::IMPROPER_LIST:
case Node::Kind::LIST: {
if (node->break_list) {
// special case compute first line length
int first_line_len = 1 + node->quoted; // open paren + quotes
int first_line_len = 1 + node->get_quote_length(); // open paren + quotes
int nodes_on_first_line =
std::min(int(node->child_nodes.size()), int(node->top_line_count));
if (nodes_on_first_line > 0) {
@@ -176,7 +213,7 @@ void recompute_lengths(const std::vector<Node*>& bfs_order) {
node->text_len = max_line_len;
} else {
node->text_len = 1 + node->quoted; // open paren + quotes
node->text_len = 1 + node->get_quote_length(); // open paren + quotes
for (auto& child : node->child_nodes) {
node->text_len += (child.text_len + 1); // space or close paren.
}
@@ -200,9 +237,34 @@ void break_list(Node* node) {
node->top_line_count = 1;
const std::unordered_set<std::string> sameline_splitters = {
"if", "<", ">", "<=", ">=", "set!", "=", "!=", "+",
"-", "*", "/", "the", "->", "and", "or", "logand", "logior",
"logxor", "+!", "*!", "logtest?", "not", "zero?", "nonzero?"};
"if",
"<",
">",
"<=",
">=",
"set!",
"=",
"!=",
"+",
"-",
"*",
"/",
"the",
"->",
"and",
"or",
"logand",
"logior",
"logxor",
"+!",
"*!",
"logtest?",
"not",
"zero?",
"nonzero?",
"dma-buffer-add-gs-set",
"dma-buffer-add-gs-set-flusha",
};
if (node->child_nodes.at(0).kind == Node::Kind::LIST) {
// ((foo
@@ -226,12 +288,17 @@ void break_list(Node* node) {
node->sub_elt_indent += name.size();
} else if (name == "defmethod") {
// things with 4 things in the top line: (defmethod <method> <type> <args>
node->top_line_count = 4;
// or just 3 things in the top line: (defmethod <method> <args>
node->top_line_count = 3;
if (node->child_nodes.size() >= 4 && node->child_nodes[2].kind == Node::Kind::ATOM) {
node->top_line_count = 4;
}
} else if (name == "until" || name == "while" || name == "dotimes" || name == "countdown" ||
name == "when" || name == "behavior" || name == "lambda" || name == "defpart" ||
name == "define") {
node->top_line_count = 2;
} else if (name == "let" || name == "let*" || name == "rlet") {
} else if (name == "let" || name == "let*" || name == "rlet" ||
name == "with-dma-buffer-add-bucket") {
// special case for things like let.
node->top_line_count = 2; // (let <defs>
if (node->child_nodes.size() > 1 && node->child_nodes[1].child_nodes.size() > 1 &&
@@ -276,7 +343,7 @@ void insert_required_breaks(const std::vector<Node*>& bfs_order) {
const std::unordered_set<std::string> always_break = {
"when", "defun-debug", "countdown", "case", "defun", "defmethod", "let",
"until", "while", "if", "dotimes", "cond", "else", "defbehavior",
"with-pp", "rlet", "defstate", "behavior", "defpart", "loop"};
"with-pp", "rlet", "defstate", "behavior", "defpart", "loop", "let*"};
for (auto node : bfs_order) {
if (!node->break_list && node->kind == Node::Kind::LIST &&
node->child_nodes.at(0).kind == Node::Kind::ATOM) {
@@ -292,7 +359,7 @@ int run_algorithm(const std::vector<Node*>& bfs_order, int line_length) {
// - too long
// - not already split.
// the "magic" of v2 is:
// the "too long" check above igores the sublist.
// the "too long" check above ignores the sublist.
int num_broken = 0;
std::optional<s32> min_depth;
@@ -334,8 +401,8 @@ void append_node_to_string(const Node* node,
for (int i = 0; i < init_indent_level; i++) {
str.push_back(' ');
}
for (u32 i = 0; i < node->quoted; i++) {
str.push_back('\'');
for (auto q : node->quotes) {
str.append(quote_symbol(q));
}
switch (node->kind) {
case Node::Kind::ATOM:
@@ -347,7 +414,7 @@ void append_node_to_string(const Node* node,
str.push_back('(');
size_t node_idx = 0;
int listing_indent = next_indent_level + node->quoted + node->sub_elt_indent;
int listing_indent = next_indent_level + node->get_quote_length() + node->sub_elt_indent;
int extra_indent = 0;
int old_indent = listing_indent;
if (node->top_line_count) {
@@ -401,7 +468,7 @@ void append_node_to_string(const Node* node,
} else {
str.push_back('(');
ASSERT(!node->child_nodes.empty());
int listing_indent = next_indent_level + node->quoted;
int listing_indent = next_indent_level + node->get_quote_length();
int extra_indent = 1;
int c0 = 0;
for (auto& child : node->child_nodes) {
+20 -12
View File
@@ -1,6 +1,12 @@
#include "Printer.h"
#include "third-party/fmt/core.h"
#include <cmath>
#include <mutex>
#include "common/goos/Object.h"
#include "common/util/print_float.h"
#include "fmt/core.h"
namespace pretty_print {
namespace {
@@ -19,9 +25,7 @@ const std::unordered_map<u32, std::string> const_floats = {{0x40490fda, "PI"},
goos::Object float_representation(float value) {
u32 int_value;
memcpy(&int_value, &value, 4);
u8 exp = (int_value >> 23) & 0xff;
u32 mant = int_value & 0x7fffff;
if ((exp == 0 && mant != 0) || exp == 0xff) {
if (!proper_float(value)) {
// lg::warn("PS2-incompatible float (0x{:08X}) detected! Writing as the-as cast.", int_value);
return pretty_print::build_list("the-as", "float", fmt::format("#x{:x}", int_value));
} else if (const_floats.find(int_value) != const_floats.end()) {
@@ -34,6 +38,7 @@ goos::Object float_representation(float value) {
}
std::unique_ptr<goos::Reader> pretty_printer_reader;
std::mutex pretty_printer_reader_mutex;
goos::Reader& get_pretty_printer_reader() {
if (!pretty_printer_reader) {
@@ -43,7 +48,12 @@ goos::Reader& get_pretty_printer_reader() {
}
goos::Object to_symbol(const std::string& str) {
return goos::SymbolObject::make_new(get_pretty_printer_reader().symbolTable, str);
std::lock_guard<std::mutex> guard(pretty_printer_reader_mutex);
return goos::Object::make_symbol(&get_pretty_printer_reader().symbolTable, str.c_str());
}
goos::Object new_string(const std::string& str) {
return goos::StringObject::make_new(str);
}
goos::Object build_list(const std::string& str) {
@@ -65,14 +75,12 @@ goos::Object build_list(const std::vector<goos::Object>& objects) {
// build a list out of an array of forms
goos::Object build_list(const goos::Object* objects, int count) {
ASSERT(count);
auto car = objects[0];
goos::Object cdr;
if (count - 1) {
cdr = build_list(objects + 1, count - 1);
} else {
cdr = goos::Object::make_empty_list();
goos::Object result = goos::Object::make_empty_list();
for (int i = count; i-- > 0;) {
result = goos::PairObject::make_new(objects[i], result);
}
return goos::PairObject::make_new(car, cdr);
return result;
}
// build a list out of a vector of strings that are converted to symbols
+2
View File
@@ -10,6 +10,8 @@ namespace pretty_print {
// string -> object (as a symbol)
goos::Object to_symbol(const std::string& str);
goos::Object new_string(const std::string& str);
// list with a single symbol from a string
goos::Object build_list(const std::string& str);
+76 -33
View File
@@ -11,12 +11,11 @@
#include "Reader.h"
#include "ReplUtils.h"
#include "common/log/log.h"
#include "common/util/FileUtil.h"
#include "common/util/FontUtils.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
namespace goos {
@@ -194,7 +193,7 @@ bool Reader::is_valid_source_char(char c) const {
/*!
* Prompt the user and read the result.
*/
std::optional<Object> Reader::read_from_stdin(const std::string& prompt, ReplWrapper& repl) {
std::optional<Object> Reader::read_from_stdin(const std::string& prompt, REPL::Wrapper& repl) {
// escape code will make sure that we remove any color
std::string prompt_full = "\033[0m" + prompt;
@@ -238,17 +237,14 @@ Object Reader::read_from_string(const std::string& str,
* Read a file
*/
Object Reader::read_from_file(const std::vector<std::string>& file_path, bool check_encoding) {
std::string joined_name;
std::string file_descriptor = fmt::format("{}", fmt::join(file_path, "/"));
const auto joined_file_path = file_util::get_file_path(file_path);
for (const auto& thing : file_path) {
if (!joined_name.empty()) {
joined_name += '/';
}
joined_name += thing;
if (!fs::exists(joined_file_path)) {
throw std::runtime_error(fmt::format("Cannot read {}, file doesn't exist", joined_file_path));
}
auto textFrag = std::make_shared<FileText>(file_util::get_file_path(file_path), joined_name);
auto textFrag = std::make_shared<FileText>(joined_file_path, file_descriptor);
db.insert(textFrag);
auto result = internal_read(textFrag, check_encoding);
@@ -291,11 +287,16 @@ Object Reader::internal_read(std::shared_ptr<SourceText> text,
ts.seek_past_whitespace_and_comments();
// read list!
auto objs = read_list(ts, false);
if (add_top_level) {
return PairObject::make_new(SymbolObject::make_new(symbolTable, "top-level"), objs);
} else {
return objs;
try {
auto objs = read_list(ts, false);
if (add_top_level) {
return PairObject::make_new(Object::make_symbol(&symbolTable, "top-level"), objs);
} else {
return objs;
}
} catch (std::exception& e) {
lg::print("{}", e.what());
throw;
}
}
@@ -343,7 +344,8 @@ Token Reader::get_next_token(TextStream& stream) {
// Second - not a special token, so we read until we get a character that ends the token.
while (stream.text_remains()) {
char next = stream.peek();
if (next == ' ' || next == '\n' || next == '\t' || next == ')' || next == ';' || next == '(') {
if (next == ' ' || next == '\n' || next == '\t' || next == '\r' || next == ')' || next == ';' ||
next == '(') {
return t;
} else {
// not the end, so add to token.
@@ -461,12 +463,51 @@ bool Reader::read_array(TextStream& stream, Object& o) {
return true;
}
struct ListBuilder {
Object head;
std::shared_ptr<PairObject> prev_tail;
std::shared_ptr<PairObject> tail;
int size = 0;
ListBuilder() { head = Object::make_empty_list(); }
void push_back(Object&& o) {
size++;
if (!tail) {
tail = std::make_shared<PairObject>(o, Object{});
head.type = ObjectType::PAIR;
head.heap_obj = tail;
} else {
auto next = std::make_shared<PairObject>(o, Object{});
tail->cdr.type = ObjectType::PAIR;
tail->cdr.heap_obj = next;
prev_tail = std::move(tail);
tail = std::move(next);
}
}
Object pop_back() {
auto obj = tail->car;
tail = std::move(prev_tail);
return obj;
}
void finalize() {
if (tail) {
tail->cdr = Object::make_empty_list();
} else {
head = Object::make_empty_list();
}
}
};
/*!
* Call this on the character after the open paren.
*/
Object Reader::read_list(TextStream& ts, bool expect_close_paren) {
ts.seek_past_whitespace_and_comments();
std::vector<Object> objects;
// std::vector<Object> objects;
ListBuilder list_builder;
bool got_close_paren = false; // does this list end?
bool got_dot = false; // did we get a . ?
@@ -508,22 +549,23 @@ Object Reader::read_list(TextStream& ts, bool expect_close_paren) {
}
// inserter function, used to properly insert a next object
auto insert_object = [&](const Object& o) {
auto insert_object = [&](Object&& o) {
if (got_thing_after_dot) {
throw_reader_error(ts, "A list cannot have multiple entries after the dot", -1);
}
if (reader_macro_string_stack.empty()) {
objects.push_back(o);
list_builder.push_back(std::move(o));
// objects.push_back(o);
} else {
Object to_push_back = o;
Object to_push_back = std::move(o);
while (!reader_macro_string_stack.empty()) {
to_push_back =
build_list({SymbolObject::make_new(symbolTable, reader_macro_string_stack.back()),
to_push_back});
to_push_back = build_list(
{Object::make_symbol(&symbolTable, reader_macro_string_stack.back().c_str()),
to_push_back});
reader_macro_string_stack.pop_back();
}
objects.push_back(to_push_back);
list_builder.push_back(std::move(to_push_back));
}
// remember if we got an object after the dot
@@ -553,7 +595,7 @@ Object Reader::read_list(TextStream& ts, bool expect_close_paren) {
if (read_object(tok, ts, obj)) {
ts.seek_past_whitespace_and_comments();
insert_object(obj);
insert_object(std::move(obj));
} else {
throw_reader_error(ts, "invalid token encountered in reader: " + tok.text,
-int(tok.text.size()));
@@ -576,12 +618,12 @@ Object Reader::read_list(TextStream& ts, bool expect_close_paren) {
// build up list or improper list, link it, and return!
if (got_thing_after_dot) {
if (objects.size() < 2) {
if (list_builder.size < 2) {
throw_reader_error(ts, "A list with a dot must have at least one thing before the dot", -1);
}
auto back = objects.back();
objects.pop_back();
auto rv = build_list(objects);
auto back = list_builder.pop_back();
list_builder.finalize();
auto rv = list_builder.head;
auto lst = rv;
while (true) {
@@ -595,7 +637,8 @@ Object Reader::read_list(TextStream& ts, bool expect_close_paren) {
db.link(rv, ts.text, start_offset);
return rv;
} else {
auto rv = build_list(std::move(objects));
list_builder.finalize();
auto rv = list_builder.head;
db.link(rv, ts.text, start_offset);
return rv;
}
@@ -609,7 +652,7 @@ bool Reader::try_token_as_symbol(const Token& tok, Object& obj) {
ASSERT(!tok.text.empty());
char start = tok.text[0];
if (m_valid_symbols_chars[(int)start]) {
obj = SymbolObject::make_new(symbolTable, tok.text);
obj = Object::make_symbol(&symbolTable, tok.text.c_str());
return true;
} else {
return false;
+2 -3
View File
@@ -16,10 +16,9 @@
#include <unordered_map>
#include <utility>
#include "ReplUtils.h"
#include "common/goos/Object.h"
#include "common/goos/TextDB.h"
#include "common/repl/repl_wrapper.h"
#include "common/util/Assert.h"
namespace goos {
@@ -74,7 +73,7 @@ class Reader {
Object read_from_string(const std::string& str,
bool add_top_level = true,
const std::optional<std::string>& string_name = {});
std::optional<Object> read_from_stdin(const std::string& prompt, ReplWrapper& repl);
std::optional<Object> read_from_stdin(const std::string& prompt, REPL::Wrapper& repl);
Object read_from_file(const std::vector<std::string>& file_path, bool check_encoding = false);
bool check_string_is_valid(const std::string& str) const;
-135
View File
@@ -1,135 +0,0 @@
#include "ReplUtils.h"
#include "common/util/FileUtil.h"
#include "common/versions.h"
#include "third-party/fmt/color.h"
#include "third-party/fmt/core.h"
#include "third-party/replxx/include/replxx.hxx"
// TODO - expand a list of hints (ie. a hint for defun to show at a glance how to write a function,
// or perhaps, show the docstring for the current function being used?)
using Replxx = replxx::Replxx;
void ReplWrapper::clear_screen() {
repl.clear_screen();
}
void ReplWrapper::print_welcome_message() {
// TODO - dont print on std-out
// Welcome message / brief intro for documentation
std::string ascii;
ascii += " _____ _____ _____ _____ __ \n";
ascii += "| |___ ___ ___| __| | _ | | \n";
ascii += "| | | . | -_| | | | | | | |__ \n";
ascii += "|_____| _|___|_|_|_____|_____|__|__|_____|\n";
ascii += " |_| \n";
fmt::print(fmt::emphasis::bold | fg(fmt::color::orange), ascii);
fmt::print("Welcome to OpenGOAL {}.{}!\n", versions::GOAL_VERSION_MAJOR,
versions::GOAL_VERSION_MINOR);
fmt::print("Run ");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(repl-help)");
fmt::print(" for help with common commands and REPL usage.\n");
fmt::print("Run ");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(lt)");
fmt::print(" to connect to the local target.\n");
fmt::print("Run ");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(mi)");
fmt::print(" to rebuild the entire game.\n\n");
}
void ReplWrapper::print_to_repl(const std::string_view& str) {
repl.print(str.data());
}
void ReplWrapper::set_history_max_size(size_t len) {
repl.set_max_history_size(len);
}
const char* ReplWrapper::readline(const std::string& prompt) {
return repl.input(prompt);
}
void ReplWrapper::add_to_history(const std::string& line) {
repl.history_add(line);
}
void ReplWrapper::save_history() {
fs::path path = file_util::get_user_config_dir() / ".opengoal.repl.history";
file_util::create_dir_if_needed_for_file(path.string());
repl.history_save(path.string());
}
void ReplWrapper::load_history() {
fs::path path = file_util::get_user_config_dir() / ".opengoal.repl.history";
if (fs::exists(path)) {
repl.history_load(path.string());
} else {
fmt::print("Couldn't locate REPL history file at '{}'\n", path.string());
}
}
std::pair<std::string, bool> ReplWrapper::get_current_repl_token(std::string const& context) {
// Find the current token
std::string token = "";
for (auto c = context.crbegin(); c != context.crend(); c++) {
if (std::isspace(*c)) {
break;
} else {
token = *c + token;
}
}
// If there is a preceeding '(' remove it
if (!token.empty() && token.at(0) == '(') {
token.erase(0, 1);
return {token, true};
}
return {token, false};
}
void ReplWrapper::print_help_message() {
fmt::print(fmt::emphasis::bold, "\nREPL Controls:\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(:clear)\n");
fmt::print(" - Clear the current screen\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(e)\n");
fmt::print(" - Exit the compiler\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(lt [ip-address] [port-number])\n");
fmt::print(
" - Connect the listener to a running target. The IP address defaults to `127.0.0.1` and the "
"port to `8112`\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(r [ip-address] [port-number])\n");
fmt::print(
" - Attempt to reset the target and reconnect. After this, the target will have nothing "
"loaded.\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(:status)\n");
fmt::print(" - Send a ping-like message to the target. Requires the target to be connected\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(shutdown-target)\n");
fmt::print(" - If the target is connected, make it exit\n");
fmt::print(fmt::emphasis::bold, "\nCompiling & Building:\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(mi)\n");
fmt::print(" - Build entire game\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(mng)\n");
fmt::print(" - Build game engine\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(m \"filename\")\n");
fmt::print(" - Compile an OpenGOAL source file\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(ml \"filename\")\n");
fmt::print(" - Compile and Load (or reload) an OpenGOAL source file\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(build-kernel)\n");
fmt::print(" - Build the GOAL kernel\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(make \"file-name\")\n");
fmt::print(
" - Build a file and any out-of-date dependencies. This file must be a target in the make "
"system.\n");
fmt::print(fmt::emphasis::bold, "\nOther:\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::magenta), "(gs)\n");
fmt::print(" - Enter a GOOS REPL\n");
}
void ReplWrapper::init_default_settings() {
repl.set_word_break_characters(" \t");
}
-34
View File
@@ -1,34 +0,0 @@
#pragma once
#include <functional>
#include <string>
#include <vector>
#include "third-party/replxx/include/replxx.hxx"
using Replxx = replxx::Replxx;
class ReplWrapper {
Replxx repl;
public:
ReplWrapper() {}
Replxx& get_repl() { return repl; }
void init_default_settings();
// Functionality / Commands
void clear_screen();
void print_to_repl(const std::string_view& str);
void print_welcome_message();
void set_history_max_size(size_t len);
const char* readline(const std::string& prompt);
void add_to_history(const std::string& line);
void save_history();
void load_history();
void print_help_message();
std::pair<std::string, bool> get_current_repl_token(std::string const& context);
std::vector<std::string> examples{};
using cl = Replxx::Color;
std::vector<std::pair<std::string, cl>> regex_colors{};
};
+46 -35
View File
@@ -15,7 +15,7 @@
#include "common/util/FileUtil.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
namespace goos {
@@ -85,9 +85,9 @@ std::pair<int, int> SourceText::get_containing_line(int offset) {
/*!
* Read text from a file.
*/
FileText::FileText(const std::string& filename, const std::string& description_name)
: m_filename(filename), m_desc_name(description_name) {
m_text = file_util::read_text_file(m_filename);
FileText::FileText(const std::string& file_path, const std::string& description_name)
: m_filepath(file_path), m_desc_name(description_name) {
m_text = file_util::read_text_file(m_filepath);
build_offsets();
}
@@ -175,39 +175,45 @@ std::optional<TextDb::ShortInfo> TextDb::get_short_info_for(const std::shared_pt
return std::make_optional(info_result);
}
std::optional<TextDb::ShortInfo> TextDb::try_get_short_info(
const std::shared_ptr<goos::HeapObject>& heap_obj) 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 (start < name.size()) {
name = name.substr(start);
}
ShortInfo result;
result.filename = name;
int line_idx = frag->get_line_idx(it->second.offset);
result.line_idx_to_display = line_idx + 1;
int offset_of_line = frag->get_offset_of_line(line_idx);
int offset_of_next_line = frag->get_offset_of_line(line_idx + 1);
int line_length = offset_of_next_line - offset_of_line;
int start_offset_in_line = it->second.offset - offset_of_line - 1;
result.pos_in_line = std::max(start_offset_in_line, 0);
result.line_text = std::string(frag->get_text() + offset_of_line + 1, line_length - 1);
return result;
}
return {};
}
std::optional<TextDb::ShortInfo> TextDb::try_get_short_info(const Object& o) const {
if (o.is_pair()) {
auto it = m_map.find(o.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 (start < name.size()) {
name = name.substr(start);
}
ShortInfo result;
result.filename = name;
int line_idx = frag->get_line_idx(it->second.offset);
result.line_idx_to_display = line_idx + 1;
int offset_of_line = frag->get_offset_of_line(line_idx);
int offset_of_next_line = frag->get_offset_of_line(line_idx + 1);
int line_length = offset_of_next_line - offset_of_line;
int start_offset_in_line = it->second.offset - offset_of_line - 1;
result.pos_in_line = std::max(start_offset_in_line, 0);
result.line_text = std::string(frag->get_text() + offset_of_line + 1, line_length - 1);
return result;
}
return try_get_short_info(o.heap_obj);
}
return {};
@@ -245,4 +251,9 @@ void TextDb::inherit_info(const Object& parent, const Object& child) {
}
}
}
void TextDb::clear_info() {
m_map.clear();
m_fragments.clear();
}
} // namespace goos
+5 -2
View File
@@ -80,13 +80,13 @@ class ProgramString : public SourceText {
*/
class FileText : public SourceText {
public:
FileText(const std::string& filename, const std::string& description_name);
FileText(const std::string& file_path, const std::string& description_name);
std::string get_description() { return m_desc_name; }
~FileText() = default;
private:
std::string m_filename;
std::string m_filepath;
std::string m_desc_name;
};
@@ -112,8 +112,11 @@ 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;
bool has_info(const Object& o) const;
void inherit_info(const Object& parent, const Object& child);
void clear_info();
private:
std::vector<std::shared_ptr<SourceText>> m_fragments;
+15
View File
@@ -54,6 +54,21 @@ struct LinkHeaderV4 {
uint32_t code_size; // length of object data before link data starts
};
struct LinkHeaderV5Core {
uint32_t length_to_get_to_code; // 4 length.. of link data?
uint16_t version; // 8
uint16_t unknown; // 10
uint32_t length_to_get_to_link; // 12
uint32_t link_length; // 16
uint8_t n_segments; // 20
char name[59]; // 21 (really??)
};
struct LinkHeaderV5 {
uint32_t type_tag; // 0 always 0?
LinkHeaderV5Core core;
};
// 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;
+1 -1
View File
@@ -34,7 +34,7 @@ enum class ListenerMessageKind : u16 {
*/
enum ListenerToTargetMsgKind : u16 {
LTT_MSG_POKE = 1, //! "Poke" the game and have it flush buffers
LTT_MSG_INSEPCT = 5, //! Inspect an object
LTT_MSG_INSPECT = 5, //! Inspect an object
LTT_MSG_PRINT = 6, //! Print an object
LTT_MSG_PRINT_SYMBOLS = 7, //! Print all symbols
LTT_MSG_RESET = 8, //! Reset the game
+125 -16
View File
@@ -1,10 +1,11 @@
#include "log.h"
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <mutex>
#include "third-party/fmt/color.h"
#include "fmt/color.h"
#ifdef _WIN32 // see lg::initialize
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
@@ -12,6 +13,7 @@
#endif
#include "common/util/Assert.h"
#include "common/util/FileUtil.h"
#include "common/util/string_util.h"
namespace lg {
struct Logger {
@@ -23,6 +25,7 @@ struct Logger {
level file_log_level = level::trace;
level flush_level = level::trace;
std::mutex mutex;
bool disable_colors = false;
~Logger() {
// will run when program exits.
@@ -35,21 +38,22 @@ struct Logger {
Logger gLogger;
namespace internal {
const char* log_level_names[] = {"trace", "debug", "info", "warn", "error", "die"};
const fmt::color log_colors[] = {fmt::color::gray, fmt::color::turquoise, fmt::color::light_green,
fmt::color::yellow, fmt::color::red, fmt::color::hot_pink};
const char* log_level_names[] = {"trace", "debug", "info", "warn", "error", "die", "die"};
const fmt::color log_colors[] = {
fmt::color::gray, fmt::color::turquoise, fmt::color::light_green, fmt::color::yellow,
fmt::color::red, fmt::color::hot_pink, fmt::color::hot_pink};
void log_message(level log_level, LogTime& now, const char* message) {
#ifdef __linux__
char date_time_buffer[128];
time_t now_seconds = now.tv.tv_sec;
auto now_milliseconds = now.tv.tv_usec / 1000;
strftime(date_time_buffer, 128, "%Y-%m-%d %H:%M:%S", localtime(&now_seconds));
std::string date_string = fmt::format("[{}:{:03d}]", date_time_buffer, now_milliseconds);
strftime(date_time_buffer, 128, "%M:%S", localtime(&now_seconds));
std::string time_string = fmt::format("[{}:{:03d}]", date_time_buffer, now_milliseconds);
#else
char date_time_buffer[128];
strftime(date_time_buffer, 128, "%Y-%m-%d %H:%M:%S", localtime(&now.tim));
std::string date_string = fmt::format("[{}]", date_time_buffer);
strftime(date_time_buffer, 128, "%M:%S", localtime(&now.tim));
std::string time_string = fmt::format("[{}]", date_time_buffer);
#endif
{
@@ -57,33 +61,134 @@ void log_message(level log_level, LogTime& now, const char* message) {
if (gLogger.fp && log_level >= gLogger.file_log_level) {
// log to file
std::string file_string =
fmt::format("{} [{}] {}\n", date_string, log_level_names[int(log_level)], message);
fmt::format("{} [{}] {}\n", time_string, log_level_names[int(log_level)], message);
fwrite(file_string.c_str(), file_string.length(), 1, gLogger.fp);
if (log_level >= gLogger.flush_level) {
fflush(gLogger.fp);
}
}
if (log_level >= gLogger.stdout_log_level) {
fmt::print("{} [", date_string);
fmt::print(fg(log_colors[int(log_level)]), "{}", log_level_names[int(log_level)]);
if (log_level >= gLogger.stdout_log_level ||
(log_level == level::die && gLogger.stdout_log_level == level::off_unless_die)) {
fmt::print("{} [", time_string);
if (gLogger.disable_colors) {
fmt::print("{}", log_level_names[int(log_level)]);
} else {
fmt::print(fg(log_colors[int(log_level)]), "{}", log_level_names[int(log_level)]);
}
fmt::print("] {}\n", message);
if (log_level >= gLogger.flush_level) {
fflush(stdout);
fflush(stderr);
}
}
}
if (log_level == level::die) {
exit(-1);
fflush(stdout);
fflush(stderr);
if (gLogger.fp) {
fflush(gLogger.fp);
}
abort();
}
}
void log_print(const char* message) {
{
// 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.
std::lock_guard<std::mutex> lock(gLogger.mutex);
if (gLogger.fp) {
// Log to File
std::string msg(message);
fwrite(msg.c_str(), msg.length(), 1, gLogger.fp);
fflush(gLogger.fp);
}
if (gLogger.stdout_log_level < lg::level::off_unless_die) {
fmt::print("{}", message);
fflush(stdout);
fflush(stderr);
}
}
}
void log_vprintf(const char* format, va_list arg_list) {
{
// 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.
std::lock_guard<std::mutex> lock(gLogger.mutex);
va_list arg_list_2;
va_copy(arg_list_2, arg_list);
if (gLogger.fp) {
// Log to File
vfprintf(gLogger.fp, format, arg_list);
fflush(gLogger.fp);
}
if (gLogger.stdout_log_level < lg::level::off_unless_die) {
vprintf(format, arg_list_2);
fflush(stdout);
fflush(stderr);
}
}
}
} // namespace internal
void set_file(const std::string& filename) {
void printstd(const char* format, va_list arg_list) {
internal::log_vprintf(format, arg_list);
}
// how many extra log files for a single program should be kept?
constexpr int LOG_ROTATE_MAX = 10;
void set_file(const std::string& filename,
const bool should_rotate,
const bool append,
const std::string& dir) {
ASSERT(!gLogger.fp);
file_util::create_dir_if_needed_for_file(filename);
gLogger.fp = file_util::open_file(filename.c_str(), "w");
std::string file_path;
if (!dir.empty()) {
file_path = file_util::combine_path(dir, filename);
} else {
file_path = file_util::get_file_path({"log", filename});
}
file_util::create_dir_if_needed_for_file(file_path);
std::string complete_filename = file_path;
if (should_rotate) {
complete_filename += "." + str_util::current_local_timestamp_no_colons() + ".log";
// remove any log files with the old format
auto old_log_files =
file_util::find_files_in_dir(fs::path(complete_filename).parent_path(),
std::regex(fmt::format("{}\\.(\\d\\.)?log", filename)));
for (const auto& file : old_log_files) {
lg::debug("removing {}", file.string());
fs::remove(file);
}
// remove the oldest log file if there are more than LOG_ROTATE_MAX
auto existing_log_files = file_util::find_files_in_dir(
fs::path(complete_filename).parent_path(), std::regex(fmt::format("{}.*\\.log", filename)));
// sort the names and remove them
existing_log_files = file_util::sort_filepaths(existing_log_files, true);
if (existing_log_files.size() > (LOG_ROTATE_MAX - 1)) {
lg::debug("removing {} log files", existing_log_files.size() - (LOG_ROTATE_MAX - 1));
for (int i = 0; i < (int)existing_log_files.size() - (LOG_ROTATE_MAX - 1); i++) {
lg::debug("removing {}", existing_log_files.at(i).string());
fs::remove(existing_log_files.at(i));
}
}
} else {
if (!str_util::ends_with(complete_filename, ".log")) {
complete_filename += ".log";
}
}
if (append) {
gLogger.fp = file_util::open_file(complete_filename.c_str(), "a");
} else {
gLogger.fp = file_util::open_file(complete_filename.c_str(), "w");
}
ASSERT(gLogger.fp);
}
@@ -105,6 +210,10 @@ void set_max_debug_levels() {
gLogger.file_log_level = level::trace;
}
void disable_ansi_colors() {
gLogger.disable_colors = true;
}
void initialize() {
ASSERT(!gLogger.initialized);
+34 -4
View File
@@ -7,7 +7,8 @@
#endif
#include <string>
#include "third-party/fmt/core.h"
#include "fmt/color.h"
#include "fmt/core.h"
namespace lg {
@@ -22,18 +23,33 @@ struct LogTime {
#endif
// Logging API
enum class level { trace = 0, debug = 1, info = 2, warn = 3, error = 4, die = 5, off = 6 };
enum class level {
trace = 0,
debug = 1,
info = 2,
warn = 3,
error = 4,
die = 5,
off_unless_die = 6,
off = 7
};
namespace internal {
// log implementation stuff, not to be called by the user
void log_message(level log_level, LogTime& now, const char* message);
void log_print(const char* message);
void log_vprintf(const char* format, va_list arg_list);
} // namespace internal
void set_file(const std::string& filename);
void set_file(const std::string& filename,
const bool should_rotate = true,
const bool append = false,
const std::string& dir = "");
void set_flush_level(level log_level);
void set_file_level(level log_level);
void set_stdout_level(level log_level);
void set_max_debug_levels();
void disable_ansi_colors();
void initialize();
void finish();
@@ -45,10 +61,24 @@ void log(level log_level, const std::string& format, Args&&... args) {
#else
now.tim = time(nullptr);
#endif
std::string formatted_message = fmt::format(format, std::forward<Args>(args)...);
std::string formatted_message = fmt::format(fmt::runtime(format), std::forward<Args>(args)...);
internal::log_message(log_level, now, formatted_message.c_str());
}
template <typename... Args>
void print(const std::string& format, Args&&... args) {
std::string formatted_message = fmt::format(fmt::runtime(format), std::forward<Args>(args)...);
internal::log_print(formatted_message.c_str());
}
template <typename... Args>
void print(const fmt::text_style& ts, const std::string& format, Args&&... args) {
std::string formatted_message = fmt::format(ts, format, std::forward<Args>(args)...);
internal::log_print(formatted_message.c_str());
}
// same as print but uses the C printf instead of fmt
void printstd(const char* format, va_list arg_list);
template <typename... Args>
void trace(const std::string& format, Args&&... args) {
log(level::trace, format, std::forward<Args>(args)...);
+52 -2
View File
@@ -2,7 +2,7 @@
#include <cmath>
#include "third-party/fmt/core.h"
#include "fmt/core.h"
namespace math {
@@ -18,8 +18,16 @@ class Vector {
return result;
}
static Vector<T, Size> unit(int idx) {
Vector<T, Size> result = Vector<T, Size>::zero();
result[idx] = T(1);
return result;
}
template <typename... Args>
explicit Vector(Args... args) : m_data{T(args)...} {}
constexpr Vector(Args... args) : m_data{T(args)...} {
static_assert(sizeof...(args) == Size, "Incorrect number of args");
}
T* begin() { return &m_data[0]; }
T* end() { return &m_data[Size]; }
@@ -77,7 +85,17 @@ class Vector {
return true;
}
bool operator==(const T other) const {
for (int i = 0; i < Size; i++) {
if (m_data[i] != other) {
return false;
}
}
return true;
}
bool operator!=(const Vector<T, Size>& other) const { return !((*this) == other); }
bool operator!=(const T other) const { return !((*this) == other); }
const T length() const { return std::sqrt(squared_length()); }
@@ -118,6 +136,13 @@ class Vector {
return *this;
}
Vector<T, Size>& operator+=(const T& other) {
for (int i = 0; i < Size; i++) {
m_data[i] += other;
}
return *this;
}
Vector<T, Size> elementwise_multiply(const Vector<T, Size>& other) const {
Vector<T, Size> result;
for (int i = 0; i < Size; i++) {
@@ -207,6 +232,22 @@ class Vector {
}
}
Vector<T, Size> min(const Vector<T, Size>& other) const {
Vector<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::min(m_data[i], other[i]);
}
return result;
}
Vector<T, Size> max(const Vector<T, Size>& other) const {
Vector<T, Size> result;
for (int i = 0; i < Size; i++) {
result[i] = std::max(m_data[i], other[i]);
}
return result;
}
std::string to_string_aligned() const {
std::string result = "[";
for (auto x : m_data) {
@@ -225,6 +266,15 @@ class Vector {
return result + "]";
}
std::string to_string_hex_word() const {
std::string result = "[";
for (auto x : m_data) {
result.append(fmt::format("0x{:08x} ", x));
}
result.pop_back();
return result + "]";
}
T* data() { return m_data; }
const T* data() const { return m_data; }
+74
View File
@@ -50,4 +50,78 @@ math::Vector4f bsphere_of_triangle(const Vector3f* vertices);
inline bool point_in_bsphere(const Vector4f& sphere, const Vector3f& pt) {
return (sphere.xyz() - pt).squared_length() <= (sphere.w() * sphere.w());
}
template <typename T>
math::Matrix<T, 4, 4> affine_inverse(const math::Matrix<T, 4, 4>& in) {
math::Matrix<T, 4, 4> result;
// transpose rotation
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
result(i, j) = in(j, i);
}
}
result(3, 0) = 0;
result(3, 1) = 0;
result(3, 2) = 0;
result(3, 3) = 1;
result(0, 3) = 0;
result(1, 3) = 0;
result(2, 3) = 0;
for (int rx = 0; rx < 3; rx++) {
for (int cx = 0; cx < 3; cx++) {
result(rx, 3) -= result(rx, cx) * in(cx, 3);
}
}
return result;
}
template <typename T>
math::Matrix<T, 4, 4> inverse(const math::Matrix<T, 4, 4>& m) {
math::Matrix<T, 4, 4> im;
T A2323 = m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2);
T A1323 = m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1);
T A1223 = m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1);
T A0323 = m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0);
T A0223 = m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0);
T A0123 = m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0);
T A2313 = m(1, 2) * m(3, 3) - m(1, 3) * m(3, 2);
T A1313 = m(1, 1) * m(3, 3) - m(1, 3) * m(3, 1);
T A1213 = m(1, 1) * m(3, 2) - m(1, 2) * m(3, 1);
T A2312 = m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2);
T A1312 = m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1);
T A1212 = m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1);
T A0313 = m(1, 0) * m(3, 3) - m(1, 3) * m(3, 0);
T A0213 = m(1, 0) * m(3, 2) - m(1, 2) * m(3, 0);
T A0312 = m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0);
T A0212 = m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0);
T A0113 = m(1, 0) * m(3, 1) - m(1, 1) * m(3, 0);
T A0112 = m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0);
T det = m(0, 0) * (m(1, 1) * A2323 - m(1, 2) * A1323 + m(1, 3) * A1223) -
m(0, 1) * (m(1, 0) * A2323 - m(1, 2) * A0323 + m(1, 3) * A0223) +
m(0, 2) * (m(1, 0) * A1323 - m(1, 1) * A0323 + m(1, 3) * A0123) -
m(0, 3) * (m(1, 0) * A1223 - m(1, 1) * A0223 + m(1, 2) * A0123);
det = 1 / det;
im(0, 0) = det * (m(1, 1) * A2323 - m(1, 2) * A1323 + m(1, 3) * A1223);
im(0, 1) = det * -(m(0, 1) * A2323 - m(0, 2) * A1323 + m(0, 3) * A1223);
im(0, 2) = det * (m(0, 1) * A2313 - m(0, 2) * A1313 + m(0, 3) * A1213);
im(0, 3) = det * -(m(0, 1) * A2312 - m(0, 2) * A1312 + m(0, 3) * A1212);
im(1, 0) = det * -(m(1, 0) * A2323 - m(1, 2) * A0323 + m(1, 3) * A0223);
im(1, 1) = det * (m(0, 0) * A2323 - m(0, 2) * A0323 + m(0, 3) * A0223);
im(1, 2) = det * -(m(0, 0) * A2313 - m(0, 2) * A0313 + m(0, 3) * A0213);
im(1, 3) = det * (m(0, 0) * A2312 - m(0, 2) * A0312 + m(0, 3) * A0212);
im(2, 0) = det * (m(1, 0) * A1323 - m(1, 1) * A0323 + m(1, 3) * A0123);
im(2, 1) = det * -(m(0, 0) * A1323 - m(0, 1) * A0323 + m(0, 3) * A0123);
im(2, 2) = det * (m(0, 0) * A1313 - m(0, 1) * A0313 + m(0, 3) * A0113);
im(2, 3) = det * -(m(0, 0) * A1312 - m(0, 1) * A0312 + m(0, 3) * A0112);
im(3, 0) = det * -(m(1, 0) * A1223 - m(1, 1) * A0223 + m(1, 2) * A0123);
im(3, 1) = det * (m(0, 0) * A1223 - m(0, 1) * A0223 + m(0, 2) * A0123);
im(3, 2) = det * -(m(0, 0) * A1213 - m(0, 1) * A0213 + m(0, 2) * A0113);
im(3, 3) = det * (m(0, 0) * A1212 - m(0, 1) * A0212 + m(0, 2) * A0112);
return im;
}
} // namespace math
-151
View File
@@ -1,151 +0,0 @@
// clang-format off
#include "ReplServer.h"
#include "common/cross_sockets/XSocket.h"
#include <common/versions.h>
#include "third-party/fmt/core.h"
#ifdef _WIN32
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif
// clang-format on
// TODO - basically REPL to listen and inject commands into a running REPL
// - we will need a C++ side client as well which will let us communicate with the repl via for
// example, ImgUI
//
// TODO - The server also needs to eventually return the result of the evaluation
ReplServer::~ReplServer() {
// Close all our client sockets!
for (const int& sock : client_sockets) {
close_socket(sock);
}
}
void ReplServer::post_init() {
// Add the listening socket to our set of sockets
fmt::print("[nREPL:{}:{}] awaiting connections\n", tcp_port, listening_socket);
}
void ReplServer::ping_response(int socket) {
std::string ping = fmt::format("Connected to OpenGOAL v{}.{} nREPL!",
versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR);
auto resp = write_to_socket(socket, ping.c_str(), ping.size());
if (resp == -1) {
fmt::print("[nREPL:{}] Client Disconnected: {}\n", tcp_port, inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port), socket);
close_socket(socket);
client_sockets.erase(socket);
}
}
std::optional<std::string> ReplServer::get_msg() {
// Clear the sockets we are listening on
FD_ZERO(&read_sockets);
// Add the server's main listening socket (where we accept clients from)
FD_SET(listening_socket, &read_sockets);
int max_sd = listening_socket;
for (const int& sock : client_sockets) {
if (sock > max_sd) {
max_sd = sock;
}
if (sock > 0) {
FD_SET(sock, &read_sockets);
}
}
// Wait for activity on _something_, with a timeout so we don't get stuck here on exit.
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
auto activity = select(max_sd + 1, &read_sockets, NULL, NULL, &timeout);
if (activity < 0) { // TODO - || error!
return std::nullopt;
}
// If something happened on the master socket - it's a new connection
if (FD_ISSET(listening_socket, &read_sockets)) {
socklen_t addr_len = sizeof(addr);
auto new_socket = accept_socket(listening_socket, (sockaddr*)&addr, &addr_len);
if (new_socket < 0) {
// TODO - handle error
} else {
fmt::print("[nREPL:{}]: New socket connection: {}:{}:{}\n", tcp_port,
inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), new_socket);
// Say hello
ping_response(new_socket);
// Track the new socket
if ((int)client_sockets.size() < max_clients) {
client_sockets.insert(new_socket);
} else {
// TODO - Respond with NO
}
}
}
// otherwise (and no matter what) check all the clients to see if they have sent us anything
// else its some IO operation on some other socket
//
// RACE - the first client wins
// TODO - there are ways to do this with iterators but, couldn't figure it out!
std::vector<int> sockets_to_scan(client_sockets.begin(), client_sockets.end());
for (const int& sock : sockets_to_scan) {
if (FD_ISSET(sock, &read_sockets)) {
// Attempt to read a header
// TODO - should this be in a loop?
auto req_bytes = read_from_socket(sock, header_buffer.data(), header_buffer.size());
if (req_bytes == 0) {
// Socket disconnected
// TODO - add a queue of messages in the ReplWrapper so we can print _BEFORE_ the prompt is
// output
fmt::print("[nREPL:{}] Client Disconnected: {}\n", tcp_port, inet_ntoa(addr.sin_addr),
ntohs(addr.sin_port), sock);
// Cleanup the socket and remove it from our set
close_socket(sock);
client_sockets.erase(sock);
} else {
// Otherwise, process the message
auto* header = (ReplServerHeader*)(header_buffer.data());
// get the body of the message
int expected_size = header->length;
int got = 0;
while (got < expected_size) {
if (got + expected_size > (int)buffer.size()) {
fmt::print(stderr,
"[nREPL:{}]: Bad message, aborting the read. Got :{}, Expected: {}, Buffer "
"Size: {}",
tcp_port, got, expected_size, buffer.size());
return std::nullopt;
}
auto x = read_from_socket(sock, buffer.data() + got, expected_size - got);
if (want_exit_callback()) {
return std::nullopt;
}
got += x > 0 ? x : 0;
}
switch (header->type) {
case ReplServerMessageType::PING:
ping_response(sock);
return std::nullopt;
case ReplServerMessageType::EVAL:
std::string msg(buffer.data(), header->length);
return std::make_optional(msg);
}
}
}
}
return std::nullopt;
}
+112
View File
@@ -0,0 +1,112 @@
#include "config.h"
#include "common/versions/versions.h"
#include "fmt/core.h"
namespace REPL {
void to_json(json& j, const Config& obj) {
j = json{
{"nreplPort", obj.nrepl_port},
{"gameVersionFolder", obj.game_version_folder},
{"numConnectToTargetAttempts", obj.target_connect_attempts},
{"asmFileSearchDirs", obj.asm_file_search_dirs},
{"keybinds", obj.keybinds},
{"perGameHistory", obj.per_game_history},
{"permissiveRedefinitions", obj.permissive_redefinitions},
};
}
void from_json(const json& j, Config& obj) {
// TODO - make a camelCase variant of json_serialize/deserialize macros
if (j.contains("nreplPort")) {
j.at("nreplPort").get_to(obj.nrepl_port);
}
if (j.contains("gameVersionFolder")) {
j.at("gameVersionFolder").get_to(obj.game_version_folder);
}
if (j.contains("numConnectToTargetAttempts")) {
j.at("numConnectToTargetAttempts").get_to(obj.target_connect_attempts);
}
if (j.contains("asmFileSearchDirs")) {
j.at("asmFileSearchDirs").get_to(obj.asm_file_search_dirs);
}
if (j.contains("appendKeybinds")) {
j.at("appendKeybinds").get_to(obj.append_keybinds);
}
if (j.contains("keybinds")) {
std::vector<KeyBind> keybinds = j.at("keybinds");
if (!obj.append_keybinds) {
obj.keybinds = keybinds;
} else {
// append the keybinds
// - start with the provided ones
// - skip ones from the default set if they have the same key + modifier combination
for (const auto& default_bind : obj.keybinds) {
// check if it's a duplicate bind
bool duplicate = false;
for (const auto& new_bind : keybinds) {
if (new_bind.key == default_bind.key && new_bind.modifier == default_bind.modifier) {
duplicate = true;
break;
}
}
if (!duplicate) {
keybinds.push_back(default_bind);
}
}
obj.keybinds = keybinds;
}
}
if (j.contains("perGameHistory")) {
j.at("perGameHistory").get_to(obj.per_game_history);
}
if (j.contains("permissiveRedefinitions")) {
j.at("permissiveRedefinitions").get_to(obj.permissive_redefinitions);
}
// if there is game specific configuration, override any values we just set
if (j.contains(version_to_game_name(obj.game_version))) {
from_json(j.at(version_to_game_name(obj.game_version)), obj);
}
}
std::string KeyBind::string() const {
switch (modifier) {
case KeyBind::Modifier::CTRL:
return fmt::format("CTRL-{}", key);
case KeyBind::Modifier::SHIFT:
return fmt::format("SHIFT-{}", key);
case KeyBind::Modifier::META:
return fmt::format("META-{}", key);
}
}
void to_json(json& j, const KeyBind& obj) {
j = json{{"description", obj.description}, {"command", obj.command}, {"key", obj.key}};
switch (obj.modifier) {
case KeyBind::Modifier::CTRL:
j["modifier"] = "ctrl";
break;
case KeyBind::Modifier::SHIFT:
j["modifier"] = "shift";
break;
case KeyBind::Modifier::META:
j["modifier"] = "meta";
break;
}
}
void from_json(const json& j, KeyBind& obj) {
j.at("description").get_to(obj.description);
j.at("command").get_to(obj.command);
j.at("key").get_to(obj.key);
auto modString = j.at("modifier").get<std::string>();
if (modString == "ctrl") {
obj.modifier = KeyBind::Modifier::CTRL;
} else if (modString == "shift") {
obj.modifier = KeyBind::Modifier::SHIFT;
} else if (modString == "meta") {
obj.modifier = KeyBind::Modifier::META;
}
}
} // namespace REPL
+63
View File
@@ -0,0 +1,63 @@
#pragma once
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
#include "common/versions/versions.h"
#include "third-party/json.hpp"
using json = nlohmann::json;
namespace REPL {
struct KeyBind {
// NOTE - in my experience, meta doesn't work on windows and shift is probably a bad idea when
// typing text! but I leave it up to the user.
enum class Modifier { CTRL, SHIFT, META };
Modifier modifier;
std::string key;
std::string description;
std::string command;
std::string string() const;
};
void to_json(json& j, const KeyBind& obj);
void from_json(const json& j, KeyBind& obj);
// TODO - per-game config
struct Config {
GameVersion game_version;
Config(GameVersion _game_version) : game_version(_game_version){};
// this is the default REPL configuration
int nrepl_port = 8181;
int temp_nrepl_port = -1;
std::string game_version_folder;
int target_connect_attempts = 30;
std::vector<std::string> asm_file_search_dirs = {};
bool append_keybinds = true;
std::vector<KeyBind> keybinds = {
{KeyBind::Modifier::CTRL, "T", "Starts up the game runtime", "(test-play)"},
{KeyBind::Modifier::CTRL, "Q", "Exit the REPL", "(e)"},
{KeyBind::Modifier::CTRL, "L", "Listen to an available game process", "(lt)"},
{KeyBind::Modifier::CTRL, "W",
"Halt the attached process so you can re-launch a crashed game", "(:stop)"},
{KeyBind::Modifier::CTRL, "G", "Attach the debugger to the process", "(dbgc)"},
{KeyBind::Modifier::CTRL, "B", "Displays the most recently caught backtrace", "(:di)"},
{KeyBind::Modifier::CTRL, "N", "Full build of the game", "(mi)"}};
bool per_game_history = true;
bool permissive_redefinitions = false;
int get_nrepl_port() {
if (temp_nrepl_port != -1) {
return temp_nrepl_port;
}
return nrepl_port;
}
};
void to_json(json& j, const Config& obj);
void from_json(const json& j, Config& obj);
} // namespace REPL
@@ -2,9 +2,9 @@
#include "ReplClient.h"
#include "common/cross_sockets/XSocket.h"
#include "common/versions.h"
#include "common/versions/versions.h"
#include "third-party/fmt/core.h"
#include "fmt/core.h"
#ifdef _WIN32
#define NOMINMAX
File renamed without changes.
+185
View File
@@ -0,0 +1,185 @@
// clang-format off
#include "ReplServer.h"
#include "common/cross_sockets/XSocket.h"
#include "common/versions/versions.h"
#include "fmt/core.h"
#ifdef _WIN32
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#endif
#include "common/log/log.h"
// clang-format on
// TODO - The server also needs to eventually return the result of the evaluation
ReplServer::~ReplServer() {
// Close all our client sockets!
for (const int& sock : client_sockets) {
close_socket(sock);
}
}
void ReplServer::post_init() {
// Add the listening socket to our set of sockets
lg::debug("[nREPL:{}:{}] awaiting connections", tcp_port, listening_socket);
}
void ReplServer::error_response(int socket, const std::string& error) {
std::string msg = fmt::format("[ERROR]: {}", error);
auto resp = write_to_socket(socket, msg.c_str(), msg.size());
if (resp == -1) {
lg::warn("[nREPL:{}] Client Disconnected: {}", tcp_port, address_to_string(addr),
ntohs(addr.sin_port), socket);
close_socket(socket);
client_sockets.erase(socket);
}
}
void ReplServer::ping_response(int socket) {
std::string ping = fmt::format("Connected to OpenGOAL v{}.{} nREPL!",
versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR);
auto resp = write_to_socket(socket, ping.c_str(), ping.size());
if (resp == -1) {
lg::warn("[nREPL:{}] Client Disconnected: {}", tcp_port, address_to_string(addr),
ntohs(addr.sin_port), socket);
close_socket(socket);
client_sockets.erase(socket);
}
}
std::optional<std::string> ReplServer::get_msg() {
// Clear the sockets we are listening on
FD_ZERO(&read_sockets);
// Add the server's main listening socket (where we accept clients from)
FD_SET(listening_socket, &read_sockets);
int max_sd = listening_socket;
for (const int& sock : client_sockets) {
if (sock > max_sd) {
max_sd = sock;
}
if (sock > 0) {
FD_SET(sock, &read_sockets);
}
}
// Wait for activity on _something_, with a timeout so we don't get stuck here on exit.
struct timeval timeout = {0, 100000};
auto activity = select(max_sd + 1, &read_sockets, NULL, NULL, &timeout);
if (activity < 0 && errno != EINTR) {
lg::error("[nREPL:{}] select error, returned: {}, errno: {}", tcp_port, activity,
strerror(errno));
return std::nullopt;
}
// If something happened on the master socket - it's a new connection
if (FD_ISSET(listening_socket, &read_sockets)) {
socklen_t addr_len = sizeof(addr);
auto new_socket = accept_socket(listening_socket, (sockaddr*)&addr, &addr_len);
if (new_socket < 0) {
if (new_socket != -1) {
lg::error("[nREPL:{}] accept error, returned: {}, errono: {}", tcp_port, new_socket,
strerror(errno));
}
} else {
lg::info("[nREPL:{}]: New socket connection: {}:{}:{}", tcp_port, address_to_string(addr),
ntohs(addr.sin_port), new_socket);
// Say hello
ping_response(new_socket);
// Track the new socket
if ((int)client_sockets.size() < max_clients) {
client_sockets.insert(new_socket);
} else {
// Respond with NO and close the socket
lg::warn("[nREPL:{}]: Maximum clients reached. Rejecting connection.", tcp_port);
error_response(new_socket, "Maximum clients reached. Rejecting connection.");
close_socket(new_socket);
}
}
}
// Check all clients for activity
for (auto it = client_sockets.begin(); it != client_sockets.end();) {
int sock = *it;
if (FD_ISSET(sock, &read_sockets)) {
// Attempt to read a header
auto req_bytes = read_from_socket(sock, header_buffer.data(), header_buffer.size());
if (req_bytes <= 0) {
// TODO - add a queue of messages in the REPL::Wrapper so we can print _BEFORE_ the prompt
// is output
if (req_bytes == 0) {
lg::warn("[nREPL:{}] Client Disconnected: {}", tcp_port, address_to_string(addr));
} else {
lg::warn("[nREPL:{}] Error reading from socket on {}: {}", tcp_port,
address_to_string(addr), strerror(errno));
}
// Cleanup the socket and remove it from our set
close_socket(sock);
it = client_sockets.erase(it); // Erase and move to the next element
continue;
} else {
// Otherwise, process the message
auto* header = (ReplServerHeader*)(header_buffer.data());
// get the body of the message
int expected_size = header->length;
int got = 0;
int tries = 0;
bool skip_to_next_socket = false;
while (got < expected_size) {
if (want_exit_callback()) {
lg::warn("[nREPL:{}] Terminating nREPL early", tcp_port);
return std::nullopt;
}
tries++;
if (tries > 100) {
break;
}
if (got + expected_size > (int)buffer.size()) {
lg::error(
"[nREPL:{}]: Bad message, aborting the read. Got :{}, Expected: {}, Buffer "
"Size: {}",
tcp_port, got, expected_size, buffer.size());
return std::nullopt;
}
auto bytes_read = read_from_socket(sock, buffer.data() + got, expected_size - got);
if (bytes_read <= 0) {
if (bytes_read == 0) {
lg::warn("[nREPL:{}] Client Disconnected: {}", tcp_port, address_to_string(addr));
} else {
lg::warn("[nREPL:{}] Error reading from socket on {}: {}", tcp_port,
address_to_string(addr), strerror(errno));
}
close_socket(sock);
it = client_sockets.erase(it); // Erase and move to the next element
skip_to_next_socket = true;
break;
}
got += bytes_read;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
if (skip_to_next_socket) {
continue;
}
switch (header->type) {
case ReplServerMessageType::PING:
ping_response(sock);
return std::nullopt;
case ReplServerMessageType::EVAL:
std::string msg(buffer.data(), header->length);
lg::debug("[nREPL:{}] Received Message: {}", tcp_port, msg);
return std::make_optional(msg);
}
}
}
++it;
}
return std::nullopt;
}
@@ -27,5 +27,6 @@ class ReplServer : public XSocketServer {
fd_set read_sockets;
std::set<int> client_sockets = {};
void error_response(int socket, const std::string& error);
void ping_response(int socket);
};
+295
View File
@@ -0,0 +1,295 @@
#include "repl_wrapper.h"
#include "common/util/FileUtil.h"
#include "common/util/json_util.h"
#include "common/util/string_util.h"
#include "common/versions/versions.h"
#include "fmt/color.h"
#include "fmt/core.h"
#include "third-party/replxx/include/replxx.hxx"
namespace REPL {
void Wrapper::clear_screen() {
repl.clear_screen();
}
void Wrapper::print_welcome_message(const std::vector<std::string>& loaded_projects) {
std::string message;
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " ..:::::..\n");
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .:-----------:.\n");
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .-----.");
message += fmt::format(fmt::emphasis::bold, " Welcome to OpenGOAL {}.{} [{}]",
versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR,
fmt::format(fg(fmt::color::gray), "{}", build_revision()));
if (!username.empty() && username != "#f" && username != "unknown") {
message += fmt::format(fg(fmt::color::light_green), " {}", username);
}
message += "!\n";
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .---.");
if (repl_config.game_version == GameVersion::Jak1) {
message += fmt::format(" [{}]: ", fmt::format(fg(fmt::color::orange), "jak1"));
} else if (repl_config.game_version == GameVersion::Jak2) {
message += fmt::format(" [{}]: ", fmt::format(fg(fmt::color::purple), "jak2"));
} else if (repl_config.game_version == GameVersion::Jak3) {
message += fmt::format(" [{}]: ", fmt::format(fg(fmt::color::gold), "jak3"));
} else {
message += fmt::format(" [{}]: ", fmt::format(fg(fmt::color::magenta), "jakx"));
}
const auto loaded_projects_str = fmt::format("{}", fmt::join(loaded_projects, ","));
message += fmt::format(fg(fmt::color::gray), "{}\n", loaded_projects_str);
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " . --- .");
message +=
fmt::format(" Project Path: {}\n",
fmt::format(fg(fmt::color::gray), file_util::get_jak_project_dir().string()));
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " - :===: -");
message += " nREPL:";
if (!nrepl_alive) {
message += fmt::format(fg(fmt::color::red), "DISABLED\n");
} else {
message += fmt::format(fg(fmt::color::light_green), " Listening on {}\n",
repl_config.get_nrepl_port());
}
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " --. .--: :--. .--");
message += " Source File Search Dirs: ";
const auto search_dir_string =
fmt::format("{}", fmt::join(repl_config.asm_file_search_dirs, ","));
message += fmt::format("[{}]\n", fmt::format(fg(fmt::color::gray), search_dir_string));
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .=======. =======.");
message += fmt::format(" {} or {} for basic help and usage\n",
fmt::format(fg(fmt::color::cyan), "(repl-help)"),
fmt::format(fg(fmt::color::cyan), "(repl-keybinds)"));
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .-=====-. .-=====-");
message +=
fmt::format(" {} to connect to the game\n", fmt::format(fg(fmt::color::cyan), "(lt)"));
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .-===========-.");
message += fmt::format(" {} to recompile the active project.\n",
fmt::format(fg(fmt::color::cyan), "(mi)"));
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .-===-.\n");
message += fmt::format(fmt::emphasis::bold | fg(fmt::color::orange), " .\n");
fmt::print("{}", message);
}
void Wrapper::print_to_repl(const std::string& str) {
repl.print(str.data());
}
void Wrapper::set_history_max_size(size_t len) {
repl.set_max_history_size(len);
}
const char* Wrapper::readline(const std::string& prompt) {
return repl.input(prompt);
}
void Wrapper::add_to_history(const std::string& line) {
repl.history_add(line);
}
void Wrapper::save_history() {
fs::path path;
if (repl_config.per_game_history) {
path = file_util::get_user_config_dir() / game_version_names[repl_config.game_version] /
".opengoal.repl.history";
} else {
path = file_util::get_user_config_dir() / ".opengoal.repl.history";
}
file_util::create_dir_if_needed_for_file(path.string());
repl.history_save(path.string());
}
void Wrapper::load_history() {
fs::path path;
if (repl_config.per_game_history) {
path = file_util::get_user_config_dir() / game_version_names[repl_config.game_version] /
".opengoal.repl.history";
} else {
path = file_util::get_user_config_dir() / ".opengoal.repl.history";
}
if (fs::exists(path)) {
repl.history_load(path.string());
} else {
fmt::print("Couldn't locate REPL history file at '{}'\n", path.string());
}
}
std::pair<std::string, bool> Wrapper::get_current_repl_token(std::string const& context) {
// Find the current token
std::string token = "";
for (auto c = context.crbegin(); c != context.crend(); c++) {
if (std::isspace(*c)) {
break;
} else {
token = *c + token;
}
}
// If there is a preceeding '(' remove it
if (!token.empty() && token.at(0) == '(') {
token.erase(0, 1);
return {token, true};
}
return {token, false};
}
void Wrapper::print_help_message() {
fmt::print(fmt::emphasis::bold, "\nREPL Controls:\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(:clear)\n");
fmt::print(" - Clear the current screen\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(e)\n");
fmt::print(" - Exit the compiler\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(lt [ip-address] [port-number])\n");
fmt::print(
" - Connect the listener to a running target. The IP address defaults to `127.0.0.1` and the "
"port to `8112`\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(r [ip-address] [port-number])\n");
fmt::print(
" - Attempt to reset the target and reconnect. After this, the target will have nothing "
"loaded.\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(:status)\n");
fmt::print(" - Send a ping-like message to the target. Requires the target to be connected\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::cyan), "(shutdown-target)\n");
fmt::print(" - If the target is connected, make it exit\n");
fmt::print(fmt::emphasis::bold, "\nCompiling & Building:\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(mi)\n");
fmt::print(" - Build entire game\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(mng)\n");
fmt::print(" - Build game engine\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(m \"filename\")\n");
fmt::print(" - Compile an OpenGOAL source file\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(ml \"filename\")\n");
fmt::print(" - Compile and Load (or reload) an OpenGOAL source file\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(build-kernel)\n");
fmt::print(" - Build the GOAL kernel\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::lime_green), "(make \"file-name\")\n");
fmt::print(
" - Build a file and any out-of-date dependencies. This file must be a target in the make "
"system.\n");
fmt::print(fmt::emphasis::bold, "\nOther:\n");
fmt::print(fmt::emphasis::bold | fg(fmt::color::magenta), "(gs)\n");
fmt::print(" - Enter a GOOS REPL\n");
}
void Wrapper::print_keybind_help() {
fmt::print(fmt::emphasis::bold, "\nREPL KeyBinds:\n");
for (const auto& bind : repl_config.keybinds) {
fmt::print("{}\n", fmt::styled(bind.string(), fmt::fg(fmt::color::cyan)));
fmt::print("{}\n", fmt::styled(bind.description, fmt::fg(fmt::color::gray)));
}
}
replxx::Replxx::key_press_handler_t Wrapper::commit_text_action(std::string text_to_commit) {
return [this, text_to_commit](char32_t code) {
repl.set_state(
replxx::Replxx::State(text_to_commit.c_str(), static_cast<int>(text_to_commit.size())));
return repl.invoke(replxx::Replxx::ACTION::COMMIT_LINE, code);
};
}
void Wrapper::init_settings() {
// NOTE - a nice popular project that uses replxx
// - https://github.com/ClickHouse/ClickHouse/blob/master/base/base/ReplxxLineReader.cpp#L366
repl.set_word_break_characters(" \t");
repl.set_complete_on_empty(false);
repl.set_indent_multiline(false);
repl.enable_bracketed_paste();
// Setup default keybinds
for (const auto& bind : repl_config.keybinds) {
char32_t code;
switch (bind.modifier) {
case KeyBind::Modifier::CTRL:
code = replxx::Replxx::KEY::control(bind.key.at(0));
break;
case KeyBind::Modifier::SHIFT:
code = replxx::Replxx::KEY::shift(bind.key.at(0));
break;
case KeyBind::Modifier::META:
code = replxx::Replxx::KEY::meta(bind.key.at(0));
break;
}
repl.bind_key(code, commit_text_action(bind.command));
}
}
void Wrapper::reload_startup_file() {
startup_file = load_user_startup_file(username, repl_config.game_version);
}
std::string find_repl_username() {
// Two options - either:
// 1. look for the `user.txt` file, which should only contain the username
// 2. if this is absent AND there is a single folder inside the "user" folder, use that as the
// username
auto user_dir = file_util::get_jak_project_dir() / "goal_src" / "user";
auto dirs = file_util::find_directories_in_dir(user_dir);
if (dirs.size() == 1) {
return dirs.at(0).filename().string();
}
std::regex allowed_chars("(^[0-9a-zA-Z\\-\\.\\!\\?<>]*$)");
if (file_util::file_exists((user_dir / "user.txt").string())) {
auto text = file_util::read_text_file(user_dir / "user.txt");
text = str_util::trim(text);
if (!text.empty() && std::regex_match(text, allowed_chars)) {
return text;
}
}
return "unknown";
}
fs::path get_startup_file_path(const std::string& username, const GameVersion game_version) {
// - first check to see if there is a game version specific startup file to prefer
auto game_specific_path = file_util::get_jak_project_dir() / "goal_src" / "user" / username /
fmt::format("startup-{}.gc", version_to_game_name(game_version));
if (file_util::file_exists(game_specific_path.string())) {
return game_specific_path;
}
return file_util::get_jak_project_dir() / "goal_src" / "user" / username / "startup.gc";
}
StartupFile load_user_startup_file(const std::string& username, const GameVersion game_version) {
// Check for a `startup.gc` file, each line will be executed on the REPL on startup
auto startup_file_path = get_startup_file_path(username, game_version);
StartupFile startup_file;
if (file_util::file_exists(startup_file_path.string())) {
auto data = file_util::read_text_file(startup_file_path);
auto startup_cmds = str_util::split(data);
bool found_run_on_listen_line = false;
for (const auto& cmd : startup_cmds) {
if (found_run_on_listen_line) {
startup_file.run_after_listen.push_back(cmd);
} else {
startup_file.run_before_listen.push_back(cmd);
}
if (str_util::contains(cmd, "og:run-below-on-listen")) {
found_run_on_listen_line = true;
}
}
}
return startup_file;
}
REPL::Config load_repl_config(const std::string& username,
const GameVersion game_version,
const int nrepl_port) {
auto repl_config_path =
file_util::get_jak_project_dir() / "goal_src" / "user" / username / "repl-config.json";
REPL::Config loaded_config(game_version);
if (file_util::file_exists(repl_config_path.string())) {
try {
auto repl_config_data =
parse_commented_json(file_util::read_text_file(repl_config_path), "repl-config.json");
from_json(repl_config_data, loaded_config);
loaded_config.temp_nrepl_port = nrepl_port;
return loaded_config;
} catch (std::exception& e) {
// do nothing
}
}
loaded_config.temp_nrepl_port = nrepl_port;
return loaded_config;
}
} // namespace REPL
+62
View File
@@ -0,0 +1,62 @@
#pragma once
#include <functional>
#include <optional>
#include <string>
#include <vector>
#include "config.h"
#include "third-party/replxx/include/replxx.hxx"
namespace REPL {
struct StartupFile {
std::vector<std::string> run_before_listen = {};
std::vector<std::string> run_after_listen = {};
};
class Wrapper {
public:
std::string username;
Config repl_config;
StartupFile startup_file;
bool nrepl_alive = false;
std::vector<std::string> examples{};
std::vector<std::pair<std::string, replxx::Replxx::Color>> regex_colors{};
Wrapper(GameVersion version) : repl_config(version) {}
Wrapper(const std::string& _username,
const Config& config,
const StartupFile& startup,
bool nrepl_alive)
: username(_username), repl_config(config), startup_file(startup), nrepl_alive(nrepl_alive) {}
replxx::Replxx& get_repl() { return repl; }
void init_settings();
void reload_startup_file();
// Functionality / Commands
void clear_screen();
void print_to_repl(const std::string& str);
void print_welcome_message(const std::vector<std::string>& loaded_projects);
void set_history_max_size(size_t len);
const char* readline(const std::string& prompt);
void add_to_history(const std::string& line);
void save_history();
void load_history();
void print_help_message();
void print_keybind_help();
std::pair<std::string, bool> get_current_repl_token(std::string const& context);
private:
replxx::Replxx repl;
replxx::Replxx::key_press_handler_t commit_text_action(std::string text_to_commit);
std::vector<REPL::KeyBind> keybindings = {};
};
std::string find_repl_username();
StartupFile load_user_startup_file(const std::string& username, const GameVersion game_version);
REPL::Config load_repl_config(const std::string& username,
const GameVersion game_version,
const int nrepl_port);
} // namespace REPL
@@ -0,0 +1,89 @@
#include "subtitles.h"
#include "common/goos/ParseHelpers.h"
#include "common/goos/Reader.h"
#include "common/util/FileUtil.h"
#include "common/util/json_util.h"
#include "fmt/core.h"
void open_subtitle_project(const std::string& project_kind,
const std::string& file_path,
std::vector<GameSubtitleDefinitionFile>& subtitle_files) {
goos::Reader reader;
auto& proj = reader.read_from_file({file_path}).as_pair()->cdr.as_pair()->car;
if (!proj.is_pair() || !proj.as_pair()->car.is_symbol() ||
proj.as_pair()->car.as_symbol() != project_kind) {
throw std::runtime_error(fmt::format("invalid project '{}'", project_kind));
}
goos::for_each_in_list(proj.as_pair()->cdr, [&](const goos::Object& o) {
if (o.is_pair() && o.as_pair()->cdr.is_pair()) {
auto args = o.as_pair();
auto& action = args->car.as_symbol();
args = args->cdr.as_pair();
if (action == "file-json") {
auto new_file = GameSubtitleDefinitionFile();
while (true) {
const auto& kwarg = args->car.as_symbol();
args = args->cdr.as_pair();
if (kwarg == ":language-id") {
new_file.language_id = args->car.as_int();
} else if (kwarg == ":text-version") {
new_file.text_version = args->car.as_string()->data;
} else if (kwarg == ":lines") {
new_file.lines_path = args->car.as_string()->data;
} else if (kwarg == ":meta") {
new_file.meta_path = args->car.as_string()->data;
} else if (kwarg == ":lines-base") {
new_file.lines_base_path = args->car.as_string()->data;
} else if (kwarg == ":meta-base") {
new_file.meta_base_path = args->car.as_string()->data;
}
if (args->cdr.is_empty_list()) {
break;
}
args = args->cdr.as_pair();
}
subtitle_files.push_back(new_file);
} else {
throw std::runtime_error(
fmt::format("unknown action {} in {} project", action.name_ptr, project_kind));
}
} else {
throw std::runtime_error(fmt::format("invalid entry in {} project", project_kind));
}
});
}
const std::unordered_map<GameVersion, std::vector<std::string>> locale_lookup = {
{GameVersion::Jak1,
{"en-US", "fr-FR", "de-DE", "es-ES", "it-IT", "jp-JP", "en-GB", "pt-PT", "fi-FI", "sv-SE",
"da-DK", "no-NO", "nl-NL", "pt-BR", "hu-HU", "ca-ES", "is-IS"}},
{GameVersion::Jak2, {"en-US", "fr-FR", "de-DE", "es-ES", "it-IT", "jp-JP", "ko-KR", "en-GB"}}};
std::string lookup_locale_code(const GameVersion game_version, const int language_id) {
if (locale_lookup.find(game_version) == locale_lookup.end() ||
(int)locale_lookup.at(game_version).size() < language_id) {
return "";
}
return locale_lookup.at(game_version).at(language_id);
}
const std::unordered_map<GameVersion, std::vector<int>> language_ids_with_audio = {
{GameVersion::Jak1, {0, 1, 2, 3, 4, 5, 6}},
{GameVersion::Jak2, {0, 1, 2, 3, 4, 5, 6, 7}}};
bool dump_language_with_duplicates_from_base(const GameVersion game_version,
const int language_id) {
if (language_ids_with_audio.find(game_version) == language_ids_with_audio.end()) {
return true;
}
if (std::find(language_ids_with_audio.at(game_version).begin(),
language_ids_with_audio.at(game_version).end(),
language_id) == language_ids_with_audio.at(game_version).end()) {
return true;
}
return false;
}
Loaded 100 of 13829 files, more files were not shown because too many files have changed in this diff. Show more