ProtonNoir / SNES-decompression-tools

SNES graphics decompression tools
23 stars 2 forks source link

SNES Konami LZ #3

Open hansbonini opened 3 years ago

hansbonini commented 3 years ago

Can you share this source code?

ProtonNoir commented 3 years ago

Yeah, sure.

hansbonini commented 3 years ago

Thank you

hansbonini commented 3 years ago

I've made a decompressor for the most common type of this compression, basically you have 4 controls ranges:

< 0x80 = LZ
>= 0x80 && < 0xC0 = RAW Byte Copy
>= 0xC0 && < 0xE0 = RLE
>= 0xE0 = RLE of Zeroes```

First 2 bytes of each compressed block are the uncompressed size.

ProtonNoir commented 2 years ago

I added source code for Konami compressor and decompressor.

Strugglemeat commented 2 years ago

I can use the decompressor to extract the graphics, but if I use the compressor to re-compress, it either segfaults (built myself from source here) or compresses to garbage that's shorter than it should be (using the exe available at romhacking.net).

./konami_d 'Contra III - The Alien Wars (USA).sfc' 0x41D7E 1
(using the addresses from https://www.romhacking.net/utilities/1102/ ) will create decomp.bin

Game type: 1
Size of data to be decompressed: 7ba
Decompressed data size: 1d3e

./konami_c decomp.bin comp.bin 1

Game type: 0
Size of data to be compressed: 1d3e
Starting compression...
Compressed data size: 1ce

note that it states game type as 0 even if I input parameter for type 1

ProtonNoir commented 2 years ago

I'll check it out.

Strugglemeat commented 2 years ago

by removing the argc/argv parameters and hardcoding them, I was able to get the compressor to run. the compressed file is, however, slightly different in some places compared with the original compressed file in the ROM. I'm trying to figure out which of the types is causing the issue.

I've attached a zip with 3 files:

note that using the decompressor on the file compressed-protonnoir.bin does result in the same as decomp.bin

thanks for taking a look!

binarydata.zip

Strugglemeat commented 2 years ago

ok, I feel like a goof! the first byte isn't read by the game, but it's the first of two bytes which state the size of the compressed structure the game I'm working on is Konami's "Tsuyoshi Shikkari Shinasai - Taisen Puzzle Dama" and the font data in question begins at 0x40395

Strugglemeat commented 2 years ago

image

your compression algo works fine! check out the English letters. thanks a ton for this tool!

Strugglemeat commented 2 years ago

compression algo is not working properly on tilemap data

Size of data to be decompressed: 179
Decompressed data size: 800
Size of data to be compressed: 800
Compressed data size: 420

decomp.bin.zip

any chance you could take a look? I'm close to being able to get this translation going. otherwise I'll have to really hack it up in order to copy decompressed tilemap data directly to vram, would be way less elegant. thank you.

Strugglemeat commented 2 years ago

more info on this issue the first 0x14C bytes of the decompressed data are the 2 bytes "00 20" repeating. based on the original compressed data, the type of compression employed should first be 0x82, for two bytes of "00 20". 82 00 20 the following compressed data represents 0x14A worth of "00 20" 7F DF 7C 00 7C 21 7C 42 7C 63 7C 84 7C A5 7C C6 7C E7 7D 08 9F

the output from the tool provided here does not match this output (results from this compression tool are shown below)

past this point, by 0x14C area in the decompressed data, the code here then works fine, matching everything in the original compressed data in the ROM, until we hit another batch of "20 00" repeating, when the compressor breaks down again

it seems as though the code is not generating what should be type "LZ (0x00 - 0x7F)"

Input position = [0] = [0]//rle_E0 0xA0-0xBF search_rle: size = 44, type = rle_A0) RLE char to repeat is: 0x0 repeat number of times is: 0x42

raw_size:0

write raw 6 write write_rle func write raw 3

20 04 BF 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 BF 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 BF 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 BF 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 BF 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20

edit: seems as though I got it to compress to a workable format by commenting out the rle_A0 section

//rle_A0...0xA0-0xBF
/*
    if (current[0]==0x00&&current[1]!=0x00&&current[2]==0x00&&current[3]!=0x00)
    {
        size_t rep;
        if(extensive_output==1)cout << "\n//rle_E0 0xA0-0xBF"; (E0 here is a typo I think)
        for (size = 0; size <= (MAX_LENGTH*2) && current + size < start + insize-1; size += 2)
        {
            if (current[size]!=0x00) break;
        }

        int s=0;

        for (rep = 1; rep <= size && current + rep < start + insize-1; rep += 2)
        {

            if (current[rep]==0x00) break;
            val[s++]=current[rep];
        }

        rep=rep-1;

        for (int i=0; i<(rep/2); i++)
        {
            candidate.ar[i] = val[i];
        }

        if (rep > (MAX_LENGTH*2)) rep = (MAX_LENGTH*2);
        if (rep >= 4 && rep > candidate.size)
        {
            candidate.size = rep;
            candidate.type = rle_A0;

            if(extensive_output==1)cout << hex << "\nsearch_rle: size = " << size << ", type = rle_A0)";
        }

    }
*/

I guess theoretically removing one type of compression should still provide working compressed code since another type will might always pick up that case? I'm gonna see about how I can fix it now that I've identified where the issue lies.

edit2: damn, removing the A0 rle type seems to give this at the end of the compressed data: 8C 00 20 00 20 00 20 00 20 00 20 00 20 instead of 2B D1 41 making the same data re-compressed larger than what was originally there =\ I guess this was an issue I was going to run into eventually, I can maybe make more room by changing the pointer data

edit3: if (current[0]==0x00 && current[1]!=0x00 && current[2]==0x00 && current[3]!=0x00) //rle_A0...0xA0-0xBF this if statement exactly matches the structure of the decompressed data, 00 20 00 20, I guess that's why it's triggering this compression type

so ultimately, the issue is the compressor is using rle RLE_A0 (0xA0 - 0xBF) instead of LZ (0x00 - 0x7F) on decompressed data that looks like 00 XX 00 XX

edit4: yeah, looking at the decompress

               chr = in_buf[in_pos++];
                win_buf[buf_pos++]=0x00;
                buf_pos=check_pos(buf_pos);
                out_buf[out_pos++]=0x00;
                win_buf[buf_pos++]=chr;
                buf_pos=check_pos(buf_pos);
                out_buf[out_pos++]=chr;

I can see why it's picking up that 00 20 00 20 data as this type

if((int)in_buf[in_pos+1]!=0x20)rle = search_rle(in_buf, in_buf + in_pos, in_size, t); adding that if gets rid of all of the issue except at the very end

edit5: I think I've isolated the issue. within search_lz function, at the end, there's a check regarding total input file size. if we're too close to the end, it won't do the lz compression. but I don't think this is in line with Konami's algo, since it will do the lz compression at the end of the file.

if (lz_len >= 2&&(lz_len+pos) < inputsize)
{
    variant.length=lz_len;
    variant.offset=lz_off;
    if(extensive_output==1)cout << hex << "search_lz: (length = " << lz_len << ", offset = " << lz_off << ")";
}
else 
{
    if(extensive_output==1)cout << "search_lz: lz_len was greater than or equal to current pos plus in_size of "<< (int)inputsize << endl;
}
Strugglemeat commented 2 years ago

image

I got it working by disabling that check at the end my modified code is at https://github.com/Strugglemeat/konami/ (credit given to you)

ProtonNoir commented 2 years ago

Great news!

Strugglemeat commented 2 years ago

https://www.romhacking.net/translations/6641/ ta-da! thanks again for providing the compression/decompression code here

Darin80s commented 2 years ago

Hello Please how do I extract the graphics from Spider-Man & Venom - Separation Anxiety?

what command to use in cmd?

I use first: g++ separation_anxiety_d.cpp

After that a.exe

is generating a file "Spider-Man & Venom - Separation Anxiety (U)_decomp.bin"

with zero KB.

spider man rom needs to be inside the folder?

sorry, i don't know what to do.

Show me this:

C:\protonoir\Software Creations>a.exe X=[ 0] Y=[ 0] In.pos.=[ 0] Out.pos.=[ 0] CNT=[ 0] Decompressed data size: 0

I need the alphabet graphic to edit.

please How to decompress the file and then compress it? I didn't find help tutorial.

ProtonNoir commented 2 years ago

Hi, please rename ROM to "Spider-Man & Venom - Separation Anxiety (U).smc" ROM name is hardcoded. I'll try to write compression tool for this game.

Darin80s commented 2 years ago

Hi, please rename ROM to "Spider-Man & Venom - Separation Anxiety (U).smc" ROM name is hardcoded. I'll try to write compression tool for this game.

Hi, I Edited graphic.

"I'll try to write compression tool for this game."

It's not possible compress Spider Man dcomp.bin back with ProtoNoir?

☹️

Gilberto99 commented 1 year ago

friend help me how to have konami updated? if you can send me the zip file because I can't compress snes graphics with the old konami compress

ProtonNoir commented 1 year ago

friend help me how to have konami updated? if you can send me the zip file because I can't compress snes graphics with the old konami compress

Hi! Send me additional information: 1) rom name 2) rom offset (for insertion) 3) file with uncompressed graphics

RitzLazyArtist commented 11 months ago

Hello @ProtonNoir and @Strugglemeat, I'm planning to make a hack of the SNES Animaniacs game to make the graphics look like the reboot. I can't find the offset for where the compressed graphics of the original Animaniacs logo located to decompress from the ROM before I could edit it myself. I only found the files of the text, stage tiles, some screens Warners from the intro cutscene, world map, and endings. I've started it off with the fonts at 0xD0087 and 0xD04F3 first. Can you help me find the tiles of the logo from the title screen? Can I send you the original ROMs from all regions first before I could work on it?