123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152 |
- SpcHandlerMain:
- php
- sep #$20
- ; stz.w $4200 ;disable irqs in case we are processing a lengthy spc transfer
- ;check if spc sends report data
- lda.w $2141
- and.b #$e0
- cmp.b #$e0
- bne SpcHandlerNoSpcReport
- rep #$31
- lda.w $2141 ;get report type and select corresponding buffer accordingly
- and.w #7
- asl a
- tax
- lda.w $2142 ;get report word and store in buffer
- sta.l SpcReportBuffer,x
- SpcHandlerNoSpcReport:
- rep #$31
- ; sep #$20
- lda.b SpcHandlerState
- and.w #$1f ;have 32 states maximum
- asl a
- tax
- jsr (SpcHandlerSubroutineJumpLUT,x)
-
-
-
-
- sep #$20
- ; lda.b InterruptEnableFlags ;reenable irqs
- ; sta.w $4200
-
- plp
- rts
- ;stops currently playing stream, song, then waits for driver to return to idle state(wait for all scheduled sound effects to play)
- SpcWaitAllCommandsProcessed:
- php
- sep #$20
- stz.w SpcStreamVolume
- jsr SpcStopSong
- SpcWaitLoop:
- lda.b SpcCmdFifoStart
- cmp.b SpcCmdFifoEnd ;check if fifo is empty
- bne SpcWaitLoop
-
- lda.b SpcHandlerState
- cmp.b #1
- bne SpcWaitLoop
-
- plp
- rts
-
- SpcHandlerSubroutineJumpLUT:
- .dw SpcUploadDriver ;0
- .dw SpcIdle
- .dw SpcUploadSong
- .dw SpcUploadSongWait
- .dw SpcUploadSampleset
- .dw SpcUploadSamplesetWait ;5
- .dw SpcStreamData
- .dw SpcStreamDataWait
- .dw SpcPlaySoundeffectUpload
- .dw SpcPlaySoundeffectWait
- .dw SpcStopSongInit ;10
- .dw SpcStopSongWait
- .dw SpcSetSpeedInit
- .dw SpcSetSpeedWait
- .dw SpcSetChMaskInit
- .dw SpcSetChMaskWait ;15
- .dw SpcSetReportTypeInit
- .dw SpcSetReportTypeWait
- SpcSetReportTypeInit:
- rep #$31
- lda.b SpcHandlerArgument0 ;store type and sub-arg
- sta.w $2141
- sep #$20
- lda.b #SpcCmdReportType ;exec command
- sta.w $2140
-
-
- inc.b SpcHandlerState ;goto "wait SE ack"-state
- rts
- SpcSetReportTypeWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdReportType
- bne SpcSetReportTypeWaitNoIdle ;wait until spc has ack'd the speed change before returning
- lda.b #1
- sta.b SpcHandlerState ;return to idle once spc has answered
- SpcSetReportTypeWaitNoIdle:
- rts
- SpcSetChMaskInit:
- sep #$20
- lda.b SpcHandlerArgument0 ;store mask
- sta.w $2141
- lda.b #SpcCmdSetSongChMask ;exec command
- sta.w $2140
-
-
- inc.b SpcHandlerState ;goto "wait SE ack"-state
- rts
- SpcSetChMaskWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdSetSongChMask
- bne SpcSetChMaskWaitNoIdle ;wait until spc has ack'd the speed change before returing
- lda.b #1
- sta.b SpcHandlerState ;return to idle once spc has answered
- SpcSetChMaskWaitNoIdle:
- rts
- SpcSetSpeedInit:
- sep #$20
- lda.b SpcHandlerArgument0 ;store speed
- sta.w $2141
- lda.b #SpcCmdSetSongSpeed ;exec command
- sta.w $2140
-
-
- inc.b SpcHandlerState ;goto "wait SE ack"-state
- rts
- SpcSetSpeedWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdSetSongSpeed
- bne SpcSetSpeedWaitNoIdle ;wait until spc has ack'd the speed change before returing
- lda.b #1
- sta.b SpcHandlerState ;return to idle once spc has answered
-
- SpcSetSpeedWaitNoIdle:
- rts
-
-
- SpcUploadSampleset:
- sep #$20
- lda.b #SpcCmdUploadSamplePack ;send "upload song" command
- sta.w $2140
- lda.b #5
- sta.b SpcHandlerState ;goto "wait for spc to ack song upload" state
- rts
-
- SpcUploadSamplesetWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdUploadSamplePack ;wait until spc has ack'd upload song command
- bne SpcUploadSamplePackWaitExit ;else try again next frame
-
- ; stz.w $4200 ;disable irqs
- ;upload SamplePack here
- lda.b SpcHandlerArgument0 ;get song number to upload
- sta.b PtPlayerCurrentSamplePack
-
- rep #$31 ;multiply song number by 3 and use as index into song pointertable
- and.w #$00ff
- sta.b PtPlayerDataPointerLo
- asl a
- clc
- adc.b PtPlayerDataPointerLo
- tax
- lda.l (PtPlayerSamplePackPointertable+BaseAdress),x ;store pointer to song
- sta.b PtPlayerDataPointerLo
-
- lda.l (PtPlayerSamplePackPointertable+$c00001),x
-
- sta.b PtPlayerDataPointerHi
- ; sep #$20
- ; sta.b PtPlayerDataPointerBa
-
- ; rep #$31
- ldy.w #$0000
- lda.b [PtPlayerDataPointerLo],y ;get song length
- dec a ;substract length word
- dec a
- sta.w PtPlayerSmplBufferPosLo
- iny ;increment source pointer to actual song offset
- iny
- sep #$20
- SpcUploadSamplePackTransfer1:
- lda.b [PtPlayerDataPointerLo],y ;write 3 bytes to ports
- sta.w $2141
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2142
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2143
- iny
-
- lda.b #SpcCmdUploadSongT1 ;write ack transfer 1 to port0
- sta.w $2140
- SpcUploadSamplePackTransfer1WaitLoop: ;wait for spc to write transfer 1 ack back
- cmp.w $2140
- bne SpcUploadSamplePackTransfer1WaitLoop
-
- SpcUploadSamplePackTransfer2:
- lda.b [PtPlayerDataPointerLo],y ;write 3 bytes to ports
- sta.w $2141
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2142
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2143
- iny
-
- lda.b #SpcCmdUploadSongT2 ;write ack transfer 1 to port0
- sta.w $2140
- SpcUploadSamplePackTransfer2WaitLoop: ;wait for spc to write transfer 1 ack back
- cmp.w $2140
- bne SpcUploadSamplePackTransfer2WaitLoop
-
- cpy.w PtPlayerSmplBufferPosLo ;check if transfer length is exceeded
- bcc SpcUploadSamplePackTransfer1
-
- lda.b #SpcCmdUploadSamplePackDone ;send "upload song complete" commadn if transfer is done
- sta.w $2140
-
- lda.b #1
- sta.b SpcHandlerState ;return to idle
- ; lda.b InterruptEnableFlags ;reenable irqs
- ; sta.w $4200
- SpcUploadSamplePackWaitExit:
- lda.b SpcUploadedFlag
- ora.b #$40 ;set sample pack uploaded flag.
- sta.b SpcUploadedFlag
- rts
- SpcStopSongInit:
- rep #$31
- stz.w $2141
- stz.w $2142
- sep #$20
- lda.b #SpcCmdStopSong ;exec command
- sta.w $2140
- inc.b SpcHandlerState ;goto "wait SE ack"-state
- rts
- SpcStopSongWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdStopSong
- bne SpcStopSongWaitNoIdle ;wait until spc has ack'd the song/stream stop before returing
- lda.b #1
- sta.b SpcHandlerState ;return to idle once spc has answered
-
- SpcStopSongWaitNoIdle:
- rts
- SpcPlaySoundeffectUpload:
- rep #$31
- lda.b SpcHandlerArgument0 ;store arguments
- sta.w $2141
- lda.b SpcHandlerArgument1
- and.w #$7fff ;mask off msb and use as wurst
- ora.w SpcSoundEffectFlipFlag
- sta.w $2142
- lda.w SpcSoundEffectFlipFlag
- eor.w #$8000
- sta.w SpcSoundEffectFlipFlag
- sep #$20
- lda.b #SpcCmdPlaySoundEffect ;exec command
- sta.w $2140
-
-
- ; lda.b #1
- ; sta.b SpcHandlerState ;don't wait
- inc.b SpcHandlerState ;goto "wait SE ack"-state
- rts
- ;dont use this cause it sometimes plays a sound effect twice
- SpcPlaySoundeffectWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdPlaySoundEffect
- bne SpcPlaySoundeffectWaitNoIdle ;wait until spc has ack'd the soundeffect before returing
- lda.b #1
- sta.b SpcHandlerState ;return to idle once spc has answered
-
- SpcPlaySoundeffectWaitNoIdle:
- rts
-
-
- SpcUploadDriver:
- sep #$20
- ; stz.w $4200
- lda.b #(:PtplayerSpcCode+BaseAdress>>16)
- ldx.w #PtplayerSpcCode
- sta.b PtPlayerDataPointerBa
- stx.b PtPlayerDataPointerLo
- ; jsr PtPlayerInit
- ; php
- ; sep #$20
- ; stz.w $4200
- REP #$31
- LDY.w #$0000 ;clear data pointer
- LDA.w #$BBAA
- PtPlayerInitSpcWaitLoop1:
- CMP.w $2140 ;wait for spc to respond
- BNE PtPlayerInitSpcWaitLoop1
- SEP #$20
- LDA.b #$CC ;send "start transfer"
- BRA PtPlayerInitDoTransfer
- PtPlayerInitGetByte:
- LDA.b [PtPlayerDataPointerLo],y
- INY
- XBA
- LDA.b #$00
- BRA PtPlayerInitClearSpcPort0
- PtPlayerInitGetNextByte:
- XBA
- LDA.b [PtPlayerDataPointerLo],y
- INY
- XBA
- PtPlayerInitSpcWaitLoop2:
- CMP.w $2140
- BNE PtPlayerInitSpcWaitLoop2
- INC A
- PtPlayerInitClearSpcPort0:
- REP #$20
- STA.w $2140
- SEP #$20
- DEX
- BNE PtPlayerInitGetNextByte
- PtPlayerInitSpcWaitLoop3:
- CMP.w $2140
- BNE PtPlayerInitSpcWaitLoop3
- PtPlayerInitAddLoop:
- ADC.b #$03
- BEQ PtPlayerInitAddLoop
- PtPlayerInitDoTransfer:
- PHA
- REP #$20
- LDA.b [PtPlayerDataPointerLo],y
- INY
- INY
- TAX
- LDA.b [PtPlayerDataPointerLo],y
- INY
- INY
- STA.w $2142
- SEP #$20
- CPX.w #$0001 ;whats this?
- LDA.b #$00
- ROL A
- STA.w $2141
- ADC.b #$7F
- PLA
- STA.w $2140
- cpx.w #$0001 ;fix to be able to upload apucode during active nmi
- bcc PtPlayerInitDone
- PtPlayerInitSpcWaitLoop4:
- CMP.w $2140
- BNE PtPlayerInitSpcWaitLoop4
- BVS PtPlayerInitGetByte
- PtPlayerInitDone:
- SEP #$20
- ; lda.b #%10000001
- ; sta.w $4200
- /*
- lda.b #$7f ;init some variables
- sta.b PtPlayerMainVolL
- sta.b PtPlayerMainVolR
- lda.b #%00001111
- sta.b PtPlayerChannelEnable
- lda.b #$00
- sta.b PtPlayerEchoVolL
- sta.b PtPlayerEchoVolR
- sta.b PtPlayerChannelEchoEnable
- lda.b #$01
- sta.b CGIntroPlaySongNumber
- */
- ; PLP
- lda.b InterruptEnableFlags ;reenable irqs
- ; sta.w $4200
- inc.b SpcHandlerState ;go to idle state
- ;init some variables
- lda.b #$a0
- sta.w SpcSongSpeed ;set speed to default
- lda.b #$0f
- sta.w SpcSongChMask ;set song channel mask to default
- jsr ClearSpcReportBuffer
-
- RTS
-
- ClearSpcReportBuffer:
- php
- rep #$31
- lda.w #$0000 ;clear with y-position at line 255
- ldx.w #16
- ClearSpcReportBufferLoop:
- sta.l (SpcReportBuffer &$ffff + $7e0000-2),x
- dex
- dex
- bne ClearSpcReportBufferLoop
- plp
- rts
-
- ;check if there's a new command in the fifo, else return
- ;fifo buffer organization is:
- ;each entry: 1 command byte, 3 argument bytes
- ;fifo has 16 entries/64bytes total
- SpcIdle:
- sep #$20
- stz.w $2140 ;clear port0
-
- lda.b SpcCmdFifoStart
- cmp.b SpcCmdFifoEnd ;check if fifo is empty
- beq SpcIdleFifoEmpty
-
- ;theres a spc command present:
- rep #$31
- and.w #$3f ;limit fifo pointer to 64 bytes
- tax
- lda.w SpcCmdFifo,x ;get command
-
- sta.b SpcHandlerState ;store command/state and argument 1
-
- lda.w SpcCmdFifo+2,x ;get command
-
- sta.b SpcHandlerArgument1 ;store arguments 1 and 2
- lda.b SpcHandlerState ;directly execute fetched command
- and.w #$1f ;except when its an idle command
- cmp.w #1 ;because this would allow for unlimited nesting and possibly stack overflow
- beq SpcIdleFifoEmpty
-
- asl a
- tax
- jsr (SpcHandlerSubroutineJumpLUT,x)
-
- sep #$20
- lda.b SpcCmdFifoStart ;goto next fifo entry next frame
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoStart
-
- SpcIdleFifoEmpty:
- rts
-
- SpcUploadSong:
- sep #$20
- lda.b #SpcCmdUploadSong ;send "upload song" command
- sta.w $2140
- lda.b #3
- sta.b SpcHandlerState ;goto "wait for spc to ack song upload" state
- rts
-
- SpcUploadSongWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdUploadSong ;wait until spc has ack'd upload song command
- bne SpcUploadSongWaitExit ;else try again next frame
-
-
- ;upload song here
- ; stz.w $4200
- lda.b SpcHandlerArgument0 ;get song number to upload
- sta.b PtPlayerCurrentSong
-
- rep #$31 ;multiply song number by 3 and use as index into song pointertable
- and.w #$00ff
- sta.b PtPlayerDataPointerLo
- asl a
- clc
- adc.b PtPlayerDataPointerLo
- tax
- lda.l (PtPlayerSongPointertable+BaseAdress),x ;store pointer to song
- sta.b PtPlayerDataPointerLo
-
- lda.l (PtPlayerSongPointertable+$c00001),x
-
- sta.b PtPlayerDataPointerHi
- ; sep #$20
- ; sta.b PtPlayerDataPointerBa
-
- ; rep #$31
- ldy.w #$0000
- lda.b [PtPlayerDataPointerLo],y ;get song length
- dec a ;substract length word
- dec a
- sta.w PtPlayerSmplBufferPosLo
- iny ;increment source pointer to actual song offset
- iny
- sep #$20
- SpcUploadSongTransfer1:
- lda.b [PtPlayerDataPointerLo],y ;write 3 bytes to ports
- sta.w $2141
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2142
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2143
- iny
-
- lda.b #SpcCmdUploadSongT1 ;write ack transfer 1 to port0
- sta.w $2140
- SpcUploadSongTransfer1WaitLoop: ;wait for spc to write transfer 1 ack back
- cmp.w $2140
- bne SpcUploadSongTransfer1WaitLoop
-
- SpcUploadSongTransfer2:
- lda.b [PtPlayerDataPointerLo],y ;write 3 bytes to ports
- sta.w $2141
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2142
- iny
- lda.b [PtPlayerDataPointerLo],y
- sta.w $2143
- iny
-
- lda.b #SpcCmdUploadSongT2 ;write ack transfer 1 to port0
- sta.w $2140
- SpcUploadSongTransfer2WaitLoop: ;wait for spc to write transfer 1 ack back
- cmp.w $2140
- bne SpcUploadSongTransfer2WaitLoop
-
- cpy.w PtPlayerSmplBufferPosLo ;check if transfer length is exceeded
- bcc SpcUploadSongTransfer1
-
- lda.b #SpcCmdUploadSongDone ;send "upload song complete" commadn if transfer is done
- sta.w $2140
-
- lda.b #1
- sta.b SpcHandlerState ;return to idle
- lda.b InterruptEnableFlags ;reenable irqs
- ; sta.w $4200
- SpcUploadSongWaitExit:
- lda.b SpcUploadedFlag
- ora.b #$80 ;set song uploaded flag.
- sta.b SpcUploadedFlag
- rts
- ;stops currently playing song/stream
- SpcStopSong:
- php
- rep #$31
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
- sep #$20
- ; sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdStopSong
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
- plp
- rts
- ;in: a,8bit: SE number to play
- ; x,16bit: volume & pitch low byte: pitch(use default if zero, multiplied by 16). high byte: volume(use default if zero) bit7:sign, bits6-4:panning, bits 3-0:volume(multiplied with $10)
- SpcPlaySoundEffect:
- php
- rep #$31
- pha ;push SE number
- phx ;push arguments
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
- pla ;get arguments
- sta.w (SpcCmdFifo+2),x ;store in fifo arguments 2,3
-
- pla ;fetch song number again
- sep #$20
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdPlaySE
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
- plp
- rts
- ;same as above, but doesn't use x as input
- SpcPlaySoundEffectSimple:
- php
- rep #$31
- phx ;push arguments
- pha ;push SE number
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
- lda.w #0
- sta.w (SpcCmdFifo+2),x ;store in fifo arguments 2,3
-
- pla ;fetch song number again
- sep #$20
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdPlaySE
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
- plx
- plp
- rts
- ;in: a,8bit: song number to play
- SpcPlaySong:
- php
- rep #$31
- pha ;push song number
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
-
- pla ;fetch song number again
- sep #$20
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdUploadSong
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
-
- stz.w SpcStreamVolume ;mute eventually playing stream, stop stream
-
- lda.b SpcUploadedFlag
- and.b #$7f ;clear song uploaded flag. will be set once song upload has been completed later on
- sta.b SpcUploadedFlag
- ; lda.b SpcCurrentStreamSet ;useful, but messes up if sampleset + song dont fit into spc ram
- ; jsr SpcIssueSamplePackUpload
- plp
- rts
- ;in: a,8bit: streamset number to play
- SpcPlayStream:
- php
- sep #$20
- pha
- rep #$31
- stz.w SpcStreamFrame
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
-
- sep #$20
- pla ;store frameset number
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdStreamBrr
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
- sep #$20
- stz.w SpcStreamVolume ;mute eventually playing stream, stop stream
- plp
- rts
-
-
- ;in: a,8bit: sample pack number to upload
- SpcIssueSamplePackUpload:
- php
- rep #$31
- pha ;push song number
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
-
- pla ;fetch song number again
- sep #$20
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdUploadSamplePack
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
- lda.b SpcUploadedFlag
- and.b #$bf ;clear sample pack uploaded flag. will be set once song upload has been completed later on
- sta.b SpcUploadedFlag
-
- plp
- rts
- SpcStreamData:
- sep #$20
- lda.b #$7f ;turn on streaming volume
- sta.w SpcStreamVolume
-
- lda.b SpcHandlerArgument0 ;get frameset number to stream
- sta.b SpcCurrentStreamSet ;multiply by 5 to get pointer into frameset table
- rep #$31
- and.w #$ff
- sta.b SpcTempBuffer
- asl a
- asl a
- clc
- adc.b SpcTempBuffer
-
- tax
- lda.l (StreamSetLut+BaseAdress+3),x ;get number of frames for this set
- sta.w $2141 ;write number of frames to stream to spc
-
-
- sep #$20
- lda.b #SpcCmdReceiveStream ;send "upload song" command
- sta.w $2140
- lda.l $2140
- cmp.b #SpcCmdReceiveStreamComplete ;don't switch to streamer yet if spc is still finishing the last transfer.(only applicable if last command was streaming)
- beq SpcStreamDataWaitSpcLastStream
-
- lda.b #7
- sta.b SpcHandlerState ;goto "wait for spc to ack song upload" state
-
- SpcStreamDataWaitSpcLastStream:
- rts
- SpcStreamDataReturnIdle:
- sep #$20
- lda.b HdmaFlags
- and.b #$7f ;disable spc stream on hdma channel 7
- sta.b HdmaFlags
- lda.b #1 ;return to idle if spc signalizes that transfer is complete
- sta.b SpcHandlerState
- SpcStreamDataExit:
- rts
-
- SpcStreamDataWait:
- sep #$20
- lda.w $2140
- cmp.b #SpcCmdReceiveStreamComplete ;check if transfer complete
- beq SpcStreamDataReturnIdle
- cmp.b #SpcCmdReceiveStream ;wait until spc has ack'd upload song command
- bne SpcStreamDataExit ;else try again next frame
-
-
- lda.b SpcCurrentStreamSet ;get current frameset number
- rep #$31
- and.w #$ff
- sta.b SpcTempBuffer ;multiply by 5
- asl a
- asl a
- clc
- adc.b SpcTempBuffer
-
- tax
- lda.l (StreamSetLut+BaseAdress),x ;store offset of first frame in set
- sta.b SpcTempBuffer+2
- lda.l (StreamSetLut+BaseAdress+1),x
- sta.b SpcTempBuffer+3
-
- lda.w $2141 ;get frame request number
- ;multiply with 144, get pointer to requested frame. warning: one bank holds $1c7 frames, or $fff0 bytes of data. must wrap to next bank if bigger.
- sta.b SpcTempBuffer+5 ;store frame request number
- sta.w SpcStreamFrame
- pha
- lda.w SpcStreamVolume ;only write current frame if stream hasnt been stopped. otherwise external routines might be confused when transitioning between streams
- and.w #$ff
- bne DontClearSpcStreamFrame
-
- stz.w SpcStreamFrame
-
- DontClearSpcStreamFrame:
- pla
- SpcStreamCalcFrameOffsetLoop:
- cmp.w #SpcFramesPerBank ;check if number of frames exceeds bank limit
- bcc SpcStreamCalcFrameOffsetNoBankWrap
- sep #$20 ;if it does, increase bank
- inc.b SpcTempBuffer+4
- rep #$31 ;and substract one bank full of samples from total amount
- sec
- sbc.w #SpcFramesPerBank
- bra SpcStreamCalcFrameOffsetLoop ;do this until we're in the bank the frame actually is in
- SpcStreamCalcFrameOffsetNoBankWrap:
-
- asl a ;multiply by 144
- asl a
- asl a
- asl a ;first multiply by 16
- sta.b SpcTempBuffer+2
-
- asl a ;then by 128
- asl a
- asl a
-
- clc
- adc.b SpcTempBuffer+2 ;this is x*144
- sta.b SpcTempBuffer+2 ;and save in pointer
- ;line 1, command
- lda.w #36/2
- sta.b SpcTempBuffer ;set scanline counter
- lda.w #SpcScanlineWaitCount ;store 1 in frame count
- ldx.w #0 ;clear hdma table pointer
- txy ;clear brr source counter
-
- sta.l HdmaSpcBuffer,x
- lda.w #SpcCmdSubmitStreamNumber ;send "submit frame #"-cmd
- sta.l HdmaSpcBuffer+1,x
-
- lda.b SpcTempBuffer+5 ;get frame submit number
- sta.l HdmaSpcBuffer+2,x
- lda.w SpcStreamVolume
- sta.l HdmaSpcBuffer+4,x ;store volume
-
- inx
- inx
- inx
- inx
- inx
- ;line 2, waitloop & frame transmit
- SpcStreamSetupHdmaTableLoop:
- lda.w #1
- sta.l HdmaSpcBuffer,x ;one line
-
- lda.b [SpcTempBuffer+2],y ;brr data to ports $2140-$2143
- sta.l HdmaSpcBuffer+1,x
- iny
- iny
-
- lda.b [SpcTempBuffer+2],y
- sta.l HdmaSpcBuffer+3,x
- inx
- inx
- inx
- inx
- inx
-
- ; iny
- ; iny
- iny
- iny
- lda.w #1
- sta.l HdmaSpcBuffer,x ;one line
-
- lda.b [SpcTempBuffer+2],y ;brr data to ports $2140-$2143
- sta.l HdmaSpcBuffer+1,x
- iny
- iny
-
- lda.b [SpcTempBuffer+2],y
- sta.l HdmaSpcBuffer+3,x
- inx
- inx
- inx
- inx
- inx
-
- ; iny
- ; iny
- iny
- iny
- dec.b SpcTempBuffer
- bne SpcStreamSetupHdmaTableLoop
- ;this doesnt work right. reason is that the the stream data sometimes contains "false" commands.
- ;write spc command here: (only play soundeffect, stop song/stream is allowed here)
- stz.b SpcTempBuffer ;clear spc command field
- stz.b SpcTempBuffer+2
- /*
-
- lda.b SpcCmdFifoStart
- cmp.b SpcCmdFifoEnd ;check if fifo is empty
- beq SpcStreamFifoEmpty
-
- ;theres a spc command present:
- rep #$31
- and.w #$3f ;limit fifo pointer to 64 bytes
- tax
- lda.w SpcCmdFifo,x ;get command
- and.w #$ff
- cmp.w #SpcCmdPlaySoundEffect
- beq SpcStreamFifoExecCmd
- cmp.w #SpcCmdStopSong
- beq SpcStreamFifoExecCmdExit
-
- bra SpcStreamFifoEmpty
- SpcStreamFifoExecCmdExit:
- sep #$20
- lda.b #1
- sta.b SpcHandlerState ;if stop command is present in fifo, immediately halt streamer and return to idle state. next frame, fifo command handler will process the stop command normally.
- rts
- SpcStreamFifoExecCmd:
- ;state
- lda.w SpcCmdFifo,x ;get command
- sta.b TempBuffer ;store command/state and argument 1
-
- lda.w SpcCmdFifo+2,x ;get command
-
- sta.b TempBuffer+2 ;store arguments 1 and 2
-
- sep #$20
- lda.b SpcCmdFifoStart ;goto next fifo entry next frame
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoStart
-
- SpcStreamFifoEmpty:
- rep #$31
- */
- lda.w #1
- sta.l HdmaSpcBuffer,x ;one line
-
- lda.b SpcTempBuffer
- sta.l HdmaSpcBuffer+1,x
-
- lda.b SpcTempBuffer+2
- sta.l HdmaSpcBuffer+3,x
- inx
- inx
- inx
- inx
- inx
- ;terminate hdma table:
- lda.w #0
- sta.l HdmaSpcBuffer,x
-
- lda.w #HdmaSpcBuffer & $ffff
- sta.l $4372 ;hdma source offset
-
- sep #$20
- lda.b HdmaFlags
- ora.b #$80 ;enable spc stream on hdma channel 7
- sta.b HdmaFlags
-
- lda.b #$7e ;hdma source bank
- sta.l $4374
-
- lda.b #%00000100 ;hdma config, direct, 4 regs write once
- sta.l $4370
-
- lda.b #$40 ;bbus target, apu port $2140-$2143
- sta.l $4371
-
- rts
-
- ;in: SpcSongSpeed,8bit: song speed(timer duration. default is #$a0. lower=faster, higher=slower
- SpcSetSongSpeed:
- php
- rep #$31
- ; pha ;push speed
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
-
- ; pla ;fetch speed again
- sep #$20
- lda.w SpcSongSpeed
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdSetSpeed
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
-
- ; stz.w SpcStreamVolume ;mute eventually playing stream, stop stream
-
- ; lda.b SpcCurrentStreamSet ;useful, but messes up if sampleset + song dont fit into spc ram
- ; jsr SpcIssueSamplePackUpload
- plp
- rts
- ;in: SpcSongSpeed,8bit: song speed(timer duration. default is #$a0. lower=faster, higher=slower
- SpcSetSongChannelMask:
- php
- rep #$31
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
-
- sep #$20
- lda.w SpcSongChMask
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdSetChMask
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
-
- plp
- rts
- ;input: SpcReportType,8bit: 0=none 1=timecode 2=channel-levels(vol out) 3=special mod command (mod command $e0. this is "set filter", unused in almost any player
- SpcSetReportType:
- php
- rep #$31
- lda.b SpcCmdFifoEnd ;get current position in spc command fifo buffer
- and.w #$ff
- tax
-
- sep #$20
- lda.w SpcReportType
- and.b #$07 ;8 types max
- sta.w (SpcCmdFifo+1),x
- lda.b #SpcFifoCmdSetReportType
- sta.w SpcCmdFifo,x
-
- lda.b SpcCmdFifoEnd
- clc
- adc.b #4
- and.b #$3f ;16x4byte entries maximum
- sta.b SpcCmdFifoEnd
-
- plp
- rts
-
- ;legacy code:
- PtPlayerInit:
- PtPlayerMainHandler:
- PtPlayerUploadVolEcho:
- rts
-
- ;plays sound effect with panning set to current objects x-position
- SpcPlaySoundEffectObjectXPos:
- php
- rep #$31
- pha
- ldx.b ObjectListPointerCurrent
- lda.w ObjEntryXPos,x ;get upper 4 nibbles of x-pos
- lsr a ;remove subpixel prec
- lsr a
- lsr a
- lsr a
-
- lsr a ;use bits 6-4 for panning
- and.w #$7f ;clear sign
- ora.w #$0F ;set max volume
- xba
- tax
- pla
- sep #$20
- jsr SpcPlaySoundEffect
-
-
-
- plp
- rts
-
|