I have two different issues I can't seem to figure out:
Issue 1:
I have a version of SNESMod that never pushes anything to the stack (except calls of course but it's not like there are a ton of nested calls). In this driver I put 144 bytes of sample data starting at 0100h. This works fine for most of my songs but there are a couple where it is fine for half of the song and than at a certain point something occurs and the stack stops hovering around 235-237 and keeps dropping very rapidly wiping out the 144 bytes at 0100h, continuing to decrease and wraparound endlessly. Other than losing that sample data, the song continues to play fine.
Although I only know the value of the stack register with the SPC player, the samples at 0100h do get destroyed in every emulator I've tried and on real hardware. Other songs tested did not have this issue. Any thoughts on what would cause this to occur? Everything else about the song plays perfectly fine so if it's some sort of bug it is only specific to whatever is going on with the stack. (I've been looking over song data but there was nothing especially noteworthy about this song it uses all of the same commands as other songs I've tested use.)
Anyway, it's not the biggest deal, but it would be nice to save some bytes for module data. In the mean time I've gone back to storing that particular sample data outside of stack space. Maybe this is something that is not possible to do...
Issue 2:
I set up a system to swap out 144 bytes (8 32 sample BRR) in SNESMod. This is stored outside of stack space. It works. Kind of. Here is the test I ran:
1: load sample
2: play module
3: change sample data
4: jump to previous pattern
repeat 3-4
The first two transfers always work, the third is unsuccessful, the fourth transfer works, and after that only the 2nd and 4th transfers are successful. When a transfer is unsuccessful, the result is either a short burst of noise or what sounds like a low pitch sine-ish waveform.
Ideally, I would like to be able to change samples at any time that a song is playing. I'm not sure what the proper way to do this is. If anybody has suggestions for what I should (or shouldn't) be doing that would be helpful. I thought about modifying the SPC streaming code from SNESMod for this task if I can't get it to work using this code, but I'd like to understand why this method isn't working consistently.
code on the SNES side:
Code:
; increment memory pointer by 2
.macro incptr
.scope
iny
iny
bne _catch_overflow
inc spc_ptr+2
_catch_overflow:
.endscope
.endmacro
;----------------------------------------------------------------------
spcLoadSample: ; y = sample address
;----------------------------------------------------------------------
phx
jsr spcFlush ; flush fifo!
plx
sty z:spc_ptr
lda sample_bank
sta z:spc_ptr+2
lda z:spc_v ; wait for spc
pha
: cmp REG_APUIO1
bne :-
lda #CMD_SAMPLE ; send SAMPLE message
sta REG_APUIO0
pla
eor #80h
ora #01h
sta z:spc_v
sta REG_APUIO1
: cmp REG_APUIO1 ; wait for spc
bne :-
ldx #144/2 ; x = word length
ldy #0 ; y = index
jsr do_transfer
rts
;--------------------------------------------------------------
; spc_ptr+y: source address
; x = length of transfer (WORDS)
;--------------------------------------------------------------
transfer_again:
eor #80h
sta REG_APUIO1
sta spc_v
incptr
: cmp REG_APUIO1
bne :-
;--------------------------------------------------------------
do_transfer:
;--------------------------------------------------------------
rep #20h ; transfer 1 word
lda [spc_ptr], y
sta REG_APUIO2
sep #20h
lda spc_v
dex
bne transfer_again
incptr
end_transfer:
lda #0 ; final word was transferred
sta REG_APUIO1 ; write p1=0 to terminate
sta spc_v
: cmp REG_APUIO1
bne :-
sta spc_pr+1
rts
code on the SPC-700 side:
Code:
;-------------------------------------------------------------------
CopySample:
;-------------------------------------------------------------------
mov xfer_address, #Sample01&0ffh
mov xfer_address+1, #Sample01>>8
call StartTransfer
mov SPC_PORT1, comms_v
ret
;-------------------------------------------------------------------
StartTransfer:
;-------------------------------------------------------------------
mov x, comms_v ; start transfer
mov y, #0
mov SPC_PORT1, x
;-------------------------------------------------------------------
DoTransfer:
;-------------------------------------------------------------------
cmp x, SPC_PORT1 ; wait for data
beq DoTransfer
mov x, SPC_PORT1
mov a, SPC_PORT2 ; copy data
mov [xfer_address]+y, a
mov a, SPC_PORT3
mov SPC_PORT1, x ;<- reply to snes
inc y
mov [xfer_address]+y, a
inc y
beq _inc_address ; catch index overflow
_cont1: cmp x, #0 ; loop until x=0
bne DoTransfer
mov m0, y
clrc
adc xfer_address, m0
adc xfer_address+1, #0
mov comms_v, x
ret
_inc_address:
inc xfer_address+1
bra _cont1