diff --git a/src/asm/6502/stream.s b/src/asm/6502/stream.s index 7cebef2a4..82dda24ef 100644 --- a/src/asm/6502/stream.s +++ b/src/asm/6502/stream.s @@ -18,6 +18,7 @@ FCS_MAX_STACK=16 ; stack depth per channel (FCS_MAX_STACK*FCS_MAX_CHAN<256) ; player constants - change if necessary fcsAddrBase=$20 ; player state address base +fcsZeroPage=$10 ; player state address base for zero-page-mandatory variables fcsGlobalStack=$200 ; player stack (best placed in a page) fcsPtr=$8000 ; pointer to command stream fcsVolMax=fcsVolMaxExample ; pointer to max channel volume array @@ -31,7 +32,8 @@ fcsSpeedDial=fcsPtr+24 ; - do not implement HINT commands - the player will never send these ; - no need to implement commands not pertaining to the target system ; - a zero pointer means "don't handle" -fcsCmdTable=fcsCmdTableExample +fcsCmdTableLow=fcsCmdTableExample +fcsCmdTableHigh=fcsCmdTableExample ; variables ; these may be read by your command handling routines @@ -42,25 +44,107 @@ fcsTicks=fcsAddrBase+8 ; short ; temporary variables fcsSendVolume=fcsAddrBase+10 ; char fcsSendPitch=fcsAddrBase+11 ; char +fcsCmd=fcsAddrBase+16 ; char[8] +fcsTempPtr=fcsZeroPage ; short ; channel state -chanPC=fcsAddrBase+16 ; short -chanTicks=fcsAddrBase+16+(FCS_MAX_CHAN*2) ; short -chanStackPtr=fcsAddrBase+16+(FCS_MAX_CHAN*4) ; char +chanPC=fcsZeroPage+2 ; short +chanTicks=fcsAddrBase+24 ; short +chanStackPtr=fcsAddrBase+24+(FCS_MAX_CHAN*2) ; char +chanNote=fcsAddrBase+24+(FCS_MAX_CHAN*2)+1 ; char +chanVibratoPos=fcsAddrBase+24+(FCS_MAX_CHAN*4) ; char ; may be used for driver detection fcsDriverInfo: .byte "Furnace" .byte 0 +; note on null +fcsNoteOnNull: + lda #0 + sta chanVibratoPos,x + jsr fcsDispatchCmd + rts + +; note off, note off env, env release +fcsNoArgDispatch: + jsr fcsDispatchCmd + rts + +fcsOneByteDispatch: + tya + pha + jsr fcsReadNext + sta fcsArg0 + pla + tay + jsr fcsDispatchCmd + rts + +; x: channel*2 +; y: command +fcsDispatchCmd: + ; read command call table + lda fcsCmdTableLow,y + sta fcsTempPtr + lda fcsCmdTableHigh,y + sta fcsTempPtr+1 + ; check for zero + lda fcsTempPtr + ora fcsTempPtr + beq :+ ; get out + ; handle command in dispatch code + jmp (fcsTempPtr) + ; only if pointer is zero +: rts + +; x: channel*2 +; a is set to next byte +fcsReadNext: + lda chanPC+1,x + sta fcsTempPtr+1 + + ldy chanPC,x + lda (fcsTempPtr),y + iny + bne :+ + inc chanPC+1,x +: sty chanPC,x + rts + ; x: channel*2 (for speed... char variables are interleaved) ; read commands fcsChannelCmd: ; read next byte + jsr fcsReadNext ; process and read arguments + ; if (a<0xb3) + bmi fcsNote ; handle $00-$7f + cmp #$b3 + bpl fcsOther - ; end - rts + ; this is a note + fcsNote: + sta fcsArg0 + sta chanNote,x + lda #0 + tay + sta chanVibratoPos,x + ; call DIV_CMD_NOTE_ON + jsr fcsDispatchCmd + rts + + ; other instructions + fcsOther: + ; call respective handler + sec + sbc #$b4 + tay + lda fcsInsTableLow,y + sta fcsTempPtr + lda fcsInsTableHigh,y + sta fcsTempPtr+1 + jmp (fcsTempPtr) ; x: channel*2 ; stuff that goes after command reading @@ -132,7 +216,7 @@ fcsTick: inc fcsTicks bne :+ inc fcsTicks+1 - + ; end : rts @@ -140,18 +224,18 @@ fcsInit: ; set all tick counters to 1 lda #1 ldy #0 - ldx #(FCS_MAX_CHANS*2)-1 -: sty fcsTicks,x - dex - sta fcsTicks,x + ldx #(FCS_MAX_CHANS*2) +: dex + sty chanTicks,x dex + sta chanTicks,x bne :- ; set channel program counters - ldx #(FCS_MAX_CHANS*2)-1 -: lda fcsPtr+40,x + ldx #(FCS_MAX_CHANS*2) +: dex + lda fcsPtr+40,x sta chanPC,x - dex bne :- ; TODO: relocate and more...