mirror of
https://github.com/open-goal/jak-project
synced 2026-09-12 04:49:19 -04:00
4fd0a57046
Found out the hard way that the `abutton` array for pressure sensitivity uses a different order than the `pad-buttons` enum, so I created a new enum for abutton indexing. I replaced any magic numbers across the codebase where it made sense, e.g. `(-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) abutton 6)` becomes `(-> *cpad-list* cpads (-> self control unknown-cpad-info00 number) abutton (abutton-idx x))`
690 lines
34 KiB
Common Lisp
690 lines
34 KiB
Common Lisp
;;-*-Lisp-*-
|
|
(in-package goal)
|
|
(require "engine/gfx/sprite/sparticle/sparticle-launcher.gc")
|
|
|
|
#|
|
|
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.
|
|
|#
|
|
|
|
(format 0 "pckernel version: ~D.~D~%" PC_KERNEL_VER_MAJOR PC_KERNEL_VER_MINOR)
|
|
|
|
(defun get-pckernel-version ()
|
|
"return the current pckernel version"
|
|
PC_KERNEL_VERSION)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; updates
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(defmethod set-window-size! ((obj pc-settings) (width int) (height int))
|
|
"sets the size of the display window"
|
|
(let ((display-mode (pc-get-display-mode)))
|
|
(cond
|
|
((= display-mode 'windowed)
|
|
(set! (-> obj window-width) width)
|
|
(set! (-> obj window-height) height)
|
|
(format 0 "Setting window size to ~D x ~D~%" width height)
|
|
(pc-set-window-size! (max PC_MIN_WIDTH (-> obj window-width)) (max PC_MIN_HEIGHT (-> obj window-height))))
|
|
(else
|
|
(format 0 "Setting borderless/fullscreen size to ~D x ~D~%" width height)
|
|
(set! (-> obj width) width)
|
|
(set! (-> obj height) height))))
|
|
(none))
|
|
|
|
(defmethod set-aspect! ((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! ((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-frame-rate! ((obj pc-settings) (rate int) (call-handlers symbol))
|
|
"set the target framerate."
|
|
(if call-handlers (pc-set-frame-rate rate))
|
|
(if (and (!= 'fullscreen (pc-get-display-mode)) (!= (pc-get-active-display-refresh-rate) rate)) (set! (-> obj vsync?) #f))
|
|
(set! (-> obj target-fps) rate)
|
|
(case rate
|
|
((50) (set-game-setting! obj 'video-mode 'pal))
|
|
((60) (set-game-setting! obj 'video-mode 'ntsc))
|
|
(else (set-game-setting! obj 'video-mode 'custom)))
|
|
rate)
|
|
|
|
(defmethod commit-to-file ((obj pc-settings))
|
|
"commits the current settings to the file"
|
|
(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 ((obj pc-settings))
|
|
"Update settings from the C kernel to GOAL."
|
|
(pc-get-window-size (&-> obj framebuffer-width) (&-> obj framebuffer-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 framebuffer-width)) (zero? (-> obj framebuffer-height)))
|
|
(let ((win-aspect (/ (the float (-> obj framebuffer-width)) (the float (-> obj framebuffer-height)))))
|
|
(cond
|
|
((and (not (-> obj use-vis?)) (-> obj aspect-ratio-auto?))
|
|
;; the window determines the resolution
|
|
(set-aspect-ratio! obj win-aspect)
|
|
(set! (-> obj framebuffer-scissor-width) (-> obj framebuffer-width))
|
|
(set! (-> obj framebuffer-scissor-height) (-> obj framebuffer-height)))
|
|
((> win-aspect (-> obj aspect-ratio))
|
|
;; too wide
|
|
(set! (-> obj framebuffer-scissor-width) (the int (* (the float (-> obj framebuffer-height)) (-> obj aspect-ratio))))
|
|
(set! (-> obj framebuffer-scissor-height) (-> obj framebuffer-height)))
|
|
((< win-aspect (-> obj aspect-ratio))
|
|
;; too tall
|
|
(set! (-> obj framebuffer-scissor-width) (-> obj framebuffer-width))
|
|
(set! (-> obj framebuffer-scissor-height) (the int (/ (the float (-> obj framebuffer-width)) (-> obj aspect-ratio)))))
|
|
(else
|
|
;; just right
|
|
(set! (-> obj framebuffer-scissor-width) (-> obj framebuffer-width))
|
|
(set! (-> obj framebuffer-scissor-height) (-> obj framebuffer-height))))))
|
|
(none))
|
|
|
|
(defmethod update-to-os ((obj pc-settings))
|
|
"Update settings from GOAL to the C kernel."
|
|
;; TODO - move the below out of this function that runs every frame
|
|
(cond
|
|
((-> obj letterbox?) (pc-set-letterbox (-> obj framebuffer-scissor-width) (-> obj framebuffer-scissor-height)))
|
|
(else (pc-set-letterbox (-> obj framebuffer-width) (-> obj framebuffer-height))))
|
|
(pc-set-vsync (and (-> obj vsync?)
|
|
(or (= 'fullscreen (pc-get-display-mode)) (>= (pc-get-active-display-refresh-rate) (-> obj target-fps)))))
|
|
(when (!= 'fullscreen (pc-get-display-mode))
|
|
(pc-set-frame-rate (-> obj target-fps)))
|
|
;; do game resolution
|
|
(if (= (pc-get-display-mode) 'windowed)
|
|
(pc-set-game-resolution (-> obj framebuffer-scissor-width) (-> obj framebuffer-scissor-height))
|
|
(pc-set-game-resolution (-> obj width) (-> obj height)))
|
|
;; set msaa sample rate. if invalid, just reset to 2.
|
|
(let ((valid? #f))
|
|
(dotimes (i 31)
|
|
(if (= (-> obj gfx-msaa) (ash 1 i)) (true! valid?)))
|
|
(if (not valid?) (set! (-> obj gfx-msaa) PC_DEFAULT_MSAA))
|
|
(pc-set-msaa (-> obj gfx-msaa)))
|
|
;; -- end TODO
|
|
(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))
|
|
(when (led-enabled? obj)
|
|
(update-led obj)
|
|
;(format *stdcon* "led: ~,,2f ~,,2f ~,,2f (~,,2f%)~%" (-> obj controller-led-color r) (-> obj controller-led-color g) (-> obj controller-led-color b) (* 100.0 (-> obj controller-led-color a)))
|
|
;; use alpha as the brightness modifier
|
|
(vector-float*! (-> obj controller-led-color) (-> obj controller-led-color) (-> obj controller-led-color a))
|
|
;; now multiply by the brightness setting
|
|
(vector-float*! (-> obj controller-led-color) (-> obj controller-led-color) (-> obj controller-led-brightness))
|
|
;; now use it as the controller led color
|
|
(let ((led-rgba (new 'static
|
|
'rgba
|
|
:r
|
|
(the int (lerp-scale 0.0 255.0 (-> obj controller-led-color r) 0.0 1.0))
|
|
:g
|
|
(the int (lerp-scale 0.0 255.0 (-> obj controller-led-color g) 0.0 1.0))
|
|
:b
|
|
(the int (lerp-scale 0.0 255.0 (-> obj controller-led-color b) 0.0 1.0))
|
|
:a #x80)))
|
|
(set! *display-led-rgba* led-rgba)
|
|
(pc-set-controller-led! 0 (the-as int (-> led-rgba r)) (the-as int (-> led-rgba g)) (the-as int (-> led-rgba b)))))
|
|
(none))
|
|
|
|
(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 real-movie? ()
|
|
"are we in an actual cutscene and should letterbox the view?"
|
|
(and (nonzero? movie?) (movie?)))
|
|
|
|
(defmethod update ((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)
|
|
(update-discord-rpc obj)
|
|
;; update auto-splitter info
|
|
(update-speedrun obj)
|
|
(when (not (-> obj use-vis?))
|
|
(update-video-hacks obj))
|
|
(cond
|
|
((not (-> obj ps2-actor-vis?))
|
|
;; 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 ((obj pc-settings))
|
|
"run cheats."
|
|
0)
|
|
|
|
(defmethod update-music-log ((obj pc-settings))
|
|
"update music log settings."
|
|
0)
|
|
|
|
(defmethod update-led ((obj pc-settings))
|
|
"set the controller led color by modifying the controller-led-color vector"
|
|
;; random colors for fun lol
|
|
(set-vector! (-> obj controller-led-color) (rand-vu) (rand-vu) (rand-vu) 1.0)
|
|
;(set-vector! (-> obj controller-led-color) 0.0 0.0 1.0 1.0)
|
|
#t)
|
|
|
|
(defmethod led-enabled? ((obj pc-settings))
|
|
"should the controller led be set?"
|
|
#f)
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; functions
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(defmethod get-current-game-width ((obj pc-settings))
|
|
"return the current width in pixels of the visible portion of the game"
|
|
(cond
|
|
((= (pc-get-display-mode) 'windowed)
|
|
(if (-> obj letterbox?) (-> obj framebuffer-scissor-width) (-> obj framebuffer-width)))
|
|
(else (-> obj width))))
|
|
|
|
(defmethod get-current-game-height ((obj pc-settings))
|
|
"return the current height in pixels of the visible portion of the game"
|
|
(cond
|
|
((= (pc-get-display-mode) 'windowed)
|
|
(if (-> obj letterbox?) (-> obj framebuffer-scissor-height) (-> obj framebuffer-height)))
|
|
(else (-> obj height))))
|
|
|
|
(when *debug-segment*
|
|
(defmethod draw ((obj pc-settings) (buf dma-buffer))
|
|
"debug draw some things on-screen"
|
|
(when (-> obj debug?)
|
|
(format *stdcon* "fullscreen resolution: ~D x ~D~%" (-> obj width) (-> obj height))
|
|
(format *stdcon*
|
|
"window size: ~D x ~D @ ~,,1f x ~,,1f~%"
|
|
(-> obj window-width)
|
|
(-> obj window-height)
|
|
(-> obj dpi-x)
|
|
(-> obj dpi-y))
|
|
(format *stdcon*
|
|
"fb size: ~D x ~D (scissor: ~D x ~D)~%"
|
|
(-> obj framebuffer-width)
|
|
(-> obj framebuffer-height)
|
|
(-> obj framebuffer-scissor-width)
|
|
(-> obj framebuffer-scissor-height))
|
|
(format *stdcon*
|
|
"aspect: ~,,3f/~,,3f auto? ~A vis? ~A lbox? ~A~%"
|
|
(-> obj aspect-ratio)
|
|
(/ (the float (-> obj framebuffer-width)) (the float (-> obj framebuffer-height)))
|
|
(-> obj aspect-ratio-auto?)
|
|
(-> obj use-vis?)
|
|
(-> obj letterbox?))
|
|
(clear *pc-temp-string*))
|
|
(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
|
|
0
|
|
(font-color default)
|
|
(font-flags shadow kerning right)))))
|
|
|
|
(defmethod set-ignore-controller-in-bg! ((obj pc-settings) (val symbol))
|
|
"sets whether or not to ignore controller inputs if the window is in the background"
|
|
(set! (-> obj ignore-controller-win-unfocused?) val)
|
|
(pc-ignore-background-controller-events! val)
|
|
(none))
|
|
|
|
(defmethod update-mouse-controls! ((obj pc-settings))
|
|
"Uses whatever is set on the [[pc-settings]] to update the runtime on how it should interpret mouse events"
|
|
(pc-set-mouse-options! (-> obj mouse-enabled?) (-> obj mouse-camera?) (-> obj mouse-movement?))
|
|
(pc-set-mouse-camera-sens! (-> obj mouse-xsens) (-> obj mouse-ysens))
|
|
(pc-set-auto-hide-cursor! (-> obj auto-hide-cursor?))
|
|
(none))
|
|
|
|
(defmethod debug-font-scale-factor ((this pc-settings))
|
|
"return the debug font scale factor to be used."
|
|
(declare (inline))
|
|
(if (-> this debug-font-scale-auto?)
|
|
(/ (-> this debug-font-scale) (fmax 1.0 (/ (the float (get-current-game-height this)) PC_BASE_HEIGHT)))
|
|
(-> this debug-font-scale)))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; 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))
|
|
;; NOTE - if you have a setting in the file that isn't handled (even if its valid lisp)
|
|
;; this error will be thrown.
|
|
(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 ((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 (> 3 (-> version build)) (and (= 3 (-> version build)) (> 1 (-> 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 (= (pc-get-display-mode) 'windowed)
|
|
(pc-set-window-size! (max PC_MIN_WIDTH (-> obj window-width)) (max PC_MIN_HEIGHT (-> obj window-height))))
|
|
#t)
|
|
|
|
(defmethod handle-input-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) #t))
|
|
(("window-size")
|
|
(set! (-> obj window-width) (file-stream-read-int file))
|
|
(set! (-> obj window-height) (file-stream-read-int file)))
|
|
(("game-size")
|
|
;; Check to see if the game-size is a valid resolution on this persons device
|
|
;; on some machines, this has been proven to cause the black-screen issue https://github.com/open-goal/jak-project/issues/3563
|
|
;; Correlating with logs like:
|
|
;; - OpenGL error 0x502 S8246 T824C: GL_INVALID_OPERATION error generated. Source and destination dimensions must be identical with the current filtering modes.
|
|
(let* ((saved-width (file-stream-read-int file))
|
|
(saved-height (file-stream-read-int file))
|
|
(supported-resolution? (pc-is-supported-resolution? saved-width saved-height)))
|
|
(cond
|
|
(supported-resolution?
|
|
(format 0 "[PC Settings]: Valid game-size resolution ~D x ~D~%" saved-width saved-height)
|
|
(set! (-> obj width) saved-width)
|
|
(set! (-> obj height) saved-height))
|
|
(else
|
|
(pc-get-active-display-size (&-> obj width) (&-> obj height))
|
|
(format 0
|
|
"[PC Settings]: Invalid game-size resolution ~D x ~D, defaulting to ~D x ~D~%"
|
|
saved-width
|
|
saved-height
|
|
(-> obj width)
|
|
(-> obj height))))))
|
|
(("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))))
|
|
;; TODO - moved to C++, has to remain because settings parsing can't handle
|
|
;; unexpected keys
|
|
(("display-mode") (file-stream-read-symbol file))
|
|
;; TODO - moved to C++, has to remain because settings parsing can't handle
|
|
;; unexpected keys
|
|
(("monitor") (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))))
|
|
(("subtitle-speaker") (set! (-> obj subtitle-speaker?) (file-stream-read-symbol file)))
|
|
(("territory") (set! (-> obj territory) (file-stream-read-int file)))
|
|
(("ignore-controller-win-unfocused?") (set-ignore-controller-in-bg! obj (file-stream-read-symbol file)))
|
|
(("controller-hp-led?") (set! (-> obj controller-led-hp?) (file-stream-read-symbol file)))
|
|
(("controller-eco-led?") (set! (-> obj controller-led-eco?) (file-stream-read-symbol file)))
|
|
(("controller-heat-led?") (set! (-> obj controller-led-heat?) (file-stream-read-symbol file)))
|
|
(("stick-deadzone") (set! (-> obj stick-deadzone) (file-stream-read-float file)))
|
|
;; TODO - remove this eventually, setting moved into json input-settings
|
|
;; has to stay here or the settings parsing code explodes
|
|
(("keyboard-enabled?") (file-stream-read-symbol file))
|
|
(("mouse-enabled?") (set! (-> obj mouse-enabled?) (file-stream-read-symbol file)))
|
|
(("mouse-camera?") (set! (-> obj mouse-camera?) (file-stream-read-symbol file)))
|
|
(("mouse-xsens") (set! (-> obj mouse-xsens) (file-stream-read-float file)))
|
|
(("mouse-ysens") (set! (-> obj mouse-ysens) (file-stream-read-float file)))
|
|
(("mouse-movement?") (set! (-> obj mouse-movement?) (file-stream-read-symbol file)))
|
|
(("auto-hide-cursor?") (set! (-> obj auto-hide-cursor?) (file-stream-read-symbol 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-shadow?") (set! (-> obj ps2-shadow?) (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 ps2-actor-vis?) (not (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)))
|
|
(("controller-led-brightness") (set! (-> obj controller-led-brightness) (file-stream-read-float file)))
|
|
(("controller-led-min-brightness") (set! (-> obj controller-led-min-brightness) (file-stream-read-float file)))
|
|
(("controller-led-max-brightness") (set! (-> obj controller-led-max-brightness) (file-stream-read-float file)))
|
|
(("memcard-volume-sfx") (set! (-> obj memcard-volume-sfx) (file-stream-read-float file)))
|
|
(("memcard-volume-music") (set! (-> obj memcard-volume-music) (file-stream-read-float file)))
|
|
(("memcard-volume-dialog") (set! (-> obj memcard-volume-dialog) (file-stream-read-float file)))
|
|
(("memcard-vibration?") (set! (-> obj memcard-vibration?) (file-stream-read-symbol file)))
|
|
;; debug
|
|
(("debug-font-scale") (set! (-> obj debug-font-scale) (file-stream-read-float file)))
|
|
(("debug-font-scale-auto?") (set! (-> obj debug-font-scale-auto?) (file-stream-read-symbol file)))
|
|
(("panic") (when (file-stream-read-symbol file) (reset obj #t) (return #f))))
|
|
0)
|
|
|
|
(defmethod handle-output-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 " (window-size ~D ~D)~%" (-> obj window-width) (-> obj window-height))
|
|
(format file " (game-size ~D ~D)~%" (-> obj width) (-> obj height))
|
|
(format file " (letterbox ~A)~%" (-> obj letterbox?))
|
|
(format file " (vsync ~A)~%" (-> obj vsync?))
|
|
;(format file " (font-scale ~f)~%" (-> obj font-scale))
|
|
(format file " (debug-font-scale ~f)~%" (-> obj debug-font-scale))
|
|
(format file " (debug-font-scale-auto? ~A)~%" (-> obj debug-font-scale-auto?))
|
|
;(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 " (ignore-controller-win-unfocused? ~A)~%" (-> obj ignore-controller-win-unfocused?))
|
|
(format file " (controller-hp-led? ~A)~%" (-> obj controller-led-hp?))
|
|
(format file " (controller-eco-led? ~A)~%" (-> obj controller-led-eco?))
|
|
(format file " (controller-heat-led? ~A)~%" (-> obj controller-led-heat?))
|
|
(format file " (controller-led-brightness ~f)~%" (-> obj controller-led-brightness))
|
|
(format file " (controller-led-min-brightness ~f)~%" (-> obj controller-led-min-brightness))
|
|
(format file " (controller-led-max-brightness ~f)~%" (-> obj controller-led-max-brightness))
|
|
(format file " (stick-deadzone ~f)~%" (-> obj stick-deadzone))
|
|
(format file " (mouse-enabled? ~A)~%" (-> obj mouse-enabled?))
|
|
(format file " (mouse-camera? ~A)~%" (-> obj mouse-camera?))
|
|
(format file " (mouse-xsens ~f)~%" (-> obj mouse-xsens))
|
|
(format file " (mouse-ysens ~f)~%" (-> obj mouse-ysens))
|
|
(format file " (mouse-movement? ~A)~%" (-> obj mouse-movement?))
|
|
(format file " (auto-hide-cursor? ~A)~%" (-> obj auto-hide-cursor?))
|
|
(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-shadow? ~A)~%" (-> obj ps2-shadow?))
|
|
(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)~%" (not (-> obj ps2-actor-vis?)))
|
|
(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 " (subtitle-speaker ~A)~%" (-> obj subtitle-speaker?))
|
|
(format file " (territory ~D)~%" (-> obj territory))
|
|
(format file " (memcard-volume-sfx ~f)~%" (-> obj memcard-volume-sfx))
|
|
(format file " (memcard-volume-music ~f)~%" (-> obj memcard-volume-music))
|
|
(format file " (memcard-volume-dialog ~f)~%" (-> obj memcard-volume-dialog))
|
|
(format file " (memcard-vibration? ~A)~%" (-> obj memcard-vibration?))
|
|
0)
|
|
|
|
(defmethod write-to-file ((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 ((obj pc-settings))
|
|
"load"
|
|
(format (clear *pc-temp-string-1*) "~S/pc-settings.gc" *pc-settings-folder*)
|
|
(cond
|
|
((pc-filepath-exists? *pc-temp-string-1*)
|
|
(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 #t)))
|
|
(else
|
|
(format 0 "[PC] PC Settings not found at '~S'...initializing with defaults!~%" *pc-temp-string-1*)
|
|
(reset obj #t)
|
|
;; save the file so users aren't confused, and so we can debug what the game is producing for them
|
|
(commit-to-file obj)))
|
|
0)
|
|
|
|
(defmethod initialize ((obj pc-settings))
|
|
"initial initialize method to be run after allocating"
|
|
;; load defaults not covered by the file
|
|
(reset obj #f)
|
|
;; if saved settings are corrupted or not found, the object will be fully reset to use all defaults
|
|
(load-settings obj)
|
|
;; any post-operations that need to be done after loading
|
|
(set! (-> obj keyboard-enabled?) (pc-get-keyboard-enabled?))
|
|
(update-mouse-controls! obj)
|
|
obj)
|
|
|
|
(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))))) (initialize obj) obj))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;; entity debugging
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(when *debug-segment*
|
|
(defmethod update-pad ((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)))
|
|
;; toggle long info
|
|
(if (cpad-pressed? pad-idx up) (not! (-> obj show-long-info)))
|
|
(minmax! (-> obj scroll-y) 0 (-> obj scroll-y-max))
|
|
(none))) ;; when debug_segment
|