Build the complete caller with make -C atari-5200/patterns/assembly/input/read-action. Press fire once, keep it held, then release and press again. The piece moves on each new press and returns to its starting position after two; holding does not repeat the action. Load the cartridge produced by the Makefile in the named configuration; retain its reset/header setup.

Take the reader
sample.inc is an inline hardware sampler: include it where the caller samples input. It has no RET/RTS and must not be called as a subroutine. It supplies the held state described below; the caller supplies previous-state storage and decides what a new press does.
The reusable reader
lda $c010
and #1 ; GTIA TRIG0 reports bit 0, unlike the TIA
eor #1
sta currentGTIA TRIG0 at $C010 uses active-low bit 0. The inline sampler stores 0/1 in current=$1004, leaving the edge decision to its caller; A/flags change.
Calculate a new-press mask as current AND NOT previous, then store current as previous on every update, including release. Test held state for continuous movement and the new-press mask for an action that should happen once. A key already held at the caller’s first sample counts as a press because previous starts at zero.
Caller storage: previous=$1001, current=$1004; turn=$1000, field clock=$1002/$1003. The sample’s display initialiser and any interrupts have their own ownership requirements; keep them with this complete example.
Change it and recognise a mistake
This reads the fire trigger only. The 5200’s analogue axes require their own sampling/calibration policy.
The broken caller feeds held state into the action decision. Keeping the button down advances repeatedly; the native fault run reaches 32 instead of remaining at one. Restore the previous-state comparison and update previous on release as well.
Deliberately broken input/update path
; Capability caller: original input/frame service, explicit drawing and sound.
; atari-5200: untimed turns from a new fire press, with independent field work.
; Owns display/input and $1000-$1004; stack is page 1. IRQ disabled.
turns = $1000
previous = $1001
clock_ticks = $1002
current = $1004
* = $4000
start:
sei
cld
ldx #$ff
txs
lda #0
sta $d40e ; disable ANTIC NMI ownership from BIOS
sta $d400 ; display-list DMA off: background-only output
lda #0
sta turns
sta previous
sta clock_ticks
sta clock_ticks+1
jsr init_picture
main:
jsr wait_frame
inc clock_ticks
bne sample
inc clock_ticks+1
sample:
!source "../sample.inc"
lda current
nop
nop
nop
nop
beq no_action
inc turns
jsr trigger_sound
no_action:
lda current
sta previous
jsr draw_picture
jsr service_sound
jmp main
wait_frame:
lda $d40b ; VCOUNT bit 7 covers the tail of the NTSC field
bmi wait_frame
wait_new:
lda $d40b
bpl wait_new
rts
!source "../picture.inc"
!source "../sound.inc"
!fill $bffe-*, $ff
!word start ; genuine BIOS cartridge handover address
The complete caller
Working setup and integration
; Capability caller: original input/frame service, explicit drawing and sound.
; atari-5200: untimed turns from a new fire press, with independent field work.
; Owns display/input and $1000-$1004; stack is page 1. IRQ disabled.
turns = $1000
previous = $1001
clock_ticks = $1002
current = $1004
* = $4000
start:
sei
cld
ldx #$ff
txs
lda #0
sta $d40e ; disable ANTIC NMI ownership from BIOS
sta $d400 ; display-list DMA off: background-only output
lda #0
sta turns
sta previous
sta clock_ticks
sta clock_ticks+1
jsr init_picture
main:
jsr wait_frame
inc clock_ticks
bne sample
inc clock_ticks+1
sample:
!source "sample.inc"
lda previous
eor #$ff
and current
beq no_action
inc turns
jsr trigger_sound
no_action:
lda current
sta previous
jsr draw_picture
jsr service_sound
jmp main
wait_frame:
lda $d40b ; VCOUNT bit 7 covers the tail of the NTSC field
bmi wait_frame
wait_new:
lda $d40b
bpl wait_new
rts
!source "picture.inc"
!source "sound.inc"
!fill $bffe-*, $ff
!word start ; genuine BIOS cartridge handover addressFor more responsive controls, compare polling, buffering and press edges in input choices.
Verification and sources
Target: NTSC 32 KiB cartridge, recorded BIOS handover. These callers were executed with released Emu198x 0.44.1; assembly uses Asm198x 0.0.71. The sample folder contains reproduction instructions and retained observations. The independent checker binds source, native captures and actual output; its rejection tests exercise wrong state, missing files and false audio claims.
This qualifies the named emulator/firmware path. Pitch accuracy, original hardware and other peripherals require their own observations.
Atari, 5200/GTIA hardware documentation: trigger inputs; POKEY data sheet: AUDF/AUDC/AUDCTL/SKCTL; ANTIC VCOUNT.