diff --git a/src/object.c b/src/object.c index fe83c540ea..ac0c1d0745 100644 --- a/src/object.c +++ b/src/object.c @@ -83,12 +83,12 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi if (*chunkSize == 0xFFFFFFFF) { chunk = (uint8*)malloc(0x600000); assert(chunk != NULL); - *chunkSize = sawyercoding_read_chunk(rw, chunk); + *chunkSize = sawyercoding_read_chunk_with_size(rw, chunk, 0x600000); chunk = realloc(chunk, *chunkSize); } else { chunk = (uint8*)malloc(*chunkSize); - *chunkSize = sawyercoding_read_chunk(rw, chunk); + *chunkSize = sawyercoding_read_chunk_with_size(rw, chunk, *chunkSize); } SDL_RWclose(rw); if (chunk == NULL) { diff --git a/src/util/sawyercoding.c b/src/util/sawyercoding.c index b903823720..d9622f4d8c 100644 --- a/src/util/sawyercoding.c +++ b/src/util/sawyercoding.c @@ -21,6 +21,7 @@ #include "util.h" static size_t decode_chunk_rle(const uint8* src_buffer, uint8* dst_buffer, size_t length); +static size_t decode_chunk_rle_with_size(const uint8* src_buffer, uint8* dst_buffer, size_t length, size_t dstSize); static size_t decode_chunk_repeat(uint8 *buffer, size_t length); static void decode_chunk_rotate(uint8 *buffer, size_t length); @@ -171,7 +172,7 @@ size_t sawyercoding_read_chunk_with_size(SDL_RWops* rw, uint8 *buffer, const siz memcpy(buffer, src_buffer, chunkHeader.length); break; case CHUNK_ENCODING_RLE: - chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); + chunkHeader.length = decode_chunk_rle_with_size(src_buffer, buffer, chunkHeader.length, buffer_size); break; case CHUNK_ENCODING_RLECOMPRESSED: chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); @@ -360,6 +361,36 @@ static size_t decode_chunk_rle(const uint8* src_buffer, uint8* dst_buffer, size_ return dst - dst_buffer; } +/** + * + * rct2: 0x0067693A + */ +static size_t decode_chunk_rle_with_size(const uint8* src_buffer, uint8* dst_buffer, size_t length, size_t dstSize) +{ + size_t count; + uint8 *dst, rleCodeByte; + + dst = dst_buffer; + + for (size_t i = 0; i < length; i++) { + rleCodeByte = src_buffer[i]; + if (rleCodeByte & 128) { + i++; + count = 257 - rleCodeByte; + memset(dst, src_buffer[i], count); + dst = (uint8*)((uintptr_t)dst + count); + } else { + assert(dst + rleCodeByte + 1 <= dst_buffer + dstSize); + memcpy(dst, src_buffer + i + 1, rleCodeByte + 1); + dst = (uint8*)((uintptr_t)dst + rleCodeByte + 1); + i += rleCodeByte + 1; + } + } + + // Return final size + return dst - dst_buffer; +} + /** * * rct2: 0x006769F1