diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 8391f685df..8321c688ef 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -20,6 +20,28 @@ #include "../common.h" #include "font.h" +// For g1 only enable packing when still relying on vanilla +#ifndef NO_RCT2 +#pragma pack(push, 1) +#endif +// Size: 0x10 +typedef struct rct_g1_element { + uint8* offset; // 0x00 + sint16 width; // 0x04 + sint16 height; // 0x06 + sint16 x_offset; // 0x08 + sint16 y_offset; // 0x0A + uint16 flags; // 0x0C + uint16 zoomed_offset; // 0x0E +} rct_g1_element; +#ifndef NO_RCT2 +#ifdef PLATFORM_32BIT +assert_struct_size(rct_g1_element, 0x10); +#endif +#pragma pack(pop) +#endif + +// Enable packing for remaining elements #pragma pack(push, 1) // Size: 0x10 typedef struct rct_drawpixelinfo { @@ -35,20 +57,6 @@ typedef struct rct_drawpixelinfo { assert_struct_size(rct_drawpixelinfo, 0x10); #endif -// Size: 0x10 -typedef struct rct_g1_element { - uint8* offset; // 0x00 - sint16 width; // 0x04 - sint16 height; // 0x06 - sint16 x_offset; // 0x08 - sint16 y_offset; // 0x0A - uint16 flags; // 0x0C - uint16 zoomed_offset; // 0x0E -} rct_g1_element; -#ifdef PLATFORM_32BIT -assert_struct_size(rct_g1_element, 0x10); -#endif - enum { G1_FLAG_BMP = (1 << 0), //No invisible sections G1_FLAG_RLE_COMPRESSION = (1<<2), diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index c13a2e6bdd..f36fba412f 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -46,15 +46,49 @@ int gfx_load_g1() file = SDL_RWFromFile(get_file_path(PATH_ID_G1), "rb"); if (file != NULL) { if (SDL_RWread(file, &header, 8, 1) == 1) { - // number of elements is stored in g1.dat, but because the entry headers are static, this can't be variable until - // made into a dynamic array + /* We need to load in the data file, which has an `offset` field, + * which is supposed to hold a pointer, but is only 32 bit long. + * We will load a 32 bit version of rct_g1_element and then convert + * pointers to however long our machine wants them. + */ + + #pragma pack(push, 1) + // Size: 0x10 + typedef struct { + uint32 offset; // 0x00 note: uint32 always! + sint16 width; // 0x04 + sint16 height; // 0x06 + sint16 x_offset; // 0x08 + sint16 y_offset; // 0x0A + uint16 flags; // 0x0C + uint16 zoomed_offset; // 0x0E + } rct_g1_element_32bit; + assert_struct_size(rct_g1_element_32bit, 0x10); + #pragma pack(pop) + + /* number of elements is stored in g1.dat, but because the entry + * headers are static, this can't be variable until made into a + * dynamic array. + */ header.num_entries = 29294; // Read element headers #if NO_RCT2 g1Elements = calloc(324206, sizeof(rct_g1_element)); #endif - SDL_RWread(file, g1Elements, header.num_entries * sizeof(rct_g1_element), 1); + + rct_g1_element_32bit *g1Elements32 = calloc(324206, sizeof(rct_g1_element_32bit)); + SDL_RWread(file, g1Elements32, header.num_entries * sizeof(rct_g1_element_32bit), 1); + for (int i = 0; i < header.num_entries; i++) { + g1Elements[i].offset = (uint8*)g1Elements32[i].offset; + g1Elements[i].width = g1Elements32[i].width; + g1Elements[i].height = g1Elements32[i].height; + g1Elements[i].x_offset = g1Elements32[i].x_offset; + g1Elements[i].y_offset = g1Elements32[i].y_offset; + g1Elements[i].flags = g1Elements32[i].flags; + g1Elements[i].zoomed_offset = g1Elements32[i].zoomed_offset; + } + free(g1Elements32); // Read element data _g1Buffer = malloc(header.total_size); @@ -64,7 +98,7 @@ int gfx_load_g1() // Fix entry data offsets for (i = 0; i < header.num_entries; i++) - g1Elements[i].offset += (int)_g1Buffer; + g1Elements[i].offset += (uintptr_t)_g1Buffer; // Successful return 1;