Files
Hat Kid 93afb02cf4 decomp3: spawn target, add merc and particle buckets and some temporary hacks (#3445)
This includes all the collision stuff needed to spawn `target`,
decompiles the sparticle code and adds some of the PC hacks needed for
merc to run (it doesn't work quite right and looks bad, likely due to a
combination of code copied from Jak 2 and the time of day hacks).

There are a bunch of temporary hacks (see commits) in place to prevent
the game from crashing quite as much, but it is still extremely prone to
doing so due to lots of missing functions/potentially bad decomp.

---------

Co-authored-by: water <awaterford111445@gmail.com>
2024-04-05 00:07:39 -04:00

238 lines
8.5 KiB
Scheme

;;-*-Lisp-*-
;; TODO extract most of this into a common lib that isn't so game dependent
;;;;;;;;;;;;;;;;;;;;;;;
;; Build system macros
;;;;;;;;;;;;;;;;;;;;;;;
(defun gc-file->o-file (filename)
"Get the name of the object file for the given GOAL (*.gc) source file."
(string-append "$OUT/obj/" (stem filename) ".o")
)
(defmacro goal-src (src-file &rest deps)
"Add a GOAL source file with the given dependencies"
`(let ((output-file ,(gc-file->o-file src-file)))
(set! *all-gc* (cons output-file *all-gc*))
(defstep :in ,(string-append "goal_src/jak3/" src-file)
;; use goal compiler
:tool 'goalc
;; will output the obj file
:out (list output-file)
;; dependencies are the obj files
:dep '(,@(apply gc-file->o-file deps))
)
)
)
(defun make-src-sequence-elt (current previous prefix)
"Helper for goal-src-sequence"
`(let ((output-file ,(gc-file->o-file current)))
(set! *all-gc* (cons output-file *all-gc*))
(defstep :in ,(string-append "goal_src/jak3/" prefix current)
:tool 'goalc
:out (list output-file)
:dep '(,(gc-file->o-file previous))
)
)
)
(defun make-src-sequence-elt-jak1 (current previous prefix)
"Helper for goal-src-sequence"
`(let ((output-file ,(gc-file->o-file current)))
(set! *all-gc* (cons output-file *all-gc*))
(defstep :in ,(string-append "goal_src/jak1/" prefix current)
:tool 'goalc
:out (list output-file)
:dep '(,(gc-file->o-file previous))
)
)
)
;; TODO - deps should probably just treated as a proper list to refactor duplication
(defmacro goal-src-sequence (prefix &key (deps '()) &rest sequence)
"Add a sequence of GOAL files (each depending on the previous) in the given directory,
with all depending on the given deps."
(let* ((first-thing `(goal-src ,(string-append prefix (first sequence)) ,@deps))
(result (cons first-thing '()))
(iter result))
(let ((prev (first sequence))
(in-iter (rest sequence)))
(while (not (null? in-iter))
;; (fmt #t "{} dep on {}\n" (first in-iter) prev)
(let* ((cur-src-file (first in-iter))
;; grotesque temp hack
(next (if (or (eq? "pc/pckernel-h.gc" cur-src-file)
(eq? "pc/pckernel-common.gc" cur-src-file)
(eq? "pc/debug/pc-debug-common.gc" cur-src-file))
(make-src-sequence-elt-jak1 cur-src-file prev prefix)
(make-src-sequence-elt cur-src-file prev prefix))))
(set-cdr! iter (cons next '()))
(set! iter (cdr iter))
)
(set! prev (car in-iter))
(set! in-iter (cdr in-iter))
)
)
`(begin ,@result)
)
)
(defun cgo (output-name desc-file-name)
"Add a CGO with the given output name (in $OUT/iso) and input name (in goal_src/jak3/dgos)"
(let ((out-name (string-append "$OUT/iso/" output-name)))
(defstep :in (string-append "goal_src/jak3/dgos/" desc-file-name)
:tool 'dgo
:out `(,out-name)
)
(set! *all-cgos* (cons out-name *all-cgos*))
)
)
(defun tpage-name (id)
"Get the name of the tpage obj file with the given id"
(fmt #f "tpage-{}.go" id)
)
(defmacro copy-texture (tpage-id)
"Copy a texture from the game, using the given tpage ID"
(let* ((path (string-append "$DECOMP/raw_obj/" (tpage-name tpage-id))))
`(defstep :in ,path
:tool 'copy
:out '(,(string-append "$OUT/obj/" (tpage-name tpage-id))))))
(defmacro copy-textures (&rest ids)
`(begin
,@(apply (lambda (x) `(copy-texture ,x)) ids)
)
)
(defmacro copy-obj (name)
(let* ((path (string-append "$DECOMP/raw_obj/" name)))
`(defstep :in ,path
:tool 'copy
:out '(,(string-append "$OUT/obj/" name)))))
(defmacro copy-objs (&rest gos)
`(begin
,@(apply (lambda (x) `(copy-obj ,x)) gos)
)
)
(defmacro group (name &rest stuff)
`(defstep :in ""
:tool 'group
:out '(,(string-append "GROUP:" name))
:dep '(,@stuff))
)
(defun group-list (name stuff)
(defstep :in ""
:tool 'group
:out `(,(string-append "GROUP:" name))
:dep stuff)
)
(defun copy-iso-file (name subdir ext)
(let* ((path (string-append "$ISO/" subdir name ext))
(out-name (string-append "$OUT/iso/" name ext)))
(defstep :in path
:tool 'copy
:out `(,out-name))
out-name))
(defmacro copy-strs (&rest strs)
`(begin ,@(apply (lambda (x) `(set! *all-str* (cons (copy-iso-file ,x "STR/" ".STR") *all-str*))) strs)))
(defmacro copy-sbk-files (&rest files)
`(begin ,@(apply (lambda (x) `(set! *all-sbk* (cons (copy-iso-file ,x "SBK/" ".SBK") *all-sbk*))) files)))
(defmacro copy-mus-files (&rest files)
`(begin ,@(apply (lambda (x) `(set! *all-mus* (cons (copy-iso-file ,x "MUS/" ".MUS") *all-mus*))) files)))
(defmacro copy-vag-files (&rest files)
`(begin ,@(apply (lambda (x) `(set! *all-vag* (cons (copy-iso-file "VAGWAD" "VAG/" (string-append "." ,x)) *all-vag*))) files)))
(defun reverse-list (list)
(let ((new-list '())
(curr-elt list))
(while (not (null? curr-elt))
(set! new-list (cons (car curr-elt) new-list))
(set! curr-elt (cdr curr-elt)))
new-list))
(defmacro cgo-file (dgo-file-name deps &key (bsp-file-name #f))
;; First read in the DGO file, it has pretty much everything we need
(let ((dgo-data (car (read-data-file (string-append "goal_src/jak3/dgos/" dgo-file-name)))))
;; Get the name of the DGO
(let ((dgo-name (car dgo-data))
(files (cadr dgo-data))
(gsrc-seq-args '())
(textures '())
(objs '()))
;; create the dgo step
(cgo dgo-name dgo-file-name)
;; Now we iterate through the list of files, skipping ones we've already processed
;; and creating steps for the ones that are new!
(while (not (null? files))
(let ((file-name (car files)))
;; Check to see if we've already handled this file
(when (not (car (hash-table-try-ref *file-entry-map* file-name)))
;; Depending on the type of file, generate the appropriate steps
(cond
((and (string-ends-with? file-name ".o")
(neq? file-name bsp-file-name)
)
;; build up a list of all gsrc files needing to be compiled
(let ((base-name (symbol->string (first (string-split file-name ".")))))
(cond
;; hardcoded cases to grab from jak1... really dont want to copy-paste these all the time!
((or (eq? base-name "pckernel-h")
(eq? base-name "pckernel-common")
(eq? base-name "pc-debug-common"))
(let ((old-path (get-gsrc-folder))
(gsrc-path (begin (set-gsrc-folder! "goal_src/jak1")
(get-gsrc-path base-name))))
(set! gsrc-seq-args (cons gsrc-path gsrc-seq-args))
(set-gsrc-folder! old-path)
)
)
(#t
(let ((gsrc-path (get-gsrc-path base-name)))
(set! gsrc-seq-args (cons gsrc-path gsrc-seq-args)))
)
))
)
((string-starts-with? file-name "tpage-")
;; copy textures
(let ((tpage-id (second (string-split (symbol->string (first (string-split file-name "."))) "-"))))
(set! textures (cons tpage-id textures))))
((or (string-ends-with? file-name ".go")
(eq? file-name bsp-file-name)
)
;; copy art files
(set! objs (cons file-name objs))))
;; Update the map so this file isn't processed again
(hash-table-set! *file-entry-map* file-name #f)))
(set! files (cdr files)))
;; TODO - need an `append`!, reverse lists by re-cons'ing them for now
(set! gsrc-seq-args (reverse-list gsrc-seq-args))
(set! textures (reverse-list textures))
(set! objs (reverse-list objs))
`(begin
;; macros can't return nothing, so these macros assume they will be given a non-empty list
(when (not (null? '(,@gsrc-seq-args)))
(goal-src-sequence "" :deps ,(eval deps) ,@gsrc-seq-args))
(when (not (null? '(,@textures)))
(copy-textures ,@textures))
(when (not (null? '(,@objs)))
(copy-objs ,@objs)))
)
))