From 928a61e1675129eea1a6371522a0ca7bb16025b3 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Thu, 25 Sep 2014 17:10:33 +0100 Subject: [PATCH 01/19] Still searching for bug --- src/object_list.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/object_list.c b/src/object_list.c index 9765363808..fba5fabb2b 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -184,9 +184,12 @@ int object_read_and_load_entries(FILE *file) // Load the obect if (!object_load(entryGroupIndex, &entries[i])) { // Failed to load the object - free(entries); + //Destroy progress bar + memcpy((char*)0x13CE952, entries[i].name, 8); + free(entries); object_unload_all(); + RCT2_GLOBAL(0x14241BC, uint32) = 0; return 0; } } @@ -201,7 +204,7 @@ int object_read_and_load_entries(FILE *file) */ int object_load_packed() { - int eax, ebx, ecx, edx, esi, edi, ebp; + int eax = 0, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); return eax; } From d2910392a480c059c50f579aa91a9f7af600cf7d Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Thu, 25 Sep 2014 18:34:51 +0100 Subject: [PATCH 02/19] Started reverse of load_object --- src/object.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/object.c b/src/object.c index 24798d7fdb..c6edd25db3 100644 --- a/src/object.c +++ b/src/object.c @@ -20,6 +20,7 @@ #include #include +#include #include "addresses.h" #include "object.h" #include "sawyercoding.h" @@ -30,6 +31,42 @@ */ int object_load(int groupIndex, rct_object_entry *entry) { + RCT2_GLOBAL(0xF42B64, uint32) = groupIndex; + + //part of 6a9866 + rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + + if (!(RCT2_GLOBAL(0xF42B6C, uint32))){ + RCT2_GLOBAL(0xF42BD9, uint8) = 0; + return 1; + } + + if (!(installedObject->flags & 0xF0)){ + if (entry->flags != installedObject->flags || + entry->checksum != installedObject->checksum || + strncmp( entry->name, installedObject->name,8 )){ + //6a9c06 + } + } + else{ + if ((entry->flags & 0xF0) != (installedObject->flags & 0xF0) || + strncmp(entry->name, installedObject->name, 8)){ + //6a9c06 + } + int eax = installedObject->flags >> 4; + if ((eax & 0xFF) != 8){ + if (!(RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16)&(1 << eax))){ + //6a9c06 + } + } + } + installedObject++;// + char* object_path = RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char); + int star_pos = strchr(object_path, '*') - object_path; + object_path = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); + strncpy(RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char), RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), star_pos); + strcat(RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char) + star_pos, installedObject); + //6a991f return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x100); } From 387ce00ae22b16756c833bb943f713e6e93387f3 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Thu, 25 Sep 2014 20:50:38 +0100 Subject: [PATCH 03/19] Added more of object load. Remember to change the openedEntry code --- src/object.c | 117 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 95 insertions(+), 22 deletions(-) diff --git a/src/object.c b/src/object.c index c6edd25db3..2fa767b067 100644 --- a/src/object.c +++ b/src/object.c @@ -25,6 +25,10 @@ #include "object.h" #include "sawyercoding.h" +int object_entry_compare(rct_object_entry *a, rct_object_entry *b); +int object_calculate_checksum(rct_object_entry *entry, char *data, int dataLength); +int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp); +rct_object_entry *object_get_next(rct_object_entry *entry); /** * * rct2: 0x006A985D @@ -40,32 +44,101 @@ int object_load(int groupIndex, rct_object_entry *entry) RCT2_GLOBAL(0xF42BD9, uint8) = 0; return 1; } - - if (!(installedObject->flags & 0xF0)){ - if (entry->flags != installedObject->flags || - entry->checksum != installedObject->checksum || - strncmp( entry->name, installedObject->name,8 )){ - //6a9c06 - } - } - else{ - if ((entry->flags & 0xF0) != (installedObject->flags & 0xF0) || - strncmp(entry->name, installedObject->name, 8)){ - //6a9c06 - } - int eax = installedObject->flags >> 4; - if ((eax & 0xFF) != 8){ - if (!(RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16)&(1 << eax))){ + for (int i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) { + if (!(installedObject->flags & 0xF0)){ + if (entry->flags != installedObject->flags || + entry->checksum != installedObject->checksum || + strncmp(entry->name, installedObject->name, 8)){ //6a9c06 } } + else{ + if ((entry->flags & 0xF0) != (installedObject->flags & 0xF0) || + strncmp(entry->name, installedObject->name, 8)){ + //6a9c06 + } + int eax = installedObject->flags >> 4; + if ((eax & 0xFF) != 8){ + if (!(RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16)&(1 << eax))){ + //6a9c06 + } + } + } + + char path[260]; + char *objectPath = (char*)installedObject + 16; + subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); + rct_object_entry openedEntry; + FILE *file = fopen(path, "rb"); + if (file != NULL) { + fread(&openedEntry, sizeof(rct_object_entry), 1, file); + if (object_entry_compare(&openedEntry, entry)) { + + // Get chunk size + char *pos = (char*)installedObject + 16; + do { + pos++; + } while (*(pos - 1) != 0); + + // Read chunk + int chunkSize = *((uint32*)pos); + char *chunk; + if (chunkSize == 0xFFFFFFFF) { + chunk = malloc(0x600000); + chunkSize = sawyercoding_read_chunk(file, chunk); + chunk = realloc(chunk, chunkSize); + } + else { + chunk = malloc(chunkSize); + sawyercoding_read_chunk(file, chunk); + } + fclose(file); + + // Calculate and check checksum + if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) { + RCT2_GLOBAL(0x00F42BD9, uint8) = 2; + free(chunk); + return 0; + } + + if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) { + RCT2_GLOBAL(0x00F42BD9, uint8) = 3; + free(chunk); + return 0; + } + + int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); + + if (yyy >= 0x4726E){ + RCT2_GLOBAL(0x00F42BD9, uint8) = 4; + free(chunk); + return 0; + } + + int ebp = RCT2_GLOBAL(0xF42B84, uint16) & 0xF; + int esi = RCT2_ADDRESS(0x98D97C, uint32)[ebp * 2]; + int ecx = RCT2_GLOBAL(0xF42B64, sint32); + if (ecx == -1){ + for (int ecx = 0; ((sint32*)esi)[ecx] != -1; ecx++){ + if ((ecx + 1) >= RCT2_ADDRESS(0x98DA00, uint16)[ebp]){ + RCT2_GLOBAL(0x00F42BD9, uint8) = 5; + free(chunk); + return 0; + } + } + } + ((sint32*)esi)[ecx] = chunk; + + int* edx = ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[ebp * 2]; + memcpy(edx, (int*)0xF42B84, 20); + if (RCT2_GLOBAL(0x9ADAFD, uint8) == 0)return 1; + object_paint(ecx, 0, ecx, ebp, 0, (int)chunk, 0, 0); + return 1; + } + fclose(file); + } + installedObject = object_get_next(installedObject); } - installedObject++;// - char* object_path = RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char); - int star_pos = strchr(object_path, '*') - object_path; - object_path = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); - strncpy(RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char), RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), star_pos); - strcat(RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char) + star_pos, installedObject); //6a991f return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x100); } From 81121db634ef1395f1c1c8dabd6f6b480a660179 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Fri, 26 Sep 2014 17:54:05 +0100 Subject: [PATCH 04/19] Still trying to find bug --- src/object.c | 143 +++++++++++++++++++++++---------------------------- 1 file changed, 63 insertions(+), 80 deletions(-) diff --git a/src/object.c b/src/object.c index 2fa767b067..eed34e230e 100644 --- a/src/object.c +++ b/src/object.c @@ -45,97 +45,80 @@ int object_load(int groupIndex, rct_object_entry *entry) return 1; } for (int i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) { - if (!(installedObject->flags & 0xF0)){ - if (entry->flags != installedObject->flags || - entry->checksum != installedObject->checksum || - strncmp(entry->name, installedObject->name, 8)){ - //6a9c06 - } - } - else{ - if ((entry->flags & 0xF0) != (installedObject->flags & 0xF0) || - strncmp(entry->name, installedObject->name, 8)){ - //6a9c06 - } - int eax = installedObject->flags >> 4; - if ((eax & 0xFF) != 8){ - if (!(RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16)&(1 << eax))){ - //6a9c06 - } - } - } + if (object_entry_compare(installedObject, entry)){ - char path[260]; - char *objectPath = (char*)installedObject + 16; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); - rct_object_entry openedEntry; - FILE *file = fopen(path, "rb"); - if (file != NULL) { - fread(&openedEntry, sizeof(rct_object_entry), 1, file); - if (object_entry_compare(&openedEntry, entry)) { + char path[260]; + char *objectPath = (char*)installedObject + 16; + subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); + rct_object_entry openedEntry; + FILE *file = fopen(path, "rb"); + if (file != NULL) { + fread(&openedEntry, sizeof(rct_object_entry), 1, file); + if (object_entry_compare(&openedEntry, entry)) { - // Get chunk size - char *pos = (char*)installedObject + 16; - do { - pos++; - } while (*(pos - 1) != 0); + // Get chunk size + char *pos = (char*)installedObject + 16; + do { + pos++; + } while (*(pos - 1) != 0); - // Read chunk - int chunkSize = *((uint32*)pos); - char *chunk; - if (chunkSize == 0xFFFFFFFF) { - chunk = malloc(0x600000); - chunkSize = sawyercoding_read_chunk(file, chunk); - chunk = realloc(chunk, chunkSize); - } - else { - chunk = malloc(chunkSize); - sawyercoding_read_chunk(file, chunk); - } - fclose(file); + // Read chunk + int chunkSize = *((uint32*)pos); + char *chunk; + //if (chunkSize == 0xFFFFFFFF) { + chunk = malloc(0x600000); + chunkSize = sawyercoding_read_chunk(file, chunk); + chunk = realloc(chunk, chunkSize); + //} + //else { + // chunk = malloc(chunkSize); + // chunkSize = sawyercoding_read_chunk(file, chunk); + //} + fclose(file); - // Calculate and check checksum - if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) { - RCT2_GLOBAL(0x00F42BD9, uint8) = 2; - free(chunk); - return 0; - } + // Calculate and check checksum + if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) { + RCT2_GLOBAL(0x00F42BD9, uint8) = 2; + free(chunk); + return 0; + } - if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) { - RCT2_GLOBAL(0x00F42BD9, uint8) = 3; - free(chunk); - return 0; - } + if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) { + RCT2_GLOBAL(0x00F42BD9, uint8) = 3; + free(chunk); + return 0; + } - int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); + int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); - if (yyy >= 0x4726E){ - RCT2_GLOBAL(0x00F42BD9, uint8) = 4; - free(chunk); - return 0; - } - - int ebp = RCT2_GLOBAL(0xF42B84, uint16) & 0xF; - int esi = RCT2_ADDRESS(0x98D97C, uint32)[ebp * 2]; - int ecx = RCT2_GLOBAL(0xF42B64, sint32); - if (ecx == -1){ - for (int ecx = 0; ((sint32*)esi)[ecx] != -1; ecx++){ - if ((ecx + 1) >= RCT2_ADDRESS(0x98DA00, uint16)[ebp]){ - RCT2_GLOBAL(0x00F42BD9, uint8) = 5; - free(chunk); - return 0; + if (yyy >= 0x4726E){ + RCT2_GLOBAL(0x00F42BD9, uint8) = 4; + free(chunk); + return 0; + } + //B84 is openedEntry + int ebp = openedEntry.flags & 0x0F; + int esi = RCT2_ADDRESS(0x98D97C, uint32)[ebp * 2]; + int ecx = groupIndex; + if (ecx == -1){ + for (int ecx = 0; ((sint32*)esi)[ecx] != -1; ecx++){ + if ((ecx + 1) >= RCT2_ADDRESS(0x98DA00, uint16)[ebp]){ + RCT2_GLOBAL(0x00F42BD9, uint8) = 5; + free(chunk); + return 0; + } } } - } - ((sint32*)esi)[ecx] = chunk; + ((sint32*)esi)[ecx] = chunk; - int* edx = ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[ebp * 2]; - memcpy(edx, (int*)0xF42B84, 20); - if (RCT2_GLOBAL(0x9ADAFD, uint8) == 0)return 1; - object_paint(ecx, 0, ecx, ebp, 0, (int)chunk, 0, 0); - return 1; + int* edx = ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[ebp * 2]; + memcpy(edx, (int*)&openedEntry, 20); + if (RCT2_GLOBAL(0x9ADAFD, uint8) == 0)return 1; + object_paint(ecx, 0, ecx, ebp, 0, (int)chunk, 0, 0); + return 1; + } + fclose(file); } - fclose(file); } installedObject = object_get_next(installedObject); } From 5cf517c7896493700447b2d42c5aee9e99726c35 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 27 Sep 2014 12:05:40 +0100 Subject: [PATCH 05/19] Added a fixed version of read_chunk requires more testing before joining --- src/object.c | 23 +++++++------- src/sawyercoding.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ src/sawyercoding.h | 1 + 3 files changed, 92 insertions(+), 11 deletions(-) diff --git a/src/object.c b/src/object.c index eed34e230e..191161855b 100644 --- a/src/object.c +++ b/src/object.c @@ -65,15 +65,16 @@ int object_load(int groupIndex, rct_object_entry *entry) // Read chunk int chunkSize = *((uint32*)pos); char *chunk; - //if (chunkSize == 0xFFFFFFFF) { + + if (chunkSize == 0xFFFFFFFF) { chunk = malloc(0x600000); - chunkSize = sawyercoding_read_chunk(file, chunk); + chunkSize = sawyercoding_read_chunk_variable(file, &chunk); chunk = realloc(chunk, chunkSize); - //} - //else { - // chunk = malloc(chunkSize); - // chunkSize = sawyercoding_read_chunk(file, chunk); - //} + } + else { + chunk = malloc(chunkSize); + chunkSize = sawyercoding_read_chunk_variable(file, &chunk); + } fclose(file); // Calculate and check checksum @@ -83,10 +84,10 @@ int object_load(int groupIndex, rct_object_entry *entry) return 0; } - if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) { - RCT2_GLOBAL(0x00F42BD9, uint8) = 3; - free(chunk); - return 0; + if (object_paint(openedEntry.flags & 0x0F, 2, 0, openedEntry.flags & 0x0F, 0, (int)chunk, 0, 0)) { + //RCT2_GLOBAL(0x00F42BD9, uint8) = 3; + //free(chunk); + //return 0; } int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); diff --git a/src/sawyercoding.c b/src/sawyercoding.c index 10af63d500..f426d60344 100644 --- a/src/sawyercoding.c +++ b/src/sawyercoding.c @@ -68,6 +68,85 @@ int sawyercoding_validate_checksum(FILE *file) return checksum == fileChecksum; } +int decode_chunk_rle_variable(uint8 *src_buffer, uint8** dst_buffer, int src_length); +/** +* +* rct2: 0x0067685F +* buffer (esi) +* this is a temp function +*/ +int sawyercoding_read_chunk_variable(FILE *file, uint8 **dst_buffer) +{ + sawyercoding_chunk_header chunkHeader; + + // Read chunk header + if (fread(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file) != 1) { + RCT2_ERROR("Unable to read chunk header!"); + return -1; + } + + uint8* src_buffer = malloc(chunkHeader.length); + // Read chunk data + if (fread(src_buffer, chunkHeader.length, 1, file) != 1) { + free(src_buffer); + RCT2_ERROR("Unable to read chunk data!"); + return -1; + } + + + // Decode chunk data + switch (chunkHeader.encoding) { + case CHUNK_ENCODING_RLE: + chunkHeader.length = decode_chunk_rle_variable(src_buffer, dst_buffer, chunkHeader.length); + break; + case CHUNK_ENCODING_ROTATE: + decode_chunk_rotate(src_buffer, chunkHeader.length); + memcpy(*dst_buffer, src_buffer, chunkHeader.length); + break; + default: + // For now this is temp function + free(src_buffer); + RCT2_ERROR("Unable to read chunk data!"); + return -1; + break; + } + + free(src_buffer); + // Set length + RCT2_GLOBAL(0x009E3828, uint32) = chunkHeader.length; + return chunkHeader.length; +} + +/** +* Temp function +* rct2: 0x0067693A +*/ +int decode_chunk_rle_variable(uint8* src_buffer, uint8 **dst_buffer, int src_length) +{ + int i, j, count; + unsigned char *src, *dst, rleCodeByte; + + src = src_buffer; + dst = *dst_buffer; + + for (i = 0; i < src_length; i++) { + rleCodeByte = src[i]; + if (rleCodeByte & 128) { + i++; + count = 257 - rleCodeByte; + for (j = 0; j < count; j++) + *dst++ = src[i]; + } + else { + for (j = 0; j <= rleCodeByte; j++) + *dst++ = src[++i]; + } + } + + // Return final size + return dst - *dst_buffer; +} + /** * * rct2: 0x0067685F diff --git a/src/sawyercoding.h b/src/sawyercoding.h index 38916cf1c3..f62bf82301 100644 --- a/src/sawyercoding.h +++ b/src/sawyercoding.h @@ -38,5 +38,6 @@ enum { int sawyercoding_validate_checksum(FILE *file); int sawyercoding_read_chunk(FILE *file, uint8 *buffer); +int sawyercoding_read_chunk_variable(FILE *file, uint8 **buffer); #endif From a63ad06e7668e11279aae84b86efcdca2a817342 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 27 Sep 2014 12:59:07 +0100 Subject: [PATCH 06/19] Fixed remaining bugs caused by not using rct2 malloc. --- src/object.c | 26 +++++++++++++------------- src/sawyercoding.c | 7 +++++++ 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/object.c b/src/object.c index 191161855b..3081f3557c 100644 --- a/src/object.c +++ b/src/object.c @@ -65,14 +65,14 @@ int object_load(int groupIndex, rct_object_entry *entry) // Read chunk int chunkSize = *((uint32*)pos); char *chunk; - + if (chunkSize == 0xFFFFFFFF) { - chunk = malloc(0x600000); + chunk = rct2_malloc(0x600000); chunkSize = sawyercoding_read_chunk_variable(file, &chunk); - chunk = realloc(chunk, chunkSize); + chunk = rct2_realloc(chunk, chunkSize); } else { - chunk = malloc(chunkSize); + chunk = rct2_malloc(chunkSize); chunkSize = sawyercoding_read_chunk_variable(file, &chunk); } fclose(file); @@ -85,9 +85,9 @@ int object_load(int groupIndex, rct_object_entry *entry) } if (object_paint(openedEntry.flags & 0x0F, 2, 0, openedEntry.flags & 0x0F, 0, (int)chunk, 0, 0)) { - //RCT2_GLOBAL(0x00F42BD9, uint8) = 3; - //free(chunk); - //return 0; + RCT2_GLOBAL(0x00F42BD9, uint8) = 3; + free(chunk); + return 0; } int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); @@ -110,9 +110,9 @@ int object_load(int groupIndex, rct_object_entry *entry) } } } - ((sint32*)esi)[ecx] = chunk; + ((char**)esi)[ecx] = chunk; - int* edx = ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[ebp * 2]; + int* edx = (int*)( ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[ebp * 2]); memcpy(edx, (int*)&openedEntry, 20); if (RCT2_GLOBAL(0x9ADAFD, uint8) == 0)return 1; object_paint(ecx, 0, ecx, ebp, 0, (int)chunk, 0, 0); @@ -124,7 +124,7 @@ int object_load(int groupIndex, rct_object_entry *entry) installedObject = object_get_next(installedObject); } //6a991f - return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x100); + return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x400); } /** @@ -208,7 +208,7 @@ int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, if (type == 10){ if (eax == 0) return object_scenario_load_custom_text((char*)esi); } - return RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098D9D4, uint32)[type], eax, ebx, ecx, edx, esi, edi, ebp) & 0x400; + return RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098D9D4, uint32)[type], eax, ebx, ecx, edx, esi, edi, ebp) & 0x100; } /** @@ -309,7 +309,7 @@ rct_object_entry *object_get_next(rct_object_entry *entry) { char *pos = (char*)entry; - // Skip + // Skip sizeof(rct_object_entry) pos += 16; // Skip filename @@ -325,7 +325,7 @@ rct_object_entry *object_get_next(rct_object_entry *entry) pos++; } while (*(pos - 1) != 0); - // Skip + // Skip size of chunk pos += 4; // Skip diff --git a/src/sawyercoding.c b/src/sawyercoding.c index f426d60344..373bc8f477 100644 --- a/src/sawyercoding.c +++ b/src/sawyercoding.c @@ -103,6 +103,13 @@ int sawyercoding_read_chunk_variable(FILE *file, uint8 **dst_buffer) decode_chunk_rotate(src_buffer, chunkHeader.length); memcpy(*dst_buffer, src_buffer, chunkHeader.length); break; + case CHUNK_ENCODING_RLECOMPRESSED: + chunkHeader.length = decode_chunk_rle_variable(src_buffer, dst_buffer, chunkHeader.length); + chunkHeader.length = decode_chunk_repeat(*dst_buffer, chunkHeader.length); + break; + case 0: + memcpy(*dst_buffer, src_buffer, chunkHeader.length); + break; default: // For now this is temp function free(src_buffer); From 335aca4164560f61de828754348a174b1b06a37e Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 27 Sep 2014 14:26:32 +0100 Subject: [PATCH 07/19] Cso now partially working. --- src/game.c | 2 +- src/object.c | 12 +++++----- src/object.h | 4 +++- src/object_list.c | 56 +++++++++++++++++++++++++++++++++++++++++++---- src/scenario.c | 2 +- 5 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/game.c b/src/game.c index 68f5448448..fbf7de384f 100644 --- a/src/game.c +++ b/src/game.c @@ -726,7 +726,7 @@ int game_load_save() if (s6Header->num_packed_objects > 0) { j = 0; for (i = 0; i < s6Header->num_packed_objects; i++) - j += object_load_packed(); + j += object_load_packed(file); if (j > 0) object_list_load(); } diff --git a/src/object.c b/src/object.c index 3081f3557c..9d2e01dbb5 100644 --- a/src/object.c +++ b/src/object.c @@ -80,13 +80,13 @@ int object_load(int groupIndex, rct_object_entry *entry) // Calculate and check checksum if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) { RCT2_GLOBAL(0x00F42BD9, uint8) = 2; - free(chunk); + rct2_free(chunk); return 0; } if (object_paint(openedEntry.flags & 0x0F, 2, 0, openedEntry.flags & 0x0F, 0, (int)chunk, 0, 0)) { RCT2_GLOBAL(0x00F42BD9, uint8) = 3; - free(chunk); + rct2_free(chunk); return 0; } @@ -94,7 +94,7 @@ int object_load(int groupIndex, rct_object_entry *entry) if (yyy >= 0x4726E){ RCT2_GLOBAL(0x00F42BD9, uint8) = 4; - free(chunk); + rct2_free(chunk); return 0; } //B84 is openedEntry @@ -105,7 +105,7 @@ int object_load(int groupIndex, rct_object_entry *entry) for (int ecx = 0; ((sint32*)esi)[ecx] != -1; ecx++){ if ((ecx + 1) >= RCT2_ADDRESS(0x98DA00, uint16)[ebp]){ RCT2_GLOBAL(0x00F42BD9, uint8) = 5; - free(chunk); + rct2_free(chunk); return 0; } } @@ -124,6 +124,8 @@ int object_load(int groupIndex, rct_object_entry *entry) installedObject = object_get_next(installedObject); } //6a991f + object_load(groupIndex, entry); + return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x400); } @@ -159,7 +161,7 @@ static int object_entry_compare(rct_object_entry *a, rct_object_entry *b) return 1; } -static int object_calculate_checksum(rct_object_entry *entry, char *data, int dataLength) +int object_calculate_checksum(rct_object_entry *entry, char *data, int dataLength) { int i; char *eee = (char*)entry; diff --git a/src/object.h b/src/object.h index 04e14eb220..70bddc040c 100644 --- a/src/object.h +++ b/src/object.h @@ -47,7 +47,7 @@ typedef struct { void object_list_load(); int object_read_and_load_entries(FILE *file); -int object_load_packed(); +int object_load_packed(FILE *file); void object_unload_all(); int object_load(int groupIndex, rct_object_entry *entry); @@ -56,5 +56,7 @@ int object_get_scenario_text(rct_object_entry *entry); void object_free_scenario_text(); int object_get_length(rct_object_entry *entry); rct_object_entry *object_get_next(rct_object_entry *entry); +int object_calculate_checksum(rct_object_entry *entry, char *data, int dataLength); +int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp); #endif diff --git a/src/object_list.c b/src/object_list.c index fba5fabb2b..d3700f0dab 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -166,7 +166,7 @@ int object_read_and_load_entries(FILE *file) // Read all the object entries entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry)); - sawyercoding_read_chunk(file, (uint8*)entries); + sawyercoding_read_chunk_variable(file, (uint8**)&entries); // Load each object for (i = 0; i < OBJECT_ENTRY_COUNT; i++) { @@ -202,10 +202,58 @@ int object_read_and_load_entries(FILE *file) * * rct2: 0x006AA2B7 */ -int object_load_packed() +int object_load_packed(FILE *file) { - int eax = 0, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; - RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + object_unload_all(); + + rct_object_entry* entry = RCT2_ADDRESS(0xF42B84, rct_object_entry); + + fread((void*)entry, 16, 1, file); + + uint8* chunk = rct2_malloc(0x600000); + uint32 chunkSize = sawyercoding_read_chunk_variable(file, &chunk); + chunk = rct2_realloc(chunk, chunkSize); + if (chunk == NULL){ + return 0; + } + + if (object_calculate_checksum(entry, chunk, chunkSize) != entry->checksum){ + rct2_free(chunk); + return 0; + } + + if (object_paint(entry->flags & 0x0F, 2, 0, entry->flags & 0x0F, 0, (int)chunk, 0, 0)) { + rct2_free(chunk); + return 0; + } + + int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); + + if (yyy >= 0x4726E){ + rct2_free(chunk); + return 0; + } + + int type = entry->flags & 0x0F; + int ecx = 0; + + for (; ecx < RCT2_ADDRESS(0x98DA00, uint16)[type]; ecx++){ + if (RCT2_ADDRESS(0x98D97C, uint32*)[type * 2][ecx] == -1){ + break; + } + } + + if (ecx == RCT2_ADDRESS(0x98DA00, uint16)[type]){ + rct2_free(chunk); + return 0; + } + + RCT2_ADDRESS(0x98D97C, uint8**)[type * 2][ecx] = chunk; + int* edx = (int*)(ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); + memcpy(edx, (int*)entry, 20); + //6aa429 + int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; + //RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); return eax; } diff --git a/src/scenario.c b/src/scenario.c index 8e58d09e78..b27fd4f830 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -109,7 +109,7 @@ void scenario_load(const char *path) if (s6Header->num_packed_objects > 0) { j = 0; for (i = 0; i < s6Header->num_packed_objects; i++) - j += object_load_packed(); + j += object_load_packed(file); if (j > 0) object_list_load(); } From 72c1acf2070776c90b58ba2fdb324d1902d8c894 Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 29 Sep 2014 12:43:12 +0100 Subject: [PATCH 08/19] Integrated fix of read chunk into main code --- src/sawyercoding.c | 120 +++++++-------------------------------------- 1 file changed, 18 insertions(+), 102 deletions(-) diff --git a/src/sawyercoding.c b/src/sawyercoding.c index 373bc8f477..6e5ccecc65 100644 --- a/src/sawyercoding.c +++ b/src/sawyercoding.c @@ -24,7 +24,7 @@ #include "rct2.h" #include "sawyercoding.h" -static int decode_chunk_rle(char *buffer, int length); +static int decode_chunk_rle(uint8* src_buffer, uint8* dst_buffer, int length); static int decode_chunk_repeat(char *buffer, int length); static void decode_chunk_rotate(char *buffer, int length); @@ -68,91 +68,6 @@ int sawyercoding_validate_checksum(FILE *file) return checksum == fileChecksum; } -int decode_chunk_rle_variable(uint8 *src_buffer, uint8** dst_buffer, int src_length); -/** -* -* rct2: 0x0067685F -* buffer (esi) -* this is a temp function -*/ -int sawyercoding_read_chunk_variable(FILE *file, uint8 **dst_buffer) -{ - sawyercoding_chunk_header chunkHeader; - - // Read chunk header - if (fread(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file) != 1) { - RCT2_ERROR("Unable to read chunk header!"); - return -1; - } - - uint8* src_buffer = malloc(chunkHeader.length); - // Read chunk data - if (fread(src_buffer, chunkHeader.length, 1, file) != 1) { - free(src_buffer); - RCT2_ERROR("Unable to read chunk data!"); - return -1; - } - - - // Decode chunk data - switch (chunkHeader.encoding) { - case CHUNK_ENCODING_RLE: - chunkHeader.length = decode_chunk_rle_variable(src_buffer, dst_buffer, chunkHeader.length); - break; - case CHUNK_ENCODING_ROTATE: - decode_chunk_rotate(src_buffer, chunkHeader.length); - memcpy(*dst_buffer, src_buffer, chunkHeader.length); - break; - case CHUNK_ENCODING_RLECOMPRESSED: - chunkHeader.length = decode_chunk_rle_variable(src_buffer, dst_buffer, chunkHeader.length); - chunkHeader.length = decode_chunk_repeat(*dst_buffer, chunkHeader.length); - break; - case 0: - memcpy(*dst_buffer, src_buffer, chunkHeader.length); - break; - default: - // For now this is temp function - free(src_buffer); - RCT2_ERROR("Unable to read chunk data!"); - return -1; - break; - } - - free(src_buffer); - // Set length - RCT2_GLOBAL(0x009E3828, uint32) = chunkHeader.length; - return chunkHeader.length; -} - -/** -* Temp function -* rct2: 0x0067693A -*/ -int decode_chunk_rle_variable(uint8* src_buffer, uint8 **dst_buffer, int src_length) -{ - int i, j, count; - unsigned char *src, *dst, rleCodeByte; - - src = src_buffer; - dst = *dst_buffer; - - for (i = 0; i < src_length; i++) { - rleCodeByte = src[i]; - if (rleCodeByte & 128) { - i++; - count = 257 - rleCodeByte; - for (j = 0; j < count; j++) - *dst++ = src[i]; - } - else { - for (j = 0; j <= rleCodeByte; j++) - *dst++ = src[++i]; - } - } - - // Return final size - return dst - *dst_buffer; -} /** * @@ -169,26 +84,33 @@ int sawyercoding_read_chunk(FILE *file, uint8 *buffer) return -1; } + uint8* src_buffer = malloc(chunkHeader.length); + // Read chunk data - if (fread(buffer, chunkHeader.length, 1, file) != 1) { + if (fread(src_buffer, chunkHeader.length, 1, file) != 1) { + free(src_buffer); RCT2_ERROR("Unable to read chunk data!"); return -1; } // Decode chunk data switch (chunkHeader.encoding) { + case CHUNK_ENCODING_NONE: + memcpy(buffer, src_buffer, chunkHeader.length); + break; case CHUNK_ENCODING_RLE: - chunkHeader.length = decode_chunk_rle(buffer, chunkHeader.length); + chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); break; case CHUNK_ENCODING_RLECOMPRESSED: - chunkHeader.length = decode_chunk_rle(buffer, chunkHeader.length); + chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); chunkHeader.length = decode_chunk_repeat(buffer, chunkHeader.length); break; case CHUNK_ENCODING_ROTATE: + memcpy(buffer, src_buffer, chunkHeader.length); decode_chunk_rotate(buffer, chunkHeader.length); break; } - + free(src_buffer); // Set length RCT2_GLOBAL(0x009E3828, uint32) = chunkHeader.length; return chunkHeader.length; @@ -198,32 +120,26 @@ int sawyercoding_read_chunk(FILE *file, uint8 *buffer) * * rct2: 0x0067693A */ -static int decode_chunk_rle(char *buffer, int length) +static int decode_chunk_rle(uint8* src_buffer, uint8* dst_buffer, int length) { int i, j, count; - unsigned char *src, *dst, rleCodeByte; + uint8 *dst, rleCodeByte; - // Backup buffer - src = malloc(length); - memcpy(src, buffer, length); - dst = buffer; + dst = dst_buffer; for (i = 0; i < length; i++) { - rleCodeByte = src[i]; + rleCodeByte = src_buffer[i]; if (rleCodeByte & 128) { i++; count = 257 - rleCodeByte; for (j = 0; j < count; j++) - *dst++ = src[i]; + *dst++ = src_buffer[i]; } else { for (j = 0; j <= rleCodeByte; j++) - *dst++ = src[++i]; + *dst++ = src_buffer[++i]; } } - // Free backup buffer - free(src); - // Return final size return (char*)dst - buffer; } From 1133f7b6095d8363a5048a08023e2f0536151b68 Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 29 Sep 2014 12:43:43 +0100 Subject: [PATCH 09/19] Removed redundant function --- src/sawyercoding.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sawyercoding.h b/src/sawyercoding.h index f62bf82301..38916cf1c3 100644 --- a/src/sawyercoding.h +++ b/src/sawyercoding.h @@ -38,6 +38,5 @@ enum { int sawyercoding_validate_checksum(FILE *file); int sawyercoding_read_chunk(FILE *file, uint8 *buffer); -int sawyercoding_read_chunk_variable(FILE *file, uint8 **buffer); #endif From 85ccec488546c55be535fb71059383ee74d7666c Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 29 Sep 2014 12:46:26 +0100 Subject: [PATCH 10/19] Switched to main version of chunk read. --- src/object.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/object.c b/src/object.c index 9d2e01dbb5..bed506afdf 100644 --- a/src/object.c +++ b/src/object.c @@ -68,12 +68,12 @@ int object_load(int groupIndex, rct_object_entry *entry) if (chunkSize == 0xFFFFFFFF) { chunk = rct2_malloc(0x600000); - chunkSize = sawyercoding_read_chunk_variable(file, &chunk); + chunkSize = sawyercoding_read_chunk(file, chunk); chunk = rct2_realloc(chunk, chunkSize); } else { chunk = rct2_malloc(chunkSize); - chunkSize = sawyercoding_read_chunk_variable(file, &chunk); + chunkSize = sawyercoding_read_chunk(file, chunk); } fclose(file); @@ -124,9 +124,9 @@ int object_load(int groupIndex, rct_object_entry *entry) installedObject = object_get_next(installedObject); } //6a991f - object_load(groupIndex, entry); - - return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x400); + // Installed Object can not be found. + return 0; + //return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x400); } /** @@ -340,4 +340,4 @@ rct_object_entry *object_get_next(rct_object_entry *entry) pos += 4; return (rct_object_entry*)pos; -} \ No newline at end of file +} From 760ecf1525d611230420c76834a816fbf8584b20 Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 29 Sep 2014 12:47:33 +0100 Subject: [PATCH 11/19] Switched to main version of chunk read. --- src/object_list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/object_list.c b/src/object_list.c index d3700f0dab..b84c6757c2 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -211,7 +211,7 @@ int object_load_packed(FILE *file) fread((void*)entry, 16, 1, file); uint8* chunk = rct2_malloc(0x600000); - uint32 chunkSize = sawyercoding_read_chunk_variable(file, &chunk); + uint32 chunkSize = sawyercoding_read_chunk(file, chunk); chunk = rct2_realloc(chunk, chunkSize); if (chunk == NULL){ return 0; @@ -269,4 +269,4 @@ void object_unload_all() for (j = 0; j < object_entry_group_counts[i]; j++) if (object_entry_groups[i].data[j] != (void**)0xFFFFFFFF) object_unload(j, &object_entry_groups[i].entries[j]); -} \ No newline at end of file +} From 44a48624669c78eb322442ae709f79948d28e948 Mon Sep 17 00:00:00 2001 From: Duncan Date: Mon, 29 Sep 2014 12:58:48 +0100 Subject: [PATCH 12/19] Small refactoring of load packed --- src/object_list.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/object_list.c b/src/object_list.c index b84c6757c2..0c759b6d87 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -34,6 +34,7 @@ typedef struct { uint32 var_10; } rct_plugin_header; +// 98DA00 int object_entry_group_counts[] = { 128, // rides 252, // small scenery @@ -235,21 +236,23 @@ int object_load_packed(FILE *file) } int type = entry->flags & 0x0F; - int ecx = 0; + + // ecx + int entryGroupIndex = 0; - for (; ecx < RCT2_ADDRESS(0x98DA00, uint16)[type]; ecx++){ - if (RCT2_ADDRESS(0x98D97C, uint32*)[type * 2][ecx] == -1){ + for (; entryGroupIndex < object_entry_group_counts[type]; entryGroupIndex++){ + if (RCT2_ADDRESS(0x98D97C, uint32*)[type * 2][entryGroupIndex] == -1){ break; } } - if (ecx == RCT2_ADDRESS(0x98DA00, uint16)[type]){ + if (entryGroupIndex == object_entry_group_counts[type]){ rct2_free(chunk); return 0; } - RCT2_ADDRESS(0x98D97C, uint8**)[type * 2][ecx] = chunk; - int* edx = (int*)(ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); + RCT2_ADDRESS(0x98D97C, uint8**)[type * 2][entryGroupIndex] = chunk; + int* edx = (int*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); memcpy(edx, (int*)entry, 20); //6aa429 int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; From a1a3df8158a9fff9e5f88c9898e1321266c47f5e Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Mon, 29 Sep 2014 19:07:25 +0100 Subject: [PATCH 13/19] Added more of load packed --- src/object.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ src/object.h | 2 + src/object_list.c | 61 +----------------------------- src/sawyercoding.c | 2 +- 4 files changed, 98 insertions(+), 61 deletions(-) diff --git a/src/object.c b/src/object.c index bed506afdf..dfc8088f04 100644 --- a/src/object.c +++ b/src/object.c @@ -21,7 +21,9 @@ #include #include #include +#include #include "addresses.h" +#include "string_ids.h" #include "object.h" #include "sawyercoding.h" @@ -129,6 +131,98 @@ int object_load(int groupIndex, rct_object_entry *entry) //return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x400); } +/** +* +* rct2: 0x006AA2B7 +*/ +int object_load_packed(FILE *file) +{ + object_unload_all(); + + rct_object_entry* entry = RCT2_ADDRESS(0xF42B84, rct_object_entry); + + fread((void*)entry, 16, 1, file); + + uint8* chunk = rct2_malloc(0x600000); + uint32 chunkSize = sawyercoding_read_chunk(file, chunk); + chunk = rct2_realloc(chunk, chunkSize); + if (chunk == NULL){ + return 0; + } + + if (object_calculate_checksum(entry, chunk, chunkSize) != entry->checksum){ + rct2_free(chunk); + return 0; + } + + if (object_paint(entry->flags & 0x0F, 2, 0, entry->flags & 0x0F, 0, (int)chunk, 0, 0)) { + rct2_free(chunk); + return 0; + } + + int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); + + if (yyy >= 0x4726E){ + rct2_free(chunk); + return 0; + } + + int type = entry->flags & 0x0F; + + // ecx + int entryGroupIndex = 0; + + for (; entryGroupIndex < object_entry_group_counts[type]; entryGroupIndex++){ + if (RCT2_ADDRESS(0x98D97C, uint32*)[type * 2][entryGroupIndex] == -1){ + break; + } + } + + if (entryGroupIndex == object_entry_group_counts[type]){ + rct2_free(chunk); + return 0; + } + + RCT2_ADDRESS(0x98D97C, uint8**)[type * 2][entryGroupIndex] = chunk; + int* edx = (int*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); + memcpy(edx, (int*)entry, 20); + + //esi + rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + + if (RCT2_GLOBAL(0xF42B6C, uint32)){ + for (uint32 i = 0; i < RCT2_GLOBAL(0xF42B6C, uint32); ++i){ + if (!object_entry_compare(entry, installedObject)){ + object_unload_all(); + return 0; + } + installedObject = object_get_next(installedObject); + } + } + + //Installing new data + //format_string(0x141ED68, 3163, 0); + //Code for updating progress bar removed. + + char path[260]; + char *objectPath = (char*)installedObject + 16; + for (int i = 0; i < 8; ++i){ + if (entry->name[i] != ' ') + objectPath[i] = toupper(entry->name[i]); + else + objectPath[i] = '\0'; + } + objectPath[8] = '\0'; + strcat(objectPath, ".DAT"); + + subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); + //create file + //6aa48C + int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; + //RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + return eax; +} + /** * * rct2: 0x006A9CAF diff --git a/src/object.h b/src/object.h index 70bddc040c..6f26351874 100644 --- a/src/object.h +++ b/src/object.h @@ -45,6 +45,8 @@ typedef struct { uint32 extended; } rct_object_entry_extended; +int object_entry_group_counts[]; + void object_list_load(); int object_read_and_load_entries(FILE *file); int object_load_packed(FILE *file); diff --git a/src/object_list.c b/src/object_list.c index 0c759b6d87..4e4d060279 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -167,7 +167,7 @@ int object_read_and_load_entries(FILE *file) // Read all the object entries entries = malloc(OBJECT_ENTRY_COUNT * sizeof(rct_object_entry)); - sawyercoding_read_chunk_variable(file, (uint8**)&entries); + sawyercoding_read_chunk(file, (uint8*)entries); // Load each object for (i = 0; i < OBJECT_ENTRY_COUNT; i++) { @@ -199,66 +199,7 @@ int object_read_and_load_entries(FILE *file) return 1; } -/** - * - * rct2: 0x006AA2B7 - */ -int object_load_packed(FILE *file) -{ - object_unload_all(); - rct_object_entry* entry = RCT2_ADDRESS(0xF42B84, rct_object_entry); - - fread((void*)entry, 16, 1, file); - - uint8* chunk = rct2_malloc(0x600000); - uint32 chunkSize = sawyercoding_read_chunk(file, chunk); - chunk = rct2_realloc(chunk, chunkSize); - if (chunk == NULL){ - return 0; - } - - if (object_calculate_checksum(entry, chunk, chunkSize) != entry->checksum){ - rct2_free(chunk); - return 0; - } - - if (object_paint(entry->flags & 0x0F, 2, 0, entry->flags & 0x0F, 0, (int)chunk, 0, 0)) { - rct2_free(chunk); - return 0; - } - - int yyy = RCT2_GLOBAL(0x009ADAF0, uint32); - - if (yyy >= 0x4726E){ - rct2_free(chunk); - return 0; - } - - int type = entry->flags & 0x0F; - - // ecx - int entryGroupIndex = 0; - - for (; entryGroupIndex < object_entry_group_counts[type]; entryGroupIndex++){ - if (RCT2_ADDRESS(0x98D97C, uint32*)[type * 2][entryGroupIndex] == -1){ - break; - } - } - - if (entryGroupIndex == object_entry_group_counts[type]){ - rct2_free(chunk); - return 0; - } - - RCT2_ADDRESS(0x98D97C, uint8**)[type * 2][entryGroupIndex] = chunk; - int* edx = (int*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); - memcpy(edx, (int*)entry, 20); - //6aa429 - int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; - //RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return eax; -} /** * diff --git a/src/sawyercoding.c b/src/sawyercoding.c index 6e5ccecc65..c788eb34a4 100644 --- a/src/sawyercoding.c +++ b/src/sawyercoding.c @@ -141,7 +141,7 @@ static int decode_chunk_rle(uint8* src_buffer, uint8* dst_buffer, int length) } // Return final size - return (char*)dst - buffer; + return dst - dst_buffer; } /** From bbc06c9ed7c3ec4563020e44d672e7a6684fa728 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Tue, 30 Sep 2014 18:04:17 +0100 Subject: [PATCH 14/19] Added code for finding next avaliable file name --- src/object.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/object.c b/src/object.c index dfc8088f04..a6c926491c 100644 --- a/src/object.c +++ b/src/object.c @@ -25,6 +25,7 @@ #include "addresses.h" #include "string_ids.h" #include "object.h" +#include "osinterface.h" #include "sawyercoding.h" int object_entry_compare(rct_object_entry *a, rct_object_entry *b); @@ -205,17 +206,33 @@ int object_load_packed(FILE *file) //Code for updating progress bar removed. char path[260]; - char *objectPath = (char*)installedObject + 16; + char objectPath[13] = { 0 }; for (int i = 0; i < 8; ++i){ if (entry->name[i] != ' ') objectPath[i] = toupper(entry->name[i]); else objectPath[i] = '\0'; } - objectPath[8] = '\0'; - strcat(objectPath, ".DAT"); - + subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); + char* last_char = path + strlen(path); + strcat(path, ".DAT"); + for (; osinterface_file_exists(path);){ + for (char* curr_char = last_char - 1;; --curr_char){ + if (*curr_char == '\\'){ + subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), "00000000.DAT"); + char* last_char = path + strlen(path); + break; + } + if (*curr_char < '0') *curr_char = '0'; + else if (*curr_char == '9') *curr_char = 'A'; + else if (*curr_char == 'Z') *curr_char = '0'; + else (*curr_char)++; + if (*curr_char != '0') break; + } + } + + //create file //6aa48C int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; From 593acfc867cf4e095f17c31cd127df7d2012a95a Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Wed, 1 Oct 2014 18:52:02 +0100 Subject: [PATCH 15/19] Added code for writing new packed file. --- src/object.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/object.c b/src/object.c index a6c926491c..eb2af65aaf 100644 --- a/src/object.c +++ b/src/object.c @@ -132,6 +132,29 @@ int object_load(int groupIndex, rct_object_entry *entry) //return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x400); } +/** rct2: 0x006a9f42 + * ebx : file + * ebp : entry + */ +int sub_6A9F42(FILE *file, rct_object_entry* entry){ + int eax = 0, entryGroupIndex = 0, type = 0, edx = 0, edi = 0, ebp = (int)entry, esi = 0; + RCT2_CALLFUNC_X(0x6A9FBE, &eax, &entryGroupIndex, &type, &edx, &esi, &edi, &ebp); + if (eax == 0) return 0; + + object_paint(type, 1, entryGroupIndex, type, edx, esi, edi, ebp); + + RCT2_GLOBAL(0x9E3CBD, uint8) = RCT2_ADDRESS(0x98DA2C, uint8)[type]; + rct_object_entry* installed_entry = (rct_object_entry*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); + + fwrite((void*)installed_entry, 1, 16, file); + + //This increases the pointer of installed_entry by 16 + //it also adds together what it jumps over? + RCT2_CALLPROC_X(0x6762D1, 0, 0, 16, 0, (int)installed_entry, 0, 0); + //6a9f8f + //Function not finished as it requires completing swayer_encoding +} + /** * * rct2: 0x006AA2B7 @@ -193,7 +216,7 @@ int object_load_packed(FILE *file) if (RCT2_GLOBAL(0xF42B6C, uint32)){ for (uint32 i = 0; i < RCT2_GLOBAL(0xF42B6C, uint32); ++i){ - if (!object_entry_compare(entry, installedObject)){ + if (object_entry_compare(entry, installedObject)){ object_unload_all(); return 0; } @@ -217,6 +240,8 @@ int object_load_packed(FILE *file) subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); char* last_char = path + strlen(path); strcat(path, ".DAT"); + + // for (; osinterface_file_exists(path);){ for (char* curr_char = last_char - 1;; --curr_char){ if (*curr_char == '\\'){ @@ -232,7 +257,25 @@ int object_load_packed(FILE *file) } } + // Removed progress bar code + // The following section cannot be finished until 6A9F42 is finished + // Run the game once with vanila rct2 to not reach this part of code. + RCT2_ERROR("Function not finished. Please run this save once with vanila rct2."); + //FILE* obj_file = fopen(path, "+w"); + //if (!obj_file){ + // Removed progress bar code + //sub_6A9F42(obj_file, entry); + //fclose(obj_file); + // Removed progress bar code + // object_unload_all(); + // Removed progress bar code + // return 1; + //} + //else{ + object_unload_all(); + return 0; + //} //create file //6aa48C int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; From e2c78f236c3457920aa9ddf6e70d434be942e0da Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Wed, 1 Oct 2014 20:08:40 +0100 Subject: [PATCH 16/19] Fix travis errors --- src/object.c | 2 +- src/object.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/object.c b/src/object.c index eb2af65aaf..da5173fb1b 100644 --- a/src/object.c +++ b/src/object.c @@ -292,7 +292,7 @@ void object_unload(int groupIndex, rct_object_entry_extended *entry) RCT2_CALLPROC_X(0x006A9CAF, 0, groupIndex, 0, 0, 0, 0, (int)entry); } -static int object_entry_compare(rct_object_entry *a, rct_object_entry *b) +int object_entry_compare(rct_object_entry *a, rct_object_entry *b) { if (a->flags & 0xF0) { if ((a->flags & 0x0F) != (b->flags & 0x0F)) diff --git a/src/object.h b/src/object.h index 6f26351874..8703b559b7 100644 --- a/src/object.h +++ b/src/object.h @@ -45,7 +45,7 @@ typedef struct { uint32 extended; } rct_object_entry_extended; -int object_entry_group_counts[]; +extern int object_entry_group_counts[]; void object_list_load(); int object_read_and_load_entries(FILE *file); From 2ea8d9e4b27b7700c65ad6449f737d66fc87a641 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Wed, 1 Oct 2014 21:49:37 +0100 Subject: [PATCH 17/19] Added start of sawyer write chunk --- src/object.c | 42 +++++++++++++++++++++++++----------------- src/object.h | 1 + src/object_list.c | 15 +++++++++++++++ src/sawyercoding.c | 26 ++++++++++++++++++++++++++ src/sawyercoding.h | 1 + 5 files changed, 68 insertions(+), 17 deletions(-) diff --git a/src/object.c b/src/object.c index da5173fb1b..61b0fd23b5 100644 --- a/src/object.c +++ b/src/object.c @@ -106,7 +106,7 @@ int object_load(int groupIndex, rct_object_entry *entry) int ecx = groupIndex; if (ecx == -1){ for (int ecx = 0; ((sint32*)esi)[ecx] != -1; ecx++){ - if ((ecx + 1) >= RCT2_ADDRESS(0x98DA00, uint16)[ebp]){ + if ((ecx + 1) >= object_entry_group_counts[ebp]){ RCT2_GLOBAL(0x00F42BD9, uint8) = 5; rct2_free(chunk); return 0; @@ -137,21 +137,28 @@ int object_load(int groupIndex, rct_object_entry *entry) * ebp : entry */ int sub_6A9F42(FILE *file, rct_object_entry* entry){ - int eax = 0, entryGroupIndex = 0, type = 0, edx = 0, edi = 0, ebp = (int)entry, esi = 0; - RCT2_CALLFUNC_X(0x6A9FBE, &eax, &entryGroupIndex, &type, &edx, &esi, &edi, &ebp); + int eax = 0, entryGroupIndex = 0, type = 0, edx = 0, edi = 0, ebp = (int)entry, chunk = 0; + RCT2_CALLFUNC_X(0x6A9DA2, &eax, &entryGroupIndex, &type, &edx, &chunk, &edi, &ebp); if (eax == 0) return 0; - object_paint(type, 1, entryGroupIndex, type, edx, esi, edi, ebp); + object_paint(type, 1, entryGroupIndex, type, edx, chunk, edi, ebp); - RCT2_GLOBAL(0x9E3CBD, uint8) = RCT2_ADDRESS(0x98DA2C, uint8)[type]; + rct_object_entry* installed_entry = (rct_object_entry*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); fwrite((void*)installed_entry, 1, 16, file); //This increases the pointer of installed_entry by 16 //it also adds together what it jumps over? - RCT2_CALLPROC_X(0x6762D1, 0, 0, 16, 0, (int)installed_entry, 0, 0); - //6a9f8f + //RCT2_CALLPROC_X(0x6762D1, 0, 0, 16, 0, (int)installed_entry, 0, 0); + + sawyercoding_chunk_header chunkHeader; + // Encoding type + RCT2_GLOBAL(0x9E3CBD, uint8) = object_entry_group_encoding[type]; + chunkHeader.encoding = object_entry_group_encoding[type]; + chunkHeader.length = *(uint32*)(((uint8*)installed_entry + 16)); + + sawyercoding_write_chunk(file, (uint8*)chunk, chunkHeader); //Function not finished as it requires completing swayer_encoding } @@ -209,7 +216,8 @@ int object_load_packed(FILE *file) RCT2_ADDRESS(0x98D97C, uint8**)[type * 2][entryGroupIndex] = chunk; int* edx = (int*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); - memcpy(edx, (int*)entry, 20); + memcpy(edx, (int*)entry, 16); + *(edx + 4) = chunkSize; //esi rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); @@ -262,20 +270,20 @@ int object_load_packed(FILE *file) // The following section cannot be finished until 6A9F42 is finished // Run the game once with vanila rct2 to not reach this part of code. RCT2_ERROR("Function not finished. Please run this save once with vanila rct2."); - //FILE* obj_file = fopen(path, "+w"); - //if (!obj_file){ + FILE* obj_file = fopen(path, "w"); + if (obj_file){ // Removed progress bar code - //sub_6A9F42(obj_file, entry); - //fclose(obj_file); + sub_6A9F42(obj_file, entry); + fclose(obj_file); // Removed progress bar code - // object_unload_all(); + object_unload_all(); // Removed progress bar code - // return 1; - //} - //else{ + return 1; + } + else{ object_unload_all(); return 0; - //} + } //create file //6aa48C int eax = 1;//, ebx = 0, ecx = 0, edx = 0, esi = 0, edi = 0, ebp = 0; diff --git a/src/object.h b/src/object.h index 8703b559b7..b0e125ae8d 100644 --- a/src/object.h +++ b/src/object.h @@ -46,6 +46,7 @@ typedef struct { } rct_object_entry_extended; extern int object_entry_group_counts[]; +extern int object_entry_group_encoding[]; void object_list_load(); int object_read_and_load_entries(FILE *file); diff --git a/src/object_list.c b/src/object_list.c index 4e4d060279..39f8a996cd 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -49,6 +49,21 @@ int object_entry_group_counts[] = { 1 // scenario text }; +// 98DA2C +int object_entry_group_encoding[] = { + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_RLE, + CHUNK_ENCODING_ROTATE +}; + struct { void **data; rct_object_entry_extended *entries; } object_entry_groups[] = { (void**)(0x009ACFA4 ), (rct_object_entry_extended*)(0x00F3F03C ), // rides (void**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery diff --git a/src/sawyercoding.c b/src/sawyercoding.c index c788eb34a4..71fb9860a4 100644 --- a/src/sawyercoding.c +++ b/src/sawyercoding.c @@ -188,3 +188,29 @@ static void decode_chunk_rotate(char *buffer, int length) code = (code + 2) % 8; } } + +/** +* +* rct2: 0x006762E1 +* +*/ +int sawyercoding_write_chunk(FILE *file, uint8* buffer, sawyercoding_chunk_header chunkHeader){ + + switch (chunkHeader.encoding){ + case CHUNK_ENCODING_NONE: + fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); + fwrite(buffer, 1, chunkHeader.length, file); + break; + case CHUNK_ENCODING_RLE: + //chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); + break; + case CHUNK_ENCODING_RLECOMPRESSED: + //chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); + //chunkHeader.length = decode_chunk_repeat(buffer, chunkHeader.length); + break; + case CHUNK_ENCODING_ROTATE: + //memcpy(buffer, src_buffer, chunkHeader.length); + //decode_chunk_rotate(buffer, chunkHeader.length); + break; + } +} \ No newline at end of file diff --git a/src/sawyercoding.h b/src/sawyercoding.h index 38916cf1c3..2ab18d76b2 100644 --- a/src/sawyercoding.h +++ b/src/sawyercoding.h @@ -38,5 +38,6 @@ enum { int sawyercoding_validate_checksum(FILE *file); int sawyercoding_read_chunk(FILE *file, uint8 *buffer); +int sawyercoding_write_chunk(FILE *file, uint8 *buffer, sawyercoding_chunk_header chunkHeader); #endif From 45f9f585f187cab785048bd8d65af1a0656924a4 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Fri, 3 Oct 2014 20:07:21 +0100 Subject: [PATCH 18/19] Added encode functions. Missing check sum calc for end of chunk --- src/sawyercoding.c | 78 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/src/sawyercoding.c b/src/sawyercoding.c index 71fb9860a4..480aa70dd6 100644 --- a/src/sawyercoding.c +++ b/src/sawyercoding.c @@ -28,6 +28,8 @@ static int decode_chunk_rle(uint8* src_buffer, uint8* dst_buffer, int length); static int decode_chunk_repeat(char *buffer, int length); static void decode_chunk_rotate(char *buffer, int length); +int encode_chunk_rle(char *src_buffer, char *dst_buffer, int length); +void encode_chunk_rotate(char *buffer, int length); /** * * rct2: 0x00676FD2 @@ -195,22 +197,88 @@ static void decode_chunk_rotate(char *buffer, int length) * */ int sawyercoding_write_chunk(FILE *file, uint8* buffer, sawyercoding_chunk_header chunkHeader){ - + uint8* dst_buffer; + switch (chunkHeader.encoding){ case CHUNK_ENCODING_NONE: fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); fwrite(buffer, 1, chunkHeader.length, file); break; case CHUNK_ENCODING_RLE: - //chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); + dst_buffer = malloc(0x600000); + chunkHeader.length = encode_chunk_rle(buffer, dst_buffer, chunkHeader.length); + fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); + fwrite(dst_buffer, 1, chunkHeader.length, file); + free(dst_buffer); break; case CHUNK_ENCODING_RLECOMPRESSED: //chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); //chunkHeader.length = decode_chunk_repeat(buffer, chunkHeader.length); break; case CHUNK_ENCODING_ROTATE: - //memcpy(buffer, src_buffer, chunkHeader.length); - //decode_chunk_rotate(buffer, chunkHeader.length); + encode_chunk_rotate(buffer, chunkHeader.length); + fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); + fwrite(buffer, 1, chunkHeader.length, file); break; } -} \ No newline at end of file + + return chunkHeader.length; +} + +/** +* Ensure dst_buffer is bigger than src_buffer then resize afterwards +* returns length of dst_buffer +*/ +int encode_chunk_rle(char *src_buffer, char *dst_buffer, int length) +{ + char* src = src_buffer; + char* dst = dst_buffer; + char* end_src = src + length; + uint8 count = 0; + char* src_norm_start = src; + + while (src < end_src - 1){ + + if ((count && *src == src[1]) || count > 126){ + *dst++ = count; + for (; count != 0; --count){ + *dst++ = *src_norm_start++; + } + } + if (*src == src[1]){ + for (; (count < 127) && ((src + count) < end_src); count++){ + if (*src != src[count]) break; + } + *dst++ = 257 - count; + *dst++ = *src; + src += count; + src_norm_start = src; + count = 0; + } + else{ + count++; + src++; + } + } + if (src == end_src - 1)count++; + if (count){ + *dst++ = count; + for (; count != 0; --count){ + *dst++ = *src_norm_start++; + } + } + return dst - dst_buffer; +} + +/** +* +* +*/ +void encode_chunk_rotate(char *buffer, int length) +{ + int i, code = 1; + for (i = 0; i < length; i++) { + buffer[i] = rol8(buffer[i], code); + code = (code + 2) % 8; + } +} From bfb132146d039e28e28969a88afb866195e0e6f2 Mon Sep 17 00:00:00 2001 From: Duncan Frost Date: Sat, 4 Oct 2014 11:41:16 +0100 Subject: [PATCH 19/19] Fixed bugs in RLE code. Loading now works --- src/object.c | 19 ++++++++-------- src/sawyercoding.c | 54 ++++++++++++++++++++++++++++++++-------------- src/sawyercoding.h | 3 ++- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/object.c b/src/object.c index 61b0fd23b5..dae1f19074 100644 --- a/src/object.c +++ b/src/object.c @@ -145,21 +145,22 @@ int sub_6A9F42(FILE *file, rct_object_entry* entry){ rct_object_entry* installed_entry = (rct_object_entry*)(entryGroupIndex * 20 + RCT2_ADDRESS(0x98D980, uint32)[type * 2]); + uint8* dst_buffer = malloc(0x600000); + memcpy(dst_buffer, (void*)installed_entry, 16); - fwrite((void*)installed_entry, 1, 16, file); - - //This increases the pointer of installed_entry by 16 - //it also adds together what it jumps over? - //RCT2_CALLPROC_X(0x6762D1, 0, 0, 16, 0, (int)installed_entry, 0, 0); + uint32 size_dst = 16; sawyercoding_chunk_header chunkHeader; - // Encoding type + // Encoding type (not used anymore) RCT2_GLOBAL(0x9E3CBD, uint8) = object_entry_group_encoding[type]; + chunkHeader.encoding = object_entry_group_encoding[type]; chunkHeader.length = *(uint32*)(((uint8*)installed_entry + 16)); - sawyercoding_write_chunk(file, (uint8*)chunk, chunkHeader); - //Function not finished as it requires completing swayer_encoding + size_dst += sawyercoding_write_chunk_buffer(dst_buffer+16, (uint8*)chunk, chunkHeader); + fwrite(dst_buffer, 1, size_dst, file); + + free(dst_buffer); } /** @@ -270,7 +271,7 @@ int object_load_packed(FILE *file) // The following section cannot be finished until 6A9F42 is finished // Run the game once with vanila rct2 to not reach this part of code. RCT2_ERROR("Function not finished. Please run this save once with vanila rct2."); - FILE* obj_file = fopen(path, "w"); + FILE* obj_file = fopen(path, "wb"); if (obj_file){ // Removed progress bar code sub_6A9F42(obj_file, entry); diff --git a/src/sawyercoding.c b/src/sawyercoding.c index 480aa70dd6..c62722f8b7 100644 --- a/src/sawyercoding.c +++ b/src/sawyercoding.c @@ -30,6 +30,20 @@ static void decode_chunk_rotate(char *buffer, int length); int encode_chunk_rle(char *src_buffer, char *dst_buffer, int length); void encode_chunk_rotate(char *buffer, int length); + +int sawyercoding_calculate_checksum(uint8* buffer, uint32 length){ + int checksum = 0; + do { + int bufferSize = min(length , 1024); + + for (int i = 0; i < bufferSize; i++) + checksum += buffer[i]; + length -= bufferSize; + } while (length != 0); + + return checksum; +} + /** * * rct2: 0x00676FD2 @@ -196,33 +210,41 @@ static void decode_chunk_rotate(char *buffer, int length) * rct2: 0x006762E1 * */ -int sawyercoding_write_chunk(FILE *file, uint8* buffer, sawyercoding_chunk_header chunkHeader){ - uint8* dst_buffer; +int sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader){ + uint8* encode_buffer; switch (chunkHeader.encoding){ case CHUNK_ENCODING_NONE: - fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); - fwrite(buffer, 1, chunkHeader.length, file); + memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header)); + dst_file += sizeof(sawyercoding_chunk_header); + memcpy(dst_file, buffer, chunkHeader.length); + //fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); + //fwrite(buffer, 1, chunkHeader.length, file); break; case CHUNK_ENCODING_RLE: - dst_buffer = malloc(0x600000); - chunkHeader.length = encode_chunk_rle(buffer, dst_buffer, chunkHeader.length); - fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); - fwrite(dst_buffer, 1, chunkHeader.length, file); - free(dst_buffer); + encode_buffer = malloc(0x600000); + chunkHeader.length = encode_chunk_rle(buffer, encode_buffer, chunkHeader.length); + memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header)); + dst_file += sizeof(sawyercoding_chunk_header); + memcpy(dst_file, encode_buffer, chunkHeader.length); + + free(encode_buffer); break; case CHUNK_ENCODING_RLECOMPRESSED: + RCT2_ERROR("This has not been implemented"); + return -1; //chunkHeader.length = decode_chunk_rle(src_buffer, buffer, chunkHeader.length); //chunkHeader.length = decode_chunk_repeat(buffer, chunkHeader.length); break; case CHUNK_ENCODING_ROTATE: encode_chunk_rotate(buffer, chunkHeader.length); - fwrite(&chunkHeader, sizeof(sawyercoding_chunk_header), 1, file); - fwrite(buffer, 1, chunkHeader.length, file); + memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header)); + dst_file += sizeof(sawyercoding_chunk_header); + memcpy(dst_file, buffer, chunkHeader.length); break; } - return chunkHeader.length; + return chunkHeader.length + sizeof(sawyercoding_chunk_header); } /** @@ -239,14 +261,14 @@ int encode_chunk_rle(char *src_buffer, char *dst_buffer, int length) while (src < end_src - 1){ - if ((count && *src == src[1]) || count > 126){ - *dst++ = count; + if ((count && *src == src[1]) || count > 120){ + *dst++ = count - 1; for (; count != 0; --count){ *dst++ = *src_norm_start++; } } if (*src == src[1]){ - for (; (count < 127) && ((src + count) < end_src); count++){ + for (; (count < 120) && ((src + count) < end_src); count++){ if (*src != src[count]) break; } *dst++ = 257 - count; @@ -262,7 +284,7 @@ int encode_chunk_rle(char *src_buffer, char *dst_buffer, int length) } if (src == end_src - 1)count++; if (count){ - *dst++ = count; + *dst++ = count - 1; for (; count != 0; --count){ *dst++ = *src_norm_start++; } diff --git a/src/sawyercoding.h b/src/sawyercoding.h index 2ab18d76b2..c965d2da94 100644 --- a/src/sawyercoding.h +++ b/src/sawyercoding.h @@ -37,7 +37,8 @@ enum { }; int sawyercoding_validate_checksum(FILE *file); +int sawyercoding_calculate_checksum(uint8* buffer, uint32 length); int sawyercoding_read_chunk(FILE *file, uint8 *buffer); -int sawyercoding_write_chunk(FILE *file, uint8 *buffer, sawyercoding_chunk_header chunkHeader); +int sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader); #endif