;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/gfx/background/subdivide.gc")
(require "engine/anim/joint.gc")
(require "engine/draw/draw-node-h.gc")
(require "engine/gfx/background/background.gc")
(require "engine/collide/collide-shape-h.gc")
(defmethod login ((obj billboard))
  "Set up the billboard adgif shader"
  (adgif-shader-login (-> obj flat))
  obj)

(defmethod mem-usage ((obj billboard) (arg0 memory-usage-block) (arg1 int))
  "Compute the memory used for the billboard."
  (set! (-> arg0 length) (max 34 (-> arg0 length)))
  (set! (-> arg0 data 33 name) "billboard")
  (+! (-> arg0 data 33 count) 1)
  (let ((v1-6 (asize-of obj))) (+! (-> arg0 data 33 used) v1-6) (+! (-> arg0 data 33 total) (logand -16 (+ v1-6 15))))
  obj)

(defun-recursive mem-usage-shrub-walk draw-node ((arg0 draw-node) (arg1 int) (arg2 memory-usage-block) (arg3 int))
  "Recursively iterate through the entire shrub tree and compute memory usage for instances."
  (set! (-> arg2 length) (max 62 (-> arg2 length)))
  (set! (-> arg2 data 61 name) "draw-node")
  (+! (-> arg2 data 61 count) arg1)
  (let ((v1-5 (* arg1 32))) (+! (-> arg2 data 61 used) v1-5) (+! (-> arg2 data 61 total) (logand -16 (+ v1-5 15))))
  (let ((s2-0 arg0))
    (dotimes (s1-0 arg1)
      (let ((a1-2 (-> s2-0 child-count)))
        (cond
          ((logtest? (-> s2-0 flags) 1) (mem-usage-shrub-walk (the-as draw-node (-> s2-0 child)) (the-as int a1-2) arg2 arg3))
          (else
           (set! (-> arg2 length) (max 35 (-> arg2 length)))
           (set! (-> arg2 data 34 name) "instance-shrubbery")
           (+! (-> arg2 data 34 count) a1-2)
           (let ((v1-18 (* (the-as uint 80) a1-2)))
             (+! (-> arg2 data 34 used) v1-18)
             (+! (-> arg2 data 34 total) (logand -16 (+ v1-18 15)))))))
      (&+! s2-0 32)))
  arg0)

(defmethod mem-usage ((obj drawable-tree-instance-shrub) (arg0 memory-usage-block) (arg1 int))
  "Compute memory usage for an entire shrub tree"
  (set! (-> arg0 length) (max 1 (-> arg0 length)))
  (set! (-> arg0 data 0 name) (symbol->string 'drawable-group))
  (+! (-> arg0 data 0 count) 1)
  (let ((v1-7 32)) (+! (-> arg0 data 0 used) v1-7) (+! (-> arg0 data 0 total) (logand -16 (+ v1-7 15))))
  ;; time of day colors
  (when (nonzero? (-> obj colors-added))
    (set! (-> arg0 length) (max 33 (-> arg0 length)))
    (set! (-> arg0 data 32 name) "shrubbery-pal")
    (+! (-> arg0 data 32 count) 1)
    (let ((v1-19 (asize-of (-> obj colors-added))))
      (+! (-> arg0 data 32 used) v1-19)
      (+! (-> arg0 data 32 total) (logand -16 (+ v1-19 15)))))
  ;; instance tree
  (mem-usage-shrub-walk (the-as draw-node (&+ (-> obj data 0) 32))
                        (-> (the-as drawable-group (-> obj data 0)) length)
                        arg0
                        arg1)
  ;; prototypes
  (mem-usage (-> obj info prototype-inline-array-shrub) arg0 (logior arg1 1))
  obj)

(defmethod login ((obj generic-shrub-fragment))
  "Set up shaders in a generic shrub fragment"
  (let ((s5-0 (/ (-> obj cnt-qwc) (the-as uint 5))))
    (dotimes (s4-0 (the-as int s5-0))
      (adgif-shader-login-no-remap (-> obj textures s4-0))))
  obj)

(defmethod mem-usage ((obj generic-shrub-fragment) (arg0 memory-usage-block) (arg1 int))
  "Compute memory usage of generic shrub fragment"
  (set! (-> arg0 length) (max 27 (-> arg0 length)))
  (set! (-> arg0 data 25 name) "generic-shrub")
  (+! (-> arg0 data 25 count) 1)
  ;; the actual fragment object
  (let ((v1-6 (asize-of obj))) (+! (-> arg0 data 25 used) v1-6) (+! (-> arg0 data 25 total) (logand -16 (+ v1-6 15))))
  ;; the referenced data
  (set! (-> arg0 data 26 name) "generic-shrub-data")
  (+! (-> arg0 data 26 count) 1)
  (let ((v1-17 (* (+ (-> obj cnt-qwc) (-> obj vtx-qwc) (-> obj col-qwc) (-> obj stq-qwc)) 16)))
    (+! (-> arg0 data 26 used) v1-17)
    (+! (-> arg0 data 26 total) (logand -16 (+ v1-17 15))))
  obj)

(defmethod inspect ((obj prototype-shrubbery))
  "Inspect all prototypes in a prototype array."
  (format #t "[~8x] ~A~%" obj (-> obj type))
  (format #t "~Tlength: ~D~%" (-> obj length))
  (format #t "~Tdata[~D]: @ #x~X~%" (-> obj length) (-> obj data))
  (dotimes (s5-0 (-> obj length))
    (format #t "~T  [~D] ~A~%" s5-0 (-> obj data s5-0)))
  obj)

(defmethod mem-usage ((obj prototype-shrubbery) (arg0 memory-usage-block) (arg1 int))
  "Compute memory usage of all prototypes in a prototype array."
  (set! (-> arg0 length) (max 1 (-> arg0 length)))
  (set! (-> arg0 data 0 name) (symbol->string 'drawable-group))
  (+! (-> arg0 data 0 count) 1)
  (let ((v1-7 32)) (+! (-> arg0 data 0 used) v1-7) (+! (-> arg0 data 0 total) (logand -16 (+ v1-7 15))))
  (dotimes (s3-0 (-> obj length))
    (mem-usage (-> obj data s3-0) arg0 arg1))
  obj)

(defmethod login ((obj prototype-shrubbery))
  "Login all prototypes in a prototype array"
  (dotimes (s5-0 (-> obj length))
    (login (-> obj data s5-0)))
  obj)

(defmethod asize-of ((obj prototype-shrubbery))
  "Compute the allocation size of a prototype shrubbery array (dynamically sized)"
  (the-as int (+ (-> prototype-shrubbery size) (* (+ (-> obj length) -1) 32))))

(defmethod login ((obj prototype-generic-shrub))
  "Initialize all fragments in a generic prototype."
  (dotimes (s5-0 (-> obj length))
    (login (-> obj data s5-0)))
  obj)

(defmethod login ((obj shrubbery))
  "Initialize a shrubbery fragment."
  (let ((s5-0 (* (-> obj header data 0) 2)))
    (dotimes (s4-0 (the-as int s5-0))
      (adgif-shader-login-no-remap (-> obj textures s4-0))))
  (shrubbery-login-post-texture obj)
  obj)

(defmethod mem-usage ((obj shrubbery) (arg0 memory-usage-block) (arg1 int))
  "Compute the memory usage of a shrubbery fragment."
  (set! (-> arg0 length) (max 28 (-> arg0 length)))
  (set! (-> arg0 data 27 name) "shrubbery")
  (+! (-> arg0 data 27 count) 1)
  (let ((v1-6 (asize-of obj))) (+! (-> arg0 data 27 used) v1-6) (+! (-> arg0 data 27 total) (logand -16 (+ v1-6 15))))
  (set! (-> arg0 length) (max 30 (-> arg0 length)))
  (set! (-> arg0 data 29 name) "shrubbery-vertex")
  (+! (-> arg0 data 29 count) 1)
  (let ((v1-16 (* (-> obj vtx-qwc) 16)))
    (+! (-> arg0 data 29 used) v1-16)
    (+! (-> arg0 data 29 total) (logand -16 (+ v1-16 15))))
  (set! (-> arg0 length) (max 31 (-> arg0 length)))
  (set! (-> arg0 data 30 name) "shrubbery-color")
  (+! (-> arg0 data 30 count) 1)
  (let ((v1-26 (* (-> obj col-qwc) 16)))
    (+! (-> arg0 data 30 used) v1-26)
    (+! (-> arg0 data 30 total) (logand -16 (+ v1-26 15))))
  (set! (-> arg0 length) (max 29 (-> arg0 length)))
  (set! (-> arg0 data 28 name) "shrubbery-object")
  (+! (-> arg0 data 28 count) 1)
  (let ((v1-36 (* (-> obj obj-qwc) 16)))
    (+! (-> arg0 data 28 used) v1-36)
    (+! (-> arg0 data 28 total) (logand -16 (+ v1-36 15))))
  (set! (-> arg0 length) (max 32 (-> arg0 length)))
  (set! (-> arg0 data 31 name) "shrubbery-stq")
  (+! (-> arg0 data 31 count) 1)
  (let ((v1-46 (* (-> obj stq-qwc) 16)))
    (+! (-> arg0 data 31 used) v1-46)
    (+! (-> arg0 data 31 total) (logand -16 (+ v1-46 15))))
  obj)

(defmethod login ((obj drawable-tree-instance-shrub))
  "Initialize a shrubbery tree."
  (if (nonzero? (-> obj info prototype-inline-array-shrub)) (login (-> obj info prototype-inline-array-shrub)))
  obj)

(define shrub-vu1-block
  (new 'static
       'vu-function
       #| :length #x26a :qlength #x135 |#
       ))

(defun shrub-num-tris ((arg0 shrubbery))
  "Get the number of triangles in a shrubbery fragment."
  (- (-> arg0 header data 2) (* (-> arg0 header data 1) 2)))

(defun shrub-make-perspective-matrix ((arg0 matrix))
  "Compute the matrix used by the shrubbery VU1 program."
  (let* ((v1-0 arg0)
         (t0-0 (-> *math-camera* camera-temp))
         (a1-1 (-> t0-0 vector 0 quad))
         (a2-0 (-> t0-0 vector 1 quad))
         (a3-0 (-> t0-0 vector 2 quad))
         (t0-1 (-> t0-0 vector 3 quad)))
    (set! (-> v1-0 vector 0 quad) a1-1)
    (set! (-> v1-0 vector 1 quad) a2-0)
    (set! (-> v1-0 vector 2 quad) a3-0)
    (set! (-> v1-0 vector 3 quad) t0-1))
  (let ((f0-1 (/ 1.0 (-> *math-camera* pfog0))))
    (set! (-> arg0 vector 0 w) (* (-> arg0 vector 0 w) f0-1))
    (set! (-> arg0 vector 1 w) (* (-> arg0 vector 1 w) f0-1))
    (set! (-> arg0 vector 2 w) (* (-> arg0 vector 2 w) f0-1))
    (set! (-> arg0 vector 3 w) (* (-> arg0 vector 3 w) f0-1)))
  (+! (-> arg0 vector 0 x) (* (-> arg0 vector 0 w) (-> *math-camera* hvdf-off x)))
  (+! (-> arg0 vector 1 x) (* (-> arg0 vector 1 w) (-> *math-camera* hvdf-off x)))
  (+! (-> arg0 vector 2 x) (* (-> arg0 vector 2 w) (-> *math-camera* hvdf-off x)))
  (+! (-> arg0 vector 3 x) (* (-> arg0 vector 3 w) (-> *math-camera* hvdf-off x)))
  (+! (-> arg0 vector 0 y) (* (-> arg0 vector 0 w) (-> *math-camera* hvdf-off y)))
  (+! (-> arg0 vector 1 y) (* (-> arg0 vector 1 w) (-> *math-camera* hvdf-off y)))
  (+! (-> arg0 vector 2 y) (* (-> arg0 vector 2 w) (-> *math-camera* hvdf-off y)))
  (+! (-> arg0 vector 3 y) (* (-> arg0 vector 3 w) (-> *math-camera* hvdf-off y)))
  (+! (-> arg0 vector 0 z) (* (-> arg0 vector 0 w) (-> *math-camera* hvdf-off z)))
  (+! (-> arg0 vector 1 z) (* (-> arg0 vector 1 w) (-> *math-camera* hvdf-off z)))
  (+! (-> arg0 vector 2 z) (* (-> arg0 vector 2 w) (-> *math-camera* hvdf-off z)))
  (+! (-> arg0 vector 3 z) (* (-> arg0 vector 3 w) (-> *math-camera* hvdf-off z)))
  arg0)

(defun shrub-init-view-data ((arg0 shrub-view-data))
  "Initialize shrubbery constants in place"
  (set! (-> arg0 texture-giftag tag) (new 'static 'gif-tag64 :nloop #x1 :nreg #x4))
  (set! (-> arg0 texture-giftag regs)
        (new 'static
             'gif-tag-regs
             :regs0 (gif-reg-id a+d)
             :regs1 (gif-reg-id a+d)
             :regs2 (gif-reg-id a+d)
             :regs3 (gif-reg-id a+d)))
  (set! (-> arg0 texture-giftag word 3) (the-as uint #x40a00000))
  (set! (-> arg0 tex-start-ptr) (the-as int 25167696.0))
  (set! (-> arg0 mtx-buf-ptr) (the-as int 8388608.0))
  (set! (-> arg0 fog-0) (-> *math-camera* pfog0))
  (set! (-> arg0 fog-1) (-> *math-camera* pfog1))
  (set! (-> arg0 fog-min) (-> *math-camera* fog-min))
  (set! (-> arg0 fog-max) (-> *math-camera* fog-max))
  #f)

(defun shrub-upload-view-data ((arg0 dma-buffer))
  "Generate DMA data to upload shrubbery constants to VU1."
  (let ((s5-0 3))
    (let* ((v1-0 arg0)
           (a0-1 (the-as object (-> v1-0 base))))
      (set! (-> (the-as dma-packet a0-1) dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc s5-0))
      (set! (-> (the-as dma-packet a0-1) vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl)))
      (set! (-> (the-as dma-packet a0-1) vif1) (new 'static 'vif-tag :cmd (vif-cmd unpack-v4-32) :num s5-0))
      (set! (-> v1-0 base) (&+ (the-as pointer a0-1) 16)))
    (shrub-init-view-data (the-as shrub-view-data (-> arg0 base)))
    (&+! (-> arg0 base) (* s5-0 16)))
  #f)

(defun shrub-time ((arg0 int) (arg1 int) (arg2 int) (arg3 int) (arg4 int))
  (+ (* arg0 8) 29 (* 22 arg2) (* 11 arg1) (* (+ (* arg4 2) 15 (* 5 arg2) (* 13 arg0)) arg3) 53))

(defun shrub-do-init-frame ((arg0 dma-buffer))
  "Generate DMA to initialize the shrubbery renderer on VU1."
  ;; upload VU1 program
  (dma-buffer-add-vu-function arg0 shrub-vu1-block 1)
  ;; upload constants
  (shrub-upload-view-data arg0)
  ;; run program initialization function
  (let* ((v1-0 arg0)
         (a0-3 (the-as object (-> v1-0 base))))
    (set! (-> (the-as dma-packet a0-3) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
    (set! (-> (the-as dma-packet a0-3) vif0) (new 'static 'vif-tag :cmd (vif-cmd mscalf) :msk #x1 :imm #x0))
    (set! (-> (the-as dma-packet a0-3) vif1) (new 'static 'vif-tag :cmd (vif-cmd flushe) :msk #x1))
    (set! (-> v1-0 base) (&+ (the-as pointer a0-3) 16)))
  ;; initialize VIF for shrubbery chains.
  (let* ((v1-1 arg0)
         (a0-5 (the-as object (-> v1-1 base))))
    (set! (-> (the-as dma-packet a0-5) dma) (new 'static 'dma-tag :qwc #x3 :id (dma-tag-id cnt)))
    (set! (-> (the-as dma-packet a0-5) vif0) (new 'static 'vif-tag))
    (set! (-> (the-as dma-packet a0-5) vif1) (new 'static 'vif-tag))
    (set! (-> v1-1 base) (&+ (the-as pointer a0-5) 16)))
  (let ((v1-2 (-> arg0 base)))
    (set! (-> (the-as (pointer vif-tag) v1-2) 0) (new 'static 'vif-tag :cmd (vif-cmd strow) :msk #x1))
    (set! (-> (the-as (pointer uint32) v1-2) 1) (the-as uint #x8080))
    (set! (-> (the-as (pointer uint32) v1-2) 2) (the-as uint #x8080))
    (set! (-> (the-as (pointer uint32) v1-2) 3) (the-as uint #x8080))
    (set! (-> (the-as (pointer uint32) v1-2) 4) (the-as uint 0))
    (set! (-> (the-as (pointer vif-tag) v1-2) 5) (new 'static 'vif-tag :cmd (vif-cmd stcol) :msk #x1))
    (set! (-> (the-as (pointer uint32) v1-2) 6) (the-as uint 4096))
    (set! (-> (the-as (pointer uint32) v1-2) 7) (the-as uint 4096))
    (set! (-> (the-as (pointer uint32) v1-2) 8) (the-as uint 4096))
    (set! (-> (the-as (pointer uint32) v1-2) 9) (the-as uint 4096))
    (set! (-> (the-as (pointer vif-tag) v1-2) 10) (new 'static 'vif-tag :cmd (vif-cmd stmask)))
    (set! (-> (the-as (pointer uint32) v1-2) 11) (the-as uint #xa0a0a0a0))
    (set! (-> arg0 base) (&+ v1-2 48)))
  (set! *shrub-state* 2)
  #f)

(defun shrub-init-frame ((arg0 dma-buffer) (arg1 gs-test))
  "Generate DMA to initialize to shrubbery renderer VU1 and GS."
  ;; init VU1
  (shrub-do-init-frame arg0)
  ;; init GS.
  (let* ((v1-0 arg0)
         (a0-2 (the-as object (-> v1-0 base))))
    (set! (-> (the-as dma-packet a0-2) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt)))
    (set! (-> (the-as dma-packet a0-2) vif0) (new 'static 'vif-tag))
    (set! (-> (the-as dma-packet a0-2) vif1) (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1))
    (set! (-> v1-0 base) (the-as pointer (the-as gs-gif-tag (&+ (the-as pointer a0-2) 16)))))
  (let* ((v1-1 arg0)
         (a0-4 (the-as object (-> v1-1 base))))
    (set! (-> (the-as gs-gif-tag a0-4) tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1))
    (set! (-> (the-as gs-gif-tag a0-4) regs)
          (new 'static
               'gif-tag-regs
               :regs0 (gif-reg-id a+d)
               :regs1 (gif-reg-id a+d)
               :regs2 (gif-reg-id a+d)
               :regs3 (gif-reg-id a+d)
               :regs4 (gif-reg-id a+d)
               :regs5 (gif-reg-id a+d)
               :regs6 (gif-reg-id a+d)
               :regs7 (gif-reg-id a+d)
               :regs8 (gif-reg-id a+d)
               :regs9 (gif-reg-id a+d)
               :regs10 (gif-reg-id a+d)
               :regs11 (gif-reg-id a+d)
               :regs12 (gif-reg-id a+d)
               :regs13 (gif-reg-id a+d)
               :regs14 (gif-reg-id a+d)
               :regs15 (gif-reg-id a+d)))
    (set! (-> v1-1 base) (&+ (the-as pointer a0-4) 16)))
  (let ((v1-2 (-> arg0 base)))
    (set! (-> (the-as (pointer gs-test) v1-2) 0) arg1)
    (set! (-> (the-as (pointer gs-reg64) v1-2) 1) (gs-reg64 test-1))
    (set! (-> arg0 base) (&+ v1-2 16)))
  (none))

(defun shrub-upload-model ((arg0 shrubbery) (arg1 dma-buffer) (arg2 int))
  "Generate DMA to upload a shrub model"
  (let* ((v1-0 arg1)
         (a3-0 (the-as object (-> v1-0 base))))
    ;; upload the data
    (set! (-> (the-as dma-packet a3-0) dma)
          (new 'static
               'dma-tag
               :id (dma-tag-id ref)
               :addr (-> arg0 obj)
               :qwc
               (+ (-> arg0 obj-qwc) (-> arg0 vtx-qwc) (-> arg0 col-qwc) (-> arg0 stq-qwc))))
    (set! (-> (the-as dma-packet a3-0) vif0) (new 'static 'vif-tag :cmd (vif-cmd base) :imm *shrub-state*))
    (set! (-> (the-as dma-packet a3-0) vif1) (new 'static 'vif-tag :cmd (vif-cmd offset)))
    (set! (-> v1-0 base) (&+ (the-as pointer a3-0) 16)))
  ;; run the program to init a model
  (cond
    ((= arg2 1)
     (let* ((v1-2 arg1)
            (a0-9 (the-as object (-> v1-2 base))))
       (set! (-> (the-as dma-packet a0-9) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
       (set! (-> (the-as dma-packet a0-9) vif0) (new 'static 'vif-tag))
       (set! (-> (the-as dma-packet a0-9) vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1 :imm #x11))
       (set! (-> v1-2 base) (&+ (the-as pointer a0-9) 16))))
    (else
     (let* ((v1-3 arg1)
            (a0-11 (the-as object (-> v1-3 base))))
       (set! (-> (the-as dma-packet a0-11) dma) (new 'static 'dma-tag :id (dma-tag-id cnt)))
       (set! (-> (the-as dma-packet a0-11) vif0) (new 'static 'vif-tag))
       (set! (-> (the-as dma-packet a0-11) vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1 :imm #x15))
       (set! (-> v1-3 base) (&+ (the-as pointer a0-11) 16)))))
  ;; some data buffer thing.
  (set! *shrub-state* (- 164 *shrub-state*))
  #f)

;; TODO drawing...

(defun draw-drawable-tree-instance-shrub ((arg0 drawable-tree-instance-shrub) (arg1 level))
  ;; (local-vars (a0-4 int) (a0-6 int) (a0-11 int) (a0-13 int))
  (set-vector! (-> *instance-shrub-work* min-dist) 4095996000.0 4095996000.0 4095996000.0 4095996000.0)
  (set! (-> *instance-shrub-work* near-last) (the-as uint 0))
  (set! (-> *instance-shrub-work* near-next) (the-as uint 0))
  (set! (-> *instance-shrub-work* near-count) (the-as uint 0))
  (set! (-> *instance-shrub-work* wind-vectors) (-> arg0 info wind-vectors))
  (set! (-> *instance-shrub-work* wait-to-spr) (the-as uint 0))
  (set! (-> *instance-shrub-work* wait-from-spr) (the-as uint 0))
  (when (logtest? *vu1-enable-user* (vu1-renderer-mask shrubbery shrub-near billboard trans-shrubbery))
    (let* ((v1-13 (-> arg0 info prototype-inline-array-shrub))
           (s4-0 (-> v1-13 length))
           (s3-0 (-> v1-13 data)))
      (countdown (a1-2 s4-0)
        (let ((a2-3 (-> v1-13 data a1-2)))
          (set! (-> a2-3 next-clear) (the-as uint128 0))
          (set! (-> a2-3 last-clear) (the-as uint128 0))
          (set! (-> a2-3 count-clear) (the-as uint 0)))
        0)
      (let ((v1-19 (-> *display* frames (-> *display* on-screen) frame global-buf)))
        (when (nonzero? (-> arg0 length))
          (let ((s5-0 (-> *display* frames (-> *display* on-screen) frame global-buf base)))
            (reset! (-> *perf-stats* data (perf-stat-bucket inst-shrub)))
            ; (draw-inline-array-instance-shrub
            ;   v1-19
            ;   (&+ (-> arg0 data 0) 32)
            ;   (-> (the-as drawable-group (-> arg0 data 0)) length)
            ;   s3-0
            ;   )
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            ;; NOTE: this part is completely rewritten for PC
            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            (when (logtest? *vu1-enable-user* (vu1-renderer-mask shrubbery))
              (let* ((s2-1 (-> *display* frames (-> *display* on-screen) frame global-buf))
                     (s3-1 (-> s2-1 base)))
                (add-pc-tfrag3-data s2-1 (-> *level* data (-> (scratchpad-object terrain-context) bsp lev-index)))
                (let ((a3-22 (-> s2-1 base)))
                  (let ((v1-57 (the-as object (-> s2-1 base))))
                    (set! (-> (the-as dma-packet v1-57) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
                    (set! (-> (the-as dma-packet v1-57) vif0) (new 'static 'vif-tag))
                    (set! (-> (the-as dma-packet v1-57) vif1) (new 'static 'vif-tag))
                    (set! (-> s2-1 base) (&+ (the-as pointer v1-57) 16)))
                  (dma-bucket-insert-tag (-> *display* frames (-> *display* on-screen) frame bucket-group)
                                         (the-as bucket-id
                                                 (if (zero? (-> (scratchpad-object terrain-context) bsp lev-index)) (bucket-id shrub0) (bucket-id shrub1)))
                                         s3-1
                                         (the-as (pointer dma-tag) a3-22)))))
            (read! (-> *perf-stats* data (perf-stat-bucket inst-shrub)))
            (reset! (-> *perf-stats* data (perf-stat-bucket proto-shrub)))
            ; (draw-prototype-inline-array-shrub s4-0 s3-0)
            (read! (-> *perf-stats* data (perf-stat-bucket proto-shrub)))
            (let ((v1-28 *dma-mem-usage*))
              (when (nonzero? v1-28)
                (set! (-> v1-28 length) (max 28 (-> v1-28 length)))
                (set! (-> v1-28 data 27 name) "shrubbery")
                (+! (-> v1-28 data 27 count) 1)
                (+! (-> v1-28 data 27 used)
                    (&- (-> *display* frames (-> *display* on-screen) frame global-buf base) (the-as uint s5-0)))
                (set! (-> v1-28 data 27 total) (-> v1-28 data 27 used))))))))
    (update-wait-stats (-> *perf-stats* data (perf-stat-bucket inst-shrub))
                       (the-as uint 0)
                       (-> *instance-shrub-work* wait-to-spr)
                       (-> *instance-shrub-work* wait-from-spr))
    (set! (-> arg1 closest-object 2) (-> *instance-shrub-work* min-dist x)))
  0
  (none))

(defmethod draw ((obj drawable-tree-instance-shrub) (arg0 drawable-tree-instance-shrub) (arg1 display-frame))
  (let* ((v1-1 (-> *background-work* shrub-tree-count))
         (a1-2 (-> (scratchpad-object terrain-context) bsp lev-index))
         (a1-5 (-> *level* level a1-2)))
    (set! (-> *background-work* shrub-trees v1-1) obj)
    (set! (-> *background-work* shrub-levels v1-1) a1-5))
  (+! (-> *background-work* shrub-tree-count) 1)
  (none))

(defmethod unpack-vis ((obj drawable-tree-instance-shrub) (arg0 (pointer int8)) (arg1 (pointer int8)))
  arg1)

(defmethod collect-stats ((obj drawable-tree-instance-shrub))
  (when (logtest? *vu1-enable-user* (vu1-renderer-mask shrubbery shrub-near billboard trans-shrubbery))
    (let* ((v1-3 (-> obj info prototype-inline-array-shrub))
           (gp-0 (the-as object (-> v1-3 data))))
      (countdown (s5-0 (-> v1-3 length))
        (when (logtest? *vu1-enable-user* (vu1-renderer-mask shrub-near))
          (let ((v1-7 (-> (the-as prototype-bucket-shrub gp-0) count 0))
                (a1-0 (-> (the-as prototype-bucket-shrub gp-0) geometry 0)))
            (when (nonzero? v1-7)
              (let ((a0-2 (-> (the-as drawable-group a1-0) length)))
                (+! (-> *terrain-stats* shrub groups) 1)
                (+! (-> *terrain-stats* shrub fragments) (* a0-2 (the-as int v1-7))))
              (+! (-> *terrain-stats* shrub instances) v1-7))))
        (when (logtest? *vu1-enable-user* (vu1-renderer-mask shrubbery))
          (let ((s4-0 (-> (the-as prototype-bucket-shrub gp-0) count 1))
                (v1-12 (-> (the-as prototype-bucket-shrub gp-0) geometry 1)))
            (when (nonzero? s4-0)
              (let ((s3-0 (&+ v1-12 32))
                    (s2-0 (-> (the-as drawable-group v1-12) length)))
                (+! (-> *terrain-stats* shrub groups) 1)
                (+! (-> *terrain-stats* shrub fragments) s2-0)
                (+! (-> *terrain-stats* shrub instances) s4-0)
                (while (nonzero? s2-0)
                  (+! s2-0 -1)
                  (let ((a0-13 (* (shrub-num-tris (the-as shrubbery s3-0)) s4-0))
                        (v1-24 (* (-> (the-as shrubbery s3-0) header data 2) s4-0)))
                    (+! (-> *terrain-stats* shrub tris) a0-13)
                    (+! (-> *terrain-stats* shrub dverts) v1-24))
                  (&+! s3-0 32))))))
        (when (logtest? *vu1-enable-user* (vu1-renderer-mask trans-shrubbery))
          (let ((s4-1 (-> (the-as prototype-bucket-shrub gp-0) count 2))
                (v1-30 (-> (the-as prototype-bucket-shrub gp-0) geometry 2)))
            (when (nonzero? s4-1)
              (let ((s3-1 (&+ v1-30 32))
                    (s2-1 (-> (the-as drawable-group v1-30) length)))
                (+! (-> *terrain-stats* trans-shrub groups) 1)
                (+! (-> *terrain-stats* trans-shrub fragments) s2-1)
                (+! (-> *terrain-stats* trans-shrub instances) s4-1)
                (while (nonzero? s2-1)
                  (+! s2-1 -1)
                  (let ((a0-24 (* (shrub-num-tris (the-as shrubbery s3-1)) s4-1))
                        (v1-42 (* (-> (the-as shrubbery s3-1) header data 2) s4-1)))
                    (+! (-> *terrain-stats* trans-shrub tris) a0-24)
                    (+! (-> *terrain-stats* trans-shrub dverts) v1-42))
                  (&+! s3-1 32))))))
        (when (logtest? *vu1-enable-user* (vu1-renderer-mask billboard))
          (let ((v1-48 (-> (the-as prototype-bucket-shrub gp-0) count 3)))
            (when (nonzero? v1-48)
              (+! (-> *terrain-stats* billboard groups) 1)
              (+! (-> *terrain-stats* billboard instances) v1-48)
              (+! (-> *terrain-stats* billboard tris) (* v1-48 2))
              (+! (-> *terrain-stats* billboard dverts) (* v1-48 4)))))
        (set! gp-0 (-> (the-as (inline-array prototype-bucket-shrub) gp-0) 1)))))
  (none))
