Fix memory alignment

See #135, #122
This commit is contained in:
Alexander Batalov 2023-01-19 20:27:22 +03:00
parent 8604d9c401
commit 2714dc1ea1
2 changed files with 57 additions and 24 deletions

View File

@ -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 artCacheGetFileSizeImpl(int a1, int* out_size);
static int artCacheReadDataImpl(int a1, int* a2, unsigned char* data); static int artCacheReadDataImpl(int a1, int* a2, unsigned char* data);
static void artCacheFreeImpl(void* ptr); 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 artReadHeader(Art* art, File* stream);
static int artGetDataSize(Art* art);
static int paddingForSize(int size);
// 0x5002D8 // 0x5002D8
static char gDefaultJumpsuitMaleFileName[] = "hmjmps"; static char gDefaultJumpsuitMaleFileName[] = "hmjmps";
@ -833,9 +835,9 @@ ArtFrame* artGetFrame(Art* art, int frame, int rotation)
return NULL; 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++) { 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; return frm;
} }
@ -921,8 +923,8 @@ static int artCacheGetFileSizeImpl(int fid, int* sizePtr)
char* artFilePath = artBuildFilePath(fid); char* artFilePath = artBuildFilePath(fid);
if (artFilePath != NULL) { if (artFilePath != NULL) {
int fileSize;
bool loaded = false; bool loaded = false;
File* stream = NULL;
if (gArtLanguageInitialized) { if (gArtLanguageInitialized) {
char* pch = strchr(artFilePath, '\\'); char* pch = strchr(artFilePath, '\\');
@ -933,21 +935,21 @@ static int artCacheGetFileSizeImpl(int fid, int* sizePtr)
char localizedPath[COMPAT_MAX_PATH]; char localizedPath[COMPAT_MAX_PATH];
snprintf(localizedPath, sizeof(localizedPath), "art\\%s\\%s", gArtLanguage, pch); snprintf(localizedPath, sizeof(localizedPath), "art\\%s\\%s", gArtLanguage, pch);
if (dbGetFileSize(localizedPath, &fileSize) == 0) { stream = fileOpen(localizedPath, "rb");
loaded = true;
}
} }
if (!loaded) { if (stream == NULL) {
if (dbGetFileSize(artFilePath, &fileSize) == 0) { stream = fileOpen(artFilePath, "rb");
loaded = true;
}
} }
if (loaded) { if (stream != NULL) {
*sizePtr = fileSize; Art art;
if (artReadHeader(&art, stream) == 0) {
*sizePtr = artGetDataSize(&art);
result = 0; result = 0;
} }
fileClose(stream);
}
} }
return result; return result;
@ -982,8 +984,7 @@ static int artCacheReadDataImpl(int fid, int* sizePtr, unsigned char* data)
} }
if (loaded) { if (loaded) {
// TODO: Why it adds 74? *sizePtr = artGetDataSize((Art*)data);
*sizePtr = ((Art*)data)->field_3A + 74;
result = 0; result = 0;
} }
} }
@ -1039,9 +1040,10 @@ out:
} }
// 0x419D60 // 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; unsigned char* ptr = data;
int padding = 0;
for (int index = 0; index < count; index++) { for (int index = 0; index < count; index++) {
ArtFrame* frame = (ArtFrame*)ptr; 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; if (fileRead(ptr + sizeof(ArtFrame), frame->size, 1, stream) != 1) return -1;
ptr += sizeof(ArtFrame) + frame->size; ptr += sizeof(ArtFrame) + frame->size;
ptr += paddingForSize(frame->size);
padding += paddingForSize(frame->size);
} }
*paddingPtr = padding;
return 0; 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->xOffsets, ROTATION_COUNT) == -1) return -1;
if (fileReadInt16List(stream, art->yOffsets, 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 (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; return 0;
} }
@ -1087,9 +1093,16 @@ int artRead(const char* path, unsigned char* data)
return -3; return -3;
} }
int currentPadding = paddingForSize(sizeof(Art));
int previousPadding = 0;
for (int index = 0; index < ROTATION_COUNT; index++) { for (int index = 0; index < ROTATION_COUNT; index++) {
art->padding[index] = currentPadding;
if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[index]) { 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); fileClose(stream);
return -5; 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; if (fileWrite(ptr + sizeof(ArtFrame), frame->size, 1, stream) != 1) return -1;
ptr += sizeof(ArtFrame) + frame->size; ptr += sizeof(ArtFrame) + frame->size;
ptr += paddingForSize(frame->size);
} }
return 0; 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->xOffsets, ROTATION_COUNT) == -1) return -1;
if (fileWriteInt16List(stream, art->yOffsets, 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 (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; return 0;
} }
@ -1161,7 +1175,7 @@ int artWrite(const char* path, unsigned char* data)
for (int index = 0; index < ROTATION_COUNT; index++) { for (int index = 0; index < ROTATION_COUNT; index++) {
if (index == 0 || art->dataOffsets[index - 1] != art->dataOffsets[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); fileClose(stream);
return -1; return -1;
} }
@ -1172,6 +1186,26 @@ int artWrite(const char* path, unsigned char* data)
return 0; 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() FrmImage::FrmImage()
{ {
_key = nullptr; _key = nullptr;

View File

@ -67,7 +67,6 @@ typedef enum Background {
BACKGROUND_COUNT, BACKGROUND_COUNT,
} Background; } Background;
#pragma pack(2)
typedef struct Art { typedef struct Art {
int field_0; int field_0;
short framesPerSecond; short framesPerSecond;
@ -76,9 +75,9 @@ typedef struct Art {
short xOffsets[6]; short xOffsets[6];
short yOffsets[6]; short yOffsets[6];
int dataOffsets[6]; int dataOffsets[6];
int field_3A; int padding[6];
int dataSize;
} Art; } Art;
#pragma pack()
typedef struct ArtFrame { typedef struct ArtFrame {
short width; short width;