From 4dd0c8bf2cd3bf30591dbdbb046f551a78ad8ca4 Mon Sep 17 00:00:00 2001
From: Tyler Wilding
Date: Sun, 14 Aug 2022 23:23:30 -0400
Subject: [PATCH 01/23] ref: update pad_REF (#1761)
---
test/decompiler/reference/jak1/engine/ps2/pad_REF.gc | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/test/decompiler/reference/jak1/engine/ps2/pad_REF.gc b/test/decompiler/reference/jak1/engine/ps2/pad_REF.gc
index 3071e8b4a9..cd1638ab7f 100644
--- a/test/decompiler/reference/jak1/engine/ps2/pad_REF.gc
+++ b/test/decompiler/reference/jak1/engine/ps2/pad_REF.gc
@@ -140,11 +140,11 @@
;; definition of type cpad-list
(deftype cpad-list (basic)
((num-cpads int32 :offset-assert 4)
- (cpads cpad-info 2 :offset-assert 8)
+ (cpads cpad-info 4 :offset-assert 8)
)
:method-count-assert 9
- :size-assert #x10
- :flag-assert #x900000010
+ :size-assert #x18
+ :flag-assert #x900000018
(:methods
(new (symbol type) _type_ 0)
)
From dee8feb00333f3510dd6900656d56d4a619dba96 Mon Sep 17 00:00:00 2001
From: ManDude <7569514+ManDude@users.noreply.github.com>
Date: Mon, 15 Aug 2022 23:46:29 +0100
Subject: [PATCH 02/23] fix a game bug and add a new compiler feature (#1758)
* dont crash on inline static value array
* [goalc] add support for non-static inline arrays of values
* add a kernel group to jak1
* move and cleanup pc debug code
* random cleanup in `hud-classes`
* pc port fix for gondola spools
* format
* address feedback (wow it was actually just changing 1 line all along...)
* minor decomp cleanup
* ref test
---
decompiler/config/all-types.gc | 2 +-
goal_src/goal-lib.gc | 5 ++
goal_src/jak1/engine/gfx/hw/display-h.gc | 9 +++
goal_src/jak1/engine/target/target-death.gc | 25 ++------
goal_src/jak1/engine/ui/hud-classes.gc | 41 +++----------
goal_src/jak1/examples/display-all-colors.gc | 61 -------------------
goal_src/jak1/game.gp | 8 +++
goal_src/jak1/levels/village3/village3-obs.gc | 10 ++-
goal_src/jak1/pc/util/display-font-color.gc | 52 ++++++++++++++++
.../{pc_debug => pc/util}/font-encode-test.gc | 39 +++++-------
.../{pc_debug => pc/util}/pc-pad-utils.gc | 14 ++---
goalc/compiler/compilation/Static.cpp | 8 ++-
goalc/compiler/compilation/Type.cpp | 11 ++--
.../jak1/engine/target/target-death_REF.gc | 26 ++------
14 files changed, 134 insertions(+), 177 deletions(-)
delete mode 100644 goal_src/jak1/examples/display-all-colors.gc
create mode 100644 goal_src/jak1/pc/util/display-font-color.gc
rename goal_src/jak1/{pc_debug => pc/util}/font-encode-test.gc (66%)
rename goal_src/jak1/{pc_debug => pc/util}/pc-pad-utils.gc (95%)
diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc
index ec87b74519..d4ff86ae98 100644
--- a/decompiler/config/all-types.gc
+++ b/decompiler/config/all-types.gc
@@ -21051,7 +21051,7 @@
(define-extern death-movie-remap (function int int int))
(define-extern pov-camera-init-by-other (function vector skeleton-group string pov-camera-flag process-drawable pair none :behavior pov-camera)) ;; TODO - not confirmed -- sunken-elevator
(define-extern target-hit-effect (function attack-info none :behavior target))
-(define-extern target-hit-setup-anim (function attack-info object :behavior target))
+(define-extern target-hit-setup-anim (function attack-info none :behavior target))
(define-extern target-hit-move (function attack-info symbol (function none :behavior target) float none :behavior target))
(define-extern target-hit-orient (function attack-info vector symbol :behavior target))
(define-extern target-hit-push (function vector matrix float float attack-info object :behavior target))
diff --git a/goal_src/goal-lib.gc b/goal_src/goal-lib.gc
index 226c131d1f..b5e08c8602 100644
--- a/goal_src/goal-lib.gc
+++ b/goal_src/goal-lib.gc
@@ -878,6 +878,11 @@
`(make-group "iso")
)
+(defmacro mkr ()
+ "Make kernel"
+ `(make-group "kernel")
+ )
+
(defmacro mng ()
"Make engine"
`(make-group "engine")
diff --git a/goal_src/jak1/engine/gfx/hw/display-h.gc b/goal_src/jak1/engine/gfx/hw/display-h.gc
index deaff89224..680d02d2ba 100644
--- a/goal_src/jak1/engine/gfx/hw/display-h.gc
+++ b/goal_src/jak1/engine/gfx/hw/display-h.gc
@@ -246,3 +246,12 @@
(defmacro real-current-time ()
`(-> *display* real-frame-counter)
)
+
+
+;; debug stuff really
+(defmacro get-screen-x (frac)
+ `(the int (* ,frac 512)))
+
+(defmacro get-screen-y (frac)
+ `(the int (* ,frac 224)))
+
diff --git a/goal_src/jak1/engine/target/target-death.gc b/goal_src/jak1/engine/target/target-death.gc
index 1327aee2fe..3df6095d27 100644
--- a/goal_src/jak1/engine/target/target-death.gc
+++ b/goal_src/jak1/engine/target/target-death.gc
@@ -714,25 +714,13 @@
(('back)
(when (not (ja-group? eichar-hit-from-back-ja))
(ja-channel-push! 1 (seconds 0.075))
- (let ((gp-1 (-> self skel root-channel 0)))
- (joint-control-channel-group-eval! gp-1 (the-as art-joint-anim eichar-hit-from-back-ja) num-func-identity)
- (let ((f0-0 0.0))
- (set! (-> gp-1 frame-num) f0-0)
- f0-0
- )
- )
+ (ja :group! eichar-hit-from-back-ja :num! min)
)
)
(('up 'up-forward)
(when (not (ja-group? eichar-hit-up-ja))
(ja-channel-push! 1 (seconds 0.075))
- (let ((gp-2 (-> self skel root-channel 0)))
- (joint-control-channel-group-eval! gp-2 (the-as art-joint-anim eichar-hit-up-ja) num-func-identity)
- (let ((f0-1 0.0))
- (set! (-> gp-2 frame-num) f0-1)
- f0-1
- )
- )
+ (ja :group! eichar-hit-up-ja :num! min)
)
)
(('air 'jump)
@@ -752,16 +740,11 @@
(else
(when (not (ja-group? eichar-hit-from-front-ja))
(ja-channel-push! 1 (seconds 0.075))
- (let ((gp-5 (-> self skel root-channel 0)))
- (joint-control-channel-group-eval! gp-5 (the-as art-joint-anim eichar-hit-from-front-ja) num-func-identity)
- (let ((f0-10 0.0))
- (set! (-> gp-5 frame-num) f0-10)
- f0-10
- )
- )
+ (ja :group! eichar-hit-from-front-ja :num! min)
)
)
)
+ (none)
)
(defbehavior target-hit-move target ((arg0 attack-info) (arg1 symbol) (arg2 (function none :behavior target)) (arg3 float))
diff --git a/goal_src/jak1/engine/ui/hud-classes.gc b/goal_src/jak1/engine/ui/hud-classes.gc
index a56ce2661e..3aa4a02483 100644
--- a/goal_src/jak1/engine/ui/hud-classes.gc
+++ b/goal_src/jak1/engine/ui/hud-classes.gc
@@ -742,38 +742,17 @@
(let ((t9-0 (method-of-type hud draw-hud)))
(t9-0 obj)
)
- (let* ((s5-0 (-> *display* frames (-> *display* on-screen) frame global-buf))
- (gp-0 (-> s5-0 base))
- )
- (let ((s4-0 draw-string-xy))
- (format (clear *temp-string*) "~D" (-> obj value))
- (s4-0
- *temp-string*
- s5-0
- (+ (-> obj text-x) (* (-> obj x-sgn) (-> obj offset)))
- (/ (* (+ (-> obj text-y) (* (-> obj y-sgn) (-> obj offset)) (-> obj y-offset))
- (the int (-> *video-parms* relative-y-scale))
+ (with-dma-buffer-add-bucket ((buf (-> (current-frame) global-buf))
+ (bucket-id debug))
+ (draw-string-xy (string-format "~D" (-> obj value)) buf
+ (+ (-> obj text-x) (* (-> obj x-sgn) (-> obj offset)))
+ (/ (* (+ (-> obj text-y) (* (-> obj y-sgn) (-> obj offset)) (-> obj y-offset))
+ (the int (-> *video-parms* relative-y-scale))
+ )
+ 2
)
- 2
- )
- (font-color dark-yellow)
- (font-flags shadow kerning large)
- )
- )
- (let ((a3-7 (-> s5-0 base)))
- (let ((v1-8 (the-as dma-packet (-> s5-0 base))))
- (set! (-> v1-8 dma) (new 'static 'dma-tag :id (dma-tag-id next)))
- (set! (-> v1-8 vif0) (new 'static 'vif-tag))
- (set! (-> v1-8 vif1) (new 'static 'vif-tag))
- (set! (-> s5-0 base) (&+ (the-as pointer v1-8) 16))
- )
- (dma-bucket-insert-tag
- (-> *display* frames (-> *display* on-screen) frame bucket-group)
- (bucket-id debug)
- gp-0
- (the-as (pointer dma-tag) a3-7)
- )
- )
+ (font-color dark-yellow)
+ (font-flags shadow kerning large))
)
0
(none)
diff --git a/goal_src/jak1/examples/display-all-colors.gc b/goal_src/jak1/examples/display-all-colors.gc
deleted file mode 100644
index 3a068c8a43..0000000000
--- a/goal_src/jak1/examples/display-all-colors.gc
+++ /dev/null
@@ -1,61 +0,0 @@
-;;-*-Lisp-*-
-(in-package goal)
-
-;; This script creates a simple process that draws text demonstrating
-;; all of GOAL's color constants to the on-screen debug output.
-
-;; Create somewhere for the handle to the process to live. See https://open-goal.github.io/docs/reference/process_and_state
-;; as well as kernel/gstate.gc
-(define *color-display-handle* (new 'static 'handle))
-(set! *color-display-handle* (the handle #f))
-
-
-(defun-debug start-display-text-colors ()
- "Spawn an onscreen string displaying all possible colors"
- (if (not (handle->process *color-display-handle*))
- (let ((disp-proc
- (process-spawn-function process :name 'display-proc
- (lambda :behavior process ()
- (stack-size-set! (-> self main-thread) 256)
- (loop
- ;; These constants live in engine/gfx/font-h.gc
- (format *stdcon* "~0k~%~%
-~0L 0 default ~1L 1 white
-~2L 2 gray ~3L 3 orange-red
-~4L 4 bright-orange-red ~5L 5 bright-orange-red
-~6L 6 bright-green ~7L 7 dark-blue
-~8L 8 light-blue ~9L 9 dark-pink
-~10L10 lighter-blue ~11L11 dark-light-blue
-~12L12 dim-white ~13L13 dim-gray
-~14L14 orange-red-2 ~15L15 yellow-green
-~16L16 dark-green ~17L17 another-gray
-~18L18 dark-dark-green ~19L19 flat-dark-purple
-~20L20 flat-yellow ~21L21 blue-white
-~22L22 pad-back ~23L23 pad-shine
-~24L24 pad-square ~25L25 pad-circle
-~26L26 pad-triangle ~27L27 pad-x
-~28L28 lighter-lighter-blue ~29L29 yellow-orange
-~30L30 yellow-green-2 ~31L31 another-light-blue
-~32L32 light-yellow ~33L33 red-orange
-~34L34 another-orange-red~0L~%
- alternate names
- ~3L3 red ~4L4 red2 ~5L5 yellow ~6L6 green ~7L7 blue
- ~10L10 cyan ~33L33 red-reverse ~34L34 red-obverse~0L"
- )
- (suspend)
- )
- )
- )
- ))
- (set! *color-display-handle* (ppointer->handle disp-proc))
- )
- ;; else
- (format #t "Colors are already being displayed")
- )
- )
-
-
-(defun-debug stop-display-text-colors ()
- "Kill the example text color display"
- (kill-by-name 'display-proc *active-pool*)
- )
diff --git a/goal_src/jak1/game.gp b/goal_src/jak1/game.gp
index 914b6d6c15..c32ebe3297 100644
--- a/goal_src/jak1/game.gp
+++ b/goal_src/jak1/game.gp
@@ -400,6 +400,14 @@
+;;;;;;;;;;;;;;;;;;;;;
+;; kernel Group
+;;;;;;;;;;;;;;;;;;;;;
+;; the kernel group is a group of files required to boot the game kernel
+
+(group "kernel" "$OUT/iso/KERNEL.CGO")
+
+
;;;;;;;;;;;;;;;;;;;;;
;; engine Group
;;;;;;;;;;;;;;;;;;;;;
diff --git a/goal_src/jak1/levels/village3/village3-obs.gc b/goal_src/jak1/levels/village3/village3-obs.gc
index ead7017be3..7ca81bd297 100644
--- a/goal_src/jak1/levels/village3/village3-obs.gc
+++ b/goal_src/jak1/levels/village3/village3-obs.gc
@@ -152,7 +152,15 @@
(not (movie?))
(not (level-hint-displayed?))
(>= (- (-> *display* base-frame-counter) (-> self state-time)) (seconds 3))
- (file-status *art-control* (-> self anim name) 0)
+ ;; pc port note : fix gondola spool not loading because it's "too far away" (technically)
+ (#if (not PC_PORT)
+ (file-status *art-control* (-> self anim name) 0)
+ (begin
+ (spool-push *art-control* (-> self anim name) 0 self (vector-vector-distance
+ (vector<-cspace! (new 'stack-no-clear 'vector) (-> self node-list data 3))
+ (target-pos 0)))
+ (file-status *art-control* (-> self anim name) 0))
+ )
)
)
(let ((s3-0 (get-reminder (get-task-control (game-task village3-button)) 2))
diff --git a/goal_src/jak1/pc/util/display-font-color.gc b/goal_src/jak1/pc/util/display-font-color.gc
new file mode 100644
index 0000000000..e2eecfe9ab
--- /dev/null
+++ b/goal_src/jak1/pc/util/display-font-color.gc
@@ -0,0 +1,52 @@
+;;-*-Lisp-*-
+(in-package goal)
+
+;; This script creates a simple process that draws text demonstrating
+;; all of GOAL's color constants to the on-screen debug output.
+
+;; Create somewhere for the handle to the process to live. See https://open-goal.github.io/docs/reference/process_and_state
+;; as well as kernel/gstate.gc
+(define *color-displays* (new 'global 'inline-array 'handle 1))
+
+(defmacro get-color-display-handle ()
+ `(-> *color-displays* 0))
+
+(set! (get-color-display-handle) INVALID_HANDLE)
+
+;; font-color is from font-h.gc
+(defun font-color->string ((val font-color))
+ "return the name of the font-color"
+ (enum->string font-color val)
+ )
+
+(defun draw-all-font-colors ()
+ "draws all font color names onscreen"
+ (with-dma-buffer-add-bucket ((buf (-> (current-frame) debug-buf))
+ (bucket-id debug-no-zbuf))
+ (dotimes (i 48)
+ (draw-string-xy (string-format "~2D ~S" i (font-color->string (the font-color i))) buf
+ (+ 4 (* (get-screen-x 0.5) (mod i 2))) (+ 8 (* 8 (/ i 2))) (the font-color i) (font-flags shadow)))
+ )
+ )
+
+(defun start-display-text-colors ()
+ "Spawn an onscreen string displaying all possible colors"
+ (if (handle->process (get-color-display-handle))
+ (format #t "Colors are already being displayed")
+ ;; else
+ (set! (get-color-display-handle)
+ (ppointer->handle (process-spawn-function process :name 'display-proc
+ (lambda :behavior process ()
+ (loop
+ (draw-all-font-colors)
+ (suspend))
+ )
+ )))
+ )
+ )
+
+
+(defun-debug stop-display-text-colors ()
+ "Kill the example text color display"
+ (kill-by-name 'display-proc *active-pool*)
+ )
diff --git a/goal_src/jak1/pc_debug/font-encode-test.gc b/goal_src/jak1/pc/util/font-encode-test.gc
similarity index 66%
rename from goal_src/jak1/pc_debug/font-encode-test.gc
rename to goal_src/jak1/pc/util/font-encode-test.gc
index 05809eef87..4b1d5ef91a 100644
--- a/goal_src/jak1/pc_debug/font-encode-test.gc
+++ b/goal_src/jak1/pc/util/font-encode-test.gc
@@ -8,11 +8,9 @@
;; To run this:
#|
-(make-group "iso") ;; build the game
-(lt) ;; connect to the runtime
-(lg) ;; have the runtime load the game engine
-(test-play) ;; start the game loop
-(ml "goal_src/pc_debug/font-encode-test.gc") ;; build and load this file.
+(mi) ;; build the game
+(lt) ;; connect to the runtime
+(ml "goal_src/jak1/pc/util/font-encode-test.gc") ;; build and load this file.
|#
@@ -30,8 +28,8 @@
;;;; functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(define *font-string* (new 'global 'string 64 (the-as string #f)))
-(define *font-string-ex* "")
+(define *font-string* (new 'global 'string 64 (the string #f)))
+(define *font-string-ex* (the string #f))
(define *font-string-val* #x96)
(defun-debug font-encode-test-start ()
@@ -40,9 +38,6 @@
(unless (process-by-name 'font-encode *active-pool*)
(process-spawn-function process :name 'font-encode
(lambda :behavior process ()
-
- (stack-size-set! (-> self main-thread) 768)
-
(let ((fnt (new 'stack 'font-context *font-default-matrix* FONT_ENCODE_TEXT_LEFT FONT_ENCODE_TEXT_Y 0.0
(font-color orange-red) (font-flags shadow kerning large middle)))
)
@@ -54,27 +49,20 @@
(suspend)
(if (or (cpad-pressed? 0 left) (cpad-hold? 0 l1))
- (-! *font-string-val* 1)
- )
+ (-! *font-string-val* 1))
(if (or (cpad-pressed? 0 right) (cpad-hold? 0 r1))
- (+! *font-string-val* 1)
- )
- (if (< *font-string-val* 1)
- (set! *font-string-val* 1)
- )
- (if (> *font-string-val* #x1ff)
- (set! *font-string-val* #x1ff)
- )
+ (+! *font-string-val* 1))
+ (minmax! *font-string-val* 1 #x1ff)
(clear *font-string*)
(cond
((>= *font-string-val* #x100)
(set! (-> *font-string* data 0) (/ *font-string-val* 256))
- (set! (-> *font-string* data 1) (mod *font-string-val* 256))
+ (set! (-> *font-string* data 1) (logand *font-string-val* #xff))
(set! (-> *font-string* data 2) 0)
)
(else
- (set! (-> *font-string* data 0) (mod *font-string-val* 256))
+ (set! (-> *font-string* data 0) (logand *font-string-val* #xff))
(set! (-> *font-string* data 1) 0)
)
)
@@ -82,11 +70,12 @@
(set-origin! fnt FONT_ENCODE_TEXT_LEFT FONT_ENCODE_TEXT_Y)
(set-flags! fnt (font-flags shadow kerning large middle))
(print-game-text *font-string* fnt #f 128 24)
- (set-origin! fnt FONT_ENCODE_TEXT_LEFT (+ FONT_ENCODE_TEXT_Y 32))
- (print-game-text *font-string-ex* fnt #f 128 24)
+ (when *font-string-ex*
+ (set-origin! fnt FONT_ENCODE_TEXT_LEFT (+ FONT_ENCODE_TEXT_Y 32))
+ (print-game-text *font-string-ex* fnt #f 128 24))
(set-origin! fnt FONT_ENCODE_TEXT_LEFT (- FONT_ENCODE_TEXT_Y 16))
(set-flags! fnt (font-flags shadow kerning middle))
- (print-game-text (string-format "#x~X" *font-string-val*) fnt #f 128 12)
+ (print-game-text (string-format "#x~x" *font-string-val*) fnt #f 128 12)
)
)
diff --git a/goal_src/jak1/pc_debug/pc-pad-utils.gc b/goal_src/jak1/pc/util/pc-pad-utils.gc
similarity index 95%
rename from goal_src/jak1/pc_debug/pc-pad-utils.gc
rename to goal_src/jak1/pc/util/pc-pad-utils.gc
index fd00295898..a240aedaf6 100644
--- a/goal_src/jak1/pc_debug/pc-pad-utils.gc
+++ b/goal_src/jak1/pc/util/pc-pad-utils.gc
@@ -10,11 +10,9 @@
;; To run this:
#|
-(make-group "iso") ;; build the game
-(lt) ;; connect to the runtime
-(lg) ;; have the runtime load the game engine
-(test-play) ;; start the game loop
-(ml "goal_src/pc_debug/pc-pad-utils.gc") ;; build and load this file.
+(mi) ;; build the game
+(lt) ;; connect to the runtime
+(ml "goal_src/jak1/pc/util/pc-pad-utils.gc") ;; build and load this file.
|#
@@ -30,12 +28,12 @@
)
(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))
+(set! (-> *pc-pad-proc-list* show) INVALID_HANDLE)
+(set! (-> *pc-pad-proc-list* input) INVALID_HANDLE)
;; a pc pad process
(deftype pc-pad-proc (process)
- ((state-time int64)
+ ((state-time time-frame)
(input-index uint64)
(pad-idx int64)
)
diff --git a/goalc/compiler/compilation/Static.cpp b/goalc/compiler/compilation/Static.cpp
index a172284acc..8c1a40149e 100644
--- a/goalc/compiler/compilation/Static.cpp
+++ b/goalc/compiler/compilation/Static.cpp
@@ -1052,7 +1052,7 @@ StaticResult Compiler::fill_static_inline_array(const goos::Object& form,
// get all arguments now
auto args = get_list_as_vector(rest);
if (args.size() < 4) {
- throw_compiler_error(form, "new static boxed array must have type and min-size arguments");
+ throw_compiler_error(form, "new static inline array must have type and min-size arguments");
}
auto content_type = parse_typespec(args.at(2), env);
s64 min_size = get_constant_integer_or_error(args.at(3), env);
@@ -1060,8 +1060,10 @@ StaticResult Compiler::fill_static_inline_array(const goos::Object& form,
auto inline_array_type = m_ts.make_inline_array_typespec(content_type);
auto deref_info = m_ts.get_deref_info(inline_array_type);
- ASSERT(deref_info.can_deref);
- ASSERT(!deref_info.mem_deref);
+ if (!deref_info.can_deref || deref_info.mem_deref) {
+ throw_compiler_error(form, "new static inline array of type {} is currently not supported",
+ content_type.print());
+ }
auto obj = std::make_unique(seg);
obj->set_offset(is_basic(content_type) ? 4 : 0);
obj->data.resize(length * deref_info.stride);
diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp
index 30b438a043..bbc3144bf3 100644
--- a/goalc/compiler/compilation/Type.cpp
+++ b/goalc/compiler/compilation/Type.cpp
@@ -982,8 +982,9 @@ Val* Compiler::compile_heap_new(const goos::Object& form,
throw_compiler_error(form, "new array form got more arguments than expected");
}
- auto ts = is_inline ? m_ts.make_inline_array_typespec(elt_type)
- : m_ts.make_pointer_typespec(elt_type);
+ auto ts = is_inline && m_ts.lookup_type(elt_type)->is_reference()
+ ? m_ts.make_inline_array_typespec(elt_type)
+ : m_ts.make_pointer_typespec(elt_type);
auto info = m_ts.get_deref_info(ts);
if (!info.can_deref) {
throw_compiler_error(form, "Cannot make an {} of {}\n", main_type.print(), ts.print());
@@ -1003,9 +1004,9 @@ Val* Compiler::compile_heap_new(const goos::Object& form,
args.push_back(array_size);
}
- auto array = compile_real_function_call(form, malloc_func, args, env);
- array->set_type(ts);
- return array;
+ auto new_array = compile_real_function_call(form, malloc_func, args, env);
+ new_array->set_type(ts);
+ return new_array;
} else {
bool got_content_type = false; // for boxed array
std::string content_type; // for boxed array.
diff --git a/test/decompiler/reference/jak1/engine/target/target-death_REF.gc b/test/decompiler/reference/jak1/engine/target/target-death_REF.gc
index baa50b097b..9eba9cd403 100644
--- a/test/decompiler/reference/jak1/engine/target/target-death_REF.gc
+++ b/test/decompiler/reference/jak1/engine/target/target-death_REF.gc
@@ -713,30 +713,19 @@
)
;; definition for function target-hit-setup-anim
+;; INFO: Return type mismatch object vs none.
(defbehavior target-hit-setup-anim target ((arg0 attack-info))
(case (-> arg0 angle)
(('back)
(when (not (ja-group? eichar-hit-from-back-ja))
(ja-channel-push! 1 (seconds 0.075))
- (let ((gp-1 (-> self skel root-channel 0)))
- (joint-control-channel-group-eval! gp-1 (the-as art-joint-anim eichar-hit-from-back-ja) num-func-identity)
- (let ((f0-0 0.0))
- (set! (-> gp-1 frame-num) f0-0)
- f0-0
- )
- )
+ (ja :group! eichar-hit-from-back-ja :num! min)
)
)
(('up 'up-forward)
(when (not (ja-group? eichar-hit-up-ja))
(ja-channel-push! 1 (seconds 0.075))
- (let ((gp-2 (-> self skel root-channel 0)))
- (joint-control-channel-group-eval! gp-2 (the-as art-joint-anim eichar-hit-up-ja) num-func-identity)
- (let ((f0-1 0.0))
- (set! (-> gp-2 frame-num) f0-1)
- f0-1
- )
- )
+ (ja :group! eichar-hit-up-ja :num! min)
)
)
(('air 'jump)
@@ -756,16 +745,11 @@
(else
(when (not (ja-group? eichar-hit-from-front-ja))
(ja-channel-push! 1 (seconds 0.075))
- (let ((gp-5 (-> self skel root-channel 0)))
- (joint-control-channel-group-eval! gp-5 (the-as art-joint-anim eichar-hit-from-front-ja) num-func-identity)
- (let ((f0-10 0.0))
- (set! (-> gp-5 frame-num) f0-10)
- f0-10
- )
- )
+ (ja :group! eichar-hit-from-front-ja :num! min)
)
)
)
+ (none)
)
;; definition for function target-hit-move
From 34d6e8d71e32ed85d0c25ed76adfb37771ec497c Mon Sep 17 00:00:00 2001
From: Liam Hackett
Date: Mon, 15 Aug 2022 23:47:23 +0100
Subject: [PATCH 03/23] Update Readme to include missing dependencies on Fedora
and Arch installations (#1763)
Update docs to include missing dependencies on Fedora and Arch
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 40318178d4..361af0e91a 100644
--- a/README.md
+++ b/README.md
@@ -135,7 +135,7 @@ cmake -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_EXE_LINKER_FLAGS="-fuse
Install packages and init repository:
```sh
-sudo pacman -S cmake libpulse base-devel nasm python
+sudo pacman -S cmake libpulse base-devel nasm python libx11 libxrandr libxinerama libxcursor libxi
yay -S go-task
```
@@ -158,7 +158,7 @@ Run tests:
Install packages and init repository:
```sh
-sudo dnf install cmake lld clang nasm libX11-devel libXrandr-devel libXinerama-devel libXcursor-devel libXi-devel pulseaudio-libs-devel
+sudo dnf install cmake python lld clang nasm libX11-devel libXrandr-devel libXinerama-devel libXcursor-devel libXi-devel pulseaudio-libs-devel
sudo sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
```
From 18dfb6c1d1ac2a4dfe18620251c7bc1287e5d0f8 Mon Sep 17 00:00:00 2001
From: Liam Hackett
Date: Tue, 16 Aug 2022 00:08:51 +0100
Subject: [PATCH 04/23] Add dockerfiles for Linux environments with
documentation (#1764)
* Add dockerfiles for linux environments with documentation
* Clean up documentation
---
README.md | 25 +++++++++++++++++++++++++
docker/Arch/Dockerfile | 28 ++++++++++++++++++++++++++++
docker/Fedora/Dockerfile | 20 ++++++++++++++++++++
docker/Ubuntu/Dockerfile | 24 ++++++++++++++++++++++++
4 files changed, 97 insertions(+)
create mode 100644 docker/Arch/Dockerfile
create mode 100644 docker/Fedora/Dockerfile
create mode 100644 docker/Ubuntu/Dockerfile
diff --git a/README.md b/README.md
index 361af0e91a..e3d4187ee0 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,7 @@
- [Current Status](#current-status)
- [Methodology](#methodology)
- [Setting up a Development Environment](#setting-up-a-development-environment)
+ - [Docker](#docker)
- [Linux](#linux)
- [Ubuntu (20.04)](#ubuntu-2004)
- [Arch](#arch)
@@ -95,6 +96,30 @@ The remainder of this README is catered towards people interested in building th
If this does not sound like you and you just want to play the game, refer to the above section [How to play the game](#how-to-play-the-game)
+### Docker
+
+All three Linux systems are supported using Docker.
+
+Pick your supported prefered flavour of linux and build your chosen image
+
+```
+docker build -f docker/(Arch|Fedora|Ubuntu)/Dockerfile -t jak .
+```
+
+This will create an image with all required dependencies and already built.
+
+```
+docker run -v "$(pwd)"/build:/home/jak/jak-project/build -it jak bash
+```
+
+Note: If you the build directory you'll need to rerun the build command. Alteratively you can get the build via `docker cp`
+
+This will link your build folder to the images so can validate your build or test it on an external device.
+
+Docker images can be linked into your IDE (e.g. CLion) to help with codesniffing, static analysis, run tests and continuous build.
+
+Unfortently you'll still need task runner on your local machine to run the game or instead, manually run the game via the commands found in `Taskfile.yml`
+
### Linux
#### Ubuntu (20.04)
diff --git a/docker/Arch/Dockerfile b/docker/Arch/Dockerfile
new file mode 100644
index 0000000000..1e82723e8b
--- /dev/null
+++ b/docker/Arch/Dockerfile
@@ -0,0 +1,28 @@
+FROM archlinux:latest
+
+RUN pacman -Syyu --noconfirm --needed cmake libpulse base-devel nasm python git libx11 libxrandr libxinerama libxcursor libxi
+
+# makepkg user and workdir
+ARG user=jak
+RUN useradd --system --create-home $user \
+ && echo "$user ALL=(ALL:ALL) NOPASSWD:ALL" > /etc/sudoers.d/$user
+USER $user
+WORKDIR /home/$user
+
+# Install yay
+RUN git clone https://aur.archlinux.org/yay.git \
+ && cd yay \
+ && makepkg -sri --needed --noconfirm \
+ && cd \
+ # Clean up
+ && rm -rf .cache yay
+
+RUN yay --noconfirm -S go-task
+
+RUN mkdir /home/$user/jak-project/
+COPY --chown=jak:jak . /home/$user/jak-project
+RUN git config --global --add safe.directory /home/jak/jak-project
+
+WORKDIR /home/$user/jak-project
+
+RUN cmake -B build && cmake --build build -j 8
\ No newline at end of file
diff --git a/docker/Fedora/Dockerfile b/docker/Fedora/Dockerfile
new file mode 100644
index 0000000000..a150cf2fb0
--- /dev/null
+++ b/docker/Fedora/Dockerfile
@@ -0,0 +1,20 @@
+FROM fedora:latest
+
+RUN dnf install -y curl cmake python lld clang nasm libX11-devel libXrandr-devel libXinerama-devel libXcursor-devel libXi-devel pulseaudio-libs-devel
+RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
+
+ARG user=jak
+
+RUN useradd -m -d /home/${user} ${user}
+
+USER $user
+
+WORKDIR /home/$user
+
+RUN mkdir /home/$user/jak-project/
+COPY --chown=jak:jak . /home/$user/jak-project
+
+WORKDIR /home/$user/jak-project
+
+RUN cmake -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -B build
+RUN cmake --build build -j$(nproc)
\ No newline at end of file
diff --git a/docker/Ubuntu/Dockerfile b/docker/Ubuntu/Dockerfile
new file mode 100644
index 0000000000..4d88164918
--- /dev/null
+++ b/docker/Ubuntu/Dockerfile
@@ -0,0 +1,24 @@
+FROM ubuntu:20.04
+
+ENV DEBIAN_FRONTEND=noninteractive
+RUN apt-get update
+RUN apt-get install -y gcc make cmake build-essential g++ nasm clang-format libxrandr-dev libxinerama-dev libxcursor-dev libpulse-dev libxi-dev python lld clang curl
+
+RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
+
+ARG user=jak
+
+RUN useradd -m -d /home/${user} ${user}
+
+USER $user
+
+WORKDIR /home/$user
+
+RUN mkdir /home/$user/jak-project/
+COPY --chown=jak:jak . /home/$user/jak-project
+
+WORKDIR /home/$user/jak-project/build
+
+RUN cmake -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld" -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ ..
+WORKDIR /home/$user/jak-project
+RUN cmake -B build && cmake --build build -j 8
From b2eb041ebe5d72678ae7f9c88c5fd8d80beae800 Mon Sep 17 00:00:00 2001
From: Tyler Wilding
Date: Wed, 17 Aug 2022 00:57:59 -0400
Subject: [PATCH 05/23] ci: add back the windows artifact (#1766)
---
.github/workflows/windows-build-clang.yaml | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/.github/workflows/windows-build-clang.yaml b/.github/workflows/windows-build-clang.yaml
index d755a47e9f..7891494a2e 100644
--- a/.github/workflows/windows-build-clang.yaml
+++ b/.github/workflows/windows-build-clang.yaml
@@ -52,3 +52,10 @@ jobs:
GTEST_OUTPUT: "xml:opengoal-test-report.xml"
run: ./build/bin/goalc-test.exe --gtest_color=yes --gtest_brief=1 --gtest_filter="-*MANUAL_TEST*"
+ - name: Upload artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: opengoal-windows-${{ inputs.cachePrefix }}
+ if-no-files-found: error
+ path: ./build/bin
+
From 375e9c7713165da5046e4d8a8d31d2a12beac9cb Mon Sep 17 00:00:00 2001
From: animalstyletaco
Date: Fri, 19 Aug 2022 08:28:06 -0700
Subject: [PATCH 06/23] Added first working instance of controller/keyboard
re-mapper (#1702)
* Added First working instance of controller/keyboard re-mapper
* Fixed clang formatting issues
* Updated newpad.cpp to inverse analog y-axis to make json labelling consistent
* Added mouse sensitivity options for X and Y axis in json, removed scroll mouse support, and other changes requested in feedback
* Added option to have ImGui debug menu appear on start up and remove hard coded set_imgui_visible calls
* Added newpad unit tests and updated function names to better describe intended functionalities
* Fixed formatting issue in newpad unit test
* Removed rumble unit test new pad
* Fixed codacy static analysis issues
* Fixed Linux build issues
* Implemented github feedback
* Implemented updated github feedback
* Fixed formatting errors
* Updated Pad::CheckPadIdx
* Implemented changes based on latest github feedback
* Implemented changes based on github feedback
Co-authored-by: animalstyletaco
---
game/graphics/display.cpp | 1 -
game/graphics/gfx.cpp | 208 ++++++++++++++---
game/graphics/gfx.h | 5 +-
game/graphics/pipelines/opengl.cpp | 98 ++++++++-
game/graphics/pipelines/opengl.h | 11 +
game/sce/libpad.cpp | 8 +-
game/system/newpad.cpp | 343 ++++++++++++++++++++++-------
game/system/newpad.h | 42 +++-
test/CMakeLists.txt | 1 +
test/game/test_newpad.cpp | 311 ++++++++++++++++++++++++++
10 files changed, 899 insertions(+), 129 deletions(-)
create mode 100644 test/game/test_newpad.cpp
diff --git a/game/graphics/display.cpp b/game/graphics/display.cpp
index dbbc4da5b4..5e75124175 100644
--- a/game/graphics/display.cpp
+++ b/game/graphics/display.cpp
@@ -92,7 +92,6 @@ int InitMainDisplay(int width,
lg::error("Failed to make main display.");
return 1;
}
- display->set_imgui_visible(true);
set_main_display(display);
return 0;
}
diff --git a/game/graphics/gfx.cpp b/game/graphics/gfx.cpp
index b98beec433..896d6b1bd1 100644
--- a/game/graphics/gfx.cpp
+++ b/game/graphics/gfx.cpp
@@ -14,6 +14,7 @@
#include "common/log/log.h"
#include "common/symbols.h"
#include "common/util/FileUtil.h"
+#include "common/util/json_util.h"
#include "game/common/file_paths.h"
#include "game/kernel/common/kscheme.h"
@@ -42,8 +43,8 @@ void InitSettings(GfxSettings& settings) {
settings.pad_mapping_info.buffer_mode = true;
// debug input settings
settings.pad_mapping_info.debug = true;
- // use a default mapping
- Pad::DefaultMapping(settings.pad_mapping_info);
+
+ Pad::DefaultMapping(Gfx::g_settings.pad_mapping_info);
}
} // namespace
@@ -53,36 +54,180 @@ namespace Gfx {
std::function vsync_callback;
GfxGlobalSettings g_global_settings;
GfxSettings g_settings;
+
+Pad::MappingInfo& get_button_mapping() {
+ return g_settings.pad_mapping_info;
+}
+
// const std::vector renderers = {&moduleOpenGL};
-// TODO serialize
-void LoadSettings() {
- const auto filename = file_util::get_file_path({GAME_CONFIG_DIR_NAME, SETTINGS_GFX_FILE_NAME});
- if (fs::exists(filename)) {
- // this is just wrong LOL
- FILE* fp = file_util::open_file(filename.c_str(), "rb");
- lg::info("Found graphics configuration file. Checking version.");
- u64 version;
- fread(&version, sizeof(u64), 1, fp);
- if (version == GfxSettings::CURRENT_VERSION) {
- fseek(fp, 0, SEEK_SET);
- fread(&g_settings, sizeof(GfxSettings), 1, fp);
- lg::info("Loaded graphics configuration file.");
- } else {
- // TODO upgrade func
- lg::info("Detected graphics configuration file from old version. Ignoring.");
+// Not crazy about this declaration
+const std::pair gamepad_map[] = {{"Select", Pad::Button::Select},
+ {"L3", Pad::Button::L3},
+ {"R3", Pad::Button::R3},
+ {"Start", Pad::Button::Start},
+ {"Up", Pad::Button::Up},
+ {"Right", Pad::Button::Right},
+ {"Down", Pad::Button::Down},
+ {"Left", Pad::Button::Left},
+ {"L1", Pad::Button::L1},
+ {"R1", Pad::Button::R1},
+ {"Triangle", Pad::Button::Triangle},
+ {"Circle", Pad::Button::Circle},
+ {"X", Pad::Button::X},
+ {"Square", Pad::Button::Square}};
+
+const std::pair analog_map[] = {
+ {"Left X Axis", Pad::Analog::Left_X},
+ {"Left Y Axis", Pad::Analog::Left_Y},
+ {"Right X Axis", Pad::Analog::Right_X},
+ {"Right Y Axis", Pad::Analog::Right_Y},
+};
+
+bool g_is_debug_menu_visible_on_startup = false;
+
+bool get_debug_menu_visible_on_startup() {
+ return g_is_debug_menu_visible_on_startup;
+}
+
+void DumpToJson(ghc::filesystem::path& filename) {
+ nlohmann::json json;
+ json["Debug Menu Visibility"] = false; // Assume start up debug display is disabled
+ auto& peripherals_json = json["Peripherals"];
+
+ for (uint32_t i = 0; i < Pad::CONTROLLER_COUNT; ++i) {
+ nlohmann::json peripheral_json;
+ peripheral_json["ID"] = i + 1;
+
+ auto& controller_json = peripheral_json["Controller"];
+ auto& controller_buttons_json = controller_json["Buttons"];
+ for (const auto& [name, value] : gamepad_map) {
+ controller_buttons_json[name] =
+ g_settings.pad_mapping_info.controller_button_mapping[i][(int)value];
}
- fclose(fp);
+
+ auto& keyboard_json = peripheral_json["Keyboard+Mouse"];
+ auto& keyboard_buttons_json = keyboard_json["Buttons"];
+ for (const auto& [name, value] : gamepad_map) {
+ keyboard_buttons_json[name] =
+ g_settings.pad_mapping_info.keyboard_button_mapping[i][(int)value];
+ }
+
+ auto& keyboard_analogs_json = keyboard_json["Analog"];
+ for (const auto& [name, value] : analog_map) {
+ if (g_settings.pad_mapping_info.keyboard_analog_mapping[i][(int)value].mode ==
+ Pad::AnalogMappingMode::AnalogInput) {
+ keyboard_analogs_json[name]["Axis Id"] =
+ g_settings.pad_mapping_info.keyboard_analog_mapping[i][(int)value].axis_id;
+ } else {
+ keyboard_analogs_json[name]["Positive Key"] =
+ g_settings.pad_mapping_info.keyboard_analog_mapping[i][(int)value].positive_key;
+ keyboard_analogs_json[name]["Negative Key"] =
+ g_settings.pad_mapping_info.keyboard_analog_mapping[i][(int)value].negative_key;
+ }
+ }
+ peripheral_json["X-Axis Mouse Sensitivity"] =
+ g_settings.pad_mapping_info.mouse_x_axis_sensitivities[i];
+ peripheral_json["Y-Axis Mouse Sensitivity"] =
+ g_settings.pad_mapping_info.mouse_y_axis_sensitivities[i];
+ peripherals_json.emplace_back(peripheral_json);
+ }
+
+ file_util::write_text_file(filename, json.dump(4));
+}
+
+void SavePeripheralSettings() {
+ auto filename = (file_util::get_user_config_dir() / "controller" / "controller-settings.json");
+ file_util::create_dir_if_needed_for_file(filename);
+
+ DumpToJson(filename);
+ lg::info("Saved graphics configuration file.");
+}
+
+void LoadPeripheralSettings(const ghc::filesystem::path& filepath) {
+ Pad::DefaultMapping(g_settings.pad_mapping_info);
+
+ auto file_txt = file_util::read_text_file(filepath);
+ auto configuration = parse_commented_json(file_txt, filepath.string());
+
+ if (configuration.find("Debug Menu Visibility") != configuration.end()) {
+ g_is_debug_menu_visible_on_startup = configuration["Debug Menu Visibility"].get();
+ }
+
+ int controller_index = 0;
+ for (const auto& peripheral : configuration["Peripherals"]) {
+ auto& controller_buttons_json = peripheral["Controller"]["Buttons"];
+ auto& keyboard_buttons_json = peripheral["Keyboard+Mouse"]["Buttons"];
+
+ for (const auto& [name, button] : gamepad_map) {
+ if (controller_buttons_json.find(name) != controller_buttons_json.end()) {
+ g_settings.pad_mapping_info.controller_button_mapping[controller_index][(int)button] =
+ controller_buttons_json[name].get();
+ } else {
+ lg::warn(
+ "Controller button override not found for {}. Using controller default value: {}", name,
+ g_settings.pad_mapping_info.controller_button_mapping[controller_index][(int)button]);
+ }
+
+ if (keyboard_buttons_json.find(name) != keyboard_buttons_json.end()) {
+ g_settings.pad_mapping_info.keyboard_button_mapping[controller_index][(int)button] =
+ keyboard_buttons_json[name].get();
+ } else {
+ lg::warn(
+ "Keyboard button override not found for {}. Using keyboard default value: {}", name,
+ g_settings.pad_mapping_info.keyboard_button_mapping[controller_index][(int)button]);
+ }
+ }
+
+ auto& keyboard_analogs_json = peripheral["Keyboard+Mouse"]["Analog"];
+ for (const auto& [name, value] : analog_map) {
+ Pad::AnalogMappingInfo analog_mapping;
+ if (keyboard_analogs_json[name].contains("Axis Id") == true) {
+ analog_mapping.mode = Pad::AnalogMappingMode::AnalogInput;
+ analog_mapping.axis_id = keyboard_analogs_json[name]["Axis Id"].get();
+ g_settings.pad_mapping_info.keyboard_analog_mapping[controller_index][(int)value] =
+ analog_mapping;
+ continue;
+ }
+
+ if (keyboard_analogs_json[name].contains("Positive Key") == true) {
+ analog_mapping.positive_key = keyboard_analogs_json[name]["Positive Key"].get();
+ } else {
+ lg::warn("Keyboard analog override not found for {}. Using keyboard default value: {}",
+ name,
+ g_settings.pad_mapping_info.keyboard_analog_mapping[controller_index][(int)value]
+ .positive_key);
+ }
+
+ if (keyboard_analogs_json[name].contains("Negative Key") == true) {
+ analog_mapping.negative_key = keyboard_analogs_json[name]["Negative Key"].get();
+ } else {
+ lg::warn("Keyboard analog override not found for {}. Using keyboard default value: {}",
+ name,
+ g_settings.pad_mapping_info.keyboard_analog_mapping[controller_index][(int)value]
+ .negative_key);
+ }
+ g_settings.pad_mapping_info.keyboard_analog_mapping[controller_index][(int)value] =
+ analog_mapping;
+ }
+ g_settings.pad_mapping_info.mouse_x_axis_sensitivities[controller_index] =
+ peripheral["X-Axis Mouse Sensitivity"].get();
+ g_settings.pad_mapping_info.mouse_y_axis_sensitivities[controller_index] =
+ peripheral["Y-Axis Mouse Sensitivity"].get();
+ controller_index++;
}
}
-void SaveSettings() {
- const auto filename = file_util::get_file_path({GAME_CONFIG_DIR_NAME, SETTINGS_GFX_FILE_NAME});
- file_util::create_dir_if_needed(file_util::get_file_path({GAME_CONFIG_DIR_NAME}));
- FILE* fp = file_util::open_file(filename.c_str(), "wb");
- fwrite(&g_settings, sizeof(GfxSettings), 1, fp);
- fclose(fp);
- lg::info("Saved graphics configuration file.");
+void LoadSettings() {
+ auto filename = (file_util::get_user_config_dir() / "controller" / "controller-settings.json");
+ if (fs::exists(filename)) {
+ LoadPeripheralSettings(filename);
+ lg::info("Loaded graphics configuration file.");
+ return;
+ } else {
+ SavePeripheralSettings();
+ lg::info("Couldn't find controller-settings.json creating new controller settings file.");
+ }
}
const GfxRendererModule* GetRenderer(GfxPipeline pipeline) {
@@ -319,7 +464,7 @@ void input_mode_save() {
g_settings.pad_mapping_info_backup = g_settings.pad_mapping_info; // copy to backup
g_settings.pad_mapping_info = Pad::g_input_mode_mapping; // set current mapping
- SaveSettings();
+ SavePeripheralSettings();
}
}
@@ -328,15 +473,18 @@ s64 get_mapped_button(s64 pad, s64 button) {
lg::error("Invalid parameters to get_mapped_button({}, {})", pad, button);
return -1;
}
- return (s64)g_settings.pad_mapping_info.pad_mapping[pad][button];
+
+ return (Pad::GetGamepadState(pad) > -1)
+ ? (s64)g_settings.pad_mapping_info.controller_button_mapping[pad][button]
+ : (s64)g_settings.pad_mapping_info.keyboard_button_mapping[pad][button];
}
int PadIsPressed(Pad::Button button, int port) {
return Pad::IsPressed(g_settings.pad_mapping_info, button, port);
}
-int PadAnalogValue(Pad::Analog analog, int port) {
- return Pad::AnalogValue(g_settings.pad_mapping_info, analog, port);
+int PadGetAnalogValue(Pad::Analog analog, int port) {
+ return Pad::GetAnalogValue(g_settings.pad_mapping_info, analog, port);
}
void SetLod(RendererTreeType tree, int lod) {
diff --git a/game/graphics/gfx.h b/game/graphics/gfx.h
index 941ac790fc..5d61f78060 100644
--- a/game/graphics/gfx.h
+++ b/game/graphics/gfx.h
@@ -124,6 +124,8 @@ u32 Init(GameVersion version);
void Loop(std::function f);
u32 Exit();
+Pad::MappingInfo& get_button_mapping();
+
u32 vsync();
void register_vsync_callback(std::function f);
void clear_vsync_callback();
@@ -152,9 +154,10 @@ void set_msaa(int samples);
void input_mode_set(u32 enable);
void input_mode_save();
s64 get_mapped_button(s64 pad, s64 button);
+bool get_debug_menu_visible_on_startup();
int PadIsPressed(Pad::Button button, int port);
-int PadAnalogValue(Pad::Analog analog, int port);
+int PadGetAnalogValue(Pad::Analog analog, int port);
// matching enum in kernel-defs.gc !!
enum class RendererTreeType { NONE = 0, TFRAG3 = 1, TIE3 = 2, INVALID };
diff --git a/game/graphics/pipelines/opengl.cpp b/game/graphics/pipelines/opengl.cpp
index 8602f83d8c..b89bf5d22e 100644
--- a/game/graphics/pipelines/opengl.cpp
+++ b/game/graphics/pipelines/opengl.cpp
@@ -78,6 +78,11 @@ struct GraphicsData {
std::unique_ptr g_gfx_data;
+std::atomic g_cursor_input_mode = GLFW_CURSOR_DISABLED;
+bool is_cursor_position_valid = false;
+double last_cursor_x_position = 0;
+double last_cursor_y_position = 0;
+
struct {
bool callbacks_registered = false;
GLFWmonitor** monitors;
@@ -209,6 +214,7 @@ static std::shared_ptr gl_make_display(int width,
}
auto display = std::make_shared(window, is_main);
+
// lg::debug("init display #x{:x}", (uintptr_t)display);
// setup imgui
@@ -255,6 +261,16 @@ GLDisplay::GLDisplay(GLFWwindow* window, bool is_main) : m_window(window) {
display->on_key(window, key, scancode, action, mods);
});
+ glfwSetMouseButtonCallback(window, [](GLFWwindow* window, int button, int action, int mode) {
+ GLDisplay* display = reinterpret_cast(glfwGetWindowUserPointer(window));
+ display->on_mouse_key(window, button, action, mode);
+ });
+
+ glfwSetCursorPosCallback(window, [](GLFWwindow* window, double xposition, double yposition) {
+ GLDisplay* display = reinterpret_cast(glfwGetWindowUserPointer(window));
+ display->on_cursor_position(window, xposition, yposition);
+ });
+
glfwSetWindowPosCallback(window, [](GLFWwindow* window, int xpos, int ypos) {
GLDisplay* display = reinterpret_cast(glfwGetWindowUserPointer(window));
display->on_window_pos(window, xpos, ypos);
@@ -289,6 +305,11 @@ GLDisplay::~GLDisplay() {
}
}
+void GLDisplay::update_cursor_visibility(GLFWwindow* window, bool is_visible) {
+ g_cursor_input_mode = (is_visible) ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED;
+ glfwSetInputMode(window, GLFW_CURSOR, g_cursor_input_mode);
+}
+
void GLDisplay::on_key(GLFWwindow* window, int key, int /*scancode*/, int action, int /*mods*/) {
if (action == GlfwKeyAction::Press) {
// lg::debug("KEY PRESS: key: {} scancode: {} mods: {:X}", key, scancode, mods);
@@ -296,13 +317,63 @@ void GLDisplay::on_key(GLFWwindow* window, int key, int /*scancode*/, int action
} else if (action == GlfwKeyAction::Release) {
// lg::debug("KEY RELEASE: key: {} scancode: {} mods: {:X}", key, scancode, mods);
Pad::OnKeyRelease(key);
- if ((key == GLFW_KEY_LEFT_ALT || key == GLFW_KEY_RIGHT_ALT) &&
- glfwGetWindowAttrib(window, GLFW_FOCUSED)) {
- set_imgui_visible(!is_imgui_visible());
+ GLDisplay* display = reinterpret_cast(glfwGetWindowUserPointer(window));
+ if (display != NULL) { // toggle ImGui when pressing Alt
+ if ((key == GLFW_KEY_LEFT_ALT || key == GLFW_KEY_RIGHT_ALT) &&
+ glfwGetWindowAttrib(window, GLFW_FOCUSED)) {
+ display->set_imgui_visible(!display->is_imgui_visible());
+ update_cursor_visibility(window, display->is_imgui_visible());
+ }
}
}
}
+void GLDisplay::on_mouse_key(GLFWwindow* window, int button, int action, int mode) {
+ int key =
+ button + GLFW_KEY_LAST; // Mouse button index are appended after initial GLFW keys in newpad
+
+ if (button == GLFW_MOUSE_BUTTON_LEFT &&
+ g_cursor_input_mode ==
+ GLFW_CURSOR_NORMAL) { // Are there any other mouse buttons we don't want to use?
+ Pad::ClearKey(key);
+ return;
+ }
+
+ if (action == GlfwKeyAction::Press) {
+ Pad::OnKeyPress(key);
+ } else if (action == GlfwKeyAction::Release) {
+ Pad::OnKeyRelease(key);
+ }
+}
+
+void GLDisplay::on_cursor_position(GLFWwindow* window, double xposition, double yposition) {
+ Pad::MappingInfo mapping_info = Gfx::get_button_mapping();
+ if (g_cursor_input_mode == GLFW_CURSOR_NORMAL) {
+ if (is_cursor_position_valid == true) {
+ Pad::ClearAnalogAxisValue(mapping_info, GlfwKeyCustomAxis::CURSOR_X_AXIS);
+ Pad::ClearAnalogAxisValue(mapping_info, GlfwKeyCustomAxis::CURSOR_Y_AXIS);
+ is_cursor_position_valid = false;
+ }
+ return;
+ }
+
+ if (is_cursor_position_valid == false) {
+ last_cursor_x_position = xposition;
+ last_cursor_y_position = yposition;
+ is_cursor_position_valid = true;
+ return;
+ }
+
+ double xoffset = xposition - last_cursor_x_position;
+ double yoffset = yposition - last_cursor_y_position;
+
+ Pad::SetAnalogAxisValue(mapping_info, GlfwKeyCustomAxis::CURSOR_X_AXIS, xoffset);
+ Pad::SetAnalogAxisValue(mapping_info, GlfwKeyCustomAxis::CURSOR_Y_AXIS, yoffset);
+
+ last_cursor_x_position = xposition;
+ last_cursor_y_position = yposition;
+}
+
void GLDisplay::on_window_pos(GLFWwindow* /*window*/, int xpos, int ypos) {
if (m_fullscreen_target_mode == GfxDisplayMode::Windowed) {
m_last_windowed_xpos = xpos;
@@ -451,7 +522,8 @@ void GLDisplay::update_fullscreen(GfxDisplayMode mode, int screen) {
x = m_last_windowed_xpos;
y = m_last_windowed_ypos;
} else {
- // fullscreen -> windowed, use last windowed size but on the monitor previously fullscreened
+ // fullscreen -> windowed, use last windowed size but on the monitor previously
+ // fullscreened
int monitorX, monitorY, monitorWidth, monitorHeight;
glfwGetMonitorWorkarea(monitor, &monitorX, &monitorY, &monitorWidth, &monitorHeight);
@@ -464,8 +536,8 @@ void GLDisplay::update_fullscreen(GfxDisplayMode mode, int screen) {
glfwSetWindowAttrib(m_window, GLFW_DECORATED, GLFW_TRUE);
glfwSetWindowFocusCallback(m_window, NULL);
glfwSetWindowAttrib(m_window, GLFW_FLOATING, GLFW_FALSE);
+
glfwSetWindowMonitor(m_window, NULL, x, y, width, height, GLFW_DONT_CARE);
- set_imgui_visible(true);
// these might have changed
m_last_windowed_width = width;
@@ -480,7 +552,6 @@ void GLDisplay::update_fullscreen(GfxDisplayMode mode, int screen) {
glfwSetWindowFocusCallback(m_window, NULL);
glfwSetWindowAttrib(m_window, GLFW_FLOATING, GLFW_FALSE);
glfwSetWindowMonitor(m_window, monitor, 0, 0, vmode->width, vmode->height, GLFW_DONT_CARE);
- set_imgui_visible(false);
} break;
case GfxDisplayMode::Borderless: {
// borderless fullscreen
@@ -495,7 +566,6 @@ void GLDisplay::update_fullscreen(GfxDisplayMode mode, int screen) {
#else
glfwSetWindowMonitor(m_window, NULL, x, y, vmode->width, vmode->height, GLFW_DONT_CARE);
#endif
- set_imgui_visible(false);
} break;
}
}
@@ -602,7 +672,9 @@ void GLDisplay::render() {
auto p = scoped_prof("poll-gamepads");
glfwPollEvents();
glfwMakeContextCurrent(m_window);
- Pad::update_gamepads();
+
+ auto& mapping_info = Gfx::get_button_mapping();
+ Pad::update_gamepads(mapping_info);
}
// imgui start of frame
@@ -761,13 +833,15 @@ void gl_send_chain(const void* data, u32 offset) {
// we copy the dma data and give a copy of it to the render.
// the copy has a few advantages:
// - if the game code has a bug and corrupts the DMA buffer, the renderer won't see it.
- // - the copied DMA is much smaller than the entire game memory, so it can be dumped to a file
+ // - the copied DMA is much smaller than the entire game memory, so it can be dumped to a
+ // file
// separate of the entire RAM.
// - it verifies the DMA data is valid early on.
- // but it may also be pretty expensive. Both the renderer and the game wait on this to complete.
+ // but it may also be pretty expensive. Both the renderer and the game wait on this to
+ // complete.
- // The renderers should just operate on DMA chains, so eliminating this step in the future may
- // be easy.
+ // The renderers should just operate on DMA chains, so eliminating this step in the future
+ // may be easy.
g_gfx_data->dma_copier.set_input_data(data, offset, run_dma_copy);
diff --git a/game/graphics/pipelines/opengl.h b/game/graphics/pipelines/opengl.h
index ffe4a1b0be..40d53be35f 100644
--- a/game/graphics/pipelines/opengl.h
+++ b/game/graphics/pipelines/opengl.h
@@ -18,6 +18,11 @@ enum GlfwKeyAction {
Repeat = GLFW_REPEAT // repeated input on hold e.g. when typing something
};
+enum GlfwKeyCustomAxis {
+ CURSOR_X_AXIS = GLFW_GAMEPAD_AXIS_LAST + 1,
+ CURSOR_Y_AXIS = GLFW_GAMEPAD_AXIS_LAST + 2
+};
+
class GLDisplay : public GfxDisplay {
public:
GLDisplay(GLFWwindow* window, bool is_main);
@@ -42,6 +47,9 @@ class GLDisplay : public GfxDisplay {
void on_window_pos(GLFWwindow* window, int xpos, int ypos);
void on_window_size(GLFWwindow* window, int width, int height);
void on_iconify(GLFWwindow* window, int iconified);
+ void on_mouse_key(GLFWwindow* window, int button, int action, int mode);
+ void on_cursor_position(GLFWwindow* window, double xposition, double yposition);
+ void update_cursor_visibility(GLFWwindow* window, bool is_visible);
private:
GLFWwindow* m_window;
@@ -52,3 +60,6 @@ class GLDisplay : public GfxDisplay {
};
extern const GfxRendererModule gRendererOpenGL;
+namespace glfw {
+static const int NUM_KEYS = GLFW_KEY_LAST + GLFW_MOUSE_BUTTON_LAST + 1;
+}
diff --git a/game/sce/libpad.cpp b/game/sce/libpad.cpp
index d92410a3c8..823cf7884c 100644
--- a/game/sce/libpad.cpp
+++ b/game/sce/libpad.cpp
@@ -70,10 +70,10 @@ int scePadRead(int port, int /*slot*/, u8* rdata) {
cpad->status = 0x70 /* (dualshock2) */ | (20 / 2); /* (dualshock2 data size) */
- cpad->rightx = Gfx::PadAnalogValue(Pad::Analog::Right_X, port);
- cpad->righty = Gfx::PadAnalogValue(Pad::Analog::Right_Y, port);
- cpad->leftx = Gfx::PadAnalogValue(Pad::Analog::Left_X, port);
- cpad->lefty = Gfx::PadAnalogValue(Pad::Analog::Left_Y, port);
+ cpad->rightx = Gfx::PadGetAnalogValue(Pad::Analog::Right_X, port);
+ cpad->righty = Gfx::PadGetAnalogValue(Pad::Analog::Right_Y, port);
+ cpad->leftx = Gfx::PadGetAnalogValue(Pad::Analog::Left_X, port);
+ cpad->lefty = Gfx::PadGetAnalogValue(Pad::Analog::Left_Y, port);
// pressure sensitivity. ignore for now.
for (int i = 0; i < 12; ++i) {
diff --git a/game/system/newpad.cpp b/game/system/newpad.cpp
index 7931b15624..cde31c0dd0 100644
--- a/game/system/newpad.cpp
+++ b/game/system/newpad.cpp
@@ -6,6 +6,9 @@
#include "newpad.h"
+#include
+#include
+
#include "common/log/log.h"
#include "common/util/Assert.h"
#include "common/util/FileUtil.h"
@@ -22,11 +25,12 @@ namespace Pad {
********************************
*/
-constexpr int NUM_KEYS = GLFW_KEY_LAST + 1;
// key-down status of any detected key.
-bool g_key_status[NUM_KEYS] = {0};
+bool g_key_status[glfw::NUM_KEYS] = {0};
// key-down status of any detected key. this is buffered for the remainder of a frame.
-bool g_buffered_key_status[NUM_KEYS] = {0};
+bool g_buffered_key_status[glfw::NUM_KEYS] = {0};
+
+float g_key_analogs[CONTROLLER_COUNT][(int)Analog::Max] = {{0}};
bool g_gamepad_buttons[CONTROLLER_COUNT][(int)Button::Max] = {{0}};
float g_gamepad_analogs[CONTROLLER_COUNT][(int)Analog::Max] = {{0}};
@@ -44,6 +48,36 @@ u64 input_mode_mod = 0;
u64 input_mode_index = 0;
MappingInfo g_input_mode_mapping;
+void ClearKey(int key) {
+ if (key < 0 || key > glfw::NUM_KEYS) {
+ lg::warn("ClearKey failed: Attempted to clear invalid key {}", key);
+ return;
+ }
+
+ g_key_status[key] = false;
+ g_buffered_key_status[key] = false;
+}
+
+void ClearAnalogAxisValue(MappingInfo& mapping_info, int axis) {
+ for (int pad = 0; pad < CONTROLLER_COUNT; ++pad) {
+ for (int analog = 0; analog < (int)Analog::Max; ++analog) {
+ if (mapping_info.keyboard_analog_mapping[pad][analog].axis_id == axis &&
+ mapping_info.keyboard_analog_mapping[pad][analog].mode ==
+ AnalogMappingMode::AnalogInput) {
+ g_key_analogs[pad][analog] = 0.0f;
+ }
+ }
+ }
+}
+
+void ForceClearAnalogValue() {
+ for (int pad = 0; pad < CONTROLLER_COUNT; ++pad) {
+ for (int analog = 0; analog < (int)Analog::Max; ++analog) {
+ g_key_analogs[pad][analog] = 0.0f;
+ }
+ }
+}
+
void ForceClearKeys() {
for (auto& key : g_key_status) {
key = false;
@@ -54,7 +88,7 @@ void ForceClearKeys() {
}
void ClearKeys() {
- for (int key = 0; key < NUM_KEYS; key++) {
+ for (int key = 0; key < glfw::NUM_KEYS; key++) {
g_buffered_key_status[key] = g_key_status[key];
}
}
@@ -77,7 +111,7 @@ void OnKeyPress(int key) {
return;
}
// set absolute key status
- ASSERT(key < NUM_KEYS);
+ ASSERT(key < glfw::NUM_KEYS);
g_key_status[key] = true;
// set buffered key status
g_buffered_key_status[key] = true;
@@ -87,7 +121,7 @@ void OnKeyRelease(int key) {
if (input_mode == InputModeStatus::Enabled) {
return;
}
- ASSERT(key < NUM_KEYS);
+ ASSERT(key < glfw::NUM_KEYS);
g_key_status[key] = false;
}
@@ -98,14 +132,15 @@ void OnKeyRelease(int key) {
*/
static int CheckPadIdx(int pad) {
- if (pad < 0 || pad > CONTROLLER_COUNT) {
+ if (pad < 0 || pad >= CONTROLLER_COUNT) {
lg::error("Invalid pad {}", pad);
return -1;
}
return pad;
}
-// returns 1 if button is pressed. returns 0 if invalid or not pressed.
+// returns 1 if either keyboard or controller button is pressed. Controller button has priority.
+// returns 0 if invalid or not pressed.
int IsPressed(MappingInfo& mapping, Button button, int pad = 0) {
if (CheckPadIdx(pad) == -1) {
return 0;
@@ -114,67 +149,119 @@ int IsPressed(MappingInfo& mapping, Button button, int pad = 0) {
if (g_gamepad_buttons[pad][(int)button]) {
return 1;
}
- auto key = mapping.pad_mapping[pad][(int)button];
+
+ int key = mapping.keyboard_button_mapping[pad][(int)button];
if (key == -1)
return 0;
auto& keymap = mapping.buffer_mode ? g_buffered_key_status : g_key_status;
- ASSERT(key < NUM_KEYS);
+ ASSERT(key < glfw::NUM_KEYS);
return keymap[key];
}
+void SetAnalogAxisValue(MappingInfo& mapping_info, int axis, double value) {
+ const double sensitivity_numerator = Gfx::g_global_settings.target_fps;
+ const double minimum_sensitivity = 1e-4;
+
+ for (int pad = 0; pad < CONTROLLER_COUNT; ++pad) {
+ for (int analog = 0; analog < (int)Analog::Max; ++analog) {
+ if (mapping_info.keyboard_analog_mapping[pad][analog].axis_id == axis) {
+ double newValue = value;
+ if (axis == GlfwKeyCustomAxis::CURSOR_X_AXIS) {
+ if (mapping_info.mouse_x_axis_sensitivities[pad] < minimum_sensitivity) {
+ mapping_info.mouse_x_axis_sensitivities[pad] = minimum_sensitivity;
+ }
+ newValue /= (sensitivity_numerator / mapping_info.mouse_x_axis_sensitivities[pad]);
+ } else if (axis == GlfwKeyCustomAxis::CURSOR_Y_AXIS) {
+ if (mapping_info.mouse_y_axis_sensitivities[pad] < minimum_sensitivity) {
+ mapping_info.mouse_y_axis_sensitivities[pad] = minimum_sensitivity;
+ }
+ newValue /= (sensitivity_numerator / mapping_info.mouse_y_axis_sensitivities[pad]);
+ }
+
+ if (newValue > 1.0) {
+ g_key_analogs[pad][analog] = 1.0;
+ } else if (newValue < -1.0) {
+ g_key_analogs[pad][analog] = -1.0;
+ } else if (std::isnan(newValue)) {
+ g_key_analogs[pad][analog] = 0.0;
+ } else {
+ g_key_analogs[pad][analog] = newValue;
+ }
+
+ // Invert logic used here. Left Y axis movement is based on towrds the camera.
+ // In game forward is treated as going away from the camera and backwards is headed towards
+ // the camera.
+ if (axis == GlfwKeyCustomAxis::CURSOR_Y_AXIS) {
+ g_key_analogs[pad][analog] *= -1;
+ }
+ }
+ }
+ }
+}
+
+void UpdateAxisValue(MappingInfo& mapping_info) {
+ for (int pad = 0; pad < CONTROLLER_COUNT; ++pad) {
+ for (int analog = 0; analog < (int)Analog::Max; ++analog) {
+ if (mapping_info.keyboard_analog_mapping[pad][analog].mode ==
+ AnalogMappingMode::AnalogInput) {
+ continue; // Assumed Set Axis set value already
+ }
+
+ // Invert logic used here. Left Y axis movement is based on towrds the camera.
+ // In game forward is treated as going away from the camera and backwards is headed towards
+ // the camera.
+ double input = 0.0f;
+ if (mapping_info.keyboard_analog_mapping[pad][analog].positive_key > -1 &&
+ mapping_info.keyboard_analog_mapping[pad][analog].positive_key < glfw::NUM_KEYS) {
+ if (analog == static_cast(Analog::Left_Y) ||
+ analog == static_cast(Analog::Right_Y)) {
+ input -=
+ g_buffered_key_status[mapping_info.keyboard_analog_mapping[pad][analog].positive_key];
+ } else {
+ input +=
+ g_buffered_key_status[mapping_info.keyboard_analog_mapping[pad][analog].positive_key];
+ }
+ }
+ if (mapping_info.keyboard_analog_mapping[pad][analog].negative_key > -1 &&
+ mapping_info.keyboard_analog_mapping[pad][analog].negative_key < glfw::NUM_KEYS) {
+ if (analog == static_cast(Analog::Left_Y) ||
+ analog == static_cast(Analog::Right_Y)) {
+ input +=
+ g_buffered_key_status[mapping_info.keyboard_analog_mapping[pad][analog].negative_key];
+ } else {
+ input -=
+ g_buffered_key_status[mapping_info.keyboard_analog_mapping[pad][analog].negative_key];
+ }
+ }
+ g_key_analogs[pad][analog] = input;
+ }
+ }
+}
+
// returns the value of the analog axis (in the future, likely pressure sensitive if we support it?)
// if invalid or otherwise -- returns 127 (analog stick neutral position)
-int AnalogValue(MappingInfo& /*mapping*/, Analog analog, int pad = 0) {
+int GetAnalogValue(MappingInfo& /*mapping*/, Analog analog, int pad = 0) {
+ float input = 0.0f;
if (CheckPadIdx(pad) == -1) {
// Pad out of range, return a stable value
return 127;
}
- float input = 0.0f;
- if (pad == 0) {
- // Movement controls mapped to WASD keys
- if (g_buffered_key_status[GLFW_KEY_W] && analog == Analog::Left_Y)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_S] && analog == Analog::Left_Y)
- input += 1.0f;
- if (g_buffered_key_status[GLFW_KEY_A] && analog == Analog::Left_X)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_D] && analog == Analog::Left_X)
- input += 1.0f;
-
- // Camera controls mapped to IJKL keys
- if (g_buffered_key_status[GLFW_KEY_I] && analog == Analog::Right_Y)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_K] && analog == Analog::Right_Y)
- input += 1.0f;
- if (g_buffered_key_status[GLFW_KEY_J] && analog == Analog::Right_X)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_L] && analog == Analog::Right_X)
- input += 1.0f;
- } else if (pad == 1) {
- // these bindings are not sane
- if (g_buffered_key_status[GLFW_KEY_KP_5] && analog == Analog::Left_Y)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_KP_2] && analog == Analog::Left_Y)
- input += 1.0f;
- if (g_buffered_key_status[GLFW_KEY_KP_1] && analog == Analog::Left_X)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_KP_3] && analog == Analog::Left_X)
- input += 1.0f;
-
- // these bindings are not sane
- if (g_buffered_key_status[GLFW_KEY_KP_DIVIDE] && analog == Analog::Right_Y)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_KP_8] && analog == Analog::Right_Y)
- input += 1.0f;
- if (g_buffered_key_status[GLFW_KEY_KP_7] && analog == Analog::Right_X)
- input += -1.0f;
- if (g_buffered_key_status[GLFW_KEY_KP_9] && analog == Analog::Right_X)
- input += 1.0f;
+ float controller_input = 0.0f;
+ if (g_gamepads.gamepad_idx[pad] > -1) {
+ controller_input = g_gamepad_analogs[pad][(int)analog];
}
- if (input == 0) {
- input = g_gamepad_analogs[pad][(int)analog];
+ float keyboard_input = g_key_analogs[pad][(int)analog];
+ // Hack. Clearing the buffer immediately can lead to inconsistencies on analog input.
+ // If a mouse is disconnected or can't calculate a new delta it would stay stuck at 1.
+ // Decreasing the values gradually seems like a good comprise.
+ g_key_analogs[pad][(int)analog] *= 0.95;
+
+ if (fabs(controller_input) > fabs(keyboard_input)) {
+ input = controller_input;
+ } else {
+ input = keyboard_input;
}
// GLFW provides float in range -1 to 1, caller expects 0-255
@@ -195,15 +282,62 @@ void MapButton(MappingInfo& mapping, Button button, int pad, int key) {
return;
}
- mapping.pad_mapping[pad][(int)button] = key;
+ if (g_gamepads.gamepad_idx[pad] == -1) {
+ // TODO: Check if other pad is keyboard and if key is already bound
+ mapping.keyboard_button_mapping[pad][(int)button] = key;
+ } else {
+ mapping.controller_button_mapping[pad][(int)button] = key;
+ }
+}
+
+void MapAnalog(MappingInfo& mapping, Analog button, int pad, AnalogMappingInfo& analomapping_info) {
+ // check if pad is valid. dont map buttons with invalid pads.
+ if (CheckPadIdx(pad) == -1) {
+ return;
+ }
+
+ if (g_gamepads.gamepad_idx[pad] == -1) {
+ // TODO: Check if other pad is keyboard and if key is already bound
+ mapping.keyboard_analog_mapping[pad][(int)button] = analomapping_info;
+ } else {
+ mapping.controller_analog_mapping[pad][(int)button] = analomapping_info;
+ }
}
// reset button mappings
void DefaultMapping(MappingInfo& mapping) {
// make every button invalid
- for (int p = 0; p < CONTROLLER_COUNT; ++p) {
- for (int i = 0; i < (int)Button::Max; ++i) {
- MapButton(mapping, (Button)i, p, -1);
+ for (int32_t pad = 0; pad < CONTROLLER_COUNT; ++pad) {
+ for (int32_t button = 0; button < (int)Pad::Button::Max; ++button) {
+ mapping.controller_button_mapping[pad][button] = -1;
+ mapping.keyboard_button_mapping[pad][button] = -1;
+ }
+
+ for (int32_t analog = 0; analog < (int)Pad::Analog::Max; ++analog) {
+ mapping.controller_analog_mapping[pad][analog] = AnalogMappingInfo();
+ mapping.keyboard_analog_mapping[pad][analog] = AnalogMappingInfo();
+ }
+ }
+
+ constexpr std::pair
-
+
@@ -11,8 +11,8 @@
-- [READ FIRST](#read-first)
- - [How to play the game](#how-to-play-the-game)
+- [Please read first](#please-read-first)
+ - [Quick Start](#quick-start)
- [Project Description](#project-description)
- [Current Status](#current-status)
- [Methodology](#methodology)
@@ -40,21 +40,21 @@
- [`goal_src/`](#goal_src)
- [`game` runtime](#game-runtime)
-## READ FIRST
+## Please read first
-The github repositories are for development of the project and tracking active issues. Most of the information you will find here pertains to setting up the project for development purposes and is not relevant to a general user.
+Our repositories on GitHub are primarily for development of the project and tracking active issues. Most of the information you will find here pertains to setting up the project for development purposes and is not relevant to the end-user.
-There is a discord server where discussion occur https://discord.gg/VZbXMHXzWv
+For questions or additional information pertaining to the project, we have a Discord for discussion here: https://discord.gg/VZbXMHXzWv
-Additionally you can find further information and answers to **frequently asked questions** on the project's main website https://open-goal.github.io/
+Additionally, you can find further documentation and answers to **frequently asked questions** on the project's main website: https://opengoal.dev
-### How to play the game
+**Do not use this decompilation project without providing your own legally purchased copy of the game.**
-To just play the game, follow the steps in this video https://www.youtube.com/watch?v=p8I9NfuZOgE
+### Quick Start
-We don't save any assets from the game - you must use your own legitimately obtained copy of the game.
+If you just want to play the game, you can follow the steps in this video: https://www.youtube.com/watch?v=p8I9NfuZOgE
-> Note that this installation method is a temporary stop gap while we work on something more user-friendly.
+We do not distribute any assets from the game - you must use your own legitimately obtained PS2 copy of the game. We support every retail PAL, NTSC, and NTSC-J build, including Greatest Hits copies.
## Project Description
@@ -94,7 +94,7 @@ Our decompiler is designed specifically for processing the output of the origina
The remainder of this README is catered towards people interested in building the project from source, typically with the intention on contributing as a developer.
-If this does not sound like you and you just want to play the game, refer to the above section [How to play the game](#how-to-play-the-game)
+If this does not sound like you and you just want to play the game, refer to the above section [Quick Start](#quick-start)
### Docker
From bae02a83af7b0d1d0e7c7d1dbeffe929af00b172 Mon Sep 17 00:00:00 2001
From: OpenGOALBot
Date: Mon, 22 Aug 2022 16:21:42 +0000
Subject: [PATCH 19/23] Updating Controller Database
---
game/assets/sdl_controller_db.txt | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/game/assets/sdl_controller_db.txt b/game/assets/sdl_controller_db.txt
index f5874a3dec..0cd4e9463c 100644
--- a/game/assets/sdl_controller_db.txt
+++ b/game/assets/sdl_controller_db.txt
@@ -19,6 +19,7 @@
03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
+03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000151000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a2,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
@@ -211,6 +212,7 @@
03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
+03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
@@ -276,7 +278,7 @@
030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
-03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b07,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b08,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows,
+03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00009c00000000000000,Hori TAC Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000c900000000000000,Hori Taiko Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000c100000000000000,Horipad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -746,6 +748,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
+03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001151000000020000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000a30c00002400000006020000,8BitDo M30,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,guide:b9,leftshoulder:b6,lefttrigger:b5,rightshoulder:b4,righttrigger:b7,start:b8,x:b3,y:b0,platform:Mac OS X,
@@ -973,6 +976,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
+05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000151000000010000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1234,7 +1239,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
-050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
+050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
@@ -1459,8 +1464,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e040000120b000007050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000005e040000130b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
-030000005e040000120b000007050000,Xbox Series X Controller,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,misc1:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
050000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
@@ -1479,8 +1484,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android,
+38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+62656331626461363634633735353032,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
38393936616436383062666232653338,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
-38426974446f2038426974446f204c69,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
+38426974446f204c6974652053450000,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
39356430616562366466646636643435,8BitDo Lite SE,a:b1,b:b0,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000006500000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a5,rightshoulder:b10,righttrigger:a4,start:b6,x:b3,y:b2,platform:Android,
05000000c82d000051060000ffff3f00,8BitDo M30,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b17,leftshoulder:b9,lefttrigger:a4,rightshoulder:b10,righttrigger:a5,start:b6,x:b3,y:b2,platform:Android,
From 5af36ac610f5d1b4616345dc2406f3f61478240c Mon Sep 17 00:00:00 2001
From: water111 <48171810+water111@users.noreply.github.com>
Date: Mon, 22 Aug 2022 18:02:31 -0400
Subject: [PATCH 20/23] maybe fix bridge blast (#1784)
---
goal_src/jak1/engine/common-obs/ropebridge.gc | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/goal_src/jak1/engine/common-obs/ropebridge.gc b/goal_src/jak1/engine/common-obs/ropebridge.gc
index 077d0f08d2..d189898f46 100644
--- a/goal_src/jak1/engine/common-obs/ropebridge.gc
+++ b/goal_src/jak1/engine/common-obs/ropebridge.gc
@@ -608,7 +608,21 @@
(when (-> self do-physics?)
(clear-spring-forces self)
(set-vel-from-riders self)
- (do-integration self)
+
+ ;; original
+ ;; (do-integration self)
+
+ ;; modified to try to fix crazy bridges
+ ;; instead of doing one big step when lagging, do multiple small steps.
+ ;; temporarily change time ratio to 1.0 (like we are 60 fps)
+ (let ((old-time-ratio (the int (-> *display* time-ratio))))
+ (set-time-ratios *display* 1.0)
+ ;; then do multiple steps to simulate the same amount of time, but without longer timesteps
+ (dotimes (i old-time-ratio)
+ (do-integration self)
+ )
+ (set-time-ratios *display* (the float old-time-ratio))
+ )
)
)
(none)
From 06ef52cd2545b15e3bfed2588129cb64717a255c Mon Sep 17 00:00:00 2001
From: water111 <48171810+water111@users.noreply.github.com>
Date: Mon, 22 Aug 2022 18:53:51 -0400
Subject: [PATCH 21/23] [decompiler] support for jak 2 (#1781)
* [decompiler] suppport jak 2
* cleanpu
* remove brief from gtest options
* fix test
---
common/type_system/TypeFieldLookup.cpp | 27 +-
decompiler/CMakeLists.txt | 3 +
decompiler/Function/Warnings.h | 1 -
decompiler/IR2/AtomicOp.cpp | 51 +-
decompiler/IR2/AtomicOp.h | 89 +-
decompiler/IR2/AtomicOpTypeAnalysis.cpp | 1 +
decompiler/IR2/Env.cpp | 124 +-
decompiler/IR2/Env.h | 1 +
decompiler/IR2/ExpressionHelpers.cpp | 31 +-
decompiler/IR2/Form.cpp | 3 +
decompiler/IR2/Form.h | 12 +-
decompiler/IR2/FormExpressionAnalysis.cpp | 70 +-
decompiler/IR2/IR2_common.h | 1 +
decompiler/ObjectFile/LinkedObjectFile.h | 4 +-
.../ObjectFile/LinkedObjectFileCreation.cpp | 2 +-
decompiler/ObjectFile/ObjectFileDB.cpp | 2 +-
decompiler/ObjectFile/ObjectFileDB.h | 1 +
decompiler/ObjectFile/ObjectFileDB_IR2.cpp | 30 +-
.../analysis/analyze_inspect_method.cpp | 9 +-
decompiler/analysis/atomic_op_builder.cpp | 88 +-
decompiler/analysis/insert_lets.cpp | 39 +-
decompiler/config/jak2/all-types.gc | 9414 +++++++++--------
.../jak2/anonymous_function_types.jsonc | 30 +
decompiler/config/jak2/hacks.jsonc | 38 +-
decompiler/config/jak2/label_types.jsonc | 67 +-
decompiler/config/jak2/stack_structures.jsonc | 159 +-
decompiler/config/jak2/type_casts.jsonc | 365 +-
decompiler/config/jak2/var_names.jsonc | 45 +-
decompiler/config/jak2_ntsc_v1.jsonc | 2 +-
decompiler/level_extractor/fr3_to_gltf.cpp | 4 +-
decompiler/types2/ForwardProp.cpp | 2455 +++++
decompiler/types2/types2.cpp | 760 ++
decompiler/types2/types2.h | 248 +
decompiler/util/DecompilerTypeSystem.cpp | 4 +-
decompiler/util/data_decompile.cpp | 27 +-
decompiler/util/goal_constants.h | 3 +
goal_src/jak2/kernel-defs.gc | 2 +-
goalc/build_level/collide_bvh.cpp | 62 +-
test.sh | 2 +-
test/decompiler/FormRegressionTest.h | 2 +-
.../reference/jak1/engine/anim/joint_REF.gc | 2 +-
.../jak1/engine/draw/drawable_REF.gc | 2 +-
.../reference/jak1/engine/gfx/sky/sky_REF.gc | 2 +-
.../reference/jak1/engine/math/vector_REF.gc | 22 +-
.../reference/jak1/engine/util/glist_REF.gc | 4 +-
.../jak1/levels/rolling/rolling-obs_REF.gc | 2 +-
.../reference/jak2/decompiler-macros.gc | 141 +
.../reference/jak2/kernel/gstate_REF.gc | 2 +-
test/decompiler/test_InstructionDecode.cpp | 8 +-
test/offline/config/jak2/config.jsonc | 21 +-
test/offline/offline_test_main.cpp | 5 +-
51 files changed, 9934 insertions(+), 4555 deletions(-)
create mode 100644 decompiler/types2/ForwardProp.cpp
create mode 100644 decompiler/types2/types2.cpp
create mode 100644 decompiler/types2/types2.h
diff --git a/common/type_system/TypeFieldLookup.cpp b/common/type_system/TypeFieldLookup.cpp
index cc013e71ec..5b690d75de 100644
--- a/common/type_system/TypeFieldLookup.cpp
+++ b/common/type_system/TypeFieldLookup.cpp
@@ -482,20 +482,6 @@ FieldReverseLookupOutput TypeSystem::reverse_field_lookup(
// just use the multi-lookup set to 1 and grab the first result.
auto multi_result = reverse_field_multi_lookup(input, 100);
- for (auto& result : multi_result.results) {
- // compute the score.
- result.total_score = 0;
- for (auto& tok : result.tokens) {
- result.total_score += tok.score();
- }
- }
-
- // use stable sort to make sure we break ties by being first in the order.
- std::stable_sort(multi_result.results.begin(), multi_result.results.end(),
- [](const FieldReverseLookupOutput& a, const FieldReverseLookupOutput& b) {
- return a.total_score > b.total_score;
- });
-
/*
if (multi_result.results.size() > 1) {
fmt::print("Multiple:\n");
@@ -532,6 +518,19 @@ FieldReverseMultiLookupOutput TypeSystem::reverse_field_multi_lookup(
try_reverse_lookup(input, *this, nullptr, &result, max_count);
if (!result.results.empty()) {
result.success = true;
+ for (auto& r : result.results) {
+ // compute the score.
+ r.total_score = 0;
+ for (auto& tok : r.tokens) {
+ r.total_score += tok.score();
+ }
+ }
+
+ // use stable sort to make sure we break ties by being first in the order.
+ std::stable_sort(result.results.begin(), result.results.end(),
+ [](const FieldReverseLookupOutput& a, const FieldReverseLookupOutput& b) {
+ return a.total_score > b.total_score;
+ });
}
return result;
}
diff --git a/decompiler/CMakeLists.txt b/decompiler/CMakeLists.txt
index db9b96959a..0374470012 100644
--- a/decompiler/CMakeLists.txt
+++ b/decompiler/CMakeLists.txt
@@ -69,6 +69,9 @@ add_library(
ObjectFile/ObjectFileDB.cpp
ObjectFile/ObjectFileDB_IR2.cpp
+ types2/ForwardProp.cpp
+ types2/types2.cpp
+
util/config_parsers.cpp
util/data_decompile.cpp
util/DataParser.cpp
diff --git a/decompiler/Function/Warnings.h b/decompiler/Function/Warnings.h
index ad1a7bc4f1..92426b73d1 100644
--- a/decompiler/Function/Warnings.h
+++ b/decompiler/Function/Warnings.h
@@ -104,6 +104,5 @@ class DecompWarnings {
}
std::vector m_warnings;
- bool m_used_lq_sq = false;
};
} // namespace decompiler
diff --git a/decompiler/IR2/AtomicOp.cpp b/decompiler/IR2/AtomicOp.cpp
index 72f19106df..d5d4b9a17e 100644
--- a/decompiler/IR2/AtomicOp.cpp
+++ b/decompiler/IR2/AtomicOp.cpp
@@ -142,16 +142,55 @@ SimpleAtom SimpleAtom::make_static_address(int static_label_id) {
return result;
}
+/*!
+ * Mark this atom as a float. It will be printed as a float.
+ * This can only be applied to an "integer" atom.
+ * This should be used carefully, as this doesn't handle casts/types - it just changes the
+ * representation, which will do the wrong thing unless the type system is aware of this
+ * too.
+ */
+void SimpleAtom::mark_as_float() {
+ ASSERT(is_int());
+ m_display_int_as_float = true;
+}
+
+bool SimpleAtom::is_integer_promoted_to_float() const {
+ return m_kind == Kind::INTEGER_CONSTANT && m_display_int_as_float;
+}
+
+float SimpleAtom::get_integer_promoted_to_float() const {
+ ASSERT(is_integer_promoted_to_float());
+ s32 as_s32 = get_int();
+ ASSERT(get_int() == (s64)as_s32);
+ float result;
+ memcpy(&result, &as_s32, 4);
+ return result;
+}
+
goos::Object SimpleAtom::to_form(const std::vector& labels, const Env& env) const {
switch (m_kind) {
case Kind::VARIABLE:
return m_variable.to_form(env);
case Kind::INTEGER_CONSTANT: {
- if (std::abs(m_int) > INT32_MAX) {
- u64 v = m_int;
- return pretty_print::to_symbol(fmt::format("#x{:x}", v));
+ if (m_display_int_as_float) {
+ float f;
+ s32 as_s32 = m_int;
+ ASSERT(((s64)as_s32) == m_int); // float should always be a sign extended 32-bit value.
+ memcpy(&f, &as_s32, 4);
+ if (f == f) {
+ return goos::Object::make_float(f);
+ } else {
+ // nan or weird
+ ASSERT(false); // let's abort on this for now, can remove if it actually comes up.
+ return pretty_print::to_symbol(fmt::format("(the-as float #x{:x})", m_int));
+ }
} else {
- return goos::Object::make_integer(m_int);
+ if (std::abs(m_int) > INT32_MAX) {
+ u64 v = m_int;
+ return pretty_print::to_symbol(fmt::format("#x{:x}", v));
+ } else {
+ return goos::Object::make_integer(m_int);
+ }
}
}
@@ -311,6 +350,8 @@ std::string get_simple_expression_op_name(SimpleExpression::Kind kind) {
return "vec3dot";
case SimpleExpression::Kind::VECTOR_4_DOT:
return "vec4dot";
+ case SimpleExpression::Kind::VECTOR_LENGTH:
+ return "veclength";
case SimpleExpression::Kind::SET_ON_LESS_THAN:
case SimpleExpression::Kind::SET_ON_LESS_THAN_IMM:
return "set-on-less-than";
@@ -378,6 +419,8 @@ int get_simple_expression_arg_count(SimpleExpression::Kind kind) {
case SimpleExpression::Kind::SET_ON_LESS_THAN:
case SimpleExpression::Kind::SET_ON_LESS_THAN_IMM:
return 2;
+ case SimpleExpression::Kind::VECTOR_LENGTH:
+ return 1;
default:
ASSERT(false);
return -1;
diff --git a/decompiler/IR2/AtomicOp.h b/decompiler/IR2/AtomicOp.h
index 7b84193768..1cecc2e497 100644
--- a/decompiler/IR2/AtomicOp.h
+++ b/decompiler/IR2/AtomicOp.h
@@ -19,6 +19,11 @@ class FormElement;
class ConditionElement;
class FormPool;
class DecompilerTypeSystem;
+namespace types2 {
+struct Instruction;
+struct TypeState;
+struct TypePropExtras;
+} // namespace types2
/*!
* An atomic operation represents a single operation from the point of view of the IR2 system.
@@ -78,6 +83,12 @@ class AtomicOp {
TypeState propagate_types(const TypeState& input, const Env& env, DecompilerTypeSystem& dts);
+ virtual void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) = 0;
+
int op_id() const { return m_my_idx; }
const std::vector& read_regs() const { return m_read_regs; }
const std::vector& write_regs() const { return m_write_regs; }
@@ -176,12 +187,16 @@ class SimpleAtom {
ASSERT(is_sym_ptr() || is_sym_val());
return m_string;
}
+ void mark_as_float();
+ bool is_integer_promoted_to_float() const;
+ float get_integer_promoted_to_float() const;
private:
Kind m_kind = Kind::INVALID;
std::string m_string; // for symbol ptr and symbol val
s64 m_int = -1; // for integer constant and static address label id
RegisterAccess m_variable;
+ bool m_display_int_as_float = false;
};
/*!
@@ -240,6 +255,7 @@ class SimpleExpression {
SUBU_L32_S7, // use SUBU X, src0, s7 to check if lower 32-bits are s7.
VECTOR_3_DOT,
VECTOR_4_DOT,
+ VECTOR_LENGTH, // jak 2 only.
SET_ON_LESS_THAN,
SET_ON_LESS_THAN_IMM
};
@@ -250,6 +266,11 @@ class SimpleExpression {
ASSERT(idx < args());
return m_args[idx];
}
+
+ SimpleAtom& get_arg(int idx) {
+ ASSERT(idx < args());
+ return m_args[idx];
+ }
Kind kind() const { return m_kind; }
SimpleExpression() = default;
SimpleExpression(Kind kind, const SimpleAtom& arg0);
@@ -304,6 +325,11 @@ class SetVarOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
const RegisterAccess& dst() const { return m_dst; }
const SimpleExpression& src() const { return m_src; }
@@ -334,6 +360,11 @@ class AsmOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
const Instruction& instruction() const { return m_instr; }
const std::optional dst() const { return m_dst; }
@@ -437,6 +468,11 @@ class SetVarConditionOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
private:
@@ -463,6 +499,11 @@ class StoreOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
const SimpleExpression& addr() const { return m_addr; }
const SimpleAtom& value() const { return m_value; }
@@ -492,9 +533,13 @@ class LoadVarOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
TP_Type get_src_type(const TypeState& input, const Env& env, DecompilerTypeSystem& dts) const;
void collect_vars(RegAccessSet& vars) const override;
-
const SimpleExpression& src() const { return m_src; }
Kind kind() const { return m_kind; }
int size() const { return m_size; }
@@ -580,6 +625,11 @@ class BranchOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
const IR2_BranchDelay& branch_delay() const { return m_branch_delay; }
const IR2_Condition& condition() const { return m_condition; }
@@ -616,6 +666,11 @@ class AsmBranchOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
bool is_likely() const { return m_likely; }
const IR2_Condition& condition() const { return m_condition; }
@@ -653,6 +708,11 @@ class SpecialOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
Kind kind() const { return m_kind; }
@@ -676,6 +736,11 @@ class CallOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
const std::vector& arg_vars() const { return m_arg_vars; }
RegisterAccess function_var() const { return m_function_var; }
@@ -717,6 +782,11 @@ class ConditionalMoveFalseOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
private:
@@ -748,6 +818,11 @@ class FunctionEndOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
void mark_function_as_no_return_value();
const RegisterAccess& return_var() const {
@@ -775,7 +850,13 @@ class StackSpillStoreOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
+ int offset() const { return m_offset; }
private:
SimpleAtom m_value;
@@ -798,7 +879,13 @@ class StackSpillLoadOp : public AtomicOp {
TypeState propagate_types_internal(const TypeState& input,
const Env& env,
DecompilerTypeSystem& dts) override;
+ void propagate_types2(types2::Instruction& instr,
+ const Env& env,
+ types2::TypeState& input_types,
+ DecompilerTypeSystem& dts,
+ types2::TypePropExtras& extras) override;
void collect_vars(RegAccessSet& vars) const override;
+ int offset() const { return m_offset; }
private:
RegisterAccess m_dst;
diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp
index 327e8ada80..c843bfbdee 100644
--- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp
+++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp
@@ -243,6 +243,7 @@ TP_Type SimpleExpression::get_type(const TypeState& input,
return TP_Type::make_from_ts("int");
case Kind::VECTOR_3_DOT:
case Kind::VECTOR_4_DOT:
+ case Kind::VECTOR_LENGTH:
return TP_Type::make_from_ts("float");
default:
throw std::runtime_error("Simple expression cannot get_type: " +
diff --git a/decompiler/IR2/Env.cpp b/decompiler/IR2/Env.cpp
index b520dbc952..011fccd69e 100644
--- a/decompiler/IR2/Env.cpp
+++ b/decompiler/IR2/Env.cpp
@@ -507,69 +507,73 @@ void Env::disable_use(const RegisterAccess& access) {
*/
void Env::set_stack_structure_hints(const std::vector& hints) {
for (auto& hint : hints) {
- StackStructureEntry entry;
- entry.hint = hint;
-
- switch (hint.container_type) {
- case StackStructureHint::ContainerType::NONE: {
- // parse the type spec.
- TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
- auto type_info = dts->ts.lookup_type(base_typespec);
- // just a plain object on the stack.
- if (!type_info->is_reference()) {
- throw std::runtime_error(
- fmt::format("Stack variable type {} is not a reference and cannot be stored directly "
- "on the stack. Use an array instead.",
- base_typespec.print()));
- }
- entry.ref_type = base_typespec;
- entry.size = type_info->get_size_in_memory();
- // sanity check the alignment
- if (align(entry.hint.stack_offset, type_info->get_in_memory_alignment()) !=
- entry.hint.stack_offset) {
- lg::error("Misaligned stack variable of type {} offset {} required align {}\n",
- entry.ref_type.print(), entry.hint.stack_offset,
- type_info->get_in_memory_alignment());
- }
- } break;
-
- case StackStructureHint::ContainerType::INLINE_ARRAY: {
- TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
- auto type_info = dts->ts.lookup_type(base_typespec);
- if (!type_info->is_reference()) {
- throw std::runtime_error(
- fmt::format("Stack inline-array element type {} is not a reference and cannot be "
- "stored in an inline-array. Use an array instead.",
- base_typespec.print()));
- }
-
- entry.ref_type = TypeSpec("inline-array", {TypeSpec(base_typespec)});
- entry.size = 1; // we assume that there is no constant propagation into this array and
- // make this only trigger in get_stack_type if we hit exactly.
- // sanity check the alignment
- if (align(entry.hint.stack_offset, type_info->get_in_memory_alignment()) !=
- entry.hint.stack_offset) {
- lg::error("Misaligned stack variable of type {} offset {} required align {}\n",
- entry.ref_type.print(), entry.hint.stack_offset,
- type_info->get_in_memory_alignment());
- }
- } break;
-
- case StackStructureHint::ContainerType::ARRAY: {
- TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
- entry.ref_type = TypeSpec("pointer", {TypeSpec(base_typespec)});
- entry.size = 1; // we assume that there is no constant propagation into this array and
- // make this only trigger in get_stack_type if we hit exactly.
- break;
- }
- default:
- ASSERT(false);
- }
-
- m_stack_structures.push_back(entry);
+ add_stack_structure_hint(hint);
}
}
+void Env::add_stack_structure_hint(const StackStructureHint& hint) {
+ StackStructureEntry entry;
+ entry.hint = hint;
+
+ switch (hint.container_type) {
+ case StackStructureHint::ContainerType::NONE: {
+ // parse the type spec.
+ TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
+ auto type_info = dts->ts.lookup_type(base_typespec);
+ // just a plain object on the stack.
+ if (!type_info->is_reference()) {
+ throw std::runtime_error(
+ fmt::format("Stack variable type {} is not a reference and cannot be stored directly "
+ "on the stack. Use an array instead.",
+ base_typespec.print()));
+ }
+ entry.ref_type = base_typespec;
+ entry.size = type_info->get_size_in_memory();
+ // sanity check the alignment
+ if (align(entry.hint.stack_offset, type_info->get_in_memory_alignment()) !=
+ entry.hint.stack_offset) {
+ lg::error("Misaligned stack variable of type {} offset {} required align {}\n",
+ entry.ref_type.print(), entry.hint.stack_offset,
+ type_info->get_in_memory_alignment());
+ }
+ } break;
+
+ case StackStructureHint::ContainerType::INLINE_ARRAY: {
+ TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
+ auto type_info = dts->ts.lookup_type(base_typespec);
+ if (!type_info->is_reference()) {
+ throw std::runtime_error(
+ fmt::format("Stack inline-array element type {} is not a reference and cannot be "
+ "stored in an inline-array. Use an array instead.",
+ base_typespec.print()));
+ }
+
+ entry.ref_type = TypeSpec("inline-array", {TypeSpec(base_typespec)});
+ entry.size = 1; // we assume that there is no constant propagation into this array and
+ // make this only trigger in get_stack_type if we hit exactly.
+ // sanity check the alignment
+ if (align(entry.hint.stack_offset, type_info->get_in_memory_alignment()) !=
+ entry.hint.stack_offset) {
+ lg::error("Misaligned stack variable of type {} offset {} required align {}\n",
+ entry.ref_type.print(), entry.hint.stack_offset,
+ type_info->get_in_memory_alignment());
+ }
+ } break;
+
+ case StackStructureHint::ContainerType::ARRAY: {
+ TypeSpec base_typespec = dts->parse_type_spec(hint.element_type);
+ entry.ref_type = TypeSpec("pointer", {TypeSpec(base_typespec)});
+ entry.size = 1; // we assume that there is no constant propagation into this array and
+ // make this only trigger in get_stack_type if we hit exactly.
+ break;
+ }
+ default:
+ ASSERT(false);
+ }
+
+ m_stack_structures.push_back(entry);
+}
+
std::optional Env::get_art_elt_name(int idx) const {
ASSERT(dts);
auto it = dts->art_group_info.find(art_group());
diff --git a/decompiler/IR2/Env.h b/decompiler/IR2/Env.h
index c577d44d06..6c5a6ef894 100644
--- a/decompiler/IR2/Env.h
+++ b/decompiler/IR2/Env.h
@@ -174,6 +174,7 @@ class Env {
}
void set_stack_structure_hints(const std::vector& hints);
+ void add_stack_structure_hint(const StackStructureHint& hint);
const std::vector& stack_structure_hints() const {
return m_stack_structures;
}
diff --git a/decompiler/IR2/ExpressionHelpers.cpp b/decompiler/IR2/ExpressionHelpers.cpp
index abbee45fca..b231cf114c 100644
--- a/decompiler/IR2/ExpressionHelpers.cpp
+++ b/decompiler/IR2/ExpressionHelpers.cpp
@@ -9,6 +9,20 @@
namespace decompiler {
+// needed for jak 2.
+std::optional try_get_const_float(const Form* form) {
+ auto* as_cfe = form->try_as_element();
+ if (as_cfe) {
+ return as_cfe->value();
+ }
+
+ auto atom = form_as_atom(form);
+ if (atom && atom->is_integer_promoted_to_float()) {
+ return atom->get_integer_promoted_to_float();
+ }
+ return {};
+}
+
FormElement* handle_get_property_value_float(const std::vector