Evergreen

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Music

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.

  1. Init (1–20): Sets screen colors, prints the title, pauses, clears, and disables scroll with POKE 23692,255.
  2. 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.
  3. Song DATA (40–230): Each record is a 4-tuple: lyric string, chord subroutine line, BEEP duration, BEEP pitch semitones.
  4. Cleanup (300–310): Calls the opening chord, pauses, silences the AY chip, then STOPs.
  5. Chord subroutines (1000–1999): Each writes directly to AY register pairs via SOUND statements 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:

RegisterValueMeaning
023Channel A tone low byte
11Channel A tone high byte → divisor 279
2234Channel B tone low byte
30Channel B tone high byte → divisor 234
4186Channel C tone low byte
50Channel 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 150 loop 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 REM comments 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 1 at 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 150 ever 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.2 uses a floating-point multiply each iteration; for large P values this could in principle exceed column 31, though the pitch range in the data stays well within safe bounds.

Content

Appears On

One of a series of library tapes. Programs on these tapes were renamed to a number series. This tape contained

Related Products

Related Articles

Related Content

Image Gallery

Evergreen

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.

People

No people associated with this content.

Scroll to Top