This program plays a two-voice rendition of “And I Love Her” by The Beatles using the SOUND command’s programmable sound generator registers. Each pass through the main loop reads four groups of note data (four values each: low and high bytes for two channels) from DATA statements, issuing separate SOUND commands with different envelope and mixer settings for each beat subdivision. The tempo is randomized at startup using RND, with T1–T4 all set to the same value, giving the playback a variable feel each run. An ON ERR handler chain at lines 9990–9998 attempts graceful recovery from errors, ultimately silencing the sound chip by writing to register 8 and setting register 7 to 63 (all channels disabled). The program is designed to chain-load a second piece called “Chopin” after the song ends.
Program Structure
The program is organized into three logical regions: display setup (lines 100–625), the main playback loop (lines 739–900), song data (lines 1097–1172), and error-handling/initialization code (lines 9800–9999). Notably, execution does not begin at line 25 in the normal run order — line 25 sets TEMPO=500 but this variable is never subsequently used, suggesting it is a leftover from an earlier version. The actual tempo variables T1–T4 are set at line 9900, implying the intended entry point is line 9900, which initializes timing and then jumps to line 1 (a non-existent line, causing execution to fall through to line 25 and onward).
Playback Loop
The main loop at line 745 iterates up to 100 times (FOR Z=1 TO 100). Each iteration reads four groups of four DATA values (A1,B1,A2,B2 through G1,H1,G2,H2), where each pair represents the low and high bytes of a frequency value for two independent sound channels. Four separate SOUND commands are issued per loop iteration, each with different register settings to vary the envelope and mixer configuration across the beat subdivisions.
SOUND Register Usage
Each SOUND statement programs multiple AY-3-8912 registers in a single call. The pattern across the four beat positions varies the envelope shape and amplitude:
- Line 800: Sets mixer (reg 7=49), amplitude for channels A and B (regs 8,9), tone periods for both voices (regs 2,3 and 4,5). No envelope.
- Line 820: Adds noise/envelope configuration (reg 6=5, regs 12,13 for envelope period and shape, reg 0,1 for noise), producing a more complex timbre.
- Line 840: Uses reg 6=31 and regs 0,1 set to 255,0 — maximum noise period — for a sustained envelope effect.
- Line 860: Identical register layout to line 840, providing a held note on the fourth subdivision.
Channel volumes S1 and S2 are both fixed at 15 (maximum) via line 739 and written to registers 9 and 10 respectively on every SOUND call.
Note Data Encoding
Frequency values are stored as two-byte little-endian integers split across consecutive DATA items. For example, the value 279 (0x0117) for a note near F#4 appears as 23,1 in the DATA (low byte 23, high byte 1). Zero-value pairs represent rests. The sentinel 9999,9999,9999,9999 at line 1172 terminates the song. Each of the four “voices” per beat reads both a melody channel pair and a harmony/bass channel pair, enabling two-voice polyphony.
Tempo Randomization
At line 9900, T1 is set to INT(RND*10), with a floor of 1 if the result is zero. All four pause variables (T1–T4) are then assigned the same value, so the tempo is uniform across beat subdivisions but varies between runs. The PAUSE values of 1–9 (in 1/50th second units) produce a tempo range of roughly 50–450 ms per note event.
Error Handling Chain
Lines 9990–9999 implement a cascading ON ERR recovery strategy. If an error occurs during playback, control passes to 9990, which resets the error handler, pauses, then sets a new handler pointing to 9995. A second error goes to 9995 (similar reset and redirect to 9998), and a third to 9998, which calls subroutine 9999. Line 9999 issues SOUND 8,0;7,63 to silence the sound chip (register 8 sets channel A amplitude to zero; register 7 value 63 = binary 111111 disables all tone and noise outputs) before returning.
Program Chaining
Line 9820 contains LOAD "Chopin", intended to chain-load the next music program after the Beatles piece finishes. Line 9800 (NEXT c) references a loop variable c from the FOR at line 9900, creating a two-pass structure before the LOAD is reached — though the end-of-data GO TO 1500 (a non-existent line) will cause an error that the ON ERR chain intercepts before normal loop termination.
Notable Anomalies
- Line 25 sets
TEMPO=500which is never referenced anywhere else in the program. - The GO TO 1500 targets at lines 752, 816, 831, and 859 jump to a non-existent line, intentionally triggering an error to exit the song — this is caught by the ON ERR handler at 9990.
- The DATA at lines 1097–1100 begins with a large block of zeros before the actual melody data, functioning as a silent lead-in.
- Lines 9900 and 9910 appear to be designed so that after two iterations of the
FOR c=1 TO 2loop, LOAD “Chopin” executes, but the error-exit mechanism via GO TO 1500 will preempt normal FOR/NEXT completion.
Content
Image Gallery
Source Code
25 LET TEMPO=500
100 BORDER 4:PAPER 4:INK 0:CLS
110 PRINT AT 4,1;"******************************"
120 PRINT AT 6,6;"TS2068 MUSIC DEMO I:"
140 PRINT AT 18,1;"******************************"
150 FOR n=4 TO 18:PRINT AT n,0;"*"; AT n,31;"*":NEXT n
624 PRINT AT 12,5; INK 0; PAPER 3;"TITLE: And I Love Her"
625 PRINT AT 8,9;"(THE BEATLES)"
739 LET S1=15:LET S2=15
740 RESTORE 1097:PAUSE 100
745 FOR Z=1 TO 100
751 READ A1,B1,A2,B2
752 IF A1=9999 OR B1=9999 THEN PRINT AT 15,12;" ":GO TO 1500
800 SOUND 7,49;6,0;12,13;13,1;8,16;9,S1;2,A1;3,B1;10,S2;4,A2;5,B2
810 PAUSE T1
815 READ C1,D1,C2,D2
816 IF C1=9999 OR D1=9999 THEN PRINT AT 15,12;" ":GO TO 1500
820 SOUND 7,49;8,16;6,5;12,5;13,0;0,100;1,6;9,S1;2,C1;3,D1;10,S2;4,C2;5,D2
825 PAUSE T2
830 READ E1,F1,E2,F2
831 IF E1=9999 OR F1=9999 THEN PRINT AT 15,12;" ":GO TO 1500
840 SOUND 7,49;8,16;6,31;12,6;13,0;0,255;1,0;9,S1;2,E1;3,F1;10,S2;4,E2;5,F2
845 PAUSE T3
858 READ G1,H1,G2,H2
859 IF G1=9999 OR H1=9999 THEN PRINT AT 15,12;" ":GO TO 1500
860 SOUND 7,49;8,16;6,31;12,6;13,0;0,255;1,0;9,S1;2,G1;3,H1;10,S2;4,G2;5,H2
865 PAUSE T4
900 NEXT Z
1097 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1098 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1099 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1100 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,186,0,0,0,186,0,0,0,165,0,0,0,165,0,0,0,156,0,0,0,156,0,0,0,110,0,0,0,110,0,0,0,124,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0
1110 DATA 186,0,0,0,186,0,0,0,165,0,0,0,165,0,0,0,156,0,0,0,156,0,0,0,110,0,0,0,110,0,0,0,124,0,0,0,124,0,0,0,124,0,0,0,124,0,0,0,124,0,0,0,124,0,0,0,124,0,0,0
1120 DATA 0,0,0,0,186,0,0,0,186,0,0,0,165,0,0,0,165,0,0,0,156,0,0,0,156,0,0,0,110,0,0,0,110,0,0,0,124,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0,104,0,0,0
1130 DATA 104,0,0,0,104,0,0,0,124,0,0,0,124,0,0,0,156,0,0,0,156,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0,186,0,0,0,186,0,0,0
1140 DATA 23,1,0,0,248,0,0,0,23,1,0,0,248,0,0,0,248,0,0,0,248,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0,165,0,0,0
1150 DATA 139,0,0,0,165,0,0,0,186,0,0,0,209,0,0,0,186,0,0,0,186,0,0,0
1151 DATA 186,0,248,0,186,0,57,1,165,0,221,0,165,0,57,1,156,0,248,0,156,0,75,1,110,0,241,1,110,0,162,1,124,0,75,1,104,0,162,1,104,0,57,1,104,0,162,1,104,0,75,1,104,0,162,1,104,0,241,1,104,0,162,1
1152 DATA 186,0,248,0,186,0,57,1,165,0,221,0,165,0,57,1,156,0,248,0,156,0,75,1,110,0,241,1,110,0,162,1,124,0,75,1,124,0,162,1,124,0,57,1,124,0,162,1,124,0,75,1,124,0,162,1,124,0,241,1
1153 DATA 0,0,57,1,186,0,248,0,186,0,57,1,165,0,221,0,165,0,57,1,156,0,248,0,156,0,75,1,110,0,241,1,110,0,162,1,124,0,75,1,104,0,162,1,104,0,46,2,104,0,162,1,104,0,116,1,104,0,162,1,104,0,114,2,104,0,241,1
1154 DATA 104,0,46,2,104,0,241,1,124,0,162,1,124,0,241,1,156,0,46,2,156,0,241,1,165,0,46,2,165,0,186,1,165,0,241,1,186,0,186,1,186,0,46,2
1155 DATA 23,1,186,1,248,0,241,1,23,1,186,1,248,0,162,1,248,0,75,1,248,0,116,1,165,0,75,1,165,0,23,1,165,0,75,1,165,0,116,1,165,0,75,1,165,0,162,1,165,0,75,1,165,0,116,1,165,0,75,1,165,0,23,1,165,0,75,1,165,0,116,1,0,0,75,1
1156 DATA 248,0,241,1,248,0,162,1,165,0,75,1,165,0,162,1,165,0,241,1,165,0,162,1,165,0,75,1,165,0,162,1,139,0,186,1,139,0,75,1,139,0,23,1,139,0,75,1,139,0,186,1,139,0,75,1,139,0,23,1,139,0,75,1
1157 DATA 165,0,241,1,165,0,162,1,110,0,75,1,110,0,162,1,139,0,241,1,139,0,162,1,165,0,75,1,165,0,162,1,139,0,186,1,139,0,75,1,139,0,23,1,139,0,75,1,139,0,248,0,139,0,75,1,139,0,23,1,139,0,75,1
1158 DATA 165,0,241,1,165,0,162,1,110,0,75,1,110,0,162,1,139,0,241,1,139,0,162,1,165,0,75,1,165,0,162,1,139,0,186,1,139,0,75,1,139,0,23,1,139,0,75,1,165,0,186,1,165,0,75,1,139,0,23,1,139,0,75,1
1159 DATA 165,0,241,1,165,0,116,1,156,0,57,1,165,0,116,1,186,0,241,1,186,0,116,1,186,0,57,1,186,0,116,1,209,0,46,2,209,0,186,1,209,0,116,1,209,0,186,1,221,0,46,2,221,0,186,1,221,0,116,1,221,0,186,1
1160 DATA 0,0,116,1,0,0,57,1,186,0,248,0,186,0,57,1,165,0,221,0,165,0,57,1,156,0,248,0,156,0,75,1,110,0,241,1,110,0,162,1,124,0,75,1,104,0,162,1,104,0,57,1,104,0,162,1,104,0,75,1,104,0,162,1,104,0,241,1,104,0,162,1
1162 DATA 186,0,248,0,186,0,57,1,165,0,221,0,165,0,57,1,156,0,248,0,156,0,75,1,110,0,241,1,110,0,162,1,124,0,75,1,124,0,162,1,124,0,57,1,124,0,162,1,124,0,75,1,124,0,162,1,124,0,241,1
1163 DATA 0,0,57,1,186,0,248,0,186,0,57,1,165,0,221,0,165,0,57,1,156,0,248,0,156,0,75,1,110,0,241,1,110,0,162,1,124,0,75,1,104,0,162,1,104,0,46,2,104,0,162,1,104,0,116,1,104,0,162,1,104,0,114,2,104,0,241,1
1164 DATA 104,0,46,2,104,0,241,1,124,0,162,1,124,0,241,1,156,0,46,2,156,0,241,1,165,0,46,2,165,0,186,1,165,0,241,1,186,0,186,1,186,0,46,2
1165 DATA 23,1,186,1,248,0,241,1,23,1,186,1,248,0,162,1,248,0,75,1,248,0,116,1,165,0,75,1,165,0,23,1,165,0,75,1,165,0,116,1,165,0,75,1,165,0,162,1,165,0,75,1,165,0,116,1,165,0,75,1,165,0,23,1,165,0,75,1,165,0,116,1,165,0,75,1
1166 DATA 209,0,162,1,209,0,75,1,209,0,116,1,209,0,75,1,209,0,23,1,209,0,75,1,209,0,116,1,209,0,75,1
1167 DATA 209,0,0,0,209,0,0,0,209,0,0,0,209,0,0,0,209,0,0,0,0,0,0,0
1168 DATA 186,0,186,0,165,0,165,0,209,0,209,0,162,1,162,1,23,1,23,1
1169 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1170 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1172 DATA 9999,9999,9999,9999
9800 NEXT c
9820 LOAD "Chopin"
9900 ON ERR GO TO 9990:FOR c=1 TO 2:LET T1= INT (RND*10):IF t1=0 THEN LET t1=1:LET T2=T1:LET T3=T1:LET T4=T1:GO TO 1
9910 LET T2=T1:LET T3=T1:LET T4=T1:GO TO 1
9990 ON ERR RESET :PAUSE 100:ON ERR GO TO 9995
9995 ON ERR RESET :PAUSE 100:ON ERR GO TO 9998
9998 ON ERR RESET :GO SUB 9999
9999 SOUND 8,0;7,63:RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.