jak-project/goal_src/jak2/engine/debug/viewer.gc

272 lines
8.7 KiB
Common Lisp
Raw Normal View History

;;-*-Lisp-*-
(in-package goal)
;; name: viewer.gc
;; name in dgo: viewer
;; dgos: ENGINE, GAME
(declare-type viewer process-drawable)
(define-extern *viewer* viewer)
;; DECOMP BEGINS
(define *viewer-sg* (new 'static 'skeleton-group
:bounds (new 'static 'vector :w 16384.0)
:lod-dist (new 'static 'array float 6 4095996000.0 0.0 0.0 0.0 0.0 0.0)
)
)
(deftype viewer (process-drawable)
`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 <6624576+Hat-Kid@users.noreply.github.com>
2023-10-29 23:20:02 -04:00
((janim art-joint-anim)
)
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 <awaterford111445@gmail.com>
2023-01-21 20:45:45 -05:00
(:states
viewer-process
)
)
(defstate viewer-process (viewer)
:code (behavior ()
(until #f
(ja-no-eval :group! (-> self janim)
:num! (seek! (the float (+ (-> self janim frames num-frames) -1)))
:frame-num 0.0
)
(until (ja-done? 0)
(compute-alignment! (-> self align))
(align!
(-> self align)
(align-opts adjust-x-vel adjust-y-vel adjust-xz-vel keep-other-velocities adjust-quat)
1.0
1.0
1.0
)
(suspend)
(ja :num! (seek!))
)
)
#f
)
:post ja-post
)
(define viewer-string (new 'global 'string 64 (the-as string #f)))
(define viewer-ja-name (new 'global 'string 64 (the-as string #f)))
(define viewer-geo-name (new 'global 'string 64 (the-as string #f)))
(defun actor-get-arg! ((arg0 string) (arg1 string) (arg2 string))
(let ((s5-0 (-> arg2 data))
(gp-0 (-> arg0 data))
)
(set! (-> gp-0 0) (the-as uint 0))
(dotimes (s2-0 (- (length arg2) (+ (length arg1) 2)))
(when (= (-> s5-0 0) 45)
(let ((s1-0 #f))
(dotimes (s0-0 (length arg1))
(if (!= (-> s5-0 (+ s0-0 1)) (-> arg1 data s0-0))
(goto cfg-10)
)
)
(if (= (-> s5-0 (+ (length arg1) 1)) 45)
(set! s1-0 #t)
)
(label cfg-10)
(when s1-0
(let ((v1-22 (&+ s5-0 (+ (length arg1) 2))))
(while (and (!= (-> v1-22 0) 45) (nonzero? (-> v1-22 0)))
(set! (-> gp-0 0) (-> v1-22 0))
(set! v1-22 (&-> v1-22 1))
(set! gp-0 (&-> gp-0 1))
)
)
(set! (-> gp-0 0) (the-as uint 0))
(return #t)
)
)
)
(set! s5-0 (&-> s5-0 1))
)
)
#f
)
(defun art-part-name ((arg0 string))
(let ((gp-0 (-> arg0 data)))
(while (nonzero? (-> gp-0 0))
(when (= (-> gp-0 0) 45)
(copyn-string<-charp
viewer-string
(&-> gp-0 1)
(- (length arg0) (the-as int (+ (- -1 (the-as int (-> arg0 data))) (the-as int gp-0))))
)
(return viewer-string)
)
(set! gp-0 (&-> gp-0 1))
)
)
(clear viewer-string)
)
;; WARN: Return type mismatch object vs none.
(defbehavior init-viewer viewer ((arg0 string) (arg1 string))
(let* ((s5-0 *level*)
(s3-0 (method-of-object s5-0 art-group-get-by-name))
)
(format (clear *temp-string*) "skel-~S" arg0)
(let ((a1-3 (s3-0 s5-0 *temp-string* (the-as (pointer uint32) #f))))
(cond
(a1-3
(initialize-skeleton self (the-as skeleton-group a1-3) (the-as pair 0))
(cond
((>= (-> self skel active-channels) (the-as uint 1))
(set! (-> self janim) (-> self skel channel 0 frame-group))
)
(else
(let ((v1-8 (-> self draw art-group)))
(dotimes (a0-5 (-> v1-8 length))
(when (= (-> v1-8 data a0-5 type) art-joint-anim)
(set! (-> self janim) (the-as art-joint-anim (-> v1-8 data a0-5)))
(ja-channel-set! 1)
(goto cfg-10)
)
)
)
(go process-drawable-art-error "anim")
)
)
(label cfg-10)
(set! (-> self align) (new 'process 'align-control self))
(logior! (-> self skel status) (joint-control-status blend-shape eye-anim))
(go viewer-process)
)
(else
(actor-get-arg! viewer-ja-name "ja" arg1)
(actor-get-arg! viewer-geo-name "geo" arg1)
(let ((s2-1 (load-to-heap-by-name (-> self level art-group) arg0 #f global 0))
(s5-1 (the-as int #f))
(s4-1 (the-as int #f))
(s3-1 (the-as int #f))
)
(when s2-1
(dotimes (s1-0 (-> s2-1 length))
(cond
((not (-> s2-1 data s1-0))
)
((and (not s4-1)
(= (-> s2-1 data s1-0 type) merc-ctrl)
(or (zero? (length viewer-geo-name)) (string= (art-part-name (-> s2-1 data s1-0 name)) viewer-geo-name))
)
(set! s4-1 s1-0)
)
((= (-> s2-1 data s1-0 type) art-joint-geo)
(set! s3-1 s1-0)
)
((and (= (-> s2-1 data s1-0 type) art-joint-anim)
(or (zero? (length viewer-ja-name)) (string= (art-part-name (-> s2-1 data s1-0 name)) viewer-ja-name))
)
(set! s5-1 s1-0)
)
)
(if (and s4-1 s3-1 s5-1)
(goto cfg-44)
)
)
)
(label cfg-44)
(cond
((and s4-1 s3-1 s5-1)
(set! (-> self janim) (the-as art-joint-anim (-> s2-1 data s5-1)))
(let ((a1-13 *viewer-sg*))
(set! (-> a1-13 art-group-name) arg0)
(set! (-> a1-13 jgeo) s3-1)
(set! (-> a1-13 janim) s5-1)
(set! (-> a1-13 mgeo 0) s4-1)
(initialize-skeleton self a1-13 (the-as pair 0))
)
(set! (-> self align) (new 'process 'align-control self))
(logior! (-> self skel status) (joint-control-status blend-shape eye-anim))
(go viewer-process)
)
(else
(go process-drawable-art-error arg0)
)
)
)
)
)
)
)
(none)
)
[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 05:54:49 -04:00
;; WARN: Return type mismatch object vs none.
`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 <6624576+Hat-Kid@users.noreply.github.com>
2023-10-29 23:20:02 -04:00
(defmethod init-from-entity! ((this viewer) (arg0 entity-actor))
"Typically the method that does the initial setup on the process, potentially using the [[entity-actor]] provided as part of that.
This commonly includes things such as:
- stack size
- collision information
- loading the skeleton group / bones
- sounds"
(set! *viewer* this)
(set! (-> this root) (new 'process 'trsqv))
(process-drawable-from-entity! this arg0)
(let ((s4-0 (-> arg0 etype)))
(if (valid? s4-0 type (the-as string #f) #f 0)
(init-viewer (symbol->string (-> s4-0 symbol)) (res-lump-struct arg0 'name string))
(go process-drawable-art-error "unknown")
)
)
(none)
)
(defbehavior init-viewer-for-other viewer ((arg0 string) (arg1 vector) (arg2 entity-actor))
(set! *viewer* self)
(process-entity-set! self arg2)
(set! (-> self root) (new 'process 'trsqv))
(set! (-> self root trans quad) (-> arg1 quad))
(quaternion-identity! (-> self root quat))
(set-vector! (-> self root scale) 1.0 1.0 1.0 1.0)
(init-viewer arg0 arg0)
(none)
)
(defun add-a-bunch ((arg0 string) (arg1 int) (arg2 int) (arg3 float) (arg4 process-tree) (arg5 entity-actor))
(local-vars (sv-32 int) (sv-48 process) (sv-64 vector))
(dotimes (s0-0 arg1)
(set! sv-32 0)
(while (< sv-32 arg2)
(set! sv-64 (new 'stack-no-clear 'vector))
(set! (-> sv-64 quad) (the-as uint128 0))
(position-in-front-of-camera! sv-64 40960.0 4096.0)
(+! (-> sv-64 x) (the float (* (- s0-0 (/ arg1 2)) (the int arg3))))
(+! (-> sv-64 z) (the float (* (- sv-32 (/ arg2 2)) (the int arg3))))
(set! sv-48 (get-process *default-dead-pool* viewer #x4000))
(when sv-48
(let ((t9-2 (method-of-type viewer activate)))
(t9-2 (the-as viewer sv-48) arg4 (symbol->string (-> viewer symbol)) (the-as pointer #x70004000))
)
(let ((t9-3 run-function-in-process)
(a0-7 sv-48)
(a1-4 init-viewer-for-other)
(a2-6 arg0)
(t0-1 arg5)
)
((the-as (function object object object object object none) t9-3) a0-7 a1-4 a2-6 sv-64 t0-1)
)
(-> sv-48 ppointer)
)
(set! sv-32 (+ sv-32 1))
)
)
#f
)
;; WARN: Return type mismatch symbol vs object.
(defun birth-viewer ((arg0 process) (arg1 entity-actor))
(set! (-> arg0 type) viewer)
(init-entity arg0 arg1 viewer)
[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 05:54:49 -04:00
#t
)