Auld Lang Syne — Dave change notes
uglisynthstart_ug:
di
call screensetup
ld hl,auldtitle ;setup the title
call printstring ;and print it
ld a,16+5 ;cyan (set up border colours red/cyan)
ld (colour1smc+1),a
ld a,2 ;red
ld (colour2smc+1),a
ld hl,auld0
call playsong
ld a,16+1 ;blue (set up border colours blue/yellow)
ld (colour1smc+1),a
ld a,6 ;yellow
ld (colour2smc+1),a
ld hl,auldtext1 ;setup the first bit of words - should alud
call printstring ;and print them
ld hl,auld1 ;setup the song fragment
call playsong ;and play it
ld hl,auldtext2 ;setup the next bit of words - and never
call printstring ;and print them
ld hl,auld2
call playsong
ld hl,auldtext3 ;should auld
call printstring
ld hl,auld3
call playsong
ld hl,auldtext4 ;for ths sake
call printstring
ld hl,auld4
call playsong
ld hl,auldtext5
call printstring
ld hl,trill1
call playsong
ld hl,auld5
call playsong
ld hl,auldtext6
call printstring
ld hl,trill1
call playsong
ld hl,auld6
call playsong
ld hl,auldtext7
call printstring
ld hl,trill1
call playsong
ld hl,auld7
call playsong
ld hl,auldtext8
call printstring
ld hl,auld8
call playsong
ld a,7 ; 7 is the code for white.
call 8859 ; set border colour.
call wastetime ;just a little pause
ld hl,auldtext9
call printstring
call wastetime ;just a little pause
call wastetime ;just a little pause
call wastetime ;just a little pause
ld hl,auldtext10
call printstring
ei
ret
playsong: ;called with HL pointing at the musidata
ld (songpointer),hl ;prime the songpointer with the song fragment
testloop:
ld hl,(songpointer)
ld (smc_data+1),hl
inc hl
inc hl
ld (songpointer),hl
smc_data:
ld hl,(auld1)
ld a,l ;check if L (low byte) is zero (end of song marker), if so, return
or a
ret z
;Check for a 'rest' (is the value of H=0)
ld a,h
or a
jr z,rest_routine
call playnote
;jr rest_routine ;THIS IS INSERTING GAPS EACH TIME, FOR TESTING PURPOSES
jr testloop ; Loop to next element in song
;
rest_routine:
ld bc,20000 ;insterts an audible gap THIS NEEDS TO BE BASED UPON length of L, ****but isn't, yet***
insert_pause:
nop
dec bc
ld a,b
or c
jr nz,insert_pause
jr testloop ; Loop to next element in song
playnote:
;load data (hl) l=length, h=pitch
tempo_smc:
ld a,4 ;eg. 4 - wow many times through the loop (sort of tempo multipler)
ld (smc_length+1),a ;setup the length of loop where it's reset
ld (noteroll),a ;noteroll ;and initially
ld (notelength),hl
ld e,1 ;make sure there is no errant "previous note" that matches the one playing
jumpbackpoint: ;come back here to setup d with the pitch of the note
ld hl,noteroll ;noteroll is a X-to-0 counter that determines how many times
dec (hl) ;it goes through the cycle (i.e. the lenghth in the l register)
jr nz,skipcounterdown ;
smc_length:
ld (hl),0 ;reset noteroll to it's value (equates to tempo) (will have been setup previously)
ld hl,notelength ;notelength is length (see also noteroll, though)
dec (hl) ;decrease it until it's zero
ret z ;
skipcounterdown:
ld hl,notepitch ;d is given the required pitch
ld d,(hl)
generateanote: ;generate a note
;pitch is held in register d
;but first check is it a "new" note ?
ld a,d
cp e ;e holds previous note
jr z,sameoldnote ;if it is the same, then we don't need to change counters etc
newnotebeingplayed:
xor a ;clear carry flag)
ld a,d
ld e,a ;store that note for comparisson next time
ld (smc_ug2+1),a
rra ;a=d/2
ld c,a ;c is used to keep counter temporarily
sameoldnote: ;enter here if if is the same note as before
ld a,c ;restore counter
inc a ;inc counter
ld b,a ;load it into b, for a djnz loop
killsometime:
nop ;4 tstates, one byte
cp (hl) ;7 tstates, one byte, no purpose - just killing some time - NB can add more time killing here, but notes will need retuning!
djnz killsometime
colour1smc:
ld a,17 ;will determine border colour as well. 16+colour. 17=blue
out (254),a
ld a,d ;get the pitch
sub c ;take away the counter
inc a ;add 1 to stop it ever being zero
ld b,a ;put the result into b
killsometime2:
nop ;4 tstates,one byte
cp (hl) ;7 tstates, one byte, no purpose - just killing some time
djnz killsometime2
colour2smc:
ld a,6 ;also determine border colour. 0+colour . 6=yellow
out (254),a
;now we'll change the pulse width by changing a/c
ld a,c
smc_ug1: ;this is smc modified to change whether pulse width is increasing or decreasing
add a,255 ;either add or subtract 1 (subtract 1=adding 255)
ld c,a ;update c
jp z,changedirection
smc_ug2:
ld a,0 ;this is smc modified when a new note is played
cp c
jp z,changedirection
jp jumpbackpoint
changedirection:
ld a,(smc_ug1+1) ;uses twos complement to turn 1 into 255 and vice versa
cpl ;
inc a ;
ld (smc_ug1+1),a ;
jp jumpbackpoint
; these variables are set up used to count the note length, and wavelength
noteroll: db 0
notelength: db 1
notepitch: db 253 ; note length and pitch
songpointer: dw auld1
;SONGDATA (Auld Lang Syne)
auld0: db c3c*2,c3 ;Shoullllldddd
db c3c*2,c3
db 0
auld1: ;should auld aquaintance be forgot,
; db c3c,c3
db 120,f3
db e3q,e3
db f3c,f3
db a3c,a3
db 135,g3
db f3q,f3
db g3c,g3
db 0
auld2: ;and never brought to mind
db a3q,a3
db g3q,g3
db 120,f3
db f3q,f3
db a3c,a3
db c4c,c4
db d4c,d4
db d4c,d4
db d4c,d4
db 0 ;endofsong marker
auld3: ;should auld aquaintance be forgot,
db d4c,d4
db 181,c4
auld7: ;same as end of melody3
db a3q,a3
db a3c,a3
db f3c,f3
db 135,g3
db f3q,f3
db g3c,g3
db 0
auld4: ;and the days of auld lang syne
db a3q,a3
db g3q,g3
db 120,f3
db d3q,d3
db d3c,d3
db c3c,c3
db 241,f3
db 0
trill1: ;for auld
db f3c/16,f3
db d4c/16,d4
db f3c/16,f3
db d4c/16,d4
db f3c/16,f3
db d4c/16,d4
db f3c/16,f3
db d4c/16,d4
db f3c/16,f3
db d4c/16,d4
db f3c/16,f3
db d4c/16,d4
db f3c/16,f3
db d4c/16,d4
db f3c/16,f3
db d4c/16,d4
DEFB 11, 122, 7, 188
DEFB 11, 122, 7, 188
DEFB 11, 122, 7, 188
DEFB 11, 122, 7, 188
DEFB 11, 122, 7, 188
DEFB 11, 122, 7, 188
DEFB 11, 122, 7, 188
DEFB 11, 122, 7, 188
db 0
auld5: ;(for auld) lang syne my dear
db a3q,a3
db a3c,a3
db f3c,f3
db 135,g3
db f3q,f3
db g3c,g3
db 0
auld6: ;(for auld) lang syne
db a3q,a3
db a3c,a3
db c4c,c4
db d4c,d4
db d4c,d4
db d4c,d4
db 0
auld8: ;as melody 4
db a3q,a3 ;for
db g3q,g3 ;the
db 120,f3 ;sake
db d3q,d3 ;of
db d3c,d3 ;auld
;langtrill
db c3c/24,c3
db e3c/24,e3
db g3c/24,g3
db as3c/24,as3
db c4c/24,c4
db c3c/24,c3
db e3c/24,e3
db g3c/24,g3
db as3c/24,as3
db c4c/24,c4
db c3c/24,c3
db e3c/24,e3
db g3c/24,g3
db as3c/24,as3
db c4c/24,c4
db c3c/24,c3
db e3c/24,e3
db g3c/24,g3
db as3c/24,as3
db c4c/24,c4
db c3c/24,c3
db e3c/24,e3
db g3c/24,g3
db as3c/24,as3
db c4c/24,c4
;synetrill
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db f3c*4/48,f3
db a3c*4/48,a3
db c4c*4/48,c4
db 0
;probably redundant stuff/fluff
screensetup:
ld a,2 ; upper screen
call 5633 ; open channel from rom print routine
ld a,56 ; black ink (6) on white paper (0*8) + bright (64*0)
ld (23693),a ; set our screen colours.
call 3503 ; clear the screen.
ld a,7 ; 7 is the code for white.
call 8859 ; set border colour.
; ld hl,memorystring ;memory text
; call printstring
; ld bc,uglisynthstart_ug
; call 11563 ; stack number in bc.
; call 11747 ; display top of calc. stack.
; ld a,"-"
; rst 16
; ld bc,firstfreebyte_ug
; call 11563 ; stack number in bc.
; call 11747 ; display top of calc. stack.
ret
;memorystring:
; db 22,21,0,"Memory : ",255
printstring: ;cheap and dirty string printing routine, hl points at string (terminated with a 255, rather than 0, to allow easier ctrl codes)
ld a,(hl)
inc a ;is it 255
ret z ;if so, exit loop
dec a
rst 16 ;if not, print it
inc hl ;and loop round
jr printstring
auldtitle: db 22,2,0,'Program: AULDLANG'
db 22,5,0,255
auldtext1:
auldtext3: db 'Should ZX Spectrums be forgot,',13,255
auldtext2: db 'And never brought to mind?',13,255
auldtext4: db 'And auld loading time?',13,13,255
auldtext5: db 'For auld loading time, my dear,',13,255
auldtext6: db 'For auld loading time,',13,255
auldtext7: db 'So put the kettle on, my dear,',13,255
auldtext8: db 'For the sake of loading time.',13,255
auldtext9: db 22,17,0,'ZX FACT:',13,13,'The R in ',34,'R Tape loading error,',34,13,'stands for ... ',255
auldtext10: db 18,1,'Robert Burns',255
wastetime: ;a dirty loop to dramatically pause
ld bc,0
timekill1: dec bc
cp (hl) ;this is just killing time
ld a,b
or c
ret z
jr timekill1
firstfreebyte_ug equ $
;Define notes'
c3 equ 253 ;c# [concert tunings, 440hz]
cs3 equ 240 ;d
db3 equ 240 ;d
d3 equ 226 ;d#
ds3 equ 212 ;e
eb3 equ 212 ;e
e3 equ 200 ;f
f3 equ 188 ;f#
fs3 equ 177 ;g
gb3 equ 177 ;g
g3 equ 166 ;g#
gs3 equ 156 ;a
ab3 equ 156 ;a
a3 equ 147 ;a#
as3 equ 137 ;b
bb3 equ 137 ;b
b3 equ 129 ;C
c4 equ 122 ;C#
cs4 equ 114 ;D
db4 equ 114 ;D
d4 equ 108 ;D#
ds4 equ 101 ;E
eb4 equ 101 ;E
e4 equ 95 ;F
f4 equ 88 ;F#
fs4 equ 83 ;G
gb4 equ 83 ;G
g4 equ 77 ;G#
gs4 equ 73 ;A
ab4 equ 73 ;A
a4 equ 68 ;A#
as4 equ 63 ;B
bb4 equ 63 ;B
;define note lengths (of crotchets)
c3c equ 60 ;c#
cs3c equ 63 ;d
db3c equ 63 ;d
d3c equ 67 ;d#
ds3c equ 72 ;e
eb3c equ 72 ;e
e3c equ 76 ;f
f3c equ 80 ;f#
fs3c equ 85 ;g
gb3c equ 85 ;g
g3c equ 90 ;g#
gs3c equ 96 ;a
ab3c equ 96 ;a
a3c equ 101 ;a#
as3c equ 108 ;b
bb3c equ 108 ;b
b3c equ 114 ;C
c4c equ 120 ;C#
cs4c equ 128 ;D
db4c equ 128 ;D
d4c equ 135 ;D#
ds4c equ 143 ;E
eb4c equ 143 ;E
e4c equ 151 ;F
f4c equ 162 ;F#
fs4c equ 171 ;G
gb4c equ 171 ;G
g4c equ 183 ;G#
gs4c equ 192 ;A
ab4c equ 192 ;A
a4c equ 204 ;A#
as4c equ 218 ;B
bb4c equ 218 ;B
d3q equ 34
e3q equ 38
f3q equ 40
g3q equ 45
a3q equ 51
end 32768
Share your thoughts about the article