mirror of
https://github.com/open-goal/jak-project
synced 2026-06-07 03:58:11 -04:00
141 lines
4.6 KiB
Common Lisp
141 lines
4.6 KiB
Common Lisp
;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: gcommon.gc
|
|
;; name in dgo: gcommon
|
|
;; dgos: KERNEL
|
|
|
|
;; gcommon is the first file compiled and loaded.
|
|
;; it's expected that this function will mostly be hand-decompiled
|
|
|
|
|
|
|
|
;; The "identity" returns its input unchanged. It uses the special GOAL "object"
|
|
;; type, which can basically be anything, so this will work on integers, floats,
|
|
;; strings, structures, arrays, etc. The only things which doesn't work with "object"
|
|
;; is a 128-bit integer. The upper 64-bits of the integer will usually be lost.
|
|
(defun identity ((x object))
|
|
;; there is an optional "docstring" that can go at the beginning of a function
|
|
"Function which returns its input. The first function of the game!"
|
|
|
|
;; the last thing in the function body is the return value. This is like "return x;" in C
|
|
;; the return type of the function is figured out automatically by the compiler
|
|
;; you don't have to specify it manually.
|
|
x
|
|
)
|
|
|
|
|
|
(defun 1/ ((x float))
|
|
"Reciprocal floating point"
|
|
|
|
;; this function computes 1.0 / x. GOAL allows strange function names like "1/".
|
|
|
|
;; Declaring this an inline function is like a C inline function, however code is
|
|
;; still generated so it can be used a function object. GOAL inline functions have type
|
|
;; checking, so they are preferable to macros when possible, to get better error messages.
|
|
(declare (inline))
|
|
|
|
;; the division form will pick the math type (float, int) based on the type of the first
|
|
;; argument. In this case, "1." is a floating point constant, so this becomes a floating point division.
|
|
(/ 1. x)
|
|
)
|
|
|
|
(defun + ((x int) (y int))
|
|
"Compute the sum of two integers"
|
|
|
|
;; this wraps the compiler's built-in handling of "add two integers" in a GOAL function.
|
|
;; now "+" can be used as a function object, but is limited to adding two integers when used like this.
|
|
;; The compiler is smart enough to not use this function unless "+" is being used as a function object.
|
|
;; ex: (+ a b c), (+ a b) ; won't use this function, uses built-in addition
|
|
;; (set-combination-function! my-thing +) ; + becomes a function pointer in this case
|
|
(+ x y)
|
|
)
|
|
|
|
(defun - ((x int) (y int))
|
|
"Compute the difference of two integers"
|
|
(- x y)
|
|
)
|
|
|
|
(defun * ((x int) (y int))
|
|
"Compute the product of two integers"
|
|
;; TODO - verify that this matches the PS2 exactly.
|
|
;; Uses mult (three operand form) in MIPS
|
|
(* x y)
|
|
)
|
|
|
|
(defun / ((x int) (y int))
|
|
"Compute the quotient of two integers"
|
|
;; TODO - verify this matches the PS2 exactly
|
|
(/ x y)
|
|
)
|
|
|
|
;; todo ash
|
|
;; todo mod
|
|
;; todo rem
|
|
|
|
(defun abs ((a int))
|
|
"Take the absolute value of an integer"
|
|
|
|
;; short function, good candidate for inlining
|
|
(declare (inline))
|
|
|
|
;; The original implementation was inline assembly, to take advantage of branch delay slots:
|
|
;; (or v0 a0 r0) ;; move input to output unchanged, for positive case
|
|
;; (bltzl v0 end) ;; if negative, execute the branch delay slot below...
|
|
;; (dsubu v0 r0 v0) ;; negate
|
|
;; (label end)
|
|
|
|
|
|
(if (> a 0) ;; condition is "a > 0"
|
|
a ;; true case, return a
|
|
(- a) ;; false case, return -a. (- a) is like (- 0 a)
|
|
)
|
|
)
|
|
|
|
(defun min ((a integer) (b integer))
|
|
"Compute minimum."
|
|
|
|
;; The original implementation was inline assembly, to take advantage of branch delay slots:
|
|
;; (or v0 a0 r0) ;; move first arg to output (case of second arg being min)
|
|
;; (or v1 a1 r0) ;; move second arg to v1 (likely strange coloring)
|
|
;; (slt a0 v0 v1) ;; compare args
|
|
;; (movz v0 v1 a0) ;; conditional move the second arg to v0 if it's the minimum
|
|
|
|
(declare (inline))
|
|
(if (> a b) b a)
|
|
)
|
|
|
|
(defun max ((a integer) (b integer))
|
|
"Compute maximum."
|
|
(declare (inline))
|
|
(if (> a b) a b)
|
|
)
|
|
|
|
;; todo logior
|
|
;; todo lognor
|
|
;; todo logxor
|
|
;; todo lognot
|
|
|
|
(defun false-func ()
|
|
"Return false"
|
|
;; In GOAL, #f is false. It's a symbol. Each symbol exists as an object, and each symbol has a value
|
|
;; The value of the false symbol #f is the false symbol #f.
|
|
|
|
;; To get the symbol, instead of its value, we use quote. Writing 'x is equivalent to (quote x)
|
|
'#f
|
|
)
|
|
|
|
(defun true-func ()
|
|
"Return true"
|
|
;; GOAL consideres anything that's not #f to be true. But there's also an explicit true symbol.
|
|
'#t
|
|
)
|
|
|
|
;; The C Kernel implements the format function and creates a trampoline function in the GOAL heap which jumps to
|
|
;; format. (In OpenGOAL, there's actually two trampoline functions, to make the 8 arguments all work.)
|
|
;; For some reason, the C Kernel names this trampoline function _format. We need to set the value of format
|
|
;; _format in order for format to work.
|
|
(define format _format)
|
|
|
|
;; todo bfloat
|
|
;; todo pinrt bfloat |