From 428c301a80641361f51af8102628b545cf9ae63e Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Tue, 11 Mar 2025 17:00:47 +0100 Subject: shared: Bring joypad into a proper style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Put functions inside of the scope, avoid useless fallthroughs and be more realistic on what is needed from elsewhere. Signed-off-by: Miquel Sabaté Solà --- shared/joypad.s | 110 +++++++++++++++++++++++++------------------------------- 1 file changed, 49 insertions(+), 61 deletions(-) (limited to 'shared/joypad.s') diff --git a/shared/joypad.s b/shared/joypad.s index 7bfc575..05797fe 100644 --- a/shared/joypad.s +++ b/shared/joypad.s @@ -15,70 +15,58 @@ ;; After running a `joypad_read_*` function these two variables will contain ;; the given result. - m_buttons1 = $22 - m_buttons2 = $23 -.endscope - -;;; -;; Read the first joypad. This method is fast but it might be vulnerable to the -;; DPCM bug (see: https://www.nesdev.org/wiki/Controller_reading_code). -joypad_unsafe_read: - ldx #$00 - ;; NOTE: fallthrough - -;;; -;; Read the joypad as indexed by the X register (0 for controller 1; 1 for -;; controller 2). This method is fast but it might be vulnerable to the DPCM bug -;; (see: https://www.nesdev.org/wiki/Controller_reading_code). -joypad_unsafe_read_x: - ;; Start the latch process. - lda #$01 - sta Joypad::JOYPAD1 - sta Joypad::m_buttons1, x ; Bit as a guard for the loop below. - lsr - sta Joypad::JOYPAD1 + zp_buttons1 = $22 + zp_buttons2 = $23 - ;; Now the joypad is ready to accept reads. -@joypad_unsafe_read_x_loop: - lda Joypad::JOYPAD1, x - and #%00000011 ; Ignore bits other than controller. - cmp #$01 ; Set carry if and only if nonzero. - rol Joypad::m_buttons1, x ; Carry -> bit 0; bit 7 -> Carry - bcc @joypad_unsafe_read_x_loop - rts + ;;; + ;; Safely read via a re-read algorithm the joypad as indexed by the X register + ;; (0 for controller 1; 1 for controller 2). + .proc read_x + jsr Joypad::unsafe_read_x -;;; -;; Safely read the first controller via a re-read algorithm. -joypad_read: - ldx #$00 - - ;; NOTE: uncomment these two lines to also read safely the second - ;; controller. - ;; - ;; jsr joypad_read_x - ;; inx + ;; The main idea around a re-read algorithm is that you read the + ;; controller "unsafely" once, then you do it again and compare both + ;; reads. If they were the same then we are on the safe side. Otherwise + ;; we would need to loop until we get two identical reads. This sounds + ;; bad but in practice it's not so much (and hey, if it worked for Super + ;; Mario Bros. 3, it should work for us too :P). Otherwise there is the + ;; algorithm via OAM DMA, but it sure is tricky. + @reread: + lda Joypad::zp_buttons1, x + tay + jsr Joypad::unsafe_read_x + tya + cmp Joypad::zp_buttons1, x + bne @reread - ;; NOTE: fallthrough + rts + .endproc -;;; -;; Safely read via a re-read algorithm the joypad as indexed by the X register -;; (0 for controller 1; 1 for controller 2). -joypad_read_x: - jsr joypad_unsafe_read_x + ;;; + ;; Read the joypad as indexed by the X register (0 for controller 1; 1 for + ;; controller 2). This method is fast but it might be vulnerable to the DPCM + ;; bug (see: https://www.nesdev.org/wiki/Controller_reading_code). + .proc unsafe_read_x + ;; Start the latch process. + lda #$01 + sta Joypad::JOYPAD1 + sta Joypad::zp_buttons1, x ; Bit as a guard for the loop below. + lsr + sta Joypad::JOYPAD1 - ;; The main idea around a re-read algorithm is that you read the controller - ;; "unsafely" once, then you do it again and compare both reads. If they - ;; were the same then we are on the safe side. Otherwise we would need to - ;; loop until we get two identical reads. This sounds bad but in practice - ;; it's not so much (and hey, if it worked for Super Mario Bros. 3, it - ;; should work for us too :P). Otherwise there is the algorithm via OAM DMA, - ;; but it sure is tricky. -@joypad_read_x_reread: - lda Joypad::m_buttons1, x - tay - jsr joypad_unsafe_read_x - tya - cmp Joypad::m_buttons1, x - bne @joypad_read_x_reread + ;; Now the joypad is ready to accept reads. + @loop: + lda Joypad::JOYPAD1, x + and #%00000011 ; Ignore bits other than controller. + cmp #$01 ; Set carry if and only if nonzero. + rol Joypad::zp_buttons1, x ; Carry -> bit 0; bit 7 -> Carry + bcc @loop + rts + .endproc +.endscope - rts +;; Shortcut for reading the joypad from the first player safely. +.macro READ_JOYPAD1 + ldx #$00 + jsr Joypad::read_x +.endmacro -- cgit v1.2.3