Code status: the maintained reader is reused by executed Amiga callers; the edge adapter has a 1,024-case CPU/state check. The edge check consumes synthetic held/previous samples; hardware decoding uses the reader’s separate evidence. The surrounding movement examples are adapters; they need their own state, bounds and frame wait. The named callers establish physical port 2 under their A500 configuration, not every peripheral.
Audit execution record · Scope and remaining checks
Overview
Basic joystick reading returns the current state - fine for continuous movement, but problematic for grid-based games where holding a direction shouldn’t cause repeated steps. Edge detection returns only newly pressed directions by comparing current state to the previous frame.
Calling contract
Set A5 to $DFF000, configure CIA-A bit 7 as an input and own physical joystick port 2. Include framework/input-to-sound/input.inc once in writable memory. read_controls returns the held controls in D0.W and controls: up $0100, down $0001, left $0200, right $0002, Fire $0010. It changes D0/D1 and condition codes; other registers survive. Only the low word of D0 is defined.
Keep the horizontal bits from the original JOYDAT sample. The XOR with its shifted copy decodes the vertical bits; applying it to the whole result can turn leftover counter bits into false horizontal input. Physical port 1 uses JOY0DAT and CIA-A bit 6 for Fire; physical port 2 uses JOY1DAT and bit 7.
Code
; Include the maintained input-to-sound/input.inc once as well.
; A5=CUSTOM, CIA-A bit7 configured as input; caller owns physical joystick port2.
; read_joystick_edge samples once and returns new presses in D0.W.
; If already sampled this update, call detect_joystick_edges instead.
; Changes D0/D1/CCR. Other registers survive. State is writable WORDs.
; Zero initial history treats a held control as a first press. To suppress that,
; sample once and copy controls into joy_prev before entering the update loop.
read_joystick_edge:
bsr read_controls
detect_joystick_edges:
move.w joy_prev,d1
not.w d1
and.w controls,d1
move.w controls,joy_prev
move.w d1,d0
rts
joy_prev: dc.w 0Usage example (grid-based movement):
update_player:
bsr read_joystick_edge
tst.w d0
beq .done ; No new input
; Check each direction
btst #8,d0 ; Up?
beq.s .not_up
subq.w #1,player_grid_y ; Move one cell up
bra.s .done
.not_up:
btst #0,d0 ; Down?
beq.s .not_down
addq.w #1,player_grid_y ; Move one cell down
bra.s .done
.not_down:
btst #9,d0 ; Left?
beq.s .not_left
subq.w #1,player_grid_x
bra.s .done
.not_left:
btst #1,d0 ; Right?
beq.s .done
addq.w #1,player_grid_x
.done:
rtsTrade-offs
| Aspect | Cost |
|---|---|
| CPU | Measure the reader and edge adapter together in your caller |
| Memory | Assembled reader/adapter plus a 2-byte history word |
| Limitation | Requires per-frame update to work correctly |
When to use: Grid-based movement, menu navigation, any single-step input.
When to avoid: Continuous movement (shooters, racing) - use basic joystick reading instead.
How It Works
- Read current joystick state (decoded)
- Invert previous state:
NOT previous - AND with current:
current AND (NOT previous) - Result: bits set only where current=1 AND previous=0
This gives you a pulse on the first frame of a press, then nothing until released and pressed again.
Comparison
| Scenario | Basic Read | Edge Detection |
|---|---|---|
| Press right | Returns “right” | Returns “right” |
| Hold right | Returns “right” | Returns nothing |
| Release | Returns nothing | Returns nothing |
| Press again | Returns “right” | Returns “right” |
Related
Patterns: Joystick Reading, VBlank Game Loop
Vault: Commodore Amiga
History belongs to the caller
Include edges.inc alongside the input reader. read_joystick_edge samples once and returns new presses in D0.W, changing D0/D1 and condition codes. If the frame already sampled input, call detect_joystick_edges instead. The shared controls word supplies that sample.
With joy_prev initially zero, a held control counts as a first press. To suppress that, sample once during initialisation and copy controls to joy_prev. Keep the history while a button remains held; clearing it on a screen transition invents another press. This routine does not clamp the example’s grid coordinates or generate timed repeats.