This program plays and displays the song “The Rose” (made famous by Bette Midler) using the TS2068’s AY-3-8912 sound chip via SOUND commands. Each syllable of the lyrics is stored in DATA statements alongside a chord subroutine number, note duration, and TAB position, which the main loop reads and renders simultaneously as printed text and music. The program uses all three AY chip channels (A, B, and C), with mixer register 7 and tone period registers 0–5 carefully set to produce triadic harmonies such as C major, F major, G major, E minor, and A minor. Line 1900 acts as a “dummy” chord subroutine that simply returns, allowing the data-driven loop to call it when no chord change is needed without special-casing the logic.
Program Analysis
Program Structure
The program is organized into three broad sections: initialization (lines 1–22), the main data-driven performance loop (lines 25–155), and a coda that replays the final phrase (lines 155–170). Supporting subroutines from line 1000 onward handle AY chip configuration and chord voicing. The song’s entire lyric and musical data is encoded in DATA statements (lines 40–160), consumed sequentially by a single FOR loop.
Data-Driven Performance Loop
Lines 25–35 form the core engine. Each iteration reads four values: L$ (a lyric syllable), C (a chord subroutine line number), D (BEEP duration in seconds), and P (a pitch value that doubles as a TAB column multiplier). The sequence is:
PRINT TAB P*1.2;L$— displays the syllable at a screen column derived from pitchGO SUB C— calls the appropriate chord subroutine to set AY registersBEEP D,P— plays the note using the built-in BEEP command (which uses the same AY chip)- If
P=30, the screen is cleared, acting as a stanza break trigger
Using the pitch value P both as a semitone offset for BEEP and as a TAB column multiplier (scaled by 1.2) is an elegant dual-purpose technique that loosely positions lyrics left-to-right on screen in a way that mirrors melodic contour.
AY Chip Usage via SOUND
The SOUND keyword (rendered as } in the source) directly writes to AY-3-8912 registers. Register 7 is the mixer control register; the comment in line 2 documents the bit patterns for enabling individual channels: value 56 enables all three tone channels (A, B, C), while values 57–63 selectively enable subsets. The chord subroutines write pairs of low/high bytes to registers 0–5 to set tone periods for all three channels simultaneously.
| Line | Chord | Notes (approx.) |
|---|---|---|
| 1015 | C Major | C, E, G (high octave) |
| 1017 | C Major (lower) | C, E, G (lower octave) |
| 1018 | C Major inversion | E, G, C (egc voicing) |
| 1030 | F Major | F, A, C |
| 1035 | G Major | G, B, D |
| 1055 | A Minor | A, C, E |
| 1060 | E Minor | E, G, B |
The Dummy Chord Subroutine
Line 1900 consists solely of RETURN with a REM comment “DUMMY CHORD TO REGULATE DATA.” Rather than adding conditional logic inside the main loop to skip chord calls for notes that fall within an existing harmony, the program stores 1900 as the chord value in the DATA. This keeps the loop body uniform and branchless for every data record.
Pause and Reset Subroutines
Lines 1991, 1995, and 1999 are short utility subroutines called via the same GO SUB C mechanism as the chord routines. They handle inter-stanza pauses and AY muting. Line 1999 silences the AY by setting tone period registers for channels A, B, C to zero and disabling the mixer. Line 1996 performs a brief silence, then re-enables all channels with specific envelope values, providing a dynamic effect between verses.
Initialization
Line 1 sets the AY mixer (register 7) to a specific channel configuration and POKEs the system variable at address 23561–23562, which controls the FRAMES counter or a related timing variable, likely to synchronize BEEP behavior. Line 20 sets the FRAMES system variable (address 23692) to 255 to prevent automatic screen timeout, then calls the channel setup subroutine at 1001.
Line 1003 Anomaly
Line 1003 contains only SOUND register writes with no RETURN statement. It is referenced as a chord number in the DATA at line 160. Without a RETURN, execution will fall through into line 1015 and return from there instead. This appears to be a deliberate or inadvertent fall-through that effectively applies both the 1003 AY settings and the C Major voicing of 1015 before returning — an unintentional chord layer or an oversight.
Screen Display
The display uses PAPER 2 (red), INK 0 (black), and BRIGHT 1 for a high-contrast presentation. Lyrics scroll down the screen as each syllable is printed. The stanza-break mechanism (detecting P=30 in line 30) clears the screen between verses, with ” ” (space) DATA records serving as the sentinel values that carry the value 30 for P.
Notable Techniques
- Using lyric pitch (
P) as both aBEEPsemitone and a scaledTABcolumn creates an implicit melodic-spatial layout on screen. - Chord subroutine numbers stored directly in DATA avoid any look-up table or conditional dispatch.
- The dummy subroutine at 1900 eliminates branching for “no chord change” cases.
- All three AY channels are driven in parallel with BEEP to create harmony over the melody.
- Line 2 is a REM that serves as inline documentation of all AY mixer register values for channel selection — a useful programmer’s reference embedded in the code.
Content
Source Code
1 SOUND 7,63: POKE 23561,20: POKE 23562,1
2 REM to enable Channel A:}7,62;B-SOUND 7,61;C-SOUND 7,59;A & B-SOUND 7,60;A & C-SOUND 7,58;B & C-SOUND 7,57;A,B,C--SOUND 7,56 MOST FREQUENT
10 PAPER 2: BRIGHT 1: BORDER 2: INK 0: CLS : PRINT AT 10,7;" T H E R O S E "
15 REM QTR=.5;RAISED AN OCTAVE
20 POKE 23692,255: GO SUB 1001
22 GO SUB 1018: PAUSE 300: CLS
25 FOR B=1 TO 185: READ L$,C,D,P
30 PRINT TAB P*1.2;L$: GO SUB C: BEEP D,P: IF P=30 THEN CLS
35 NEXT B
40 DATA "SOME",1999,.25,12,"SAY",1000,.25,14,"LOVE",1015,1.25,16,"IT",1900,.25,16,"IS",1900,.25,17,"A",1900,.25,16,"RIV",1035,.25,16,"ER",1900,1.25,14
45 DATA "THAT",1900,.25,14,"DROWNS",1030,1.25,12,"THE",1900,.25,12,"TEN-",1035,.25,14,"DER",1900,.25,16,"REED",1015,1,16
47 DATA " ",1991,0,30
50 DATA "SOME",1900,.25,12,"SAY",1015,.25,14,"LOVE",1900,1.25,16,"IT",1900,.25,16,"IS",1015,.25,17,"A",1900,.25,16,"RA-",1035,.25,16,"ZOR",1900,1.25,14,"THAT",1900,.25,14,"LEAVES",1030,1.25,12,"YOUR",1900,.25,12,"HEART",1035,.25,14,"TO",1900,.25,16,"BLEED",1015,1,16
55 DATA " ",1991,0,30
60 DATA "SOME",1015,.25,16,"SAY",1900,.25,17,"LOVE",1018,1.25,19,"IT",1900,.25,19,"IS",1900,.25,19,"A",1900,.25,19,"HUN-",1055,.25,19,"GER,",1900,1.25,12,"AN",1900,.25,16,"END-",1030,1.25,17,"LESS",1900,.25,16,"ACH-",1900,.25,14,"ING",1900,.25,12,"NEED",1035,1.25,9
65 DATA " ",1991,0,30
70 DATA "I",1035,.25,12,"SAY",1900,.25,14,"LOVE",1015,1.25,16,"IT",1900,.25,16,"IS",1900,.25,17,"A",1900,.25,16,"FLOW-",1017,.25,16,"ER",1900,1.25,14,"AND",1900,.25,16,"YOU",1030,1.25,12,"IT'S",1900,.25,12,"ON-",1035,.375,14,"LY",1900,.125,12,"SEED.",1017,1.25,12
75 DATA " ",1999,0,30
80 DATA "IT'S",1000,.25,12,"THE",1900,.25,14,"HEART",1017,1.25,16,"A-",1900,.25,16,"FRAID",1900,.25,17,"OF",1900,.26,16,"BREAK-",1035,.25,16,"ING",1900,1.25,14,"THAT",1900,.25,14,"NEV-",1030,.25,12,"ER",1900,1.25,12,"LEARNS",1035,.25,14,"TO",1900,.25,16,"DANCE.",1015,1.25,16
85 DATA " ",1991,0,30
90 DATA "IT'S",1000,.25,12,"THE",1900,.25,14,"DREAM",1015,1.25,16,"A-",1900,.25,16,"FRAID",1018,.25,17,"OF",1900,.25,16,"WAK-",1035,.25,16,"ING",1900,1.25,14,"THAT",1900,.25,14,"NEV-",1030,.25,14,"ER",1900,1.25,12,"TAKES",1035,.25,14,"THE",1900,.25,16,"CHANCE.",1017,1.25,16
95 DATA " ",1999,0,30
100 DATA "IT'S",1000,.25,16,"THE",1900,.25,17,"ONE",1060,1.25,19,"WHO",1900,.25,19,"WON'T",1900,.25,19,"BE",1900,.25,19,"TAK-",1055,.25,19,"EN",1900,1.25,12,"WHO",1015,.25,16,"CAN",1030,1.25,17,"NOT",1900,.25,16,"SEEM",1900,.25,14,"TO",1900,.25,12,"GIVE,",1035,.25,9," ",1900,.75,7
105 DATA " ",1991,0,30
110 DATA "AND",1035,.25,12,"THE",1900,.25,14,"SOUL",1015,1.25,16,"A-",1900,.25,16,"FRAID",1018,.25,17,"OF",1900,.25,16,"DY-",1035,.25,16,"ING",1900,1.25,14,"THAT",1900,.25,14,"NEV-",1030,.25,14,"ER",1900,.25,12,"LEARNS",1035,.25,14,"TO",1900,.25,12,"LIVE.",1017,2.5,12
115 DATA " ",1999,0,30
120 DATA "WHEN",1000,.25,12,"THE",1900,.25,14,"NIGHT",1015,1.25,16,"HAS",1900,.25,16,"BEEN",1018,.25,17,"TOO",1015,.25,16,"LONE-",1035,.25,16,"LY",1900,1.25,14,"AND",1900,.25,14,"THE",1900,.25,14,"ROAD",1030,.25,12,"HAS",1900,.5,9,"BEEN",1035,.25,14,"TOO",1900,.25,16,"LONG,",1015,1.25,16
125 DATA " ",1991,0,30
130 DATA "AND",1017,.25,12,"YOU",1015,.25,14,"THINK",1900,1.25,16,"THAT",1900,.25,16,"LOVE",1015,.25,17,"IS",1900,.25,16,"ON-",1035,.25,16,"LY",1900,1,14,"FOR",1900,.25,14,"THE",1900,.25,14,"LUCK-",1030,.25,14,"Y",1900,1.25,12,"AND",1035,.25,14,"THE",1900,.25,16,"STRONG,",1017,1.25,16
135 DATA " ",1999,0,30
140 DATA "JUST",1000,.25,16,"RE-",1900,.25,17,"MEM-",1060,1,19,"BER",1900,.25,16,"IN",1900,.25,19,"THE",1900,.25,19,"WIN-",1055,.25,19,"TER",1900,1,12,"FAR",1017,.25,12,"BE-",1015,.25,16,"NEATH",1030,1.25,17,"THE",1900,.25,16,"BIT-",1900,.25,14,"TER",1900,.25,12,"SNOWS",1035,1,9
145 DATA " ",1995,0,30
150 DATA "LIES",1035,.25,12,"THE",1900,.25,14,"SEED",1015,1.25,16,"THAT",1900,.25,16,"WITH",1900,.25,17,"THE",1035,.25,16,"SUN'S",1900,.25,16,"LOVE",1900,1,14,"IN",1900,.25,14,"THE",1900,.25,14,"SPRING",1030,1.25,12," ",1996,0,30,"BE-",1030,.25,12,"COMES",1035,.25,14,"THE",1900,.25,12,"ROSE.",1015,2,12
155 SOUND 7,63: PAUSE 60: FOR E=1 TO 5: READ L$,C,D,P: PRINT TAB P*1.2;L$: GO SUB C: BEEP D,P: NEXT E
160 DATA " ",1000,0,0,"BE-",1030,.25,12,"COMES",1035,.25,14,"THE",1003,.25,12,"ROSE.",1018,2.5,19
170 SOUND 7,63: PAUSE 180: STOP
1000 SOUND 7,56;8,10;9,12;10,16;11,2;12,2;13,13: RETURN : REM ON
1001 SOUND 7,57;9,16;10,16;11,32;12,32;13,8: RETURN : REM channels b & c only
1003 SOUND 8,16;9,16;10,16;11,225;12,225;13,9
1015 SOUND 0,209;1,0;2,165;3,0;4,139;5,0: RETURN : REM C MAJ
1017 SOUND 0,162;1,1;2,75;3,1;4,23;5,1: RETURN : REM LOWER C MAJ
1018 SOUND 0,165;1,0;2,139;3,0;4,104;5,0: RETURN : REM C MAJ chord inversion egc--hi & sweet
1030 SOUND 0,156;1,0;2,124;3,0;4,104;5,0: RETURN : REM F MAJ
1035 SOUND 0,139;1,0;2,110;3,0;4,93;5,0: RETURN : REM G MAJ
1055 SOUND 0,248;1,0;2,209;3,0;4,165;5,0: RETURN : REM A MIN
1060 SOUND 0,165;1,0;2,139;3,0;4,110;5,0: RETURN : REM E MIN
1900 RETURN : REM DUMMY CHORD TO REGULATE DATA
1991 PAUSE 30: RETURN
1995 PAUSE 40: RETURN
1996 SOUND 7,63: PAUSE 30: SOUND 7,56;8,16;9,16;10,16;11,0;12,0;13,13: RETURN
1999 SOUND 7,63;8,0;9,0;10,0: RETURN : REM OFF
9997 STOP
9998 CLEAR : SAVE "THE*ROSE" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
