Files
jak-project/goal_src/jak2/engine/gfx/foreground/bones.gc
T
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

314 lines
11 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
;; name: bones.gc
;; name in dgo: bones
;; dgos: ENGINE, GAME
#|@file
bones, joints, cspace, matrix, joint-anim-frames...
The "joints" define the structure of the skeleton, just storing a bind pose, and parent info. These don't change,
and are loaded as part of the skeleton. The actual joint objects are stored in the art-joint-geo.
The "do-joint-math" method of process-drawable is responsible for computing the joint-anim-frame and the bones.
The "cspace" system is used to compute bones from joint-anim-frames.
The "joint-anim-frame" is a list of transformqs for the relative transform between bones.
The "bones" are the world space transform of each 'bone'
The "do-joint-math" function does:
- call the generate-frame-function callback to generate a joint-anim-frame (does the joint anim decompress/blending)
- call the prebind-function which can modify the relative transforms (eg: joint-mods)
- walk the tree of joints, computing bones using the cspace
- call the postbind-function, for other effects.
The "bones" system creates matrices for foreground renderers from bones/joints.
The inputs are bones/joints, and the output is pris-mtx, which is a 4x4 "t-mtx" for transforming, and a 3x3 (stored in 3 vec4's)
n-mtx for rotating normals.
all matrices are calculated at once, and shared between merc/emerc/gmerc/shadow
this is done by a linked list of "bone calculations", which is stashed in the dma buffer.
|#
;; todo check bad reference.
;; DECOMP BEGINS
;; list node for pending bone calculations. These are terminated by 0's.
(deftype bone-calculation-list (structure)
((first bone-calculation :offset-assert 0)
(next bone-calculation :offset-assert 4)
)
:method-count-assert 9
:size-assert #x8
:flag-assert #x900000008
)
;; head of bone calculation list
(define *bone-calculation-list* (new 'global 'bone-calculation-list))
(defun bone-list-init ()
"Reset bone calculation list to have nothing in it."
(let ((v1-0 *bone-calculation-list*))
(set! (-> v1-0 first) (the-as bone-calculation 0))
(set! (-> v1-0 next) (the-as bone-calculation 0))
)
0
0
(none)
)
;; clear list.
(bone-list-init)
;; VU0 microprogram for bone calculations.
(define bones-vu0-block (new 'static 'vu-function))
(defun bones-set-sqwc ()
"Set the sqwc register so the DMA transfer of joints skips the metadata and just transfers the bind-pose."
(set! (-> (the-as dma-bank-control #x1000e000) sqwc) (new 'static 'dma-sqwc :sqwc #x1 :tqwc #x4))
(none)
)
(defun bones-reset-sqwc ()
"Reset sqwc so DMA works normally again (see bones-set-sqwc)"
(set! (-> (the-as dma-bank-control #x1000e000) sqwc) (new 'static 'dma-sqwc :sqwc #x1 :tqwc #x1))
(none)
)
(defun bones-init ((arg0 dma-buffer))
"Initialize scratchpad/vu0 for BONE MATH."
(let ((v1-1 (-> (scratchpad-object bone-memory) work)))
(+ #x70000000 0)
;; scratchpad layout of double-buffered bone calculation.
;; "joints", which are stripped of their metadata qw and are 4qw matrices
(set! (-> v1-1 layout joint 0) (-> (scratchpad-object bone-memory) buffer 0 joint))
(set! (-> v1-1 layout joint 1) (-> (scratchpad-object bone-memory) buffer 1 joint))
;; "bones", which are 5 qw transform + scale separately
(set! (-> v1-1 layout bone 0) (-> (scratchpad-object bone-memory) buffer 0 bone))
(set! (-> v1-1 layout bone 1) (-> (scratchpad-object bone-memory) buffer 1 bone))
;; "output" pris-mtx.
(set! (-> v1-1 layout output 0) (-> (scratchpad-object bone-memory) buffer 0 output))
(set! (-> v1-1 layout output 1) (-> (scratchpad-object bone-memory) buffer 1 output))
)
;; upload the bones vu0 block.
(unless PC_PORT
(let ((gp-0 *vu0-dma-list*))
(let ((v1-2 gp-0))
(set! (-> v1-2 base) (-> v1-2 data))
(set! (-> v1-2 end) (&-> v1-2 data-buffer (-> v1-2 allocated-length)))
)
(dma-buffer-add-vu-function gp-0 bones-vu0-block 0)
(let* ((v1-3 gp-0)
(a0-20 (the-as object (-> v1-3 base)))
)
(set! (-> (the-as dma-packet a0-20) dma) (new 'static 'dma-tag :id (dma-tag-id end)))
(set! (-> (the-as (pointer uint64) a0-20) 1) (the-as uint 0))
(set! (-> v1-3 base) (&+ (the-as pointer a0-20) 16))
)
(.sync.l)
(dma-buffer-send-chain (the-as dma-bank-source #x10008000) gp-0)
)
)
0
(none)
)
;; note that the original game doesn't quite use a normal calling convention here, so we cheat and pass an extra arg.
;; see the C++ code for more details.
(def-mips2c bones-mtx-calc (function (inline-array pris-mtx) (inline-array joint) (inline-array bone) uint object none))
(defun bones-mtx-calc-execute ()
"Execute all bone matrix calculations."
(rlet ((vf1 :class vf)
(vf25 :class vf)
(vf26 :class vf)
(vf27 :class vf)
(vf28 :class vf)
(vf29 :class vf)
(vf30 :class vf)
(vf31 :class vf)
(vf4 :class vf)
(vf5 :class vf)
(vf6 :class vf)
(vf7 :class vf)
(vf8 :class vf)
)
(with-profiler 'bones *profile-bones-color*
(reset! (-> *perf-stats* data (perf-stat-bucket bones)))
;; set up layout in scratchpad (again)
(let ((v1-24 (-> (scratchpad-object bone-memory) work)))
(set! (-> v1-24 layout joint 0) (-> (scratchpad-object bone-memory) buffer 0 joint))
(set! (-> v1-24 layout joint 1) (-> (scratchpad-object bone-memory) buffer 1 joint))
(set! (-> v1-24 layout bone 0) (-> (scratchpad-object bone-memory) buffer 0 bone))
(set! (-> v1-24 layout bone 1) (-> (scratchpad-object bone-memory) buffer 1 bone))
(set! (-> v1-24 layout output 0) (-> (scratchpad-object bone-memory) buffer 0 output))
(set! (-> v1-24 layout output 1) (-> (scratchpad-object bone-memory) buffer 1 output))
)
;; set sqwc to upload joints. This will skip the 1 qw of metadata and just grab the joint matrix.
;; (set! (-> (the-as dma-bank-control #x1000e000) sqwc) (new 'static 'dma-sqwc :sqwc #x1 :tqwc #x4))
;; loop over bone calculations:
(let* ((v1-26 *bone-calculation-list*)
(gp-1 *identity-matrix*)
(s5-1 (-> *math-camera* camera-rot))
(s4-1 (-> v1-26 first))
)
(while (nonzero? s4-1) ;; loop
;; pick correct matrix. The pris-mtx includes camera rotation, so all that's needed in the final
;; renderers is perspective. (unless you set no-cam-rot)
(let ((v1-29 (if (logtest? (-> s4-1 flags) (bone-calc-flags no-cam-rot))
gp-1
s5-1
)
)
)
(.lvf vf28 (&-> v1-29 quad 0))
(.lvf vf29 (&-> v1-29 quad 1))
(.lvf vf30 (&-> v1-29 quad 2))
(.lvf vf31 (&-> v1-29 trans quad))
(.lvf vf25 (&-> v1-29 quad 0))
(.lvf vf26 (&-> v1-29 quad 1))
(.lvf vf27 (&-> v1-29 quad 2))
;; calculate!
(bones-mtx-calc
(-> s4-1 matrix-area)
(-> s4-1 joints)
(-> s4-1 bones)
(-> s4-1 num-bones)
v1-29 ;; hack, to pass matrix to bones-mtx-calc in a better way.
)
)
;; there is an optional post-processing step for ripple.
(when (logtest? (-> s4-1 flags) (bone-calc-flags write-ripple-data))
(let* ((a2-1 s4-1)
(v1-34 (-> a2-1 num-bones))
(a0-26 (the-as pris-mtx (-> a2-1 matrix-area)))
(a1-11 (the-as pris-mtx (-> a2-1 ripple-area)))
)
(.lvf vf1 (&-> a2-1 ripple-vec quad))
(label cfg-15)
(.lvf vf5 (&-> a0-26 t-mtx quad 1))
(.lvf vf6 (&-> a0-26 t-mtx trans quad))
(.lvf vf7 (&-> a0-26 n-mtx quad 0))
(.lvf vf8 (&-> a0-26 n-mtx quad 2))
(.mul.x.vf vf4 vf5 vf1)
(.mul.y.vf vf5 vf5 vf1)
(let ((a3-1 (-> a0-26 t-mtx quad 0)))
(.mul.z.vf vf7 vf7 vf1)
(let ((a2-2 (-> a0-26 t-mtx quad 2)))
(.mul.z.vf vf8 vf8 vf1)
(set! (-> a1-11 t-mtx quad 0) a3-1)
(let ((a3-2 (-> a0-26 n-mtx quad 1)))
(.sub.vf vf6 vf6 vf4)
(set! (-> a1-11 t-mtx quad 2) a2-2)
(.svf (&-> a1-11 t-mtx quad 1) vf5)
(set! (-> a1-11 n-mtx quad 1) a3-2)
)
)
)
(+! v1-34 -1)
(.svf (&-> a1-11 n-mtx quad 0) vf7)
;; (.addiu a0-26 a0-26 128)
(&+! a0-26 128)
(.svf (&-> a1-11 t-mtx trans quad) vf6)
;; (.addiu a1-11 a1-11 128)
(&+! a1-11 128)
(b! (nonzero? v1-34) cfg-15 :delay (.svf (&-> (the (inline-array vector) a1-11) -2 quad) vf8))
)
0
)
(set! s4-1 (-> s4-1 next))
)
)
;; reset sqwc
;; (set! (-> (the-as dma-bank-control #x1000e000) sqwc) (new 'static 'dma-sqwc :sqwc #x1 :tqwc #x1))
;; clear bone list
(bone-list-init)
(read! (-> *perf-stats* data (perf-stat-bucket bones)))
)
0
(none)
)
)
(defun-debug dump-qword ((arg0 qword))
(let ((v1-0 arg0))
(format
0
"~8,'0X: ~8,'0X ~8,'0X ~8,'0X ~8,'0X~%"
v1-0
(-> v1-0 data 0)
(-> v1-0 data 1)
(-> v1-0 data 2)
(-> v1-0 data 3)
)
)
0
(none)
)
(defun-debug dump-mem ((arg0 pointer) (arg1 int))
(dotimes (s4-0 arg1)
(format
0
"~8,'0X: ~8,'0X ~8,'0X ~8,'0X ~8,'0X"
(&+ arg0 (* (* s4-0 4) 4))
(-> (the-as (pointer uint32) (&+ arg0 (* (* s4-0 4) 4))))
(-> (the-as (pointer uint32) (&+ arg0 (* (+ (* s4-0 4) 1) 4))))
(-> (the-as (pointer uint32) (&+ arg0 (* (+ (* s4-0 4) 2) 4))))
(-> (the-as (pointer uint32) (&+ arg0 (* (+ (* s4-0 4) 3) 4))))
)
(format
0
" ~F ~F ~F ~F ~%"
(-> (the-as (pointer uint32) (&+ arg0 (* (* s4-0 4) 4))))
(-> (the-as (pointer uint32) (&+ arg0 (* (+ (* s4-0 4) 1) 4))))
(-> (the-as (pointer uint32) (&+ arg0 (* (+ (* s4-0 4) 2) 4))))
(-> (the-as (pointer uint32) (&+ arg0 (* (+ (* s4-0 4) 3) 4))))
)
)
0
(none)
)
(defun-debug bones-debug ()
0
(none)
)
(defun-debug dump-bone-mem ()
(format 0 "== joints 0 ===========~%")
(dump-mem (the-as pointer (+ 80 #x70000000)) 64)
(format 0 "== bones 0 ============~%")
(dump-mem (the-as pointer (+ 1104 #x70000000)) 80)
(format 0 "== output 0 ===========~%")
(dump-mem (the-as pointer (+ 2384 #x70000000)) 128)
(format 0 "~%~%~%")
(format 0 "== joints 1 ===========~%")
(dump-mem (the-as pointer (+ 4432 #x70000000)) 64)
(format 0 "== bones 1 ============~%")
(dump-mem (the-as pointer (+ 5456 #x70000000)) 80)
(format 0 "== output 1 ===========~%")
(dump-mem (the-as pointer (+ 6736 #x70000000)) 128)
(format 0 "========================~%~%")
0
(none)
)