jak-project/goal_src/jak2/engine/game/main.gc

1188 lines
44 KiB
Common Lisp
Raw Normal View History

;;-*-Lisp-*-
(in-package goal)
;; name: main.gc
;; name in dgo: main
;; dgos: ENGINE, GAME
;; DECOMP BEGINS
(defun set-letterbox-frames ((arg0 time-frame))
"Set the remaining time until letterboxing is removed.
This uses the current clock ratio of the process and the game-clock.
This overrides any previous letterboxing."
(with-pp
(set! (-> *game-info* letterbox-time)
(+ (-> *display* base-clock frame-counter)
(the int (/ (* (the float arg0) (-> *display* game-clock clock-ratio)) (-> pp clock clock-ratio)))
)
)
(none)
)
)
(defun letterbox ()
"Draw letterbox bars."
(with-dma-buffer-add-bucket ((dma-buf (-> (current-frame) global-buf))
(bucket-id screen-filter))
(#cond
((not PC_PORT)
(draw-sprite2d-xy-absolute dma-buf 0 0 512 46 (new 'static 'rgba :a #x80))
(draw-sprite2d-xy-absolute dma-buf 0 370 512 47 (new 'static 'rgba :a #x80))
)
(#t
(if (-> *pc-settings* use-vis?)
;; original game mode. dont do anything.
(begin
(draw-sprite2d-xy-absolute dma-buf 0 0 512 46 (new 'static 'rgba :a #x80))
(draw-sprite2d-xy-absolute dma-buf 0 370 512 47 (new 'static 'rgba :a #x80)))
;; native mode. force 16x9 letterboxing always.
(begin
(cond
((< (-> *pc-settings* aspect-ratio) ASPECT_16X9)
;; too tall. needs vertical letterboxing.
(let ((lbx-h (the int (* 208.0 (- 1.0 (/ (-> *pc-settings* aspect-ratio) ASPECT_16X9))))))
;(format 0 "using new letterbox! size: ~D~%" lbx-h)
(draw-sprite2d-xy dma-buf 0 0 512 lbx-h (new 'static 'rgba :a #x80))
(draw-sprite2d-xy dma-buf 0 (- 416 lbx-h) 512 lbx-h (new 'static 'rgba :a #x80))
)
)
((> (-> *pc-settings* aspect-ratio) ASPECT_16X9)
;; too wide. needs horizontal letterboxing.
(let ((lbx-w (the int (* 256.0 (- 1.0 (/ ASPECT_16X9 (-> *pc-settings* aspect-ratio)))))))
;(format 0 "using new pillarbox! size: ~D~%" lbx-w)
(draw-sprite2d-xy dma-buf 0 0 lbx-w 416 (new 'static 'rgba :a #x80))
(draw-sprite2d-xy dma-buf (- 512 lbx-w) 0 lbx-w 416 (new 'static 'rgba :a #x80))
)
)
)
)
)
)
)
)
(none)
)
(defun set-blackout-frames ((arg0 time-frame))
"Set the remaining time until blackout is removed.
Unlike letterbox, this only can increase the time, unless
you request 0, in which case blackout is disabled immediately"
(with-pp
(if (zero? arg0)
(set! (-> *game-info* blackout-time) (-> *display* base-clock frame-counter))
(set! (-> *game-info* blackout-time)
(the-as time-frame
(max (-> *game-info* blackout-time)
(+ (-> *display* base-clock frame-counter)
(the int (/ (* (the float arg0) (-> *display* game-clock clock-ratio)) (-> pp clock clock-ratio)))
arg0
)
)
)
)
)
(none)
)
)
(defun blackout ()
"Draw blackout over the whole screen.
This isn't used - instead they adjust some GS setting to fade the whole
screen to black, which is much faster than drawing over the entire screen."
(with-dma-buffer-add-bucket ((s5-0 (-> *display* frames (-> *display* on-screen) global-buf))
(bucket-id debug-no-zbuf2)
)
(draw-sprite2d-xy-absolute s5-0 0 0 512 416 (new 'static 'rgba :a #x80))
)
(none)
)
(defun paused? ()
"Are we paused, or in some menu that should make us pause?"
(or (= *master-mode* 'pause) (= *master-mode* 'progress) (= *master-mode* 'menu) (= *master-mode* 'freeze))
)
(defun movie? ()
"Are we in a movie?"
(logtest? (-> *kernel-context* prevent-from-run) (process-mask movie))
)
(defun demo? ()
"Are we a demo version?"
(or (= *kernel-boot-message* 'demo) (= *kernel-boot-message* 'demo-shared))
)
;; the "master-mode" is a single "mode" for the game:
;; - 'game: normal play
;; - 'pause: select pause (with PAUSE on screen)
;; - 'freeze: a pause, but without PAUSE on screen
;; - 'menu: debug menu system open
;; - 'progress: progress menu open (start menu)
(define *last-master-mode* 'game)
(defun set-master-mode ((arg0 symbol))
"Change the master mode, updating pause masks in the kernel/sound system as needed."
(when (!= arg0 *master-mode*)
(set! *last-master-mode* *master-mode*)
(set! *master-mode* arg0)
;; transition stuff:
(case *master-mode*
(('pause)
;; entering pause, set pause bit in masks
(if (not *debug-pause*)
(logior! (-> *setting-control* user-default process-mask) (process-mask pause))
)
(logclear! (-> *setting-control* user-default process-mask) (process-mask freeze menu))
(set! *pause-lock* #f)
(sound-group-pause (sound-group sfx music dialog sog3 ambient dialog2 sog6 sog7))
(set! (-> *game-info* pause-start-time) (-> *display* real-clock frame-counter))
)
(('freeze)
(logior! (-> *setting-control* user-default process-mask) (process-mask freeze))
(logclear! (-> *setting-control* user-default process-mask) (process-mask pause menu))
(sound-group-pause (sound-group sfx ambient))
(set! (-> *game-info* pause-start-time) (-> *display* real-clock frame-counter))
)
(('menu)
(logior! (-> *setting-control* user-default process-mask) (process-mask menu))
(logclear! (-> *setting-control* user-default process-mask) (process-mask freeze pause progress))
(sound-group-pause (sound-group sfx music dialog sog3 ambient dialog2 sog6 sog7))
(set! *pause-lock* #f)
)
(('progress)
;; entering progress, start the process
(logclear! (-> *setting-control* user-default process-mask) (process-mask freeze pause menu))
(sound-group-pause (sound-group sfx music dialog sog3 ambient dialog2 sog6 sog7))
(when (not *progress-process*)
(activate-progress *dproc* 'main)
(if (not *progress-process*) ;; process didn't start, back to game.
(set-master-mode 'game)
)
)
(set! (-> *game-info* pause-start-time) (-> *display* real-clock frame-counter))
)
(('game)
(logclear! (-> *setting-control* user-default process-mask) (process-mask freeze pause menu))
(sound-group-continue (sound-group sfx music dialog sog3 ambient dialog2 sog6 sog7))
)
)
;; update from setting-control to kernel
(apply-settings *setting-control*)
)
;; tell the debug menu system we changed modes.
(if *debug-segment*
(menu-respond-to-pause)
)
0
(none)
)
(defun pause-allowed? ()
"Are you allowed to pause?"
(not (or (< (-> *display* base-clock frame-counter) (-> *game-info* blackout-time))
(!= (-> *setting-control* user-current bg-a) 0.0)
(!= (-> *setting-control* user-current bg-a-force) 0.0)
(not (-> *setting-control* user-current allow-pause))
(handle->process (-> *game-info* auto-save-proc))
(= *master-mode* 'freeze)
(not *target*)
*master-exit*
(not *common-text*)
)
)
)
(defun toggle-pause ()
"Update the current master mode because a pause has been requested.
This can reject the transition, or decide to go to any mode."
(case *master-mode*
(('game)
(set-master-mode
(cond
((and (logtest? (-> *cpad-list* cpads 0 valid) 128)
*target*
(>= (-> *display* base-clock frame-counter) (-> *game-info* blackout-time))
(= (-> *setting-control* user-current bg-a) 0.0)
(and (= (-> *setting-control* user-current bg-a-force) 0.0)
(< (seconds 1003) (-> *display* real-clock frame-counter))
)
)
;; in 'game, controller fell out, target is spawned, can pause if it's allowed, and not in progress.
(if (or *progress-process* (not (-> *setting-control* user-current allow-pause)))
*master-mode*
'pause
)
)
;; game -> debug menu when pressing select/start with L3.
((and (cpad-pressed? 0 select start) (cpad-hold? 0 l3) *debug-segment*)
'menu
)
;; select in debug pauses (also check R2 here for the frame-advance feature)
((and (or (cpad-hold? 0 select) (cpad-hold? 0 r2)) *debug-segment*)
'pause
)
;; not debugging, not pressing start, should pause if possible
((and (not *debug-segment*) (not (logtest? (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons start))))
(if (pause-allowed?)
'pause
*master-mode* ;; and if we can't, reject
)
)
;; if we can't open progress, fall back to pause
((not (progress-allowed?))
(if (pause-allowed?)
'pause
*master-mode* ;; otherwise reject
)
)
((cpad-hold? 0 start) ;; finally, if we're pressing start and pausing is impossible, open progress
'progress
)
(else
*master-mode* ;; otherwise reject
)
)
)
)
(('menu)
;; og:preserve-this Let the popup menu code handle inputs instead of the code written for the original debug menu
(when (not *popup-menu-open*)
(set-master-mode (cond
((and *debug-segment* (cpad-hold? 0 l3) (cpad-pressed? 0 select start))
'menu
)
((cpad-hold? 0 select r2)
(if *debug-segment*
'pause
*master-mode*
)
)
((cpad-hold? 0 r3 r2 triangle circle)
'game
)
((cpad-hold? 0 start)
'game
)
(else
*master-mode*
)
)
))
(set! *pause-lock* #f)
)
(('pause)
(set-master-mode (cond
((and (cpad-pressed? 0 select start) (cpad-hold? 0 l3) *debug-segment*)
'menu
)
((and (not *debug-segment*) (cpad-hold? 0 select))
'game
)
((and *cheat-mode* (cpad-hold? 0 select r2))
'game
)
((cpad-hold? 0 start)
'game
)
(else
*master-mode*
)
)
)
(set! *pause-lock* (and *cheat-mode* (cpad-hold? 0 r2)))
)
(('freeze)
(set-master-mode (if (and (cpad-pressed? 0 select start) (cpad-hold? 0 l3) *debug-segment*)
'menu
*master-mode*
)
)
)
(('progress)
(if (cpad-hold? 0 start)
(hide-progress-screen)
)
(set! *pause-lock* (and *cheat-mode* (cpad-hold? 0 r2)))
)
)
0
)
(define *screen-filter* (new 'static 'screen-filter :draw? #f :bucket (bucket-id screen-filter)))
`deftype` and `defmethod` syntax major changes (#3094) Major change to how `deftype` shows up in our code: - the decompiler will no longer emit the `offset-assert`, `method-count-assert`, `size-assert` and `flag-assert` parameters. There are extremely few cases where having this in the decompiled code is helpful, as the types there come from `all-types` which already has those parameters. This also doesn't break type consistency because: - the asserts aren't compared. - the first step of the test uses `all-types`, which has the asserts, which will throw an error if they're bad. - the decompiler won't emit the `heap-base` parameter unless necessary now. - the decompiler will try its hardest to turn a fixed-offset field into an `overlay-at` field. It falls back to the old offset if all else fails. - `overlay-at` now supports field "dereferencing" to specify the offset that's within a field that's a structure, e.g.: ```lisp (deftype foobar (structure) ((vec vector :inline) (flags int32 :overlay-at (-> vec w)) ) ) ``` in this structure, the offset of `flags` will be 12 because that is the final offset of `vec`'s `w` field within this structure. - **removed ID from all method declarations.** IDs are only ever automatically assigned now. Fixes #3068. - added an `:overlay` parameter to method declarations, in order to declare a new method that goes on top of a previously-defined method. Syntax is `:overlay <method-name>`. Please do not ever use this. - added `state-methods` list parameter. This lets you quickly specify a list of states to be put in the method table. Same syntax as the `states` list parameter. The decompiler will try to put as many states in this as it can without messing with the method ID order. Also changes `defmethod` to make the first type definition (before the arguments) optional. The type can now be inferred from the first argument. Fixes #3093. --------- Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
2023-10-29 23:20:02 -04:00
(defmethod draw ((this screen-filter))
(local-vars (v1-1 float))
(rlet ((vf0 :class vf)
(vf1 :class vf)
(vf2 :class vf)
(vf3 :class vf)
(vf4 :class vf)
)
(init-vf0-vector)
(when (not (paused?))
(.lvf vf4 (&-> this extra quad))
(.lvf vf1 (&-> this color-dest quad))
(.lvf vf2 (&-> this color quad))
(.sub.vf vf3 vf1 vf2)
(.add.x.vf vf4 vf4 vf4 :mask #b10)
(.min.w.vf vf4 vf4 vf0 :mask #b10)
(.max.y.vf vf4 vf4 vf0 :mask #b10)
(.mul.y.vf vf3 vf3 vf4)
(.add.vf vf1 vf2 vf3)
(.svf (&-> this extra quad) vf4)
(.svf (&-> this color quad) vf1)
(.mov v1-1 vf1)
)
(with-dma-buffer-add-bucket ((s4-0 (-> *display* frames (-> *display* on-screen) global-buf))
(-> this bucket)
)
(dma-buffer-add-gs-set s4-0
(test-1 (new 'static 'gs-test :ate #x1 :afail #x3 :zte #x1 :ztst (gs-ztest always)))
)
(let ((t1-0 (new 'static 'rgba
:r (the int (-> this color x))
:g (the int (-> this color y))
:b (the int (-> this color z))
:a (the int (-> this color w))
)
)
)
(draw-sprite2d-xy s4-0 -256 -208 512 416 t1-0)
)
)
0
(none)
)
)
`deftype` and `defmethod` syntax major changes (#3094) Major change to how `deftype` shows up in our code: - the decompiler will no longer emit the `offset-assert`, `method-count-assert`, `size-assert` and `flag-assert` parameters. There are extremely few cases where having this in the decompiled code is helpful, as the types there come from `all-types` which already has those parameters. This also doesn't break type consistency because: - the asserts aren't compared. - the first step of the test uses `all-types`, which has the asserts, which will throw an error if they're bad. - the decompiler won't emit the `heap-base` parameter unless necessary now. - the decompiler will try its hardest to turn a fixed-offset field into an `overlay-at` field. It falls back to the old offset if all else fails. - `overlay-at` now supports field "dereferencing" to specify the offset that's within a field that's a structure, e.g.: ```lisp (deftype foobar (structure) ((vec vector :inline) (flags int32 :overlay-at (-> vec w)) ) ) ``` in this structure, the offset of `flags` will be 12 because that is the final offset of `vec`'s `w` field within this structure. - **removed ID from all method declarations.** IDs are only ever automatically assigned now. Fixes #3068. - added an `:overlay` parameter to method declarations, in order to declare a new method that goes on top of a previously-defined method. Syntax is `:overlay <method-name>`. Please do not ever use this. - added `state-methods` list parameter. This lets you quickly specify a list of states to be put in the method table. Same syntax as the `states` list parameter. The decompiler will try to put as many states in this as it can without messing with the method ID order. Also changes `defmethod` to make the first type definition (before the arguments) optional. The type can now be inferred from the first argument. Fixes #3093. --------- Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
2023-10-29 23:20:02 -04:00
(defmethod setup ((this screen-filter) (arg0 vector) (arg1 vector) (arg2 float) (arg3 bucket-id))
(set! (-> this draw?) #t)
(set! (-> this color quad) (-> arg0 quad))
(set! (-> this color-src quad) (-> arg0 quad))
(set! (-> this color-dest quad) (-> arg1 quad))
(set! (-> this extra x) arg2)
(set! (-> this extra y) 0.0)
(set! (-> this bucket) arg3)
0
(none)
)
`deftype` and `defmethod` syntax major changes (#3094) Major change to how `deftype` shows up in our code: - the decompiler will no longer emit the `offset-assert`, `method-count-assert`, `size-assert` and `flag-assert` parameters. There are extremely few cases where having this in the decompiled code is helpful, as the types there come from `all-types` which already has those parameters. This also doesn't break type consistency because: - the asserts aren't compared. - the first step of the test uses `all-types`, which has the asserts, which will throw an error if they're bad. - the decompiler won't emit the `heap-base` parameter unless necessary now. - the decompiler will try its hardest to turn a fixed-offset field into an `overlay-at` field. It falls back to the old offset if all else fails. - `overlay-at` now supports field "dereferencing" to specify the offset that's within a field that's a structure, e.g.: ```lisp (deftype foobar (structure) ((vec vector :inline) (flags int32 :overlay-at (-> vec w)) ) ) ``` in this structure, the offset of `flags` will be 12 because that is the final offset of `vec`'s `w` field within this structure. - **removed ID from all method declarations.** IDs are only ever automatically assigned now. Fixes #3068. - added an `:overlay` parameter to method declarations, in order to declare a new method that goes on top of a previously-defined method. Syntax is `:overlay <method-name>`. Please do not ever use this. - added `state-methods` list parameter. This lets you quickly specify a list of states to be put in the method table. Same syntax as the `states` list parameter. The decompiler will try to put as many states in this as it can without messing with the method ID order. Also changes `defmethod` to make the first type definition (before the arguments) optional. The type can now be inferred from the first argument. Fixes #3093. --------- Co-authored-by: Hat Kid <6624576+Hat-Kid@users.noreply.github.com>
2023-10-29 23:20:02 -04:00
(defmethod disable ((this screen-filter))
(set! (-> this draw?) #f)
0
(none)
)
(define *cheat-temp* (the-as (pointer int32) (malloc 'global 20)))
(define *master-exit* #f)
(define *progress-cheat* #f)
(define *first-boot* #t)
(defun main-cheats ()
(when (and (cpad-hold? 0 l3) (or *cheat-mode* (not (demo?))))
((lambda ()
(check-cheat-code (-> *cheat-temp* 0) 0
(up up down down left right left right x x square circle square circle)
(cpad-clear! 0 r1)
;; toggle!
(not! *cheat-mode*)
(cheats-sound-play *cheat-mode*)
)
(when *cheat-mode*
(check-cheat-code (-> *cheat-temp* 1) 0
(circle square circle square x x right left right left down down up up)
(cpad-clear! 0 r1)
(set! *cheat-mode* (if (= *cheat-mode* 'debug)
#t
'debug
)
)
(cheats-sound-play *cheat-mode*)
)
)
(none)
)
)
((lambda ()
(case (scf-get-territory)
((GAME_TERRITORY_SCEI)
(check-cheat-code (-> *cheat-temp* 2) 0
(l1 r1 l1 r1 triangle circle x square)
(cpad-clear! 0 r1)
(set! *progress-cheat* (if *progress-cheat*
#f
'language
)
)
(cheats-sound-play *progress-cheat*)
)
)
)
(when *debug-segment*
(check-cheat-code (-> *cheat-temp* 3) 0
(x square triangle circle x square triangle circle)
(cpad-clear! 0 r1)
(set! *progress-cheat* (if *progress-cheat*
#f
'pal
)
)
(cheats-sound-play *progress-cheat*)
)
(check-cheat-code (-> *cheat-temp* 4) 1 ;; note : this erroneously uses (-> *cheat-temp* 5) in the original game
(triangle x circle square triangle x circle square)
(cpad-clear! 0 r1)
(set! *cheat-mode* (if (= *cheat-mode* 'camera)
#f
'camera
)
)
(cond
(*cheat-mode*
(if (not *external-cam-mode*)
(external-cam-reset!)
)
(set! *external-cam-mode* 'pad-1)
(sound-play-by-spec (static-sound-spec "menu-pick" :fo-curve 1) (new-sound-id) (the-as vector #t))
)
(else
(set! *external-cam-mode* #f)
(sound-play-by-spec (static-sound-spec "menu-back" :fo-curve 1) (new-sound-id) (the-as vector #t))
)
)
)
)
(none)
)
)
)
(if (and *cheat-mode* (not *debug-segment*) (cpad-hold? 1 l3))
((lambda ()
(cond
((cpad-pressed? 1 x)
(send-event *target* 'get-pickup (pickup-type ammo-yellow) 1000.0)
(send-event *target* 'get-pickup (pickup-type ammo-red) 1000.0)
(send-event *target* 'get-pickup (pickup-type ammo-blue) 1000.0)
(send-event *target* 'get-pickup (pickup-type ammo-dark) 1000.0)
(send-event *target* 'get-pickup (pickup-type eco-pill-dark) 1000.0)
(send-event *target* 'get-pickup (pickup-type skill) 1000.0)
(send-event *target* 'get-pickup (pickup-type gem) 1000.0)
(logior!
(-> *game-info* features)
(game-feature
gun
gun-yellow
gun-red
gun-blue
gun-dark
board
darkjak
darkjak-bomb0
darkjak-bomb1
darkjak-invinc
darkjak-giant
)
)
(logior!
(-> *game-info* debug-features)
(game-feature gun gun-yellow gun-red gun-blue gun-dark board darkjak)
)
(sound-play-by-spec (static-sound-spec "menu-pick" :fo-curve 1) (new-sound-id) (the-as vector #t))
)
((cpad-pressed? 1 square)
(set! (-> *level* disk-load-timing?) (not (-> *level* disk-load-timing?)))
(if (-> *level* disk-load-timing?)
(sound-play-by-spec (static-sound-spec "menu-pick" :fo-curve 1) (new-sound-id) (the-as vector #t))
(sound-play-by-spec (static-sound-spec "menu-back" :fo-curve 1) (new-sound-id) (the-as vector #t))
)
)
((cpad-pressed? 1 r1)
(set! *display-scene-control* (logxor *display-scene-control* (scene-controls bounds-spheres)))
(if (logtest? *display-scene-control* (scene-controls bounds-spheres))
(sound-play-by-spec (static-sound-spec "menu-pick" :fo-curve 1) (new-sound-id) (the-as vector #t))
(sound-play-by-spec (static-sound-spec "menu-back" :fo-curve 1) (new-sound-id) (the-as vector #t))
)
)
((cpad-pressed? 1 circle)
(set! *display-bug-report* (not *display-bug-report*))
(if *display-bug-report*
(sound-play-by-spec (static-sound-spec "menu-pick" :fo-curve 1) (new-sound-id) (the-as vector #t))
(sound-play-by-spec (static-sound-spec "menu-back" :fo-curve 1) (new-sound-id) (the-as vector #t))
)
)
)
(none)
)
)
)
(if *display-bug-report*
(position->stream *stdcon* '*stdcon* #t)
)
(when (and (= *cheat-mode* 'debug) (not *debug-segment*))
(when (and (cpad-hold? 0 l1) (cpad-hold? 0 l2) (cpad-hold? 0 r1) (cpad-pressed? 0 r2))
(if *target*
(stop 'debug)
(start 'play (get-current-continue-forced *game-info*))
)
)
(if (and (cpad-hold? 0 left) (cpad-hold? 0 up) (cpad-pressed? 0 select))
(initialize! *game-info* 'game (the-as game-save #f) "title-restart")
)
(if (cpad-pressed? 1 r3)
(inspect global)
)
(when (cpad-hold? 1 r3)
(with-dma-buffer-add-bucket ((s5-1 (if *debug-segment*
(-> *display* frames (-> *display* on-screen) debug-buf)
(-> *display* frames (-> *display* on-screen) global-buf)
)
)
(bucket-id debug2)
)
(show-iop-memory s5-1)
)
)
(if (cpad-pressed? 1 triangle)
(set! *display-level-border* (not *display-level-border*))
)
)
(when (demo?)
(let ((gp-2 (scf-get-timeout))
(v1-93 (scf-get-inactive-timeout))
)
(when (and (or (and (nonzero? gp-2)
(>= (+ -300000 (-> *display* real-clock frame-counter)) (the int (* 300.0 (the float gp-2))))
)
(and (nonzero? v1-93)
(or (and (>= (- (-> *display* base-clock frame-counter) (-> *cpad-list* cpads 0 change-time))
(the int (* 300.0 (the float v1-93)))
)
(>= (- (-> *display* game-clock frame-counter) (the-as int (-> *game-info* kiosk-timeout)))
(the int (* 300.0 (the float v1-93)))
)
)
(and (or (= *master-mode* 'pause) (= *master-mode* 'progress) (= *master-mode* 'freeze))
(>= (- (-> *display* real-clock frame-counter) (-> *game-info* pause-start-time))
(the int (* 300.0 (the float v1-93)))
)
)
)
)
(or (= *master-exit* 'force) (= *master-exit* 'movie))
)
(or *master-exit* (-> *setting-control* user-current allow-timeout))
(!= *master-exit* #t)
)
(cond
((and (= *kernel-boot-message* 'demo) (not *master-exit*))
(let ((v1-109 (level-get-target-inside *level*)))
(when (and v1-109 (!= (-> v1-109 name) 'demo) (not (logtest? (-> v1-109 info level-flags) 1)))
(persist-with-delay *setting-control* 'sfx-volume (seconds 0.5) 'sfx-volume 'abs 0.0 0)
(persist-with-delay *setting-control* 'music-volume (seconds 0.5) 'music-volume 'abs 0.0 0)
(persist-with-delay *setting-control* 'dialog-volume (seconds 0.5) 'dialog-volume 'abs 0.0 0)
(persist-with-delay *setting-control* 'ambient-volume (seconds 0.5) 'ambient-volume 'abs 0.0 0)
(set! (-> *setting-control* user-current sfx-volume) 0.01)
(set! (-> *setting-control* user-current music-volume) 0.01)
(set! (-> *setting-control* user-current dialog-volume) 0.01)
(set! (-> *setting-control* user-current ambient-volume) 0.01)
(apply-settings *setting-control*)
(set! (-> *game-info* mode) 'play)
(initialize! *game-info* 'game (the-as game-save #f) "demo-restart")
)
)
)
(else
(when (process-spawn-function
process
(lambda ((arg0 time-frame))
(set-blackout-frames (seconds 100))
(set! (-> *setting-control* user-default allow-pause) #f)
(set! (-> *setting-control* user-default allow-progress) #f)
(apply-settings *setting-control*)
(set! (-> *setting-control* user-default sfx-volume) 0.0)
(set! (-> *setting-control* user-default music-volume) 0.0)
(set! (-> *setting-control* user-default dialog-volume) 0.0)
(set! (-> *setting-control* user-default ambient-volume) 0.0)
(let ((s5-0 (current-time)))
(until (>= (- (current-time) s5-0) (seconds 0.1))
(suspend)
)
)
;; og:preserve-this
(kernel-shutdown (runtime-exit-status exit))
(none)
)
(if (= *master-exit* 'movie)
2
1
)
:to *display-pool*
)
(set! (-> *setting-control* user-default sfx-volume) 0.0)
(set! (-> *setting-control* user-default music-volume) 0.0)
(set! (-> *setting-control* user-default dialog-volume) 0.0)
(set! (-> *setting-control* user-default ambient-volume) 0.0)
(set! *master-exit* #t)
)
)
)
)
)
)
0
)
;; Rough loop outline:
;; (while *run*
;; - suspend ;; runs actors
;; - display-loop-main ;; runs the drawing/per frame updates
;; - per-frame updates for level, global effets
;; - draw-hook ;; generates DMA data
;; - sync-path ;; waits for previous frame to finish render
;; - end-display
;; - swap-display
;; - display-frame-finish
;; - display-sync
;; - display-frame-start
;; )
(defun end-display ((arg0 display))
"Update debug drawing:
- debug draws (triangles, spheres, etc)
- profile bars
- file info
- console
- other info (iop, memcard, pause)
This function runs after DMA sync.
It's not clear why they did this - in the Jak 1 PC port, it is fine to move this to before sync.
Possibly they wanted to leave the bus alone for graphics DMA."
;; DMA buffer for memory usage counting.
(let ((s5-0 (-> (if *debug-segment*
(-> arg0 frames (-> arg0 on-screen) debug-buf)
(-> arg0 frames (-> arg0 on-screen) global-buf)
)
base
)
)
)
;; debug draw, profile bars, deci count, file info
(when *debug-segment*
;; do all debug drawing.
(#when PC_PORT
(when (and (or (= *master-mode* 'game) (= *master-mode* 'pause)))
(when (-> *entity-debug-inspect* entity)
(define-extern entity-inspect-draw (function entity-debug-inspect object))
(entity-inspect-draw *entity-debug-inspect*)
)
;; go through active levels
(dotimes (lev-i (-> *level* length))
(let ((lev (-> *level* level lev-i)))
(when (= (-> lev status) 'active)
(let ((region-trees (-> lev bsp region-trees)))
(when (nonzero? region-trees)
(let* ((s3-5 (-> region-trees length))
(tree-i 0)
(region-tree (-> region-trees tree-i))
)
(while (< tree-i s3-5)
(let ((tree-name (-> region-tree name)))
(let* ((s0-4 (-> region-tree data2 (+ (-> region-tree length) -1) length))
(i 0)
(region (-> (the-as drawable-inline-array-region-prim (-> region-tree data2 (+ (-> region-tree length) -1))) data i))
)
(while (< i s0-4)
(let ((draw? #f))
(when (and *display-region-inside* (!= tree-name 'water) (point-in-region-debug! (-> region region) (target-pos 0)))
(true! draw?)
(format *stdcon* "~1kinside region-~D [~A] (l: ~A)~%" (-> region region id) tree-name (-> lev name)))
(when (and *region-debug-inspect* (or (= *region-debug-inspect* region) (and *merge-region-prims* (= (-> region region id) (-> *region-debug-inspect* region id)))))
(when (= *region-debug-inspect* region)
(format *stdcon* "~1kinspecting region-~D [~A] (l: ~A)~%" (-> *region-debug-inspect* region id) tree-name (-> lev name))
(format *stdcon* " on-enter: ~A~%" (-> *region-debug-inspect* region on-enter))
(format *stdcon* " on-inside: ~A~%" (-> *region-debug-inspect* region on-inside))
(format *stdcon* " on-exit: ~A~%" (-> *region-debug-inspect* region on-exit))
)
(true! draw?)
)
(when draw?
(set! *debug-region-color-alt* (= tree-name 'camera))
(debug-draw-region region 0)))
(set! i (+ i 1))
(set! region (-> (the-as drawable-inline-array-region-prim (-> region-tree data2 (+ (-> region-tree length) -1))) data i))
)
)
)
(+! tree-i 1)
(set! region-tree (-> region-trees tree-i))
)
)
)
)
)
)
)
)
(if *debug-track-skill*
(debug-track-skill))
)
(debug-draw-buffers)
(with-dma-buffer-add-bucket ((s3-0 (-> arg0 frames (-> arg0 on-screen) debug-buf)) (bucket-id debug-no-zbuf2))
(when (or *display-profile* *stats-profile-bars*)
(postprocess-data! (-> arg0 frames (-> arg0 on-screen) profile-array))
(let ((a2-0 7))
(if *display-profile*
(draw-bars! *profile-array* s3-0 a2-0)
)
)
(if (and (!= *master-mode* 'menu) *stats-profile-bars*)
(draw-text! *profile-array*)
)
)
(when *display-deci-count*
(let ((s2-0 draw-string-xy))
(format (clear *temp-string*) "~D" *deci-count*)
(s2-0 *temp-string* s3-0 448 210 (font-color default) (font-flags shadow))
)
)
(#when PC_PORT
(draw *pc-settings* s3-0)
(draw-memory *pc-settings* s3-0)
(print-debug-misc *pc-settings*)
)
(display-file-info)
)
)
;; draw console buffer
(let ((buf (if *debug-segment*
(-> arg0 frames (-> arg0 on-screen) debug-buf)
(-> arg0 frames (-> arg0 on-screen) global-buf)
)
)
)
(with-dma-buffer-add-bucket ((s3-0 buf) (bucket-id debug-no-zbuf2))
(if (and (= *master-mode* 'pause)
(and (!= *cheat-mode* 'camera) (or (zero? *screen-shot-work*) (= (-> *screen-shot-work* count) -1)))
)
(draw-string-xy
(lookup-text! *common-text* (text-id pause) #f)
buf
256
(if (< (-> *display* base-clock frame-counter) (-> *game-info* letterbox-time))
352
320
)
(font-color red)
(font-flags shadow kerning middle large)
)
)
(let ((s2-2 (the int (-> *font-context* origin y))))
(cond
;; og:preserve-this the console is drawn over the letterbox so this is pointless and has been disabled
((#if PC_PORT #f (or (movie?) (< (-> *display* base-clock frame-counter) (-> *game-info* letterbox-time))))
(+! s2-2 56)
)
(*display-profile*
(+! s2-2 48)
)
)
(when (or (zero? *screen-shot-work*) (= (-> *screen-shot-work* count) -1))
(let* ((v1-82
(draw-string-xy
*stdcon0*
buf
(the int (-> *font-context* origin x))
s2-2
(font-color default)
(font-flags shadow)
)
)
(a3-6 (+ s2-2 (the int (* 2.0 (the-as float (-> v1-82 b))))))
)
(draw-string-xy
*stdcon1*
buf
(the int (-> *font-context* origin x))
a3-6
(font-color default)
(font-flags shadow)
)
)
)
)
(if *display-iop-info*
(show-iop-info buf)
)
(if *display-memcard-info*
(show-mc-info buf)
)
)
)
(let ((v1-101 *dma-mem-usage*))
(when (nonzero? v1-101)
(set! (-> v1-101 length) (max 88 (-> v1-101 length)))
(set! (-> v1-101 data 87 name) "debug")
(+! (-> v1-101 data 87 count) 1)
(+! (-> v1-101 data 87 used) (&-
(-> (if *debug-segment*
(-> arg0 frames (-> arg0 on-screen) debug-buf)
(-> arg0 frames (-> arg0 on-screen) global-buf)
)
base
)
(the-as uint s5-0)
)
)
(set! (-> v1-101 data 87 total) (-> v1-101 data 87 used))
)
)
)
(set! *stdcon* (clear *stdcon0*))
0
(none)
)
(defun display-loop-main ((arg0 display))
"Run the engine.
This function is called after actors update."
(local-vars (a0-94 int) (a0-96 int))
(with-pp
;; added for PC port : increment this to invalidate some weird task-control caches
(#when PC_PORT
(1+! (-> *game-info* task-counter)))
; ;; LOAD LEVEL
(if (-> *level* loading-level)
(load-continue (-> *level* loading-level))
)
; ;; Run blerc to modify foreground models
2022-11-30 22:36:09 -05:00
(with-profiler 'merc *profile-merc-color*
(blerc-execute)
[merc2] support vertex updates, use this for blerc in jak 1 and jak 2 (#2179) This PR adds a feature to merc2 to update vertices. This will be needed to efficient do effects like blerc/ripple/texture scroll. It's enabled for blerc in jak 1 and jak 2, but with a few disclaimers: - currently we still use the mips2c blerc implementation, which is slow and has some "jittering" because of integer precision. When porting to PC, there was an additional synchronization problem because blerc overwrites the merc data as its being read by the renderers. I _think_ this wasn't an issue on PS2 because the blerc dma is higher priority than the VIF1 DMA, but I'm not certain. Either way, I had to add a mutex for this on PC to avoid very slight flickering/gaps. This isn't ideal for performance, but still beats generic by a significant amount in every place I tested. If you see merc taking 2ms to draw, it is likely because it is stuck waiting on blerc to finish. This will go away once blerc itself is ported to C++. - in jak 1, we end up using generic in some cases where we could use merc. In particular maia in village3 hut. This will be fixed later once we can use merc in more places. I don't want to mess with the merc/generic selection logic when we're hopefully going to get rid of it soon. - There is no support for ripple or texture scroll. These use generic on jak 1, and remain broken on jak 2. - Like with `emerc`, jak 1 has a toggle to go back to the old behavior `*blerc-hack*`. - In most cases, toggling this causes no visual differences. One exception is Gol's teeth. I believe this is caused by texture coordinate rounding issues, where generic has an additional float -> int -> float compared to PC merc. It is very hard to notice so I'm not going to worry about it.
2023-01-31 18:23:39 -05:00
(blerc-init)
2022-11-30 22:36:09 -05:00
)
; ;; Run other merc effects that modify vertices
(texscroll-execute)
[merc2] support vertex updates, use this for blerc in jak 1 and jak 2 (#2179) This PR adds a feature to merc2 to update vertices. This will be needed to efficient do effects like blerc/ripple/texture scroll. It's enabled for blerc in jak 1 and jak 2, but with a few disclaimers: - currently we still use the mips2c blerc implementation, which is slow and has some "jittering" because of integer precision. When porting to PC, there was an additional synchronization problem because blerc overwrites the merc data as its being read by the renderers. I _think_ this wasn't an issue on PS2 because the blerc dma is higher priority than the VIF1 DMA, but I'm not certain. Either way, I had to add a mutex for this on PC to avoid very slight flickering/gaps. This isn't ideal for performance, but still beats generic by a significant amount in every place I tested. If you see merc taking 2ms to draw, it is likely because it is stuck waiting on blerc to finish. This will go away once blerc itself is ported to C++. - in jak 1, we end up using generic in some cases where we could use merc. In particular maia in village3 hut. This will be fixed later once we can use merc in more places. I don't want to mess with the merc/generic selection logic when we're hopefully going to get rid of it soon. - There is no support for ripple or texture scroll. These use generic on jak 1, and remain broken on jak 2. - Like with `emerc`, jak 1 has a toggle to go back to the old behavior `*blerc-hack*`. - In most cases, toggling this causes no visual differences. One exception is Gol's teeth. I believe this is caused by texture coordinate rounding issues, where generic has an additional float -> int -> float compared to PC merc. It is very hard to notice so I'm not going to worry about it.
2023-01-31 18:23:39 -05:00
(ripple-execute)
2022-11-30 22:36:09 -05:00
(region-execute)
;; final call to update joints before drawing.
(with-profiler 'joints *profile-joints-color*
(execute-math-engine)
)
;; execute the debug hook before doing the big updates
(with-profiler 'debug *profile-debug-color*
(let* ((s5-5 *debug-hook*)
(t9-12 (car s5-5)))
(while (not (null? s5-5))
((the-as (function none) t9-12))
(set! s5-5 (cdr s5-5))
(set! t9-12 (car s5-5))
)
)
(main-cheats)
)
;; using the position of the in-game camera, update visiblity and matrices for rendering.
(with-profiler 'camera *profile-camera-color*
(update-camera)
)
;; map texture stuff
(update *bigmap*)
;; continue loading level
(if (-> *level* loading-level)
(load-continue (-> *level* loading-level))
)
;; drawing - this runs foreground/background drawing.
(with-profiler 'draw-hook *profile-draw-hook-color*
(*draw-hook*)
)
;; another level load
(if (-> *level* loading-level)
(load-continue (-> *level* loading-level))
)
; (if *display-color-bars*
; (draw-color-bars)
; )
;; draw and update menus
(with-profiler 'menu-hook *profile-menu-hook-color*
;; og:preserve-this Let the popup menu code handle inputs instead of the code written for the original debug menu
(when (not *popup-menu-open*)
(*menu-hook*))
(when *speedrun-manager*
(draw-menu (-> *speedrun-manager* 0)))
)
;; load text files as needed from the menu update
(load-level-text-files -1)
;; post-processing filter drawing
(if (-> *screen-filter* draw?)
(draw *screen-filter*)
)
;; letterbox drawing
(when (or (movie?) (< (-> *display* base-clock frame-counter) (-> *game-info* letterbox-time)))
(if (< (-> *game-info* letterbox-time) (-> *display* base-clock frame-counter))
(set! (-> *game-info* letterbox-time) (-> *display* base-clock frame-counter))
)
(if (#if (not PC_PORT)
(and (= (-> *setting-control* user-current aspect-ratio) 'aspect4x3)
(or (zero? *screen-shot-work*) (= (-> *screen-shot-work* count) -1))
)
(or (and (= (-> *setting-control* user-current aspect-ratio) 'aspect4x3)
(or (zero? *screen-shot-work*) (= (-> *screen-shot-work* count) -1))
)
(not (-> *pc-settings* use-vis?))))
(letterbox)
)
)
;; send alp to C++ for blackout
(put-display-env (-> *display* pmode alp))
;; blackout drawing
(when (-> *setting-control* user-current render)
(if (< (-> *display* base-clock frame-counter) (-> *game-info* blackout-time))
(set! (-> *setting-control* user-default bg-a-force) 1.0)
(set! (-> *setting-control* user-default bg-a-force) 0.0)
)
)
;; generate DMA data for doing the main blit
(blit-displays)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; END of normal frame
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; and we're done with the main frame! end profiling/stat collection
(when *debug-segment*
(let ((s5-13 (-> arg0 frames (-> arg0 on-screen) profile-array data 0)))
(when (and *dproc* *debug-segment*)
(let* ((v1-294 (+ (-> s5-13 depth) -1))
(s4-12 (-> s5-13 segment v1-294))
(s3-12 (-> s5-13 base-time))
)
(when (>= v1-294 0)
(set! (-> s4-12 end-time) (the-as int (- (timer-count (the-as timer-bank #x10000800)) (the-as uint s3-12))))
(+! (-> s5-13 depth) -1)
)
)
)
)
0
(read! (-> *perf-stats* data (perf-stat-bucket all-code)))
)
;; now wait for the previous frame to finish rendering...
(when (nonzero? (sync-path 0 0))
(*dma-timeout-hook*)
(reset-vif1-path)
)
;; debug drawing
(end-display arg0)
;; og:preserve-this
;; Added to push text below the imgui bar if it's currently open
(when (pc-is-imgui-visible?)
(format *stdcon* "~%~%"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; display the frame, and start a new one!
;; this will kick off the next dma transfer
(swap-display arg0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; start profiling for the new frame
(when *debug-segment*
(start-frame! (-> arg0 frames (-> arg0 on-screen) profile-array data 0))
(reset! (-> *perf-stats* data (perf-stat-bucket all-code)))
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; START of next frame
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; a few things before the actor updates...
(set! (-> *time-of-day-context* title-updated) #f)
;; update teleport counter
(set! *teleport* #f)
(when (nonzero? *teleport-count*)
(set! *teleport* #t)
(set! *teleport-count* (+ *teleport-count* -1))
)
;; update particles (we're racing the DMA transfer again, do this asap)
(let ((gp-1 (-> pp clock)))
(set! (-> pp clock) (-> *display* part-clock))
(process-particles)
(set! (-> pp clock) gp-1)
)
;; set up VU0's VIF for collision code run by actors
; (dma-send
; (the-as dma-bank #x10008000)
; (the-as uint (-> *collide-vif0-init* data))
; (the-as uint (/ (-> *collide-vif0-init* length) 4))
; )
;; send sound commands to IOP
(swap-sound-buffers (ear-trans 0) (ear-trans 1) (camera-pos) (camera-angle))
;; advance streaming animation
(str-play-kick)
;; handle spawning/despawning as needed.
(level-update *level*)
;; do some memory card operations, check auto-save
2023-04-14 15:39:58 -04:00
(mc-run)
;; for the same reasons as jak 1, we do not run this.
; (auto-save-check)
(none)
)
)
(defbehavior display-loop process ()
(stack-size-set! (-> self main-thread) 512)
;; it's unclear why this exists, when there's also a call to execute-math-engine
;; in display-loop-main
(process-spawn-function
process
(lambda :behavior process
()
(logclear! (-> self mask) (process-mask freeze pause menu progress entity))
(until #f
(with-profiler 'joints *profile-joints-color*
(execute-math-engine)
)
(suspend)
)
#f
(none)
)
:name "matrix"
:from *4k-dead-pool*
:to *mid-pool*
)
(let ((gp-1 *display*))
(set! *teleport* #t)
(update *setting-control*)
[decomp] Decompile some time-of-day stuff, support new style Jak 2 time of day (#1943) - Add "tfrag-water" tfrag tree support (may just be the same as Jak 1's 'dirt' for the settings) - Add "tfrag-trans" tfrag tree support, reusing "trans-tfrag" from jak 1. - Add a hack to `LinkedObjectFileCreation` to handle `oracle`, which is accidentally multiply defined as a type leftover from jak 1 (an entity in village1), and level info for jak 2. - Add `VI1.DGO` - add `time-of-day.gc`, and a few other stub functions so it works - Set up some time of day stuff in GOAL for jak 2/PC renderers - Clean up time of day in c++ renderers, support the more complicated weight system used by jak 2 (backward compatible with jak 1, thankfully) The mood functions now run, so this could cause problems if they rely on stuff we don't have yet. But it seems fine for ctysluma and prison for now. ![image](https://user-images.githubusercontent.com/48171810/194719441-d185f59c-19dc-4cd3-a5c4-00b0cfe1d6c3.png) ![image](https://user-images.githubusercontent.com/48171810/194719449-6e051bf3-0750-42e5-a654-901313dbe479.png) ![image](https://user-images.githubusercontent.com/48171810/194719455-3ca6793e-873a-449a-8e85-9c20ffeb4da3.png) ![image](https://user-images.githubusercontent.com/48171810/194719461-8f27af17-4434-4492-96cd-8c5eec6eafdf.png) ![image](https://user-images.githubusercontent.com/48171810/194719468-720715b9-985a-4acf-928c-eab948cfcb03.png) ![image](https://user-images.githubusercontent.com/48171810/194719486-bfb91e83-f6ca-4585-80ad-3b2c0cbbd5af.png) ![image](https://user-images.githubusercontent.com/48171810/194719492-df065d2f-cb5a-47e3-a248-f5317c42082f.png) ![image](https://user-images.githubusercontent.com/48171810/194719507-91e1f477-ecfe-4d6c-b744-5f24646255ca.png)
2022-10-08 13:33:03 -04:00
(init-time-of-day-context *time-of-day-context*)
(display-sync gp-1)
(swap-display gp-1)
(install-handler 3 vblank-handler)
(free-nodes *touching-list*)
(prepare *collide-rider-pool*)
(update-actor-hash)
[merc2] support vertex updates, use this for blerc in jak 1 and jak 2 (#2179) This PR adds a feature to merc2 to update vertices. This will be needed to efficient do effects like blerc/ripple/texture scroll. It's enabled for blerc in jak 1 and jak 2, but with a few disclaimers: - currently we still use the mips2c blerc implementation, which is slow and has some "jittering" because of integer precision. When porting to PC, there was an additional synchronization problem because blerc overwrites the merc data as its being read by the renderers. I _think_ this wasn't an issue on PS2 because the blerc dma is higher priority than the VIF1 DMA, but I'm not certain. Either way, I had to add a mutex for this on PC to avoid very slight flickering/gaps. This isn't ideal for performance, but still beats generic by a significant amount in every place I tested. If you see merc taking 2ms to draw, it is likely because it is stuck waiting on blerc to finish. This will go away once blerc itself is ported to C++. - in jak 1, we end up using generic in some cases where we could use merc. In particular maia in village3 hut. This will be fixed later once we can use merc in more places. I don't want to mess with the merc/generic selection logic when we're hopefully going to get rid of it soon. - There is no support for ripple or texture scroll. These use generic on jak 1, and remain broken on jak 2. - Like with `emerc`, jak 1 has a toggle to go back to the old behavior `*blerc-hack*`. - In most cases, toggling this causes no visual differences. One exception is Gol's teeth. I believe this is caused by texture coordinate rounding issues, where generic has an additional float -> int -> float compared to PC merc. It is very hard to notice so I'm not going to worry about it.
2023-01-31 18:23:39 -05:00
(blerc-init)
; (dma-send
; (the-as dma-bank #x10008000)
; (the-as uint (-> *collide-vif0-init* data))
; (the-as uint (/ (-> *collide-vif0-init* length) 4))
; )
(suspend)
(set! (-> *setting-control* user-default bg-a) 0.0)
(set! (-> gp-1 frames 0 start-time) (the-as int (timer-count (the-as timer-bank #x10000800))))
(set! (-> gp-1 frames 1 start-time) (the-as int (timer-count (the-as timer-bank #x10000800))))
(set! (-> gp-1 dog-ratio) 1.0)
(while *run*
(display-loop-main gp-1)
(with-profiler 'actors *profile-actors-color*
(suspend)
)
(#when PC_PORT
(update *pc-settings*)
(if (and *display-sha* *debug-segment* (not-screen-shot?))
(draw-build-revision)))
)
)
(set! *dproc* #f)
(format 0 "display is off #<#x~X>.~%" self)
0
)
(defun on ((arg0 symbol))
"Start the display loop."
(when (not *dproc*)
(when (not arg0)
(if (= (-> *level* level0 status) 'inactive)
(bg 'halfpipe)
)
)
(set! *run* #t)
(set! *dproc* (ppointer->process (process-spawn-function
process
display-loop
:name "display"
:from *4k-dead-pool*
:to *display-pool*
:stack *kernel-dram-stack*
)
)
)
(cond
((or (level-get-with-status *level* 'loaded)
(level-get-with-status *level* 'alive)
(level-get-with-status *level* 'active)
)
(activate-levels! *level*)
(when (not arg0)
(let ((gp-1 (entity-by-type camera-start)))
(when (and gp-1 (type? gp-1 entity-actor))
(while (not (camera-teleport-to-entity gp-1))
(suspend)
)
)
)
)
; (if (and (= *kernel-boot-message* 'art-group) *kernel-boot-art-group*)
; (anim-tester-add-object *kernel-boot-art-group*)
; )
)
(else
(format 0 "startup failed, killing dproc~%")
(kill-by-name "display" *active-pool*)
(set! *dproc* #f)
)
)
)
*dproc*
)
(defun off ()
(stop 'debug)
(dotimes (gp-0 (-> *level* length))
(let ((a0-2 (-> *level* level gp-0)))
(if (= (-> a0-2 status) 'active)
(deactivate a0-2)
)
)
)
(set! *run* #f)
0
)