mirror of
https://github.com/open-goal/jak-project
synced 2026-06-29 19:42:41 -04:00
0a9cc68a27
* use meters degrees and seconds * update changelog
193 lines
4.7 KiB
Common Lisp
193 lines
4.7 KiB
Common Lisp
;; This file should contain an implementation for all macros that the decompiler uses in its output.
|
|
|
|
(defun ash ((value int) (shift-amount int))
|
|
"Arithmetic shift value by shift-amount.
|
|
A positive shift-amount will shift to the left and a negative will shift to the right.
|
|
"
|
|
;; OpenGOAL does not support ash in the compiler, so we implement it here as an inline function.
|
|
(declare (inline))
|
|
(if (> shift-amount 0)
|
|
(shl value shift-amount)
|
|
(sar value (- shift-amount))
|
|
)
|
|
)
|
|
|
|
(defmacro suspend()
|
|
'(none)
|
|
)
|
|
|
|
(defmacro empty-form ()
|
|
'(none)
|
|
)
|
|
|
|
(defmacro .sync.l ()
|
|
`(none))
|
|
|
|
(defmacro make-u128 (upper lower)
|
|
`(rlet ((result :class i128)
|
|
(upper-xmm :class i128)
|
|
(lower-xmm :class i128))
|
|
(.mov upper-xmm ,upper)
|
|
(.mov lower-xmm ,lower)
|
|
(.pcpyld result upper-xmm lower-xmm)
|
|
(the uint result)
|
|
)
|
|
)
|
|
|
|
(defmacro init-vf0-vector ()
|
|
"Initializes the VF0 vector which is a constant vector in the VU set to <0,0,0,1>"
|
|
`(.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0))
|
|
)
|
|
|
|
(defconstant SYM_TO_STRING_OFFSET #xff38)
|
|
(defmacro symbol->string (sym)
|
|
"Convert a symbol to a goal string."
|
|
`(-> (the-as (pointer string) (+ SYM_TO_STRING_OFFSET (the-as int ,sym))))
|
|
)
|
|
|
|
(defmacro new-stack-matrix0 ()
|
|
"Get a new matrix on the stack that's set to zero."
|
|
`(let ((mat (new 'stack-no-clear 'matrix)))
|
|
(set! (-> mat quad 0) (the-as uint128 0))
|
|
(set! (-> mat quad 1) (the-as uint128 0))
|
|
(set! (-> mat quad 2) (the-as uint128 0))
|
|
(set! (-> mat quad 3) (the-as uint128 0))
|
|
mat
|
|
)
|
|
)
|
|
|
|
(defmacro new-stack-vector0 ()
|
|
"Get a stack vector that's set to 0.
|
|
This is more efficient than (new 'stack 'vector) because
|
|
this doesn't call the constructor."
|
|
`(let ((vec (new 'stack-no-clear 'vector)))
|
|
(set! (-> vec quad) (the-as uint128 0))
|
|
vec
|
|
)
|
|
)
|
|
|
|
(defmacro new-stack-quaternion0 ()
|
|
"Get a stack quaternion that's set to 0.
|
|
This is more efficient than (new 'stack 'quaternion) because
|
|
this doesn't call the constructor."
|
|
`(let ((q (new 'stack-no-clear 'quaternion)))
|
|
(set! (-> q quad) (the-as uint128 0))
|
|
q
|
|
)
|
|
)
|
|
|
|
|
|
(defmacro with-pp (&rest body)
|
|
`(rlet ((pp :reg r13 :reset-here #t :type process))
|
|
,@body)
|
|
)
|
|
|
|
(defmacro fabs (x)
|
|
`(if (< (the float ,x) 0)
|
|
(- (the float ,x))
|
|
(the float ,x))
|
|
)
|
|
|
|
(defconstant PI (the-as float #x40490fda))
|
|
(defconstant MINUS_PI (the-as float #xc0490fda))
|
|
|
|
(defmacro handle->process (handle)
|
|
;; the actual implementation is more clever than this.
|
|
;; Checks PID.
|
|
`(if (-> ,handle process)
|
|
(let ((proc (-> (-> ,handle process))))
|
|
(if (= (-> ,handle pid) (-> proc pid))
|
|
proc
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
(defmacro defbehavior (name process-type bindings &rest body)
|
|
(if (and
|
|
(> (length body) 1) ;; more than one thing in function
|
|
(string? (first body)) ;; first thing is a string
|
|
)
|
|
;; then it's a docstring and we ignore it.
|
|
`(define ,name (lambda :name ,name :behavior ,process-type ,bindings ,@(cdr body)))
|
|
;; otherwise don't ignore it.
|
|
`(define ,name (lambda :name ,name :behavior ,process-type ,bindings ,@body))
|
|
)
|
|
)
|
|
|
|
(defmacro b! (pred destination &key (delay '()) &key (likely-delay '()))
|
|
"Branch!"
|
|
;; evaluate the predicate
|
|
`(let ((should-branch ,pred))
|
|
;; normal delay slot:
|
|
,delay
|
|
(when should-branch
|
|
,likely-delay
|
|
(goto ,destination)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
(defglobalconstant METER_LENGTH 4096.0)
|
|
|
|
(defmacro meters (x)
|
|
"Convert number to meters.
|
|
If the input is a constant float or integer, the result will be a
|
|
compile time constant float. Otherwise, it will not be constant."
|
|
|
|
;; we don't have enough constant propagation for the compiler to figure this out.
|
|
(cond
|
|
((float? x)
|
|
(* METER_LENGTH x)
|
|
)
|
|
((integer? x)
|
|
(* METER_LENGTH x)
|
|
)
|
|
(#t
|
|
`(* METER_LENGTH ,x)
|
|
)
|
|
)
|
|
)
|
|
|
|
(defglobalconstant DEGREES_PER_ROT 65536.0)
|
|
|
|
(defmacro degrees (x)
|
|
"Convert number to degrees unit.
|
|
Will keep a constant float/int constant."
|
|
(cond
|
|
((or (float? x) (integer? x))
|
|
(* DEGREES_PER_ROT (/ (+ 0.0 x) 360.0))
|
|
)
|
|
(#t
|
|
`(* (/ (the float ,x) 360.0)
|
|
DEGREES_PER_ROT
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
(defglobalconstant TICKS_PER_SECOND 300) ;; 5 t/frame @ 60fps, 6 t/frame @ 50fps
|
|
|
|
(defmacro seconds (x)
|
|
"Convert number to seconds unit."
|
|
(cond
|
|
((float? x)
|
|
(* 1.0 TICKS_PER_SECOND x)
|
|
)
|
|
((integer? x)
|
|
(* TICKS_PER_SECOND x)
|
|
)
|
|
(#t
|
|
`(* 1.0 TICKS_PER_SECOND ,x)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; maybe rename to "velocity"?
|
|
(defmacro vel-tick (vel)
|
|
"turn a velocity value into a per-tick value"
|
|
`(* (/ 1.0 ,TICKS_PER_SECOND) ,vel)
|
|
)
|
|
|