*sigh* Well, it's useless anyway, without extra space. So I'll put that on hold for a few weeks. I just wish I knew why I can't understand the necessary sequence. I keep thinking I get it, but soon as I "Get it" something else slips away.
Anyway... music is something I CAN focus on, so here's something I've been struggling with as well.
At the end of Music_DoScore...
@Code_F1_F2: I am fairly sure this should work... it works for @Code_Fx, right?
@Code_Fx: ; here if $F0-F7, or $F9-FE
CMP #$F9 ; if less than F9,
BCC @Code_F0_F7 ; see if $F0-F7
JSR Music_SetTempo ; here if $F9-FE -- Tempo select
;JMP Music_DoScore_IncByA ; resume processing after incing by 1
CMP #$F0 ; if = $F0
BNE @Code_F1_F2 ; see if $F1 or $F2
JSR Music_LoopCode2 ; this loop stuff works fine!
CMP #$F3 ; if less than F3
JSR Music_Goto ; it must be $F1-F2
JMP Music_DoScore_IncByA ; just skip over this byte and continue processing
The following code is based off what I thought would be a simple concept: to split a song's parts up, and basically do a JSR/RTS to them, which should save tons of space if a song has some repeated chords arranged in a loop-unfriendly way.
The way I decided to do this was to save a "return" point using the extra variables. F1 calls the code, F2 closes it. The return point is saved as the code right after the goto label following F1.
CHAN_START = $A0
CHAN_BYTES = $14
ch_loop_marker = $10 ; works fine!
ch_return = $11 ;+$12
ch_freespace = $13 ;+$14? (or, since 00 counts as 1, is 14 the 00 of the next instrument?)
;DC to EF are empty for noise channel
AND #$0F ; get low bits
ORA #$02 ; if 2 then goto the Return part
BEQ @Return ; otherwise its a 1, so use the following goto label to find the point in the song to start playing next--
JSR @SaveReturnPoint ; ...once we get the return point saved...
JMP ResumeLoop ; --which works the same way as resuming a loop! But is skipping to another spot entirely.
LDA ch_return, X ; load return pointers
STA ch_scoreptr, X ; save as channel and music pointers
STA mu_scoreptr ;
LDA ch_return+1, X ;
STA ch_scoreptr+1, X ;
STA mu_scoreptr+1 ;
LDY #3 ; skip past the F1 code and the following GOTO label...
LDA (mu_scoreptr), Y ; get low byte of return-to address from the score
STA ch_return, X ; save as channel's return point (low)
INY ; get the high byte
LDA (mu_scoreptr), Y ;
STA ch_return+1, X ; save as channel's return point (high)
LDA (mu_scoreptr), Y ; to resume the loop, get low byte of loop address from the score
STA ch_scoreptr, X ; record that as the new score pointer for the channel
STA tmp ; store in tmp (don't change mu_scoreptr yet because we still need it
INY ; to get the high byte)
LDA (mu_scoreptr), Y
STA ch_scoreptr+1, X ; get high byte
STA mu_scoreptr ; then set low byte of mu_scoreptr previously tmp'd
RTS ; channel is now pointing to loop address -- exit
An Alternate @SaveReturnPoint attempt, based off skipping a loop...
LDA ch_scoreptr, X
STA ch_return, X
LDA ch_scoreptr+1, X
STA ch_return+1, X
And the song I've been testing with... Triangle channel.
.BYTE $F9 ; tempo ; does a triangle channel need an $F8 envelope speed command? (original game code seems to use them...)