I was looking through the snes9x source code when I happened upon the rom that the SPC boots up with. I decided to try to convert it to assembly code, in spite never having looked at SPC700 asm before O_o. ouch.... here goes
//added by MONapkins /* above rom reads in spc opcodes:
MOV X, #$EF MOV SP, X // the stack is at $EF
LOOPBACK: MOV A, #$00 MOV (X), A // zero out $01 through $EF DEC X
BNE #$FC (LOOPBACK)
MOV $F4, #$AA // #$BBAA is the classic value you see on the 65816 MOV $F5, #$BB // side of things, indicating the SPC is "ready"
LOOPBACK2:
CMP $F4, #$CC // another value seen on the 65816 side, when preparing to send data. As I recall, this value is fed from the 65816 side through the $F4 port.
BNE #$FB (LOOPBACK2) // Hence, until we receive that message, we do nothing.
BRA #$19 (BRANCH2)
LOOPBACK3:
MOV Y, $F4 // put that lower byte in Y
BNE $FC (LOOPBACK3) // maybe an internal process insures $F4 will drop down to zero. Otherwise this is an infinite loop.
LOOPBACK4:
CMP Y, $F4
BNE #$0B (BRANCH1)
MOVZ A, $F5 MOV $F4, Y MOV [$00+Y], A INC Y
BNE #$F3 (LOOPBACK4)
INCZ $01 // again, you got me on the specification here.
BRANCH1:
BPL #$EF (LOOPBACK4)
CMP Y, $F4
BPL #$EB (LOOPBACK4)
BRANCH2:
MOVW YA, $F6 // move a word of data received from the 65816 ($2142-3) MOVW $00, YA // move it to $00-$01 MOVW YA, $F4 // check the word on the other port. MOVZ $F4, A // it's called MOV with zero extended, but I'm not sure what exactly that means. Maybe it erases the upper byte, i.e. $F5 MOV A, Y // MOV X, A // chain along the upper byte to X BNE #$DB (LOOPBACK3) // if it wasn't 0, loop back and do some stuff
JMP [$0000+X]
DI // no fricken clue...
STOP */
for posterity I will also provide the data in the globals.cpp file
uint8 APUROM [64] = { 0xCD,0xEF,0xBD,0xE8,0x00,0xC6,0x1D,0xD0,0xFC,0x8F,0xAA,0xF4,0x8F,0xBB,0xF5,0x78, 0xCC,0xF4,0xD0,0xFB,0x2F,0x19,0xEB,0xF4,0xD0,0xFC,0x7E,0xF4,0xD0,0x0B,0xE4,0xF5, 0xCB,0xF4,0xD7,0x00,0xFC,0xD0,0xF3,0xAB,0x01,0x10,0xEF,0x7E,0xF4,0x10,0xEB,0xBA, 0xF6,0xDA,0x00,0xBA,0xF4,0xC4,0xF4,0xDD,0x5D,0xD0,0xDB,0x1F,0x00,0x00,0xC0,0xFF };
So anyways, just out of curiosity, anybody know what MOVZ and DI are for? I've read some docs on MOVZ, but it's a little unclear. And DI is on the SPC700 opcode list, but I can't figure out what it does from any source I've seen.
(edited by MathOnNapkins on 06-10-05 08:40 PM)
|
The MOVZ and INCZ aren't part of the "standard" spc700 opcode list that I am used to. What did you use to disassemble it? (Or where did you get the list of opcodes if you did it by hand?)
Anyway, it appears they are using "Z" to denote "byte" (as opposed to the MOVW opcode, etc). Also, the ending of the boot rom isn't code, it's just the reset vector. So don't worry about trying to interpret that.
Anyway, here is the code I commented up for myself:
Start: MOV X, #$EF ;setup the stack to 0x01EF MOV SP, X
MOV A, #$00 ;Note: on reset DP=0 ClearLoop: MOV (X), A ;save $00 --> 0x0001 - 0x00EF DEC X ; BNE ClearLoop ;
MOV $AA, #$F4 ;make initial value port $F4 = 0xAA MOV $BB, #$F5 ;make initial value port $F5 = 0xBB WaitForInit: CMP $CC, #$F4 ;Is there a 0xCC on port $F4? BNE WaitForInit ; no -> look again BRA StartBlock ; yes -> goto StartBlock
GetMem: MOV Y, $F4 ;wait for $F4 to be set to zero, saying that the first byte is ready BNE GetMem ;if $F4 != 0x00 goto GetMem NextByte: CMP Y, $F4 ;Y = current count, $F4 tells current data byte # that is on $F5 BNE Blah ;if the byte we need isn't there yet, goto Blah MOV A, $F5 ; get data MOV $F4, Y ; echo count MOV [$00]+Y, A ; store data INC Y ; count++ BNE NextByte ; if count didn't roll over then goto NextByte INC $01 ; else increase the address pointer (the high byte) Blah: BPL NextByte ;=blah= if >= 0 goto NextByte CMP Y, $F4 ; BPL NextByte ;if Y >= $F4 goto NextByte
StartBlock: MOVW YA, $F6 ;get address from $F6-$F7 (2142H-2143H from SNES side) MOVW $00, YA ; store address at 0x0000-0x0001 MOVW YA, $F4 ; read $F4-$F5 MOV $F4, A ;echo the $F4 read, back into $F4 (tell SNES we got the value)
MOV A, Y ; MOV X, A ; put $F5 into x BNE GetMem ; if $F5 != $#00, then this isn't the terminal block, goto "GetMem"
JMP [$0000+X] ;run program...
ResetVector: .dw $FFC0
Edit: grr... the board keeps clipping my post (the lines don't wrap around). Should I not be using "pre" tags? It seems to mess everything up after it, even though I've closed the tag. Oh well, for now I'll just manually enter the line breaks.
Edit: The point of the "blah" section is to check if the bootstrap is being signalled to move onto the next block (this is done by changing the counter by more than 1, ie not just incrementing it). As I said, the above is just comments I wrote for myself ... so you may want to comment it up yourself for it to be more useful.
Hope it helps though.
(edited by neviksti on 06-10-05 10:07 PM) (edited by neviksti on 06-10-05 10:10 PM) (edited by neviksti on 06-10-05 10:11 PM)
|