Page 1 of 2

APU I/O ports, TV cycles, Cx4 and other miscellaneous things

Posted: Wed Jul 01, 2009 3:21 pm
by Gekko
1) Every document I've come across that deals with the APU I/O ports go over the SNES side briefly, not giving me enough information on what format I should upload the data in, and normally, how I should upload it. (I do have the latter information now but I'm unsure if I'm thinking of it properly)
As such, I want to know what the format the data is uploaded in or preferably a clear explanation of what you are doing at any step, as opposed to merely saying "copy a byte here" or whatever. An example of what I don't want is here.
2) This is simply statistical. Anyway, I want to know how long the following take, in terms of FastROM master clock cycles, although machine cycles and non-FastROM (SlowROM?) would be acceptable too.
Anyway, the things I want this data for, are: V-blank, H-blank and the difference between H-blanks (time to go from the beginning of a scanline to the end of it).

Any help would be appreciated, greatly!

Posted: Wed Jul 01, 2009 3:45 pm
by Memblers
1. I found the explanations to be confusing, too. There's nothing special about the data format, but what was helpful to me was just to disassemble the internal ROM of the SPC. It's only 64 bytes I think, you can extract it from any .SPC file. I found the code much easier to follow than any explanations of the loading process. You only need to use that once, then you can communicate any way you want (from within your loaded code).

Posted: Wed Jul 01, 2009 4:42 pm
by Gekko
If I understand your post properly, you think I'm talking about the SPC700 data as opposed to the format that the SNES stores it in. (Correct me if I'm wrong.) In the SNES Development manual, I got the following information before hand:
1) The first word is the length of the block
2) The second word is the address of the block
3) The rest is the SPC700 data.
What I want to know is:
1) What is that address for? Is it for where the SPC700 puts it in its RAM/cache/whatever it is? (I'm not well versed in SPC700. In fact, I'm still learning it. It's just I'm asking for information on the SNES side, not the SPC700 side).
2) How is the SPC700 data sent? I'm pretty sure it would just be on word at a time but would that be reversed byte order (little-endian) or standard order (big-endian).
In addition, I want to know what exactly you are inputing into the APU I/O ports.
Sorry for not being clear enough before hand! (And not realizing what exactly it was that I wanted)

Posted: Wed Jul 01, 2009 5:12 pm
by Memblers
I don't remember about the endien-ness. It's been years since I've used the SPC. I don't know why, but I can't find that part of my source code (just a broken commented out one). If that code was right, the data is sent as bytes. And you're right about the address.

Posted: Wed Jul 01, 2009 5:15 pm
by Memblers
oh nevermind, I found what I did. i ripped someone else's code.

Code: Select all

;Sound.ASM
;
;Support routines for the SPC700
;(C) 1999 Realtime Simulations and Roleplaying Games
;
;Grog's worst nightmares come true with this bloody CPU

InitSoundCPU:
        phk
        plb
        php
        rep #$30
        sep #$20
        .mem 8
        .index 16

        ldx #$0400      ;Target SPC address for program
        stx $2142
        ldx #$0000
        lda #$01
        sta $2141
        lda #$CC
        sta $2140
-       cmp $2140       ;Wait for SPC to sync
        bne -

        SoundSendLoop:
        lda spcprogg,X
        sta $2141       ;Set the address
        txa
        sta $2140       ;Set the data
-       cmp $2140
        bne -           ;Wait for SPC to sync
        inx
        cpx #spcend-spcprogg   ;Check for last data byte
        bne SoundSendLoop

        stz $2141       ;Mark end of data
        ldy #$0400      ;Set starting address of SPC code
        sty $2142
        inx
        inx
        txa
        sta $2140       ;Tell SPC to begin executing its program

        plp
        rtl

spcprogg:
.incbin "SPC.obj"
;.incbin "FLUTEC4.BRR"
;.incbin "MOO.BRR"
spcend:
        .dcb $FF

Posted: Wed Jul 01, 2009 7:29 pm
by Gekko
O.K., a few things.
1) While this is definitely easier to understand than the other routines I've seen, I am going more for an actual understanding of the ports. It doesn't matter much but it might be nice. (After all, having a routine isn't like knowing what the routine does.)
2) Why did you never check $2140 to be #$AA and $2141 to be #$BB? I recall that being the SPC700's signal that it is ready. Do you assume that someone already did that?
3) What is spcend-spcprogg?
4) Just in case you were wondering, little-endian reverses the byte order. (so the highest address would store the highest byte and the lowest address would store the lowest byte) while big-endian is what we would expect, namely the lowest byte is at the highest address and the highest byte would be stored at the lowest address.

Yet again, I apologize for a lack of clarity and any such examples to be shown in the future.

Posted: Thu Jul 02, 2009 5:56 pm
by Memblers
1. IIRC, you can only write 8-bits to the port at a time. I'm not sure what else I can add. I couldn't locate the disassembly of the SPC's ROM. I did have another routine in my SNES program, to transfer data to it every frame (and definitely not using the internal loader thing), I could dig that out if that'd be useful.

2. I didn't write that particular routine, but the one I did write did check for #$AA and #$BB like the docs say, but it apparently didn't work because I commented it all out. Seems it can be ignored. I'm guessing it may be for when games want to re-use that loader routine later (for further data, samples, etc.).

3. The "spc.obj" file there is a binary, it's the whole SPC program/data, assembled with TASM (table assembler). spcend-spcprogg lets it calculate the filesize.

Posted: Thu Jul 02, 2009 6:26 pm
by Gekko
1) Well, don't worry about it. I looked over the places I previously found information and that helped me understand even further.

2) What do you mean? Do you mean sound effects or different music? Also, should I add a

Code: Select all

LDA #$BBAA
CMP $2140
BEQ $02 ;Skip the PLP and RTL or RTS
PLP
RTL ;or RTS
between the REP #$30 and the SEP #$20?

3) That clears that one up!

Another thing, though: It just occurred to me that that routine sets the address manually. Does this mean that if I were to use multiple sounds, (as in sound effects and music at the same time) I would want to use indexed pointers, for example?

Also, thank you for your great help!

Posted: Thu Jul 02, 2009 6:57 pm
by Memblers
2. I mean music, code, basically anything.

For doing music/sfx at the same time, really you'll want all the sample data to be preloaded in SPC's RAM. Then have some variables that you transfer to the SPC every frame, to trigger the sound effects. I suppose you could reuse that loader thing to transfer a few variables, but it seems kinda slow and complicated.

The debugger in old ZSNES was really helpful when I was working on communications since it could step through the code for both CPUs at the same time.

Gekko wrote:ean? Do you mean sound effects or different music? Also, should I add a

Code: Select all

LDA #$BBAA
CMP $2140
BEQ $02 ;Skip the PLP and RTL or RTS
PLP
RTL ;or RTS
between the REP #$30 and the SEP #$20?
I'd highly suspect a 16-bit access won't work, as the port is probably an 8-bit link between the chips.

Posted: Thu Jul 02, 2009 7:47 pm
by Gekko
Memblers wrote:I'd highly suspect a 16-bit access won't work, as the port is probably an 8-bit link between the chips.
Actually, I've seen it before, even in a commercial games.

Anyway, thank you for taking so much time to answer my questions!

If anyone could answer my other question, I would be thankful as well.

Posted: Thu Jul 02, 2009 10:22 pm
by koitsu
Memblers wrote:
Gekko wrote:Also, should I add a

Code: Select all

LDA #$BBAA
CMP $2140
BEQ $02 ;Skip the PLP and RTL or RTS
PLP
RTL ;or RTS
between the REP #$30 and the SEP #$20?
I'd highly suspect a 16-bit access won't work, as the port is probably an 8-bit link between the chips.
The CMP in question would actually read 8 bits from $2140 (APU_PORT_0) and $2141 (APU_PORT_1). So the ""16-bit read"" method should work just fine. The official developers manual even uses to this method in example SPC bootloader code; see Section D.4 (of manual revision A, dated 1992/05/01).

And yes, you should wait for APU_PORT_0==$AA and APU_PORT_1==$BB before doing transferring any data to/from the SPC.

Posted: Fri Jul 03, 2009 6:41 am
by Memblers
koitsu wrote: And yes, you should wait for APU_PORT_0==$AA and APU_PORT_1==$BB before doing transferring any data to/from the SPC.
A couple guys built my NSF player on a cartridge, and it worked. Looks like I run InitSoundCPU somewhat early in reset, too (after RAM/VRAM clearing). So maybe I just got lucky that time. SPC loading was quite an ordeal at first, so I'm glad if I can help anyone else with that.

Thanks for clearing up my guesses, probably would make more sense if I referred to docs instead of my old source code and memories. :)

Posted: Fri Jul 03, 2009 2:58 pm
by Near
It doesn't take the S-SMP long to clear 240 bytes of stack and signal to the S-CPU that it's ready. Clearing all of WRAM / VRAM gives you plenty of time for it to finish its setup process.

Still, it's good advice. For a one-time check, especially for a library routine, it's best to just add the cmp #$bbaa. Never know when someone might call it right off the bat.

Posted: Fri Jul 10, 2009 8:07 pm
by Gekko
I already posted two unrelated questions, so why not more?
3) This is a Cx4 question. (or set) What is the purpose (or what do you store to, and in what format) of the registers that are labeled MSBs/MSB of the above in this documentation? For example, how does this work: (command $00, subcommand $03)
$7f8c: Height
$7f8d-e: ??? (MSBs of above?)
In addition, for that same command, what about the format of $7F83-5 and $7F86-8? Are they bb.bbbb?
EDIT: It's the most significant byte/bytes for the value, not of the value.
4) Does DMA actually stop the CPU from reading off more instructions (like using the DSP-1 would) or can the CPU still go on reading instructions during DMA?
5) This isn't a question as much as the others but I've noticed that many places reference things like SPC7110 information floating around. Since I want to know about all of the chips, where can I find information on the following chips:
DSP-2
DSP-3
DSP-4
OBC-1
S-DD1
S-RTC
SPC7110
MX15001TFC
ST010
I already know of this place but I don't understand C, except for the parts that English enough. (And the if, then, else things)

Posted: Sat Jul 11, 2009 9:05 am
by koitsu
Gekko wrote:4) Does DMA actually stop the CPU from reading off more instructions (like using the DSP-1 would) or can the CPU still go on reading instructions during DMA?
Yes. Once you enable a DMA transfer via $420B, the transfer takes place and the main CPU is essentially "halted" until the transfer finishes.

E.g.:

Code: Select all

...

$8004: LDA #$01       ; Enable channel 0
$8006: STA $420B      ; Begin DMA transfer
;
; CPU is stalled/held until the DMA transfer is completed.
; Below instructions won't occur until the DMA transfer has
; completed.
;
$8009: REP #$10
$800B: LDX #$1234

...