Ah, thanks! And yeah this is obviously not complete, being able to automatically construct sprites from the tiles would be much better.
Also, while I was writing all the instructions into my program, I was wondering if there was a better way to do it. I had a helper function that simplified what I had to do, but I still had to write in checks for the instructions, and then what to do depending on that. Once I got to $BF I noticed it was getting quite tedious, so I had a better look at the bits of the bytes to see if there was some way to automatically know what each byte does. And there is. So here I'll have my own little lecture
As you know, each byte has 8 bits. For the instruction bytes, these bits tell you how to read the following bytes to end up with 8 bytes in total. How it works is like this:
1 = read the next byte and print it.
0 = print the last read byte.
So for example, let's say we have the instruction $D8. In binary this is 11011000. Let's check these out one by one:
1 = read the following byte and print it.
1 = read the following byte and print it.
0 = print the last read byte.
1 = read the following byte and print it.
1 = read the following byte and print it.
0 = print the last read byte.
0 = print the last read byte.
0 = print the last read byte.
You can see that only four bytes are read, the second one is printed twice and the last is printed four times. This is the same as your instruction for $D8: "Read the following four bytes, but print the second byte twice and the last byte four times".
You can check it out yourself, convert the instruction bytes to binary and you should see that they match up with the instructions you deduced.
This also shows why $FF (11111111) is read the following 8 bytes and print them once each, and $80 (10000000) is read the first byte and print it 8 times.
As you can imagine, this is much quicker and simpler to implement than checking for specific bytes and doing specific actions depending on them. So I'm glad I discovered that.
You might also notice that for this to actually work, the first bit has to be 1; 0 means print the last byte, and there's no byte before the first one! This means that anything below $80 can't be an instruction (except for $00 which, as you said, is probably the end of that section). I'll account for this in the program.
EDIT: Done! Here you go; TripWorldDecompressor. Just download and unzip it somewhere, and double click the program (or start it through the commandline, whatever). It'll ask you to type in the ROM name, do that. It'll ask where to start decompressing, so type that in (without any $ or 0x prefix, just the hex offset directly). Once it reaches a null byte it'll say how many "chunks" it decompressed, and you can choose to let it continue or not. Keep in mind that the chunk counter is for the total of that session, so if it says it's done 80, then you say to continue, and it says 80 again, that means it's done 80 in total (not 160). Getting the same number twice like this also means two adjacent null bytes, so there's probably no graphics data for a while after that.
Anyway, once you've said no to a null byte notification, it'll stop decompressing and ask you to name a file to save the decompressed data to. Keep in mind that if you name an existing file then it will overwrite that completely. So just do something like "hedgehog.bin" or whatever. After that'll it'll end and you just press any key to close it.
If it reaches an invalid instruction during the decompression process, it'll tell you the byte it reached and then automatically stop decompressing. It'll go straight to the file saving question so you can save what it's decompressed so far.
So yeah, this should hopefully make the decompressing a lot easier!
Also, while I was writing all the instructions into my program, I was wondering if there was a better way to do it. I had a helper function that simplified what I had to do, but I still had to write in checks for the instructions, and then what to do depending on that. Once I got to $BF I noticed it was getting quite tedious, so I had a better look at the bits of the bytes to see if there was some way to automatically know what each byte does. And there is. So here I'll have my own little lecture
As you know, each byte has 8 bits. For the instruction bytes, these bits tell you how to read the following bytes to end up with 8 bytes in total. How it works is like this:
1 = read the next byte and print it.
0 = print the last read byte.
So for example, let's say we have the instruction $D8. In binary this is 11011000. Let's check these out one by one:
1 = read the following byte and print it.
1 = read the following byte and print it.
0 = print the last read byte.
1 = read the following byte and print it.
1 = read the following byte and print it.
0 = print the last read byte.
0 = print the last read byte.
0 = print the last read byte.
You can see that only four bytes are read, the second one is printed twice and the last is printed four times. This is the same as your instruction for $D8: "Read the following four bytes, but print the second byte twice and the last byte four times".
You can check it out yourself, convert the instruction bytes to binary and you should see that they match up with the instructions you deduced.
This also shows why $FF (11111111) is read the following 8 bytes and print them once each, and $80 (10000000) is read the first byte and print it 8 times.
As you can imagine, this is much quicker and simpler to implement than checking for specific bytes and doing specific actions depending on them. So I'm glad I discovered that.
You might also notice that for this to actually work, the first bit has to be 1; 0 means print the last byte, and there's no byte before the first one! This means that anything below $80 can't be an instruction (except for $00 which, as you said, is probably the end of that section). I'll account for this in the program.
EDIT: Done! Here you go; TripWorldDecompressor. Just download and unzip it somewhere, and double click the program (or start it through the commandline, whatever). It'll ask you to type in the ROM name, do that. It'll ask where to start decompressing, so type that in (without any $ or 0x prefix, just the hex offset directly). Once it reaches a null byte it'll say how many "chunks" it decompressed, and you can choose to let it continue or not. Keep in mind that the chunk counter is for the total of that session, so if it says it's done 80, then you say to continue, and it says 80 again, that means it's done 80 in total (not 160). Getting the same number twice like this also means two adjacent null bytes, so there's probably no graphics data for a while after that.
Anyway, once you've said no to a null byte notification, it'll stop decompressing and ask you to name a file to save the decompressed data to. Keep in mind that if you name an existing file then it will overwrite that completely. So just do something like "hedgehog.bin" or whatever. After that'll it'll end and you just press any key to close it.
If it reaches an invalid instruction during the decompression process, it'll tell you the byte it reached and then automatically stop decompressing. It'll go straight to the file saving question so you can save what it's decompressed so far.
So yeah, this should hopefully make the decompressing a lot easier!