From efdc598c0997b38a449cb81df7b1f2d57a1e71c0 Mon Sep 17 00:00:00 2001 From: ManDude <7569514+ManDude@users.noreply.github.com> Date: Mon, 16 Aug 2021 07:44:05 +0100 Subject: [PATCH] make pc pad remapping process (incomplete) --- game/graphics/gfx.cpp | 10 ++ game/graphics/gfx.h | 10 +- game/kernel/kmachine.cpp | 4 +- game/system/newpad.cpp | 43 ++++-- game/system/newpad.h | 5 +- goal_src/engine/gfx/hw/display-h.gc | 8 ++ goal_src/engine/util/types-h.gc | 5 +- goal_src/kernel-defs.gc | 4 + goal_src/kernel/gstate.gc | 18 ++- goal_src/pc_debug/pc-pad-utils.gc | 202 +++++++++++++++++++++++----- 10 files changed, 258 insertions(+), 51 deletions(-) diff --git a/game/graphics/gfx.cpp b/game/graphics/gfx.cpp index a4bc089019..122fffaaf6 100644 --- a/game/graphics/gfx.cpp +++ b/game/graphics/gfx.cpp @@ -9,6 +9,8 @@ #include "display.h" #include "pipelines/opengl.h" +#include "game/kernel/kscheme.h" +#include "common/symbols.h" #include "common/log/log.h" #include "game/runtime.h" #include "game/system/newpad.h" @@ -131,6 +133,14 @@ void poll_events() { g_settings.renderer->poll_events(); } +void input_mode_set(u32 enable) { + if (enable == s7.offset + FIX_SYM_TRUE) { // #t + Pad::EnterInputMode(); + } else { + Pad::ExitInputMode(enable != s7.offset); // use #f for graceful exit, or 'canceled for abrupt + } +} + int PadIsPressed(Pad::Button button, int port) { return Pad::IsPressed(g_settings.pad_mapping_info, button, port); } diff --git a/game/graphics/gfx.h b/game/graphics/gfx.h index 431090d0e5..92ca95fff7 100644 --- a/game/graphics/gfx.h +++ b/game/graphics/gfx.h @@ -42,12 +42,13 @@ struct GfxRendererModule { struct GfxSettings { // current version of the settings. this should be set up so that newer versions are always higher // than older versions - static constexpr u64 CURRENT_VERSION = 0x0000'0000'0002'0001; + static constexpr u64 CURRENT_VERSION = 0x0000'0000'0003'0001; + + u64 version; // the version of this settings struct + int vsync; // (temp) number of screen update per frame + bool debug; // graphics debugging - u64 version; // the version of this settings struct const GfxRendererModule* renderer; // which rendering pipeline to use. - int vsync; // (temp) number of screen update per frame - bool debug; // graphics debugging Pad::MappingInfo pad_mapping_info; // button mapping Pad::MappingInfo pad_mapping_info_backup; // button mapping backup (see newpad.h) @@ -70,6 +71,7 @@ void send_chain(const void* data, u32 offset); void texture_upload_now(const u8* tpage, int mode, u32 s7_ptr); void texture_relocate(u32 destination, u32 source, u32 format); void poll_events(); +void input_mode_set(u32 enable); int PadIsPressed(Pad::Button button, int port); diff --git a/game/kernel/kmachine.cpp b/game/kernel/kmachine.cpp index 30cc6dd578..8a0d1f08a1 100644 --- a/game/kernel/kmachine.cpp +++ b/game/kernel/kmachine.cpp @@ -717,8 +717,10 @@ void InitMachine_PCPort() { make_function_symbol_from_c("__pc-texture-relocate", (void*)pc_texture_relocate); // pad stuff - make_function_symbol_from_c("pc-pad-input-mode-set", (void*)Pad::input_mode_set); + make_function_symbol_from_c("pc-pad-input-mode-set", (void*)Gfx::input_mode_set); make_function_symbol_from_c("pc-pad-input-mode-get", (void*)Pad::input_mode_get); + make_function_symbol_from_c("pc-pad-input-key-get", (void*)Pad::input_mode_get_key); + make_function_symbol_from_c("pc-pad-input-index-get", (void*)Pad::input_mode_get_index); // init ps2 VM if (VM::use) { diff --git a/game/system/newpad.cpp b/game/system/newpad.cpp index 0a5ec76e5b..e715adb882 100644 --- a/game/system/newpad.cpp +++ b/game/system/newpad.cpp @@ -22,9 +22,18 @@ std::unordered_map g_key_status; std::unordered_map g_buffered_key_status; // input mode for controller mapping -bool input_mode = false; +// this enum is also in pc-pad-utils.gc +enum class InputModeStatus { + Disabled, + Enabled, + Canceled +}; +InputModeStatus input_mode = InputModeStatus::Disabled; +u64 input_mode_pad = 0; u64 input_mode_key = -1; u64 input_mode_mod = 0; +u64 input_mode_index = 0; +MappingInfo input_mode_mapping; void ForceClearKeys() { g_key_status.clear(); @@ -39,12 +48,16 @@ void ClearKeys() { } void OnKeyPress(int key) { - if (input_mode) { + if (input_mode == InputModeStatus::Enabled) { if (key == GLFW_KEY_ESCAPE) { - input_mode = false; + ExitInputMode(true); return; } input_mode_key = key; + MapButton(input_mode_mapping, (Button)(input_mode_index++), input_mode_pad, key); + if (input_mode_index > (u64)Button::Max) { + ExitInputMode(false); + } return; } // set absolute key status @@ -63,7 +76,7 @@ void OnKeyPress(int key) { } void OnKeyRelease(int key) { - if (input_mode) { + if (input_mode == InputModeStatus::Enabled) { return; } // set absolute key status @@ -126,16 +139,26 @@ void DefaultMapping(MappingInfo& mapping) { MapButton(mapping, Button::Left, 0, GLFW_KEY_LEFT); } -void input_mode_set(u32 enable) { - if (enable != s7.offset) { - input_mode = true; - } else { - input_mode = false; - } +void EnterInputMode() { + input_mode = InputModeStatus::Enabled; + input_mode_index = 0; + input_mode_pad = 0; +} + +void ExitInputMode(bool canceled) { + input_mode = canceled ? InputModeStatus::Canceled : InputModeStatus::Disabled; } u64 input_mode_get() { + return (u64)input_mode; +} + +u64 input_mode_get_key() { return input_mode_key; } +u64 input_mode_get_index() { + return input_mode_index; +} + }; // namespace Pad diff --git a/game/system/newpad.h b/game/system/newpad.h index a2cd77cc89..fa09694a9d 100644 --- a/game/system/newpad.h +++ b/game/system/newpad.h @@ -72,7 +72,10 @@ void DefaultMapping(MappingInfo& mapping); int IsPressed(MappingInfo& mapping, Button button, int pad); void MapButton(MappingInfo& mapping, Button button, int pad, int key); -void input_mode_set(u32 enable); +void EnterInputMode(); +void ExitInputMode(bool); u64 input_mode_get(); +u64 input_mode_get_key(); +u64 input_mode_get_index(); } // namespace Pad diff --git a/goal_src/engine/gfx/hw/display-h.gc b/goal_src/engine/gfx/hw/display-h.gc index 56b8669906..f9d01521e7 100644 --- a/goal_src/engine/gfx/hw/display-h.gc +++ b/goal_src/engine/gfx/hw/display-h.gc @@ -234,3 +234,11 @@ (defmacro current-display-frame (&rest args) `(-> *display* frames (-> *display* on-screen) frame ,@args) ) + +(defmacro current-time () + `(-> *display* base-frame-counter) + ) + +(defmacro integral-current-time () + `(-> *display* integral-frame-counter) + ) diff --git a/goal_src/engine/util/types-h.gc b/goal_src/engine/util/types-h.gc index 1e1554bf9b..fa02edbd54 100644 --- a/goal_src/engine/util/types-h.gc +++ b/goal_src/engine/util/types-h.gc @@ -83,9 +83,12 @@ "Convert number to seconds unit. Returns uint." (cond - ((or (integer? x) (float? x)) + ((integer? x) (* TICKS_PER_SECOND x) ) + ((float? x) + (* 1 (* 1.0 x TICKS_PER_SECOND)) + ) (#t `(the uint (* TICKS_PER_SECOND ,x)) ) diff --git a/goal_src/kernel-defs.gc b/goal_src/kernel-defs.gc index e474ed451d..2faedcc56d 100644 --- a/goal_src/kernel-defs.gc +++ b/goal_src/kernel-defs.gc @@ -268,6 +268,10 @@ (define-extern __send-gfx-dma-chain (function object object none)) (define-extern __pc-texture-upload-now (function object object none)) (define-extern __pc-texture-relocate (function object object object none)) +(define-extern pc-pad-input-mode-set (function symbol none)) +(define-extern pc-pad-input-mode-get (function int)) +(define-extern pc-pad-input-key-get (function int)) +(define-extern pc-pad-input-index-get (function int)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; vm functions diff --git a/goal_src/kernel/gstate.gc b/goal_src/kernel/gstate.gc index c3388ed83f..5cdf6aeb96 100644 --- a/goal_src/kernel/gstate.gc +++ b/goal_src/kernel/gstate.gc @@ -82,7 +82,7 @@ There are several ways to "go" (defmacro make-function-process (dead-pool new-pool proc-type proc-name func &key (stack-size #x4000) &key (stack *kernel-dram-stack*) &rest args) "Start a new process that runs a function on its main thread. - Returns a pointer to the new process (or #f on error)." + Returns a pointer to the new process (or #f? on error)." (with-gensyms (new-proc) `(let ((,new-proc (the-as ,proc-type (get-process ,dead-pool ,proc-type ,stack-size)))) @@ -418,7 +418,21 @@ There are several ways to "go" #f ) - +(defmacro set-state-time () + "set the state-time field of the current object to the current time. process-drawable has one" + + `(set! (-> self state-time) (current-time)) + ) + +(defmacro time-passed () + "how much time has passed since set-state-time" + `(- (current-time) (-> self state-time)) + ) + +(defmacro time-passed? (time) + "has it been 'time' since set-state-time?" + `(>= (time-passed) ,time) + ) diff --git a/goal_src/pc_debug/pc-pad-utils.gc b/goal_src/pc_debug/pc-pad-utils.gc index 66247dc3cf..c8b0e75917 100644 --- a/goal_src/pc_debug/pc-pad-utils.gc +++ b/goal_src/pc_debug/pc-pad-utils.gc @@ -17,18 +17,60 @@ (ml "goal_src/pc_debug/pc-pad-utils.gc") ;; build and load this file. |# -(if *debug-segment* (begin +(cond (*debug-segment* -(define *pc-pad-show-proc* (the handle #f)) -(define *pc-pad-input-proc* (the handle #f)) +(deftype pc-pad-proc-list (basic) + ((show handle) + (input handle) + ) + ) +(define *pc-pad-proc-list* (new 'static 'pc-pad-proc-list)) +(set! (-> *pc-pad-proc-list* show) (the handle #f)) +(set! (-> *pc-pad-proc-list* input) (the handle #f)) + +(deftype pc-pad-proc (process) + ((state-time seconds) + (input-index uint64) + ) + :heap-base #x10 + ) + +(define *pc-pad-button-names* + (new 'static 'array string 16 + "SELECT" + "L3" + "R3" + "START" + + "UP" + "RIGHT" + "DOWN" + "LEFT" + + "L2" + "R2" + "L1" + "R1" + + "TRIANGLE" + "CIRCLE" + "X" + "SQUARE" + )) + +(defenum pc-pad-input-status + (disabled) + (enabled) + (canceled) + ) (defun-debug pc-pad-show-start () "Start the PC port pad debug display" - (if (not (handle->process *pc-pad-show-proc*)) - (set! *pc-pad-show-proc* (ppointer->handle - (make-function-process *nk-dead-pool* *active-pool* process 'pc-pad-show - (lambda :behavior process () + (if (not (handle->process (-> *pc-pad-proc-list* show))) + (let ((procp + (make-function-process *nk-dead-pool* *active-pool* pc-pad-proc 'pc-pad-show + (lambda :behavior pc-pad-proc () (stack-size-set! (-> self main-thread) 512) (loop (let ((cpad (-> *cpad-list* cpads 0))) @@ -46,8 +88,10 @@ ) ) )) + (set! (-> *pc-pad-proc-list* show) (ppointer->handle procp)) + ) - (format #t "That process is already running. :-)") + (format #t "That process is already running. :-)~%") ) ) @@ -57,36 +101,130 @@ (kill-by-name 'pc-pad-show *active-pool*) ) + +(defconstant PC_PAD_INPUT_NOTICE_TIME (seconds 1.5)) + + +(define-extern pc-pi-mapping-button state) + +(defstate pc-pi-new-mapping (pc-pad-proc) + + :enter (behavior () (set! (-> self input-index) (pc-pad-input-index-get)) ) + :code (behavior () + (set-state-time) + (until (time-passed? PC_PAD_INPUT_NOTICE_TIME) + (with-dma-buffer-add-bucket ((buf (current-display-frame debug-buf)) + (current-display-frame bucket-group) + (bucket-id debug-draw1)) + (draw-string-xy (string-format "MAPPED ~D FOR ~S!" + (pc-pad-input-key-get) (-> *pc-pad-button-names* (1- (-> self input-index)))) + buf 256 96 (font-color green) (font-flags shadow kerning large middle)) + ) + (suspend) + ) + (go pc-pi-mapping-button) + ) + :trans (behavior () + (if (or (!= (-> self input-index) (pc-pad-input-index-get)) + (!= (pc-pad-input-mode-get) (pc-pad-input-status enabled))) + ;; something's changed, go back to the main state and check everything + (go pc-pi-mapping-button) + ) + ) + + ) + +(defstate pc-pi-canceled (pc-pad-proc) + + :code (behavior () + (set-state-time) + (until (time-passed? PC_PAD_INPUT_NOTICE_TIME) + (with-dma-buffer-add-bucket ((buf (current-display-frame debug-buf)) + (current-display-frame bucket-group) + (bucket-id debug-draw1)) + (draw-string-xy "CANCELED!" buf 256 96 (font-color red-reverse) (font-flags shadow kerning large middle)) + ) + (suspend) + ) + ) + ) + +(defstate pc-pi-done (pc-pad-proc) + + :code (behavior () + (set-state-time) + (until (time-passed? PC_PAD_INPUT_NOTICE_TIME) + (with-dma-buffer-add-bucket ((buf (current-display-frame debug-buf)) + (current-display-frame bucket-group) + (bucket-id debug-draw1)) + (draw-string-xy "DONE!" buf 256 96 (font-color green) (font-flags shadow kerning large middle)) + ) + (suspend) + ) + ) + ) + +(defstate pc-pi-mapping-button (pc-pad-proc) + + :code (behavior () + (set-state-time) + (loop + (with-dma-buffer-add-bucket ((buf (current-display-frame debug-buf)) + (current-display-frame bucket-group) + (bucket-id debug-draw1)) + (if (< (mod (time-passed) (seconds 2)) (seconds 1)) + (draw-string-xy "NOW MAPPING PAD" buf 256 32 (font-color red) (font-flags shadow kerning large middle)) + ) + (draw-string-xy "PRESS ESCAPE TO EXIT" buf 256 64 (font-color default) (font-flags shadow kerning large middle)) + (draw-string-xy (string-format "PLEASE MAP FOR ~S" (-> *pc-pad-button-names* (-> self input-index))) + buf 256 96 (font-color default) (font-flags shadow kerning large middle)) + ) + (suspend) + ) + ) + :trans (behavior () + (cond + ;; canceled + ((= (pc-pad-input-mode-get) (pc-pad-input-status canceled)) + (go pc-pi-canceled) + ) + ;; finished + ((or (>= (pc-pad-input-index-get) 16) + (= (pc-pad-input-mode-get) (pc-pad-input-status disabled))) + (go pc-pi-done) + ) + ;; waiting input + ((= (-> self input-index) (pc-pad-input-index-get)) + ) + ;; one input has been done! + ((= (1+ (-> self input-index)) (pc-pad-input-index-get)) + (go pc-pi-new-mapping) + ) + ;; more than one input has been done. go to last mapping. + ((< (1+ (-> self input-index)) (pc-pad-input-index-get)) + (go pc-pi-new-mapping) + ) + ) + ) + + ) + (defun-debug pc-pad-input-start () "Start the PC port pad debug key mapping" - (if (not (handle->process *pc-pad-input-proc*)) - (set! *pc-pad-input-proc* (ppointer->handle - (make-function-process *nk-dead-pool* *active-pool* process 'pc-pad-input - (lambda :behavior process () - (stack-size-set! (-> self main-thread) 512) - (let ((start-time (get-current-time)) - (time-passed 0)) - (loop - (set! time-passed (- (the int (get-current-time)) start-time)) - - (with-dma-buffer-add-bucket ((buf (current-display-frame debug-buf)) - (current-display-frame bucket-group) - (bucket-id debug-draw1)) - (if (< (mod time-passed (seconds 2)) (seconds 1)) - (draw-string-xy "NOW MAPPING PAD" buf 256 64 (font-color red) (font-flags shadow kerning large middle)) - ) - - ) - - (suspend) - ) - ) + (if (not (handle->process (-> *pc-pad-proc-list* input))) + (let ((procp + (make-init-process *nk-dead-pool* *active-pool* pc-pad-proc 'pc-pad-input + (lambda :behavior pc-pad-proc () + (pc-pad-input-mode-set #t) + (go pc-pi-mapping-button) ) ) )) + (set! (-> *pc-pad-proc-list* input) (ppointer->handle procp)) + ) - (format #t "That process is already running. :-)") + (format #t "That process is already running. :-)~%") ) ) @@ -97,4 +235,4 @@ ) ) -(format #t "No debug memory in use. pc-pad-utils not loaded.")) \ No newline at end of file +(else (format #t "No debug memory in use. pc-pad-utils not loaded."))) \ No newline at end of file