TascoDLX wrote:
Well, the VRAM dump you posted from Slam City is definitely byteswapped. You can tell by looking at the name table. That's the only reason I mention it. It's an old KMod bug and I'm not sure if it was ever fixed in an official release. Just something to look out for.
I'll take your word for it.
Here's what I can tell about C2: The data is all encoded, no compression. The decoder takes advantage of the Sega CD's font generator, which is used to generate 2-color patterns. The packet breakdown (in order) is: palette data, command data, color (index) data, pattern data. Offsets for color data and pattern data are tacked on to the header. The (implied) offset for command data is zero. All offsets are relative to the end of palette data.
Thanks for that. After poking around a bit I figured out that the palette data comes before any other data, and I knew there were two (or sometimes three) distinct groups of data following it, but I didn't know what they were for. Do you have any more information on the Sega CD font generator?
EDIT: Is it significant that the routine makes so many writes to $FF804D? I did some research and noticed that a the range from $FF0000 ~ is used for a lot of special functions of the Sega CD, including graphics at $FF8058. Actually, if I think about it, the tile routines actually appear read out some data from the RAM used for Sega CD graphics, but it looks like it would be reading from the status area, which doesn't make a lot of sense.
EDIT 2: Got it. I just checked out the Mega CD Software Development Manual, and yeah, $FF804D is the address used for writing a color data, and $FF804E~F are used for patterns. When these bytes are written to, the system automatically generates font data and stores it in the read-only range $FF8050~6. That's why the code looks like it's reading from RAM that hasn't been written to yet.
Also, if you need a pointer, the C2 decode routine in Slam City is located at $012792 on the sub side [SUBCODE.BIN, file offset $A52A].
Thanks so much for this! I've taken it upon myself to learn a bit of M68k assembly language, and after studying a disassembly of SUBCODE.BIN, I've learned that the video in C2 frames is built from coded patterns, just like you said. My knowledge of assembler is really shaky (I just started learning a few days ago), but I think I might be able to figure this out now.
Of course, if anybody who knows a lot about the 68k wants to take a look at the disassembly, I'd be happy to make it available.
It looks like the SUBCODE.BIN from Slam City also contains decoding routines for some of the other chunk types that I previously figured out (as I figured it would, being a later game and all). A quick check of the code has shown me so far that a lot of the guesses I made were correct. I'm seeing a lot of values in the code that I had to figure out by trial and error. I'm curious to look through the code now to see if I missed anything in my implementation, though.
One really cool thing is that the routine that branches out to the various decoding routines also does checks for some chunk types that I haven't seen before. I'm interested to find out whether these chunk types are actually used or not.
EDIT:
I spent some time translating the 68K assembly into Visual Basic, and I've got a working parser that can read through all the data commands and build a tile map.
It looks like the codes range from $00 to $3F, and the palette index is stored in the top two bits of the code. For codes $00 ~ $2F, the routine branches off into lots of subroutines for drawing whole or partial tiles. There look to be about 50 subroutines in total. Codes $30 ~ $3F are for referencing repeated tiles.
Below are the routines for codes $01 and $02:
Code: Select all
;ADDRESSES
;a2 = color index data
;a3 = bit pattern data
;a4 = decoded tile data
;a6 = scratch RAM for building tiles
;Code $01
move.b (a2)+,(a6)
move.l 3(a6),(a4)+
move.l 3(a6),(a4)+
move.l 3(a6),(a4)+
move.l 3(a6),(a4)+
move.l 3(a6),(a4)+
move.l 3(a6),(a4)+
move.l 3(a6),(a4)+
move.l 3(a6),(a4)+
rts
;Code $02
move.b (a2)+,(a6)
move.b (a3)+,1(a6)
move.b (a3)+,2(a6)
move.l 3(a6),(a4)+
move.l 7(a6),(a4)+
move.b (a3)+,1(a6)
move.b (a3)+,2(a6)
move.l 3(a6),(a4)+
move.l 7(a6),(a4)+
move.b (a3)+,1(a6)
move.b (a3)+,2(a6)
move.l 3(a6),(a4)+
move.l 7(a6),(a4)+
move.b (a3)+,1(a6)
move.b (a3)+,2(a6)
move.l 3(a6),(a4)+
move.l 7(a6),(a4)+
rts
What kind of tiles would these build? I'm guessing that both codes build 8 x 8 tiles, because they both output 8 incremental long words to a4. Code $01 looks like it builds a tile with a two-pixel wide vertical line on one edge of the tile, but how? To me, it looks like it copies a byte of color index data to the first byte of (a6), but then it copies long words to (a4) from (a6) starting three bytes AFTER the color data it just copied. I'm sure I'm just reading it wrong, but I don't know how.
EDIT: If it helps, address register a6 points to address $FF804D, an odd address. I think the fact that the address is odd might have something to do with the way these routines work.
As always, help would be much appreciated.