6502 command stream player, part 2

This commit is contained in:
tildearrow 2025-04-15 18:48:51 -05:00
parent ecc60a3a64
commit c1e97e3467

View file

@ -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...