mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
90 lines
3.5 KiB
Common Lisp
90 lines
3.5 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
|
|
;; name: dma-bucket.gc
|
|
;; name in dgo: dma-bucket
|
|
;; dgos: GAME, ENGINE
|
|
|
|
;; A dma-bucket is used to organize dma data.
|
|
;; When an object is drawn, it may add data to multiple buckets.
|
|
;; When the dma data is transferred, it is transferred bucket by bucket.
|
|
|
|
;; A dma-bucket is a 16 byte thing that lives in the dma-buffer.
|
|
;; buckets live consecutively in the dma-buffer, and can mark the start of a DMA chain
|
|
;; location anywhere.
|
|
|
|
;; The bucket doesn't own the data, but rather is a beginning of a linked list of DMA data associated with that bucket
|
|
;; that's stored somewhere else.
|
|
|
|
;; At the end, all the buckets are spliced together.
|
|
|
|
;; The typical process is:
|
|
;; - empty buckets are allocated with add-buckets
|
|
;; - tags are put somewhere and added to the appropriate bucket with insert-tag, updating last as needed.
|
|
;; - buckets are patched to link to each other with dma-buffer-patch-buckets.
|
|
|
|
;; the idea here is that you can build the buckets in whatever order you want, but the buckets
|
|
;; will be DMAd in the bucket allocation order.
|
|
|
|
;; Each bucket contains:
|
|
;; a tag, (64-bits), to point to the chain of the bucket
|
|
;; last, a pointer to the last tag of this bucket, so that the bucket can be patched to point to the next.
|
|
|
|
(defun dma-buffer-add-buckets ((dma-buf dma-buffer) (count int))
|
|
"Add count buckets. Each bucket is initialized as empty and won't transfer anything."
|
|
(let* ((initial-bucket (the-as dma-bucket (-> dma-buf base)))
|
|
(current-bucket initial-bucket))
|
|
|
|
;;(let ((current-bucket (the-as dma-bucket (-> dma-buf base))))
|
|
(dotimes (i count)
|
|
;; set the DMA tag to next, with a qwc of zero.
|
|
;; the address is set to the next bucket.
|
|
;; By default, this will do no transfer and just move on in the dma-buf.
|
|
;; Data will be added to the bucket later.
|
|
(set! (-> current-bucket tag)
|
|
(new 'static 'dma-tag
|
|
:id (dma-tag-id next)
|
|
:addr (the-as int (&+ (the-as pointer current-bucket) 16))
|
|
)
|
|
)
|
|
;; Set the last pointer to point to this tag (this lives in the 8 byte gap)
|
|
(set! (-> current-bucket last) (the-as (pointer dma-tag) current-bucket))
|
|
;; Advance to next bucket.
|
|
(&+! current-bucket 16)
|
|
)
|
|
;; update base ptr of dma-buffer to point after the buckets.
|
|
(set! (-> dma-buf base) (the-as pointer current-bucket))
|
|
(the (inline-array dma-bucket) initial-bucket)
|
|
)
|
|
)
|
|
|
|
(defun dma-buffer-patch-buckets ((bucket (inline-array dma-bucket)) (count int))
|
|
"After adding all data to buckets, call this to stitch together the chains for
|
|
count consecutive buckets"
|
|
(when (nonzero? bucket)
|
|
(dotimes (i count)
|
|
;; set last tag's address to the next bucket.
|
|
(set! (-> bucket 0 last 0 addr) (the-as int (the-as pointer (-> bucket 1))))
|
|
;; clear last pointer.
|
|
(set! (-> bucket 0 last) (the-as (pointer dma-tag) 0))
|
|
;; next bucket
|
|
(set! bucket (the-as (inline-array dma-bucket) (-> bucket 1)))
|
|
)
|
|
)
|
|
bucket
|
|
)
|
|
|
|
(defun dma-bucket-insert-tag ((base (inline-array dma-bucket)) (idx bucket-id) (tag-start pointer) (tag-end (pointer dma-tag)))
|
|
"Add a DMA chain to the bucket"
|
|
;; find the bucket
|
|
(let ((bucket (-> base idx)))
|
|
;; update our last bucket to point to this one.
|
|
;; this is abusing the dma-bucket type to set the "addr" field of the dma-tag.
|
|
(set! (-> (the-as dma-bucket (-> bucket last)) next) (the-as uint tag-start))
|
|
;; remember this as the last tag in the bucket.
|
|
(set! (-> bucket last) tag-end)
|
|
)
|
|
tag-start
|
|
)
|
|
|