diff --git a/src/art.cc b/src/art.cc index 3955489..bf17d69 100644 --- a/src/art.cc +++ b/src/art.cc @@ -34,8 +34,10 @@ static int artReadList(const char* path, char** out_arr, int* out_count); static int artCacheGetFileSizeImpl(int a1, int* out_size); static int artCacheReadDataImpl(int a1, int* a2, unsigned char* data); static void artCacheFreeImpl(void* ptr); -static int artReadFrameData(unsigned char* data, File* stream, int count); +static int artReadFrameData(unsigned char* data, File* stream, int count, int* paddingPtr); static int artReadHeader(Art* art, File* stream); +static int artGetDataSize(Art* art); +static int paddingForSize(int size); // 0x5002D8 static char gDefaultJumpsuitMaleFileName[] = "hmjmps"; @@ -833,9 +835,9 @@ ArtFrame* artGetFrame(Art* art, int frame, int rotation) return NULL; } - ArtFrame* frm = (ArtFrame*)((unsigned char*)art + sizeof(*art) + art->dataOffsets[rotation]); + ArtFrame* frm = (ArtFrame*)((unsigned char*)art + sizeof(*art) + art->dataOffsets[rotation] + art->padding[rotation]); for (int index = 0; index < frame; index++) { - frm = (ArtFrame*)((unsigned char*)frm + sizeof(*frm) + frm->size); + frm = (ArtFrame*)((unsigned char*)frm + sizeof(*frm) + frm->size + paddingForSize(frm->size)); } return frm; } @@ -921,8 +923,8 @@ static int artCacheGetFileSizeImpl(int fid, int* sizePtr) char* artFilePath = artBuildFilePath(fid); if (artFilePath != NULL) { - int fileSize; bool loaded = false; + File* stream = NULL; if (gArtLanguageInitialized) { char* pch = strchr(artFilePath, '\\'); @@ -933,20 +935,20 @@ static int artCacheGetFileSizeImpl(int fid, int* sizePtr) char localizedPath[COMPAT_MAX_PATH]; snprintf(localizedPath, sizeof(localizedPath), "art\\%s\\%s", gArtLanguage, pch); - if (dbGetFileSize(localizedPath, &fileSize) == 0) { - loaded = true; - } + stream = fileOpen(localizedPath, "rb"); } - if (!loaded) { - if (dbGetFileSize(artFilePath, &fileSize) == 0) { - loaded = true; - } + if (stream == NULL) { + stream = fileOpen(artFilePath, "rb"); } - if (loaded) { - *sizePtr = fileSize; - result = 0; + if (stream != NULL) { + Art art; + if (artReadHeader(&art, stream) == 0) { + *sizePtr = artGetDataSize(&art); + result = 0; + } + fileClose(stream); } } @@ -982,8 +984,7 @@ static int artCacheReadDataImpl(int fid, int* sizePtr, unsigned char* data) } if (loaded) { - // TODO: Why it adds 74? - *sizePtr = ((Art*)data)->field_3A + 74; + *sizePtr = artGetDataSize((Art*)data); result = 0; } } @@ -1039,9 +1040,10 @@ out: } // 0x419D60 -static int artReadFrameData(unsigned char* data, File* stream, int count) +static int artReadFrameData(unsigned char* data, File* stream, int count, int* paddingPtr) { unsigned char* ptr = data; + int padding = 0; for (int index = 0; index < count; index++) { ArtFrame* frame = (ArtFrame*)ptr; @@ -1053,8 +1055,12 @@ static int artReadFrameData(unsigned char* data, File* stream, int count) if (fileRead(ptr + sizeof(ArtFrame), frame->size, 1, stream) != 1) return -1; ptr += sizeof(ArtFrame) + frame->size; + ptr += paddingForSize(frame->size); + padding += paddingForSize(frame->size); } + *paddingPtr = padding; + return 0; } @@ -1068,7 +1074,7 @@ static int artReadHeader(Art* art, File* stream) if (fileReadInt16List(stream, art->xOffsets, ROTATION_COUNT) == -1) return -1; if (fileReadInt16List(stream, art->yOffsets, ROTATION_COUNT) == -1) return -1; if (fileReadInt32List(stream, art->dataOffsets, ROTATION_COUNT) == -1) return -1; - if (fileReadInt32(stream, &(art->field_3A)) == -1) return -1; + if (fileReadInt32(stream, &(art->dataSize)) == -1) return -1; return 0; } @@ -1087,9 +1093,16 @@ int artRead(const char* path, unsigned char* data) return -3; } + int currentPadding = paddingForSize(sizeof(Art)); + int previousPadding = 0; + for (int index = 0; index < ROTATION_COUNT; index++) { + art->padding[index] = currentPadding; + if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) { - if (artReadFrameData(data + sizeof(Art) + art->dataOffsets[index], stream, art->frameCount) != 0) { + art->padding[index] += previousPadding; + currentPadding += previousPadding; + if (artReadFrameData(data + sizeof(Art) + art->dataOffsets[index] + art->padding[index], stream, art->frameCount, &previousPadding) != 0) { fileClose(stream); return -5; } @@ -1117,6 +1130,7 @@ int artWriteFrameData(unsigned char* data, File* stream, int count) if (fileWrite(ptr + sizeof(ArtFrame), frame->size, 1, stream) != 1) return -1; ptr += sizeof(ArtFrame) + frame->size; + ptr += paddingForSize(frame->size); } return 0; @@ -1134,7 +1148,7 @@ int artWriteHeader(Art* art, File* stream) if (fileWriteInt16List(stream, art->xOffsets, ROTATION_COUNT) == -1) return -1; if (fileWriteInt16List(stream, art->yOffsets, ROTATION_COUNT) == -1) return -1; if (fileWriteInt32List(stream, art->dataOffsets, ROTATION_COUNT) == -1) return -1; - if (fileWriteInt32(stream, art->field_3A) == -1) return -1; + if (fileWriteInt32(stream, art->dataSize) == -1) return -1; return 0; } @@ -1161,7 +1175,7 @@ int artWrite(const char* path, unsigned char* data) for (int index = 0; index < ROTATION_COUNT; index++) { if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) { - if (artWriteFrameData(data + sizeof(Art) + art->dataOffsets[index], stream, art->frameCount) != 0) { + if (artWriteFrameData(data + sizeof(Art) + art->dataOffsets[index] + art->padding[index], stream, art->frameCount) != 0) { fileClose(stream); return -1; } @@ -1172,6 +1186,26 @@ int artWrite(const char* path, unsigned char* data) return 0; } +static int artGetDataSize(Art* art) +{ + int dataSize = sizeof(*art) + art->dataSize; + + for (int index = 0; index < ROTATION_COUNT; index++) { + if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) { + // Assume worst case - every frame is unaligned and need + // max padding. + dataSize += (sizeof(int) - 1) * art->frameCount; + } + } + + return dataSize; +} + +static int paddingForSize(int size) +{ + return (sizeof(int) - size % sizeof(int)) % sizeof(int); +} + FrmImage::FrmImage() { _key = nullptr; diff --git a/src/art.h b/src/art.h index 9f0d628..0073cdc 100644 --- a/src/art.h +++ b/src/art.h @@ -67,7 +67,6 @@ typedef enum Background { BACKGROUND_COUNT, } Background; -#pragma pack(2) typedef struct Art { int field_0; short framesPerSecond; @@ -76,9 +75,9 @@ typedef struct Art { short xOffsets[6]; short yOffsets[6]; int dataOffsets[6]; - int field_3A; + int padding[6]; + int dataSize; } Art; -#pragma pack() typedef struct ArtFrame { short width;