mirror of
https://github.com/open-goal/jak-project
synced 2026-08-20 06:16:35 -04:00
up to gsound
This commit is contained in:
@@ -18669,7 +18669,7 @@ buffer if necessary, record receive-buffer, and swap buffers so new commands can
|
||||
submitted immediately with function number zero and no receive buffer before reserving the
|
||||
element, so callers needing other call parameters must flush explicitly."
|
||||
(rpc-buffer-pair) pointer) ;; 10
|
||||
(decrement-elt-used "Discard the most recently reserved element when the current buffer is not
|
||||
(free-last-element "Discard the most recently reserved element when the current buffer is not
|
||||
empty." (rpc-buffer-pair) int) ;; 11
|
||||
(sync "Wait for the previous buffer's RPC to finish, optionally print a stall warning, then
|
||||
release that buffer for reuse." (rpc-buffer-pair symbol) int) ;; 12
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "kernel/gcommon.gc")
|
||||
|
||||
;; Asserts didn't appear in the final game, likely they were disabled in the
|
||||
;; final build.
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Source location captured by the assert macro before it reports a failure.
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; A path-control is a curve that can be loaded from res-lump/entities.
|
||||
(deftype path-control (basic)
|
||||
"A resource-loaded polyline associated with a drawable process. The embedded curve stores the
|
||||
control-vertex pointer and count; plain path controls do not use knots."
|
||||
"A polyline associated with a process which stores its data in a resource lump.
|
||||
Despite having a curve, this base class is only a polyline.
|
||||
Use curve-control for the b-spline curve"
|
||||
((flags path-control-flag)
|
||||
(name symbol)
|
||||
(process process-drawable)
|
||||
@@ -42,38 +42,34 @@ control-vertex pointer and count; plain path controls do not use knots."
|
||||
|
||||
;; A curve-control is very similar, but also gets knots.
|
||||
(deftype curve-control (path-control)
|
||||
"A path control backed by a knot spline. If vertices load without matching knot data, the
|
||||
constructor downgrades the object to path-control."
|
||||
"A B-spline associated with a process which stores its data in a resource lump."
|
||||
()
|
||||
(:methods
|
||||
(new (symbol type process symbol float) _type_)))
|
||||
|
||||
(defmethod new path-control ((allocation symbol) (type-to-make type) (proc process) (name symbol) (time float))
|
||||
"Load the named control vertices for proc at time. A path named path may come from the
|
||||
linked path-actor; missing data sets not-found, while allocation failure reports an art error."
|
||||
(local-vars (tag res-tag))
|
||||
"Load the named control vertices for proc at time. If the name is `path`, we try a `path-actor`
|
||||
referenced by this process's actor."
|
||||
(let ((this (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
|
||||
(when (zero? this)
|
||||
;; allocation failed.
|
||||
(go process-drawable-art-error "memory")
|
||||
(set! this (the-as path-control 0))
|
||||
(goto cfg-9))
|
||||
(set! (-> this process) (the-as process-drawable proc))
|
||||
(set! (-> this name) name)
|
||||
(let ((ent (-> proc entity)))
|
||||
;; the path may be in a separate actor referenced by path-actor.
|
||||
(when (= name 'path)
|
||||
;; if we are a path, try to look up the path-actor.
|
||||
(let ((lookup-entity (entity-actor-lookup ent 'path-actor 0))) (if lookup-entity (set! ent lookup-entity))))
|
||||
;; look up the curve data
|
||||
(set! tag (new 'static 'res-tag))
|
||||
(let ((data (res-lump-data ent name pointer :tag-ptr (& tag) :time time)))
|
||||
(let ((lookup-entity (entity-actor-lookup ent 'path-actor 0)))
|
||||
(if lookup-entity
|
||||
(set! ent lookup-entity))))
|
||||
(let* ((tag (new 'static 'res-tag))
|
||||
(data (res-lump-data ent name pointer :tag-ptr (& tag) :time time)))
|
||||
(cond
|
||||
(data
|
||||
;; success, we got some data
|
||||
(set! (-> this cverts) (the-as (inline-array vector) data))
|
||||
(set! (-> this curve num-cverts) (the-as int (-> tag elt-count))))
|
||||
(else
|
||||
;; did not find the data. Set flags and zero stuff
|
||||
(else ;; not found
|
||||
(logior! (-> this flags) (path-control-flag not-found))
|
||||
(set! (-> this cverts) (the-as (inline-array vector) #f))
|
||||
(set! (-> this curve num-cverts) 0)
|
||||
@@ -109,8 +105,11 @@ constructor downgrades the object to path-control."
|
||||
)
|
||||
(else
|
||||
;; appends a -k to the symbol name.
|
||||
(let ((intern-symbol string->symbol)) (format (clear *temp-string*) "~A-k" name) (intern-symbol *temp-string*))))))
|
||||
(let ((lookup-entity (entity-actor-lookup ent 'path-actor 0))) (if lookup-entity (set! ent lookup-entity)))
|
||||
(let ((intern-symbol string->symbol))
|
||||
(format (clear *temp-string*) "~A-k" name)
|
||||
(intern-symbol *temp-string*))))))
|
||||
(let ((lookup-entity (entity-actor-lookup ent 'path-actor 0)))
|
||||
(if lookup-entity (set! ent lookup-entity)))
|
||||
(when (not (get-curve-data! ent (the-as curve (&-> this cverts)) name knot-name time))
|
||||
(cond
|
||||
((> (-> this curve num-cverts) 0)
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
(set! (-> request filename) (string->sound-name vis-filename))
|
||||
(set! (-> request ee-id) ramdisk-id)
|
||||
(load-dbg "doing ramdisk vis load: ~A~%" vis-filename)
|
||||
(call *ramdisk-rpc* RAMDISK_RPC_FILL_FNO (the-as pointer 0) (the-as uint 0))
|
||||
(call *ramdisk-rpc* (the uint (ramdisk-rpc-function reset-and-load)) (the-as pointer 0) (the-as uint 0))
|
||||
;; remember which ramdisk id we are assigned
|
||||
(set! (-> this vis-info (-> this vis-self-index) ramdisk) ramdisk-id)))
|
||||
;; return the ramdisk ID.
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; status flag sent from OVERLORD about a DGO load.
|
||||
;; Cancelling a DGO load is not really supported in Jak 1.
|
||||
(defenum load-msg-result
|
||||
:type uint16
|
||||
:bitfield #f
|
||||
@@ -22,21 +23,30 @@
|
||||
(invalid 666) ;; invalid status indicating a communication error.
|
||||
)
|
||||
|
||||
;; Commands sent to OVERLORD for streaming audio
|
||||
(defenum str-play-command
|
||||
:type uint16
|
||||
:bitfield #f
|
||||
(play 0)
|
||||
(stop 1)
|
||||
(queue 2))
|
||||
(play 0) ;; start playback
|
||||
(stop 1) ;; stop playback
|
||||
(queue 2)) ;; pre-load a file so playback can begin immediately.
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; load command sent to the IOP to load a DGO.
|
||||
;; The OVERLORD responds with the same message.
|
||||
(deftype load-dgo-msg (structure)
|
||||
"A 32-byte bidirectional DGO RPC message. A new load supplies two temporary object buffers, the
|
||||
current heap top, and the DGO name. A continuation supplies an updated heap top. The reply overlays
|
||||
b1 with the address of the loaded object and reports whether that object was the last in the DGO."
|
||||
"Bidirectional DGO RPC message.
|
||||
When starting a new load, GOAL code provides two temporary buffers b1 and b2
|
||||
for double buffering, and a pointer to the heap top bt.
|
||||
|
||||
When continuing a load, GOAL should update bt, the heap top.
|
||||
The OVERLORD replies with the address of the loaded object in b1.
|
||||
The linker is responsible for book-keeping the heap.
|
||||
Generally, objects are loaded/linked double buffered in b1/b2 until
|
||||
the final object (typically the very large level BSP), which is loaded
|
||||
directly to bt. This can overlap b1 and b2 to fill the heap completely,
|
||||
and avoids the need to copy from b1/b2 to the heap on the largest object."
|
||||
((rsvd uint16)
|
||||
(result load-msg-result)
|
||||
(b1 pointer)
|
||||
@@ -60,15 +70,11 @@ struct RPC_Dgo_Cmd {
|
||||
;; load commmand/response for loading a chunk of a file.
|
||||
;; It can either be an entire file, or a section of a STR file.
|
||||
(deftype load-chunk-msg (structure)
|
||||
"The shared 64-byte layout used for STR loads and streamed-audio commands. STR loads transmit
|
||||
only the first 32 bytes, so their filename occupies the first 16 bytes of basename; playback sends
|
||||
the full record and can use all 48 bytes. For playback, result is a str-play-command rather than a
|
||||
load status, and id overlays the destination address."
|
||||
((rsvd uint16)
|
||||
(result load-msg-result)
|
||||
(address pointer)
|
||||
(section uint32)
|
||||
(maxlen uint32)
|
||||
(address pointer) ;; Address to load to
|
||||
(section uint32) ;; chunk ID for a chunked file (typically animation) or -1 for whole file
|
||||
(maxlen uint32) ;; buffer size, loaded size
|
||||
(id uint32 :overlay-at address)
|
||||
(basename uint8 48)))
|
||||
|
||||
@@ -86,10 +92,7 @@ struct RPC_Str_Cmd {
|
||||
|
||||
;; The header before an object in a DGO file.
|
||||
(deftype dgo-header (structure)
|
||||
"The 64-byte header immediately before each GOAL object loaded from a DGO. length is the byte
|
||||
length of this object, not the DGO object count; rootname names the object, and its dynamic data
|
||||
begins directly after the header."
|
||||
((length uint32)
|
||||
((length uint32) ;; size of the object
|
||||
(rootname uint8 60)
|
||||
(data uint8 :dynamic)))
|
||||
|
||||
@@ -108,12 +111,21 @@ struct ObjectHeader {
|
||||
|
||||
(when (= 0 (the int *load-dgo-rpc*))
|
||||
;; we need to allocate the rpc buffers
|
||||
|
||||
;; DGO (contains all GOAL objects for a level) load RPC.
|
||||
(set! *load-dgo-rpc* (new 'global 'rpc-buffer-pair (the uint 32) (the uint 1) RPC-DGO))
|
||||
|
||||
;; File loading for streaming animation chunks
|
||||
(define *load-str-rpc* (new 'global 'rpc-buffer-pair (the uint 64) (the uint 1) RPC-LOAD-STR))
|
||||
|
||||
;; Streaming audio playback for animation. Audio remains entirely on the OVERLORD
|
||||
(define *play-str-rpc* (new 'global 'rpc-buffer-pair (the uint 64) (the uint 2) RPC-PLAY-STR))
|
||||
;; we have separate locks for queuing and loading.
|
||||
(define *load-str-lock* '#f)
|
||||
(define *que-str-lock* '#f)
|
||||
;; Lock on an in-progress animation chunk load. Prevent a new load from starting while
|
||||
;; one is already in progress.
|
||||
(define *load-str-lock* #f)
|
||||
;; Lock on OVERLORD-side streaming audio. Prevents an audio pre-load from
|
||||
;; kicking out the currently playing audio.
|
||||
(define *que-str-lock* #f)
|
||||
(define *dgo-name* (new 'global 'string 64 (the string '#f))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -146,7 +158,8 @@ struct ObjectHeader {
|
||||
(defun str-load-status ((length-out (pointer int32)))
|
||||
"Poll the current STR load. Return busy while the RPC is in flight,
|
||||
error when OVERLORD reports a failure, or complete after storing the loaded byte count in
|
||||
length-out."
|
||||
length-out. If not busy, also turns on the que-str-lock, preventing audio from
|
||||
being changed."
|
||||
;; still going..
|
||||
(if (check-busy *load-str-rpc*) (return 'busy))
|
||||
;; not busy, we can free the lock
|
||||
@@ -163,6 +176,9 @@ struct ObjectHeader {
|
||||
(defun str-load-cancel ()
|
||||
"Release this client's STR-load lock without cancelling the
|
||||
in-flight OVERLORD request. A new load still waits for the RPC channel to become idle."
|
||||
|
||||
;; there's no cancel feature, so the best we do is allow a new load to start
|
||||
;; once the RPC isn't busy.
|
||||
(set! *load-str-lock* #f)
|
||||
;; keep the stream-selection queue unchanged for the rest of this update
|
||||
(set! *que-str-lock* #t)
|
||||
@@ -200,6 +216,8 @@ struct ObjectHeader {
|
||||
(let ((cmd (the-as load-chunk-msg (add-element *play-str-rpc*))))
|
||||
(charp<-string (-> cmd basename) name)
|
||||
(set! (-> cmd result) (the-as load-msg-result (str-play-command queue)))))
|
||||
|
||||
;; this lock release is a bit odd...
|
||||
(set! *que-str-lock* #f)
|
||||
(none))
|
||||
|
||||
@@ -228,10 +246,12 @@ struct ObjectHeader {
|
||||
(defun str-play-kick ()
|
||||
"Send the accumulated streamed-audio commands when the playback RPC
|
||||
channel is idle."
|
||||
;; is written with an empty body for the first case.
|
||||
(cond
|
||||
((check-busy *play-str-rpc*))
|
||||
(else (call *play-str-rpc* (the-as uint 0) (the-as pointer 0) (the-as uint 0))))
|
||||
((check-busy *play-str-rpc*)
|
||||
;; wait...
|
||||
)
|
||||
(else
|
||||
(call *play-str-rpc* (the-as uint 0) (the-as pointer 0) (the-as uint 0))))
|
||||
(none))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -249,16 +269,15 @@ struct ObjectHeader {
|
||||
(format 0 "Starting level load clock~%")
|
||||
;; flush pending RPC
|
||||
(sync *load-dgo-rpc* #t)
|
||||
;; grab a new command from the RCP buffer
|
||||
;; grab a new command from the RPC buffer
|
||||
(let ((cmd (the-as load-dgo-msg (add-element *load-dgo-rpc*))))
|
||||
;; set parameters
|
||||
(set! (-> cmd result) (load-msg-result invalid))
|
||||
(set! (-> cmd b1) buffer1)
|
||||
(set! (-> cmd b2) buffer2)
|
||||
(set! (-> cmd bt) buffer-top)
|
||||
;; modified due to OpenGOAL not supporting uint128 return values yet
|
||||
(set! (-> cmd name) (string->sound-name name))
|
||||
;; call now!
|
||||
;; send!
|
||||
(call *load-dgo-rpc* (the-as uint 0) (the-as pointer cmd) (the-as uint 32))
|
||||
cmd))
|
||||
|
||||
@@ -305,23 +324,23 @@ struct ObjectHeader {
|
||||
(defun dgo-load-cancel ()
|
||||
"Synchronize the DGO RPC and cancel the active load. Call this
|
||||
between receiving an object and requesting the next one; cancelling during an object transfer
|
||||
can stall for several frames."
|
||||
can stall for several frames due to the sync."
|
||||
(sync *load-dgo-rpc* #t)
|
||||
(let ((cmd (add-element *load-dgo-rpc*))) (call *load-dgo-rpc* (the-as uint 2) cmd (the-as uint 32)))
|
||||
(none))
|
||||
|
||||
(defun find-temp-buffer ((size int))
|
||||
"Return a 16-byte-aligned address in the current frame's global DMA
|
||||
"(unused) Return a 16-byte-aligned address in the current frame's global DMA
|
||||
buffer when it has room for size/16 plus two quadwords, otherwise return #f. The second branch
|
||||
repeats the same test and is unreachable."
|
||||
;; it checks the same thing twice.
|
||||
(let ((qwc (+ (/ size 16) 2)))
|
||||
(the-as pointer
|
||||
(cond
|
||||
((< (the-as uint qwc) (the-as uint (dma-buffer-free (-> *display* frames (-> *display* on-screen) frame global-buf))))
|
||||
(logand -16 (the-as int (&+ (-> *display* frames (-> *display* on-screen) frame global-buf base) 15))))
|
||||
((< (the-as uint qwc) (the-as uint (dma-buffer-free (-> *display* frames (-> *display* on-screen) frame global-buf))))
|
||||
(logand -16 (the-as int (&+ (-> *display* frames (-> *display* on-screen) frame global-buf base) 15))))))))
|
||||
((< (the-as uint qwc) (the-as uint (dma-buffer-free (-> (current-frame) global-buf))))
|
||||
(logand -16 (the-as int (&+ (-> (current-frame) global-buf base) 15))))
|
||||
((< (the-as uint qwc) (the-as uint (dma-buffer-free (-> (current-frame) global-buf))))
|
||||
(logand -16 (the-as int (&+ (-> (current-frame) global-buf base) 15))))))))
|
||||
|
||||
(defenum link-flag
|
||||
:bitfield #t
|
||||
@@ -333,11 +352,6 @@ struct ObjectHeader {
|
||||
(force-debug 4)
|
||||
(fast-link 5))
|
||||
|
||||
; (link-flag output-load-msg
|
||||
; output-load-true-msg
|
||||
; execute-login
|
||||
; fast-link)
|
||||
|
||||
(defun dgo-load-link ((obj-file dgo-header) (heap kheap) (print-login symbol) (last-object symbol))
|
||||
"Check the loaded object's heap bounds, remember its name, and start
|
||||
linking its data into heap. print-login enables linker login output; last-object enables the final
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
(reset-and-load 1)
|
||||
(bypass-load-file 4))
|
||||
|
||||
(defconstant RAMDISK_RPC_FILL_FNO (the uint (ramdisk-rpc-function reset-and-load)))
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; command to load something into the OVERLORD RAMDISK from the DVD
|
||||
|
||||
@@ -56,7 +56,8 @@
|
||||
;; Zero would take the old-diff=0 path and defeat this one-frame confirmation.
|
||||
(* 0.000000001 saturated-yaw)))))
|
||||
(set! (-> this old-y-angle-diff) saturated-yaw)
|
||||
(let ((rotation (get-quaternion this))) (quaternion-rotate-y! rotation rotation saturated-yaw))))
|
||||
(let ((rotation (get-quaternion this)))
|
||||
(quaternion-rotate-y! rotation rotation saturated-yaw))))
|
||||
|
||||
(defmethod set-heading-vec! ((this trsqv) (heading vector))
|
||||
"Immediately turn toward heading within the plane perpendicular to the current up direction,
|
||||
@@ -189,8 +190,8 @@
|
||||
(.lvf vf3 (&-> dst vector 0 quad))
|
||||
(.lvf vf4 (&-> dst vector 1 quad))
|
||||
(.lvf vf5 (&-> dst vector 2 quad))
|
||||
(.mov.vf.w vf2 vf0)
|
||||
(.mul.x.vf vf3 vf3 vf1)
|
||||
(.mov.vf.w vf2 vf0) ;; set trans.w = 1
|
||||
(.mul.x.vf vf3 vf3 vf1) ;; apply scale
|
||||
(.mul.y.vf vf4 vf4 vf1)
|
||||
(.mul.z.vf vf5 vf5 vf1)
|
||||
(.svf (&-> dst vector 3 quad) vf2)
|
||||
@@ -215,8 +216,8 @@
|
||||
(.lvf vf3 (&-> dst vector 0 quad))
|
||||
(.lvf vf4 (&-> dst vector 1 quad))
|
||||
(.lvf vf5 (&-> dst vector 2 quad))
|
||||
(.mov.vf vf2 vf0)
|
||||
(.mul.x.vf vf3 vf3 vf1)
|
||||
(.mov.vf vf2 vf0) ;; set trans = [0, 0, 0, 1]
|
||||
(.mul.x.vf vf3 vf3 vf1) ;; apply scale
|
||||
(.mul.y.vf vf4 vf4 vf1)
|
||||
(.mul.z.vf vf5 vf5 vf1)
|
||||
(.svf (&-> dst vector 3 quad) vf2)
|
||||
@@ -244,14 +245,14 @@
|
||||
(.lvf vf3 (&-> dst vector 0 quad))
|
||||
(.lvf vf4 (&-> dst vector 1 quad))
|
||||
(.lvf vf5 (&-> dst vector 2 quad))
|
||||
(.mov.vf.w vf2 vf0)
|
||||
(.mul.x.vf vf3 vf3 vf1)
|
||||
(.mov.vf.w vf2 vf0) ;; set original-trans.w = 1
|
||||
(.mul.x.vf vf3 vf3 vf1) ;; scale matrix
|
||||
(.mul.y.vf vf4 vf4 vf1)
|
||||
(.mul.z.vf vf5 vf5 vf1)
|
||||
(.mul.x.vf acc vf3 vf6)
|
||||
(.mul.x.vf acc vf3 vf6) ;; rotate local-offset by scaled matrix
|
||||
(.add.mul.y.vf acc vf4 vf6 acc)
|
||||
(.add.mul.z.vf acc vf5 vf6 acc)
|
||||
(.add.mul.w.vf.xyz vf2 vf2 vf0 acc)
|
||||
(.add.mul.w.vf.xyz vf2 vf2 vf0 acc) ;; adds the offset and original translation
|
||||
(.svf (&-> dst vector 3 quad) vf2)
|
||||
(.svf (&-> dst vector 0 quad) vf3)
|
||||
(.svf (&-> dst vector 1 quad) vf4)
|
||||
@@ -276,11 +277,11 @@
|
||||
(.lvf vf3 (&-> dst vector 0 quad))
|
||||
(.lvf vf4 (&-> dst vector 1 quad))
|
||||
(.lvf vf5 (&-> dst vector 2 quad))
|
||||
(.mov.vf.w vf2 vf0)
|
||||
(.mul.x.vf vf3 vf3 vf1)
|
||||
(.mov.vf.w vf2 vf0) ;; set trans.w = 1
|
||||
(.mul.x.vf vf3 vf3 vf1) ;; scale matrix
|
||||
(.mul.y.vf vf4 vf4 vf1)
|
||||
(.mul.z.vf vf5 vf5 vf1)
|
||||
(.add.vf.xyz vf2 vf2 vf6)
|
||||
(.add.vf.xyz vf2 vf2 vf6) ;; add world trans offset
|
||||
(.svf (&-> dst vector 3 quad) vf2)
|
||||
(.svf (&-> dst vector 0 quad) vf3)
|
||||
(.svf (&-> dst vector 1 quad) vf4)
|
||||
@@ -307,15 +308,15 @@
|
||||
(set! (-> inverse-parent-scale z) (/ 1.0 (-> parent-scale z)))
|
||||
(.lvf vf1 (&-> src scale quad))
|
||||
(.lvf vf2 (&-> src trans quad))
|
||||
(.mov.vf.w vf2 vf0)
|
||||
(.mov.vf.w vf2 vf0) ;; trans.w = 0
|
||||
(.lvf vf4 (&-> dst vector 0 quad))
|
||||
(.lvf vf5 (&-> dst vector 1 quad))
|
||||
(.lvf vf6 (&-> dst vector 2 quad))
|
||||
(.mul.x.vf vf4 vf4 vf1)
|
||||
(.mul.x.vf vf4 vf4 vf1) ;; apply our scale
|
||||
(.mul.y.vf vf5 vf5 vf1)
|
||||
(.mul.z.vf vf6 vf6 vf1)
|
||||
(.lvf vf3 (&-> inverse-parent-scale quad)))
|
||||
(.mul.vf vf4 vf4 vf3)
|
||||
(.mul.vf vf4 vf4 vf3) ;; apply inverse parent scale
|
||||
(.mul.vf vf5 vf5 vf3)
|
||||
(.mul.vf vf6 vf6 vf3)
|
||||
(.svf (&-> dst vector 3 quad) vf2)
|
||||
|
||||
@@ -36,14 +36,12 @@
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; Nav mesh triangle. In jak 1, nav-poly is always a triangle.
|
||||
(deftype nav-poly (structure)
|
||||
"One navigation triangle. vertex indexes the mesh-local vertex array; adj-poly gives neighboring
|
||||
triangles with 255 as the boundary sentinel. pat bit zero marks a gap and the remaining defined
|
||||
bits select debug colors."
|
||||
((id uint8)
|
||||
(vertex uint8 3)
|
||||
(adj-poly uint8 3)
|
||||
(pat uint8))
|
||||
(vertex uint8 3) ;; index into mesh vertex table
|
||||
(adj-poly uint8 3) ;; 255 for no neighbor
|
||||
(pat uint8)) ;; first bit set on gaps, other bits used for colors
|
||||
:pack-me)
|
||||
|
||||
(deftype nav-vertex (vector)
|
||||
@@ -51,7 +49,7 @@ bits select debug colors."
|
||||
())
|
||||
|
||||
(deftype nav-sphere (structure)
|
||||
"A world-space obstacle sphere baked into the level navigation data."
|
||||
"A world-space obstacle sphere."
|
||||
((trans sphere :inline)))
|
||||
|
||||
(deftype nav-ray (structure)
|
||||
@@ -252,13 +250,15 @@ gathers obstacle spheres, and reports gap, blocked, and destination progress to
|
||||
;; try to find an entity with a nav-mesh, first from the given process
|
||||
(let ((ent (-> proc entity)))
|
||||
(when (zero? (-> ent nav-mesh))
|
||||
;; and if that doesn't have one already, lookup from the res-lump
|
||||
(let ((lookup-entity (entity-actor-lookup ent 'nav-mesh-actor 0))) (if lookup-entity (set! ent lookup-entity))))
|
||||
;; now, look at the nav-mesh from the entity
|
||||
;; and if that doesn't have a nav-mesh, see if the res-lump specifies another entity-actor to check
|
||||
(let ((lookup-entity (entity-actor-lookup ent 'nav-mesh-actor 0)))
|
||||
(if lookup-entity
|
||||
(set! ent lookup-entity))))
|
||||
;; try the nav-mesh from the entity
|
||||
(let ((entity-nav-mesh (-> ent nav-mesh)))
|
||||
(cond
|
||||
((nonzero? entity-nav-mesh)
|
||||
;; We have a nav mesh already.
|
||||
;; We have a nav mesh, see if it needs initialization
|
||||
(when (zero? (-> entity-nav-mesh user-list))
|
||||
;; Use the current process's level heap because process-level-heap is not guaranteed to
|
||||
;; be established while navigation connections are built.
|
||||
@@ -267,12 +267,15 @@ gathers obstacle spheres, and reports gap, blocked, and destination progress to
|
||||
(set! (-> entity-nav-mesh user-list)
|
||||
(new 'process-level-heap 'engine 'nav-engine (res-lump-value ent 'nav-max-users int :default (the-as uint128 32))))
|
||||
(initialize-mesh! entity-nav-mesh)
|
||||
;; the route table in the nav-mesh is patched so adjacent triangles have a portal
|
||||
;; edge index of 3. Unclear why this isn't done in advance.
|
||||
(update-route-table entity-nav-mesh))
|
||||
;; param1 is the user process, param2 its nav-control, and param3 its transform or shape.
|
||||
(add-connection (-> entity-nav-mesh user-list) proc nothing proc nav-cont trans))
|
||||
(else
|
||||
;; Mark an actor setup error and use the empty default mesh.
|
||||
(if (and nav-cont (-> proc entity)) (logior! (-> proc entity extra perm status) (entity-perm-status error)))
|
||||
(if (and nav-cont (-> proc entity))
|
||||
(logior! (-> proc entity extra perm status) (entity-perm-status error)))
|
||||
(set! entity-nav-mesh *default-nav-mesh*)))
|
||||
entity-nav-mesh)))
|
||||
|
||||
|
||||
@@ -3,18 +3,14 @@
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "kernel/gcommon.gc")
|
||||
|
||||
;; RPC channels.
|
||||
;; Channel indices to execute remote procedure calls in the Overlord IOP driver.
|
||||
;; these should match XXX_RPC_CHANNEL in the game/common/xxx_rpc_types.h
|
||||
|
||||
(defconstant RPC-SOUND-PLAYER 0) ;; called player in IOP code
|
||||
|
||||
(defconstant RPC-SOUND-LOADER 1) ;; called loader in IOP code
|
||||
|
||||
(defconstant RPC-RAMDISK 2) ;; called server in IOP code, sometimes
|
||||
|
||||
(defconstant RPC-DGO 3)
|
||||
|
||||
(defconstant RPC-LOAD-STR 4) ;; called STR in IOP code
|
||||
|
||||
(defconstant RPC-PLAY-STR 5) ;; called PLAY in IOP code
|
||||
|
||||
(defun-extern sound-buffer-dump int)
|
||||
@@ -33,7 +29,6 @@ payload area within the dynamic trailing allocation."
|
||||
(elt-used uint32)
|
||||
(busy symbol) ;; are we being sent currently?
|
||||
(base pointer) ;; 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)))
|
||||
@@ -69,7 +64,7 @@ the other buffer may still be in use by the IOP."
|
||||
(new (symbol type uint uint int) rpc-buffer-pair)
|
||||
(call (rpc-buffer-pair uint pointer uint) int)
|
||||
(add-element (rpc-buffer-pair) pointer)
|
||||
(decrement-elt-used (rpc-buffer-pair) int)
|
||||
(free-last-element (rpc-buffer-pair) int)
|
||||
(sync (rpc-buffer-pair symbol) int)
|
||||
(check-busy (rpc-buffer-pair) symbol)
|
||||
(pop-last-received (rpc-buffer-pair) pointer)))
|
||||
@@ -163,7 +158,9 @@ the other buffer may still be in use by the IOP."
|
||||
(defmethod pop-last-received ((this rpc-buffer-pair))
|
||||
"Return and clear the receive-buffer pointer supplied to the most recent
|
||||
call. The caller must first establish that the asynchronous RPC has completed."
|
||||
(let ((result (-> this last-recv-buffer))) (set! (-> this last-recv-buffer) (the-as pointer #f)) result))
|
||||
(let ((result (-> this last-recv-buffer)))
|
||||
(set! (-> this last-recv-buffer) (the-as pointer #f))
|
||||
result))
|
||||
|
||||
(defmethod add-element ((this rpc-buffer-pair))
|
||||
"Reserve and return the next element in the current buffer. A full buffer is
|
||||
@@ -187,7 +184,7 @@ the other buffer may still be in use by the IOP."
|
||||
(+! (-> current-buffer elt-used) 1)
|
||||
result)))
|
||||
|
||||
(defmethod decrement-elt-used ((this rpc-buffer-pair))
|
||||
(defmethod free-last-element ((this rpc-buffer-pair))
|
||||
"Discard the most recently reserved element when the current buffer is not
|
||||
empty."
|
||||
(if (> (-> this current elt-used) 0) (+! (-> this current elt-used) -1))
|
||||
|
||||
@@ -59,7 +59,10 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
(defun current-str-pos ((id sound-id))
|
||||
"Return the current streamed-audio position for id, or -1 when
|
||||
another stream is active."
|
||||
(let ((position -1)) (if (= id (-> *sound-iop-info* str-id)) (set! position (-> *sound-iop-info* strpos))) position))
|
||||
(let ((position -1))
|
||||
(if (= id (-> *sound-iop-info* str-id))
|
||||
(set! position (-> *sound-iop-info* strpos)))
|
||||
position))
|
||||
|
||||
(defun is-cd-in? ()
|
||||
"Return whether the IOP reports that a disc is present."
|
||||
@@ -74,7 +77,8 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
"Allocate the next sound ID, reserving values below #x10000 even after
|
||||
the counter wraps."
|
||||
(set! *current-sound-id* (the sound-id (1+ (the uint *current-sound-id*))))
|
||||
(if (< (the-as int *current-sound-id*) #x10000) (set! *current-sound-id* (the-as sound-id #x10000)))
|
||||
(if (< (the-as int *current-sound-id*) #x10000)
|
||||
(set! *current-sound-id* (the-as sound-id #x10000)))
|
||||
*current-sound-id*)
|
||||
|
||||
(defun check-irx-version ()
|
||||
@@ -135,16 +139,15 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
(call *sound-loader-rpc* (the-as uint 0) (the-as pointer 0) (the-as uint 0))
|
||||
0)
|
||||
|
||||
;; Load the common sound bank, which remains loaded the whole time
|
||||
(case (scf-get-territory)
|
||||
((GAME_TERRITORY_SCEI) (sound-bank-load (static-sound-name "commonj")))
|
||||
(else (sound-bank-load (static-sound-name "common"))))
|
||||
|
||||
;; Load empty sound banks in the other two slots
|
||||
(sound-bank-load (static-sound-name "empty1"))
|
||||
|
||||
(sound-bank-load (static-sound-name "empty2"))
|
||||
|
||||
(define *sound-bank-1* 'empty1)
|
||||
|
||||
(define *sound-bank-2* 'empty2)
|
||||
|
||||
(defun sound-reload-info ()
|
||||
@@ -212,13 +215,20 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
listener state when space permits. Disable new sound commands while the previous RPC remains busy,
|
||||
and show the no-disc or bad-disc screen reported by the IOP."
|
||||
(cond
|
||||
((check-busy *sound-player-rpc*) (set! *sound-player-enable* #f))
|
||||
((check-busy *sound-player-rpc*)
|
||||
;; stop generating sounds to let the IOP catch up
|
||||
(set! *sound-player-enable* #f))
|
||||
(else
|
||||
(let ((command-buffer (-> *sound-player-rpc* current)))
|
||||
;; set "ear" location if there's room
|
||||
(if (< (-> command-buffer elt-used) (-> command-buffer elt-count))
|
||||
(sound-set-ear-trans ear-position camera-position camera-angle)))
|
||||
;; submit sounds to IOP!
|
||||
(call *sound-player-rpc* (the-as uint 0) (the-as pointer 0) (the-as uint 0))
|
||||
;; re-enable more sounds to be queued by the engine on the next fame.
|
||||
(set! *sound-player-enable* #t)))
|
||||
|
||||
;; display CD errors to user
|
||||
(cond
|
||||
((not (is-cd-in?))
|
||||
(if (or (not *progress-process*) (!= (-> *progress-process* 0 display-state) (progress-screen no-disc)))
|
||||
@@ -235,7 +245,7 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
|
||||
(defun free-last-sound-buffer-entry ()
|
||||
"Discard the most recently reserved sound-player command."
|
||||
(decrement-elt-used *sound-player-rpc*)
|
||||
(free-last-element *sound-player-rpc*)
|
||||
0)
|
||||
|
||||
(defun sound-basic-cb ((value int) (result (pointer int32)))
|
||||
@@ -255,9 +265,12 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
(defun sound-angle-convert ((angle float))
|
||||
"Interpret the low signed 16 bits of angle as one full turn,
|
||||
convert them to integer degrees, and wrap the result into zero through 359."
|
||||
(let ((degrees (the int (* (/ 360.0 65536.0) (the float (sar (shl (the int angle) 48) 48))))))
|
||||
(if (< degrees 0) (+! degrees 360))
|
||||
(if (< 359 degrees) (+! degrees -360))
|
||||
(let* ((signed-angle (unwrap-angle angle))
|
||||
(degrees (the int (* 0.005493164 signed-angle))))
|
||||
(if (< degrees 0)
|
||||
(+! degrees 360))
|
||||
(if (< 359 degrees)
|
||||
(+! degrees -360))
|
||||
degrees))
|
||||
|
||||
(defun string->sound-name ((str string))
|
||||
@@ -326,8 +339,6 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
"Queue name with the supplied sound ID, IOP-scale volume, pitch,
|
||||
bend, and group, then return id. trans may be a position, #t for the current process drawable's
|
||||
root, or #f for the listener."
|
||||
(local-vars (sv-16 sound-group))
|
||||
(set! sv-16 group)
|
||||
(let ((sound-trans trans))
|
||||
(when *sound-player-enable*
|
||||
(let ((cmd (the-as sound-rpc-play (get-sound-buffer-entry))))
|
||||
@@ -335,7 +346,7 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
(set! (-> cmd id) id)
|
||||
(set! (-> cmd name) name)
|
||||
(set! (-> cmd parms mask) (sound-mask))
|
||||
(set! (-> cmd parms group) sv-16)
|
||||
(set! (-> cmd parms group) group)
|
||||
(set! (-> cmd parms volume) vol)
|
||||
(set! (-> cmd parms pitch-mod) pitch)
|
||||
(set! (-> cmd parms bend) bend)
|
||||
@@ -505,61 +516,53 @@ starting at frame, extending 12 bytes past the nominal type into the 16-byte all
|
||||
"Update continuous playback or start a scheduled one-shot when its timer expires.
|
||||
Entity-backed sounds rebuild their shared specification and skip playback outside the far falloff
|
||||
distance."
|
||||
(if (not *ambient-sound-class*) (return (the int #f)))
|
||||
(cond
|
||||
((-> this spec)
|
||||
(when (or (< (-> this time-base) 0) (>= (-> *display* base-frame-counter) (-> this play-time)))
|
||||
(when (>= (-> this time-base) 0)
|
||||
(set! (-> this play-time)
|
||||
(+ (-> *display* base-frame-counter) (-> this time-base) (rand-vu-int-count (-> this time-random))))
|
||||
(set! (-> this playing-id) (new-sound-id)))
|
||||
(let ((spec (-> this spec)))
|
||||
(when (= spec *ambient-spec*)
|
||||
(set! (-> spec volume) (-> this volume))
|
||||
(set! (-> spec pitch-mod) (-> this pitch))
|
||||
(set! (-> spec bend) 0)
|
||||
(set! (-> spec sound-name) (-> this name))
|
||||
(set! (-> spec fo-max) (-> this falloff-far))
|
||||
(set! (-> spec mask) (sound-mask))
|
||||
(if (-> this params) (effect-param->sound-spec spec (-> this params) (-> this param-count))))
|
||||
(if (and (nonzero? (-> spec fo-max))
|
||||
(< (* 4096.0 (the float (-> spec fo-max))) (vector-vector-distance (ear-trans) (-> this trans))))
|
||||
(return 0))
|
||||
(when (and *debug-effect-control* (>= (-> this time-base) 0))
|
||||
(with-pp
|
||||
(format #t "(~5D) effect sound ~A ~G " (-> *display* base-frame-counter) (-> pp name) (-> spec sound-name-char))
|
||||
(with-pp
|
||||
(if (not *ambient-sound-class*)
|
||||
(return (the-as int #f)))
|
||||
(cond
|
||||
((-> this spec)
|
||||
(when (or (< (-> this time-base) 0) (>= (current-time) (-> this play-time)))
|
||||
(when (>= (-> this time-base) 0)
|
||||
(set! (-> this play-time) (+ (current-time) (-> this time-base) (rand-vu-int-count (the-as int (-> this time-random)))))
|
||||
(set! (-> this playing-id) (new-sound-id)))
|
||||
(let ((spec (-> this spec)))
|
||||
(when (= spec *ambient-spec*)
|
||||
(set! (-> spec volume) (-> this volume))
|
||||
(set! (-> spec pitch-mod) (-> this pitch))
|
||||
(set! (-> spec bend) 0)
|
||||
(set! (-> spec sound-name) (-> this name))
|
||||
(set! (-> spec fo-max) (-> this falloff-far))
|
||||
(set! (-> spec mask) (sound-mask))
|
||||
(if (-> this params)
|
||||
(effect-param->sound-spec spec (-> this params) (-> this param-count))))
|
||||
(if (and (nonzero? (-> spec fo-max))
|
||||
(< (* 4096.0 (the float (-> spec fo-max))) (vector-vector-distance (ear-trans) (-> this trans))))
|
||||
(return 0))
|
||||
(when (and *debug-effect-control* (>= (-> this time-base) 0))
|
||||
(format #t "(~5D) effect sound ~A ~G " (current-time) (-> pp name) (&-> spec sound-name))
|
||||
(format #t
|
||||
"volume: ~f pitch-mod: ~f~%"
|
||||
(* (1/ 10.24) (the float (-> spec volume)))
|
||||
(* 0.000656168 (the float (-> spec pitch-mod))))))
|
||||
(let ((spec-volume (-> spec volume)))
|
||||
(set! (-> spec volume) (-> this volume))
|
||||
(set! (-> this playing-id) (sound-play-by-spec spec (-> this playing-id) (-> this trans)))
|
||||
(set! (-> spec volume) spec-volume)))))
|
||||
(else
|
||||
(cond
|
||||
((< (-> this time-base) 0)
|
||||
(set! (-> this playing-id)
|
||||
(sound-play-by-name (-> this name)
|
||||
(-> this playing-id)
|
||||
(-> this volume)
|
||||
(-> this pitch)
|
||||
0
|
||||
(sound-group sfx)
|
||||
(the-as symbol (-> this trans)))))
|
||||
(else
|
||||
(when (>= (-> *display* base-frame-counter) (-> this play-time))
|
||||
(set! (-> this playing-id)
|
||||
(sound-play-by-name (-> this name)
|
||||
(new-sound-id)
|
||||
(-> this volume)
|
||||
(-> this pitch)
|
||||
0
|
||||
(sound-group sfx)
|
||||
(the-as symbol (-> this trans))))
|
||||
(set! (-> this play-time)
|
||||
(+ (-> *display* base-frame-counter) (-> this time-base) (rand-vu-int-count (-> this time-random)))))))))
|
||||
0)
|
||||
(* 0.09765625 (the float (-> spec volume)))
|
||||
(* 0.000656168 (the float (-> spec pitch-mod)))))
|
||||
(let ((spec-volume (-> spec volume)))
|
||||
(set! (-> spec volume) (-> this volume))
|
||||
(set! (-> this playing-id) (sound-play-by-spec spec (-> this playing-id) (-> this trans)))
|
||||
(set! (-> spec volume) spec-volume)))))
|
||||
((< (-> this time-base) 0)
|
||||
(set! (-> this playing-id)
|
||||
(sound-play-by-name (-> this name)
|
||||
(-> this playing-id)
|
||||
(-> this volume)
|
||||
(-> this pitch)
|
||||
0
|
||||
(sound-group sfx)
|
||||
(-> this trans))))
|
||||
(else
|
||||
(when (>= (current-time) (-> this play-time))
|
||||
(set! (-> this playing-id)
|
||||
(sound-play-by-name (-> this name) (new-sound-id) (-> this volume) (-> this pitch) 0 (sound-group sfx) (-> this trans)))
|
||||
(set! (-> this play-time) (+ (current-time) (-> this time-base) (rand-vu-int-count (the-as int (-> this time-random))))))))
|
||||
0))
|
||||
|
||||
(defmethod stop! ((this ambient-sound))
|
||||
"Queue a stop command for this background sound's current playback ID."
|
||||
@@ -694,7 +697,8 @@ event has no alternate variation for this bank."
|
||||
"Return the music variation mapped to event for music, or zero when
|
||||
the music or event has no mapping."
|
||||
(dotimes (i (-> *flava-table* count))
|
||||
(if (= (-> *flava-table* row i music) music) (return (the-as int (-> *flava-table* row i flava event)))))
|
||||
(if (= (-> *flava-table* row i music) music)
|
||||
(return (the-as int (-> *flava-table* row i flava event)))))
|
||||
0)
|
||||
|
||||
(defmacro flava-table-add (name &rest flavas)
|
||||
|
||||
@@ -2,47 +2,32 @@
|
||||
(in-package goal)
|
||||
(bundles "ENGINE.CGO" "GAME.CGO")
|
||||
(require "kernel-defs.gc")
|
||||
|
||||
(define-extern activate-hud (function process none))
|
||||
|
||||
(define-extern activate-orb-all (function int int))
|
||||
|
||||
(define-extern hide-hud (function none))
|
||||
|
||||
(define-extern hide-hud-quick (function none))
|
||||
|
||||
(define-extern hide-bottom-hud (function none))
|
||||
|
||||
(define-extern hud-hidden? (function symbol))
|
||||
|
||||
(define-extern bottom-hud-hidden? (function symbol))
|
||||
|
||||
(define-extern enable-hud (function none))
|
||||
|
||||
(define-extern disable-hud (function int none))
|
||||
|
||||
(declare-type hud process)
|
||||
|
||||
(declare-type hud-pickups hud)
|
||||
|
||||
(declare-type hud-money hud)
|
||||
|
||||
(declare-type hud-fuel-cell hud)
|
||||
|
||||
(declare-type hud-health hud)
|
||||
|
||||
(declare-type hud-buzzers hud)
|
||||
|
||||
(declare-type hud-power hud)
|
||||
|
||||
(declare-type hud-bike-speed hud)
|
||||
|
||||
(declare-type hud-bike-heat hud)
|
||||
|
||||
(declare-type hud-money-all hud)
|
||||
|
||||
;; DECOMP BEGINS
|
||||
|
||||
;; One manipy-backed HUD image with its screen position and nonuniform scale.
|
||||
;; A hud icon is a full 3D model drawn with a screen-space projection.
|
||||
;; The "manipy" controls the drawing of the model.
|
||||
(deftype hud-icon (basic)
|
||||
((icon (pointer manipy))
|
||||
(icon-y int32)
|
||||
|
||||
@@ -186,8 +186,7 @@
|
||||
(buzzer-count int32)) ;; total scout flies
|
||||
:pack-me)
|
||||
|
||||
;; Variable-length table of per-level collectible totals. The inline data continues beyond the
|
||||
;; nominal header size.
|
||||
;; Table of per-level collectible totals.
|
||||
(deftype game-count-info (basic)
|
||||
((length int32)
|
||||
(data count-info :inline :dynamic)))
|
||||
@@ -202,7 +201,8 @@
|
||||
|
||||
;; Progress-screen data for one level. text-group-index selects the level text bank, nb-of-tasks
|
||||
;; gives the used portion of the eight-entry task-info array, and buzzer-task-index identifies the
|
||||
;; scout-fly task or is -1 when the level has none.
|
||||
;; scout-fly task or is -1 when the level has none. The level text bank argument is set, but
|
||||
;; effectively useless since all text is in a common bank in the final build.
|
||||
(deftype level-tasks-info (basic)
|
||||
((level-name-id text-id)
|
||||
(text-group-index int32)
|
||||
|
||||
Reference in New Issue
Block a user