;;-*-Lisp-*-
(in-package goal)
(bundles "ENGINE.CGO" "GAME.CGO")
(require "engine/draw/drawable-h.gc")

;; Each level has a bsp file. There is a bsp-header, and a list of bsp-nodes.
;; The bsp-nodes make up a tree.  Each node has a plane and two child nodes.
;; The bsp-header also contains (or references) all of the static level information.
;; The file containing the bsp-header is called the "bt" and is loaded in a special
;; way because that allows it to use all of the remaining level heap memory.
;; This file is very large (>8 MB), and always the last file in a level DGO.
;; The bsp file also contains all the drawable trees and lots of other level data,
;; so the "bsp-header" name isn't very accurate.

;; Typically, the "bsp" refers to the static level data, and the "level" to the runtime level info.

;; In the game, all of these bsp-header files have -vis after their name
;; I believe this means that this is a version of a level that has an associated vis file
;; for precomputed visibility.

(declare-type entity-camera basic)

;; flags: 1 = load
;;        2 = display

;; DECOMP BEGINS

;; a node in the bsp tree
(deftype bsp-node (structure)
  ((front       int32)
   (back        int32)
   (front-flags uint32)
   (back-flags  uint32)
   (plane       vector :inline)))

;; This is the object stored first in the level bt (-vis)
;; It is also a drawable, and drawing it will draw the level.
(deftype bsp-header (drawable)
  ((info                    file-info :overlay-at id)
   (all-visible-list        (pointer uint16))
   (visible-list-length     int32)
   (drawable-trees          drawable-tree-array)
   (pat                     pointer)
   (pat-length              int32)
   (texture-remap-table     (pointer uint64))
   (texture-remap-table-len int32)
   (texture-ids             (pointer texture-id))
   (texture-page-count      int32)
   (unk-zero-0              basic)
   (name                    symbol)
   (nickname                symbol)
   (vis-info                level-vis-info 8)
   (actors                  drawable-inline-array-actor)
   (cameras                 (array entity-camera))
   (nodes                   (inline-array bsp-node))
   (level                   level)
   (current-leaf-idx        uint16)
   (unk-data-2              uint16 9)
   (boxes                   box8s-array)
   (current-bsp-back-flags  uint32)
   (ambients                drawable-inline-array-ambient)
   (unk-data-4              float)
   (unk-data-5              float)
   (adgifs                  adgif-shader-array)
   (actor-birth-order       (pointer uint32))
   (split-box-indices       (pointer uint16))
   (unk-data-8              uint32 55))
  (:methods
   (relocate (_type_ kheap (pointer uint8)) none :replace)
   (birth (_type_) none)
   (deactivate-entities (_type_) none)))

;; seems to be unused?
;; In practice, a normal bsp-header is a game-level.
(deftype game-level (basic)
  ((master-bsp basic)))

(deftype view-frustum (structure)
  ((hither-top-left     vector :inline)
   (hither-top-right    vector :inline)
   (hither-bottom-left  vector :inline)
   (hither-bottom-right vector :inline)
   (yon-top-left        vector :inline)
   (yon-top-right       vector :inline)
   (yon-bottom-left     vector :inline)
   (yon-bottom-right    vector :inline)))

(defun-debug-recursive inspect-bsp-tree none ((arg0 bsp-header) (arg1 bsp-node))
  "Recursively print all nodes in a bsp tree. This makes a huge mess"
  (cond
    ((zero? arg1))
    (else
     (format #t "_#x~X________________~%" arg1)
     (inspect arg1)
     (let ((s4-0 *print-column*))
       (set! *print-column* (+ *print-column* 64))
       (if (> (-> arg1 front) 0)
         (inspect-bsp-tree arg0 (the-as bsp-node (-> arg1 front)))
         (format #t "_#x~X________________~%" arg1))
       (if (> (-> arg1 back) 0) (inspect-bsp-tree arg0 (the-as bsp-node (-> arg1 back))) (format #t "_#x~X________________~%" arg1))
       (set! *print-column* s4-0))))
  (none))

(defun-recursive map-bsp-tree none ((arg0 (function bsp-node none)) (arg1 bsp-header) (arg2 bsp-node))
  "Recursively apply arg0 to all nodes in the bsp tree"
  (cond
    ((zero? arg2))
    (else
     (if (> (-> arg2 front) 0) (map-bsp-tree arg0 arg1 (the-as bsp-node (-> arg2 front))) (arg0 arg2))
     (if (> (-> arg2 back) 0) (map-bsp-tree arg0 arg1 (the-as bsp-node (-> arg2 back))) (arg0 arg2))))
  (none))

(deftype cl-stat (structure)
  ((fragments uint32)
   (tris      uint32)
   (output    uint32))
  :pack-me)

(deftype collide-stats (structure)
  ((other             cl-stat :inline)
   (total             cl-stat :inline)
   (nodes             uint32)
   (calls             uint32)
   (total-target      stopwatch :inline)
   (target-cache-fill stopwatch :inline)
   (target-ray-poly   stopwatch :inline)
   (pad               uint32)))

;; offsets of stuff in the scratchpad during bsp draw.
(defconstant TERRAIN_BSP_SCRATCHPAD #x0)

(defconstant VISIBLE_LIST_SCRATCHPAD #x38b0)

;; TODO - for cam-update
(define-extern bsp-camera-asm (function bsp-header vector none))
