mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
6e0ff4c9d0
* fix parent issue * fix compiler issue * update * add error messages * fix error * fix array access, temporary * more clean * fix * rename arg variables better * fix method name * fix no return value in decompiler * many small fixes * cheat types so it works * name map * fix old test'
228 lines
8.1 KiB
Common Lisp
228 lines
8.1 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: rpc-h.gc
|
|
;; name in dgo: rpc-h
|
|
;; dgos: GAME, ENGINE
|
|
|
|
;; an RPC buffer is a container of elements to send to the IOP.
|
|
;; each element is size elt-size, and there are maximum of elt-count elements
|
|
;; it is possible to use fewer elements than elt-count.
|
|
;; the buffer is 64-byte aligned.
|
|
(deftype rpc-buffer (basic)
|
|
((elt-size uint32 :offset-assert 4)
|
|
(elt-count uint32 :offset-assert 8)
|
|
(elt-used uint32 :offset-assert 12)
|
|
(busy basic :offset-assert 16) ;; are we being sent currently?
|
|
(base pointer :offset-assert 20) ;; 64-byte aligned buffer of elts.
|
|
;; I suspect this was 16-byte aligned for DMA purposes.
|
|
(data uint8 :dynamic :offset 32)
|
|
)
|
|
(:methods
|
|
(new (symbol type uint uint) rpc-buffer 0)
|
|
)
|
|
:method-count-assert 9
|
|
:size-assert #x20
|
|
:flag-assert #x900000020
|
|
)
|
|
|
|
(defmethod new rpc-buffer ((allocation symbol) (type-to-make type) (elt-size uint) (elt-count uint))
|
|
"Create a new rpc-buffer with room for elt-count elements of elt-size.
|
|
The element array is 64-byte aligned."
|
|
;; we make room for a buffer of size elt-size * elt-count that is _64 byte_ aligned.
|
|
(let ((obj (object-new allocation type-to-make (the int (+ (-> type-to-make size) 63 (* elt-size elt-count))))))
|
|
(set! (-> obj elt-size) elt-size)
|
|
(set! (-> obj elt-count) elt-count)
|
|
(set! (-> obj elt-used) 0)
|
|
(set! (-> obj busy) '#f)
|
|
;(set! (-> obj base) (logand -64 (+ (the uint obj) 28 63)))
|
|
;; base is the 64-byte aligned buffer.
|
|
(set! (-> obj base) (the pointer (logand -64 (+ (the uint (-> obj data)) 63))))
|
|
obj
|
|
)
|
|
)
|
|
|
|
;; An RPC buffer pair is a pair of two buffers that implement double buffering.
|
|
;; The "current" buffer is the one being loaded on the EE.
|
|
;; The other is referred to as the active buffer.
|
|
;; This also supports receiving data, though it just gives you a plain pointer.
|
|
(deftype rpc-buffer-pair (basic)
|
|
((buffer rpc-buffer 2 :offset-assert 4) ;; the two buffers
|
|
(current rpc-buffer :offset-assert 12) ;; the buffer being loaded
|
|
(last-recv-buffer pointer :offset-assert 16) ;; the last reply
|
|
(rpc-port int32 :offset-assert 20) ;; the RPC port number
|
|
)
|
|
:method-count-assert 15
|
|
:size-assert #x18
|
|
:flag-assert #xf00000018
|
|
(:methods
|
|
(new (symbol type uint uint int) rpc-buffer-pair 0)
|
|
(call (rpc-buffer-pair uint pointer uint) int 9)
|
|
(add-element (rpc-buffer-pair) pointer 10)
|
|
(decrement-elt-used (rpc-buffer-pair) int 11)
|
|
(sync (rpc-buffer-pair symbol) int 12)
|
|
(check-busy (rpc-buffer-pair) symbol 13)
|
|
(pop-last-received (rpc-buffer-pair) pointer 14)
|
|
)
|
|
)
|
|
|
|
(defmethod new rpc-buffer-pair ((allocation symbol) (type-to-make type) (elt-size uint) (elt-count uint) (rpc-port int))
|
|
"Create a new rpc-buffer-pair"
|
|
(let ((obj (object-new allocation type-to-make)))
|
|
(set! (-> obj buffer 0) (new 'global 'rpc-buffer elt-size elt-count))
|
|
(set! (-> obj buffer 1) (new 'global 'rpc-buffer elt-size elt-count))
|
|
(set! (-> obj current) (-> obj buffer 0))
|
|
(set! (-> obj last-recv-buffer) (the pointer '#f))
|
|
(set! (-> obj rpc-port) rpc-port)
|
|
obj
|
|
)
|
|
)
|
|
|
|
;; method 12
|
|
(defmethod sync rpc-buffer-pair ((obj rpc-buffer-pair) (print-stall-warning symbol))
|
|
"Wait for the in progress RPC to complete."
|
|
(let ((active-buffer (if (= (-> obj buffer 0) (-> obj current))
|
|
(-> obj buffer 1)
|
|
(-> obj buffer 0))
|
|
)
|
|
)
|
|
|
|
(when (-> active-buffer busy)
|
|
;; the flag is set, meaning we should check.
|
|
(cond
|
|
((!= 0 (rpc-busy? (-> obj rpc-port)))
|
|
;; we're busy
|
|
(if print-stall-warning
|
|
(format 0 "STALL: waiting for IOP on RPC port #~D~%" (-> obj rpc-port))
|
|
)
|
|
(while (!= 0 (rpc-busy? (-> obj rpc-port)))
|
|
;; real game has a bunch of nops
|
|
(+ 1 2 3)
|
|
)
|
|
)
|
|
(else
|
|
;; not actually busy, clear the flag!
|
|
(set! (-> active-buffer busy) '#f)
|
|
(set! (-> active-buffer elt-used) 0)
|
|
)
|
|
)
|
|
)
|
|
|
|
)
|
|
0
|
|
)
|
|
|
|
;; method 13
|
|
(defmethod check-busy rpc-buffer-pair ((obj rpc-buffer-pair))
|
|
"Is the currently running RPC still busy?"
|
|
(let ((active-buffer (if (= (-> obj buffer 0) (-> obj current))
|
|
(-> obj buffer 1)
|
|
(-> obj buffer 0)
|
|
)))
|
|
(when (-> active-buffer busy)
|
|
(if (!= 0 (rpc-busy? (-> obj rpc-port)))
|
|
(return-from #f '#t)
|
|
)
|
|
(set! (-> active-buffer busy) '#f)
|
|
(set! (-> active-buffer elt-count) 0)
|
|
)
|
|
)
|
|
'#f
|
|
)
|
|
|
|
|
|
;; method 9
|
|
(defmethod call rpc-buffer-pair ((obj rpc-buffer-pair) (fno uint) (recv-buff pointer) (recv-size uint))
|
|
"Call an RPC. This is an async RPC. Use check-busy or sync to see if it's done."
|
|
(when (!= 0 (-> obj current elt-used))
|
|
;; when we have used elements
|
|
(format 0 "call rpc-buffer-pair with ~D elts~%" (-> obj current elt-used))
|
|
|
|
;; make sure the previous buffer is done
|
|
(let ((active-buffer (if (= (-> obj buffer 0) (-> obj current))
|
|
(-> obj buffer 1)
|
|
(-> obj buffer 0))))
|
|
(when (-> active-buffer busy)
|
|
;; we think the active buffer may be busy.
|
|
;; first lets just do a simple check
|
|
(cond
|
|
((!= 0 (rpc-busy? (-> obj rpc-port)))
|
|
;; busy! print an error and stall!
|
|
(format 0 "STALL: waiting for IOP on RPC port #~D~%" (-> obj rpc-port))
|
|
(while (!= 0 (rpc-busy? (-> obj rpc-port)))
|
|
(+ 1 2 3)
|
|
)
|
|
)
|
|
(else
|
|
;; not busy.
|
|
(set! (-> active-buffer busy) '#f)
|
|
(set! (-> active-buffer elt-used) 0)
|
|
)
|
|
)
|
|
)
|
|
;; now we've cleared the last RPC call, we can do another
|
|
(let ((current-buffer (-> obj current)))
|
|
;; rpc_channel, fno, async, send_buff, send_size, recv_buff, recv_size
|
|
(format 0 "recv-size is ~D~%" recv-size)
|
|
(rpc-call (-> obj rpc-port)
|
|
fno
|
|
(the uint 1)
|
|
(the uint (-> current-buffer base))
|
|
(the int (* (-> current-buffer elt-used) (-> current-buffer elt-size)))
|
|
(the uint recv-buff)
|
|
(the int recv-size)
|
|
)
|
|
(set! (-> current-buffer busy) '#t)
|
|
(set! (-> obj last-recv-buffer) recv-buff)
|
|
(set! (-> obj current) active-buffer)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
)
|
|
|
|
|
|
;; method 14
|
|
(defmethod pop-last-received rpc-buffer-pair ((obj rpc-buffer-pair))
|
|
(let ((result (-> obj last-recv-buffer)))
|
|
(set! (-> obj last-recv-buffer) (the pointer '#f))
|
|
result
|
|
)
|
|
)
|
|
|
|
;; method 10
|
|
(defmethod add-element rpc-buffer-pair ((obj rpc-buffer-pair))
|
|
"Add an element, and return a pointer to the element.
|
|
If we are out of elements, flush by doing an RPC call.
|
|
DANGER: this uses all arguments of 0. If you want something else, flush it yourself.
|
|
If we're RPC 0 and we do this auto-flush, print a warning.
|
|
"
|
|
(let ((current-buffer (-> obj current)))
|
|
(when (= (-> current-buffer elt-count) (-> current-buffer elt-used))
|
|
;; oops, we're full.
|
|
(if (= 0 (-> obj rpc-port))
|
|
;; if we're RPC 0, this is evidently a situation to warn about.
|
|
(format 0 "WARNING: too many sound commands queued~%")
|
|
)
|
|
;; otherwise we just flush
|
|
;; seems kinda dangerous. these could be the wrong parameters...
|
|
(call obj (the uint 0) (the pointer 0) (the uint 0))
|
|
;; update the current-buffer.
|
|
(set! current-buffer (-> obj current))
|
|
)
|
|
(let ((result (&+ (-> current-buffer base) (* (-> current-buffer elt-size) (-> current-buffer elt-used)))))
|
|
(+! (-> current-buffer elt-used) 1)
|
|
result
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
;; method 11
|
|
(defmethod decrement-elt-used rpc-buffer-pair ((obj rpc-buffer-pair))
|
|
"If elt-used > 0, decrease it by one."
|
|
(when (> (-> obj current elt-used) 0)
|
|
(-! (-> obj current elt-used) 1)
|
|
)
|
|
0
|
|
) |