aboutsummaryrefslogtreecommitdiff
path: root/examples/input.s
diff options
context:
space:
mode:
Diffstat (limited to 'examples/input.s')
-rw-r--r--examples/input.s170
1 files changed, 0 insertions, 170 deletions
diff --git a/examples/input.s b/examples/input.s
deleted file mode 100644
index 25b17b0..0000000
--- a/examples/input.s
+++ /dev/null
@@ -1,170 +0,0 @@
-;;
-;; This example shows how to read from one controller and set it into the $20
-;; memory address. The `Main` subroutine will call the `ReadController`
-;; subroutine and then increment the value on $42 if the right arrow was
-;; pressed. When running this ROM, watch for the following RAM addresses:
-;;
-;; - $20: the bitmap of the current status of the controller (notice that since
-;; we are constantly polling it and filling it, the value will move constantly).
-;; - $21: the previous status of the right arrow.
-;; - $42: the counter which is incremented on each press of the right arrow button.
-;;;
-
-;;;
-;; You can safely ignore all of this up until the `ReadController` subroutine.
-;; This is boilerplate that is explained on the `sprite.s` example.
-;;;
-
-.segment "HEADER"
- .byte 'N', 'E', 'S', $1A
- .byte $02
- .byte $01
- .byte $00
- .byte $00
-
-.segment "VECTORS"
- .addr nmi
- .addr reset
- .addr irq
-
-.segment "STARTUP"
-
-.segment "CODE"
-
-nmi:
-irq:
- rti
-
-reset:
- sei
- cld
- ldx #$40
- stx $4017
-
- ldx #$ff
- txs
-
- inx
- stx $2000
- stx $2001
- stx $4010
-
-@vblankwait1:
- bit $2002
- bpl @vblankwait1
-
- ldx #0
- lda #0
-@ram_reset_loop:
- sta $000, x
- sta $100, x
- sta $200, x
- sta $300, x
- sta $400, x
- sta $500, x
- sta $600, x
- sta $700, x
- inx
- bne @ram_reset_loop
-
-@vblankwait2:
- bit $2002
- bpl @vblankwait2
-
- jmp main
-
-.proc ReadController
- ;; The status of the eight buttons fits into a single byte. We start the whole
- ;; dance by setting the first bit of the position we are storing this info
- ;; ($20). This bit will act as a guard in the following code.
- lda #1
- sta $20
-
- ;; The 4021 chip is the one responsible to bring the input from the controller
- ;; into the NES. The console reserves two addresses on the memory for the
- ;; controllers: $4016 and $4017 (see
- ;; https://www.nesdev.org/wiki/Input_devices). If you write into one of them
- ;; first with a #1 and then with a #0, we activate the latch for the
- ;; controller, and it will start to send a bit representing the state for each
- ;; button upon each read.
- ;;
- ;; Thus, since we conveniently now have #1 into the 'a' register, we send this
- ;; value to the 4021 chip, and we follow it by sending #0. This way we tell
- ;; the controller to start to deliver the data.
- sta $4016
- lda #0
- sta $4016
-
- ;; The status of the buttons will be provided one by one following a specific
- ;; order. The algorithm goes as follows:
- ;;
- ;; 1. Load the bit you get from the 4021 chip into `a`. After performing
- ;; this read the controller will send the next one so it's ready for the
- ;; next iteration.
- ;; 2. Shift the value right so to set the carry flag as its comes (note:
- ;; overflowing from the right also sets the carry flag on!).
- ;; 3. Rotate one bit left from $20: C <- [$20] <- C. This way, we always get
- ;; the result we put on the carry register at the right-most part of the
- ;; byte on $20, and we clear the carry flag (the previous left-most bit
- ;; moves into the carry register, which is 0 until we reach the one we
- ;; planted as a guard).
- ;; 4. We jump back into `read_loop` if the carry flag is clear. This is the
- ;; case for most of the time until the #1 that we set at the very
- ;; beginning as a guard flows into the carry flag as expected from the
- ;; `rol` instruction. At this point, we have already read the full byte.
-read_loop:
- lda $4016
- lsr a
- rol $20
- bcc read_loop
-
- rts
-.endproc
-
-;; The main function will run indefinitely and it will continuously poll from
-;; the controller and increment the value on $42 each time the user performs a
-;; new press on the right arrow (that is, we want to count new presses on this
-;; button, and we don't want to increment this value while the right arrow is
-;; being pressed).
-.proc main
- ;; Initialize the value on $21 (previous state) and on $42 (counter).
- lda #0
- sta $42
- sta $21
-
-loop:
- jsr ReadController
-
- ;; Was the right arrow being pressed? If that's the case, then jump into the
- ;; `pressed` label to compare it with the previous state.
- lda #1
- and $20
- bne pressed
-
- ;; The right arrow was not being pressed. Thus, we need to update the previous
- ;; state to #0 before we read the controller again.
- lda #0
- sta $21
- jmp loop
-
-pressed:
- ;; Now the right arrow is being pressed, and we have the guarantee that `a =
- ;; 1` (because of the `and $20` instruction returning a non-zero result). Now
- ;; do the same with the previous state. If it's a non-zero result, then it
- ;; means that the previous state was already of pressed. Hence, at this point
- ;; we can return into the main loop. If this was not the case, then it's a new
- ;; press.
- and $21
- bne loop
-
- ;; It's a new press, set $21 to #1 accordinly and increment the counter on $42.
- inc $21
- inc $42
-
- ;; There and back again.
- jmp loop
-
- rts
-.endproc
-
-.segment "CHARS"