I'm spearheading the complete re-rip of
http://www.sprites-inc.co.uk/ graphic archives and replacing everything with data rips.
Of course this means dealing with compression at times, and the game I'm currently working with is Mega Man X4 (X5-6 look to use the same compression method just by looking in Tile Molester). The player sprites and weapons seem to be the only things that are compressed fortunately. I know I can dump them with a VRAM viewer, but I'd like to increase my knowlegde and skills by figuring out the decompression routine; I just need a bit of guidance on what I'm doing.
What I've got going so far:I found a tool called BioFAT that was able to split the game archives into parts. Looking at the palettes stored in the files, I was able to determine what the compressed graphics were, despite not being able to view them.
The compressed MMX4 files:PL00_U.ARC > PL00_U02.BIN = X (Force Armor)
PL01_U.ARC > PL01_U02.BIN = Zero
PL02_U.ARC > PL02_U02.BIN = X (Ultimate Armor)
The compressed MMX5 files:ROCK_X5.DAT > ROCK_X588.BIN > ROCK_X58803.BIN = X (Force Armor)
ROCK_X5.DAT > ROCK_X590.BIN > ROCK_X59003.BIN = Zero
ROCK_X5.DAT > ROCK_X592.BIN > ROCK_X59203.BIN = X (Force Armor) - DUPLICATE
ROCK_X5.DAT > ROCK_X593.BIN > ROCK_X59303.BIN = X (Ultimate Armor)
ROCK_X5.DAT > ROCK_X594.BIN > ROCK_X59403.BIN = X (Falcon Armor)
ROCK_X5.DAT > ROCK_X595.BIN > ROCK_X59503.BIN = X (Gaea Armor)
The compressed MMX6 files:ROCK_X6.DAT > ROCK_X685.BIN > ROCK_X68503.BIN = Zero
ROCK_X6.DAT > ROCK_X686.BIN > ROCK_X68603.BIN = X (Ultimate Armor)
ROCK_X6.DAT > ROCK_X687.BIN > ROCK_X68703.BIN = X (Falcon Armor)
ROCK_X6.DAT > ROCK_X688.BIN > ROCK_X68803.BIN = X (Shadow Armor)
ROCK_X6.DAT > ROCK_X689.BIN > ROCK_X68903.BIN = X (Blade Armor)
Here are the files, perhaps someone recognizes the compression method and/or a tool exists already that would work on them.
http://www.mediafire.com/download/cm0wn55j180i411/MMX4-6+Compressed+Graphics.zipAt any rate, I'll probably be stuck using a debugger and figuring out the decompression routine myself. I've been messing around with PCSX Agemo Debugger and pSX's built in debugger the past couple of days and want to make sure I did everything correctly. I figure I better make sure I even found the correct routine before I start trying to figure out what it all does.
PCSX Agemo Debugger:1) Use GPU upload breakpoint to find where X's graphics are loaded into VRAM from and then dump the RAM.
GPU Upload from $8016DEA8 , $800 bytes
area X/Y(320, 0) W/H(64,16)
2) Use tracing and assembly logs to find the code being executed.
Tracing: Use the emulator's Save(F1),load(F3) + debugger's "total inst."
a) Emulator F1 then F3 (set "total inst." to 0).
b) Break on Memory Write ($8016DEA8 in this case).
c) Resume.
d) When break point occured, remember current "total inst." value.
e) Emulator F3 (set "total inst." to 0 again).
f) Use "exec" to execute to before.
g) Then you can enable "asm log" to get all the instructions.
3) Use AdisasM to disassemble the RAM that was previously dumped and search for the final snippet of code that was executed in the assembly log. This snippet should be located in the Decompression Routine, so just copy the entire function.
func16ff4: ; 80016FF4
80016FF4 lhu t1, $0000(a0)
80016FF8 addiu a0, a0, $0002
80016FFC ori t0, zero, $8000
80017000 addiu a3, zero, $0010
loop17004: ; 80017004
80017004 and v0, t0, t1
80017008 bne v0, zero, L17024 [$80017024]
8001700C nop
80017010 lhu v0, $0000(a0)
80017014 addiu a0, a0, $0002
80017018 sh v0, $0000(a1)
8001701C j L17094 [$80017094]
80017020 addiu a1, a1, $0002
L17024: ; 80017024
80017024 lhu a2, $0000(a0)
80017028 nop
8001702C andi v0, a2, $f800
80017030 beq v0, zero, L17044 [$80017044]
80017034 addiu a0, a0, $0002
80017038 srl v1, v0, $0b
8001703C j L1704c [$8001704c]
80017040 andi a2, a2, $07ff
L17044: ; 80017044
80017044 lhu v1, $0000(a0)
80017048 addiu a0, a0, $0002
L1704c: ; 8001704C
8001704C or v0, v1, a2
80017050 beq v0, zero, L170a8 [$800170a8]
80017054 nop
80017058 bne a2, zero, L17078 [$80017078]
8001705C sll v0, a2, $01
loop17060: ; 80017060
80017060 sh zero, $0000(a1)
80017064 addiu v1, v1, $ffff (=-$1)
80017068 bne v1, zero, loop17060 [$80017060]
8001706C addiu a1, a1, $0002
80017070 j L17098 [$80017098]
80017074 addiu a3, a3, $ffff (=-$1)
L17078: ; 80017078
80017078 subu a2, a1, v0
loop1707c: ; 8001707C
8001707C lhu v0, $0000(a2)
80017080 addiu a2, a2, $0002
80017084 addiu v1, v1, $ffff (=-$1)
80017088 sh v0, $0000(a1)
8001708C bne v1, zero, loop1707c [$8001707c]
80017090 addiu a1, a1, $0002
L17094: ; 80017094
80017094 addiu a3, a3, $ffff (=-$1)
L17098: ; 80017098
80017098 bne a3, zero, loop17004 [$80017004]
8001709C srl t0, t0, $01
800170A0 j func16ff4 [$80016ff4]
800170A4 nop
L170a8: ; 800170A8
800170A8 jr ra
800170AC nop
pSX:5) To help confirm this is correct, use pSX's built in debugger and set a memory write breakpoint on $8016DEA8. Open the Memory and Dissasembly windows, and use the Step Into (F7) command. Disassembly shows the game going through the code we pulled and Memory shows data being written into RAM.
Here's the resulting logs, assembly, and RAM dump that were produced while doing all this:
http://www.mediafire.com/download/q52a42iy2dcfuo8/MMX4+-+RAM+Assembly+Logs.zipHave I done everything correctly?