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 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;

View File

@ -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;