Macbeth Corvell
Maybe one of you two can help me instead, can either of you tell me how the various files of arcanum are read, eg the ART, map, or prototype files?
If you do, please share,
Though it to be useful to me, I will need whatever you have to be structured similarly to this, which is just a quickie I wrote up to describe Arcanum's DAT files.
Maybe one of you two can help me instead, can either of you tell me how the various files of arcanum are read, eg the ART, map, or prototype files?
If you do, please share,
Though it to be useful to me, I will need whatever you have to be structured similarly to this, which is just a quickie I wrote up to describe Arcanum's DAT files.
Code:
The dat files are structured in this order
1. Series of zlib deflate streams
2. number of DatEntry items
3. The DatEntry items
4. DatFooter
So to read it, you first jump to the end of the file, then you back up sizeof(DatFooter) bytes and read the footer.
The DatFooter looks like this and weighs 28 bytes.
struct DatFooter {
char uuid[16]; //no idea what this is used for
char magic[4]; // should be 1TAD to indicate a valid file
uint filenameTotalBytes; // size in bytes of all filenames in the archive put together, serves no purpose unless you want to address the items in one big buffer
uint datEntryStartFromEnd; // basically a sum of bytes of everything written that isn't a deflate stream
};
Once you've read the footer, you should be back at the end of the file.
You now want to backup datEntryStartFromEnd bytes so you jump right after all the deflatestreams in the archive.
So basically you want to now fseek(archiveStream, filesize - footer.datEntryStartFromEnd, SEEK_SET);
Here you read an integer from the file, and this is the number of DatEntry objects that are in the file, then you just iteratively load them.
Each DatEntry object looks like this:
struct DatEntry {
enum EntryType
{
STORED = 0x00000001, //It's just stored, not a deflate stream
COMPRESSED = 0x00000002, //deflate stream
DIRECTORY = 0x00000400 //a directory
};
const char *filename;
uint unk_value; // no idea, probably a crc or an offset
EntryType type;
uint originalSize; //size of uncompressed blob
uint deflateSize; //size of the deflatestream blob
uint offset; //position in the fileStream where the deflatestream blob starts
};
To read the filename, you read an int, this will get you the string size to allocate. Then you read size bytes from the stream; the filename read includes a terminating '\0' character so you do not need to account for it.
Then you read another 5 integers and store them in the respective fields and you're done.
To then load a file, you just jump to the offset and use your favourite tool/library to 'reinflate' the deflate streams - eg zlib