mirror of
https://github.com/open-goal/jak-project
synced 2026-06-01 01:40:07 -04:00
2225 lines
87 KiB
Common Lisp
2225 lines
87 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: drawable.gc
|
|
;; name in dgo: drawable
|
|
;; dgos: ENGINE, GAME
|
|
|
|
(define-extern draw-vortex (function none))
|
|
|
|
;; DECOMP BEGINS
|
|
|
|
(defmacro spr-work ()
|
|
`(the work-area *fake-scratchpad-data*))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;
|
|
;; culling
|
|
;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; these functions check to see if objects are within view.
|
|
;; these use the math-camera values, which is calculated based on the in-game camera position/settings.
|
|
|
|
(defun sphere-cull ((arg0 vector))
|
|
"Is the given sphere in the view frustum?
|
|
Uses the planes in vf16-vf19."
|
|
(local-vars (v1-0 uint128) (v1-1 uint128) (v1-2 uint128))
|
|
(rlet ((acc :class vf)
|
|
(vf0 :class vf)
|
|
(vf10 :class vf)
|
|
(vf16 :class vf)
|
|
(vf17 :class vf)
|
|
(vf18 :class vf)
|
|
(vf19 :class vf)
|
|
(vf9 :class vf)
|
|
)
|
|
;; og:preserve-this modified for PC: these register would be loaded by the draw method of bsp.
|
|
(let ((at-0 *math-camera*))
|
|
(.lvf vf16 (&-> at-0 plane 0 quad))
|
|
(.lvf vf17 (&-> at-0 plane 1 quad))
|
|
(.lvf vf18 (&-> at-0 plane 2 quad))
|
|
(.lvf vf19 (&-> at-0 plane 3 quad))
|
|
)
|
|
(init-vf0-vector)
|
|
(.lvf vf10 (&-> arg0 quad))
|
|
(.mul.x.vf acc vf16 vf10)
|
|
(.add.mul.y.vf acc vf17 vf10 acc)
|
|
(.add.mul.z.vf acc vf18 vf10 acc)
|
|
(.sub.mul.w.vf vf9 vf19 vf0 acc)
|
|
;; og:preserve-this
|
|
;; checking to see if we are inside all 4 planes.
|
|
|
|
;; using the inside part of the sphere
|
|
(.add.w.vf vf9 vf9 vf10)
|
|
(.mov v1-0 vf9)
|
|
(.pcgtw v1-1 0 v1-0)
|
|
(.ppach v1-2 (the-as uint128 0) v1-1)
|
|
(zero? (the-as int v1-2))
|
|
)
|
|
)
|
|
|
|
;; og:preserve-this
|
|
(defun sphere-cull-for-ocean ((arg0 vector))
|
|
"Is the given sphere in the view frustum?
|
|
PC-port ocean version"
|
|
(local-vars (v1-0 uint128) (v1-1 uint128) (v1-2 uint128))
|
|
(rlet ((acc :class vf)
|
|
(vf0 :class vf)
|
|
(vf10 :class vf)
|
|
(vf16 :class vf)
|
|
(vf17 :class vf)
|
|
(vf18 :class vf)
|
|
(vf19 :class vf)
|
|
(vf9 :class vf)
|
|
)
|
|
;; og:preserve-this modified for PC: these register would be loaded by the draw method of bsp.
|
|
(cond
|
|
((-> *time-of-day-context* use-camera-other)
|
|
(let ((at-0 *math-camera*))
|
|
(.lvf vf16 (&-> at-0 plane-other 0 quad))
|
|
(.lvf vf17 (&-> at-0 plane-other 1 quad))
|
|
(.lvf vf18 (&-> at-0 plane-other 2 quad))
|
|
(.lvf vf19 (&-> at-0 plane-other 3 quad))
|
|
)
|
|
)
|
|
(else
|
|
(let ((at-0 *math-camera*))
|
|
(.lvf vf16 (&-> at-0 plane 0 quad))
|
|
(.lvf vf17 (&-> at-0 plane 1 quad))
|
|
(.lvf vf18 (&-> at-0 plane 2 quad))
|
|
(.lvf vf19 (&-> at-0 plane 3 quad))
|
|
)
|
|
)
|
|
)
|
|
|
|
(init-vf0-vector)
|
|
(.lvf vf10 (&-> arg0 quad))
|
|
(.mul.x.vf acc vf16 vf10)
|
|
(.add.mul.y.vf acc vf17 vf10 acc)
|
|
(.add.mul.z.vf acc vf18 vf10 acc)
|
|
(.sub.mul.w.vf vf9 vf19 vf0 acc)
|
|
|
|
;; checking to see if we are inside all 4 planes.
|
|
|
|
;; using the inside part of the sphere
|
|
(.add.w.vf vf9 vf9 vf10)
|
|
(.mov v1-0 vf9)
|
|
(.pcgtw v1-1 0 v1-0)
|
|
(.ppach v1-2 (the-as uint128 0) v1-1)
|
|
(zero? (the-as int v1-2))
|
|
)
|
|
)
|
|
|
|
|
|
(defun guard-band-cull ((arg0 vector))
|
|
"Is the given sphere within the guard band, and possibly needs clipping?"
|
|
(local-vars (v1-0 uint128) (v1-1 uint128) (v1-2 uint128))
|
|
(rlet ((acc :class vf)
|
|
(vf0 :class vf)
|
|
(vf10 :class vf)
|
|
(vf20 :class vf)
|
|
(vf21 :class vf)
|
|
(vf22 :class vf)
|
|
(vf23 :class vf)
|
|
(vf9 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
;; og:preserve-this modified for PC: these registers would be loaded in dma-add-process-drawable
|
|
(let ((at-0 *math-camera*))
|
|
(.lvf vf20 (&-> at-0 guard-plane 0 quad))
|
|
(.lvf vf21 (&-> at-0 guard-plane 1 quad))
|
|
(.lvf vf22 (&-> at-0 guard-plane 2 quad))
|
|
(.lvf vf23 (&-> at-0 guard-plane 3 quad))
|
|
)
|
|
(.lvf vf10 (&-> arg0 quad))
|
|
(.mul.x.vf acc vf20 vf10)
|
|
(.add.mul.y.vf acc vf21 vf10 acc)
|
|
(.add.mul.z.vf acc vf22 vf10 acc)
|
|
(.sub.mul.w.vf vf9 vf23 vf0 acc)
|
|
|
|
;; checking to see if we are outside any 1 of the 4 planes
|
|
|
|
;; using the outside part of the sphere.
|
|
(.sub.w.vf vf9 vf9 vf10)
|
|
(.mov v1-0 vf9)
|
|
(.pcgtw v1-1 0 v1-0)
|
|
(.ppach v1-2 (the-as uint128 0) v1-1)
|
|
(nonzero? (the-as int v1-2))
|
|
)
|
|
)
|
|
|
|
(defun sphere-in-view-frustum? ((arg0 sphere))
|
|
"Is the given sphere in the view frustum?
|
|
Safe to use anywhere, uses planes from math-camera.
|
|
Unlike sphere-cull, which assumes that the register are setup.
|
|
"
|
|
(local-vars (v1-1 uint128) (v1-2 uint128) (v1-3 uint128))
|
|
(rlet ((acc :class vf)
|
|
(vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf2 :class vf)
|
|
(vf3 :class vf)
|
|
(vf4 :class vf)
|
|
(vf5 :class vf)
|
|
(vf6 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(let ((v1-0 *math-camera*))
|
|
(.lvf vf6 (&-> arg0 quad))
|
|
(.lvf vf1 (&-> v1-0 plane 0 quad))
|
|
(.lvf vf2 (&-> v1-0 plane 1 quad))
|
|
(.lvf vf3 (&-> v1-0 plane 2 quad))
|
|
(.lvf vf4 (&-> v1-0 plane 3 quad))
|
|
)
|
|
(.mul.x.vf acc vf1 vf6)
|
|
(.add.mul.y.vf acc vf2 vf6 acc)
|
|
(.add.mul.z.vf acc vf3 vf6 acc)
|
|
(.sub.mul.w.vf vf5 vf4 vf0 acc)
|
|
(.add.w.vf vf5 vf5 vf6)
|
|
(.mov v1-1 vf5)
|
|
(.pcgtw v1-2 0 v1-1)
|
|
(.ppach v1-3 (the-as uint128 0) v1-2)
|
|
(zero? (the-as int v1-3))
|
|
)
|
|
)
|
|
|
|
(defun line-in-view-frustum? ((arg0 vector) (arg1 vector))
|
|
"Is the line segment at least partially in the view frustum?
|
|
Safe to use anywhere, uses planes in math-camera."
|
|
(local-vars (v1-1 uint128) (v1-2 uint128) (v1-3 uint128) (a0-1 uint128) (a0-2 uint128) (a0-3 uint128))
|
|
(rlet ((acc :class vf)
|
|
(vf0 :class vf)
|
|
(vf10 :class vf)
|
|
(vf16 :class vf)
|
|
(vf17 :class vf)
|
|
(vf18 :class vf)
|
|
(vf19 :class vf)
|
|
(vf9 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(let ((v1-0 *math-camera*))
|
|
(.lvf vf9 (&-> arg0 quad))
|
|
(.lvf vf10 (&-> arg1 quad))
|
|
(.lvf vf16 (&-> v1-0 plane 0 quad))
|
|
(.lvf vf17 (&-> v1-0 plane 1 quad))
|
|
(.lvf vf18 (&-> v1-0 plane 2 quad))
|
|
(.lvf vf19 (&-> v1-0 plane 3 quad))
|
|
)
|
|
(.mul.x.vf acc vf16 vf9)
|
|
(.add.mul.y.vf acc vf17 vf9 acc)
|
|
(.add.mul.z.vf acc vf18 vf9 acc)
|
|
(.sub.mul.w.vf vf9 vf19 vf0 acc)
|
|
(.mul.x.vf acc vf16 vf10)
|
|
(.add.mul.y.vf acc vf17 vf10 acc)
|
|
(.add.mul.z.vf acc vf18 vf10 acc)
|
|
(.sub.mul.w.vf vf10 vf19 vf0 acc)
|
|
(.mov v1-1 vf9)
|
|
(.pcgtw v1-2 0 v1-1)
|
|
(.ppach v1-3 (the-as uint128 0) v1-2)
|
|
(.mov a0-1 vf10)
|
|
(.pcgtw a0-2 0 a0-1)
|
|
(.ppach a0-3 (the-as uint128 0) a0-2)
|
|
(not (logtest? (the-as int v1-3) (the-as int a0-3)))
|
|
)
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; precomputed visibility
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(defun vis-cull ((id int))
|
|
"Is this thing visible in the precomputed visiblity data? By draw-node id.
|
|
Assumes the scratchpad has the vis-list loaded."
|
|
(let* ((vis-byte (-> (spr-work) background vis-list (/ id 8))) ;; vis byte
|
|
(shift-amount (+ 56 (logand id 7)))
|
|
(shifted (shl vis-byte shift-amount))
|
|
)
|
|
(< (the-as int shifted) 0)
|
|
)
|
|
)
|
|
|
|
(defun-debug vis-cull-debug ((a0-0 work-area) (id int))
|
|
"Like vis-cull, but you can specify a different work-area.
|
|
Unused."
|
|
(let* ((vis-byte (-> a0-0 background vis-list (/ id 8))) ;; vis byte
|
|
(shift-amount (+ 56 (logand id 7)))
|
|
(shifted (shl vis-byte shift-amount))
|
|
)
|
|
(< (the-as int shifted) 0)
|
|
)
|
|
)
|
|
|
|
(defun error-sphere ((arg0 drawable-error) (arg1 string))
|
|
"Draw a sphere with an error message around this drawable-error."
|
|
(when *artist-error-spheres*
|
|
(when (vis-cull (-> arg0 id))
|
|
(when (sphere-cull (-> arg0 bsphere))
|
|
(add-debug-sphere
|
|
#t
|
|
(bucket-id debug2)
|
|
(-> arg0 bsphere)
|
|
(-> arg0 bsphere w)
|
|
(new 'static 'rgba :r #x80 :a #x80)
|
|
)
|
|
(add-debug-text-3d
|
|
#t
|
|
(bucket-id debug-no-zbuf1)
|
|
arg1
|
|
(-> arg0 bsphere)
|
|
(font-color white)
|
|
(the-as vector2h #f)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; drawable methods
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; the drawable class is the base class for tons of things
|
|
;; basically anything in the a tree-like structure in the level uses this
|
|
;; so these methods are super vague and not well defined.
|
|
;; Generally, you shouldn't call any of these unless you know the type and
|
|
;; what they will do.
|
|
|
|
(defmethod login ((this drawable))
|
|
"Initialize a drawable after load."
|
|
this
|
|
)
|
|
|
|
(defmethod draw ((this drawable) (arg0 drawable) (arg1 display-frame))
|
|
"Draw something. The meaning of this depends on the exact drawable class,
|
|
but in general the heavy work isn't here - this just adds stuff to lists."
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod fill-collide-list-from-box ((this drawable) (arg0 int) (arg1 collide-list) (arg2 collide-query))
|
|
"Collect a list of collision meshes contained in the box."
|
|
0
|
|
)
|
|
|
|
(defmethod fill-collide-list-from-line-sphere ((this drawable) (arg0 int) (arg1 collide-list) (arg2 collide-query))
|
|
"Collect a list of collision meshes contained in 'line-sphere'."
|
|
0
|
|
)
|
|
|
|
(defmethod collect-regions ((this drawable) (arg0 sphere) (arg1 int) (arg2 region-prim-list))
|
|
"Determines the number of [[drawable]]s in the `obj` that overlap the given `area-of-interest` this number is stored in the `region-list`'s item count
|
|
@param area-of-interest The area defined by a sphere that we care about overlaps
|
|
@param _count The amount of [[drawable]]s in the object to enumerate through
|
|
@param! region-list Stores the overlapping regions and a count for how many were found
|
|
@returns none"
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod collect-stats ((this drawable))
|
|
"Collect statistics for debugging"
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod debug-draw ((this drawable) (arg0 drawable) (arg1 display-frame))
|
|
"Draw debug visualizations"
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod draw ((this drawable-error) (arg0 drawable-error) (arg1 display-frame))
|
|
"Draw a debug sphere."
|
|
(error-sphere arg0 (-> arg0 name))
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defmethod unpack-vis ((this drawable) (arg0 (pointer int8)) (arg1 (pointer int8)))
|
|
"Unpack vis data from arg1 to arg0, unpacking it. Return pointer to next thing."
|
|
arg1
|
|
)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; instance system
|
|
;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; instance debug
|
|
(define *edit-instance* (the-as string #f))
|
|
(when *debug-segment*
|
|
(define *instance-mem-usage* (new 'debug 'memory-usage-block))
|
|
)
|
|
|
|
(defun find-instance-by-name-level ((arg0 string) (arg1 level))
|
|
"Look in the given level for prototypes with the given name.
|
|
Will find both tie and shrub.
|
|
Despite the name, returns the _prototype_, not the instance (the instances aren't named)."
|
|
(let ((s5-0 (-> arg1 bsp drawable-trees)))
|
|
(dotimes (s4-0 (-> s5-0 length))
|
|
(let ((v1-3 (-> s5-0 trees s4-0)))
|
|
(case (-> v1-3 type)
|
|
((drawable-tree-instance-shrub)
|
|
(let ((s3-0 (-> (the-as drawable-tree-instance-shrub v1-3) info prototype-inline-array-shrub)))
|
|
(dotimes (s2-0 (-> s3-0 length))
|
|
(if (string= arg0 (-> s3-0 data s2-0 name))
|
|
(return (-> s3-0 data s2-0))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((drawable-tree-instance-tie)
|
|
(let ((s3-1 (-> (the-as drawable-tree-instance-tie v1-3) prototypes prototype-array-tie)))
|
|
(dotimes (s2-1 (-> s3-1 length))
|
|
(if (string= arg0 (-> s3-1 array-data s2-1 name))
|
|
(return (-> s3-1 array-data s2-1))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(the-as prototype-bucket #f)
|
|
)
|
|
|
|
(defun find-instance-by-name ((arg0 string))
|
|
"Look in all levels for prototypes with the given name.
|
|
Will find both tie and shrub.
|
|
Despite the name, returns the _prototype_, not the instance (the instances aren't named)."
|
|
(dotimes (s5-0 (-> *level* length))
|
|
(let ((a1-0 (-> *level* level s5-0)))
|
|
(when (= (-> a1-0 status) 'active)
|
|
(let ((a0-4 (find-instance-by-name-level arg0 a1-0)))
|
|
(if a0-4
|
|
(return a0-4)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(the-as prototype-bucket #f)
|
|
)
|
|
|
|
(defun prototypes-game-visible-set! ((arg0 pair) (arg1 symbol))
|
|
"Set the visibility of the given prototypes, to hide stuff in levels that shouldn't appear.
|
|
Also disables collision."
|
|
(let ((a0-1 (car arg0)))
|
|
(while (not (null? arg0))
|
|
(let ((v1-0 (find-instance-by-name (the-as string a0-1))))
|
|
(when v1-0
|
|
(if arg1
|
|
(logclear! (-> v1-0 flags) (prototype-flags visible no-collide))
|
|
(logior! (-> v1-0 flags) (prototype-flags visible no-collide))
|
|
)
|
|
)
|
|
)
|
|
(set! arg0 (cdr arg0))
|
|
(set! a0-1 (car arg0))
|
|
)
|
|
)
|
|
0
|
|
)
|
|
|
|
(defun-debug find-instance-by-index ((arg0 type) (arg1 int) (arg2 bsp-header))
|
|
"Find an instance by its index in the bsp's drawable-tree-instance array.
|
|
The type should be either drawable-tree-instance-shrub or drawable-tree-instance-tie.
|
|
If bsp-header isn't set, picks the first active level. Otherwise looks in the level with this bsp."
|
|
(dotimes (v1-0 (-> *level* length))
|
|
(let ((a3-3 (-> *level* level v1-0)))
|
|
(when (= (-> a3-3 status) 'active)
|
|
(let ((a3-4 (-> a3-3 bsp)))
|
|
(when (or (not arg2) (= a3-4 arg2))
|
|
(let ((a3-5 (-> a3-4 drawable-trees)))
|
|
(dotimes (t0-5 (-> a3-5 length))
|
|
(let ((t1-3 (-> a3-5 trees t0-5)))
|
|
(case (-> t1-3 type)
|
|
((drawable-tree-instance-shrub)
|
|
(when (= arg0 (-> t1-3 type))
|
|
(let ((v1-2 (-> (the-as drawable-tree-instance-shrub t1-3) info prototype-inline-array-shrub)))
|
|
(return (-> v1-2 data arg1))
|
|
)
|
|
)
|
|
)
|
|
((drawable-tree-instance-tie)
|
|
(when (= arg0 (-> t1-3 type))
|
|
(let ((v1-5 (-> (the-as drawable-tree-instance-tie t1-3) prototypes prototype-array-tie)))
|
|
(return (-> v1-5 array-data arg1))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(the-as prototype-bucket #f)
|
|
)
|
|
|
|
(defun-debug prototype-bucket-type ((arg0 prototype-bucket))
|
|
"Get the instance type for this bucket. Will always be instance-shrubbery/instance-tie, doesn't
|
|
consider generic/billboard stuff."
|
|
|
|
;; using 1 here to avoid generic stuff.
|
|
(case (-> arg0 geometry 1 type)
|
|
((prototype-shrubbery shrubbery)
|
|
instance-shrubbery
|
|
)
|
|
((prototype-tie prototype-tie tie-fragment)
|
|
instance-tie
|
|
)
|
|
)
|
|
)
|
|
|
|
(defun-debug prototype-bucket-recalc-fields ((arg0 prototype-bucket))
|
|
"Recalculate the dists for a prototype (either tie or shrub) after it has been adjusted."
|
|
(case (prototype-bucket-type arg0)
|
|
((instance-shrubbery)
|
|
(set! (-> arg0 rdists x) (/ 1.0 (- (-> arg0 dists w) (-> arg0 dists x))))
|
|
)
|
|
(else
|
|
(set! (-> arg0 dists z) (+ (-> arg0 dists x) (* 0.33333334 (- (-> arg0 dists w) (-> arg0 dists x)))))
|
|
(set! (-> arg0 rdists x) (/ 1.0 (- (-> arg0 dists z) (-> arg0 dists x))))
|
|
)
|
|
)
|
|
(set! (-> arg0 rdists z) (/ 1.0 (- (-> arg0 dists w) (-> arg0 dists z))))
|
|
(set! (-> arg0 dists y) (* 0.5 (-> arg0 dists x)))
|
|
(set! (-> arg0 rdists y) (/ 1.0 (-> arg0 dists y)))
|
|
arg0
|
|
)
|
|
|
|
(defun-debug print-prototype-list ()
|
|
"Print all prototypes in all loaded levels."
|
|
(local-vars (sv-16 (function prototype-bucket-shrub memory-usage-block int prototype-bucket-shrub)))
|
|
(dotimes (gp-0 (-> *level* length))
|
|
(let ((s5-0 (-> *level* level gp-0)))
|
|
(when (= (-> s5-0 status) 'active)
|
|
(format #t "-------- level ~S~%" (-> s5-0 name))
|
|
(let ((s5-1 (-> s5-0 bsp drawable-trees)))
|
|
(dotimes (s4-0 (-> s5-1 length))
|
|
(let ((v1-8 (-> s5-1 trees s4-0)))
|
|
(case (-> v1-8 type)
|
|
((drawable-tree-instance-shrub)
|
|
(let ((s3-0 (-> (the-as drawable-tree-instance-shrub v1-8) info prototype-inline-array-shrub)))
|
|
(dotimes (s2-0 (-> s3-0 length))
|
|
0
|
|
(let ((s1-0 (-> s3-0 data s2-0)))
|
|
(dotimes (s0-0 4)
|
|
(reset! *instance-mem-usage*)
|
|
(if (nonzero? (-> s1-0 geometry s0-0))
|
|
(mem-usage (-> s1-0 geometry s0-0) *instance-mem-usage* 0)
|
|
)
|
|
)
|
|
(let ((s0-1 s1-0))
|
|
(set! sv-16 (method-of-object s0-1 mem-usage))
|
|
(let ((a1-4 (reset! *instance-mem-usage*))
|
|
(a2-2 0)
|
|
)
|
|
(sv-16 s0-1 a1-4 a2-2)
|
|
)
|
|
)
|
|
(let ((v1-29 (calculate-total *instance-mem-usage*)))
|
|
(format
|
|
#t
|
|
" ~-48S~4D shrub ~5,,2fK ~4,,2fK~%"
|
|
(-> s1-0 name)
|
|
(-> s1-0 in-level)
|
|
(* 0.0009765625 (the float v1-29))
|
|
(* 0.0009765625 (the float (* (the-as uint 80) (-> s1-0 in-level))))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((drawable-tree-instance-tie)
|
|
(let ((s3-1 (-> (the-as drawable-tree-instance-tie v1-8) prototypes prototype-array-tie)))
|
|
(dotimes (s2-1 (-> s3-1 length))
|
|
0
|
|
(let ((s1-1 (-> s3-1 array-data s2-1)))
|
|
(reset! *instance-mem-usage*)
|
|
(dotimes (s0-2 4)
|
|
(when (nonzero? (-> s1-1 tie-geom s0-2))
|
|
(let* ((a0-13 (-> s1-1 tie-geom s0-2))
|
|
(t9-8 (method-of-object a0-13 mem-usage))
|
|
(a1-7 *instance-mem-usage*)
|
|
(v1-47 s0-2)
|
|
)
|
|
(t9-8 a0-13 a1-7 (logior (cond
|
|
((= v1-47 1)
|
|
4
|
|
)
|
|
((= v1-47 2)
|
|
8
|
|
)
|
|
((= v1-47 3)
|
|
16
|
|
)
|
|
(else
|
|
0
|
|
)
|
|
)
|
|
2
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(mem-usage s1-1 *instance-mem-usage* 0)
|
|
(let ((v1-54 (calculate-total *instance-mem-usage*)))
|
|
(format
|
|
#t
|
|
" ~-48S~4D tie ~5,,2fK ~4,,2fK~%"
|
|
(-> s1-1 name)
|
|
(-> s1-1 in-level)
|
|
(* 0.0009765625 (the float v1-54))
|
|
(* 0.0009765625 (the float (* (-> s1-1 in-level) 64)))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun-debug draw-instance-info ((arg0 string))
|
|
"Print info about a prototype."
|
|
(local-vars
|
|
(sv-16 uint)
|
|
;; og:preserve-this uint -> uint32
|
|
(sv-32 uint32)
|
|
(sv-48 uint32)
|
|
(sv-64 int)
|
|
(sv-80 int)
|
|
(sv-96 int)
|
|
(sv-112 int)
|
|
(sv-128 int)
|
|
(sv-144 int)
|
|
)
|
|
(when (and *display-instance-info* *edit-instance*)
|
|
(let ((s5-0 (find-instance-by-name *edit-instance*)))
|
|
(when s5-0
|
|
(dotimes (s4-0 (-> *level* length))
|
|
(let ((v1-5 (-> *level* level s4-0)))
|
|
(when (= (-> v1-5 status) 'active)
|
|
(let ((s3-0 (-> v1-5 bsp drawable-trees)))
|
|
(dotimes (s2-0 (-> s3-0 length))
|
|
(let ((v1-9 (-> s3-0 trees s2-0)))
|
|
(case (-> v1-9 type)
|
|
((drawable-tree-instance-shrub)
|
|
)
|
|
((drawable-tree-instance-tie)
|
|
(let ((s1-0 (-> v1-9 data (+ (-> v1-9 length) -1))))
|
|
(dotimes (s0-0 (-> (the-as drawable-inline-array-instance-tie s1-0) length))
|
|
(if (string= (-> (the-as drawable-inline-array-instance-tie s1-0) data s0-0 bucket-ptr name) *edit-instance*)
|
|
(add-debug-sphere
|
|
#t
|
|
(bucket-id debug-no-zbuf1)
|
|
(the-as
|
|
vector
|
|
(+ (the-as uint (-> (the-as drawable-inline-array-instance-tie s1-0) data 0 bsphere)) (* s0-0 64))
|
|
)
|
|
(-> (the-as drawable-inline-array-instance-tie s1-0) data s0-0 bsphere w)
|
|
(new 'static 'rgba :g #xff :a #x80)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(let ((s2-1 (prototype-bucket-type s5-0)))
|
|
(let ((s4-1 0))
|
|
0
|
|
(cond
|
|
((= s2-1 instance-shrubbery)
|
|
(set! s4-1 80)
|
|
)
|
|
((= s2-1 instance-tie)
|
|
(reset! *instance-mem-usage*)
|
|
(dotimes (s4-2 4)
|
|
(when (nonzero? (-> s5-0 geometry s4-2))
|
|
(let* ((a0-17 (-> s5-0 geometry s4-2))
|
|
(t9-5 (method-of-object a0-17 mem-usage))
|
|
(a1-6 *instance-mem-usage*)
|
|
(v1-40 s4-2)
|
|
)
|
|
(t9-5 a0-17 a1-6 (logior (cond
|
|
((= v1-40 1)
|
|
4
|
|
)
|
|
((= v1-40 2)
|
|
8
|
|
)
|
|
((= v1-40 3)
|
|
16
|
|
)
|
|
(else
|
|
0
|
|
)
|
|
)
|
|
2
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(set! s4-1 (+ (calculate-total *instance-mem-usage*) 64))
|
|
)
|
|
)
|
|
(mem-usage s5-0 (reset! *instance-mem-usage*) 0)
|
|
(let ((v1-50 (calculate-total *instance-mem-usage*)))
|
|
(format
|
|
arg0
|
|
"~%~A ~A b @ #x~X ~,,2fK/~,,2fK~%"
|
|
s2-1
|
|
(-> s5-0 name)
|
|
s5-0
|
|
(* 0.0009765625 (the float v1-50))
|
|
(* 0.0009765625 (the float s4-1))
|
|
)
|
|
)
|
|
)
|
|
(format arg0 "near: ~m mid: ~m far: ~m~%" (-> s5-0 dists x) (-> s5-0 dists z) (-> s5-0 dists w))
|
|
(let ((s3-2 0)
|
|
(s4-3 0)
|
|
)
|
|
(cond
|
|
((= s2-1 instance-shrubbery)
|
|
(let ((f30-0 0.0))
|
|
(format
|
|
arg0
|
|
"usage: vis: ~D shrub: ~D trans-shrub ~D bill: ~D in level: ~D~%"
|
|
(-> (the-as prototype-bucket-shrub s5-0) count 0)
|
|
(-> (the-as prototype-bucket-shrub s5-0) count 1)
|
|
(-> (the-as prototype-bucket-shrub s5-0) count 2)
|
|
(-> (the-as prototype-bucket-shrub s5-0) count 3)
|
|
(-> (the-as prototype-bucket-shrub s5-0) in-level)
|
|
)
|
|
(format arg0 "~%frag# tris dverts strlen tex~%")
|
|
(let ((s1-2 (the-as prototype-shrubbery (-> (the-as prototype-bucket-shrub s5-0) geometry 1)))
|
|
(s2-2 (+ (-> (the-as prototype-bucket-shrub s5-0) count 1) (-> (the-as prototype-bucket-shrub s5-0) count 2)))
|
|
)
|
|
(dotimes (s0-1 (-> s1-2 length))
|
|
(set! sv-16 (shrub-num-tris (-> s1-2 data s0-1)))
|
|
(set! sv-32 (-> s1-2 data s0-1 header data 2))
|
|
(set! sv-48 (-> s1-2 data s0-1 header data 0))
|
|
(format
|
|
arg0
|
|
"~5D ~4D ~5D ~6f ~D~%"
|
|
s0-1
|
|
sv-16
|
|
sv-32
|
|
(/ (* 2.0 (the float sv-16)) (the float (- sv-32 (the-as uint sv-16))))
|
|
sv-48
|
|
)
|
|
(+! s3-2 sv-16)
|
|
(+! s4-3 (the-as int sv-32))
|
|
(set! f30-0
|
|
(+ 29.0
|
|
(* 5.5 (the float (- sv-32 (the-as uint sv-16))))
|
|
(* 22.0 (the float sv-48))
|
|
(* 8.0 (the float sv-32))
|
|
(* 53.0 (the float (/ (+ s2-2 9) (the-as uint 10))))
|
|
(* (the float s2-2) (+ 15.0 (* 5.0 (the float sv-48)) (* 13.5 (the float sv-32))))
|
|
f30-0
|
|
)
|
|
)
|
|
)
|
|
(format
|
|
arg0
|
|
"total ~4D ~5D ~6f ~D speed: ~f~%"
|
|
s3-2
|
|
s4-3
|
|
(/ (* 2.0 (the float s3-2)) (the float (- s4-3 s3-2)))
|
|
(-> s5-0 utextures)
|
|
(/ f30-0 (* (the float s2-2) (the float s3-2)))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
((= s2-1 instance-tie)
|
|
(set! sv-144 0)
|
|
(let ((s1-3 0)
|
|
(s0-2 0)
|
|
(s2-3 0)
|
|
)
|
|
(format arg0 "~%level visible frags tris dverts strlen tex ttris~%")
|
|
(set! sv-64 1)
|
|
(set! sv-80 3)
|
|
(while (>= sv-80 sv-64)
|
|
(let ((v1-100 (-> (the-as prototype-bucket-tie s5-0) tie-geom sv-64)))
|
|
(set! sv-96 0)
|
|
(set! sv-112 0)
|
|
(set! sv-128 0)
|
|
(dotimes (a0-36 (-> v1-100 length))
|
|
(set! sv-96 (+ sv-96 (-> v1-100 data a0-36 debug num-tris)))
|
|
(set! sv-112 (+ sv-112 (-> v1-100 data a0-36 debug num-dverts)))
|
|
(set! sv-128 (+ sv-128 (-> v1-100 data a0-36 tex-count)))
|
|
)
|
|
(set! sv-144 (+ sv-144 (the-as int (-> (the-as prototype-bucket-tie s5-0) count sv-64))))
|
|
(format
|
|
arg0
|
|
"~5D ~7D ~5D ~5D"
|
|
sv-64
|
|
(-> (the-as prototype-bucket-tie s5-0) count sv-64)
|
|
(-> v1-100 length)
|
|
sv-96
|
|
)
|
|
)
|
|
(format
|
|
arg0
|
|
" ~5D ~6f ~3D ~5D~%"
|
|
sv-112
|
|
(/ (* 2.0 (the float sv-96)) (the float (- sv-112 sv-96)))
|
|
sv-128
|
|
(* (the-as uint sv-96) (the-as uint (-> (the-as prototype-bucket-tie s5-0) count sv-64)))
|
|
)
|
|
(+! s1-3 (* (the-as uint sv-96) (the-as uint (-> (the-as prototype-bucket-tie s5-0) count sv-64))))
|
|
(+! s0-2 (* (the-as uint sv-112) (the-as uint (-> (the-as prototype-bucket-tie s5-0) count sv-64))))
|
|
(+! s3-2 sv-96)
|
|
(+! s4-3 sv-112)
|
|
(+! s2-3 sv-128)
|
|
(set! sv-64 (+ sv-64 1))
|
|
)
|
|
(let ((t9-20 format)
|
|
(a0-52 arg0)
|
|
(a1-28 "total ~7D/~3D ~5D")
|
|
(a3-12 (-> s5-0 in-level))
|
|
)
|
|
(t9-20 a0-52 a1-28 sv-144 a3-12 s3-2)
|
|
)
|
|
(format
|
|
arg0
|
|
" ~5D ~6f ~3D ~5D~%"
|
|
s4-3
|
|
(/ (* 2.0 (the float s1-3)) (the float (- s0-2 s1-3)))
|
|
s2-3
|
|
s1-3
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defun-debug set-shadow-by-name ((arg0 string) (arg1 int) (arg2 int))
|
|
"Update the shadow masks and values for an active process-drawable."
|
|
(let ((v1-0 (process-by-name arg0 *active-pool*)))
|
|
(when v1-0
|
|
(let ((v1-1 (-> (the-as process-drawable v1-0) draw)))
|
|
(cond
|
|
((< arg2 16)
|
|
(logior! (-> v1-1 shadow-mask) (ash 1 arg1))
|
|
(logclear! (-> v1-1 shadow-values) (ash 15 (* arg1 4)))
|
|
(logior! (-> v1-1 shadow-values) (ash arg2 (* arg1 4)))
|
|
)
|
|
(else
|
|
(logclear! (-> v1-1 shadow-mask) (ash 1 arg1))
|
|
(logclear! (-> v1-1 shadow-values) (ash 15 (* arg1 4)))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defun-debug get-shadow-by-name ((arg0 string))
|
|
"Get the current mask/values for an active process-drawable"
|
|
(let ((v1-0 (process-by-name arg0 *active-pool*)))
|
|
(when v1-0
|
|
(let ((s5-0 (-> (the-as process-drawable v1-0) draw)))
|
|
(format 0 "actor ~s {~%" arg0)
|
|
(format 0 " SHADOW_MASK(0x~02x)~%" (-> s5-0 shadow-mask))
|
|
(format 0 " SHADOW_VALUES(0x~08x)~%" (-> s5-0 shadow-values))
|
|
)
|
|
(format 0 "}~%")
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defun-debug teleport-camera-by-name ((arg0 string))
|
|
"Send the camera to an entity, switch to string mode."
|
|
(let* ((gp-0 (entity-by-name arg0))
|
|
(v1-0 (if (type? gp-0 entity-actor)
|
|
gp-0
|
|
)
|
|
)
|
|
)
|
|
(if (and v1-0 *camera*)
|
|
(send-event *camera* 'teleport-to-vector-start-string (-> v1-0 trans))
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; foreground drawing system
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;; processes will call ja-post, which adds them to the matrix engine
|
|
;; the matrix engine runs (there's a few ways), it computes joints, then kicks out the process from the matrix engine
|
|
;; all drawable processes belong to the foreground-draw-engine.
|
|
;; - foreground-initialize-engines runs, preparing for the foreground engine run
|
|
;; - foreground-engine-execute runs,
|
|
;; - foreground-init runs
|
|
;; - execute-connections runs on the foreground engine
|
|
;; it calls add-process-drawable which calls dma-add-func which is usually dma-add-process-drawable
|
|
;; - dma-add-process-drawable does culling, picking lights/shadow
|
|
;; - calls foreground-draw
|
|
;; picks merc/emerc/shadow/generic/effects, more light processing
|
|
;; adds the bone calculation, calls the foreground-<renderer> to generate dma
|
|
;; - foreground-wrapup runs, patching up merc/emerc stuff
|
|
;; - foreground-execute-cpu-vu0-engines runs
|
|
;; - does bone calcs for merc
|
|
;; - does VU0/CPU stuff for generic/shadow/lightning
|
|
|
|
(defun dma-add-process-drawable ((pd process-drawable) (dc draw-control) (flag symbol) (dma-buf dma-buffer))
|
|
"Draw a normal process-drawable. Set up lighting/shadow settings, then pass on to foreground renderer."
|
|
(local-vars
|
|
(a0-82 int)
|
|
(a0-84 int)
|
|
(a3-11 uint128)
|
|
(sv-16 process-drawable)
|
|
(tod time-of-day-context)
|
|
(shadow-mask uint)
|
|
(lev-idx-for-mood uint)
|
|
(my-origin vector)
|
|
(lev-mood mood-context)
|
|
(light-result-bucket light-hash-bucket)
|
|
(index-ptr pointer)
|
|
(index-index int)
|
|
)
|
|
(with-pp
|
|
(rlet ((acc :class vf)
|
|
(Q :class vf)
|
|
(vf0 :class vf)
|
|
(vf1 :class vf)
|
|
(vf15 :class vf)
|
|
(vf16 :class vf)
|
|
(vf17 :class vf)
|
|
(vf18 :class vf)
|
|
(vf19 :class vf)
|
|
(vf2 :class vf)
|
|
(vf20 :class vf)
|
|
(vf21 :class vf)
|
|
(vf22 :class vf)
|
|
(vf23 :class vf)
|
|
(vf24 :class vf)
|
|
(vf25 :class vf)
|
|
(vf26 :class vf)
|
|
(vf27 :class vf)
|
|
(vf28 :class vf)
|
|
(vf29 :class vf)
|
|
(vf3 :class vf)
|
|
(vf4 :class vf)
|
|
(vf5 :class vf)
|
|
(vf6 :class vf)
|
|
)
|
|
(init-vf0-vector)
|
|
(set! sv-16 pd)
|
|
;; og:preserve-this
|
|
(reset! (-> *perf-stats* data (perf-stat-bucket foreground)))
|
|
|
|
;; skip drawing when in menu mode.
|
|
(when (-> *blit-displays-work* menu-mode)
|
|
(if (not (logtest? (-> dc status) (draw-control-status hud)))
|
|
(return #f)
|
|
)
|
|
)
|
|
|
|
;; clear previous on-screen flag, we don't know if we're on-screen yet.
|
|
(logclear! (-> dc status) (draw-control-status on-screen))
|
|
|
|
;; only if we should draw...
|
|
(when (not (logtest? (-> dc status) (draw-control-status no-draw no-draw-temp uninited)))
|
|
;; og:preserve-this scratchpad
|
|
(let ((fg-bounds (-> (scratchpad-object foreground-work) bounds))
|
|
(fg-lights (-> (scratchpad-object foreground-work) lights))
|
|
)
|
|
(set! tod *time-of-day-context*)
|
|
(.lvf vf16 (&-> dc origin quad))
|
|
(.svf (&-> fg-bounds quad) vf16)
|
|
|
|
;; sphere cull.
|
|
(when (sphere-in-view-frustum? fg-bounds)
|
|
(cond
|
|
((logtest? (-> dc global-effect) (draw-control-global-effect title-light))
|
|
;; magic special case for title light.
|
|
(when (not (-> tod title-updated))
|
|
(set! (-> tod title-updated) #t)
|
|
(let ((s1-0 (-> *math-camera* inv-camera-rot))
|
|
(a1-3 (new 'stack-no-clear 'vector))
|
|
(s2-0 (new 'stack-no-clear 'vector))
|
|
)
|
|
(set-vector! a1-3 0.612 0.5 -0.612 0.0)
|
|
(set-vector! s2-0 -0.696 0.174 0.696 0.0)
|
|
(vector-matrix*! (the-as vector (-> tod title-light-group)) a1-3 s1-0)
|
|
(vector-matrix*! (the-as vector (-> tod title-light-group dir1)) s2-0 s1-0)
|
|
)
|
|
)
|
|
(vu-lights<-light-group! fg-lights (-> tod title-light-group))
|
|
)
|
|
(else
|
|
;; terrible lighting and shadow stuff
|
|
(set! shadow-mask (-> dc shadow-mask))
|
|
(let ((shadow-mask-not (lognot shadow-mask)))
|
|
(set! lev-idx-for-mood (-> dc level-index))
|
|
(let ((light-idx (-> dc light-index))
|
|
(lg (new 'stack-no-clear 'light-group))
|
|
)
|
|
(if (and (>= lev-idx-for-mood (the-as uint 6)) (< light-idx (the-as uint 20)))
|
|
(+! light-idx 20)
|
|
)
|
|
(let ((v1-40 (the-as
|
|
mood-context
|
|
(+ (the-as uint (-> *level* level0 mood-context)) (* (the-as uint 5232) lev-idx-for-mood))
|
|
)
|
|
)
|
|
)
|
|
(cond
|
|
((< light-idx (the-as uint 8))
|
|
(quad-copy! (the-as pointer lg) (the-as pointer (-> v1-40 light-group light-idx)) 12)
|
|
)
|
|
((< light-idx (the-as uint 18))
|
|
(quad-copy! (the-as pointer lg) (the-as pointer (-> v1-40 light-group (+ light-idx -10))) 12)
|
|
)
|
|
((< light-idx (the-as uint 28))
|
|
(quad-copy! (the-as pointer lg) (the-as pointer (-> tod light-group (+ light-idx -20))) 12)
|
|
)
|
|
((< light-idx (the-as uint 38))
|
|
(quad-copy! (the-as pointer lg) (the-as pointer (-> tod light-group (+ light-idx -30))) 12)
|
|
)
|
|
)
|
|
)
|
|
(when (not (or (>= lev-idx-for-mood (the-as uint 6)) (zero? shadow-mask)))
|
|
(let ((packed-shadow-vals (-> dc shadow-values)))
|
|
(dotimes (light-idx2 4)
|
|
(when (nonzero? (-> lg lights light-idx2 mask))
|
|
(when (not (logtest? (-> lg lights light-idx2 mask) shadow-mask-not))
|
|
(let ((light-pal-idx (-> lg lights light-idx2 palette-index)))
|
|
(set! (-> lg lights light-idx2 extra x)
|
|
(* 0.0625
|
|
(the float (logand (ash packed-shadow-vals (* -4 light-pal-idx)) 15))
|
|
(-> lg lights light-idx2 extra x)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(when (or (and (>= light-idx (the-as uint 10)) (< light-idx (the-as uint 18)))
|
|
(and (>= light-idx (the-as uint 30)) (< light-idx (the-as uint 38)))
|
|
)
|
|
(dotimes (fg-light-lev-idx (-> *level* length))
|
|
(let ((lev (-> *level* level fg-light-lev-idx)))
|
|
(when (= (-> lev status) 'active)
|
|
(let ((light-hash (-> lev light-hash)))
|
|
(set! my-origin (-> dc origin))
|
|
(set! lev-mood (-> lev mood-context))
|
|
(when (nonzero? light-hash)
|
|
(let ((light-lookup-result (light-hash-get-bucket-index light-hash (-> dc origin))))
|
|
(when (!= light-lookup-result -1)
|
|
(set! light-result-bucket (-> light-hash bucket-array light-lookup-result))
|
|
(set! index-ptr (the pointer (+ (+ (-> light-result-bucket index) 0) (the-as uint (-> light-hash index-array)))))
|
|
(set! index-index 0)
|
|
(while (< index-index (the-as int (-> light-result-bucket count)))
|
|
(let* ((light-sphere (-> light-hash light-sphere-array (-> (the-as (pointer uint8) (&+ index-ptr index-index)))))
|
|
(palette-idx (-> light-sphere palette-index))
|
|
(interp (if (= palette-idx -1)
|
|
1.0
|
|
(-> lev-mood times palette-idx w)
|
|
)
|
|
)
|
|
)
|
|
(if (!= (* (-> light-sphere brightness) interp) 0.0)
|
|
(add-light-sphere-to-light-group lg light-sphere my-origin lev-mood)
|
|
)
|
|
)
|
|
(set! index-index (+ index-index 1))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; convert to vu format
|
|
(vu-lights<-light-group! fg-lights lg)
|
|
|
|
;; adjust shadow angle
|
|
(when (and (nonzero? (-> dc shadow-ctrl))
|
|
(-> dc shadow-ctrl)
|
|
(not (logtest? (-> dc shadow-ctrl settings flags) (shadow-flags disable-draw)))
|
|
(not (logtest? (-> dc shadow-ctrl settings flags) (shadow-flags shdf07)))
|
|
)
|
|
(let ((target-shadow-dir (new 'stack-no-clear 'vector))
|
|
(current-shadow-dir (-> dc shadow-ctrl settings shadow-dir))
|
|
(shadow-dir-w (-> dc shadow-ctrl settings shadow-dir w))
|
|
)
|
|
(.lvf vf1 (&-> lg dir0 direction quad))
|
|
(.lvf vf2 (&-> lg dir1 direction quad))
|
|
(.lvf vf3 (&-> lg dir2 direction quad))
|
|
(.lvf vf4 (&-> lg dir0 extra quad))
|
|
(.lvf vf5 (&-> lg dir1 extra quad))
|
|
(.lvf vf6 (&-> lg dir2 extra quad))
|
|
(.mul.x.vf acc vf1 vf4)
|
|
(.add.mul.x.vf acc vf2 vf5 acc)
|
|
(.add.mul.x.vf vf1 vf3 vf6 acc)
|
|
(.svf (&-> target-shadow-dir quad) vf1)
|
|
(vector-normalize! target-shadow-dir -1.0)
|
|
(when (< (- (-> target-shadow-dir y)) 0.9063)
|
|
(let* ((f0-16 0.4226)
|
|
(f1-6 (-> target-shadow-dir x))
|
|
(f1-8 (* f1-6 f1-6))
|
|
(f2-0 (-> target-shadow-dir z))
|
|
(f0-17 (/ f0-16 (sqrtf (+ f1-8 (* f2-0 f2-0)))))
|
|
)
|
|
(set! (-> target-shadow-dir x) (* (-> target-shadow-dir x) f0-17))
|
|
(set! (-> target-shadow-dir y) -0.9063)
|
|
(set! (-> target-shadow-dir z) (* (-> target-shadow-dir z) f0-17))
|
|
)
|
|
)
|
|
(when (not (paused?))
|
|
(vector-seek! current-shadow-dir target-shadow-dir (* 0.2 (seconds-per-frame)))
|
|
(vector-normalize! current-shadow-dir 1.0)
|
|
)
|
|
(set! (-> dc shadow-ctrl settings shadow-dir w) shadow-dir-w)
|
|
)
|
|
)
|
|
;; og:preserve-this
|
|
(#when PC_PORT (add-debug-lights *display-lights* (bucket-id debug2) (-> lg lights) (-> dc origin)))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; apply mult and emissive lighting.
|
|
(.lvf vf28 (&-> dc color-mult quad))
|
|
(.lvf vf29 (&-> dc color-emissive quad))
|
|
(.lvf vf2 (&-> fg-lights color 0 quad))
|
|
(.lvf vf3 (&-> fg-lights color 1 quad))
|
|
(.lvf vf4 (&-> fg-lights color 2 quad))
|
|
(.lvf vf5 (&-> fg-lights ambient quad))
|
|
(.mul.vf vf5 vf5 vf28)
|
|
(.mul.vf vf2 vf2 vf28)
|
|
(.mul.vf vf3 vf3 vf28)
|
|
(.mul.vf vf4 vf4 vf28)
|
|
(.add.vf vf5 vf5 vf29)
|
|
(.svf (&-> fg-lights color 0 quad) vf2)
|
|
(.svf (&-> fg-lights color 1 quad) vf3)
|
|
(.svf (&-> fg-lights color 2 quad) vf4)
|
|
(.svf (&-> fg-lights ambient quad) vf5)
|
|
|
|
;; load math camera registers for distance calcs
|
|
(let ((at-0 *math-camera*))
|
|
(.lvf vf16 (&-> at-0 plane 0 quad))
|
|
(.lvf vf17 (&-> at-0 plane 1 quad))
|
|
(.lvf vf18 (&-> at-0 plane 2 quad))
|
|
(.lvf vf19 (&-> at-0 plane 3 quad))
|
|
(.lvf vf20 (&-> at-0 guard-plane 0 quad))
|
|
(.lvf vf21 (&-> at-0 guard-plane 1 quad))
|
|
(.lvf vf22 (&-> at-0 guard-plane 2 quad))
|
|
(.lvf vf23 (&-> at-0 guard-plane 3 quad))
|
|
(.lvf vf24 (&-> at-0 camera-rot quad 0))
|
|
(.lvf vf25 (&-> at-0 camera-rot quad 1))
|
|
(.lvf vf26 (&-> at-0 camera-rot quad 2))
|
|
(.lvf vf27 (&-> at-0 camera-rot trans quad))
|
|
)
|
|
|
|
;; og:preserve-this scratchpad
|
|
;; do distance math
|
|
(let ((fg-dist (-> (scratchpad-object foreground-work) distance)))
|
|
(.lvf vf15 (&-> fg-bounds quad))
|
|
(.mul.w.vf acc vf27 vf0)
|
|
(.add.mul.x.vf acc vf24 vf15 acc)
|
|
(.add.mul.y.vf acc vf25 vf15 acc)
|
|
(.add.mul.z.vf vf15 vf26 vf15 acc :mask #b111)
|
|
(.mul.vf vf28 vf15 vf15)
|
|
(.max.w.vf vf29 vf0 vf0)
|
|
(.add.y.vf acc vf28 vf28)
|
|
(.add.mul.z.vf vf28 vf29 vf28 acc :mask #b1)
|
|
(.sqrt.vf Q vf28 :ftf #b0)
|
|
(.sub.w.vf vf28 vf0 vf15 :mask #b1000)
|
|
(.wait.vf)
|
|
(.add.vf vf15 vf28 Q :mask #b1000)
|
|
(.svf (&-> fg-dist quad) vf15)
|
|
|
|
;; pick lods
|
|
(when (< 0.0 (+ (-> fg-dist z) (-> dc bounds w)))
|
|
(let ((lod-idx 0))
|
|
(let ((dist-w (-> fg-dist w)))
|
|
(set! (-> dc distance) dist-w)
|
|
(when (nonzero? (-> dc lod-set max-lod))
|
|
(cond
|
|
((>= (-> dc force-lod) 0)
|
|
(set! lod-idx (-> dc force-lod))
|
|
;; og:preserve-this force high lods
|
|
(if (#if (not PC_PORT)
|
|
(< (-> dc lod-set lod (-> dc lod-set max-lod) dist) dist-w)
|
|
(and (-> *pc-settings* ps2-lod-dist?) (< (-> dc lod-set lod (-> dc lod-set max-lod) dist) dist-w)))
|
|
(return #f)
|
|
)
|
|
)
|
|
(else
|
|
(while (and (< lod-idx (the-as int (-> dc lod-set max-lod))) (< (-> dc lod-set lod lod-idx dist) dist-w))
|
|
(+! lod-idx 1)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
;; og:preserve-this lod hacks!
|
|
(with-pc
|
|
(when (not (-> *pc-settings* ps2-lod-dist?))
|
|
(set! lod-idx (minmax (-> *pc-settings* lod-force-actor) 0 (-> dc lod-set max-lod)))
|
|
(when (> (-> dc force-lod) -1)
|
|
(set! lod-idx (-> dc force-lod))
|
|
)
|
|
)
|
|
)
|
|
(if (#if (not PC_PORT)
|
|
(and (< (-> dc lod-set lod lod-idx dist) dist-w) (< (-> dc force-lod) 0))
|
|
(and (-> *pc-settings* ps2-lod-dist?) (< (-> dc lod-set lod lod-idx dist) dist-w) (< (-> dc force-lod) 0))
|
|
)
|
|
(return #f)
|
|
)
|
|
|
|
;; predict texture use and set masks.
|
|
(let ((src-lev (-> *level* level (-> dc level-index)))
|
|
(corrected-dist (* dist-w (-> *math-camera* fov-correction-factor)))
|
|
(tex-use (-> dc mgeo header texture-usage-group))
|
|
)
|
|
(dotimes (use-fg-idx 7)
|
|
(let ((use-idx (+ use-fg-idx 11)))
|
|
(if (not (logtest? (-> dc status) (draw-control-status no-closest-distance)))
|
|
(set! (-> src-lev closest-object-array use-idx) (fmin (-> src-lev closest-object-array use-idx) dist-w))
|
|
)
|
|
)
|
|
(let ((tex-lod (cond
|
|
((>= corrected-dist (-> tex-use data use-fg-idx data 0 dist))
|
|
0
|
|
)
|
|
((>= corrected-dist (-> tex-use data use-fg-idx data 1 dist))
|
|
1
|
|
)
|
|
(else
|
|
2
|
|
)
|
|
)
|
|
)
|
|
(a2-23 (+ use-fg-idx 11))
|
|
)
|
|
(let ((a3-10 (-> src-lev texture-mask a2-23 mask quad))
|
|
(t0-3 (-> (the-as (pointer uint128) (+ (the-as uint tex-use) (* 48 use-fg-idx) (* tex-lod 16))) 0))
|
|
)
|
|
(.por a3-11 a3-10 t0-3)
|
|
)
|
|
(set! (-> src-lev texture-mask a2-23 mask quad) a3-11)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; see if we need special scissor mode.
|
|
(if (or (guard-band-cull fg-bounds) (< dist-w (* 1.2 (-> *math-camera* d))))
|
|
(logior! (-> dc status) (draw-control-status close-to-screen))
|
|
(logclear! (-> dc status) (draw-control-status close-to-screen))
|
|
)
|
|
|
|
;; if we got this far, we're on-screen.
|
|
(logior! (-> dc status) (draw-control-status on-screen))
|
|
(if (logtest? (-> dc status) (draw-control-status no-draw-bounds no-draw-bounds2))
|
|
(return #f)
|
|
)
|
|
(set! (-> pp clock) (-> sv-16 clock))
|
|
|
|
;; draw!
|
|
;; og:preserve-this PC port note: we ALWAYS disable the envmap hack when a process-drawable has warp effect enabled
|
|
(when (or (= lod-idx (-> dc cur-lod)) (logtest? (-> dc status) (draw-control-status lod-set)))
|
|
(protect ((-> *pc-settings* force-envmap?))
|
|
(when (not (movie?))
|
|
(dotimes (eff-i (-> dc mgeo header effect-count))
|
|
(if (and (zero? (logand (ash 1 eff-i) (-> dc effect-mask)))
|
|
(logtest? (effect-bits cross-fade) (-> dc mgeo effect eff-i effect-bits)))
|
|
(false! (-> *pc-settings* force-envmap?)))))
|
|
(foreground-draw dc dma-buf dist-w)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; og:preserve-this trick to do joint math twice if we're changing lods.
|
|
(when (and (< lod-idx (-> dc cur-lod)) (logtest? (-> dc status) (draw-control-status math-skel)))
|
|
;; og:preserve-this added this check for PC port to prevent memory corruption
|
|
(if (< (-> *matrix-engine* length) (-> *matrix-engine* allocated-length))
|
|
(let ((v1-159 *matrix-engine*))
|
|
(set! (-> v1-159 (-> v1-159 length)) (process->handle sv-16))
|
|
(+! (-> v1-159 length) 1)
|
|
)
|
|
)
|
|
)
|
|
(lod-set! dc lod-idx)
|
|
)
|
|
(logior! (-> dc status) (draw-control-status lod-set))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
;; og:preserve-this
|
|
(read! (-> *perf-stats* data (perf-stat-bucket foreground)))
|
|
(none)
|
|
)
|
|
)
|
|
)
|
|
|
|
(define *hud-lights* (new 'global 'vu-lights))
|
|
(set-vector! (-> *hud-lights* direction 0) 1.0 0.0 0.0 1.0)
|
|
(set-vector! (-> *hud-lights* direction 1) 0.0 1.0 0.0 1.0)
|
|
(set-vector! (-> *hud-lights* direction 2) 0.0 0.0 1.0 1.0)
|
|
(set-vector! (-> *hud-lights* color 0) 0.0 0.0 0.0 1.0)
|
|
(set-vector! (-> *hud-lights* color 1) 0.0 0.0 0.0 1.0)
|
|
(set-vector! (-> *hud-lights* color 2) 0.5 0.5 0.5 1.0)
|
|
(set-vector! (-> *hud-lights* ambient) 0.5 0.5 0.5 1.0)
|
|
|
|
(defun dma-add-process-drawable-hud ((arg0 process-drawable) (arg1 draw-control) (arg2 float) (arg3 dma-buffer))
|
|
"Generate DMA for a foreground-hud process-drawable."
|
|
(local-vars (a3-4 uint128))
|
|
|
|
;; clear old value of on-screen
|
|
(logclear! (-> arg1 status) (draw-control-status on-screen))
|
|
|
|
;; only draw if we're enabled
|
|
(when (not (logtest? (-> arg1 status) (draw-control-status no-draw no-draw-temp uninited)))
|
|
;; og:preserve-this scratchpad
|
|
;; copy *hud-lights* to the scratchpad lights.
|
|
(let ((v1-6 (-> (scratchpad-object foreground-work) lights))
|
|
(a0-3 *hud-lights*)
|
|
)
|
|
(set! (-> v1-6 direction 0 quad) (-> a0-3 direction 0 quad))
|
|
(set! (-> v1-6 direction 1 quad) (-> a0-3 direction 1 quad))
|
|
(set! (-> v1-6 direction 2 quad) (-> a0-3 direction 2 quad))
|
|
(set! (-> v1-6 color 0 quad) (-> a0-3 color 0 quad))
|
|
(set! (-> v1-6 color 1 quad) (-> a0-3 color 1 quad))
|
|
(set! (-> v1-6 color 2 quad) (-> a0-3 color 2 quad))
|
|
(set! (-> v1-6 ambient quad) (-> a0-3 ambient quad))
|
|
)
|
|
|
|
;; force lod0 and on-screen
|
|
(lod-set! arg1 0)
|
|
(logior! (-> arg1 status) (draw-control-status on-screen))
|
|
|
|
;; send to foreground.
|
|
(foreground-draw-hud arg1 arg3 arg2)
|
|
|
|
;; update textures.
|
|
(let ((v1-12 (-> *level* default-level))
|
|
(a0-8 (-> arg1 mgeo header texture-usage-group))
|
|
)
|
|
(dotimes (a1-9 7)
|
|
(let ((a2-1 (+ a1-9 11)))
|
|
(let ((a3-3 (-> v1-12 texture-mask a2-1 mask quad))
|
|
(t0-3 (-> a0-8 data a1-9 data 2 mask quad))
|
|
)
|
|
(.por a3-4 a3-3 t0-3)
|
|
)
|
|
(set! (-> v1-12 texture-mask a2-1 mask quad) a3-4)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun add-process-drawable ((arg0 process-drawable) (arg1 draw-control) (arg2 symbol) (arg3 dma-buffer))
|
|
"Call the dma-add-func callback on a draw-control to draw it."
|
|
((-> arg1 dma-add-func) arg0 arg1 arg2 arg3)
|
|
(none)
|
|
)
|
|
|
|
(defun foreground-engine-execute ((arg0 engine) (arg1 display-frame))
|
|
"Run the foreground drawing engine."
|
|
(when (> (length arg0) 0)
|
|
(let ((gp-0 (-> *display* frames (-> *display* on-screen) global-buf base)))
|
|
(with-profiler 'foreground *profile-foreground-color*
|
|
(let ((s4-1 (-> arg1 global-buf)))
|
|
;; og:preserve-this
|
|
; (let ((v1-29 (-> s4-1 base)))
|
|
; (.sync.l)
|
|
; (.cache dxwbin v1-29 0)
|
|
; (.sync.l)
|
|
; (.cache dxwbin v1-29 1)
|
|
; )
|
|
; (.sync.l)
|
|
; 0
|
|
|
|
;; prepare for foreground functions
|
|
(foreground-init)
|
|
|
|
;; add dma for each foreground object
|
|
(execute-connections arg0 s4-1)
|
|
|
|
;; stitch together buckets/finalize renderers.
|
|
(foreground-wrapup)
|
|
)
|
|
)
|
|
(let ((v1-49 *dma-mem-usage*))
|
|
(when (nonzero? v1-49)
|
|
(set! (-> v1-49 length) (max 36 (-> v1-49 length)))
|
|
(set! (-> v1-49 data 35 name) "pris-fragment")
|
|
(+! (-> v1-49 data 35 count) 1)
|
|
(+! (-> v1-49 data 35 used)
|
|
(&- (-> *display* frames (-> *display* on-screen) global-buf base) (the-as uint gp-0))
|
|
)
|
|
(set! (-> v1-49 data 35 total) (-> v1-49 data 35 used))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun-debug main-debug-hook ()
|
|
"Execute the debug engine, collision renderer, and draw-instance-info."
|
|
(when (not (or (= *master-mode* 'menu) (= *master-mode* 'progress)))
|
|
(let ((a0-3 *col-rend*))
|
|
(if (-> a0-3 draw?)
|
|
(col-rend-method-9 a0-3)
|
|
)
|
|
)
|
|
(execute-connections *debug-engine* #f)
|
|
(draw-instance-info *stdcon*)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(define *debug-hook* (cons main-debug-hook '()))
|
|
|
|
(define *add-sphere* #f)
|
|
|
|
(define *generic-effect-mode* 0)
|
|
|
|
(defun foreground-initialize-engines ()
|
|
"Called before dispatching foreground engine to set up."
|
|
|
|
;; initialize shadow lists.
|
|
(let ((v1-0 *shadow-globals*))
|
|
(dotimes (a0-0 2)
|
|
(let ((a1-2 (-> v1-0 bucket a0-0)))
|
|
(set! (-> a1-2 first) (the-as pointer 0))
|
|
(set! (-> a1-2 next) (the-as pointer 0))
|
|
(set! (-> a1-2 shadow-color) (if (zero? a0-0)
|
|
(new 'static 'rgba :r #xf0 :g #xf0 :b #xf0 :a #x80)
|
|
(the-as rgba (-> *setting-control* user-current spotlight-color))
|
|
)
|
|
)
|
|
(set! (-> a1-2 constants) (the-as shadow-vu1-constants 0))
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defun foreground-execute-cpu-vu0-engines ()
|
|
"Run the CPU/VU0 part of foreground. Happens after the foreground-engine-execute is done (first pass dma done).
|
|
Generates bone matrices for VU1 renderers and does leftover stuff that depends on bones."
|
|
(let ((gp-0 (-> *display* frames (-> *display* on-screen) global-buf)))
|
|
;; do the bones
|
|
(bones-init gp-0)
|
|
(bones-mtx-calc-execute)
|
|
;; generic-merc/shadow have VU0/CPU parts that need bones, run them here.
|
|
(generic-merc-execute-all gp-0)
|
|
(shadow-execute-all gp-0)
|
|
)
|
|
(lightning-draw-all)
|
|
(none)
|
|
)
|
|
|
|
|
|
(defun real-main-draw-hook ()
|
|
"Main function to run the drawable system, called from the display-loop in main.gc"
|
|
(local-vars (a0-96 int) (a0-98 int))
|
|
(with-pp
|
|
(when *slow-frame-rate*
|
|
;; og:preserve-this
|
|
(dotimes (v1-2 128000000) ;; was 12800000
|
|
(nop!)
|
|
(nop!)
|
|
(nop!)
|
|
(nop!)
|
|
(nop!)
|
|
(nop!)
|
|
)
|
|
)
|
|
"Function to be executed to set up for engine dma"
|
|
|
|
;; update render/texture upload masks
|
|
(set! (-> *display* vu1-enable-user) (-> *display* vu1-enable-user-menu))
|
|
(set! (-> *texture-pool* texture-enable-user) (-> *texture-pool* texture-enable-user-menu))
|
|
|
|
;; display memory stats
|
|
(when *debug-segment*
|
|
(when (and *stats-memory* (!= *master-mode* 'menu))
|
|
(cond
|
|
(*stats-memory-short*
|
|
(dotimes (gp-0 (-> *level* length))
|
|
(let ((s5-0 (-> *level* level gp-0)))
|
|
(if (= (-> s5-0 status) 'active)
|
|
(print-mem-usage (compute-memory-usage! s5-0 #f) s5-0 *stdcon*)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(else
|
|
(let ((gp-1 (-> *level* level *stats-memory-level-index*)))
|
|
(if (and gp-1 (= (-> gp-1 status) 'active))
|
|
(print-mem-usage (compute-memory-usage! gp-1 #f) gp-1 *stdcon*)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(reset! *dma-mem-usage*)
|
|
)
|
|
|
|
;; set up foreground buckets
|
|
(foreground-initialize-engines)
|
|
|
|
;; update time of day and wind effects.
|
|
(let ((gp-2 (-> pp clock)))
|
|
(if (= (-> *time-of-day-context* mode) (time-of-day-palette-id unk3))
|
|
(set! (-> pp clock) (-> *display* bg-clock))
|
|
(set! (-> pp clock) (-> *display* real-clock))
|
|
)
|
|
;; og:preserve-this
|
|
; (if (not (paused?))
|
|
; (update-wind *wind-work* *wind-scales*)
|
|
; )
|
|
(update-time-of-day *time-of-day-context*)
|
|
(set! (-> pp clock) gp-2)
|
|
)
|
|
|
|
|
|
;; draw the sky
|
|
(with-profiler 'sky *profile-sky-color*
|
|
(if (-> *sky-work* draw-vortex)
|
|
(draw-vortex)
|
|
(draw *sky-work*)
|
|
)
|
|
(flush-cache 0)
|
|
)
|
|
|
|
;; draw the ocean
|
|
(let ((gp-5 (-> pp clock)))
|
|
(if (= (-> *time-of-day-context* mode) (time-of-day-palette-id unk3))
|
|
(set! (-> pp clock) (-> *display* bg-clock))
|
|
(set! (-> pp clock) (-> *display* real-clock))
|
|
)
|
|
(with-profiler 'ocean *profile-ocean-color*
|
|
(draw! *ocean*)
|
|
(when *ocean-map*
|
|
(update-map *ocean*)
|
|
)
|
|
)
|
|
(set! (-> pp clock) gp-5)
|
|
)
|
|
|
|
;; run the foreground system
|
|
(foreground-engine-execute *foreground-draw-engine* (-> *display* frames (-> *display* on-screen)))
|
|
(let ((gp-6 (-> pp clock)))
|
|
(if (= (-> *time-of-day-context* mode) (time-of-day-palette-id unk3))
|
|
(set! (-> pp clock) (-> *display* bg-clock))
|
|
(set! (-> pp clock) (-> *display* real-clock))
|
|
)
|
|
(foreground-execute-cpu-vu0-engines)
|
|
(set! (-> pp clock) gp-6)
|
|
)
|
|
;; og:preserve-this
|
|
;; ??
|
|
; (when *add-sphere*
|
|
; )
|
|
|
|
;; run the sprite/particle system.
|
|
(if (not (paused?))
|
|
(execute-part-engine)
|
|
)
|
|
(if (logtest? (vu1-renderer-mask sprite) (-> *display* vu1-enable-user))
|
|
(sprite-draw *display*)
|
|
)
|
|
|
|
;; debug draw collision stuff before processing it.
|
|
(when *debug-segment*
|
|
(debug-draw-actors *level* *display-actor-marks*)
|
|
(collide-shape-draw-debug-marks)
|
|
)
|
|
|
|
;; after debug drawing, send events to actors
|
|
(send-events-for-touching-shapes *touching-list*)
|
|
(free-nodes *touching-list*)
|
|
(prepare *collide-rider-pool*)
|
|
(send-all! *event-queue*)
|
|
|
|
;; spawn/update actors
|
|
(with-profiler 'update-actors *profile-update-actors-color*
|
|
(actors-update *level*)
|
|
)
|
|
|
|
(with-profiler 'nav *profile-nav-color*
|
|
(update-nav-meshes-method *level*)
|
|
)
|
|
|
|
(with-profiler 'background *profile-background-color*
|
|
;; Run the background renderers!
|
|
|
|
;; first, reset the background-work
|
|
(init-background)
|
|
|
|
;; next, collect all levels that are registered with the engine
|
|
;; this will call the drawable system's draw method on the levels which adds all
|
|
;; trees known to the background system to *background-work*.
|
|
(execute-connections *background-draw-engine* (-> *display* frames (-> *display* on-screen)))
|
|
|
|
;; execute all background drawing
|
|
(reset! (-> *perf-stats* data (perf-stat-bucket background)))
|
|
(finish-background)
|
|
(read! (-> *perf-stats* data (perf-stat-bucket background)))
|
|
|
|
;; update VU stats for background draw.
|
|
(update-wait-stats (-> *perf-stats* data (perf-stat-bucket background))
|
|
(-> *background-work* wait-to-vu0)
|
|
(the-as uint 0)
|
|
(the-as uint 0)
|
|
)
|
|
)
|
|
|
|
(end-perf-stat-collection)
|
|
|
|
;; background stats
|
|
(when (and (!= *master-mode* 'menu) *stats-poly*)
|
|
(dotimes (gp-13 (-> *level* length))
|
|
(let ((v1-307 (-> *level* level gp-13)))
|
|
(if (= (-> v1-307 status) 'active)
|
|
(collect-stats (-> v1-307 bsp))
|
|
)
|
|
)
|
|
)
|
|
(print-terrain-stats)
|
|
)
|
|
|
|
|
|
;; perf and collide stats
|
|
(when (not (paused?))
|
|
(if (and (!= *master-mode* 'menu) *stats-perf*)
|
|
(print-perf-stats)
|
|
)
|
|
(if (and (!= *master-mode* 'menu) *stats-collide*)
|
|
(print-collide-stats)
|
|
)
|
|
(when (and (!= *master-mode* 'menu) *stats-joint*)
|
|
(format *stdcon* "joint calls: ~D~%" (-> *new-joint-decompressor-stats* num-calls))
|
|
(format *stdcon* "joint anims: ~D~%" (-> *new-joint-decompressor-stats* num-anims))
|
|
(format *stdcon* "joint joints: ~D~%" (-> *new-joint-decompressor-stats* num-joints))
|
|
(format *stdcon* "joint time us: ~D~%" (-> *new-joint-decompressor-stats* total-time))
|
|
|
|
(reset! *new-joint-decompressor-stats*)
|
|
)
|
|
)
|
|
(start-perf-stat-collection)
|
|
|
|
0
|
|
(none)
|
|
)
|
|
)
|
|
|
|
(defun main-draw-hook ()
|
|
(real-main-draw-hook)
|
|
(none)
|
|
)
|
|
|
|
(define *draw-hook* main-draw-hook)
|
|
|
|
(defun default-init-buffer ((arg0 bucket-id) (arg1 gs-zbuf) (arg2 gs-test))
|
|
(let ((v1-6 (-> *display* frames (-> *display* on-screen) bucket-group arg0)))
|
|
(when (!= v1-6 (-> v1-6 last))
|
|
(let* ((a0-8 (-> *display* frames (-> *display* on-screen) global-buf))
|
|
(a3-3 (-> a0-8 base))
|
|
)
|
|
(dma-buffer-add-gs-set-flusha a0-8
|
|
(zbuf-1 arg1)
|
|
(test-1 arg2)
|
|
(alpha-1 (new 'static 'gs-alpha :b #x1 :d #x1))
|
|
(pabe 0)
|
|
(clamp-1 (new 'static 'gs-clamp :wms (gs-tex-wrap-mode clamp) :wmt (gs-tex-wrap-mode clamp)))
|
|
(tex1-1 (new 'static 'gs-tex1 :mmag #x1 :mmin #x1))
|
|
(texa (new 'static 'gs-texa :ta1 #x80))
|
|
(texclut (new 'static 'gs-texclut :cbw #x4))
|
|
(fogcol *fog-color*)
|
|
)
|
|
(let ((a1-18 (the-as object (-> a0-8 base))))
|
|
(set! (-> (the-as dma-packet a1-18) dma) (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> v1-6 next)))
|
|
(set! (-> (the-as dma-packet a1-18) vif0) (new 'static 'vif-tag))
|
|
(set! (-> (the-as dma-packet a1-18) vif1) (new 'static 'vif-tag))
|
|
(set! (-> a0-8 base) (&+ (the-as pointer a1-18) 16))
|
|
)
|
|
(set! (-> v1-6 next) (the-as uint a3-3))
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defun default-end-buffer ((arg0 bucket-id) (arg1 gs-zbuf) (arg2 gs-test))
|
|
(let ((v1-6 (-> *display* frames (-> *display* on-screen) bucket-group arg0)))
|
|
(when (!= v1-6 (-> v1-6 last))
|
|
(let* ((a3-2 (-> *display* frames (-> *display* on-screen) global-buf))
|
|
(a0-8 (-> a3-2 base))
|
|
)
|
|
(dma-buffer-add-gs-set-flusha a3-2
|
|
(zbuf-1 arg1)
|
|
(test-1 arg2)
|
|
(alpha-1 (new 'static 'gs-alpha :b #x1 :d #x1))
|
|
(pabe 0)
|
|
(clamp-1 (new 'static 'gs-clamp :wms (gs-tex-wrap-mode clamp) :wmt (gs-tex-wrap-mode clamp)))
|
|
(tex1-1 (new 'static 'gs-tex1 :mmag #x1 :mmin #x1))
|
|
(texa (new 'static 'gs-texa :ta1 #x80))
|
|
(texclut (new 'static 'gs-texclut :cbw #x4))
|
|
(fogcol *fog-color*)
|
|
)
|
|
(let ((t0-4 (-> a3-2 base)))
|
|
(let ((a1-18 (the-as object (-> a3-2 base))))
|
|
(set! (-> (the-as dma-packet a1-18) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
|
|
(set! (-> (the-as dma-packet a1-18) vif0) (new 'static 'vif-tag))
|
|
(set! (-> (the-as dma-packet a1-18) vif1) (new 'static 'vif-tag))
|
|
(set! (-> a3-2 base) (&+ (the-as pointer a1-18) 16))
|
|
)
|
|
(set! (-> (the-as dma-bucket (-> v1-6 last)) next) (the-as uint a0-8))
|
|
(set! (-> v1-6 last) (the-as (pointer dma-tag) t0-4))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defun-debug screen-shot-scale ((arg0 int) (arg1 string))
|
|
(set! (-> *screen-shot-work* size) arg0)
|
|
(set! (-> *screen-shot-work* name) arg1)
|
|
(set! *display-profile* #f)
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun-debug screen-shot ()
|
|
(screen-shot-scale 1 "image")
|
|
0
|
|
(none)
|
|
)
|
|
|
|
(defun display-frame-start ((arg0 display) (arg1 int) (arg2 float))
|
|
"Advance clocks, poll pads/mouse, set up buckets."
|
|
;; og:preserve-this workaround for PS2 HW bug
|
|
; (set! (-> (the-as vif-bank #x10003c00) err me0) 1)
|
|
;; tick frame clocks
|
|
(set-time-ratios *display* 1.0)
|
|
(tick! (-> arg0 frame-clock))
|
|
(tick! (-> arg0 real-frame-clock))
|
|
|
|
;; tick other clocks
|
|
(set-time-ratios *display* arg2)
|
|
(tick! (-> arg0 session-clock))
|
|
(tick! (-> arg0 game-clock))
|
|
(tick! (-> arg0 total-game-clock))
|
|
(tick! (-> arg0 base-clock))
|
|
(tick! (-> arg0 real-clock))
|
|
(tick! (-> arg0 target-clock))
|
|
(tick! (-> arg0 camera-clock))
|
|
(tick! (-> arg0 entity-clock))
|
|
(tick! (-> arg0 user0-clock))
|
|
(tick! (-> arg0 bg-clock))
|
|
(set! (-> arg0 bg-clock frame-counter) (the-as time-frame (mod (-> arg0 bg-clock frame-counter) #x69780)))
|
|
(tick! (-> arg0 part-clock))
|
|
(when (and (nonzero? *screen-shot-work*) (!= (-> *screen-shot-work* count) -1))
|
|
(let ((v1-43 (-> *screen-shot-work* size)))
|
|
(if (!= (-> *screen-shot-work* count) (* v1-43 v1-43))
|
|
(store-image *screen-shot-work*)
|
|
)
|
|
)
|
|
(+! (-> *screen-shot-work* count) -1)
|
|
(if (= (-> *screen-shot-work* count) -1)
|
|
(set! (-> *screen-shot-work* size) -1)
|
|
)
|
|
)
|
|
|
|
(let ((s5-1 (-> arg0 frames arg1)))
|
|
(if *sync-dma*
|
|
(sync-path 0 0)
|
|
)
|
|
|
|
(let ((v1-57 (-> s5-1 global-buf)))
|
|
(set! (-> v1-57 base) (-> v1-57 data))
|
|
(set! (-> v1-57 end) (&-> v1-57 data-buffer (-> v1-57 allocated-length)))
|
|
)
|
|
(let ((v1-58 (-> s5-1 global-buf)))
|
|
(&+! (-> v1-58 end) -65536)
|
|
)
|
|
(when *debug-segment*
|
|
(let ((v1-61 (-> s5-1 debug-buf)))
|
|
(set! (-> v1-61 base) (-> v1-61 data))
|
|
(set! (-> v1-61 end) (&-> v1-61 data-buffer (-> v1-61 allocated-length)))
|
|
)
|
|
)
|
|
(let ((v1-62 (-> s5-1 calc-buf)))
|
|
(set! (-> v1-62 base) (-> v1-62 data))
|
|
(set! (-> v1-62 end) (&-> v1-62 data-buffer (-> v1-62 allocated-length)))
|
|
)
|
|
(*pre-draw-hook* (-> s5-1 calc-buf))
|
|
(when (not (paused?))
|
|
(clear *stdcon1*)
|
|
(debug-reset-buffers)
|
|
(clear! *simple-sprite-system*)
|
|
)
|
|
;; og:preserve-this
|
|
(set! (-> s5-1 bucket-group) (dma-buffer-add-buckets (-> s5-1 calc-buf) (enum-length bucket-id)))
|
|
)
|
|
|
|
(service-cpads)
|
|
(service-mouse)
|
|
(execute-connections *pad-engine* #f)
|
|
(none)
|
|
)
|
|
|
|
;; og:preserve-this pc port function
|
|
(defun pc-maybe-vsync ()
|
|
"PC Port implementation of the block of code in display-sync that computes frame-time-ratio and maybe vsyncs."
|
|
;; for now, it's very simple.
|
|
|
|
;; I think the right logic in the future is to always vsync here, but return a more accurate dog ratio.
|
|
|
|
(syncv 0) ;; sync always!
|
|
;(set! *ticks-per-frame* 9765) ;; hack!
|
|
1.0 ;; and report that we run at full speed.
|
|
)
|
|
|
|
(defun display-sync ((arg0 display))
|
|
"Determine frame timing, possibly vsync, and kick off next DMA.
|
|
This also calls sync-path, but this appears redundant because the display loop did this already."
|
|
|
|
;; The "rendered" frame is the one that has had its DMA processed and is completed and in VRAM.
|
|
;; The "drawn" frame is the one that has DMA ready, but not sent.
|
|
;; The "vblank period" is how long in between actual frames on the TV. This is 16.67 ms for NTSC.
|
|
|
|
;; This function will kick off the drawn frame's DMA, possibly vsync, and update timing stuff.
|
|
;; Currently, I believe the _start_ of the drawn frame's DMA will do the "blit" to move
|
|
;; the "rendered" frame's image from the drawing buffer to the frame buffer, but it's possible I have this backward.
|
|
|
|
;; apparently useless sync
|
|
;; everything in here happens after DMA is done.
|
|
(sync-path 0 0)
|
|
|
|
(let* ((just-rendered-frame (-> arg0 last-screen))
|
|
(current-time (shl (timer1-time) 48))
|
|
(just-rendered-frame-start-time (shl (-> arg0 frames just-rendered-frame start-time) 48))
|
|
(prev-vblank-time-1 (shl (-> arg0 vblank-start-time 0) 48))
|
|
(prev-vblank-time-2 (shl (-> arg0 vblank-start-time 1) 48))
|
|
)
|
|
|
|
;; measure the actual *ticks-per-frame* by comparing the timings of the last two vblanks.
|
|
;; I think this should be constant for PAL/NTSC, the vblank interrupt happens no matter what and is based
|
|
;; on the TV timing stuff.
|
|
;(set! *ticks-per-frame* (sar (- prev-vblank-time-2 prev-vblank-time-1) 48))
|
|
(set! *ticks-per-frame* 9765) ;; HACK
|
|
|
|
(let* ((ticks-per-frame-f (the float *ticks-per-frame*))
|
|
;; how long we spent on this frame (measured from the dma-send until now)
|
|
(frame-duration (the float (sar (- current-time (the-as uint just-rendered-frame-start-time)) 48)))
|
|
;; how long we spent on this frame, as a fraction of the time between vblanks (the actual TV framerate)
|
|
(frame-time-ratio (/ frame-duration ticks-per-frame-f))
|
|
)
|
|
(/ (the float (sar (- current-time (the-as uint prev-vblank-time-2)) 48)) ticks-per-frame-f)
|
|
|
|
;; how close we are to the next vblank (should be between 0 and 1)
|
|
(let ((vysnc-progress (/ (the float (sar (- current-time (the-as uint prev-vblank-time-2)) 48)) ticks-per-frame-f))
|
|
;; the "lag ratio" of the frame that was just drawn.
|
|
(last-dog (fmax 1.0 (fmin 4.0 (-> *display* dog-ratio))))
|
|
)
|
|
;; store the amount of ticks that the frame took.
|
|
;; og:preserve-this
|
|
;; PC PORT NOTE : the originaly game reads this field in places to check if frames are taking too long and avoid doing potentially laggy things.
|
|
;; those numbers are hardcoded for 60fps, they would be a pain to adjust, and the effects in the pc port are negligible.
|
|
;; so, we just pretend frames rendered in planck time.
|
|
(set! (-> arg0 frames just-rendered-frame run-time) (#if PC_PORT 0 (the int frame-duration)))
|
|
|
|
;; next, we'll compute this "lag" ratio (will become dog-ratio of the next frame).
|
|
;; higher numbers = game running slower = bigger timesteps
|
|
#|
|
|
(set! frame-time-ratio
|
|
(cond
|
|
((-> arg0 run-half-speed)
|
|
;; running at half speed flag is likely used for debugging? It forces 1 vsync here always.
|
|
(syncv 0)
|
|
|
|
;; do a vysnc if we are both:
|
|
;; - took less than 2 vblank periods to do the last frame (we finished early)
|
|
;; - we have more than 10% of the frame left.
|
|
;; see the comments in the next section for a better explanation of why they do this.
|
|
(if (and (< (/ (the float (sar (- (shl (timer1-time) 48) (the-as uint just-rendered-frame-start-time)) 48))
|
|
ticks-per-frame-f
|
|
)
|
|
2.0
|
|
)
|
|
(< vysnc-progress 0.9)
|
|
)
|
|
(syncv 0)
|
|
)
|
|
|
|
;; report a dog-ratio of exactly 2 always, for this debug mode
|
|
2.0
|
|
)
|
|
(else
|
|
;; not using the half-speed debug option.
|
|
|
|
(cond
|
|
;; case where we're lagging and don't want to vsync usually.
|
|
((< 1.0 frame-time-ratio)
|
|
;; we're lagging! In this case, we usually don't bother with vsync, and there would be tearing.
|
|
|
|
;; not sure about this check, but I guess we never vysnc here if we're on the first 2 frames of the game?
|
|
(when (not (or (zero? prev-vblank-time-1) (zero? prev-vblank-time-2)))
|
|
;; if the force sync counter is set, do a vsync and decrease the counter.
|
|
(when (> (-> arg0 force-sync) 0)
|
|
(syncv 0)
|
|
(+! (-> arg0 force-sync) -1)
|
|
|
|
;; update the frame-time-ratio because we just made this frame longer by vsyncing.
|
|
(let ((v1-23 (shl (timer1-time) 48)))
|
|
(the float (sar (- v1-23 (the-as uint just-rendered-frame-start-time)) 48))
|
|
(set! frame-time-ratio
|
|
(/ (the float (sar (- v1-23 (the-as uint just-rendered-frame-start-time)) 48)) ticks-per-frame-f)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; this "dog-count" thing can be set to 1.0 if the game thinks that its running fast enough for full framerate
|
|
;; but the frame start time is misaligned with the actual TV's vblank.
|
|
;; we are lagging here, so we don't want this, and dog-count should be set to 0
|
|
(set! (-> arg0 dog-count) 0.0)
|
|
)
|
|
|
|
;; case where we're vsyncing.
|
|
;; this should happen if the last-dog is 1.0 (was fast enough), or if the dog-count is set
|
|
;; the dog-count will be set if the frames are fast enough, but not currently aligned.
|
|
((or (= last-dog 1.0) (!= (-> arg0 dog-count) 0.0))
|
|
;; still, only do the sync if we have a lot of time. I guess that vsyncing in other cases is not
|
|
;; needed, and just wastes time. Might as well start on the next frame early!
|
|
(if (< vysnc-progress 0.9)
|
|
(syncv 0)
|
|
)
|
|
;; force no lag
|
|
(set! frame-time-ratio 1.0)
|
|
;; clear dog-count, go back to normal lag/no-lag decisions.
|
|
(set! (-> arg0 dog-count) 0.0)
|
|
)
|
|
(else
|
|
;; weird case: last frame was lag (last-dog != 1.0), but this frame wasn't (frame-time-ratio < 1).
|
|
;; so we're transition from lag to no lag. In this case, we want to get back aligned with vsyncs.
|
|
;; interestingly, we don't vsync immediately, but instead set a flag to vsync on the next frame, if
|
|
;; that frame's time is also non-lag. As a result, we only syncrhonize with vsync if we have 2 non-lag frames
|
|
;; in a row (both of them misaligned.), and we spread the syncrhonization delays between 2 frames
|
|
|
|
|
|
(when (not (or (zero? prev-vblank-time-1) (zero? prev-vblank-time-2))) ;; only if we've done at least 2 syncs..
|
|
|
|
;; here we wait, recomputing frame-time-ratio/vsync-progress until either:
|
|
;; - we're in the first or last third of the frame
|
|
;; - we've waited longer than the previous frame lagged.
|
|
(while (or (< frame-time-ratio last-dog) (and (< 0.333 vysnc-progress) (< vysnc-progress 0.667)))
|
|
(let ((v1-34 (shl (timer1-time) 48)))
|
|
(set! frame-time-ratio
|
|
(/ (the float (sar (- v1-34 (the-as uint just-rendered-frame-start-time)) 48)) ticks-per-frame-f)
|
|
)
|
|
(if (< frame-time-ratio 0.0) ;; ?? timer wraparound issues?
|
|
(set! frame-time-ratio last-dog)
|
|
)
|
|
(set! vysnc-progress
|
|
(/ (the float (sar (- v1-34 (the-as uint (shl (-> arg0 vblank-start-time 1) 48))) 48)) ticks-per-frame-f)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
;; force next frame to vsync if it didn't lag, then we will be back on framerate!
|
|
(set! (-> arg0 dog-count) 1.0)
|
|
)
|
|
)
|
|
frame-time-ratio
|
|
)
|
|
)
|
|
)
|
|
|#
|
|
|
|
;; og:preserve-this added: just skip this for now.
|
|
(set! frame-time-ratio (pc-maybe-vsync))
|
|
|
|
(if (< frame-time-ratio 0.0)
|
|
(set! frame-time-ratio last-dog)
|
|
)
|
|
)
|
|
|
|
;; never allow faster than full-speed frames (the logic above will prevent running faster than TV framerate)
|
|
(let ((next-dog (fmax 1.0 frame-time-ratio))
|
|
(frame-to-render (-> arg0 on-screen))
|
|
)
|
|
|
|
;; measure time again, after waiting/vsyncing.
|
|
(let ((time-after-vsync (timer1-time)))
|
|
(+! (-> arg0 total-run-time)
|
|
(sar (- (shl time-after-vsync 48) (the-as uint just-rendered-frame-start-time)) 48)
|
|
)
|
|
;; and use this as the start time for the frame we're about to render.
|
|
(set! (-> arg0 frames frame-to-render start-time) (the-as int time-after-vsync))
|
|
)
|
|
;; while nothing is drawing, update GS/video/magic stuff.
|
|
;; (set-graphics-mode)
|
|
|
|
;; start DMA
|
|
(let ((next-dma-buf (-> arg0 frames frame-to-render calc-buf)))
|
|
(when (nonzero? (dma-buffer-length next-dma-buf))
|
|
(+! frame-to-render 1)
|
|
(if (< 1 frame-to-render)
|
|
(set! frame-to-render 0)
|
|
)
|
|
;; swap DMA buffers
|
|
(set! (-> arg0 last-screen) (-> arg0 on-screen))
|
|
(set! (-> arg0 on-screen) frame-to-render)
|
|
;; reset VU profiler for upcoming chain
|
|
(when *debug-segment*
|
|
(set! *profile-interrupt-segment* (-> *display* frames (-> *display* last-screen) profile-array data 1))
|
|
(set! (-> *profile-interrupt-segment* depth) 0)
|
|
(set! (-> *profile-interrupt-segment* max-depth) 1)
|
|
)
|
|
;; send the chain!
|
|
(__send-gfx-dma-chain (the-as dma-bank-source #x10009000) (-> next-dma-buf data-buffer))
|
|
)
|
|
)
|
|
|
|
;; screenshot/pause stuff.
|
|
(determine-pause-mode)
|
|
(when (and (nonzero? *screen-shot-work*) (= (-> *screen-shot-work* count) -1) (!= (-> *screen-shot-work* size) -1))
|
|
(let ((v1-77 (-> *screen-shot-work* size)))
|
|
(set! (-> *screen-shot-work* count) (* v1-77 v1-77))
|
|
)
|
|
(set-master-mode 'pause)
|
|
)
|
|
|
|
;; prepare engine for the next frame
|
|
(display-frame-start arg0 frame-to-render next-dog)
|
|
)
|
|
)
|
|
)
|
|
(none)
|
|
)
|
|
|
|
(defun display-frame-finish ((arg0 display))
|
|
"Do final DMA setup after drawing.
|
|
Note that this runs _after_ rendering, while VU1/GS are not doing anything.
|
|
so it's best to keep this code as simple as possible."
|
|
(with-pp
|
|
(let* ((s4-0 (-> arg0 frames (-> arg0 on-screen)))
|
|
(s5-0 (-> s4-0 calc-buf))
|
|
)
|
|
;(-> s4-0 global-buf)
|
|
|
|
;; post-draw buffer setup
|
|
(tfrag-vu1-init-buffers)
|
|
(tie-vu1-init-buffers)
|
|
(merc-vu1-init-buffers)
|
|
;; og:preserve-this
|
|
; (emerc-vu1-init-buffers)
|
|
(generic-vu1-init-buffers)
|
|
|
|
;; sprite texture remaps
|
|
(when (-> *texture-pool* update-sprites-flag)
|
|
(update-sprites *texture-pool*)
|
|
(particle-adgif-cache-flush)
|
|
(remap-all-particles)
|
|
)
|
|
|
|
;; texture uploads while GS is not doing anything.
|
|
(with-profiler 'texture *profile-texture-color*
|
|
(let ((s3-1 (-> pp clock)))
|
|
(if (= (-> *time-of-day-context* mode) (time-of-day-palette-id unk3))
|
|
(set! (-> pp clock) (-> *display* bg-clock))
|
|
(set! (-> pp clock) (-> *display* real-clock))
|
|
)
|
|
(upload-textures *texture-pool*)
|
|
(set! (-> pp clock) s3-1)
|
|
)
|
|
)
|
|
|
|
;; more texture mapping.
|
|
(if (-> *texture-pool* update-flag)
|
|
(update-warp-and-hud *texture-pool*)
|
|
)
|
|
|
|
;; unclear why eyes are here... maybe they rely on textures that were just remapped.
|
|
; (-> *display* frames (-> *display* on-screen) global-buf)
|
|
(update-eyes)
|
|
|
|
|
|
;; end each normal bucket with the standard GS state reset
|
|
(let ((s3-3 6)
|
|
(s2-2 (bucket-id debug2))
|
|
)
|
|
(while (>= s2-2 s3-3)
|
|
(default-end-buffer
|
|
(the-as bucket-id s3-3)
|
|
(new 'static 'gs-zbuf :zbp #x130 :psm (gs-psm ct24))
|
|
(new 'static 'gs-test :zte #x1 :ztst (gs-ztest greater-equal))
|
|
)
|
|
(+! s3-3 1)
|
|
)
|
|
)
|
|
|
|
;; initialize buckets with weird custom settings (disable z buffer)
|
|
(default-init-buffer
|
|
(bucket-id debug-no-zbuf1)
|
|
(new 'static 'gs-zbuf :zbp #x130 :psm (gs-psm ct24) :zmsk #x1)
|
|
(new 'static 'gs-test :zte #x1 :ztst (gs-ztest always))
|
|
)
|
|
(default-init-buffer
|
|
(bucket-id debug-no-zbuf2)
|
|
(new 'static 'gs-zbuf :zbp #x130 :psm (gs-psm ct24) :zmsk #x1)
|
|
(new 'static 'gs-test :zte #x1 :ztst (gs-ztest always))
|
|
)
|
|
(default-init-buffer
|
|
(bucket-id screen-filter)
|
|
(new 'static 'gs-zbuf :zbp #x130 :psm (gs-psm ct24) :zmsk #x1)
|
|
(new 'static 'gs-test :zte #x1 :ztst (gs-ztest always))
|
|
)
|
|
(*post-draw-hook* (-> arg0 frames (-> arg0 on-screen) calc-buf))
|
|
|
|
;; final flushe
|
|
(let* ((v1-70 s5-0)
|
|
(a0-25 (the-as object (-> v1-70 base)))
|
|
)
|
|
(set! (-> (the-as dma-packet a0-25) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
|
|
(set! (-> (the-as dma-packet a0-25) vif0) (new 'static 'vif-tag :imm #x148 :cmd (vif-cmd mark)))
|
|
(set! (-> (the-as dma-packet a0-25) vif1) (new 'static 'vif-tag :cmd (vif-cmd flushe) :irq #x1 :msk #x1))
|
|
(set! (-> v1-70 base) (the-as pointer (&+ (the-as dma-packet a0-25) 16)))
|
|
)
|
|
|
|
;; link all buckets to build the final massive dma list.
|
|
(dma-buffer-patch-buckets (-> s4-0 bucket-group) (enum-length bucket-id))
|
|
|
|
;; append the final END
|
|
(let* ((v1-71 s5-0)
|
|
(a0-28 (the-as object (-> v1-71 base)))
|
|
)
|
|
(set! (-> (the-as dma-packet a0-28) dma) (new 'static 'dma-tag :id (dma-tag-id end)))
|
|
(set! (-> (the-as (pointer int64) a0-28) 1) 0)
|
|
(set! (-> v1-71 base) (&+ (the-as pointer a0-28) 16))
|
|
)
|
|
|
|
;; make sure nothing is in cache
|
|
(flush-cache 0)
|
|
|
|
;; list final dma sizes
|
|
(when (not (paused?))
|
|
(when *stats-buffer*
|
|
(let* ((a0-31 (-> s4-0 global-buf))
|
|
(v1-75 (-> s5-0 base))
|
|
(a2-4 (-> s5-0 data))
|
|
(s4-1 (-> a0-31 base))
|
|
(s5-1 (-> a0-31 data))
|
|
(s3-4 (-> a0-31 end))
|
|
)
|
|
(format *stdcon* "~0kvu1 buf = ~d~%" (&- v1-75 (the-as uint a2-4)))
|
|
(format *stdcon* "~0kglobal buf = ~d~%" (&- s4-1 (the-as uint s5-1)))
|
|
(format *stdcon* "~0kbase = #x~x~%" s4-1)
|
|
(format *stdcon* "~0kend = #x~x~%" s3-4)
|
|
)
|
|
)
|
|
)
|
|
;; now the DMA is ready to send!
|
|
)
|
|
arg0
|
|
)
|
|
)
|
|
|
|
;; definition for function determine-pause-mode
|
|
(defun determine-pause-mode ()
|
|
(when (and (or (not *progress-process*) (can-go-back? (-> *progress-process* 0)))
|
|
(or (!= *master-mode* 'freeze) (and *debug-segment* (cpad-pressed? 0 select start) (cpad-hold? 0 l3)))
|
|
)
|
|
(if (or (cpad-pressed? 0 select start)
|
|
(cond
|
|
((= *master-mode* 'menu)
|
|
(cpad-pressed? 0 r3 r2 triangle circle)
|
|
)
|
|
(*cam-layout*
|
|
#f
|
|
)
|
|
(else
|
|
#f
|
|
)
|
|
)
|
|
(or (and (logtest? (-> *cpad-list* cpads 0 valid) 128)
|
|
(= *master-mode* 'game)
|
|
(>= (-> *display* base-clock frame-counter) (-> *game-info* blackout-time))
|
|
(= (-> *setting-control* user-current bg-a) 0.0)
|
|
(and (= (-> *setting-control* user-current bg-a-force) 0.0)
|
|
(< (seconds 1003) (-> *display* real-clock frame-counter))
|
|
)
|
|
)
|
|
(and (cpad-pressed? 0 r2) (or (= *master-mode* 'pause) (= *master-mode* 'menu)))
|
|
*pause-lock*
|
|
)
|
|
)
|
|
(toggle-pause)
|
|
)
|
|
)
|
|
(if (and *progress-process* (!= *master-mode* 'progress))
|
|
(deactivate-progress)
|
|
)
|
|
0
|
|
)
|
|
|
|
(defun swap-display ((arg0 display))
|
|
(display-frame-finish arg0)
|
|
(display-sync arg0)
|
|
(none)
|
|
)
|