Split out joypad

This commit is contained in:
yenatch 2013-02-19 23:57:07 -05:00
parent 9102b9a498
commit da406973c5
3 changed files with 292 additions and 253 deletions

View File

@ -3417,15 +3417,20 @@ BATTLETYPE_SUICUNE EQU $0c
; joypad
NO_INPUT EQU %00000000
BUTTON_A EQU %00000001
BUTTON_B EQU %00000010
SELECT EQU %00000100
START EQU %00001000
D_RIGHT EQU %00010000
D_LEFT EQU %00100000
D_UP EQU %01000000
D_DOWN EQU %10000000
BUTTONS EQU %00010000
D_PAD EQU %00100000
AUTO_INPUT EQU $ff
NO_INPUT EQU %00000000
BUTTON_A EQU %00000001
BUTTON_B EQU %00000010
SELECT EQU %00000100
START EQU %00001000
D_RIGHT EQU %00010000
D_LEFT EQU %00100000
D_UP EQU %01000000
D_DOWN EQU %10000000
; mbc
NUM_SRAM_BANKS EQU 4

275
joypad.asm Normal file
View File

@ -0,0 +1,275 @@
JoypadInt: ; 92e
; Replaced by Joypad, called from VBlank instead of the useless
; joypad interrupt.
; This is a placeholder in case the interrupt is somehow enabled.
reti
; 92f
ClearJoypadPublic: ; 92f
xor a
; Pressed this frame (delta)
ld [$ffa7], a
; Currently pressed
ld [$ffa8], a
ret
; 935
Joypad: ; 935
; Read the joypad register and translate it to something more
; workable for use in-game. There are 8 buttons, so we can use
; one byte to contain all player input.
; Updates:
; $ffa2: released this frame (delta)
; $ffa3: pressed this frame (delta)
; $ffa4: currently pressed
; $ffa5: pressed so far
; Any of these three bits can be used to disable input.
ld a, [$cfbe]
and %11010000
ret nz
; If we're saving, input is disabled.
ld a, [$c2cd]
and a
ret nz
; We can only get four inputs at a time.
; We take d-pad first for no particular reason.
ld a, D_PAD
ld [$ff00], a
; Read twice to give the request time to take.
ld a, [$ff00]
ld a, [$ff00]
; The Joypad register output is in the lo nybble (inversed).
; We make the hi nybble of our new container d-pad input.
cpl
and $f
swap a
; We'll keep this in b for now.
ld b, a
; Buttons make 8 total inputs (A, B, Select, Start).
; We can fit this into one byte.
ld a, BUTTONS
ld [$ff00], a
; Wait for input to stabilize.
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
; Buttons take the lo nybble.
cpl
and $f
or b
ld b, a
; Reset the joypad register since we're done with it.
ld a, $30
ld [$ff00], a
; To get the delta we xor the last frame's input with the new one.
ld a, [$ffa4] ; last frame
ld e, a
xor b
ld d, a
; Released this frame:
and e
ld [$ffa2], a
; Pressed this frame:
ld a, d
and b
ld [$ffa3], a
; Add any new presses to the list of collective presses:
ld c, a
ld a, [$ffa5]
or c
ld [$ffa5], a
; Currently pressed:
ld a, b
ld [$ffa4], a
; Now that we have the input, we can do stuff with it.
; For example, soft reset:
and BUTTON_A | BUTTON_B | SELECT | START
cp BUTTON_A | BUTTON_B | SELECT | START
jp z, $0150 ; reset
ret
; 984
GetJoypadPublic: ; 984
; Update mirror joypad input from $ffa4 (real input)
; $ffa6: released this frame (delta)
; $ffa7: pressed this frame (delta)
; $ffa8: currently pressed
; bit 0 A
; 1 B
; 2 SELECT
; 3 START
; 4 RIGHT
; 5 LEFT
; 6 UP
; 7 DOWN
push af
push hl
push de
push bc
; The player input can be automated using an input stream.
; See more below.
ld a, [InputType]
cp a, AUTO_INPUT
jr z, .auto
; To get deltas, take this and last frame's input.
ld a, [$ffa4] ; real input
ld b, a
ld a, [$ffa8] ; last frame mirror
ld e, a
; Released this frame:
xor b
ld d, a
and e
ld [$ffa6], a
; Pressed this frame:
ld a, d
and b
ld [$ffa7], a
; It looks like the collective presses got commented out here.
ld c, a
; Currently pressed:
ld a, b
ld [$ffa8], a ; frame input
.quit
pop bc
pop de
pop hl
pop af
ret
.auto
; Use a predetermined input stream (used in the catching tutorial).
; Stream format: [input][duration]
; A value of $ff will immediately end the stream.
; Read from the input stream.
ld a, [$ff9d]
push af
ld a, [AutoInputBank]
rst Bankswitch
ld hl, AutoInputAddress
ld a, [hli]
ld h, [hl]
ld l, a
; We only update when the input duration has expired.
ld a, [AutoInputLength]
and a
jr z, .updateauto
; Until then, don't change anything.
dec a
ld [AutoInputLength], a
pop af
rst Bankswitch
jr .quit
.updateauto
; An input of $ff will end the stream.
ld a, [hli]
cp a, $ff
jr z, .stopauto
ld b, a
; A duration of $ff will end the stream indefinitely.
ld a, [hli]
ld [AutoInputLength], a
cp a, $ff
jr nz, .next
; The current input is overwritten.
dec hl
dec hl
ld b, NO_INPUT
jr .finishauto
.next
; On to the next input...
ld a, l
ld [AutoInputAddress], a
ld a, h
ld [AutoInputAddress+1], a
jr .finishauto
.stopauto
call StopAutoInput
ld b, NO_INPUT
.finishauto
pop af
rst Bankswitch
ld a, b
ld [$ffa7], a ; pressed
ld [$ffa8], a ; input
jr .quit
; 9ee
StartAutoInput: ; 9ee
; Start reading automated input stream at a:hl.
ld [AutoInputBank], a
ld a, l
ld [AutoInputAddress], a
ld a, h
ld [AutoInputAddress+1], a
; Start reading the stream immediately.
xor a
ld [AutoInputLength], a
; Reset input mirrors.
xor a
ld [$ffa7], a ; pressed this frame
ld [$ffa6], a ; released this frame
ld [$ffa8], a ; currently pressed
ld a, AUTO_INPUT
ld [InputType], a
ret
; a0a
StopAutoInput: ; a0a
; Clear variables related to automated input.
xor a
ld [AutoInputBank], a
ld [AutoInputAddress], a
ld [AutoInputAddress+1], a
ld [AutoInputLength], a
; Back to normal input.
ld [InputType], a
ret
; a1b

247
main.asm
View File

@ -47,7 +47,7 @@ SECTION "serial",HOME[$58] ; serial interrupt
jp $06ef
SECTION "joypad",HOME[$60] ; joypad interrupt
jp $092e
jp JoypadInt
SECTION "romheader",HOME[$100]
Start:
@ -425,252 +425,11 @@ SetClock: ; 691
ret
; 6c4
INCBIN "baserom.gbc",$6c4,$935 - $6c4
Joypad: ; 935
; update joypad state
; $ffa2: released
; $ffa3: pressed
; $ffa4: input
; $ffa5: total pressed
;
ld a, [$cfbe]
and $d0
ret nz
; pause game update?
ld a, [$c2cd]
and a
ret nz
; d-pad
ld a, $20
ld [$ff00], a
ld a, [$ff00]
ld a, [$ff00]
; hi nybble
cpl
and $f
swap a
ld b, a
; buttons
ld a, $10
ld [$ff00], a
; wait to stabilize
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
ld a, [$ff00]
; lo nybble
cpl
and $f
or b
ld b, a
; reset joypad
ld a, $30
ld [$ff00], a
; get change in input
ld a, [$ffa4] ; last frame's input
ld e, a
xor b ; current frame input
ld d, a
; released
and e
ld [$ffa2], a
; pressed
ld a, d
and b
ld [$ffa3], a
; total pressed
ld c, a
ld a, [$ffa5]
or c
ld [$ffa5], a
; original input
ld a, b
ld [$ffa4], a
; A+B+SELECT+START
and $f
cp $f
jp z, $0150 ; reset
ret
; 984
INCBIN "baserom.gbc",$6c4,$92e - $6c4
GetJoypadPublic: ; 984
; update mirror joypad input from $ffa4 (real input)
INCLUDE "joypad.asm"
; $ffa6: released
; $ffa7: pressed
; $ffa8: input
; bit 0 A
; 1 B
; 2 SELECT
; 3 START
; 4 RIGHT
; 5 LEFT
; 6 UP
; 7 DOWN
push af
push hl
push de
push bc
; automated input?
ld a, [InputType]
cp a, $ff ; INPUT_AUTO
jr z, .auto
; get input
ld a, [$ffa4] ; real input
ld b, a
ld a, [$ffa8] ; last frame mirror
ld e, a
; released
xor b
ld d, a
and e
ld [$ffa6], a
; pressed
ld a, d
and b
ld [$ffa7], a
; leftover from pasted code
ld c, a
;
ld a, b
ld [$ffa8], a ; frame input
.quit
pop bc
pop de
pop hl
pop af
ret
.auto
; use predetermined input feed (used in catch tutorial)
; struct: [input][duration]
; save bank
ld a, [$ff9d]
push af
;
ld a, [AutoInputBank]
rst Bankswitch
;
ld hl, AutoInputAddress ; AutoInputAddress-9
ld a, [hli]
ld h, [hl]
ld l, a
; update when frame count hits 0
ld a, [AutoInputLength]
and a
jr z, .updateauto
; until then, do nothing
dec a
ld [AutoInputLength], a
; restore bank
pop af
rst Bankswitch
; we're done
jr .quit
.updateauto
; get input
ld a, [hli]
; stop?
cp a, $ff
jr z, .stopinput
ld b, a
; duration
ld a, [hli]
ld [AutoInputLength], a
; duration $ff = end at input
cp a, $ff
jr nz, .next
; no input
dec hl
dec hl
ld b, $00 ; no input
jr .finishauto
.next
; output recorded
ld a, l
ld [AutoInputAddress], a
ld a, h
ld [AutoInputAddress+1], a
jr .finishauto
.stopinput
call StopAutoInput
ld b, $00 ; no input
.finishauto
; restore bank
pop af
rst Bankswitch
; update mirrors
ld a, b
ld [$ffa7], a ; pressed
ld [$ffa8], a ; input
jr .quit
; 9ee
StartAutoInput: ; 9ee
; start auto input stream at a:hl
; bank
ld [AutoInputBank], a
; address
ld a, l
ld [AutoInputAddress], a
ld a, h
ld [AutoInputAddress+1], a
; don't wait to update
xor a
ld [AutoInputLength], a
; clear input mirrors
xor a
ld [$ffa7], a ; pressed
ld [$ffa6], a ; released
ld [$ffa8], a ; input
; start reading input stream instead of player input
ld a, $ff ; INPUT_AUTO
ld [InputType], a
ret
; a0a
StopAutoInput: ; a0a
; clear autoinput ram
xor a
ld [AutoInputBank], a
ld [AutoInputAddress], a
ld [AutoInputAddress+1], a
ld [AutoInputLength], a
; normal input
ld [InputType], a
ret
; a1b
INCBIN "baserom.gbc",$a1b,$b40 - $a1b