mirror of https://github.com/OpenRCT2/OpenRCT2.git
commit
f6bdab1eea
|
@ -840,7 +840,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();
|
||||
}
|
||||
|
|
273
src/object.c
273
src/object.c
|
@ -20,17 +20,276 @@
|
|||
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#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);
|
||||
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
|
||||
*/
|
||||
int object_load(int groupIndex, rct_object_entry *entry)
|
||||
{
|
||||
return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x100);
|
||||
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;
|
||||
}
|
||||
for (int i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) {
|
||||
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)) {
|
||||
|
||||
// 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 = rct2_malloc(0x600000);
|
||||
chunkSize = sawyercoding_read_chunk(file, chunk);
|
||||
chunk = rct2_realloc(chunk, chunkSize);
|
||||
}
|
||||
else {
|
||||
chunk = rct2_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;
|
||||
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;
|
||||
rct2_free(chunk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yyy = RCT2_GLOBAL(0x009ADAF0, uint32);
|
||||
|
||||
if (yyy >= 0x4726E){
|
||||
RCT2_GLOBAL(0x00F42BD9, uint8) = 4;
|
||||
rct2_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) >= object_entry_group_counts[ebp]){
|
||||
RCT2_GLOBAL(0x00F42BD9, uint8) = 5;
|
||||
rct2_free(chunk);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
((char**)esi)[ecx] = chunk;
|
||||
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
installedObject = object_get_next(installedObject);
|
||||
}
|
||||
//6a991f
|
||||
// Installed Object can not be found.
|
||||
return 0;
|
||||
//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, 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, chunk, edi, ebp);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
uint32 size_dst = 16;
|
||||
|
||||
sawyercoding_chunk_header chunkHeader;
|
||||
// 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));
|
||||
|
||||
size_dst += sawyercoding_write_chunk_buffer(dst_buffer+16, (uint8*)chunk, chunkHeader);
|
||||
fwrite(dst_buffer, 1, size_dst, file);
|
||||
|
||||
free(dst_buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 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, 16);
|
||||
*(edx + 4) = chunkSize;
|
||||
|
||||
//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[13] = { 0 };
|
||||
for (int i = 0; i < 8; ++i){
|
||||
if (entry->name[i] != ' ')
|
||||
objectPath[i] = toupper(entry->name[i]);
|
||||
else
|
||||
objectPath[i] = '\0';
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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, "wb");
|
||||
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;
|
||||
//RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
return eax;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,7 +301,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))
|
||||
|
@ -65,7 +324,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;
|
||||
|
@ -114,7 +373,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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,7 +474,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
|
||||
|
@ -231,7 +490,7 @@ rct_object_entry *object_get_next(rct_object_entry *entry)
|
|||
pos++;
|
||||
} while (*(pos - 1) != 0);
|
||||
|
||||
// Skip
|
||||
// Skip size of chunk
|
||||
pos += 4;
|
||||
|
||||
// Skip
|
||||
|
@ -244,4 +503,4 @@ rct_object_entry *object_get_next(rct_object_entry *entry)
|
|||
pos += 4;
|
||||
|
||||
return (rct_object_entry*)pos;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,9 +45,12 @@ typedef struct {
|
|||
uint32 extended;
|
||||
} 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);
|
||||
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 +59,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
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct {
|
|||
uint32 var_10;
|
||||
} rct_plugin_header;
|
||||
|
||||
// 98DA00
|
||||
int object_entry_group_counts[] = {
|
||||
128, // rides
|
||||
252, // small scenery
|
||||
|
@ -48,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
|
||||
|
@ -184,9 +200,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;
|
||||
}
|
||||
}
|
||||
|
@ -195,16 +214,7 @@ int object_read_and_load_entries(FILE *file)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006AA2B7
|
||||
*/
|
||||
int object_load_packed()
|
||||
{
|
||||
int eax, ebx, ecx, edx, esi, edi, ebp;
|
||||
RCT2_CALLFUNC_X(0x006AA2B7, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp);
|
||||
return eax;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -218,4 +228,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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,26 @@
|
|||
#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);
|
||||
|
||||
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
|
||||
|
@ -68,6 +84,7 @@ int sawyercoding_validate_checksum(FILE *file)
|
|||
return checksum == fileChecksum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x0067685F
|
||||
|
@ -83,26 +100,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;
|
||||
|
@ -112,34 +136,28 @@ 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;
|
||||
return dst - dst_buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -186,3 +204,103 @@ static void decode_chunk_rotate(char *buffer, int length)
|
|||
code = (code + 2) % 8;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x006762E1
|
||||
*
|
||||
*/
|
||||
int sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader){
|
||||
uint8* encode_buffer;
|
||||
|
||||
switch (chunkHeader.encoding){
|
||||
case CHUNK_ENCODING_NONE:
|
||||
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:
|
||||
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);
|
||||
memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header));
|
||||
dst_file += sizeof(sawyercoding_chunk_header);
|
||||
memcpy(dst_file, buffer, chunkHeader.length);
|
||||
break;
|
||||
}
|
||||
|
||||
return chunkHeader.length + sizeof(sawyercoding_chunk_header);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 > 120){
|
||||
*dst++ = count - 1;
|
||||
for (; count != 0; --count){
|
||||
*dst++ = *src_norm_start++;
|
||||
}
|
||||
}
|
||||
if (*src == src[1]){
|
||||
for (; (count < 120) && ((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 - 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +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_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue