shithub: pokecrystal

Download patch

ref: da406973c565c24c089d137d056e03be8451242e
parent: 9102b9a498c1f3073b89367945330b7de6baf016
author: yenatch <[email protected]>
date: Tue Feb 19 18:57:07 EST 2013

Split out joypad

--- a/constants.asm
+++ b/constants.asm
@@ -3417,15 +3417,20 @@
 
 
 ; 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
--- /dev/null
+++ b/joypad.asm
@@ -1,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
+
--- a/main.asm
+++ b/main.asm
@@ -47,7 +47,7 @@
 	jp $06ef
 
 SECTION "joypad",HOME[$60] ; joypad interrupt
-	jp $092e
+	jp JoypadInt
 
 SECTION "romheader",HOME[$100]
 Start:
@@ -425,252 +425,11 @@
 	ret
 ; 6c4
 
-INCBIN "baserom.gbc",$6c4,$935 - $6c4
+INCBIN "baserom.gbc",$6c4,$92e - $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
+INCLUDE "joypad.asm"
 
-
-GetJoypadPublic: ; 984
-; update mirror joypad input from $ffa4 (real input)
-
-; $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