Skip to content

Commit

Permalink
Fix memory alignment
Browse files Browse the repository at this point in the history
See #135, #122
  • Loading branch information
alexbatalov committed Jan 19, 2023
1 parent 8604d9c commit 2714dc1
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 24 deletions.
76 changes: 55 additions & 21 deletions src/art.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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, '\\');
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -1039,9 +1040,10 @@ int buildFid(int objectType, int frmId, int animType, int a3, int rotation)
}

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

Expand All @@ -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;
}

Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand Down
5 changes: 2 additions & 3 deletions src/art.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ typedef enum Background {
BACKGROUND_COUNT,
} Background;

#pragma pack(2)
typedef struct Art {
int field_0;
short framesPerSecond;
Expand All @@ -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;
Expand Down

0 comments on commit 2714dc1

Please sign in to comment.