When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
80 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
looks to me like all the logic regarding the actual file format would be in the functions this would call
dunno, i don't see much that would help up there
you're probably gonna have to reverse engineer the format
unless there's more code
mandatory disclaimer ofc: since you almost certainly don't hold the copyright to the art in these files, you generally can't redistribute whatever you may be able to scrape out of them. and ofc depending on where you are located, and the original license of the software, reverse engineering might be illegal.
well, this is just using the stuff it got from somewhere
the interesting part would be where stuff is actually read from the file
is this code on github somewhere?
k
is the data all in one huge file?
or are there many individual files?
ok
well, the standard trick is to try to open the file with a zip program
ok
that's ofc unfortunate
i don't see any useful clues in the code above
lol
ah
well that contains some clues
A compression algorithm.
a compression algorithm
void compressBitmap(Bitmap& bitmap)
{
if (bitmap.compressionMethod!=0)return;
bitmap.compressionMethod=3;
Fay::MemoryStream uncompressed;
uncompressed.write(bitmap.data.data,bitmap.data.size); //fixme: use a wrapper stream instead
uncompressed.seek(0);
Fay::MemoryStream compressed;
auto ret=Fay::lzmaCompress(uncompressed,compressed);
assert(ret);
delete[] bitmap.data.data;
bitmap.data.data=new byte[compressed.size()];
bitmap.data.size=compressed.size();
memcpy(bitmap.data.data,compressed.data(),compressed.size());
bitmap.data.crc=crc32(0,bitmap.data.data,bitmap.data.size);
}
```this pretty much describes how it writes bitmaps to a stream of bytes
apparently
sure: a lot of hard and very technical work
from what i've seen, it seems that this game stores a bunch of sprite sheets as compressed bitmaps in a sort of archive format
the function above is probably pretty descriptive of what each sprite sheet looks like on disk
at least if i'm understanding this correctly
knowing the things we know now, it should be very possible to reverse engineer the format
probably relatively easy actually
at least for someone with the necessary expertise and motivation to do so ^^
np ^^
i'm guessing GFXC is the format you're trying to figure out
TBitStream header;
header.writeRawString("GFXC");
header.writeBits(3,8); //version
header.writeBits(bitmaps.size(),16);
header.writeBits(0,24); //header size
foreach(bitmap,bitmaps)bitmap->serialize(header);
const int headerSize=header.getSize();
header.seek(7);
header.writeBits(headerSize,24);
uint currentPos=headerSize;
foreach(bitmap,bitmaps)
{
bitmap->dataPosition=currentPos;
bitmap->serialize(header);
currentPos+=bitmap->data.size;
}
header.flush();
TBitStream full(getBasePath()+"/data",BSFM_FILE|BSFM_READWRITE|BSFM_TRUNCATE);
header.seek(0);
full.write(header,header.getSize());
foreach(bitmap,bitmaps)full.write(bitmap->data.data,bitmap->data.size);
```this would seem to be pretty much what it looks like
at least it provides the general structure
even if it doesn't tell us what's inside all the header and stuff
i guess it's
GFXC followed bythis is definitely gonna be quite some work
but yeah
seems doable
is this the actual source of the game?
because this looks like the source of some tool that produces those files
ok ^^
yeah this is basically the other part
that tells you what the bitmap headers look like i guess
void serialize(TBitStream& stream) const
{
stream.writeBits(width,16);
stream.writeBits(height,16);
stream.writeBits(bitmapWidth,16);
stream.writeBits(bitmapHeight,16);
stream.writeBits(leftBorder,16);
stream.writeBits(upperBorder,16);
stream.writeBits(getRValue(transparentColor),8);
stream.writeBits(getGValue(transparentColor),8);
stream.writeBits(getBValue(transparentColor),8);
stream.writeBits(bytesPerPixel*8,8);
stream.writeBits(group,32);
stream.writeBits(id,32);
stream.writeString(name,8);
stream.writeBits(compressionMethod,8);
stream.writeBits(compressionParams,8);
//stream.writeBits(0,32); //?
stream.writeBits(dataPosition,32);
stream.writeBits(data.size,32);
}
yeah i mean, with this, you have basically the entire format mapped out
at least so it would seem to me
GFXC followed byupdated
a C++ thing ^^
i think as far as getting the data ouf of those files is concerned, that's pretty much everything
.hpp is a cpp header file extension (usually)
It's mainly used in projects with bot C and C++ where they want to make sure nobody accidentally uses a C++ header in C (or by people having been burned by that before enough to type those 2 letters per include)
shouldn't be too hard to roll a python script with ctypes or smth that just reads those files
the decompression is gonna be the only really tricky bit
i don't see any encryption there
just compression
Depends on the data, but for assets, usually not, especially if it hasn't been online for a few years
it seems that compression method can either be 0, in which case the data is uncompressed, or 3, in which case it's compressed with BCM_LZMA, whatever that is exactly (some variation of the LZMA algorithm i suppose)
do note that there's a lot of guesswork there based on just a cursory glance of those fragments of code ^^
i'm not sure what more to look for
we have pretty much figured out the format
at least assuming that code is indeed the correct code ^^
with the info above, it should be possible to extract the bitmaps
well, you said the code is not from the actual game
so ofc there could have been changes
and so the actual files might be different
based on this screenshot, there would supposedly be about 20000 bitmaps in that file
no idea if that makes sense
seems a bit much
@livid olive Has your question been resolved? If so, type !solved :)