6502 command stream player, part 16

incomplete vibrato/pitch implementation
incomplete porta implementation
prepare for arp impl
This commit is contained in:
tildearrow 2025-04-21 19:38:19 -05:00
parent de752a17e9
commit 6c2ef8d2dd
3 changed files with 173 additions and 30 deletions

View file

@ -45,9 +45,9 @@ initPPU:
bpl - bpl -
startPlayer: startPlayer:
; draw some text ; draw some text
lda #$21 lda #$20
sta PPUADDR sta PPUADDR
lda #$02 lda #$42
sta PPUADDR sta PPUADDR
ldx #$00 ldx #$00
@ -123,7 +123,6 @@ irq:
; command stream player definition ; command stream player definition
FCS_MAX_CHAN=8 FCS_MAX_CHAN=8
FCS_MAX_STACK=10
fcsAddrBase=$30 fcsAddrBase=$30
fcsZeroPage=$0e fcsZeroPage=$0e
@ -139,7 +138,7 @@ fcsCmdTableHigh=fcsCmdTableExample
; data ; data
helloWorld: helloWorld:
.db "Hello, World!" .db "Furnace Test Player"
.db 0 .db 0
ppuPalette: ppuPalette:

Binary file not shown.

View file

@ -4,7 +4,6 @@
; usage: ; usage:
; define the following constants: ; define the following constants:
; - FCS_MAX_CHAN: the number of channels in your stream ; - FCS_MAX_CHAN: the number of channels in your stream
; - FCS_MAX_STACK: the maximum stack size
; - fcsAddrBase: player state address base ; - fcsAddrBase: player state address base
; - fcsZeroPage: player state address base for zero-page-mandatory variables ; - fcsZeroPage: player state address base for zero-page-mandatory variables
; - fcsGlobalStack: player stack (best placed in a page) ; - fcsGlobalStack: player stack (best placed in a page)
@ -26,6 +25,7 @@
; calculated from player constants ; calculated from player constants
fcsDelays=fcsPtr+8 fcsDelays=fcsPtr+8
fcsSpeedDial=fcsPtr+24 fcsSpeedDial=fcsPtr+24
fcsStackSize=fcsPtr+40+(FCS_MAX_CHAN*2)
; variables ; variables
; these may be read by your command handling routines ; these may be read by your command handling routines
@ -53,6 +53,8 @@ chanPortaTarget=fcsAddrBase+24+(FCS_MAX_CHAN*8)+1 ; char
chanVol=fcsAddrBase+24+(FCS_MAX_CHAN*10) ; short chanVol=fcsAddrBase+24+(FCS_MAX_CHAN*10) ; short
chanVolSpeed=fcsAddrBase+24+(FCS_MAX_CHAN*12) ; short chanVolSpeed=fcsAddrBase+24+(FCS_MAX_CHAN*12) ; short
chanPan=fcsAddrBase+24+(FCS_MAX_CHAN*14) ; short chanPan=fcsAddrBase+24+(FCS_MAX_CHAN*14) ; short
chanArpStage=fcsAddrBase+24+(FCS_MAX_CHAN*16) ; char
chanArpTicks=fcsAddrBase+24+(FCS_MAX_CHAN*16)+1 ; char
; may be used for driver detection ; may be used for driver detection
fcsDriverInfo: fcsDriverInfo:
@ -481,19 +483,38 @@ fcsChannelCmd:
sta fcsTempPtr+1 sta fcsTempPtr+1
jmp (fcsTempPtr) jmp (fcsTempPtr)
; this is called when vibrato depth is zero
fcsChanPitchShortcut:
; extend pitch sign
lda chanPitch,x
sta fcsArg0
bmi +
lda #0
sta fcsArg0+1
beq ++
+ lda #$ff
sta fcsArg0+1
++
; dispatch command
ldy #9
jsr fcsDispatchCmd
; end
jmp fcsChanDoPorta
; x: channel*2 ; x: channel*2
; stuff that goes after command reading ; stuff that goes after command reading
fcsChannelPost: fcsChannelPost:
rts
;;; DO VOLUME ;;; DO VOLUME
fcsChanDoVolume: fcsChanDoVolume:
; if (sendVolume || chanVolSpeed[x]!=0) ; if (sendVolume || chanVolSpeed[x]!=0)
lda fcsSendVolume lda fcsSendVolume
bne fcsChanDoPitch bne +
lda chanVolSpeed,x lda chanVolSpeed,x
ora chanVolSpeed+1,x ora chanVolSpeed+1,x
beq fcsChanDoPitch beq fcsChanDoPitch
; increase volume ; increase volume
lda chanVol,x + lda chanVol,x
clc clc
adc chanVolSpeed,x adc chanVolSpeed,x
sta chanVol,x sta chanVol,x
@ -506,22 +527,150 @@ fcsChannelPost:
bpl fcsChanPlus bpl fcsChanPlus
fcsChanMinus: fcsChanMinus:
; if (chanVol[x]<0) ; if (chanVol[x]<0)
bcc fcs bcs fcsChanSubmitVol
jmp fcsChanDoPitch ; chanVol[x]=0
lda #0
sta chanVol,x
sta chanVol+1,x
beq fcsChanSubmitVol ; shortcut
fcsChanPlus: fcsChanPlus:
; if (chanVol[x]>=fcsVolMax[x] || CARRY) ; if (chanVol[x]>=fcsVolMax[x] || CARRY)
bcs + ; overflow check
lda chanVol+1,x ; comparison check
cmp fcsVolMax.w,x
bmi fcsChanSubmitVol
; chanVol[x]=fcsVolMax[x]
+ lda fcsVolMax.w,x
sta chanVol+1,x
lda #0
sta chanVol,x
fcsChanSubmitVol:
lda chanVol+1,x
sta fcsArg0
ldy #$05 ; volume
jsr fcsDispatchCmd
;;; DO PITCH ;;; DO PITCH
fcsChanDoPitch: fcsChanDoPitch:
; if (sendPitch || chanVibrato[x]!=0)
lda fcsSendPitch
bne +
lda chanVibrato,x
and #$0f ; depth only
beq fcsChanDoPorta
; update vibrato
; get vibrato
+ lda chanVibrato,x
lsr
lsr
lsr
lsr
clc
adc chanVibratoPos,x
and #$3f
sta chanVibratoPos,x
; calculate vibrato pitch (TODO)
; 1. calculate vibrato position
; - we use 15 quarter sine tables, one for each vibrato depth
; - 32-63 are negatives of 0-31
; - a&31: zero is zero. otherwise a-1 in the table unless a&16
; - if a&16 then invert a
tay
; check for zero in a&31
and #$1f
bne +
; it is. load zero
lda #0
jmp fcsPostVibratoCalc1
; it is not. check a&16
+ and #$10
bne +
; 0-15
dey
tya
and #$0f
jmp fcsPostVibratoCalc
; 16-31
+ tya
and #$0f
eor #$0f ; 0-15 -> 15-0
fcsPostVibratoCalc:
; check for 32-63
pha
tya
and #$20
bne +
; 0-31
pla
tay
lda (fcsTempPtr),y
jmp fcsPostVibratoCalc1
; 32-63 (negate)
+ pla
tay
lda (fcsTempPtr),y
eor #$ff
clc
adc #1
; at this point, a contains the vibrato pitch
fcsPostVibratoCalc1:
sta fcsArg0
; extend sign
bmi +
lda #0
sta fcsArg0+1
beq ++
+ lda #$ff
sta fcsArg0+1
; extend pitch sign
++ lda chanPitch,x
sta fcsTempPtr
bmi +
lda #0
sta fcsTempPtr+1
beq ++
+ lda #$ff
sta fcsTempPtr+1
; add pitch
++ lda fcsArg0
clc
adc fcsTempPtr
sta fcsArg0
lda fcsArg0+1
adc fcsTempPtr+1
sta fcsArg0+1
; dispatch command
ldy #9
jsr fcsDispatchCmd
;;; DO PORTAMENTO ;;; DO PORTAMENTO
fcsChanDoPorta: fcsChanDoPorta:
; if (chanPortaSpeed[x])
lda chanPortaSpeed,x
beq fcsChanDoArp
; do portamento
sta fcsArg0
lda #0
sta fcsArg0+1
lda chanPortaTarget,x
sta fcsArg1
ldy #8 ; NOTE_PORTA
jsr fcsDispatchCmd
; get out (we can't do porta and arp simultaneously)
rts
;;; DO ARPEGGIO ;;; DO ARPEGGIO
fcsChanDoArp: fcsChanDoArp:
; if (chanArp[x] && !chanPortaSpeed[x])
lda chanArp,x
beq +
; do arpeggio (TODO)
nop
;;; END ;;; END
rts + rts
; x: channel*2 ; x: channel*2
fcsDoChannel: fcsDoChannel:
@ -530,12 +679,7 @@ fcsDoChannel:
sta fcsSendVolume sta fcsSendVolume
sta fcsSendPitch sta fcsSendPitch
; check whether this channel is halted (PC = 0) ; begin processing
lda chanPC,x
ora chanPC+1,x
bne +
rts
; channel not halted... begin processing
; chanTicks-- ; chanTicks--
+ lda chanTicks,x + lda chanTicks,x
sec sec
@ -619,15 +763,18 @@ fcsInit:
; initialize channel stacks ; initialize channel stacks
lda #0 lda #0
ldx #0 ldx #0
ldy #0
- sta chanStackPtr,x - sta chanStackPtr,x
clc clc
adc #FCS_MAX_STACK adc fcsStackSize.w,y
clc
adc fcsStackSize.w,y
inx inx
inx inx
iny
cpx #(FCS_MAX_CHAN*2) cpx #(FCS_MAX_CHAN*2)
bne - bne -
; set volumes ; set volumes
; TODO ; TODO
@ -637,10 +784,7 @@ fcsInit:
; floor(127*sin((x/64)*(2*pi))) ; floor(127*sin((x/64)*(2*pi)))
fcsVibTable: fcsVibTable:
.db 0, 12, 24, 36, 48, 59, 70, 80, 89, 98, 105, 112, 117, 121, 124, 126 .db 12, 24, 36, 48, 59, 70, 80, 89, 98, 105, 112, 117, 121, 124, 126, 127
.db 127, 126, 124, 121, 117, 112, 105, 98, 89, 80, 70, 59, 48, 36, 24, 12
.db 0, -12, -24, -36, -48, -59, -70, -80, -89, -98, -105, -112, -117, -121, -124, -126
.db -126, -126, -124, -121, -117, -112, -105, -98, -89, -80, -70, -59, -48, -36, -24, -12
; COMMAND TABLE ; COMMAND TABLE
; $b4 fcsNoArgDispatch, ; $b4 fcsNoArgDispatch,
@ -957,14 +1101,14 @@ fcsDummyFunc:
rts rts
fcsVolMaxExample: fcsVolMaxExample:
.dw $7f00 .db $7f, $00
.dw $7f00 .db $7f, $00
.dw $7f00 .db $7f, $00
.dw $7f00 .db $7f, $00
.dw $7f00 .db $7f, $00
.dw $7f00 .db $7f, $00
.dw $7f00 .db $7f, $00
.dw $7f00 .db $7f, $00
; first 64 commands ; first 64 commands
fcsCmdTableExample: fcsCmdTableExample: