Radfordhound / HedgeLib

A C++ library and collection of tools that aims to make modding games in the Sonic the Hedgehog franchise easier.
MIT License
88 stars 24 forks source link

Add a Heroes/Shadow ONE Archive class #1

Closed Radfordhound closed 7 years ago

Radfordhound commented 7 years ago

I need to figure out the format. This would be nice to have!

Radfordhound commented 7 years ago

Alright so far it seems that the archives themselves are, in-fact, not compressed, only the contents of the files within them. So that's good lol.

It appears that like the SR/BK ONE files, the filenames are essentially just a char array of a set character amount, only hear it seems that amount can possibly be set within the archive file itself? At 0x10 you can see an unsigned short of 0x40, which is the length of the filenames. image

Radfordhound commented 7 years ago

Dang... "bob.one" contains 0x3E80 consecutive nulls between the file entries and the actual file data... what on earth? image

Radfordhound commented 7 years ago

On second thought, I believe that 0x00400000 at 0x10 is actually an offset to when the actual file data begins, hence all the nulls.

thesupersonic16 commented 7 years ago

So the null area is used to store file information and 0x4000 and over stores the data?

Radfordhound commented 7 years ago

The area at the beginning of the file is the file entry data (for the SB ONE files this was filenames, data offsets/lengths, etc., though here it seems to just be filenames), whereas the data itself is the stuff from 0x4000 and beyond. So basically, yeah. xP

Those nulls in-between the filenames and the actual data itself have absolutely no use other than making the file larger (which can actually be helpful in some weird cases with the way stuff is stored on disks from what I understand), lol. No idea why Sonic Team did that.

thesupersonic16 commented 7 years ago

So the nulls are there so you can add more file entrys? (I mean so you wont have to move everything down when adding a new file) Also how will it know the file size?

Radfordhound commented 7 years ago

Well if you want to repack the archives you're basically making a new file from scratch anyway, so I'm not really sure why the nulls are there, tbh. I'd be willing to bet if you removed them (being careful to not remove the ones that are part of the filenames) and changed the offset at 0x10 to reflect where the data actually begins now with those nulls gone, the files would load fine in-game and be much smaller, though I haven't tried that yet lol so who knows?

As for the file-size of each file within the archive, that appears to be located at the beginning of each piece of file data. For example, here: image

Radfordhound commented 7 years ago

Got the basic format down - it's weird lol. Here's a WIP pseudo-code spec.

const uint HeroesMagic = 0x1400FFFF;

//File data starts here
struct HEADER
{
    uint padding = 0;
    uint fileSize; // The size of the archive minus 0xC for some reason
    uint magic1 = HeroesMagic;
    uint magic2 = 1;

    uint unknown1; // Either the offset to the file data, or the length of each file name as a big-endian ushort?
    uint magic3 = HeroesMagic;
}

struct DATA
{
    FileName[] fileNames = new FileName[256];
    FileEntry[] fileEntries = new FileEntry[]; // The length is indefinite from my understanding - simply keep reading them until the end of the file.
}
//File data ends here

//Data types used in the file
class FileName
{
    char[] name = new char[0x40]; // The length is possibly unknown1 instead of a hard-coded 0x40 value.
}

class FileEntry
{
    uint fileNameIndex; // The index to the file name from the fileNames array in DATA
    uint fileSize; // The length of the data
    uint magic1 = HeroesMagic;
    byte[] fileData = new byte[fileSize]; // The data for the file, typically PRS compressed.
}
Radfordhound commented 7 years ago

In stg00.one "HeroesMagic" is actually equal to 0x1003FFFF instead of 0x1400FFFF, and it's probably different in other files, too.

All I can think of is this is either:

thesupersonic16 commented 7 years ago

Wow that was quick.

Radfordhound commented 7 years ago

Thanks lol, I've seen a lot of these archives I guess. xD Writing a class to try and read them now. This format honestly could've been written a LOT better and would be just as efficient (if not way moreso) to read from the disc - I honestly have no idea why Sonic Team wrote it like this lol.

thesupersonic16 commented 7 years ago

You shuld see the .pac format. it looks much different.

Radfordhound commented 7 years ago

I poked around at it a bit actually, lol. Started a class for that (LWArchive) just never got around to actually finishing it. xD It looks to use a lot of the BINA stuff present in most of Colors/LW's formats, so I understand at least that much of it.

Radfordhound commented 7 years ago

Added a WIP Heroes Archive class, reads data correctly. 6943cd173a069a7f7ed1abfa60c7b4744ef0d86e