Endless Love

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

This program is a musical rendition of “Endless Love,” playing the song’s lyrics and melody using the TS2068’s three-channel SOUND chip. Each lyric syllable is stored as a DATA record containing the word string, a chord subroutine number, a note duration, and a pitch value, which are READ and processed in the main loop at lines 25–35. Chord voicings (C major, F major, G major, A minor, D minor, E minor) are implemented as subroutines in the 1000–1060 range using raw SOUND register POKE-style parameters to set tone periods for all three channels simultaneously. Rest durations are handled by dedicated subroutines (1985, 1990, 1995) that silence the sound chip via SOUND 7,63 and use PAUSE to hold timing before re-enabling the chip with a new register configuration. A short melodic introduction is played via GO SUB 1800, which reads its own DATA sequence for an eight-note and a five-note phrase over C major and F major chords.


Program Analysis

Program Structure

The program divides into four logical sections:

  1. Initialization (lines 1–17): Silences the sound chip, sets screen colors, displays a title screen, pauses briefly, then calls the chord-initialization subroutine (1000) and the intro melody subroutine (1800).
  2. Main playback loop (lines 20–35): Iterates over 214 DATA records, reading and displaying lyrics, calling chord subroutines, playing BEEP notes, and clearing the screen at phrase boundaries.
  3. DATA section (lines 40–350): Each DATA record is a four-field tuple: L$ (lyric syllable), C (chord subroutine line number), D (BEEP duration), P (pitch / TAB position).
  4. Subroutine bank (lines 1000–1999): Chord voicings, rest handlers, and the intro melody routine.

Data Record Format

Each of the 214 records in the DATA pool encodes four values consumed by the main loop:

FieldVariablePurpose
1L$Lyric syllable printed to screen
2CLine number of chord subroutine to GO SUB
3DDuration argument for BEEP
4PPitch argument for BEEP; also used as TAB column (scaled by 1.2) and screen-clear trigger

Chord Subroutine Bank

Each subroutine in the 1000–1060 range directly programs the AY-3-8912 sound chip registers via chained SOUND parameters to produce a three-voice chord. Registers 0/1, 2/3, and 4/5 hold the low and high bytes of the tone period for channels A, B, and C respectively. The REM comments name the intended chord:

  • 1015 — C major (root position)
  • 1018 — C major (inversion: E–G–C)
  • 1030 — F major
  • 1035 — G major
  • 1050 — D minor (D–F–A)
  • 1055 — A minor
  • 1060 — E minor
  • 1001 — channels A and C only (partial voicing)
  • 1900 — dummy RETURN (no chord change; sustains previous state)

Sound Chip Control

Register 7 of the AY chip is the mixer control register. SOUND 7,63 sets all bits high, disabling all tone and noise outputs — used as a “silence” command before rest subroutines. The initialization at line 1000 sets register 7 to 56 (binary 00111000), enabling tone output on all three channels while disabling noise. Registers 8–10 set channel volume, and registers 11–13 configure the envelope generator; the rest subroutines (1985, 1990, 1995) reprogram these on exit with slightly varied envelope settings to simulate articulation differences between eighth, quarter, and half rests.

Rest and Timing Subroutines

Three subroutines handle musical rests with different durations:

  • 1985 — eighth rest: PAUSE 20
  • 1990 — quarter rest: PAUSE 30
  • 1995 — half rest: PAUSE 40

Each silences the chip first, pauses, then re-enables it with a new register configuration. The space-character DATA records (e.g., " ",1990,0,0) use these subroutines as their chord call while passing duration 0 and pitch 0 to BEEP, effectively making BEEP a no-op for the rest duration.

Screen Clear Mechanism

The pitch field P doubles as a phrase-boundary signal: when P=30, line 30 executes CLS after the BEEP. This clears the lyric display at the end of each major phrase. The value 30 is chosen because it is outside the normal TAB column range used for lyrics (0–21), making it an unambiguous sentinel.

TAB Column Calculation

Line 30 uses TAB P*1.2 to position lyrics. Since P is the BEEP pitch semitone offset (ranging roughly 0–21), multiplying by 1.2 maps pitches to screen columns 0–25, giving a crude visual representation of melodic contour — higher-pitched syllables appear further right on screen.

Scroll Suppression

Line 20 executes POKE 23692,255, which sets the system variable SCRCT (scroll count) to 255. This suppresses the “scroll?” prompt that would otherwise interrupt screen output after 22 lines, allowing continuous lyric printing without user intervention.

Intro Melody (Subroutine 1800)

The intro plays two short melodic phrases before the main loop. It uses a local RESTORE/FOR/READ pattern with its own DATA at lines 1810 and 1820, reading duration/pitch pairs independently of the main DATA sequence. It calls chord subroutines 1015 (C major) for the first eight-note phrase and 1030 (F major) for the five-note phrase. The variable b (lowercase) used here shadows the main loop’s B (uppercase); in Sinclair BASIC, variable names are case-sensitive only by convention — on the TS2068, b and B are actually the same variable, so the intro loop resets B before the main loop begins at line 25, which is harmless since B is immediately reinitialized by the FOR at line 25.

Notable Techniques

  • Using the BEEP pitch argument simultaneously as a screen TAB column for visual melody representation.
  • Using a sentinel value in the pitch field (P=30) to trigger CLS within the main data-driven loop.
  • The dummy subroutine at line 1900 (RETURN only) allows the DATA to specify “no chord change” without special-casing the main loop.
  • Direct AY register programming via chained SOUND statements to define polyphonic chord voicings.
  • Local RESTORE calls within subroutines to read subroutine-local DATA without disturbing the main DATA pointer — though this works here because the intro subroutine is called before the main RESTORE 40 at line 25.

Bugs and Anomalies

  • Line 1125 defines an “Eb” chord subroutine but it is never called from any DATA record — it is dead code.
  • The BEEP D,P call when D=0 produces an extremely short (zero-duration) beep rather than true silence; in practice this is inaudible but is not strictly a no-op.
  • The DATA count of 214 records stated in the FOR loop (line 25) should be verified against the actual DATA lines — if the count is slightly off, either a “Out of DATA” error or unused records at the end will result; the DATA appears to reach exactly 214 records based on the listing, but no programmatic count verification is performed.

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

Endless Love

Source Code

    1 SOUND 7,63
   10 PAPER 3: BRIGHT 1: BORDER 7: INK 7: CLS : PRINT AT 10,5;"E N D L E S S  L O V E"
   15 PAUSE 150: CLS 
   17 GO SUB 1000: GO SUB 1800
   20 POKE 23692,255
   25 RESTORE 40: FOR B=1 TO 214: 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 "MY",1018,1,4,"LOVE",1018,1,4
   45 DATA " ",1995,0,0
   50 DATA "THERE'S",1018,.5,4," ON-",1900,.25,5,"LY",1900,.25,7,"YOU",1030,.5,7,"IN",1900,.25,5,"MY",1900,.25,4,"LIFE",1900,.75,5
   55 DATA " ",1990,0,0
   60 DATA "THE",1035,.25,2,"ON-",1900,.5,2,"LY",1900,.5,2,"THING",1018,.5,2,"THAT'S",1900,.5,4,"RIGHT.",1900,1,4
   65 DATA " ",1990,0,30
   70 DATA "MY",1015,.25,7,"FIRST",1900,.25,5,"LOVE",1018,1,4
   75 DATA " ",1995,0,0
   80 DATA "YOU'RE",1055,.5,4,"EV-",1900,.25,5,"'RY",1900,.25,7,"BREATH",1030,.5,7,"THAT",1900,.25,5,"I",1030,.25,7,"TAKE",1900,.75,5
   85 DATA " ",1990,0,0
   90 DATA "YOU'RE",1035,.25,2,"EV-",1900,.5,2,"'RY",1900,.5,2,"STEP",1018,.5,2,"I",1900,.5,7,"MAKE",1018,1,4
   95 DATA " ",1990,0,30
  100 DATA "AND",1018,.25,0,"I--",1030,2,9
  105 DATA " ",1990,0,0
  110 DATA "I",1035,.5,11,"WANT",1900,.25,12,"TO",1900,.25,14,"SHARE",1018,1,7,"ALL",1900,.75,7,"MY",1001,.25,14,"LOVE",1055,1,12," ",1000,0,0,"WITH",1030,.25,11,"YOU",1900,1,9
  115 DATA " ",1990,0,0
  120 DATA "NO",1035,.25,11,"ONE",1900,.25,12,"ELSE",1900,.5,14,"WILL",1015,.25,12,"DO",1900,.5,11
  125 DATA " ",1995,0,30
  130 DATA "AND",1018,.25,0,"YOUR",1015,.25,12,"EYES,",1030,2,9,"THEY",1050,.5,11,"TELL",1035,.25,11,"ME",1900,.25,12,"HOW",1900,.5,14,"MUCH",1015,.75,14,"YOU",1001,.25,16,"CARE",1055,1,12
  135 DATA " ",1000,0,0,"OH,",1055,.25,14,"YES",1030,1,11
  140 DATA " ",1990,0,30
  150 DATA "YOU",1030,.5,11,"WILL",1900,.25,12,"AL-",1060,1,11,"WAYS",1900,.5,12,"BE",1050,2,12,"MY",1030,.5,12,"END-",1900,.5,12,"LESS",1900,.5,12,"LOVE",1018,2,12
  155 DATA " ",1995,0,30," ",1000,0,0
  160 DATA "TWO",1018,1,4,"HEARTS---",1900,1,4
  165 DATA " ",1995,0,0
  170 DATA "TWO",1018,.5,4,"HEARTS",1900,.25,5,"THAT",1900,.25,7,"BEAT",1030,.5,7,"AS",1900,.25,5,"ONE",1900,.75,5
  175 DATA " ",1990,0,0
  180 DATA "OUR",1035,.25,2,"LIVES",1900,.5,2,"HAVE",1900,.5,2,"JUST",1018,.5,2,"BE-",1900,.5,4,"GUN",1900,1,4
  185 DATA " ",1985,0,0
  190 DATA "FOR-",1018,.25,7,"EV-",1900,.25,5,"ER",1900,1,4
  195 DATA " ",1995,0,30
  200 DATA "I",1055,.5,4,"HOLD",1900,.25,5,"YOU",1900,.25,7,"CLOSE",1030,.5,7,"IN",1900,.25,5,"MY",1900,.25,7,"ARMS",1900,.75,5
  210 DATA "I",1035,.25,2," CAN'T",1900,.5,2," RE-",1900,.5,2,"SIST",1018,.5,2," YOUR",1900,.5,7," CHARMS",1900,1,4
  215 DATA " ",1990,0,30
  220 DATA "AND",1018,.25,0," LOVE",1030,2,9
  225 DATA " ",1990,0,0
  230 DATA "I'D",1035,.5,11," BE",1900,.25,12," A",1900,.25,14," FOOL",1018,1,7," FOR",1900,.75,14," YOU",1055,1,12,"I'M",1900,.5,11,"SURE",1030,1.5,9
  235 DATA " ",1990,0,0
  240 DATA "YOU",1035,.25,11," KNOW",1900,.25,12," I",1900,.5,14," DON'T",1015,.25,12," MIND",1900,.25,11
  245 DATA " ",1985,0,30
  250 DATA "CAUSE",1030,2,9," YOU,",1080,.5,11," YOU",1035,.25,11," MEAN",1900,.25,12," THE",1900,.5,14," WORLD",1015,.75,14," TO",1900,.25,16," ME",1900,.75,16,"AND,",1900,1,12,"OH",1900,1,14
  255 DATA " ",1990,0,0
  260 DATA "I",1030,.5,14," KNOW",1900,1,12
  265 DATA " ",1990,0,0
  270 DATA "I",1060,.5,12," FOUND",1900,.75,11," IN",1900,.25,12," YOU",1050,2,12
  275 DATA " ",1990,0,30
  280 DATA "MY",1030,.5,12," END-",1900,.25,12," LESS",1900,.5,12," LOVE",1015,2,12
  285 DATA " ",1985,0,30
  290 DATA "AND",1018,.25,0," LOVE",1030,2,9
  295 DATA " ",1990,0,0
  300 DATA "I'D",1035,.5,11," BE",1900,.25,12," A",1900,.25,14," FOOL",1018,1,7," FOR",1900,.75,14," YOU",1055,1,12,"I'M",1900,.5,11,"SURE",1030,1.5,9
  305 DATA " ",1990,0,0
  310 DATA "YOU",1035,.25,11," KNOW",1900,.25,12," I",1900,.5,14," DON'T",1015,.25,12," MIND",1900,.25,11
  315 DATA " ",1985,0,30
  320 DATA "AND",1018,.25,12," YES,",1030,2,9," YOU'LL",1035,.25,11," BE",1900,.25,12," THE",1900,.5,14," ON-",1018,.5,14,"LY",1900,.25,19," ONE",1900,2,16
  325 DATA " ",1999,0,30," ",1000,0,0
  330 DATA "OH",1055,.5,19," NO,",1030,1,21," I",1900,.25,19," CAN'T",1900,.25,17," DE-",1900,.25,16,"NY",1900,1.5,19," THIS",1900,.5,16," LOVE",1030,1,21," I",1900,.25,19," HAVE",1900,.25,17," IN-",1900,.25,16,"SIDE",1060,1,19
  335 DATA " ",1990,0,30
  340 DATA "AND",1060,.25,16," I'LL",1900,.25,16," GIVE",1030,1,21," IT",1900,.25,19," ALL",1900,.25,17," TO",1900,.25,16," YOU",1060,1.5,19," MY",1900,.5,16," LOVE",1030,.5,21
  345 DATA " ",1990,0,30
  350 DATA "MY",1030,.5,12," END-",1900,.25,12,"LESS",1900,.25,12," LOVE",1018,3,12
  400 SOUND 7,63: STOP 
 1000 SOUND 7,56;8,10;9,16;10,14;11,16;12,16;13,8: RETURN : REM ON
 1001 SOUND 7,58;8,15;10,15: RETURN : REM channels a & c only
 1015 SOUND 0,209;1,0;2,165;3,0;4,139;5,0: RETURN : REM C MAJ 
 1018 SOUND 0,165;1,0;2,139;3,0;4,104;5,0: RETURN : REM C MAJ chord inversion egc
 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
 1060 SOUND 0,165;1,0;2,139;3,0;4,110;5,0: RETURN : REM E MIN
 1125 SOUND 0,165;1,0;2,139;3,0;4,117;5,0: RETURN : REM Eb
 1800 GO SUB 1015
 1805 RESTORE 1810: FOR b=1 TO 8: READ d,p: BEEP d,p: NEXT b
 1810 DATA .25,12,.25,7,.25,12,.25,16,.25,14,.25,7,.25,14,.25,17
 1812 GO SUB 1030
 1815 RESTORE 1820: FOR b=1 TO 5: READ d,p: BEEP d,p: NEXT b
 1820 DATA .25,16,.25,7,.25,12,.25,16,.5,14
 1830 RETURN 
 1900 RETURN : REM DUMMY CHORD TO REGULATE DATA
 1985 SOUND 7,63: PAUSE 20: SOUND 7,56;8,12;9,16;10,14;11,5;12,5;13,13: RETURN : REM 8TH rest
 1990 SOUND 7,63: PAUSE 30: SOUND 7,56;8,16;9,15;10,15;11,64;12,64;13,13: RETURN : REM qtr rest
 1995 SOUND 7,63: PAUSE 40: SOUND 7,56;8,12;9,15;10,16;11,64;12,64;13,13: RETURN : REM half rest
 1999 SOUND 7,63;8,0;9,0;10,0: RETURN : REM OFF
 9997 STOP 
 9998 CLEAR : SAVE "ENDLESSLUV" 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