SPC data upload

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
Post Reply
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

SPC data upload

Post by mic_ »

Ok, here's another problem: I'm trying to upload data to the SPC using the code available at the SNES Programming wiki. It works fine in Snes9x (at least for the first upload), but it hangs on a real SNES. After placing some printouts in the code I've come to the conclusion that it most likely hangs in this loop which does the actual data transfer:

Code: Select all

CopyBlockToSPC_loop:
	; Load the high byte of a with the destination byte.
	xba
	lda     [musicSourceAddr],y
	xba

	; Load the low byte of a with the counter.
	tya

	; Send the counter/byte.
	rep     #A_8BIT
	sta     AUDIO_R0
	sep     #A_8BIT

	; Wait for counter to echo back.
	waitForAudio0M

	; Update counter and number of bytes left to send.
	iny
	dex
	bne     CopyBlockToSPC_loop
The waitForAudio0M macro simply does -: cmp AUDIO_R0 / bne -
I really don't know why this would hang. Interrupts are disabled at this point, and the data to transfer is in RAM.

Any ideas?
User avatar
Memblers
Site Admin
Posts: 3901
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

Is this communicating with the SPC's built-in loader, or a different loader? Because that seems too simple to be for the initial loader. I could dig up the code I used if it'd help.

It also may be useful to disassemble the 64-byte ROM built in to the SPC, to see the loader itself.
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

Post by mic_ »

I assume it's using some built-in loader since it doesn't send anything else to the SPC prior to this. Note that I only pasted the loop where I suspect that it hangs, but the program doesn't just enter that loop right away. There's some initial hand-shaking, setting the destination address etc.

If you have some SPC communication code that you know works on a real SNES then that'd be helpful, sure.
orwannon
Posts: 40
Joined: Fri Feb 20, 2009 10:07 am

Post by orwannon »

mic_ wrote:If you have some SPC communication code that you know works on a real SNES then that'd be helpful, sure.
You might want to check out d4s's N-Warp Daisakusen Sourcecode. It contains a full-fledged SPC700 mod player. Have fun. :)
User avatar
Memblers
Site Admin
Posts: 3901
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

Here is another thread with the code and more info:
http://nesdev.com/bbs/viewtopic.php?t=5362
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

Post by mic_ »

Using BSNES (0.60) I've managed to track down what's happening, though I haven't yet figured out why.

After 240 bytes have been transfered (it always happens after 240 bytes regardless of what block size I use) the value that the SPC writes to Port0 fails to get mirrored on the SNES side, so the S-CPU gets stuck in an infinite loop waiting for the SPC to mirror the last value written by the S-CPU.

Here's a trace done with BSNES. I've replaced the SPC output with the actual instructions, since the BSNES debugger only outputs NOPs for the SPC for some reason. The block size I used here was $E0, so that's why Y=$10 when it freezes ($E0+$10 = $F0 = 240 bytes).

Code: Select all

..ffe4 inc   y                    A:ff X:01 Y:0e SP:01ef YA:0eff NvpbhizC
00848d cpy #$00e0             A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzC V:230 H:1116
008490 beq $84ab     [0084ab] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:230 H:1140
..ffe5 bne $ffda                    A:ff X:01 Y:0f SP:01ef YA:0fff nvpbhizC
008492 lda [$fd],y   [7f00f1] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:230 H:1156
008494 sta $2141     [002141] A:0031 X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:230 H:1204
008497 tya                    A:0031 X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:230 H:1234
..ffda cmp y,Port0                    A:ff X:01 Y:0f SP:01ef YA:0fff nvpbhizC
008498 sta $2140     [002140] A:000f X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:230 H:1248
00849b sta $f1       [0000f1] A:000f X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:230 H:1278
..ffdc bne $ffe9                    A:ff X:01 Y:0f SP:01ef YA:0fff nvpbhiZC
00849d lda $2140     [002140] A:000f X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:230 H:1302
0084a0 cmp $f1       [0000f1] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:230 H:1332
..ffde mov a,Port1                    A:ff X:01 Y:0f SP:01ef YA:0fff nvpbhiZC
0084a2 bne $849d     [00849d] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:230 H:1356
00849d lda $2140     [002140] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H:  14
..ffe0 mov Port0,y                    A:31 X:01 Y:0f SP:01ef YA:0f31 nvpbhizC
0084a0 cmp $f1       [0000f1] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:231 H:  44
0084a2 bne $849d     [00849d] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H:  68
00849d lda $2140     [002140] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H:  90
0084a0 cmp $f1       [0000f1] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:231 H: 120
..ffe2 mov [DestAddr]+y,a                    A:31 X:01 Y:0f SP:01ef YA:0f31 nvpbhizC
0084a2 bne $849d     [00849d] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H: 144
00849d lda $2140     [002140] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H: 166
0084a0 cmp $f1       [0000f1] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:231 H: 196
0084a2 bne $849d     [00849d] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H: 220
00849d lda $2140     [002140] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H: 242
..ffe4 inc y                    A:31 X:01 Y:0f SP:01ef YA:0f31 nvpbhizC
0084a0 cmp $f1       [0000f1] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:231 H: 272
0084a2 bne $849d     [00849d] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H: 296
..ffe5 bne $ffda                    A:31 X:01 Y:10 SP:01ef YA:1031 nvpbhizC
00849d lda $2140     [002140] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 NvMxdIzc V:231 H: 318
0084a0 cmp $f1       [0000f1] A:000e X:fecf Y:000f S:1ff9 D:0000 DB:00 nvMxdIzc V:231 H: 348
As you can see on the line ..ffe0 mov Port0,y A:31 X:01 Y:0f SP:01ef YA:0f31 nvpbhizC, the SPC actually writes $0f to Port0, but the S-CPU still keeps getting $0e when reading Port0 after that no matter how many times it tries.
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

Post by mic_ »

Ack.. Now it became obvious why it happens after 240 bytes. $F0 is Port0 on the SPC side, so it's overwriting the real value of Port0.
bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy »

This is the same thing I was fighting with last week!

F0 is the test register, I figured its best to just not touch it.

F1 can disable the IPL, so make sure you keep D7 set when you write to it. It can also clear the IO ports which probably will do bad stuff.

F2/F3 are the DSP regs, to be used later

F4-F7 are the IO ports, which you also shouldn't touch.

I got all this working on real hardware, but the DSP register uploads would frequently stall. No idea whats going wrong and debugging messages would make it happen more often.
Near
Founder of higan project
Posts: 1553
Joined: Mon Mar 27, 2006 5:23 pm

Post by Near »

mic_ wrote:the BSNES debugger only outputs NOPs for the SPC for some reason.
The debugger can't call any of the memory access functions that consume time or affect I/O states, specifically I need to avoid $f0-ff, just as you found out in this case :)

But the same function that reads $f0-ff also handles the switch to override reading $ffc0-ffff when the IPLROM is enabled.

So the debugger only reads from raw APURAM, bypassing the IPLROM enable bit for now.

I do need to come up with a workaround, of course. It's quite annoying seeing NOPs for the initial loading.
User avatar
blargg
Posts: 3717
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Here's a short set of routines for uploading and executing data on the SPC-700: spc_util.s

For example, to do the following:

upload $1234 bytes of data from $7E1200 in main RAM to $5678 in the SPC
upload $2345 bytes of data from $7F1111 in main RAM to $4321 in the SPC
execute at $7654 in the SPC

do this:

ldy #$5678 ; addr in SPC
jsr spc_first_addr

ldx #$1234 ; length
lda #$7E ; 24-bit addr
ldy #$1200
jsr spc_upload

ldy #$4321 ; addr in SPC
jsr spc_next_addr

ldx #$2345 ; length
lda #$7F ; 24-bit addr
ldy #$1111
jsr spc_upload

ldy #$7654 ; exec addr in SPC
jsr spc_execute
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

Post by mic_ »

Here's another fun fact: if you're initializing the DSP registers with data from an .SPC file you need to do it in reverse order (or at least make sure that you write to register $6D (ESA) before register $6C (FLG)).

If you write a value with bit5==0 to FLG it seems like the echo buffer will begin to be filled with data almost immediately. If ESA hasn't been initalized to a proper value at that point, the DSP will write echo data starting at $0000, which makes the IPL routine go crazy since it uses the word at $0000 as a buffer for indirect writes/jumps.

This was confusing me a bit at first, since the fact that the DSP was overwriting $0000 meant that it would go undetected by the breakpoint I had put on writes to $0000 over the S-SMP bus :P
bunnyboy
Posts: 449
Joined: Thu Oct 27, 2005 1:44 pm
Location: CA
Contact:

Post by bunnyboy »

Thats great info! Will have to try it out with my loader. Would bet there are lots more little problems like that when loading SPCs on real hardware. Someone needs to make a good NSF type ripped format instead...
mic_
Posts: 922
Joined: Thu Oct 05, 2006 6:29 am

Post by mic_ »

There is a format like that. It's called SNSF, but it's not widely used.
User avatar
Bregalad
Posts: 8036
Joined: Fri Nov 12, 2004 2:49 pm
Location: Caen, France

Post by Bregalad »



Thats great info! Will have to try it out with my loader. Would bet there are lots more little problems like that when loading SPCs on real hardware. Someone needs to make a good NSF type ripped format instead...
Will a SPC player be added to the super powerpak ? I'd be great :P
Else I think there is already a programm called SPC2ROM or something I've used it before so if it works on real HW it'd do the trick too altough it'd be a slower process.
Useless, lumbering half-wits don't scare us.
User avatar
Memblers
Site Admin
Posts: 3901
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

bunnyboy wrote:Someone needs to make a good NSF type ripped format instead...
Yeah, seriously. SPC format is perfect if you want to play something just on the actual sound module (like this), but it's not really an SNES format because it excludes most of the SNES.
Post Reply