This program performs the song “Evergreen” (the Barbra Streisand ballad) by displaying lyrics syllable-by-syllable while playing the melody and chord accompaniment through the AY-3-8912 sound chip. Each DATA record holds a lyric fragment, a chord subroutine line number, a note duration, and a pitch value used both for BEEP and for horizontal text positioning via TAB. The chord subroutines use SOUND register writes to program the three AY chip tone channels simultaneously, implementing named chords such as C Major, A Minor, G Minor, B-flat Major, and others by poking raw 12-bit frequency divisor values split across paired registers. A dummy chord at line 1900 simply RETURNs immediately, allowing chord changes to be skipped mid-phrase without restructuring the DATA. Lines 1990 and 1995 handle inter-section pauses by silencing and restarting the noise/envelope settings, while POKE 23692,255 suppresses the scroll prompt.
Program Analysis
Program Structure
The program is organized into three distinct regions. Lines 1–35 handle initialization and the main playback loop. Lines 40–230 contain all the song DATA. Lines 300–310 perform a final cleanup and stop. Lines 1000–1999 are a library of subroutines, each setting AY-3-8912 registers for a specific chord or control function.
- Init (1–20): Sets screen colors, prints the title, pauses, clears, and disables scroll with
POKE 23692,255. - Main loop (25–35): Reads 150 DATA records and for each one prints a lyric fragment, calls a chord subroutine, sounds a note, and clears the screen if the pitch value equals 30.
- Song DATA (40–230): Each record is a 4-tuple: lyric string, chord subroutine line, BEEP duration, BEEP pitch semitones.
- Cleanup (300–310): Calls the opening chord, pauses, silences the AY chip, then STOPs.
- Chord subroutines (1000–1999): Each writes directly to AY register pairs via
SOUNDstatements and RETURNs.
Data Format and Dual Use of the Pitch Field
Each DATA record uses four fields: L$ (lyric), C (chord subroutine address), D (BEEP duration in seconds), and P (BEEP pitch in semitones above middle A). The field P serves double duty: it is also passed to TAB P*1.2 to position the lyric text horizontally on screen, creating a rough left-to-right visual spread that loosely reflects the melodic pitch range. When P=30 (a sentinel value used for inter-section silences), the screen is cleared after the beat.
AY-3-8912 Chord Programming
Each chord subroutine programs the three tone channels of the AY chip by writing raw frequency divisor values to register pairs 0/1, 2/3, and 4/5 via the SOUND keyword. Because the AY frequency registers are 12 bits wide, each pitch requires a low byte (even register) and a high byte (odd register). For example, line 1065 sets:
| Register | Value | Meaning |
|---|---|---|
| 0 | 23 | Channel A tone low byte |
| 1 | 1 | Channel A tone high byte → divisor 279 |
| 2 | 234 | Channel B tone low byte |
| 3 | 0 | Channel B tone high byte → divisor 234 |
| 4 | 186 | Channel C tone low byte |
| 5 | 0 | Channel C tone high byte → divisor 186 |
This represents a G Minor chord. The opening subroutines at lines 1000 and 1001 also configure registers 7–13 to set the mixer, amplitude, and envelope shape, establishing noise and volume levels that persist for the rest of the song.
The Dummy Chord Technique
Line 1900 is a subroutine that consists of nothing but RETURN (with a comment labeling it “DUMMY CHORD”). Wherever a note in the melody should continue the previous chord without change, the DATA record points C to 1900. This avoids duplicating chord-setting code and keeps the DATA loop uniform: every record unconditionally executes GO SUB C, regardless of whether a chord change is intended.
Silence and Section Break Subroutines
Lines 1990 and 1995 handle inter-section gaps. Both mute all AY channels by writing 63 to register 7 (mixer: all off), pause for 30 or 40 frames respectively, then restore the mixer and amplitude settings. Line 1999, called at the very end of the program, writes 63 to register 7 and zeros channels A, B, and C to fully silence the chip.
Screen Management
POKE 23692,255 at line 20 writes to the system variable that controls how many lines can be printed before a scroll prompt appears, suppressing the “scroll?” message for 255 lines. The screen is cleared mid-song only when the pitch sentinel value P=30 is encountered, which coincides with the DATA records at the end of lyric phrases. The TAB expression TAB P*1.2 will produce values from 0 to roughly 26 across the pitch range used (0–21 semitones), staying within the 32-column display width.
Notable Idioms and Techniques
- Chord subroutine addresses are stored directly as numeric DATA values and called with
GO SUB C, making the line numbers part of the song’s data structure. - The
FOR B=1 TO 150loop iterates exactly as many times as there are DATA records, relying on the programmer to keep both counts in sync — there is no runtime check. - The
REMcomments in chord subroutines (e.g.,REM C MAJ,REM A MIN) serve as inline documentation of the musical harmony, which is otherwise encoded entirely as raw register values. - Line 1 initializes the AY chip’s noise register before the title screen appears, likely to silence any residual sound from a previous run.
- The
SAVE "EVERGREEN" LINE 1at line 9998 saves the program with an auto-run directive starting at line 1.
Potential Issues
- The comment at line 15 reads
REM QTR=.4 till 2nd note line 80, indicating the programmer considered extracting the quarter-note duration as a variable but did not do so; durations are instead hard-coded in each DATA record. - If the DATA count and the loop bound
150ever fall out of sync, the program will either exhaust its DATA (causing an error) or loop past the last record silently, depending on direction. - The expression
TAB P*1.2uses a floating-point multiply each iteration; for largePvalues this could in principle exceed column 31, though the pitch range in the data stays well within safe bounds.
Content
Source Code
1 SOUND 7,63
10 PAPER 4: BRIGHT 1: BORDER 4: INK 0: CLS : PRINT AT 10,6;"E V E R G R E E N"
15 PAUSE 150: CLS : REM QTR=.4 till 2nd note line 80
20 POKE 23692,255
25 FOR B=1 TO 150: 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 "LOVE,",1001,1.6,9,"SOFT",1030,.4,9
50 DATA "AS",1000,.4,10,"AN",1030,.4,12,"EAS-",1900,.4,12,"Y",1035,.4,14,"CHAIR;",1030,2,7
55 DATA " ",1995,0,0
60 DATA "LOVE,",1900,1.6,7,"FRESH",1015,.4,7,"AS",1900,.4,9,"THE",1900,.4,10,"MORN-",1030,.4,9,"ING",1900,.4,12,"AIR.",1900,2,5
65 DATA " ",1995,0,30
70 DATA "ONE",1050,1.6,17,"LOVE",1900,.4,14,"THAT",1900,.4,16,"IS",1900,.4,17,"SHARED",1055,.4,16,"BY",1900,.4,19,"TWO,",1900,2,12
80 DATA "I",1065,.4,14,"HAVE",1900,.3,17,"FOUND",1900,1.2,10,"WITH",1900,.3,9,"YOU.",1125,1.2,7
85 DATA " ",1995,0,30
90 DATA "LIKE",1015,.3,5,"A",1900,.3,7,"ROSE",1030,1.5,5
100 DATA "UN-",1900,.3,9,"DER",1900,.3,10,"THE",1900,.3,12,"A-",1035,.3,12,"PRIL",1900,.3,14,"SNOW,",1900,1.8,7
105 DATA " ",1990,0,30
110 DATA "I",1065,.6,19,"WAS",1900,.3,17,"AL-",1015,.3,14,"WAYS",1900,.3,12,"CER",1900,.15,8,"-",1900,.15,7,"TAIN",1900,.3,5,"LOVE",1030,.3,7,"WOULD",1900,.3,9,"GROW.",1900,1.8,5
115 DATA " ",1995,0,30
120 DATA "LOVE,",1050,1.2,17,"AGE-",1900,.3,14,"LESS",1900,.3,16,"AND",1900,.3,17,"EV-",1055,.3,16,"ER-",1900,.3,19,"GREEN,",1900,1.8,12
125 DATA " ",1995,0,30
130 DATA "SEL-",1105,.3,14,"DOM",1900,.3,17,"SEEN",1900,.6,14,"BY",1900,.3,9,"TWO.",1130,2.2,12
140 DATA "YOU",1105,.6,17,"AND",1900,.3,16,"I",1900,.6,14,"WILL",1900,.15,16,"MAKE",1900,.15,17,"EACH",1055,.6,16,"NIGHT",1900,.15,12,"A",1900,.15,9,"FIRST,",1900,1.2,12
145 DATA " ",1995,0,30
150 DATA "EV-",1105,.3,17,"RY",1900,.3,16,"DAY",1900,.6,14,"A",1900,.15,16,"BE-",1900,.15,17,"GIN-",1055,.3,16,"NING.",1900,.6,12
155 DATA " ",1995,0,30
160 DATA "SPIR-",1105,.3,17,"ITS",1900,.3,16,"RISE",1025,.9,14,"AND",1900,.15,16,"THEIR",1900,.15,17,"DANCE",1055,.6,21,"IS",1900,.3,22,"UN-",1900,.3,21,"RE-",1900,.3,17,"HEARSED.",1055,1.2,12
165 DATA " ",1990,0,30
170 DATA "THEY",1030,.3,14,"WARM",1900,.3,17,"AND",1900,.15,16,"EX-",1900,.15,17,"CITE",1035,.3,16,"US",1900,.9,14
175 DATA " ",1990,0,30
180 DATA "CAUSE",1105,.6,22,"WE",1900,.3,22,"HAVE",1900,.3,21,"THE",1900,.3,22,"BRIGHT",1015,.3,21,"-",1900,.3,19,"EST",1900,.9,21
185 DATA " ",1995,0,30
190 DATA "LOVE,",1030,1.2,9,"TWO",1900,.3,9,"LIGHTS",1900,.3,10,"THAT",1900,.3,12,"SHINE",1900,.3,12,"AS",1035,.3,14,"ONE,",1900,1.8,7
195 DATA " ",1995,0,30
200 DATA "MORN-",1035,.3,7,"ING",1900,.3,7,"GLO-",1015,.6,7,"RY",1900,.3,7,"AND",1900,.3,9,"THE",1900,.3,10,"MID-",1030,.3,9,"NIGHT",1900,.3,12,"SUN.",1900,1.8,5
205 DATA " ",1995,0,30
210 DATA "TIME,",1050,1.2,17,"WE'VE",1900,.3,14,"LEARNED",1900,.3,16,"TO",1900,.3,17,"SAIL",1055,.3,16,"A-",1900,.3,19,"BOVE;",1900,1.8,12
220 DATA "TIME",1065,.3,14,"WON'T",1900,.3,17,"CHANGE",1900,.6,10,"THE",1900,.3,10,"MEAN-",1900,.3,10,"ING",1900,.3,9,"OF",1125,1.2,7
225 DATA " ",1995,0,30
230 DATA "ONE",1015,.6,7,"LOVE",1030,1.2,5,"AGE-",1900,.3,9,"LESS",1900,.3,10,"AND",1900,.3,12,"EV-",1035,1.2,10,"ER",1900,.9,19,"EV-",1115,.3,10,"ER",1900,1.2,10,"GREEN.",1030,1.8,17
300 GO SUB 1001: PAUSE 90: GO SUB 1999
310 STOP
1000 SOUND 7,56;8,15;9,15;10,16;11,5;12,5;13,13: RETURN : REM ON
1001 SOUND 7,58;8,8;10,8: RETURN : REM channels a & c only
1015 SOUND 0,209;1,0;2,165;3,0;4,139;5,0: RETURN : REM C MAJ
1025 SOUND 0,165;1,0;2,131;3,0;4,110;5,0: RETURN : REM E MAJ
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
1050 SOUND 0,186;1,0;2,156;3,0;4,124;5,0: RETURN : REM D MINOR D FNATURAL A
1055 SOUND 0,248;1,0;2,209;3,0;4,165;5,0: RETURN : REM A MIN
1065 SOUND 0,23;1,1;2,234;3,0;4,186;5,0: RETURN : REM G MIN
1105 SOUND 0,234;1,0;2,186;3,0;4,156;5,0: RETURN : REM B FLAT MAJ
1115 SOUND 0,147;1,0;2,124;3,0;4,98;5,0: RETURN : REM F# MIN
1125 SOUND 0,165;1,0;2,139;3,0;4,117;5,0: RETURN : REM Eb
1130 SOUND 0,7;1,1;2,209;3,0;4,175;5,0: RETURN : REM Ab
1900 RETURN : REM DUMMY CHORD TO REGULATE DATA
1990 SOUND 7,63: PAUSE 30: SOUND 7,56;8,10;9,10;10,16;11,5;12,5;13,13: RETURN
1995 SOUND 7,63: PAUSE 40: SOUND 7,56;8,10;9,10;10,16;11,5;12,5;13,13: RETURN
1999 SOUND 7,63;8,0;9,0;10,0: RETURN : REM OFF
9997 STOP
9998 CLEAR : SAVE "EVERGREEN" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
