;;-*-Lisp-*- (in-package goal) ;; name: pad.gc ;; name in dgo: pad ;; dgos: ENGINE, GAME ;; Interface for game controllers. ;; the *cpad-list* contains both game controllers. ;; Use the service-cpads functions once per frame to update the data and vibration control ;; The cpad-set-buzz! function can be used for vibration. (define-extern get-current-time (function time-frame)) (define-extern get-integral-current-time (function uint)) (define-extern get-current-language (function language-enum)) (define-extern add-debug-cursor (function symbol bucket-id int int int none)) (defenum pad-buttons :bitfield #t :type uint32 (select 0) (l3 1) (r3 2) (start 3) (up 4) (right 5) (down 6) (left 7) (l2 8) (r2 9) (l1 10) (r1 11) (triangle 12) (circle 13) (x 14) (square 15) ) (defenum pad-type (normal 4) (analog 5) (dualshock 7) (negcon 2) (namco-gun 6) ) (deftype scf-time (structure) ((stat uint8 :offset-assert 0) (second uint8 :offset-assert 1) (minute uint8 :offset-assert 2) (hour uint8 :offset-assert 3) (week uint8 :offset-assert 4) (day uint8 :offset-assert 5) (month uint8 :offset-assert 6) (year uint8 :offset-assert 7) ) :method-count-assert 9 :size-assert #x8 :flag-assert #x900000008 ) ;; this gets set to #f later on. (define *cheat-mode* #t) ;; data that comes directly from hardware. it's 32 bytes + type tag (ignored in C kernel). (deftype hw-cpad (basic) (;; BASIC CONTROLLER data ;; status = 0x40 | (data length / 2) (valid uint8 :offset-assert 4) ;; 0 if success, 255 if fail (status uint8 :offset-assert 5) ;; depends on controller (button0 uint16 :offset-assert 6) ;; binary button states! ;; DUALSHOCK or JOYSTICK data ;; status (dualshock) = 0x70 | (data length / 2) ;; status (joystick) = 0x50 | (data length / 2) (rightx uint8 :offset-assert 8) ;; right stick xdir (righty uint8 :offset-assert 9) ;; right stick ydir (leftx uint8 :offset-assert 10) ;; left stick xdir (lefty uint8 :offset-assert 11) ;; left stick ydir ;; DUALSHOCK 2 data ;; status = 0x70 | (data length / 2) (abutton uint8 12 :offset-assert 12) ;; pressure sensitivity information ;; pad buffer needs to be 32 bytes large. (dummy uint8 12 :offset-assert 24) ) :method-count-assert 9 :size-assert #x24 :flag-assert #x900000024 ) ;; data from hardware + additional info calculated here. (deftype cpad-info (hw-cpad) ((number int32 :offset-assert 36) (cpad-file int32 :offset-assert 40) (button0-abs pad-buttons 3 :offset-assert 44) (button0-shadow-abs pad-buttons 1 :offset-assert 56) (button0-rel pad-buttons 3 :offset-assert 60) (stick0-dir float :offset-assert 72) (stick0-speed float :offset-assert 76) (new-pad int32 :offset-assert 80) (state int32 :offset-assert 84) (align uint8 6 :offset-assert 88) (direct uint8 6 :offset-assert 94) (buzz-val uint8 2 :offset-assert 100) (buzz-pause-val uint8 1 :offset-assert 102) (buzz-pause-time uint8 :offset-assert 103) (buzz-time time-frame 2 :offset-assert 104) (buzz basic :offset-assert 120) (buzz-act int32 :offset-assert 124) (change-time time-frame :offset-assert 128) (old-rightx uint8 2 :offset-assert 136) (old-righty uint8 2 :offset-assert 138) (old-leftx uint8 2 :offset-assert 140) (old-lefty uint8 2 :offset-assert 142) ) :method-count-assert 10 :size-assert #x90 :flag-assert #xa00000090 (:methods (new (symbol type int) _type_ 0) (invert-analog-if-needed (_type_) none 9) ) ) (defmacro cpad-type? (type) `(= (shr (-> pad status) 4) (cpad-type ,type)) ) (defun cpad-invalid! ((arg0 cpad-info)) "Reset all data in a cpad-info" (logior! (-> arg0 valid) 128) (set! (-> arg0 button0) (the-as uint 0)) (set! (-> arg0 button0-abs 0) (pad-buttons)) (set! (-> arg0 button0-shadow-abs 0) (pad-buttons)) (set! (-> arg0 button0-rel 0) (pad-buttons)) (dotimes (v1-2 12) (nop!) (set! (-> arg0 abutton v1-2) (the-as uint 0)) ) (set! (-> arg0 stick0-dir) 0.0) (set! (-> arg0 stick0-speed) 0.0) (set! (-> arg0 rightx) (the-as uint 128)) (set! (-> arg0 righty) (the-as uint 128)) (set! (-> arg0 leftx) (the-as uint 128)) (set! (-> arg0 lefty) (the-as uint 128)) (set! (-> arg0 align 0) (the-as uint 0)) (set! (-> arg0 align 1) (the-as uint 1)) (set! (-> arg0 align 2) (the-as uint 255)) (set! (-> arg0 align 3) (the-as uint 255)) (set! (-> arg0 align 4) (the-as uint 255)) (set! (-> arg0 align 5) (the-as uint 255)) (dotimes (v1-14 6) (nop!) (set! (-> arg0 direct v1-14) (the-as uint 0)) ) ;; hey, this was fixed from jak 1! (dotimes (v1-17 2) (nop!) (set! (-> arg0 buzz-val v1-17) (the-as uint 0)) (set! (-> arg0 buzz-time v1-17) 0) ) (set! (-> arg0 buzz-pause-val 0) (the-as uint 0)) (set! (-> arg0 buzz-time 0) 0) arg0 ) (defmethod new cpad-info ((allocation symbol) (type-to-make type) (arg0 int)) "Allocate a new cpad-info and open the pad itself through the kernel" (let ((s5-0 (object-new allocation type-to-make (the-as int (-> type-to-make size))))) (set! (-> s5-0 number) arg0) (set! (-> s5-0 buzz) #f) (cpad-open s5-0 arg0) (cpad-invalid! s5-0) ) ) ;; List of controllers. It always has 2 controllers. (deftype cpad-list (basic) ((num-cpads int32 :offset-assert 4) (cpads cpad-info 2 :offset-assert 8) ) :method-count-assert 9 :size-assert #x10 :flag-assert #x900000010 (:methods (new (symbol type) _type_ 0) ) ) (defmethod new cpad-list ((allocation symbol) (type-to-make type)) "Create a cpad-list for 2 controllers. It's fine to do this even if one or both controllers aren't connected yet." (let ((gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size))))) (set! (-> gp-0 num-cpads) 2) (set! (-> gp-0 cpads 0) (new 'global 'cpad-info 0)) (set! (-> gp-0 cpads 1) (new 'global 'cpad-info 1)) gp-0 ) ) (defun analog-input ((arg0 int) (arg1 float) (arg2 float) (arg3 float) (arg4 float)) "Convert integer input from pad into a float between -out-range and +out-range. The offset is applied directly to the input. The center val is the expected value for 0, after applying offset. The max val is the expected value with the stick pushed all the way" (let* ((f1-1 (- (the float arg0) arg1)) (f0-3 (- (fabs f1-1) arg2)) (v1-0 (- arg3 arg2)) ) (if (< f1-1 0.0) (set! arg4 (- arg4)) ) (cond ((>= 0.0 f0-3) 0.0 ) ((>= f0-3 v1-0) arg4 ) (else (/ (* f0-3 arg4) v1-0) ) ) ) ) (defun cpad-set-buzz! ((arg0 cpad-info) (arg1 int) (arg2 int) (arg3 time-frame)) "Turn on vibration motor 'buzz-idx' for duration, at magnitude buzz-amount." (cond ((zero? arg2) (set! (-> arg0 buzz-val arg1) (the-as uint 0)) 0 ) ((= arg2 (-> arg0 buzz-val arg1)) (set! (-> arg0 buzz-time arg1) (the-as time-frame (max (-> arg0 buzz-time arg1) (+ (get-current-time) arg3)))) ) ((< (-> arg0 buzz-val arg1) (the-as uint arg2)) (set! (-> arg0 buzz-val arg1) (the-as uint arg2)) (set! (-> arg0 buzz-time arg1) (+ (get-current-time) arg3)) ) ) 0 (none) ) ;; the two controllers (define *cpad-list* (new 'global 'cpad-list)) ;; weird leftover debug thing, enabling overrides the x position of both sticks on both controllers. (define *cpad-debug* #f) (defun service-cpads () "Read from cpads and update vibration" (let ((gp-0 *cpad-list*)) (dotimes (s5-0 (-> gp-0 num-cpads)) (let ((s4-0 (-> *cpad-list* cpads s5-0))) (set! (-> s4-0 old-leftx 1) (-> s4-0 old-leftx 0)) (set! (-> s4-0 old-leftx 0) (-> s4-0 leftx)) (set! (-> s4-0 old-lefty 1) (-> s4-0 old-lefty 0)) (set! (-> s4-0 old-lefty 0) (-> s4-0 lefty)) (set! (-> s4-0 old-rightx 1) (-> s4-0 old-rightx 0)) (set! (-> s4-0 old-rightx 0) (-> s4-0 rightx)) (set! (-> s4-0 old-righty 1) (-> s4-0 old-righty 0)) (set! (-> s4-0 old-righty 0) (-> s4-0 righty)) (cpad-get-data s4-0) (invert-analog-if-needed s4-0) (cond ((zero? (logand (-> s4-0 valid) 128)) (dotimes (s3-0 2) (cond ((and (-> s4-0 buzz) (< (get-current-time) (-> s4-0 buzz-time s3-0)) (= *master-mode* 'game)) (let ((v1-20 s3-0)) (cond ((zero? v1-20) (set! (-> s4-0 direct s3-0) (logand (ash (-> s4-0 buzz-val s3-0) (- (the-as int (logand (get-integral-current-time) 7)))) 1) ) ) ((= v1-20 1) (set! (-> s4-0 direct s3-0) (-> s4-0 buzz-val s3-0)) ) ) ) ) ((and (zero? s3-0) (> (-> s4-0 buzz-pause-time) 0)) (set! (-> s4-0 direct s3-0) (logand (ash (-> s4-0 buzz-pause-val s3-0) (- (the-as int (logand (get-integral-current-time) 7)))) 1) ) (+! (-> s4-0 buzz-pause-time) -1) ) (else (set! (-> s4-0 buzz-val s3-0) (the-as uint 0)) (set! (-> s4-0 direct s3-0) (the-as uint 0)) (when (zero? s3-0) (set! (-> s4-0 buzz-pause-time) (the-as uint 0)) 0 ) ) ) ) (when (< (the-as uint 192) (-> s4-0 direct 1)) (set! (-> s4-0 direct 0) (the-as uint 0)) 0 ) (set! (-> s4-0 button0-abs 2) (-> s4-0 button0-abs 1)) (set! (-> s4-0 button0-abs 1) (-> s4-0 button0-shadow-abs 0)) (set! (-> s4-0 button0-rel 2) (-> s4-0 button0-rel 1)) (set! (-> s4-0 button0-rel 1) (-> s4-0 button0-rel 0)) (when (= (-> s4-0 status) 115) (set! (-> s4-0 abutton 0) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons right)) 255 0 ) ) ) (set! (-> s4-0 abutton 1) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons left)) 255 0 ) ) ) (set! (-> s4-0 abutton 2) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons up)) 255 0 ) ) ) (set! (-> s4-0 abutton 3) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons down)) 255 0 ) ) ) (set! (-> s4-0 abutton 6) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons x)) 255 0 ) ) ) (set! (-> s4-0 abutton 5) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons circle)) 255 0 ) ) ) (set! (-> s4-0 abutton 4) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons triangle)) 255 0 ) ) ) (set! (-> s4-0 abutton 7) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons square)) 255 0 ) ) ) (set! (-> s4-0 abutton 8) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons l1)) 255 0 ) ) ) (set! (-> s4-0 abutton 10) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons l2)) 255 0 ) ) ) (set! (-> s4-0 abutton 9) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons r1)) 255 0 ) ) ) (set! (-> s4-0 abutton 11) (the-as uint (if (logtest? (-> s4-0 button0-abs 0) (pad-buttons r2)) 255 0 ) ) ) ) (let ((s3-1 (-> s4-0 button0))) (cond ((< (-> s4-0 lefty) (the-as uint 30)) (set! s3-1 (logior s3-1 #x10000)) ) ((< (the-as uint 225) (-> s4-0 lefty)) (set! s3-1 (logior s3-1 #x40000)) ) ) (cond ((< (-> s4-0 leftx) (the-as uint 30)) (set! s3-1 (logior s3-1 #x80000)) ) ((< (the-as uint 225) (-> s4-0 leftx)) (set! s3-1 (logior s3-1 #x20000)) ) ) (cond ((< (-> s4-0 righty) (the-as uint 30)) (set! s3-1 (logior s3-1 #x100000)) ) ((< (the-as uint 225) (-> s4-0 righty)) (set! s3-1 (logior s3-1 #x400000)) ) ) (cond ((< (-> s4-0 rightx) (the-as uint 30)) (set! s3-1 (logior s3-1 #x800000)) ) ((< (the-as uint 225) (-> s4-0 rightx)) (set! s3-1 (logior s3-1 #x200000)) ) ) (let ((v1-123 (get-current-language))) (cond ((or (= v1-123 (language-enum japanese)) (= v1-123 (language-enum korean))) (case (scf-get-territory) ((2 3) (if (logtest? s3-1 8192) (set! s3-1 (logior s3-1 #x1000000)) ) ) (else (if (logtest? s3-1 #x6000) (set! s3-1 (logior s3-1 #x1000000)) ) ) ) ) ((let ((v1-135 (scf-get-territory))) (or (= v1-135 2) (= v1-135 3)) ) (if (logtest? s3-1 #x6000) (set! s3-1 (logior s3-1 #x1000000)) ) ) (else (if (logtest? s3-1 #x4000) (set! s3-1 (logior s3-1 #x1000000)) ) ) ) ) (set! (-> s4-0 button0-shadow-abs 0) (the-as pad-buttons s3-1)) (set! (-> s4-0 button0-abs 0) (the-as pad-buttons s3-1)) ) (set! (-> s4-0 button0-rel 0) (logclear (-> s4-0 button0-abs 0) (-> s4-0 button0-abs 1))) (when *cpad-debug* (set! (-> s4-0 leftx) (the-as uint 255)) (set! (-> s4-0 rightx) (the-as uint 255)) ) (set! (-> s4-0 stick0-speed) 1.0) (cond ((= (shr (-> s4-0 status) 4) 7) (let ((f30-0 (* 0.0078125 (the float (+ (-> s4-0 leftx) -128)))) (f28-0 (* 0.0078125 (the float (- 127 (the-as int (-> s4-0 lefty)))))) ) (set! (-> s4-0 stick0-dir) (atan (- f30-0) f28-0)) (set! (-> s4-0 stick0-speed) (fmin 1.0 (sqrtf (+ (* f30-0 f30-0) (* f28-0 f28-0))))) ) (if (< (-> s4-0 stick0-speed) 0.3) (set! (-> s4-0 stick0-speed) 0.0) ) ) (else (set! (-> s4-0 leftx) (the-as uint 128)) (set! (-> s4-0 lefty) (the-as uint 128)) (set! (-> s4-0 rightx) (the-as uint 128)) (set! (-> s4-0 righty) (the-as uint 128)) (set! (-> s4-0 stick0-dir) 0.0) (set! (-> s4-0 stick0-speed) 0.0) ) ) (if (or (!= (-> s4-0 button0-abs 0) (-> s4-0 button0-abs 1)) (or (< 0.3 (-> s4-0 stick0-speed)) (zero? (-> s4-0 change-time))) ) (set! (-> s4-0 change-time) (get-current-time)) ) ) (else (cpad-invalid! s4-0) ) ) ) ) ) *cpad-list* ) (defun buzz-stop! ((arg0 int)) "Set the buzz to 0 on both vibration motors of the given cpad." (cpad-set-buzz! (-> *cpad-list* cpads arg0) 0 0 0) (cpad-set-buzz! (-> *cpad-list* cpads arg0) 1 0 0) 0 (none) ) (defmacro cpad-pressed (pad-idx) `(-> *cpad-list* cpads ,pad-idx button0-rel 0) ) (defmacro cpad-hold (pad-idx) `(-> *cpad-list* cpads ,pad-idx button0-abs 0) ) (defmacro cpad-pressed? (pad-idx &rest buttons) `(logtest? (cpad-pressed ,pad-idx) (pad-buttons ,@buttons)) ) (defmacro cpad-hold? (pad-idx &rest buttons) `(logtest? (cpad-hold ,pad-idx) (pad-buttons ,@buttons)) ) (defmacro cpad-clear! (pad-idx &rest buttons) `(begin (logclear! (cpad-pressed ,pad-idx) (pad-buttons ,@buttons)) (logclear! (cpad-hold ,pad-idx) (pad-buttons ,@buttons)) ) ) (defmacro cpad-change-time (pad-idx) `(-> *cpad-list* cpads ,pad-idx change-time) ) (deftype mouse-info (basic) ((active symbol :offset-assert 4) (cursor basic :offset-assert 8) (valid symbol :offset-assert 12) (id uint8 :offset-assert 16) (status uint16 :offset-assert 18) (button0 uint16 :offset-assert 20) (deltax int8 :offset-assert 22) (deltay int8 :offset-assert 23) (wheel uint8 :offset-assert 24) (change-time time-frame :offset-assert 32) (button0-abs uint32 3 :offset-assert 40) (button0-shadow-abs uint32 1 :offset-assert 52) (button0-rel uint32 3 :offset-assert 56) (pos vector 2 :inline :offset-assert 80) (posx float :offset 80) (posy float :offset 84) (oldposx float :offset 96) (oldposy float :offset 100) (speedx float :offset 92) (speedy float :offset 108) ) :method-count-assert 9 :size-assert #x70 :flag-assert #x900000070 (:methods (new (symbol type) _type_ 0) ) ) (defmethod new mouse-info ((allocation symbol) (type-to-make type)) "Allocate a new mouse." (let ((v0-0 (object-new allocation type-to-make (the-as int (-> type-to-make size))))) (set! (-> v0-0 active) #f) (set! (-> v0-0 valid) #f) (set! (-> v0-0 cursor) #f) v0-0 ) ) (define *mouse* (new 'global 'mouse-info)) (defun service-mouse () "Update the mouse, and draw the cursor." (let ((gp-0 *mouse*)) (mouse-get-data gp-0) (set! (-> gp-0 pos 1 quad) (-> gp-0 pos 0 quad)) (set! (-> gp-0 button0-abs 2) (-> gp-0 button0-abs 1)) (set! (-> gp-0 button0-abs 1) (-> gp-0 button0-shadow-abs 0)) (set! (-> gp-0 button0-rel 2) (-> gp-0 button0-rel 1)) (set! (-> gp-0 button0-rel 1) (-> gp-0 button0-rel 0)) (set! (-> gp-0 button0-rel 0) (the-as uint 0)) (set! (-> gp-0 speedx) 0.0) (set! (-> gp-0 speedy) 0.0) (cond ((or (not (-> gp-0 valid)) (not (-> gp-0 active))) (set! (-> gp-0 valid) #f) (set! (-> gp-0 status) (the-as uint 0)) (set! (-> gp-0 pos 0 quad) (the-as uint128 0)) (set! (-> gp-0 pos 1 quad) (the-as uint128 0)) ) ((logtest? (-> gp-0 status) 1) (set! (-> gp-0 change-time) (get-current-time)) (set! (-> gp-0 speedx) (* (sign (the float (-> gp-0 deltax))) (pow (fabs (the float (-> gp-0 deltax))) 1.3))) (set! (-> gp-0 speedy) (* (sign (the float (-> gp-0 deltay))) (pow (fabs (the float (-> gp-0 deltay))) 1.3))) (set! (-> gp-0 posx) (fmax -256.0 (fmin 256.0 (+ (-> gp-0 posx) (-> gp-0 speedx))))) (set! (-> gp-0 posy) (fmax -208.0 (fmin 208.0 (+ (-> gp-0 posy) (-> gp-0 speedy))))) (let ((v1-22 (-> gp-0 button0))) (set! (-> gp-0 button0-shadow-abs 0) v1-22) (set! (-> gp-0 button0-abs 0) v1-22) ) (set! (-> gp-0 button0-rel 0) (logclear (-> gp-0 button0-abs 0) (-> gp-0 button0-abs 1))) ) ) (if (and (-> gp-0 active) (-> gp-0 valid) (-> gp-0 cursor)) (add-debug-cursor #t (bucket-id debug-no-zbuf) (+ (the int (-> gp-0 posx)) 256) (+ (the int (-> gp-0 posy)) 208) (the-as int (-> gp-0 button0-abs 0)) ) ) ) (none) )