From 2f4a418102084d869aaaee8d80e5d8d6e78bca86 Mon Sep 17 00:00:00 2001 From: water111 Date: Mon, 17 Aug 2026 09:14:26 -0700 Subject: [PATCH] up to gsound --- decompiler/config/jak1/all-types.gc | 2 +- goal_src/jak1/engine/debug/assert-h.gc | 2 + goal_src/jak1/engine/geometry/path-h.gc | 37 +++-- goal_src/jak1/engine/level/level.gc | 2 +- goal_src/jak1/engine/load/load-dgo.gc | 90 +++++++----- goal_src/jak1/engine/load/ramdisk.gc | 2 - goal_src/jak1/engine/math/transformq.gc | 31 ++-- goal_src/jak1/engine/nav/navigate-h.gc | 27 ++-- goal_src/jak1/engine/ps2/rpc-h.gc | 17 +-- goal_src/jak1/engine/sound/gsound.gc | 138 +++++++++--------- goal_src/jak1/engine/ui/hud-h.gc | 21 +-- .../jak1/engine/ui/progress/progress-h.gc | 6 +- 12 files changed, 189 insertions(+), 186 deletions(-) diff --git a/decompiler/config/jak1/all-types.gc b/decompiler/config/jak1/all-types.gc index c8f993baec..724e1a5554 100644 --- a/decompiler/config/jak1/all-types.gc +++ b/decompiler/config/jak1/all-types.gc @@ -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 diff --git a/goal_src/jak1/engine/debug/assert-h.gc b/goal_src/jak1/engine/debug/assert-h.gc index 4926051c8c..ec94f2ff78 100644 --- a/goal_src/jak1/engine/debug/assert-h.gc +++ b/goal_src/jak1/engine/debug/assert-h.gc @@ -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. diff --git a/goal_src/jak1/engine/geometry/path-h.gc b/goal_src/jak1/engine/geometry/path-h.gc index ef363aa978..bc1b565172 100644 --- a/goal_src/jak1/engine/geometry/path-h.gc +++ b/goal_src/jak1/engine/geometry/path-h.gc @@ -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) diff --git a/goal_src/jak1/engine/level/level.gc b/goal_src/jak1/engine/level/level.gc index cac726cbbc..00b6178bf3 100644 --- a/goal_src/jak1/engine/level/level.gc +++ b/goal_src/jak1/engine/level/level.gc @@ -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. diff --git a/goal_src/jak1/engine/load/load-dgo.gc b/goal_src/jak1/engine/load/load-dgo.gc index dca321bd85..2ff36031cf 100644 --- a/goal_src/jak1/engine/load/load-dgo.gc +++ b/goal_src/jak1/engine/load/load-dgo.gc @@ -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 diff --git a/goal_src/jak1/engine/load/ramdisk.gc b/goal_src/jak1/engine/load/ramdisk.gc index d75d269b08..f978adb0ee 100644 --- a/goal_src/jak1/engine/load/ramdisk.gc +++ b/goal_src/jak1/engine/load/ramdisk.gc @@ -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 diff --git a/goal_src/jak1/engine/math/transformq.gc b/goal_src/jak1/engine/math/transformq.gc index 82918116d7..f2aa2ed89a 100644 --- a/goal_src/jak1/engine/math/transformq.gc +++ b/goal_src/jak1/engine/math/transformq.gc @@ -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) diff --git a/goal_src/jak1/engine/nav/navigate-h.gc b/goal_src/jak1/engine/nav/navigate-h.gc index 2dac01fe99..936aeeeda2 100644 --- a/goal_src/jak1/engine/nav/navigate-h.gc +++ b/goal_src/jak1/engine/nav/navigate-h.gc @@ -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))) diff --git a/goal_src/jak1/engine/ps2/rpc-h.gc b/goal_src/jak1/engine/ps2/rpc-h.gc index 6e55121958..bcb18396d3 100644 --- a/goal_src/jak1/engine/ps2/rpc-h.gc +++ b/goal_src/jak1/engine/ps2/rpc-h.gc @@ -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)) diff --git a/goal_src/jak1/engine/sound/gsound.gc b/goal_src/jak1/engine/sound/gsound.gc index 1ac00d9231..6fddb29d93 100644 --- a/goal_src/jak1/engine/sound/gsound.gc +++ b/goal_src/jak1/engine/sound/gsound.gc @@ -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) diff --git a/goal_src/jak1/engine/ui/hud-h.gc b/goal_src/jak1/engine/ui/hud-h.gc index 9fa6517393..d8e068946e 100644 --- a/goal_src/jak1/engine/ui/hud-h.gc +++ b/goal_src/jak1/engine/ui/hud-h.gc @@ -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) diff --git a/goal_src/jak1/engine/ui/progress/progress-h.gc b/goal_src/jak1/engine/ui/progress/progress-h.gc index 3683fccc2f..ea796e02a3 100644 --- a/goal_src/jak1/engine/ui/progress/progress-h.gc +++ b/goal_src/jak1/engine/ui/progress/progress-h.gc @@ -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)