jak-project/goal_src/jak1/pc/pckernel-common.gc

939 lines
33 KiB
Common Lisp

;;-*-Lisp-*-
(in-package goal)
#|
This file contains new code that we need for the PC port of the game specifically.
It should be included as part of the game engine package (engine.cgo).
This file contains various types and functions to store PC-specific information
and also to communicate between the game (GOAL) and the operating system.
This way we can poll, change and display information about the system the game
is running on, such as:
- display devices and their settings, such as fullscreen, DPI, refresh rate, etc.
- audio devices and their settings, such as audio latency, channel number, etc.
- graphics devices and their settings, such as resolution, FPS, anisotropy, shaders, etc.
- input devices and their settings, such as controllers, keyboards, mice, etc.
- information about the game window (position, size)
- PC-specific goodies, enhancements, fixes and settings.
- whatever else.
If you do not want to include these PC things, you should exclude it from the build system.
|#
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; global variables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; collision renderer things. debug only.
(define *collision-renderer* #f)
(define *collision-wireframe* #f)
(define *collision-mode* (pc-collision-mode mode))
;; todo
(defenum pc-pat-skip-hack
:bitfield #t
(noentity 0)
(nocamera 1)
(noedge 2)
(nolineofsight 12)
(unknowncamera 13)
(unknown 15)
)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; updates
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmethod set-display-mode! pc-settings ((obj pc-settings) (mode symbol))
"sets the game's display mode"
;; change the display mode.
(set! (-> obj display-mode) mode)
;; if windowed mode, set the size properly
(when (= (-> obj display-mode) 'windowed)
(pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height))))
0)
(defmethod set-size! pc-settings ((obj pc-settings) (width int) (height int))
"sets the size of the display window"
(format 0 "Setting ~A size to ~D x ~D~%" (-> obj display-mode) width height)
(cond
((= 'windowed (-> obj display-mode))
(set! (-> obj win-width) width)
(set! (-> obj win-height) height)
(pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height)))
)
(else
(set! (-> obj width) width)
(set! (-> obj height) height)
)
)
(none))
(defmethod set-aspect! pc-settings ((obj pc-settings) (aw int) (ah int))
"set the aspect ratio used for rendering. this forces native widescreen and takes width and height ratios."
(let ((aspect (/ (the float aw) (the float ah))))
(set-aspect-ratio! obj aspect)
(set! (-> obj aspect-custom-x) aw)
(set! (-> obj aspect-custom-y) ah)
(set! (-> obj aspect-ratio-auto?) #f)
(set! (-> obj use-vis?) #f)
)
(none))
(defmethod set-aspect-ratio! pc-settings ((obj pc-settings) (aspect float))
"set the aspect ratio used for rendering."
(set! (-> obj aspect-ratio) aspect)
(set! (-> obj aspect-ratio-scale) (/ aspect ASPECT_4X3))
(set! (-> obj aspect-ratio-reciprocal) (/ ASPECT_4X3 aspect))
(none))
(defmethod set-window-lock! pc-settings ((obj pc-settings) (lock symbol))
"set the aspect ratio used for rendering."
(pc-set-window-lock lock)
(set! (-> obj window-lock?) lock))
(defmethod set-frame-rate! pc-settings ((obj pc-settings) (rate int))
"set the target framerate."
(pc-set-frame-rate rate)
(if (and (!= 'fullscreen (-> obj display-mode))
(!= (pc-get-screen-rate -1) rate))
(set! (-> obj vsync?) #f))
(case rate
((50)
(set! (-> obj target-fps) rate)
(set-game-setting! obj 'video-mode 'pal)
)
((60)
(set! (-> obj target-fps) rate)
(set-game-setting! obj 'video-mode 'ntsc)
)
(else
(set! (-> obj target-fps) rate)
(set-game-setting! obj 'video-mode 'custom)
)
)
rate)
(defmethod set-monitor! pc-settings ((obj pc-settings) (monitor int))
"set the monitor to use when in fullscreen/borderless"
(set! (-> obj monitor) monitor)
(none))
(defmethod commit-to-file pc-settings ((obj pc-settings))
"commits the current settings to the file"
;; auto load settings if available
(format (clear *pc-temp-string-1*) "~S/pc-settings.gc" *pc-settings-folder*)
(pc-mkdir-file-path *pc-temp-string-1*)
(write-to-file obj *pc-temp-string-1*)
(none))
(defmethod update-from-os pc-settings ((obj pc-settings))
"Update settings from the C kernel to GOAL."
(set! (-> obj os) (pc-get-os))
(pc-get-window-size (&-> obj real-width) (&-> obj real-height))
(pc-get-window-scale (&-> obj dpi-x) (&-> obj dpi-y))
(when (-> obj use-vis?)
(if (= (get-game-setting obj 'aspect-ratio) 'aspect4x3)
(set-aspect-ratio! obj ASPECT_4X3)
(set-aspect-ratio! obj ASPECT_16X9)
)
)
(unless (or (zero? (-> obj real-width)) (zero? (-> obj real-height)))
(let ((win-aspect (/ (the float (-> obj real-width)) (the float (-> obj real-height)))))
(cond
((and (not (-> obj use-vis?)) (-> obj aspect-ratio-auto?))
;; the window determines the resolution
(set-aspect-ratio! obj win-aspect)
(set! (-> obj lbox-width) (-> obj real-width))
(set! (-> obj lbox-height) (-> obj real-height))
)
((> win-aspect (-> obj aspect-ratio))
;; too wide
(set! (-> obj lbox-width) (the int (* (the float (-> obj real-height)) (-> obj aspect-ratio))))
(set! (-> obj lbox-height) (-> obj real-height))
)
((< win-aspect (-> obj aspect-ratio))
;; too tall
(set! (-> obj lbox-width) (-> obj real-width))
(set! (-> obj lbox-height) (the int (/ (the float (-> obj real-width)) (-> obj aspect-ratio))))
)
(else
;; just right
(set! (-> obj lbox-width) (-> obj real-width))
(set! (-> obj lbox-height) (-> obj real-height))
)
)
))
(none))
(defmethod update-to-os pc-settings ((obj pc-settings))
"Update settings from GOAL to the C kernel."
(cond
((-> obj letterbox?)
(pc-set-letterbox (-> obj lbox-width) (-> obj lbox-height))
)
(else
(pc-set-letterbox (-> obj real-width) (-> obj real-height))
)
)
;; if monitor selection is out of bounds (e.g. if a monitor got disconnected),
;; then default to the primary monitor
(when (>= (-> obj monitor) (pc-get-monitor-count))
(format 0 "Monitor selection out of bounds, defaulting to primary monitor.~%")
(set! (-> obj monitor) 0)
)
;; set fullscreen to what we want
(pc-set-fullscreen (-> obj display-mode) (-> obj monitor))
;; set window size and fps automatically if the window lock is enabled.
(when (-> obj window-lock?)
(pc-set-vsync (-> obj vsync?))
(when (!= 'fullscreen (-> obj display-mode))
(if (< (pc-get-screen-rate -1) (-> obj target-fps))
(pc-set-vsync #f))
(pc-set-frame-rate (-> obj target-fps)))
)
;; do game resolution
(if (= (-> obj display-mode) 'windowed)
(pc-set-game-resolution (-> obj real-width) (-> obj real-height))
(pc-set-game-resolution (-> obj width) (-> obj height)))
;; set msaa sample rate. if invalid, just reset to 4.
(let ((valid? #f))
(dotimes (i 31)
(if (= (-> obj gfx-msaa) (ash 1 i))
(true! valid?))
)
(if (not valid?) (set! (-> obj gfx-msaa) 4))
(pc-set-msaa (-> obj gfx-msaa))
)
(pc-discord-rpc-set (if (-> obj discord-rpc?) 1 0))
(when #t ;; (not (-> obj ps2-lod-dist?))
(pc-renderer-tree-set-lod (pc-renderer-tree-type tfrag3) (-> obj lod-force-tfrag))
(pc-renderer-tree-set-lod (pc-renderer-tree-type tie3) (-> obj lod-force-tie))
)
(when *debug-segment*
(pc-set-collision *collision-renderer*)
(pc-set-collision-wireframe *collision-wireframe*)
(pc-set-collision-mode *collision-mode*)
)
(pc-sound-set-flava-hack (-> obj flava-hack))
(let ((fade-hack 0))
(unless (-> obj music-fadein?) (logior! fade-hack 1))
(unless (-> obj music-fadeout?) (logior! fade-hack 2))
(pc-sound-set-fade-hack fade-hack)
)
(none))
;; where we store the input progress for the cheat codes. make sure there's enough space for all cheats.
(define *pc-cheat-temp* (new 'global 'inline-array 'uint8 PC_CHEAT_MAX))
(defmacro pc-cheat-toggle-and-tune (cheats-var cheat)
"quickly toggle a cheat code and play an appropriate sound"
`(begin
(cpad-clear! 0 r1)
(logxor! ,cheats-var (pc-cheats ,cheat))
(cheats-sound-play (logtest? ,cheats-var (pc-cheats ,cheat)))
)
)
(defun bcd->dec ((bcd uint))
"Convert a number encoded in BCD to its decimal equivalent"
(+ (* (shr (logand bcd #xf0) 4) 10) (logand bcd #x0f))
)
(defmethod update pc-settings ((obj pc-settings))
"Update settings to/from PC kernel. Call this at the start of every frame.
This will update things like the aspect-ratio, which will be used for graphics code later."
(update-from-os obj)
(update-to-os obj)
(set! (-> obj movie?) (movie?))
(update-discord-rpc obj)
;; update auto-splitter info
(when (-> *pc-settings* speedrunner-mode?)
(update-speedrun obj))
(when (not (-> obj use-vis?))
(update-video-hacks obj)
)
(cond
((-> obj force-actors?)
;; kinda overkill.
(set! (-> *ACTOR-bank* birth-dist) (meters 10000))
(set! (-> *ACTOR-bank* pause-dist) (meters 10000))
(set! (-> *ACTOR-bank* birth-max) 1000)
)
((> (-> *ACTOR-bank* birth-dist) (meters 220)) ;; the original caps at 220m, exceeding that means it was using our hacks
(set! (-> *ACTOR-bank* birth-dist) (meters 220))
(set! (-> *ACTOR-bank* pause-dist) (meters 220))
))
;; cheats.
(update-cheats obj)
;; music.
(update-music-log obj)
(none))
(defmethod update-cheats pc-settings ((obj pc-settings))
"run cheats."
0)
(defmethod add-to-music-log pc-settings ((obj pc-settings) (music symbol) (flava int))
"add music and flava information to the music log.
if music already exists, adds flava. if flava already exists, nothing happens."
;; go through our music log
(dotimes (i PC_MUSIC_LOG_LENGTH)
(cond
;; an empty log entry! place the currently playing music there, and fill flava.
((not (-> obj secrets music i name))
(set! (-> obj secrets music i name) music)
(set! (-> obj secrets music i flava-mask) (ash 1 flava))
(return 0)
)
;; an existing log entry for the current music. fill flava.
((= music (-> obj secrets music i name))
(logior! (-> obj secrets music i flava-mask) (ash 1 flava))
(return 0)
)
;; something else. maybe the wrong entry, in which case nothing to do.
)
)
0)
(defmethod update-music-log pc-settings ((obj pc-settings))
"update music log settings."
0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmethod get-current-game-width pc-settings ((obj pc-settings))
"return the current width in pixels of the visible portion of the game"
(cond
((= (-> obj display-mode) 'windowed)
(if (-> obj letterbox?)
(-> obj lbox-width)
(-> obj real-width)))
(else
(-> obj width))
)
)
(defmethod get-current-game-height pc-settings ((obj pc-settings))
"return the current height in pixels of the visible portion of the game"
(cond
((= (-> obj display-mode) 'windowed)
(if (-> obj letterbox?)
(-> obj lbox-height)
(-> obj real-height)))
(else
(-> obj height))
)
)
(when *debug-segment*
(defmethod draw pc-settings ((obj pc-settings) (buf dma-buffer))
"debug draw some things on-screen"
(when (-> obj debug?)
(clear *pc-temp-string*)
(format *pc-temp-string* "game resolution: ~D x ~D~%" (-> obj width) (-> obj height))
(format *pc-temp-string* "window size: ~D x ~D (~,,1f x ~,,1f)~%" (-> obj real-width) (-> obj real-height) (-> obj dpi-x) (-> obj dpi-y))
(format *pc-temp-string* "target aspect: ~,,3f/~,,3f A: ~A/~A L: ~A~%" (-> obj aspect-ratio) (/ (the float (-> obj real-width)) (the float (-> obj real-height))) (-> obj aspect-ratio-auto?) (-> obj use-vis?) (-> obj letterbox?))
(format *pc-temp-string* "display-type: ~A ~A~%" (-> obj display-mode) (-> obj vsync?))
(draw-string-xy *pc-temp-string* buf 0 (- 224 (* 8 4)) (font-color default) (font-flags shadow kerning))
)
(when *display-actor-bank*
(draw-string-xy (string-format "Actor Bank: ~,,1m/~,,1m (~D)" (-> *ACTOR-bank* pause-dist) (-> *ACTOR-bank* birth-dist) (-> *ACTOR-bank* birth-max)) buf 512 (- 224 8) (font-color default) (font-flags shadow kerning right))
)
)
)
(defun find-music-log ((music symbol))
"return #t if the given music is logged into the *pc-settings*, #f otherwise."
(dotimes (i PC_MUSIC_LOG_LENGTH)
(if (= music (-> *pc-settings* secrets music i name))
(return #t)))
#f)
(defun find-flava-log ((music symbol) (flava-idx int))
"return #t if the given music's flava is logged into the *pc-settings*, #f otherwise."
(dotimes (i PC_MUSIC_LOG_LENGTH)
(if (= music (-> *pc-settings* secrets music i name))
(return (logtest? (-> *pc-settings* secrets music i flava-mask) (ash 1 flava-idx)))))
#f)
(defun-debug print-music-log ((out object))
"prints the *pc-settings* music log."
(dotimes (i PC_MUSIC_LOG_LENGTH)
(if (-> *pc-settings* secrets music i name)
(format out "music log ~D: ~A (f #x~x)~%" i (-> *pc-settings* secrets music i name) (-> *pc-settings* secrets music i flava-mask)))
)
0)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; file IO
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmacro file-stream-seek-until (fs func-name)
`(let ((done? #f)
(tell -1))
(until done?
(let ((read (file-stream-read ,fs (-> *pc-temp-string* data) PC_TEMP_STRING_LEN)))
(cond
((zero? read)
(set! (-> *pc-temp-string* data read) 0)
(true! done?)
)
(else
(dotimes (i read)
(when (,func-name (-> *pc-temp-string* data i))
(true! done?)
(set! tell (+ i (- (file-stream-tell ,fs) read)))
(set! i read)
)
)
)
)
)
)
(if (!= tell -1)
(file-stream-seek ,fs tell SCE_SEEK_SET)
tell
)
)
)
(defmacro file-stream-read-until (fs func-name)
`(let ((read (file-stream-read ,fs (-> *pc-temp-string* data) PC_TEMP_STRING_LEN)))
(dotimes (i read)
(when (,func-name (-> *pc-temp-string* data i))
(set! (-> *pc-temp-string* data i) 0)
(file-stream-seek ,fs (+ i (- (file-stream-tell ,fs) read)) SCE_SEEK_SET)
(set! i read)
)
)
*pc-temp-string*
)
)
(defmacro is-whitespace-or-bracket? (c)
`(or (is-whitespace-char? ,c) (= #x28 ,c) (= #x29 ,c))
)
(defun file-stream-seek-past-whitespace ((file file-stream))
(file-stream-seek-until file not-whitespace-char?)
)
(defun file-stream-read-word ((file file-stream))
(file-stream-read-until file is-whitespace-or-bracket?)
;(format 0 "word ~A~%" *pc-temp-string*)
)
(defmacro file-stream-getc (fs)
`(let ((buf 255))
(file-stream-read ,fs (& buf) 1)
;(format 0 "getc got #x~X~%" buf)
buf
)
)
(defun file-stream-read-int ((file file-stream))
(file-stream-seek-past-whitespace file)
(file-stream-read-word file)
(string->int *pc-temp-string*)
)
(defun file-stream-read-float ((file file-stream))
(file-stream-seek-past-whitespace file)
(file-stream-read-word file)
(string->float *pc-temp-string*)
)
(defun file-stream-read-symbol ((file file-stream))
(file-stream-seek-past-whitespace file)
(file-stream-read-word file)
(string->symbol *pc-temp-string*)
)
(defmacro pc-settings-read-throw-error (fs msg)
"not an actual throw..."
`(begin
(format 0 "pc settings read error: ~S~%" ,msg)
(file-stream-close ,fs)
(return #f)
)
)
(defmacro with-settings-scope (bindings &rest body)
(let ((fs (first bindings)))
`(begin
(file-stream-seek-past-whitespace ,fs)
(when (!= #x28 (file-stream-getc ,fs))
(pc-settings-read-throw-error ,fs "invalid char, ( not found")
)
,@body
(file-stream-seek-past-whitespace ,fs)
(when (!= #x29 (file-stream-getc ,fs))
(pc-settings-read-throw-error ,fs "invalid char, ) not found")
)
)
)
)
(defmacro file-stream-get-next-char-ret (fs)
`(begin
(file-stream-seek-past-whitespace ,fs)
(let ((c (file-stream-getc ,fs)))
(file-stream-seek ,fs -1 SCE_SEEK_CUR)
c))
)
(defmacro file-stream-get-next-char (fs)
`(begin
(file-stream-seek-past-whitespace ,fs)
(file-stream-getc ,fs)
)
)
(defmacro dosettings (bindings &rest body)
"iterate over a list of key-value pairs like so: (<key> <value>) (<key> <value>) ...
the name of key is stored in *pc-temp-string*"
(let ((fs (first bindings)))
`(let ((c -1))
(while (begin (file-stream-seek-past-whitespace ,fs) (set! c (file-stream-getc ,fs)) (= #x28 c))
(file-stream-read-word ,fs)
,@body
(set! c (file-stream-get-next-char ,fs))
(when (!= #x29 c)
(pc-settings-read-throw-error ,fs (string-format "invalid char, ) not found, got #x~X ~A" c *pc-temp-string*))
)
)
(file-stream-seek ,fs -1 SCE_SEEK_CUR)
)
)
)
(defmethod read-from-file pc-settings ((obj pc-settings) (filename string))
"read settings from a file"
(if (not filename)
(return #f))
(let ((file (new 'stack 'file-stream filename 'read)))
(when (not (file-stream-valid? file))
(return #f))
(let ((version PC_KERNEL_VERSION))
(with-settings-scope (file)
(case-str (file-stream-read-word file)
(("settings")
(set! version (the pckernel-version (file-stream-read-int file)))
(cond
((and (= (-> version major) PC_KERNEL_VER_MAJOR)
(= (-> version minor) PC_KERNEL_VER_MINOR))
;; minor or no difference
)
(else
;; major difference
(format 0 "PC kernel version mismatch! Got ~D.~D vs ~D.~D~%" PC_KERNEL_VER_MAJOR PC_KERNEL_VER_MINOR (-> version major) (-> version minor))
(file-stream-close file)
(return #f)
)
)
(dosettings (file)
(handle-input-settings obj file)
)
;; upgrade settings if minor changes
;; remember to delete this when major changes to the version number are made
(when (and (= PC_KERNEL_VER_MAJOR 1)
(= PC_KERNEL_VER_MINOR 10)
(or (!= PC_KERNEL_VER_BUILD (-> version build))
(!= PC_KERNEL_VER_REVISION (-> version revision))))
;; 1.10 upgrade: turn envmap on
(set! (-> obj force-envmap?) #t)
)
)
)
)
)
(file-stream-close file)
)
(format 0 "pc settings file read: ~A~%" filename)
;; restore the windowed mode resolution properly
(when (= (-> obj display-mode) 'windowed)
(pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height))))
#t
)
(defmethod handle-input-settings pc-settings ((obj pc-settings) (file file-stream))
"handle the text parsing input for the 'settings' group"
(case-str *pc-temp-string*
(("fps") (set-frame-rate! obj (file-stream-read-int file)))
(("window-size")
(set! (-> obj win-width) (file-stream-read-int file))
(set! (-> obj win-height) (file-stream-read-int file))
)
(("game-size")
(set! (-> obj width) (file-stream-read-int file))
(set! (-> obj height) (file-stream-read-int file))
)
(("msaa") (set! (-> obj gfx-msaa) (file-stream-read-int file)))
(("aspect-state")
;; game aspect
(set-game-setting! obj 'aspect-ratio (file-stream-read-symbol file))
;; aspect ratio
(set! (-> obj aspect-custom-x) (file-stream-read-int file))
(set! (-> obj aspect-custom-y) (file-stream-read-int file))
;; aspect auto
(set! (-> obj aspect-ratio-auto?) (file-stream-read-symbol file))
(unless (-> obj aspect-ratio-auto?)
(set-aspect! obj (-> obj aspect-custom-x) (-> obj aspect-custom-y))
)
)
(("display-mode") (set-display-mode! obj (file-stream-read-symbol file)))
(("monitor") (set-monitor! obj (file-stream-read-int file)))
(("letterbox") (set! (-> obj letterbox?) (file-stream-read-symbol file)))
(("vsync") (set! (-> obj vsync?) (file-stream-read-symbol file)))
(("font-scale") (set! (-> obj font-scale) (file-stream-read-float file)))
(("audio-latency-ms") (set! (-> obj audio-latency-ms) (file-stream-read-int file)))
(("audio-pan-override") (set! (-> obj audio-pan-override) (file-stream-read-float file)))
(("audio-volume-override") (set! (-> obj audio-volume-override) (file-stream-read-float file)))
(("audio-channel-nb") (set! (-> obj audio-channel-nb) (file-stream-read-int file)))
(("gfx-renderer") (set! (-> obj gfx-renderer) (the-as pc-gfx-renderer (file-stream-read-int file))))
(("gfx-resolution") (set! (-> obj gfx-resolution) (file-stream-read-float file)))
(("gfx-anisotropy") (set! (-> obj gfx-anisotropy) (file-stream-read-float file)))
(("shrub-dist-mod") (set! (-> obj shrub-dist-mod) (file-stream-read-float file)))
(("lod-dist-mod") (set! (-> obj lod-dist-mod) (file-stream-read-float file)))
(("lod-force-tfrag") (set! (-> obj lod-force-tfrag) (file-stream-read-int file)))
(("lod-force-tie") (set! (-> obj lod-force-tie) (file-stream-read-int file)))
(("lod-force-ocean") (set! (-> obj lod-force-ocean) (file-stream-read-int file)))
(("lod-force-actor") (set! (-> obj lod-force-actor) (file-stream-read-int file)))
(("game-language") (set-game-language! obj (the-as language-enum (file-stream-read-int file))))
(("text-language") (set! (-> obj text-language) (the-as pc-subtitle-lang (file-stream-read-int file))))
(("subtitle-speaker") (set! (-> obj subtitle-speaker?) (file-stream-read-symbol file)))
(("stick-deadzone") (set! (-> obj stick-deadzone) (file-stream-read-float file)))
(("ps2-read-speed?") (set! (-> obj ps2-read-speed?) (file-stream-read-symbol file)))
(("ps2-parts?") (set! (-> obj ps2-parts?) (file-stream-read-symbol file)))
(("ps2-music?") (set! (-> obj ps2-music?) (file-stream-read-symbol file)))
(("ps2-se?") (set! (-> obj ps2-se?) (file-stream-read-symbol file)))
(("ps2-hints?") (set! (-> obj ps2-hints?) (file-stream-read-symbol file)))
(("ps2-lod-dist?") (set! (-> obj ps2-lod-dist?) (file-stream-read-symbol file)))
(("force-envmap?") (set! (-> obj force-envmap?) (file-stream-read-symbol file)))
(("force-actors?") (set! (-> obj force-actors?) (file-stream-read-symbol file)))
(("music-fade?") (file-stream-read-symbol file)) ;; TODO remove
(("use-vis?") (set! (-> obj use-vis?) (file-stream-read-symbol file)))
(("hinttitles?") (set! (-> obj hinttitles?) (file-stream-read-symbol file)))
(("discord-rpc?") (set! (-> obj discord-rpc?) (file-stream-read-symbol file)))
(("speedrunner-mode?") (set! (-> obj speedrunner-mode?) (file-stream-read-symbol file)))
(("cutscene-skips?") (file-stream-read-symbol file)) ;; TODO remove
(("first-camera-h-inverted?") (set! (-> obj first-camera-h-inverted?) (file-stream-read-symbol file)))
(("first-camera-v-inverted?") (set! (-> obj first-camera-v-inverted?) (file-stream-read-symbol file)))
(("third-camera-h-inverted?") (set! (-> obj third-camera-h-inverted?) (file-stream-read-symbol file)))
(("third-camera-v-inverted?") (set! (-> obj third-camera-v-inverted?) (file-stream-read-symbol file)))
(("music-fadein?") (set! (-> obj music-fadein?) (file-stream-read-symbol file)))
(("music-fadeout?") (set! (-> obj music-fadeout?) (file-stream-read-symbol file)))
(("scenes-seen")
(dotimes (i PC_SPOOL_LOG_LENGTH)
(set! (-> obj scenes-seen i) (file-stream-read-int file))
)
)
(("secrets")
(dosettings (file)
(case-str *pc-temp-string*
(("hard-rats?") (set! (-> obj secrets hard-rats?) (file-stream-read-symbol file)))
(("hero-mode?") (set! (-> obj secrets hero-mode?) (file-stream-read-symbol file)))
(("hud-map?") (set! (-> obj secrets hud-map?) (file-stream-read-symbol file)))
(("hud-counters?") (set! (-> obj secrets hud-counters?) (file-stream-read-symbol file)))
(("hud-watch?") (set! (-> obj secrets hud-watch?) (file-stream-read-symbol file)))
(("watch-12hr?") (set! (-> obj secrets watch-12hr?) (file-stream-read-symbol file)))
(("art") (set! (-> obj secrets art) (the-as pc-jak1-concept-art (file-stream-read-int file))))
(("hard-fish-hiscore") (set! (-> obj secrets hard-fish-hiscore) (file-stream-read-int file)))
(("hard-rats-hiscore") (set! (-> obj secrets hard-rats-hiscore) (file-stream-read-int file)))
(("hard-rats-hiwave") (set! (-> obj secrets hard-rats-hiwave) (file-stream-read-int file)))
(("cheats")
(set! (-> obj cheats-known) (the pc-cheats (file-stream-read-int file)))
(set! (-> obj cheats) (logand (-> obj cheats-known) (file-stream-read-int file)))
)
(("music")
(dotimes (i PC_MUSIC_LOG_LENGTH)
(when (!= #x29 (file-stream-get-next-char-ret file))
(with-settings-scope (file)
(set! (-> obj secrets music i name) (file-stream-read-symbol file))
(set! (-> obj secrets music i flava-mask) (file-stream-read-int file))
)
)
)
)
)
)
)
(("panic")
(when (file-stream-read-symbol file)
(reset obj)
(set-display-mode! obj #f)
(return #f)
)
)
)
0)
(defmethod handle-output-settings pc-settings ((obj pc-settings) (file file-stream))
"handle the text writing output for the 'settings' group"
(format file " (fps ~D)~%" (-> obj target-fps))
(format file " (msaa ~D)~%" (-> obj gfx-msaa))
(format file " (aspect-state ~A ~D ~D ~A)~%" (get-game-setting obj 'aspect-ratio)
(-> obj aspect-custom-x) (-> obj aspect-custom-y)
(-> obj aspect-ratio-auto?))
(format file " (display-mode ~A)~%" (-> obj display-mode))
(format file " (window-size ~D ~D)~%" (-> obj win-width) (-> obj win-height))
(format file " (game-size ~D ~D)~%" (-> obj width) (-> obj height))
(format file " (monitor ~D)~%" (-> obj monitor))
(format file " (letterbox ~A)~%" (-> obj letterbox?))
(format file " (vsync ~A)~%" (-> obj vsync?))
(format file " (font-scale ~f)~%" (-> obj font-scale))
(format file " (audio-latency-ms ~D)~%" (-> obj audio-latency-ms))
(format file " (audio-pan-override ~f)~%" (-> obj audio-pan-override))
(format file " (audio-volume-override ~f)~%" (-> obj audio-volume-override))
(format file " (audio-channel-nb ~D)~%" (-> obj audio-channel-nb))
(format file " (gfx-renderer ~D)~%" (-> obj gfx-renderer))
(format file " (gfx-resolution ~f)~%" (-> obj gfx-resolution))
(format file " (gfx-anisotropy ~f)~%" (-> obj gfx-anisotropy))
(format file " (shrub-dist-mod ~f)~%" (-> obj shrub-dist-mod))
(format file " (lod-dist-mod ~f)~%" (-> obj lod-dist-mod))
(format file " (lod-force-tfrag ~D)~%" (-> obj lod-force-tfrag))
(format file " (lod-force-tie ~D)~%" (-> obj lod-force-tie))
(format file " (lod-force-ocean ~D)~%" (-> obj lod-force-ocean))
(format file " (lod-force-actor ~D)~%" (-> obj lod-force-actor))
(format file " (stick-deadzone ~f)~%" (-> obj stick-deadzone))
(format file " (ps2-read-speed? ~A)~%" (-> obj ps2-read-speed?))
(format file " (ps2-parts? ~A)~%" (-> obj ps2-parts?))
(format file " (ps2-music? ~A)~%" (-> obj ps2-music?))
(format file " (ps2-se? ~A)~%" (-> obj ps2-se?))
(format file " (ps2-hints? ~A)~%" (-> obj ps2-hints?))
(format file " (ps2-lod-dist? ~A)~%" (-> obj ps2-lod-dist?))
(format file " (force-envmap? ~A)~%" (-> obj force-envmap?))
(format file " (use-vis? ~A)~%" (-> obj use-vis?))
(format file " (discord-rpc? ~A)~%" (-> obj discord-rpc?))
(format file " (speedrunner-mode? ~A)~%" (-> obj speedrunner-mode?))
(format file " (first-camera-h-inverted? ~A)~%" (-> obj first-camera-h-inverted?))
(format file " (first-camera-v-inverted? ~A)~%" (-> obj first-camera-v-inverted?))
(format file " (third-camera-h-inverted? ~A)~%" (-> obj third-camera-h-inverted?))
(format file " (third-camera-v-inverted? ~A)~%" (-> obj third-camera-v-inverted?))
(format file " (force-actors? ~A)~%" (-> obj force-actors?))
(format file " (music-fadein? ~A)~%" (-> obj music-fadein?))
(format file " (music-fadeout? ~A)~%" (-> obj music-fadeout?))
(format file " (hinttitles? ~A)~%" (-> obj hinttitles?))
(format file " (game-language ~D)~%" (get-game-language obj))
(format file " (text-language ~D)~%" (-> obj text-language))
(format file " (subtitle-speaker ~A)~%" (-> obj subtitle-speaker?))
#|
(format file " (scenes-seen")
(dotimes (i PC_SPOOL_LOG_LENGTH)
(if (zero? (mod i 16))
(format file "~% ")
)
(format file " ~D" (-> obj scenes-seen i))
)
(format file "~% )~%")
|#
(format file " (secrets~%")
#|
(format file " (art #x~X)~%" (-> obj secrets art))
(format file " (hard-rats? ~A)~%" (-> obj secrets hard-rats?))
(format file " (hero-mode? ~A)~%" (-> obj secrets hero-mode?))
(format file " (hud-map? ~A)~%" (-> obj secrets hud-map?))
(format file " (hud-counters? ~A)~%" (-> obj secrets hud-counters?))
(format file " (hard-fish-hiscore ~D)~%" (-> obj secrets hard-fish-hiscore))
(format file " (hard-rats-hiscore ~D)~%" (-> obj secrets hard-rats-hiscore))
(format file " (hard-rats-hiwave ~D)~%" (-> obj secrets hard-rats-hiwave))
|#
(format file " (cheats #x~x #x~x)~%" (-> obj cheats-known) (-> obj cheats))
(format file " (music~%")
(dotimes (i PC_MUSIC_LOG_LENGTH)
(if (-> obj secrets music i name)
(format file " (~A #x~X)~%" (-> obj secrets music i name) (-> obj secrets music i flava-mask))
)
)
(format file " )~%")
(format file " )~%")
0)
(defmethod write-to-file pc-settings ((obj pc-settings) (filename string))
"write settings to a file"
(if (not filename)
(return #f))
(let ((file (new 'stack 'file-stream filename 'write)))
(if (not (file-stream-valid? file))
(return #f))
(format file "(settings #x~X~%" PC_KERNEL_VERSION)
(handle-output-settings obj file)
(format file " )~%")
(file-stream-close file)
)
(format 0 "pc settings file write: ~A~%" filename)
#t
)
(defmethod load-settings pc-settings ((obj pc-settings))
"load"
(format (clear *pc-temp-string-1*) "~S/pc-settings.gc" *pc-settings-folder*)
(if (pc-filepath-exists? *pc-temp-string-1*)
(begin
(format 0 "[PC] PC Settings found at '~S'...loading!~%" *pc-temp-string-1*)
(unless (read-from-file obj *pc-temp-string-1*)
(format 0 "[PC] PC Settings found at '~S' but could not be loaded, using defaults!~%" *pc-temp-string-1*)
(reset obj)))
(format 0 "[PC] PC Settings not found at '~S'...initializing with defaults!~%" *pc-temp-string-1*))
0)
(defmethod new pc-settings ((allocation symbol) (type-to-make type))
"make a new pc-settings"
(let ((obj (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(reset obj)
;; auto load settings if available
;; if saved settings are corrupted or not found, use defaults
(load-settings obj)
obj))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; entity debugging
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(when *debug-segment*
(deftype entity-debug-inspect (basic)
(
(scroll-y int16)
(scroll-y-max int16)
(entity entity)
(show-actor-info symbol)
)
(:methods
(new (symbol type) _type_)
(set-entity! (_type_ entity) entity)
(update-pad (_type_ int) none)
)
)
(defmethod new entity-debug-inspect ((allocation symbol) (type-to-make type))
"make a new entity-debug-inspect object"
(let ((obj (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(set! (-> obj scroll-y) 0)
(set! (-> obj scroll-y-max) 0)
(set! (-> obj entity) (the entity #f))
(set! (-> obj show-actor-info) #f)
obj
)
)
(defmethod update-pad entity-debug-inspect ((obj entity-debug-inspect) (pad-idx int))
"respond to pad inputs"
;; scroll up
(if (cpad-pressed? pad-idx l1)
(1-! (-> obj scroll-y)))
;; scroll down
(if (cpad-pressed? pad-idx r1)
(1+! (-> obj scroll-y)))
;; toggle actor info
(if (cpad-pressed? pad-idx l3)
(not! (-> obj show-actor-info)))
(minmax! (-> obj scroll-y) 0 (-> obj scroll-y-max))
(none))
(define *entity-debug-inspect* (new 'debug 'entity-debug-inspect))
) ;; when debug_segment