In that case you would have compiled your assembly routine, known where the address of the volume resides and simply poke a value to it, following that with the routine itself and a Frame Flyback to generate the same effect as if it would have come from the SOUND in basic. The advantage to doing this is perhaps clearer when using other Languages which don't have their own SOUND routines, though can access the Firmware Routines in order to generate the effects using that approach.
'''Holding Notes without Frame Flyback'''
Back in 2011 when I wrote these sound routines which holds the notes with Frame Flyback, I forgot to look into this further as at the time I was somewhat happy with the result. However, I've rectified this by using the appropriate flag to hold the note until it becomes True. This is the resulting program:
<pre>
org &4000
.sque equ &bcaa
ld b,15
.loop ld hl,volume
ld (hl),b
push bc
ld hl,sdata
.holdnote
call sque
jr nc,holdnote
pop bc
djnz loop
ret
.sdata defb 1
defb 0
defb 0
defb 0
defb 0
defb 31
.volume defb 0
defb 3
defb 0
</pre>
So now the Frame Flyback has been removed (CALL &BD19), and a new label called holdnote is used with jr nc,holdnote causing a jump to take place until carry becomes true.
=== Sample Sound Example 3 ===
My next BASIC example is a simple example of playing a tune, however BASIC is cleverly using math to play the tune:
<pre>
10 FOR octave=-1 TO 2
20 FOR x=1 TO 7: REM notes per octave
30 READ note
40 SOUND 1,note/2^octave
50 NEXT
60 RESTORE
70 NEXT
80 DATA 426,379,358,319,284,253,239
</pre>
For this example, I've simplified my Assembly example by working out the values of each tone and rounding the values to their nearest whole values, this is what I ended up with, with some of the value either being rounded up or down depending on it's decimal weight:
<pre>
852, 758, 716, 638, 568, 506, 478
426, 379, 358, 319, 284, 253, 239
213, 190, 179, 160, 142, 127, 120
107, 95, 90, 80, 71, 63, 60</pre>
From that, that information can be used for the Assembly routine, with each note being pick and stored where the other sound data resides. This produces the simplist of Sound tune engines which like BASIC variants, no other operations are carried out until the routine has run its course.
<pre> org &8000
ld b,29
.loop
ld hl,(adrtune) ;; address of tune
ld e,(hl) ;; put contents of
inc hl
ld d,(hl) ;; tune into DE
ld hl,tone ;; address of tone
ld (hl),e ;; store tune
inc hl
ld (hl),d ;; into tone
push bc ;; preserve loop value
ld hl,sdata ;; address of sound data
.holdnote
call &bcaa ;; Sound Queue
jr nc,holdnote ;; Hold note until carry is true
pop bc ;; restore loop value
ld hl,(adrtune) ;; increment address of tune
inc hl
inc hl
ld (adrtune),hl ;; to the next tune value
djnz loop ;; loop until b=0
ld hl,tune ;; return the tune
ld (adrtune),hl ;; back to the start.
ret ;; exit routine.
.sdata
defb 1,0,0
.tone
defb 0,0,0,12,20,0
.adrtune
defw tune
.tune
defw 852,758,716,638,568,506,478
defw 426,379,358,319,284,253,239
defw 213,190,179,160,142,127,120
defw 107,95,90,80,71,63,60,0</pre>
The only other limiting factor is how big the tune can be, using this approach only 255 notes can be played.
[[Category:Programming]]