-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjoypad_subroutines.asm
94 lines (75 loc) · 2.39 KB
/
joypad_subroutines.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
;;;;;;;;;;;;;; CONSTANTS FOR THE BUTTONS ;;;;;;;;;;;;;;;;;
BUTTON_A = %10000000
BUTTON_B = %01000000
BUTTON_SELECT = %00100000
BUTTON_START = %00010000
BUTTON_UP = %00001000
BUTTON_DOWN = %00000100
BUTTON_LEFT = %00000010
BUTTON_RIGHT = %00000001
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; OAM DMA might cause glitches in clock signal while reading joaypads sometimes
;; causing incorrect reading. To avoid this, read twice and compar results. If they differ, start over.
;; more info: https://wiki.nesdev.com/w/index.php/Controller_reading_code#DPCM_Safety_using_OAM_DMA
;;
;; We also use this subroutine to determine which buttons were "freshly" pressed
safe_read_joypads:
;; Save the previous controller states
;; We need to do it here, because if we do it in the read_joypads subroutine
;; it would overwrite the old again on the second read (usually with same value)
;; thus making it impossible to determine the newly pressed buttons
lda joypad1_current
sta joypad1_old
lda joypad2_current
sta joypad2_old
jsr read_joypads
.reread:
;; push the last read values to stack
lda joypad1_current
pha
lda joypad2_current
pha
;; read again
jsr read_joypads
;; first check joy 2 becuase that was pushed last
pla
cmp joypad2_current
bne .reread
;; then check the first one
pla
cmp joypad1_current
bne .reread
;; now determine which buttons were pressed now
lda joypad1_old ;; flip bits with EOR to find which buttons were not pressed last time
eor #$FF
and joypad1_current ;; and with an AND find out which of those is pressed now
sta joypad1_pressed
lda joypad2_old
eor #$FF
and joypad2_current
sta joypad2_pressed
rts
;; This subroutine reads the joypads
;; Don't call it directly, use safe_read_joypads instead
read_joypads:
;; in this method using a ring counter
;; it means that we load 01 to the target memory address
;; with each ROL this 1 moves bit to the right
;; after the 8th ROL carry bit will be 1, indicating that we are done
;; since we need to read 8 times
;; latch the controllers
ldx #$01
stx $4016
stx joypad2_current
dex
stx $4016
;; read 8 times
.loop:
lda $4016
lsr a ; bit0 -> Carry
rol joypad1_current ; bit0 <- Carry
lda $4017
lsr a
rol joypad2_current
bcc .loop
rts