;;-*-Lisp-*-
(in-package goal)

;; name: background.gc
;; name in dgo: background
;; dgos: ENGINE, GAME

;; DECOMP BEGINS

(define *background-work* (new 'global 'background-work))

;; identical to Jak 1's VU0 program here.
(define background-vu0-block (new 'static 'vu-function))

(defun background-upload-vu0 ()
  ;; (upload-vu0-program background-vu0-block (&-> *background-work* wait-to-vu0))
  0
  (none)
  )

(defun init-background ()
  "Clear the tree list in background-work."
  (dotimes (v1-0 8)
    (set! (-> *background-work* tfrag-trees v1-0) #f)
    (set! (-> *background-work* tfrag-trans-trees v1-0) #f)
    (set! (-> *background-work* tfrag-water-trees v1-0) #f)
    )
  (set! (-> *background-work* tfrag-tree-count) 0)
  (set! (-> *background-work* tfrag-trans-tree-count) 0)
  (set! (-> *background-work* tfrag-water-tree-count) 0)
  (set! (-> *background-work* shrub-tree-count) 0)
  (set! (-> *background-work* tie-tree-count) 0)
  (set! (-> *background-work* wait-to-vu0) (the-as uint 0))
  0
  (none)
  )

(defconstant VISIBLE_LIST_SCRATCHPAD #x38a0)

(defun upload-vis-bits ((arg0 level) (arg1 level) (arg2 bsp-header))
  "Upload visibility data to the scratchpad."
  (let ((qwc (/ (+ (-> arg2 visible-list-length) 15) 16)))
    (let ((lev-vis-bits (the-as (pointer uint128) (-> arg0 vis-bits)))
          (all-vis (the-as (pointer uint128) (-> arg2 all-visible-list)))
          ;;(spad-vis (the-as (pointer uint128) (+ #x38a0 #x70000000)))
          (spad-vis (scratchpad-ptr uint128 :offset VISIBLE_LIST_SCRATCHPAD))
          )

      (b! (not *artist-flip-visible*) cfg-5 :delay (nop!))
      (nop!)
      (nop!)
      (label cfg-2)
      ;; flip visible is selected. unfortunately this code is wrong and uses a 64-bit xor.
      (let ((a3-2 (-> lev-vis-bits 0)))
        (set! lev-vis-bits (&-> lev-vis-bits 1))
        (let ((t0-0 (-> all-vis 0)))
          (set! all-vis (&-> all-vis 1))
          (nop!)
          (nop!)
          ;; xor with all visible to flip the bits of the things that exist.
          (let ((a3-3 (logxor a3-2 (the-as uint t0-0))))
            (+! qwc -1)
            (set! (-> spad-vis 0) a3-3)
            )
          )
        )
      (set! spad-vis (&-> spad-vis 1))
      (b! (> qwc 0) cfg-2 :delay (nop!))
      0
      (b! #t cfg-8 :delay (nop!))
      ;; flip visible isn't selected, just copy to scratchpad.
      (nop!)
      (label cfg-5)
      (nop!)
      (nop!)
      (label cfg-6)
      (let ((a1-2 (-> lev-vis-bits 0)))
        (set! lev-vis-bits (&-> lev-vis-bits 1))
        (nop!)
        (+! qwc -1)
        (set! (-> spad-vis 0) a1-2)
        )
      (set! spad-vis (&-> spad-vis 1))
      )
    (b! (> qwc 0) cfg-6 :delay (nop!))
    )
  0
  (label cfg-8)
  (none)
  )

(defun set-background-regs! ((arg0 level))
  "Set up registers for background drawing.
  These are the ones actually used by the background renderers."
  (local-vars (v1-1 float) (v1-2 float))

  ;; set up background regs. These are the same ones used in bsp, but different from "transform" regs.
  ;; the "transform" have stuff like hmge/hvdf required to do screen space stuff. This is just geometry.
  (let ((v1-0 *math-camera*))
    (with-vf (vf16 vf17 vf18 vf19 vf20 vf21 vf22 vf23 vf24 vf25 vf26 vf27 vf28 vf29 vf30 vf31)
             :rw 'write
             (cond
               ((-> arg0 info use-camera-other)
                (.lvf vf16 (&-> v1-0 plane-other 0 quad))
                (.lvf vf17 (&-> v1-0 plane-other 1 quad))
                (.lvf vf18 (&-> v1-0 plane-other 2 quad))
                (.lvf vf19 (&-> v1-0 plane-other 3 quad))
                (.lvf vf20 (&-> v1-0 shrub-mat-other vector 0 quad))
                (.lvf vf21 (&-> v1-0 shrub-mat-other vector 1 quad))
                (.lvf vf22 (&-> v1-0 shrub-mat-other vector 2 quad))
                (.lvf vf23 (&-> v1-0 shrub-mat-other trans quad))
                (.lvf vf24 (&-> v1-0 camera-rot-other vector 0 quad))
                (.lvf vf25 (&-> v1-0 camera-rot-other vector 1 quad))
                (.lvf vf26 (&-> v1-0 camera-rot-other vector 2 quad))
                (.lvf vf27 (&-> v1-0 camera-rot-other trans quad))
                (.lvf vf28 (&-> v1-0 camera-temp-other vector 0 quad))
                (.lvf vf29 (&-> v1-0 camera-temp-other vector 1 quad))
                (.lvf vf30 (&-> v1-0 camera-temp-other vector 2 quad))
                (.lvf vf31 (&-> v1-0 camera-temp-other trans quad))
                (.mov v1-1 vf31)
                )
               (else
                 (.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))
                 (.lvf vf20 (&-> v1-0 shrub-mat vector 0 quad))
                 (.lvf vf21 (&-> v1-0 shrub-mat vector 1 quad))
                 (.lvf vf22 (&-> v1-0 shrub-mat vector 2 quad))
                 (.lvf vf23 (&-> v1-0 shrub-mat trans quad))
                 (.lvf vf24 (&-> v1-0 camera-rot vector 0 quad))
                 (.lvf vf25 (&-> v1-0 camera-rot vector 1 quad))
                 (.lvf vf26 (&-> v1-0 camera-rot vector 2 quad))
                 (.lvf vf27 (&-> v1-0 camera-rot trans quad))
                 (.lvf vf28 (&-> v1-0 camera-temp vector 0 quad))
                 (.lvf vf29 (&-> v1-0 camera-temp vector 1 quad))
                 (.lvf vf30 (&-> v1-0 camera-temp vector 2 quad))
                 (.lvf vf31 (&-> v1-0 camera-temp trans quad))
                 (.mov v1-2 vf31)
                 )
               )
             )
    )

  ;; this code would wait for VU0 program upload, then do a vcallms 0 which sets up additional registers,
  ;; and stashes stuff in vu0 data memory.
  ;; note: vf24-vf27 get messed with here, but after they are stashed in VU0 memory.

  ; sq.xyzw vf24, 4(vi00)      |  maxw.xyzw vf01, vf00, vf00
  ; sq.xyzw vf25, 5(vi00)      |  nop
  ; sq.xyzw vf26, 6(vi00)      |  nop
  ; sq.xyzw vf27, 7(vi00)      |  nop
  ; sq.xyzw vf16, 0(vi00)      |  mulz.xyzw vf24, vf01, vf24
  ; sq.xyzw vf17, 1(vi00)      |  mulz.xyzw vf25, vf01, vf25
  ; sq.xyzw vf18, 2(vi00)      |  mulz.xyzw vf26, vf01, vf26
  ; sq.xyzw vf19, 3(vi00)      |  mulz.xyzw vf27, vf01, vf27
  ; sq.xyzw vf24, 12(vi00)     |  nop
  ; sq.xyzw vf25, 13(vi00)     |  nop
  ; sq.xyzw vf26, 14(vi00)     |  nop
  ; sq.xyzw vf27, 15(vi00)     |  nop
  ; sq.xyzw vf28, 8(vi00)      |  nop
  ; sq.xyzw vf29, 9(vi00)      |  nop
  ; sq.xyzw vf30, 10(vi00)     |  nop
  ; sq.xyzw vf31, 11(vi00)     |  nop :e
  ; iaddiu vi02, vi00, 0xf0    |  nop

  #|
  (let ((v1-3 (the-as object #x10008000))
        (a0-4 (the-as (pointer integer) (&-> *background-work* wait-to-vu0)))
        )
    (b! (zero? (logand (-> (the-as (pointer int32) v1-3) 0) 256)) cfg-5 :delay (nop!))
    (let ((a1-2 (-> (the-as (pointer int32) a0-4) 0)))
      (nop!)
      (let ((a2-0 (-> (the-as (pointer int32) v1-3) 0)))
        (nop!)
        (let ((a2-1 (logand a2-0 256))
              (a1-3 (+ a1-2 1))
              )
          (b! (nonzero? a2-1) cfg-4 :delay (set! (-> (the-as (pointer uint32) a0-4) 0) (the-as uint a1-3)))
          )
        )
      )
    )
  (label cfg-5)
  0
  (.vcallms 0)
  |#
  0
  (none)
  )

(defun set-tie-quard-planes! ((arg0 level))
  "Update guard planes for tie. The use-camera-other stuff can be used to effectively 'move' a level,
   so the camera guard planes need to be set accordingly."
  (cond
    ((-> arg0 info use-camera-other)
     (set! (-> *instance-tie-work* guard-plane 0 quad) (-> *math-camera* guard-plane-other 0 quad))
     (set! (-> *instance-tie-work* guard-plane 1 quad) (-> *math-camera* guard-plane-other 1 quad))
     (set! (-> *instance-tie-work* guard-plane 2 quad) (-> *math-camera* guard-plane-other 2 quad))
     (set! (-> *instance-tie-work* guard-plane 3 quad) (-> *math-camera* guard-plane-other 3 quad))
     )
    (else
      (set! (-> *instance-tie-work* guard-plane 0 quad) (-> *math-camera* guard-plane 0 quad))
      (set! (-> *instance-tie-work* guard-plane 1 quad) (-> *math-camera* guard-plane 1 quad))
      (set! (-> *instance-tie-work* guard-plane 2 quad) (-> *math-camera* guard-plane 2 quad))
      (set! (-> *instance-tie-work* guard-plane 3 quad) (-> *math-camera* guard-plane 3 quad))
      )
    )
  (none)
  )

(defun set-shrub-quard-planes! ((arg0 level))
  "Update guard planes for shrub. The use-camera-other stuff can be used to effectively 'move' a level,
   so the camera guard planes need to be set accordingly."
  (cond
    ((-> arg0 info use-camera-other)
     (set! (-> *instance-shrub-work* guard-plane 0 quad) (-> *math-camera* guard-plane-other 0 quad))
     (set! (-> *instance-shrub-work* guard-plane 1 quad) (-> *math-camera* guard-plane-other 1 quad))
     (set! (-> *instance-shrub-work* guard-plane 2 quad) (-> *math-camera* guard-plane-other 2 quad))
     (set! (-> *instance-shrub-work* guard-plane 3 quad) (-> *math-camera* guard-plane-other 3 quad))
     )
    (else
      (set! (-> *instance-shrub-work* guard-plane 0 quad) (-> *math-camera* guard-plane 0 quad))
      (set! (-> *instance-shrub-work* guard-plane 1 quad) (-> *math-camera* guard-plane 1 quad))
      (set! (-> *instance-shrub-work* guard-plane 2 quad) (-> *math-camera* guard-plane 2 quad))
      (set! (-> *instance-shrub-work* guard-plane 3 quad) (-> *math-camera* guard-plane 3 quad))
      )
    )
  (none)
  )


(defun add-pc-tfrag3-data ((dma-buf dma-buffer) (lev level))
  "Add PC-port specific tfrag data"
  (let ((packet (the-as dma-packet (-> dma-buf base))))
    (set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 25))
    (set! (-> packet vif0) (new 'static 'vif-tag))
    (set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
    (set! (-> dma-buf base) (the pointer (&+ packet 16)))
    )

  ;; first 4 quadwords are planes, then itimes
  (let ((data-ptr (the-as (pointer uint128) (-> dma-buf base)))
        (vec-ptr (the-as (inline-array vector) (-> dma-buf base)))
        )
    ;; the "use-camera-other" flag is set to "move" entire levels,
    ;; like the rotating city below in the throne room.
    (cond
      ((-> lev info use-camera-other)
        (set! (-> data-ptr 0) (-> *math-camera* plane-other 0 quad))
        (set! (-> data-ptr 1) (-> *math-camera* plane-other 1 quad))
        (set! (-> data-ptr 2) (-> *math-camera* plane-other 2 quad))
        (set! (-> data-ptr 3) (-> *math-camera* plane-other 3 quad))
        (set! (-> data-ptr 4) (-> lev mood-context itimes 0 quad))
        (set! (-> data-ptr 5) (-> lev mood-context itimes 1 quad))
        (set! (-> data-ptr 6) (-> lev mood-context itimes 2 quad))
        (set! (-> data-ptr 7) (-> lev mood-context itimes 3 quad))
        (set! (-> data-ptr 8) (-> *math-camera* camera-temp-other vector 0 quad))
        (set! (-> data-ptr 9) (-> *math-camera* camera-temp-other vector 1 quad))
        (set! (-> data-ptr 10) (-> *math-camera* camera-temp-other vector 2 quad))
        (set! (-> data-ptr 11) (-> *math-camera* camera-temp-other vector 3 quad))
        (set! (-> data-ptr 12) (-> *math-camera* hvdf-off quad))
        (let ((vec (-> (the (inline-array vector) data-ptr) 13)))
          (set! (-> vec x) (-> *math-camera* pfog0))
          (set! (-> vec y) (-> *math-camera* fog-min))
          (set! (-> vec z) (-> *math-camera* fog-max))
          )

        ;; the "other" version of trans doesn't have the same meaning as the normal one.
        ;; but inv-camera-rot-other is right, and we can just pull the translation from there.
        ;; I'm not certain the most accurate way to get this - either way there is an extra rotation to do.
        (set! (-> data-ptr 14) (-> *math-camera* inv-camera-rot-other vector 3 quad))
        (set! (-> vec-ptr 14 w) 1.0)

        (set! (-> data-ptr 15) (-> *math-camera* camera-rot-other vector 0 quad))
        (set! (-> data-ptr 16) (-> *math-camera* camera-rot-other vector 1 quad))
        (set! (-> data-ptr 17) (-> *math-camera* camera-rot-other vector 2 quad))
        (set! (-> data-ptr 18) (-> *math-camera* camera-rot-other vector 3 quad))


        (set! (-> data-ptr 19) (-> *math-camera* perspective vector 0 quad))
        (set! (-> data-ptr 20) (-> *math-camera* perspective vector 1 quad))
        (set! (-> data-ptr 21) (-> *math-camera* perspective vector 2 quad))
        (set! (-> data-ptr 22) (-> *math-camera* perspective vector 3 quad))

       )
      (else
        (set! (-> data-ptr 0) (-> *math-camera* plane 0 quad))
        (set! (-> data-ptr 1) (-> *math-camera* plane 1 quad))
        (set! (-> data-ptr 2) (-> *math-camera* plane 2 quad))
        (set! (-> data-ptr 3) (-> *math-camera* plane 3 quad))
        (set! (-> data-ptr 4) (-> lev mood-context itimes 0 quad))
        (set! (-> data-ptr 5) (-> lev mood-context itimes 1 quad))
        (set! (-> data-ptr 6) (-> lev mood-context itimes 2 quad))
        (set! (-> data-ptr 7) (-> lev mood-context itimes 3 quad))
        (set! (-> data-ptr 8) (-> *math-camera* camera-temp vector 0 quad))
        (set! (-> data-ptr 9) (-> *math-camera* camera-temp vector 1 quad))
        (set! (-> data-ptr 10) (-> *math-camera* camera-temp vector 2 quad))
        (set! (-> data-ptr 11) (-> *math-camera* camera-temp vector 3 quad))
        (set! (-> data-ptr 12) (-> *math-camera* hvdf-off quad))
        (let ((vec (-> (the (inline-array vector) data-ptr) 13)))
          (set! (-> vec x) (-> *math-camera* pfog0))
          (set! (-> vec y) (-> *math-camera* fog-min))
          (set! (-> vec z) (-> *math-camera* fog-max))
          )
        ;; use the camera-trans used to derive the camera matrix.
        (set! (-> data-ptr 14) (-> *math-camera* trans quad))

        (set! (-> data-ptr 15) (-> *math-camera* camera-rot vector 0 quad))
        (set! (-> data-ptr 16) (-> *math-camera* camera-rot vector 1 quad))
        (set! (-> data-ptr 17) (-> *math-camera* camera-rot vector 2 quad))
        (set! (-> data-ptr 18) (-> *math-camera* camera-rot vector 3 quad))

        (set! (-> data-ptr 19) (-> *math-camera* perspective vector 0 quad))
        (set! (-> data-ptr 20) (-> *math-camera* perspective vector 1 quad))
        (set! (-> data-ptr 21) (-> *math-camera* perspective vector 2 quad))
        (set! (-> data-ptr 22) (-> *math-camera* perspective vector 3 quad))
        )
      )

    (copyn-charp<-string (the (pointer uint8) (&-> data-ptr 23)) (symbol->string (bsp-name lev)) 32)
    )
  (&+! (-> dma-buf base) (* 16 25))
  )

(defun add-pc-camera-data ((dma-buf dma-buffer))
  "Add PC-port specific camera data. used as fallback for collide mesh renderer.
   Same as add-pc-trag3-data but level-specific data is left undefined."
  (let ((packet (the-as dma-packet (-> dma-buf base))))
    (set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 25))
    (set! (-> packet vif0) (new 'static 'vif-tag))
    (set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
    (set! (-> dma-buf base) (the pointer (&+ packet 16)))
    )

  ;; first 4 quadwords are planes, then itimes
  (let ((data-ptr (the-as (pointer uint128) (-> dma-buf base))))
    ;; the "use-camera-other" flag is set to "move" entire levels,
    ;; like the rotating city below in the throne room.
    (set! (-> data-ptr 0) (-> *math-camera* plane 0 quad))
    (set! (-> data-ptr 1) (-> *math-camera* plane 1 quad))
    (set! (-> data-ptr 2) (-> *math-camera* plane 2 quad))
    (set! (-> data-ptr 3) (-> *math-camera* plane 3 quad))
    ;; (set! (-> data-ptr 4) (-> lev mood-context itimes 0 quad))
    ;; (set! (-> data-ptr 5) (-> lev mood-context itimes 1 quad))
    ;; (set! (-> data-ptr 6) (-> lev mood-context itimes 2 quad))
    ;; (set! (-> data-ptr 7) (-> lev mood-context itimes 3 quad))
    (set! (-> data-ptr 8) (-> *math-camera* camera-temp vector 0 quad))
    (set! (-> data-ptr 9) (-> *math-camera* camera-temp vector 1 quad))
    (set! (-> data-ptr 10) (-> *math-camera* camera-temp vector 2 quad))
    (set! (-> data-ptr 11) (-> *math-camera* camera-temp vector 3 quad))
    (set! (-> data-ptr 12) (-> *math-camera* hvdf-off quad))
    (let ((vec (-> (the (inline-array vector) data-ptr) 13)))
      (set! (-> vec x) (-> *math-camera* pfog0))
      (set! (-> vec y) (-> *math-camera* fog-min))
      (set! (-> vec z) (-> *math-camera* fog-max))
      )
    (set! (-> data-ptr 14) (-> *math-camera* trans quad))

    (set! (-> data-ptr 15) (-> *math-camera* camera-rot vector 0 quad))
    (set! (-> data-ptr 16) (-> *math-camera* camera-rot vector 1 quad))
    (set! (-> data-ptr 17) (-> *math-camera* camera-rot vector 2 quad))
    (set! (-> data-ptr 18) (-> *math-camera* camera-rot vector 3 quad))

    (set! (-> data-ptr 19) (-> *math-camera* perspective vector 0 quad))
    (set! (-> data-ptr 20) (-> *math-camera* perspective vector 1 quad))
    (set! (-> data-ptr 21) (-> *math-camera* perspective vector 2 quad))
    (set! (-> data-ptr 22) (-> *math-camera* perspective vector 3 quad))

    (charp<-string (the (pointer uint8) (&-> data-ptr 23)) (symbol->string #f))
    )
  (&+! (-> dma-buf base) (* 16 25))
  )


(defun add-pc-port-background-data ((dma-buf dma-buffer))
  "PC Port added"
  ;; loop over levels
  (dotimes (lev-idx (-> *level* length))
    (let ((lev (-> *level* draw-level lev-idx))
          (dma-start (-> dma-buf base)))
      (cond
        ((and lev (= (-> lev status) 'active))
         ;; the level is active.
         (let ((packet (the-as dma-packet (-> dma-buf base))))
           (set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 128))
           (set! (-> packet vif0) (the-as vif-tag *fog-color*))
           (set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
           (set! (-> dma-buf base) (the pointer (&+ packet 16)))
           )
         (quad-copy! (-> dma-buf base) (-> lev vis-bits) 128)
         (&+! (-> dma-buf base) (* 16 128))
         )
        (else
          (let ((packet (the-as dma-packet (-> dma-buf base))))
            (set! (-> packet dma) (new 'static 'dma-tag :id (dma-tag-id cnt) :qwc 1))
            (set! (-> packet vif0) (the-as vif-tag *fog-color*))
            (set! (-> packet vif1) (new 'static 'vif-tag :cmd (vif-cmd pc-port)))
            (set! (-> dma-buf base) (the pointer (&+ packet 16)))
            )
          (set! (-> (the (pointer uint128) (-> dma-buf base))) (the uint128 0))
          (&+! (-> dma-buf base) (* 16 1))
          )
        )


      (let ((a3-3 (-> dma-buf base)))
        (let ((v1-38 (the-as object (-> dma-buf base))))
          (set! (-> (the-as dma-packet v1-38) dma) (new 'static 'dma-tag :id (dma-tag-id next)))
          (set! (-> (the-as dma-packet v1-38) vif0) (new 'static 'vif-tag))
          (set! (-> (the-as dma-packet v1-38) vif1) (new 'static 'vif-tag))
          (set! (-> dma-buf base) (&+ (the-as pointer v1-38) 16))
          )
        (dma-bucket-insert-tag (-> *display* frames (-> *display* on-screen) bucket-group)
                               (bucket-id bucket-2)
                               dma-start
                               (the-as (pointer dma-tag) a3-3)
                               )
        )
      )
    )
  (let* ((dma-buff (-> *display* frames (-> *display* on-screen) global-buf))
         (dma-start (-> dma-buff base)))
    (add-pc-camera-data dma-buff)
    (let ((a3-22 (-> dma-buff base)))
      (let ((v1-57 (the-as object (-> dma-buff 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! (-> dma-buff base) (&+ (the-as pointer v1-57) 16))
        )
      (dma-bucket-insert-tag
        (-> *display* frames (-> *display* on-screen) bucket-group)
        (bucket-id bucket-2)
        dma-start
        (the-as (pointer dma-tag) a3-22)
        )
      )
    )
  (the-as pointer 0)
  )

(defun finish-background ()
  "Main function for drawing the background (wind, shrub, tie, tfrag)"

  (#when PC_PORT
    (add-pc-port-background-data
      (-> *display* frames (-> *display* on-screen) global-buf)
      )
    )

  (if (-> *blit-displays-work* menu-mode)
      (return #f)
      )

  ;; update wind!
  (when (not (paused?))
    (flush-cache 0)
    (with-profiler 'wind *profile-particles-color*
      (dotimes (gp-1 (-> *level* length))
        (let ((v1-28 (-> *level* level gp-1)))
          (when (= (-> v1-28 status) 'active)
            (-> v1-28 bsp wind-array-length)
            (if (nonzero? (-> v1-28 bsp wind-array-length))
                (when (nonzero? level-update-wind) (level-update-wind *wind-work*)) ;; added nonzero check
                )
            )
          )
        )
      )
    )

  ;; start VU0 upload for background.
  (background-upload-vu0)
  (dotimes (v1-51 (-> *level* length))
    (let ((a0-23 (-> *level* level v1-51)))
      (when (= (-> a0-23 status) 'active)
        (let ((a0-24 (-> a0-23 bsp)))
          (when (nonzero? (-> a0-24 tfrag-masks))
            (dotimes (a1-9 (-> a0-24 tfrag-masks length))
              (set! (-> a0-24 tfrag-closest a1-9) 4095996000.0)
              )
            )
          (when (nonzero? (-> a0-24 shrub-masks))
            (dotimes (a1-14 (-> a0-24 shrub-masks length))
              (set! (-> a0-24 shrub-closest a1-14) 4095996000.0)
              )
            )
          (when (nonzero? (-> a0-24 alpha-masks))
            (dotimes (a1-19 (-> a0-24 alpha-masks length))
              (set! (-> a0-24 alpha-closest a1-19) 4095996000.0)
              )
            )
          (when (nonzero? (-> a0-24 water-masks))
            (dotimes (a1-24 (-> a0-24 water-masks length))
              (set! (-> a0-24 water-closest a1-24) 4095996000.0)
              )
            )
          )
        )
      )
    )


  (when (nonzero? (-> *background-work* shrub-tree-count))
    (with-profiler 'instance-shrubbery *profile-instance-shrubbery-color*
      (dotimes (gp-4 (-> *background-work* shrub-tree-count))
        (set! *draw-index* (-> *background-work* shrub-levels gp-4 draw-index))
        (flush-cache 0)
        (let ((s5-3 (-> *background-work* shrub-trees gp-4))
              (s4-3 (-> *background-work* shrub-levels gp-4))
              )
          ; (if (nonzero? (-> s5-3 colors-added))
          ;     (time-of-day-interp-colors
          ;       (-> *instance-shrub-work* colors)
          ;       (the-as uint (-> s5-3 colors-added))
          ;       (-> s4-3 mood-context)
          ;       )
          ;     )
          (set-background-regs! s4-3)
          (set-shrub-quard-planes! s4-3)
          (draw-drawable-tree-instance-shrub s5-3 s4-3)
          )
        )
      )
    )

  (let ((gp-6 (the-as level #f)))
    (when (or (nonzero? (-> *background-work* tfrag-tree-count))
              (nonzero? (-> *background-work* tfrag-trans-tree-count))
              (nonzero? (-> *background-work* tfrag-water-tree-count))
              )
      (let ((s5-7 (max (max (-> *background-work* tfrag-tree-count) (-> *background-work* tfrag-trans-tree-count))
                       (-> *background-work* tfrag-water-tree-count)
                       )
                  )
            (s4-5 (the-as time-of-day-palette #f))
            )

        (with-profiler 'tfrag *profile-tfrag-color*
          (dotimes (s3-3 s5-7)
            (let ((s2-1 (-> *background-work* tfrag-trees s3-3)))
              (when s2-1
                (let ((s1-1 (-> *background-work* tfrag-levels s3-3)))
                  (let ((a2-23 (-> s1-1 bsp))
                        (s0-1 (-> s2-1 time-of-day-pal))
                        )
                    (upload-vis-bits s1-1 gp-6 a2-23)
                    (when (not (or (zero? s0-1) (= s4-5 s0-1)))
                      (flush-cache 0)
                      ;; (time-of-day-interp-colors-scratch (the-as (pointer rgba) (+ 6144 #x70000000)) s0-1 (-> s1-1 mood-context))
                      (set! s4-5 s0-1)
                      )
                    )
                  (set! *draw-index* (-> s1-1 draw-index))
                  (set! (-> *tfrag-work* min-dist z) 4095996000.0)
                  (set-background-regs! s1-1)
                  )
                (draw-drawable-tree-tfrag s2-1)
                (set! (-> *level* draw-level *draw-index* closest-object) (-> *tfrag-work* min-dist z))
                )
              )
            (let ((s2-2 (-> *background-work* tfrag-trans-trees s3-3)))
              (when s2-2
                (let ((s1-2 (-> *background-work* tfrag-trans-levels s3-3)))
                  (let ((a2-25 (-> s1-2 bsp))
                        (s0-2 (-> s2-2 time-of-day-pal))
                        )
                    (upload-vis-bits s1-2 gp-6 a2-25)
                    (when (not (or (zero? s0-2) (= s4-5 s0-2)))
                      (flush-cache 0)
                      ;; (time-of-day-interp-colors-scratch (the-as (pointer rgba) (+ 6144 #x70000000)) s0-2 (-> s1-2 mood-context))
                      (set! s4-5 s0-2)
                      )
                    )
                  (set! *draw-index* (-> s1-2 draw-index))
                  (set! (-> *tfrag-work* min-dist z) 4095996000.0)
                  (set-background-regs! s1-2)
                  )
                (draw-drawable-tree-tfrag-trans s2-2)
                (set! (-> *level* draw-level *draw-index* closest-object-array 3) (-> *tfrag-work* min-dist z))
                )
              )
            (let ((s2-3 (-> *background-work* tfrag-water-trees s3-3)))
              (when s2-3
                (let ((s1-3 (-> *background-work* tfrag-water-levels s3-3)))
                  (let ((a2-27 (-> s1-3 bsp))
                        (s0-3 (-> s2-3 time-of-day-pal))
                        )
                    (upload-vis-bits s1-3 gp-6 a2-27)
                    (when (not (or (zero? s0-3) (= s4-5 s0-3)))
                      (flush-cache 0)
                      ;; (time-of-day-interp-colors-scratch (the-as (pointer rgba) (+ 6144 #x70000000)) s0-3 (-> s1-3 mood-context))
                      (set! s4-5 s0-3)
                      )
                    )
                  (set! *draw-index* (-> s1-3 draw-index))
                  (set! (-> *tfrag-work* min-dist z) 4095996000.0)
                  (set-background-regs! s1-3)
                  )
                (draw-drawable-tree-tfrag-water s2-3)
                (set! (-> *level* draw-level *draw-index* closest-object-array 4) (-> *tfrag-work* min-dist z))
                )
              )
            )
          )
        )
      )

    (when (nonzero? (-> *background-work* tie-tree-count))
      (set! (-> *instance-tie-work* tod-env-color quad) (-> *time-of-day-context* current-env-color quad))
      (with-profiler 'instance-tie *profile-instance-tie-color*
        (dotimes (s5-10 (-> *background-work* tie-tree-count))
          (let ((s4-8 (-> *background-work* tie-levels s5-10)))
            (let ((a2-29 (-> s4-8 bsp)))
              (when (!= s4-8 gp-6)
                (set! (-> *instance-tie-work* min-dist x) 4095996000.0)
                (upload-vis-bits s4-8 gp-6 a2-29)
                (set! gp-6 s4-8)
                )
              )
            (set! *draw-index* (-> s4-8 draw-index))
            (set! (-> *prototype-tie-work* mood) (-> s4-8 mood-context))
            (set-background-regs! s4-8)
            (set-tie-quard-planes! s4-8)
            (tie-scissor-make-perspective-matrix
              (-> *instance-tie-work* tie-scissor-perspective-matrix)
              (if (-> s4-8 info use-camera-other)
                  (-> *math-camera* camera-temp-other)
                  (-> *math-camera* camera-temp)
                  )
              )
            (draw-drawable-tree-instance-tie (-> *background-work* tie-trees s5-10) s4-8)
            )
          (set! (-> *background-work* tie-generic s5-10) (the-as basic (-> *prototype-tie-work* generic-next)))
          (set! (-> *background-work* tie-generic-trans s5-10)
                (the-as basic (-> *prototype-tie-work* generic-trans-next))
                )
          )
        )
      )
    )

  (dotimes (v1-282 (-> *level* length))
    (let ((a1-46 (-> *level* level v1-282)))
      (when (= (-> a1-46 status) 'active)
        (let ((a0-120 (-> a1-46 bsp)))
          (when (nonzero? (-> a0-120 tfrag-masks))
            (let ((a2-34 (-> a1-46 texture-mask)))
              (dotimes (a3-4 (-> a0-120 tfrag-masks length))
                (let ((f0-12 (* (-> (the-as (pointer float) (&+ (-> a0-120 tfrag-closest) (* a3-4 4))) 0)
                                (-> *math-camera* fov-correction-factor)
                                )
                             )
                      )
                  (when (!= f0-12 4095996000.0)
                    (let ((t0-8 (-> a0-120 tfrag-masks data a3-4)))
                      (dotimes (t1-2 3)
                        (when (or (= t1-2 2) (>= f0-12 (-> t0-8 data t1-2 dist)))
                          (dotimes (t2-5 3)
                            (logior!
                              (-> (&-> a2-34 0 mask data t2-5) 0)
                              (-> (the-as (pointer int32) (+ (* t2-5 4) (the-as int t0-8) (* t1-2 16))) 0)
                              )
                            )
                          (goto cfg-158)
                          )
                        )
                      )
                    )
                  )
                (label cfg-158)
                )
              )
            )
          (when (nonzero? (-> a0-120 shrub-masks))
            (let ((a2-39 (-> a1-46 texture-mask 2)))
              (dotimes (a3-5 (-> a0-120 shrub-masks length))
                (let ((f0-14 (* (-> (the-as (pointer float) (&+ (-> a0-120 shrub-closest) (* a3-5 4))) 0)
                                (-> *math-camera* fov-correction-factor)
                                )
                             )
                      )
                  (when (!= f0-14 4095996000.0)
                    (let ((t0-24 (-> a0-120 shrub-masks data a3-5)))
                      (dotimes (t1-5 3)
                        (when (or (= t1-5 2) (>= f0-14 (-> t0-24 data t1-5 dist)))
                          (dotimes (t2-11 3)
                            (logior!
                              (-> a2-39 mask data t2-11)
                              (-> (the-as (pointer int32) (+ (* t2-11 4) (the-as int t0-24) (* t1-5 16))) 0)
                              )
                            )
                          (goto cfg-178)
                          )
                        )
                      )
                    )
                  )
                (label cfg-178)
                )
              )
            )
          (when (nonzero? (-> a0-120 alpha-masks))
            (let ((a2-44 (-> a1-46 texture-mask 3)))
              (dotimes (a3-6 (-> a0-120 alpha-masks length))
                (let ((f0-16 (* (-> (the-as (pointer float) (&+ (-> a0-120 alpha-closest) (* a3-6 4))) 0)
                                (-> *math-camera* fov-correction-factor)
                                )
                             )
                      )
                  (when (!= f0-16 4095996000.0)
                    (let ((t0-40 (-> a0-120 alpha-masks data a3-6)))
                      (dotimes (t1-8 3)
                        (when (or (= t1-8 2) (>= f0-16 (-> t0-40 data t1-8 dist)))
                          (dotimes (t2-17 3)
                            (logior!
                              (-> a2-44 mask data t2-17)
                              (-> (the-as (pointer int32) (+ (* t2-17 4) (the-as int t0-40) (* t1-8 16))) 0)
                              )
                            )
                          (goto cfg-198)
                          )
                        )
                      )
                    )
                  )
                (label cfg-198)
                )
              )
            )
          (when (nonzero? (-> a0-120 water-masks))
            (let ((a1-47 (-> a1-46 texture-mask 4)))
              (dotimes (a2-49 (-> a0-120 water-masks length))
                (let ((f0-18 (* (-> (the-as (pointer float) (&+ (-> a0-120 water-closest) (* a2-49 4))) 0)
                                (-> *math-camera* fov-correction-factor)
                                )
                             )
                      )
                  (when (!= f0-18 4095996000.0)
                    (let ((a3-15 (-> a0-120 water-masks data a2-49)))
                      (dotimes (t0-50 3)
                        (when (or (= t0-50 2) (>= f0-18 (-> a3-15 data t0-50 dist)))
                          (dotimes (t1-14 3)
                            (logior!
                              (-> a1-47 mask data t1-14)
                              (-> (the-as (pointer int32) (+ (* t1-14 4) (the-as int a3-15) (* t0-50 16))) 0)
                              )
                            )
                          (goto cfg-218)
                          )
                        )
                      )
                    )
                  )
                (label cfg-218)
                )
              )
            )
          )
        )
      )
    )
  0
  (none)
  )
