Skip to content

Trigger a sound on Mattel Aquarius

Reuse a small real effect, understand who stops it, and compare its native output with an omitted-trigger control.

Give an accepted action a sound. The same caller changes its picture and triggers this effect; a second version performs the action with the trigger removed. Listen to both.

Working effect

Trigger omitted

Take the effect

The reusable effect

sound.bas
2000 X=USR(0)
2010 RETURN
3000 DATA 245,197,14,80,175,211,252,238
3008 DATA 1,6,100,16,254,13,32,245
3016 DATA 175,211,252,193,241,201

The caller creates all its scalar variables before DIM Z(16), locates that array storage and installs a 22-byte Z80 helper plus USR vector. GOSUB 2000 calls it. It toggles output port $FC with a CPU delay and returns, preserving AF/BC. The routine blocks and uses W/J/B/X plus the Z array and USR vector.

Copy the 2000-range subroutine and call GOSUB 2000 when the game accepts an action. Keep its global scratch variables and any DATA/setup lines with it. A sound call is a consequence of an action, not a substitute for input validation.

Change it and recognise a mistake

Keep the array/vector setup with the sound routine. Adding variables or changing array layout can move its storage; do not reuse a stale pointer. A ROM-independent allocator/driver would need a different storage contract.

The omitted-trigger control still accepts the action but fails the same audio guard as the working caller. Keyboard clicks or other machine output are not enough: the BASIC checks compare against a separate rejected-command recording.

Deliberately omitted sound trigger

no-sound.bas
1 N=0:W=0:J=0:B=0:X=0:A$=""
2 DIM Z(16)
3 W=PEEK(14552)+256*PEEK(14553)+7
4 FOR J=0 TO 21:READ B:POKE W+J,B:NEXT J
5 POKE 14340,W AND 255:POKE 14341,INT(W/256)
10 N=0
20 PRINT "TURN";N
21 GOSUB 1000
30 GOSUB 4000
40 IF A$="GO" THEN N=N+1
50 GOTO 20
1000 PRINT "XXX"
1010 PRINT "X X"
1020 PRINT "XXX"
1030 RETURN
2000 X=USR(0)
2010 RETURN
3000 DATA 245,197,14,80,175,211,252,238
3008 DATA 1,6,100,16,254,13,32,245
3016 DATA 175,211,252,193,241,201
4000 INPUT A$
4010 RETURN

The working implementation above repairs that omission. If an effect instead drones on, check the mute/service path and that its state is initialised. Servicing twice makes a counted effect shorter; servicing only after input can leave it running while the player waits. Those are lifecycle decisions to test when adapting it.

Run the caller

Enter the complete demo.bas in Mattel Aquarius BASIC and RUN. Submit GO, then Return. One accepted command advances the displayed turn; another gives two.

Mattel Aquarius native caller after accepted input.
Captured from the running caller in the configuration below.

Where setup, trigger and service belong

demo.bas
1 N=0:W=0:J=0:B=0:X=0:A$=""
2 DIM Z(16)
3 W=PEEK(14552)+256*PEEK(14553)+7
4 FOR J=0 TO 21:READ B:POKE W+J,B:NEXT J
5 POKE 14340,W AND 255:POKE 14341,INT(W/256)
10 N=0
20 PRINT "TURN";N
21 GOSUB 1000
30 GOSUB 4000
40 IF A$="GO" THEN N=N+1:GOSUB 2000
50 GOTO 20
1000 PRINT "XXX"
1010 PRINT "X X"
1020 PRINT "XXX"
1030 RETURN
2000 X=USR(0)
2010 RETURN
3000 DATA 245,197,14,80,175,211,252,238
3008 DATA 1,6,100,16,254,13,32,245
3016 DATA 175,211,252,193,241,201
4000 INPUT A$
4010 RETURN

Compare blocking, serviced and queued sound when choosing the next step.

Verification and sources

Target: stock Aquarius BASIC with an array-backed USR sound helper. 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.

Mattel/Radofin, Aquarius BASIC documentation: INPUT, DATA/READ, DIM and USR; machine-code helper bytes and port behaviour are identified by this configuration’s executed source.