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.
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:


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

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 <6624576+Hat-Kid@users.noreply.github.com>
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.
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.
- 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.
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.
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.
- [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
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.
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.
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.
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.
- 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)