g/j2: Implement speedrunner mode in jak 2 (#2976)

This commit is contained in:
Tyler Wilding 2023-09-16 21:23:29 -06:00 committed by GitHub
parent d784561d43
commit d701a54c43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 401 additions and 137 deletions

View file

@ -1124,8 +1124,46 @@ static std::vector<ReplaceInfo> s_replace_info_jak2 = {
{"~Y~-6Hº~Z~+10H", "°"},
// Color / Emphasis
{"~[~0L", "<COLOR_DEFAULT>"},
{"~[~1L", "<COLOR_WHITE>"},
{"~[~32L", "<COLOR_DEFAULT>"}};
{"~[~2L", "<COLOR_TRANSPARENT>"},
{"~[~3L", "<COLOR_RED>"},
{"~[~4L", "<COLOR_ORANGE>"},
{"~[~5L", "<COLOR_YELLOW>"},
{"~[~6L", "<COLOR_GREEN>"},
{"~[~7L", "<COLOR_BLUE>"},
{"~[~8L", "<COLOR_CYAN>"},
{"~[~9L", "<COLOR_PINK>"},
{"~[~10L", "<COLOR_MENU-SELECTED>"},
{"~[~11L", "<COLOR_MENU-SELECTED-PARENT>"},
{"~[~12L", "<COLOR_MENU>"},
{"~[~13L", "<COLOR_MENU-PARENT>"},
{"~[~14L", "<COLOR_MENU-FUNC-BAD>"},
{"~[~15L", "<COLOR_MENU-FLAG-ON>"},
{"~[~16L", "<COLOR_MENU-FLAG-ON-PARENT>"},
{"~[~17L", "<COLOR_MENU-FLAG-OFF>"},
{"~[~18L", "<COLOR_MENU-FLAG-OFF-PARENT>"},
{"~[~19L", "<COLOR_MENU-INVALID>"},
{"~[~20L", "<COLOR_FLAT-YELLOW>"},
{"~[~21L", "<COLOR_COLOR-21>"},
{"~[~22L", "<COLOR_PAD-BACK>"},
{"~[~23L", "<COLOR_PAD-SHINE>"},
{"~[~24L", "<COLOR_PAD-SQUARE>"},
{"~[~25L", "<COLOR_PAD-CIRCLE>"},
{"~[~26L", "<COLOR_PAD-TRIANGLE>"},
{"~[~27L", "<COLOR_PAD-CROSS>"},
{"~[~28L", "<COLOR_PROGRESS-OLD-BLUE>"},
{"~[~29L", "<COLOR_PROGRESS-OLD-YELLOW>"},
{"~[~30L", "<COLOR_PROGRESS-OLD-SELECTED>"},
{"~[~31L", "<COLOR_PROGRESS-OLD-PERCENT>"},
{"~[~32L", "<COLOR_PROGRESS>"},
{"~[~33L", "<COLOR_PROGRESS-SELECTED>"},
{"~[~34L", "<COLOR_PROGRESS-FORCE-SELECTED>"},
{"~[~35L", "<COLOR_PROGRESS-OPTION-OFF>"},
{"~[~36L", "<COLOR_COLOR-36>"},
{"~[~37L", "<COLOR_CREDITS-STAFF-TITLE-1>"},
{"~[~38L", "<COLOR_CREDITS-STAFF-TITLE-2>"},
{"~[~39L", "<COLOR_COLOR-39>"}};
static std::vector<EncodeInfo> s_encode_info_jak2 = {
{"ˇ", {0x10}}, // caron

View file

@ -292,7 +292,7 @@ void InitIOP() {
}
}
AutoSplitterBlock gAutoSplitterBlock;
AutoSplitterBlock g_auto_splitter_block_jak1;
/*!
* Initialize GOAL Runtime. This is the main initialization which is called before entering
@ -357,7 +357,8 @@ int InitMachine() {
}
// TODO - better place to put this?
gAutoSplitterBlock.pointer_to_symbol =
// TODO - yes, see jak2's code!
g_auto_splitter_block_jak1.pointer_to_symbol =
(u64)g_ee_main_mem + intern_from_c("*autosplit-info-jak1*")->value;
lg::info("InitListenerConnect");

View file

@ -45,5 +45,5 @@ struct AutoSplitterBlock {
const char marker[20] = "UnLiStEdStRaTs_JaK1";
u64 pointer_to_symbol = 0;
};
extern AutoSplitterBlock gAutoSplitterBlock;
extern AutoSplitterBlock g_auto_splitter_block_jak1;
} // namespace jak1

View file

@ -362,7 +362,8 @@ void InitIOP() {
}
printf("InitIOP OK\n");
}
AutoSplitterBlock gAutoSplitterBlock;
AutoSplitterBlock g_auto_splitter_block_jak2;
int InitMachine() {
// heap_start = malloc(0x10);
@ -662,7 +663,7 @@ void pc_set_levels(u32 lev_list) {
}
void init_autosplit_struct() {
gAutoSplitterBlock.pointer_to_symbol =
g_auto_splitter_block_jak2.pointer_to_symbol =
(u64)g_ee_main_mem + (u64)intern_from_c("*autosplit-info-jak2*")->value();
}
@ -741,6 +742,12 @@ inline u64 bool_to_symbol(const bool val) {
// return bool_to_symbol(false);
//}
void encode_utf8_string(u32 src_str_ptr, u32 str_dest_ptr) {
auto str = std::string(Ptr<String>(src_str_ptr).c()->data());
std::string converted = get_font_bank(GameTextVersion::JAK2)->convert_utf8_to_game(str);
strcpy(Ptr<String>(str_dest_ptr).c()->data(), converted.c_str());
}
void InitMachine_PCPort() {
// PC Port added functions
init_common_pc_port_functions(
@ -756,6 +763,7 @@ void InitMachine_PCPort() {
make_function_symbol_from_c("__pc-set-levels", (void*)pc_set_levels);
make_function_symbol_from_c("__pc-get-tex-remap", (void*)lookup_jak2_texture_dest_offset);
make_function_symbol_from_c("pc-init-autosplitter-struct", (void*)init_autosplit_struct);
make_function_symbol_from_c("pc-encode-utf8-string", (void*)encode_utf8_string);
// discord rich presence
make_function_symbol_from_c("pc-discord-rpc-update", (void*)update_discord_rpc);

View file

@ -111,6 +111,6 @@ struct AutoSplitterBlock {
u64 pointer_to_symbol = 0;
};
extern AutoSplitterBlock gAutoSplitterBlock;
extern AutoSplitterBlock g_auto_splitter_block_jak2;
} // namespace jak2

View file

@ -157,7 +157,7 @@
(initialize! *game-info* 'game (the-as game-save #f) "jungle-start")
)
(((speedrun-category il-misty))
;; spawn at start of misty
;; spawn at start of misty
(initialize! *game-info* 'game (the-as game-save #f) "misty-start")
)
(((speedrun-category il-firecanyon))
@ -240,7 +240,7 @@
(set! (-> *setting-control* default auto-save) #t)
(none)
)
(defun setup-speedrun-post-blackout ()
(when (and (-> *speedrun-info* needs-post-blackout-setup?) (>= (-> *display* base-frame-counter) (-> *game-info* blackout-time)))
(set! (-> *speedrun-info* needs-post-blackout-setup?) #f)

View file

@ -295,8 +295,7 @@
(update-discord-rpc obj)
;; update auto-splitter info
(when (-> *pc-settings* speedrunner-mode?)
(update-speedrun obj))
(update-speedrun obj)
(when (not (-> obj use-vis?))
(update-video-hacks obj)

View file

@ -292,7 +292,7 @@
(defmethod update-speedrun pc-settings-jak1 ((obj pc-settings-jak1))
"update speedrun module"
(with-profiler "speedrun-update-jak1"
(with-profiler "speedrun-update"
(speedrun-mode-update))
(none))

View file

@ -238,8 +238,8 @@
"settings.o"
"autosplit-h.o" ;; added
"autosplit.o" ;; added
"popup-menu-h.o" ;; added
"speedruns-h.o" ;; added
"speedruns.o" ;; added
"mood-tables.o"
"mood-tables2.o"
"mood.o"
@ -327,6 +327,8 @@
"board-states.o"
"mech-h.o"
"menu.o"
"popup-menu.o" ;; added
"speedruns.o" ;; added
"drawable.o"
"drawable-group.o"
"drawable-inline-array.o"

View file

@ -1778,7 +1778,9 @@ auto-save-post
)
(suspend)
)
(activate-progress *dproc* 'icon-info)
;; og:preserve-this Disable the auto-save prompt in speedrunner mode, we get it
(when (not (-> *pc-settings* speedrunner-mode?))
(activate-progress *dproc* 'icon-info))
(while *progress-process*
(suspend)
)

View file

@ -922,6 +922,8 @@
;; draw and update menus
(with-profiler 'menu-hook *profile-menu-hook-color*
(*menu-hook*)
(when *speedrun-menu*
(draw! (-> *speedrun-menu* 0)))
)
;; load text files as needed from the menu update

View file

@ -3308,6 +3308,31 @@
)
:want-sound (new 'static 'array symbol 3 'ctywide1 'forexit1 'forexit2)
)
;; og:preserve-this Added to enable fast-game-starts with hero mode
(new 'static 'continue-point
:name "game-start-hero"
:level 'prison
:flags (continue-flags game-start hero-mode)
:trans (new 'static 'vector :x 1942413.2 :y 34479.31 :z 275525.62 :w 1.0)
:quat (new 'static 'vector :y 0.4562 :w 0.8898)
:camera-trans (new 'static 'vector :x 1921090.8 :y 53425.766 :z 237949.75 :w 1.0)
:camera-rot (new 'static 'inline-array vector3s 3
(new 'static 'vector3s :data (new 'static 'array float 3 0.869 0.0 -0.4947))
(new 'static 'vector3s :data (new 'static 'array float 3 0.0663 0.9909 0.1165))
(new 'static 'vector3s :data (new 'static 'array float 3 0.4903 -0.134 0.8611))
)
:on-goto #f
:vis-nick 'prison
:want (new 'static 'inline-array level-buffer-state 6
(new 'static 'level-buffer-state :name 'prison :display? 'display :force-vis? #f :force-inside? #f)
(new 'static 'level-buffer-state :name 'forexita :display? #f :force-vis? #f :force-inside? #f)
(new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
(new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
(new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
(new 'static 'level-buffer-state :name #f :display? #f :force-vis? #f :force-inside? #f)
)
:want-sound (new 'static 'array symbol 3 'ctywide1 'forexit1 'forexit2)
)
(new 'static 'continue-point
:name "prison-intro-start"
:level 'prison
@ -15698,4 +15723,4 @@
(cons! *level-load-list* 'teststdd)
(cons! *level-load-list* 'wasall)
(cons! *level-load-list* 'stadocc)
)
)

View file

@ -293,6 +293,14 @@
)
(cond
((logtest? (-> arg0 flags) (continue-flags game-start))
;; og:preserve-this Added to make fast-game-start work with hero-mode
(when (logtest? (-> arg0 flags) (continue-flags hero-mode))
(logior! (-> self game secrets) (game-secrets hero-mode))
(logior! (-> self game purchase-secrets) (game-secrets hero-mode))
;; TODO - there might be a better way to do this, the way hero-mode is set kinda feels like a side-effect
;; `update-task-masks` gets called during the `intro-start-hero` via `setting-control::apply-settings`
;; Which runs the following line if hero-mode is enabled
(set! (-> *game-info* features) (game-feature gun gun-yellow gun-red gun-blue gun-dark)))
(case *kernel-boot-message*
(('kiosk)
(let ((s5-5 (ppointer->handle (auto-save-command 'restore 0 0 *default-pool* #f))))

View file

@ -86,15 +86,22 @@
arg0
)
(defun progress-intro-start ((arg0 symbol))
(defun progress-intro-start ((hero-mode? symbol))
(set! (-> *game-info* mode) 'play)
(if arg0
(initialize! *game-info* 'game (the-as game-save #f) "intro-start-hero")
(initialize! *game-info* 'game (the-as game-save #f) "intro-start")
)
(cond
;; Start a new game differently if speedrunning mode is active
((= (-> *pc-settings* speedrunner-mode?) #t)
(if hero-mode?
(set-category! *speedrun-info* (speedrun-category newgame-heromode))
(set-category! *speedrun-info* (speedrun-category newgame-normal)))
(start-run! *speedrun-info*))
;; start the game normally
(else
(if hero-mode?
(initialize! *game-info* 'game (the-as game-save #f) "intro-start-hero")
(initialize! *game-info* 'game (the-as game-save #f) "intro-start"))))
(set-master-mode 'game)
0
)
0)
(defmethod init-defaults progress ((obj progress))
"Initialize default menu settings."

View file

@ -220,6 +220,8 @@
(define-extern pc-is-imgui-visible? (function symbol))
(define-extern pc-rand (function int))
(define-extern pc-encode-utf8-string (function string string none))
;; Used to dump fixture data for the editor, re-enable end-to-end if you need it
;; (define-extern has-level-been-dumped-lights? (function string symbol))
;; (define-extern has-level-been-dumped-regions? (function string symbol))

View file

@ -809,6 +809,8 @@
)
)
(define *pc-encoded-temp-string* (new 'global 'string 2048 (the-as string #f)))
(kmemclose)

View file

@ -7,7 +7,7 @@
;;
;; DO NOT change the order, appending to the end is safe!
(deftype autosplit-info-jak2 (structure)
(deftype autosplit-info (structure)
(;; Version Info
(version-major uint16)
(version-minor uint16)
@ -127,8 +127,9 @@
(res-stadium-burning-bush-race-class1-r uint8)
;; TODO - orbs in level X
;; end marker just to make things look nice in a memory view
(end-marker uint8 4)))
(end-marker uint8 4))
(:methods
(reset! (_type_) none)
(update! (_type_) none)))
(define-extern *autosplit-info-jak2* autosplit-info-jak2)
(define-extern update-autosplit-info-jak2 (function none))
(define-extern update-autosplit-jak2-new-game (function none))
(define-extern *autosplit-info-jak2* autosplit-info)

View file

@ -1,7 +1,7 @@
;;-*-Lisp-*-
(in-package goal)
(define *autosplit-info-jak2* (new 'static 'autosplit-info-jak2))
(define *autosplit-info-jak2* (new 'static 'autosplit-info))
(pc-init-autosplitter-struct)
;; Setup Version
(set! (-> *autosplit-info-jak2* version-major) 0)
@ -14,16 +14,14 @@
(defmacro autosplit-flag-task-complete! (field-name task-name)
"Given a field name in the autosplitter struct, and a [[game-task]] name to check, sets either a 0 or a 1"
`(set! (-> *autosplit-info-jak2* ,field-name) (if (task-complete? *game-info* (game-task ,task-name)) 1 0)))
`(set! (-> this ,field-name) (if (task-complete? *game-info* (game-task ,task-name)) 1 0)))
(defun update-autosplit-info-jak2 ()
(defmethod update! autosplit-info ((this autosplit-info))
;; general statistics
(set! (-> *autosplit-info-jak2* num-orbs) (the int (-> *game-info* skill-total)))
(set! (-> *autosplit-info-jak2* num-skullgems) (the int (-> *game-info* gem-total)))
(set! (-> this num-orbs) (the int (-> *game-info* skill-total)))
(set! (-> this num-skullgems) (the int (-> *game-info* gem-total)))
;; loading/cutscene related flags
(set! (-> *autosplit-info-jak2* in-cutscene?) (if (movie?) 1 0))
(set! (-> this in-cutscene?) (if (movie?) 1 0))
;; need resolution flags
(autosplit-flag-task-complete! res-fortress-escape fortress-escape)
(autosplit-flag-task-complete! res-city-help-kid city-help-kid)
@ -129,10 +127,9 @@
(autosplit-flag-task-complete! res-stadium-burning-bush-race-class3-r stadium-burning-bush-race-class3-r)
(autosplit-flag-task-complete! res-stadium-burning-bush-race-class2-r stadium-burning-bush-race-class2-r)
(autosplit-flag-task-complete! res-stadium-burning-bush-race-class1-r stadium-burning-bush-race-class1-r)
(none))
(defun update-autosplit-jak2-new-game ()
(set! (-> *autosplit-info-jak2* game-hash) (pc-get-unix-timestamp))
(defmethod reset! autosplit-info ((this autosplit-info))
(set! (-> this game-hash) (pc-get-unix-timestamp))
(none))

View file

@ -5,32 +5,41 @@
(defenum speedrun-category
:type uint32
;; Main Categories
(full-game 0) ;; Full game run (any category for now, can repurpose as Any% if we split them out later)
;; (full-game-100 1) ;; 100%
;; (full-game-allMission 2) ;; All Missions
;; Individual Levels
(il-placeholder1 100) ;; Geyser Rock IL
(il-placeholdere3 101) ;; Sandover Village IL
(il-placeholder3 102) ;; Sentinel Beach IL
;; Extension Categories (TBD)
(newgame-normal 0)
(newgame-heromode 1)
;; TODO - add ILs and such later
;; there's no point in adding categories that just start from a new-game and have later restrictions
;; because we aren't going to modify the code to make that possible
;; ie. removing mars tomb skip if you pick "all missions"
)
(deftype speedrun-info (structure)
((category speedrun-category)
(display-run-info? symbol))
(:methods
(set-category! (_type_ speedrun-category) none)
(start-run! (_type_) none)
(enforce-settings! (_type_) none)
(hide-run-info! (_type_) none)
(update! (_type_) none)
(draw-run-info! (_type_) none)))
(deftype speedrun-info-jak2 (structure)
(
(category speedrun-category)
(needs-post-blackout-setup? symbol)
(should-display? symbol)
)
)
(define-extern *speedrun-info* speedrun-info)
(define-extern start-speedrun (function speedrun-category none))
(define-extern is-speedrun-category? (function symbol symbol))
(define-extern hide-speedrun-display (function none))
(define-extern speedrun-start-full-game-run (function none))
(define-extern setup-speedrun-post-blackout (function none))
(define-extern speedrun-mode-update (function none))
(define-extern speedrun-draw-settings (function none))
(defenum speedrun-menu-command
:type uint32
(reset 0)
(exit 1))
(deftype speedrun-menu (process-drawable)
((popup-menu popup-menu)
(draw-menu? symbol)
(ignore-menu-toggle? symbol))
(:methods
(draw! (_type_) none))
(:states
idle))
(define-extern *speedrun-popup-menu* popup-menu)
(define-extern *speedrun-menu* (pointer speedrun-menu))
(define-extern speedrun-menu-init (function none :behavior speedrun-menu))

View file

@ -1,87 +1,160 @@
;;-*-Lisp-*-
(in-package goal)
(define *speedrun-info* (new 'static 'speedrun-info-jak2 :should-display? #t :needs-post-blackout-setup? #f))
(define *speedrun-info* (new 'static 'speedrun-info))
(defun is-speedrun-category? ((category symbol))
(and (-> *pc-settings* speedrunner-mode?)
(name= category (enum->string speedrun-category (-> *speedrun-info* category)))
)
)
(defmethod set-category! speedrun-info ((this speedrun-info) (category speedrun-category))
(set! (-> this category) category)
(none))
(defun start-speedrun ((category speedrun-category))
(defmethod start-run! speedrun-info ((this speedrun-info))
;; randomize game id so the autosplitter knows to restart
(update-autosplit-jak2-new-game)
;; turn on speedrun verification display and flip flag for setting up speedrun after initialize!
(set! (-> *speedrun-info* should-display?) #t)
;; start new game with specified checkpoint, if any (otherwise we're resetting current category)
(when category
(set! (-> *speedrun-info* category) category))
;; TODO - ensure any required settings are enabled
(set-frame-rate! *pc-settings* 60 #t)
(none)
)
(reset! *autosplit-info-jak2*)
;; turn on speedrun verification display
(set! (-> this display-run-info?) #t)
;; ensure any required settings are enabled
(enforce-settings! this)
;; finalize any category specific setup code
(case (-> this category)
(((speedrun-category newgame-normal))
(initialize! *game-info* 'game (the-as game-save #f) "game-start"))
(((speedrun-category newgame-heromode))
(initialize! *game-info* 'game (the-as game-save #f) "game-start-hero")))
;; enable auto saving by default, no downside on PC
;; this has to come after the `initialize!` call as it sets it to false!
(set! (-> *setting-control* user-default auto-save) #t)
(none))
;; TODO - fix me
(define post-blackout? #f)
(defmethod enforce-settings! speedrun-info ((this speedrun-info))
(set! (-> *pc-settings* ps2-actor-vis?) #t) ;; force PS2 actor visibility
(set-frame-rate! *pc-settings* 60 #t) ;; force FPS to `60`
(set! (-> *pc-settings* cheats) (the-as pc-cheats #x0)) ;; disable any active cheats
(none))
(defun setup-speedrun-post-blackout ()
(when post-blackout?
(set! (-> *speedrun-info* needs-post-blackout-setup?) #f)
(case (-> *speedrun-info* category)
(((speedrun-category full-game))
;; setup a full-game run here
(none)
)
(else
;;speedrun-category was not recognized, print an error to the screen and maybe play a sound.
)
)
;; reset speedrun display (gets hidden on first collectable pickup)
(set! (-> *speedrun-info* should-display?) #t)
;; reset actors to ensure any above changes take effect
(reset-actors 'life)
;; autosave any changes back to file
(auto-save-command 'auto-save 0 0 *default-pool* #f)
)
(none)
)
(defmethod hide-run-info! speedrun-info ((this speedrun-info))
(set! (-> this display-run-info?) #f)
(none))
(defun hide-speedrun-display ()
(set! (-> *speedrun-info* should-display?) #f)
(none)
)
(defun speedrun-mode-update ()
(defmethod update! speedrun-info ((this speedrun-info))
"A per frame update for speedrunning related stuff"
;; Ensure the speedrunner menu process is enabled or destroyed
(when (and (-> *pc-settings* speedrunner-mode?)
(not *speedrun-menu*))
(process-spawn speedrun-menu :init speedrun-menu-init #f :to *entity-pool*))
(when (and (not (-> *pc-settings* speedrunner-mode?))
*speedrun-menu*)
(deactivate (-> *speedrun-menu* 0)))
;; do speedrunner mode things
(when (-> *pc-settings* speedrunner-mode?)
;; Update auto-splitter
(update-autosplit-info-jak2)
;; Draw info to the screen
(speedrun-draw-settings)
;;Disable any active cheats
;; (set! (-> *pc-settings* cheats) (the-as pc-cheats #x0))
;; Run after-blackout speedrun setup (if needed)
(setup-speedrun-post-blackout)
)
;; Update auto-splitter struct
(update! *autosplit-info-jak2*)
;; see if we should stop drawing the run info (when you escape the fortress!)
(when (task-complete? *game-info* (game-task fortress-escape))
(set! (-> this display-run-info?) #f))
(when (-> this display-run-info?)
;; Draw info to the screen
(draw-run-info! this))
;; enforce settings even if they've changed them
(enforce-settings! this))
(none))
(defun speedrun-start-full-game-run ()
;; start a full game speedrun, save file is already selected so don't default to first slot
(start-speedrun (speedrun-category full-game))
(none))
(defun speedrun-draw-settings ()
(defmethod draw-run-info! speedrun-info ((this speedrun-info))
"Draw speedrun related settings in the bottom left corner"
(when (and (-> *pc-settings* speedrunner-mode?)
(not (paused?))
(-> *speedrun-info* should-display?))
(with-dma-buffer-add-bucket ((buf (-> (current-frame) global-buf))
(bucket-id debug-no-zbuf1))
(draw-string-xy (string-format "OpenGOAL Version: ~S ~%Speedrun mode: ~A ~%Category: ~S ~%Is fortress escaped: ~D"
*pc-settings-built-sha*
(-> *pc-settings* speedrunner-mode?)
(enum->string speedrun-category (-> *speedrun-info* category))
(-> *autosplit-info-jak2* res-fortress-escape))
buf 0 (- 220 (* 8 4)) (font-color progress-old-yellow) (font-flags shadow kerning))))
(-> this display-run-info?))
(clear *temp-string*)
(format *temp-string* "<COLOR_WHITE>PC Cheats: <COLOR_GREEN>~D~%<COLOR_WHITE>Frame Rate: <COLOR_GREEN>~D~%<COLOR_WHITE>PS2 Actor Vis?: <COLOR_GREEN>~S~%<COLOR_WHITE>Version: <COLOR_GREEN>~S~%"
(the-as int (-> *pc-settings* cheats))
(-> *pc-settings* target-fps)
(if (-> *pc-settings* ps2-actor-vis?) "true" "false")
*pc-settings-built-sha*)
(pc-encode-utf8-string *temp-string* *pc-encoded-temp-string*)
(with-dma-buffer-add-bucket ((buf (-> (current-frame) global-buf)) (bucket-id debug-no-zbuf1))
(let ((font-ctx (new 'stack 'font-context *font-default-matrix* 510 375 0.0 (font-color default) (font-flags right shadow kerning large))))
(set! (-> font-ctx scale) 0.325)
(draw-string-adv *pc-encoded-temp-string* buf font-ctx))))
(none))
;; Speedrun Menu
(define *speedrun-popup-menu*
(new 'static 'popup-menu
:entries (new 'static 'boxed-array :type popup-menu-entry
(new 'static 'popup-menu-button :label "Reset" :on-press (lambda () (send-event (ppointer->process *speedrun-menu*) 'invoke (speedrun-menu-command reset))))
(new 'static 'popup-menu-button :label "Exit" :on-press (lambda () (send-event (ppointer->process *speedrun-menu*) 'invoke (speedrun-menu-command exit))))
)
)
)
(define *speedrun-menu* (the-as (pointer speedrun-menu) #f))
(defbehavior speedrun-menu-init speedrun-menu ()
(set! *speedrun-menu* (the-as (pointer speedrun-menu) (process->ppointer self)))
(set! (-> *speedrun-menu* 0 popup-menu) *speedrun-popup-menu*)
(set! (-> *speedrun-menu* 0 draw-menu?) #f)
(set! (-> *speedrun-menu* 0 ignore-menu-toggle?) #f)
(go idle)
(none))
(defmethod deactivate speedrun-menu ((this speedrun-menu))
(set! *speedrun-menu* (the-as (pointer speedrun-menu) #f))
((method-of-type process-drawable deactivate) this)
(none))
(defstate idle (speedrun-menu)
:event (behavior ((proc process) (arg1 int) (event-type symbol) (event event-message-block))
(case event-type
(('invoke)
(case (-> event param 0)
(((speedrun-menu-command reset))
(start-run! *speedrun-info*))
(((speedrun-menu-command exit))
(set-master-mode 'game)
(set! (-> self draw-menu?) #f))
(else
(format 0 "nyi: invoke ~D~%" (-> event param 0))))))
(the-as object 0))
:trans (behavior ()
(none))
:code (behavior ()
(until #f (suspend) )
(none))
:post (behavior ()
(none)))
(defmethod draw! speedrun-menu ((this speedrun-menu))
;; handle opening and closing the menu
;; allow the menu to be toggled again once one of the currents is released
(when (and (-> this ignore-menu-toggle?)
(or (not (cpad-hold? 0 l1)) (not (cpad-hold? 0 r1)) (not (cpad-hold? 0 select))))
(set! (-> this ignore-menu-toggle?) #f))
(when (and (cpad-hold? 0 l1) (cpad-hold? 0 r1) (cpad-hold? 0 select)
(not (-> this ignore-menu-toggle?)))
(cond
((= *master-mode* 'game)
(set-master-mode 'menu)
(set! (-> this draw-menu?) #t))
((= *master-mode* 'menu)
(set-master-mode 'game)
(set! (-> this draw-menu?) #f)))
(logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons l1))
(logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons l1))
(logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons r1))
(logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons r1))
(logclear! (-> *cpad-list* cpads 0 button0-abs 0) (pad-buttons select))
(logclear! (-> *cpad-list* cpads 0 button0-rel 0) (pad-buttons select))
(set! (-> this ignore-menu-toggle?) #t))
(when (-> this draw-menu?)
;; handle any inputs for within the menu
(cond
((cpad-pressed? 0 triangle select)
(set! (-> this draw-menu?) #f))
((cpad-pressed? 0 up)
(move-up! (-> this popup-menu)))
((cpad-pressed? 0 down)
(move-down! (-> this popup-menu)))
((cpad-pressed? 0 x)
(press! (-> this popup-menu))))
;; draw it
(draw! (-> this popup-menu)))
(none))

View file

@ -161,15 +161,17 @@
(set! (-> info time-of-day) (-> *time-of-day-context* time))
(set! (-> info percent-complete) (calculate-percentage *game-info*))
(set! (-> info focus-status) (if *target* (-> *target* focus-status) 0))
;; TODO - wrapping in `with-profiler` causes an error, fix it
;; TODO - update to new with-profiler syntax
(pc-discord-rpc-update info)
)
(none))
(defmethod update-speedrun pc-settings-jak2 ((obj pc-settings-jak2))
"update speedrun module"
(when (-> *pc-settings* speedrunner-mode?)
(speedrun-mode-update))
;; TODO - update to new with-profiler syntax
;; (with-profiler "speedrun-update"
(update! *speedrun-info*)
;;)
(none))
(defmethod update-video-hacks pc-settings-jak2 ((obj pc-settings-jak2))

View file

@ -0,0 +1,25 @@
;;-*-Lisp-*-
(in-package goal)
;; A debug-menu style popup menu, a lightweight way to make a context menu that doesn't involve the progress code
;; and isn't debug-only
;;
;; Currently only supports a single 1-level menu of buttons, add more features as required
(deftype popup-menu-entry (basic)
((label string)
(on-press (function none)))
(:methods
(draw! (_type_ font-context dma-buffer) none)))
(deftype popup-menu-button (popup-menu-entry) ())
(deftype popup-menu (basic)
((entries (array popup-menu-entry))
(curr-entry-index int32))
(:methods
(draw! (_type_) none)
(move-up! (_type_) none)
(move-down! (_type_) none)
(press! (_type_) none)
(get-widest-label (_type_ font-context) float)))

View file

@ -0,0 +1,61 @@
;;-*-Lisp-*-
(in-package goal)
(defmethod draw! popup-menu-entry ((this popup-menu-entry) (font-ctx font-context) (dma-buf dma-buffer))
(none))
(defmethod draw! popup-menu-button ((this popup-menu-button) (font-ctx font-context) (dma-buf dma-buffer))
(let ((old-x (-> font-ctx origin x))
(old-y (-> font-ctx origin y)))
(pc-encode-utf8-string (-> this label) *pc-encoded-temp-string*)
(draw-string-adv *pc-encoded-temp-string* dma-buf font-ctx)
(set! (-> font-ctx origin x) old-x)
(set! (-> font-ctx origin y) old-y))
(none))
(defmethod draw! popup-menu ((this popup-menu))
(let ((font-ctx (new 'debug 'font-context *font-default-matrix* 0 0 0.0 (font-color default) (font-flags shadow kerning large))))
(set! (-> font-ctx scale) 0.35)
(set! (-> font-ctx origin x) 15.0)
(set! (-> font-ctx origin y) 75.0)
(with-dma-buffer-add-bucket ((buf (-> (current-frame) global-buf)) (bucket-id debug-no-zbuf1))
;; background border
(draw-sprite2d-xy buf 6 64
(+ 17 (the int (get-widest-label this font-ctx))) ;; width
(+ 17 (* 15 (-> this entries length))) ;; height
(new 'static 'rgba :r 255 :g 255 :b 255 :a 75))
;; background
(draw-sprite2d-xy buf 7 65
(+ 15 (the int (get-widest-label this font-ctx))) ;; width
(+ 15 (* 15 (-> this entries length))) ;; height
(new 'static 'rgba :r 0 :g 0 :b 0 :a 255))
;; menu contents
(dotimes (i (-> this entries length))
(if (= i (-> this curr-entry-index))
(set! (-> font-ctx color) (font-color cyan))
(set! (-> font-ctx color) (font-color default)))
(draw! (-> this entries i) font-ctx buf)
(set! (-> font-ctx origin y) (+ 15.0 (-> font-ctx origin y)))))
)
(none))
(defmethod move-up! popup-menu ((this popup-menu))
(set! (-> this curr-entry-index) (max 0 (dec (-> this curr-entry-index))))
(none))
(defmethod move-down! popup-menu ((this popup-menu))
(set! (-> this curr-entry-index) (min (dec (-> this entries length)) (inc (-> this curr-entry-index))))
(none))
(defmethod press! popup-menu ((this popup-menu))
(let ((entry (-> this entries (-> this curr-entry-index))))
((-> entry on-press)))
(none))
(defmethod get-widest-label popup-menu ((this popup-menu) (font-ctx font-context))
(let ((max-len 0.0))
(dotimes (i (-> this entries length))
(let ((label-len (-> (get-string-length (-> this entries i label) font-ctx) length)))
(when (> label-len max-len)
(set! max-len label-len))))
max-len))