2014-04-10 18:08:41 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* Copyright (c) 2014 Ted John
|
|
|
|
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
|
|
|
*
|
|
|
|
* This file is part of OpenRCT2.
|
|
|
|
*
|
|
|
|
* OpenRCT2 is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2014-05-24 17:48:13 +02:00
|
|
|
*****************************************************************************/
|
|
|
|
|
2014-05-26 18:59:42 +02:00
|
|
|
#include <memory.h>
|
|
|
|
#include <stdio.h>
|
2014-09-25 19:34:51 +02:00
|
|
|
#include <string.h>
|
2014-09-29 20:07:25 +02:00
|
|
|
#include <ctype.h>
|
2014-05-24 17:48:13 +02:00
|
|
|
#include "addresses.h"
|
2014-09-29 20:07:25 +02:00
|
|
|
#include "string_ids.h"
|
2014-05-24 17:48:13 +02:00
|
|
|
#include "object.h"
|
2014-09-30 19:04:17 +02:00
|
|
|
#include "osinterface.h"
|
2014-05-26 18:59:42 +02:00
|
|
|
#include "sawyercoding.h"
|
2014-05-24 17:48:13 +02:00
|
|
|
|
2014-09-25 21:50:38 +02:00
|
|
|
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);
|
2014-05-24 17:48:13 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006A985D
|
|
|
|
*/
|
2014-05-24 19:07:29 +02:00
|
|
|
int object_load(int groupIndex, rct_object_entry *entry)
|
2014-05-24 17:48:13 +02:00
|
|
|
{
|
2014-09-25 19:34:51 +02:00
|
|
|
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;
|
|
|
|
}
|
2014-09-25 21:50:38 +02:00
|
|
|
for (int i = 0; i < RCT2_GLOBAL(0x00F42B6C, sint32); i++) {
|
2014-09-26 18:54:05 +02:00
|
|
|
if (object_entry_compare(installedObject, entry)){
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-26 18:54:05 +02:00
|
|
|
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)) {
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-26 18:54:05 +02:00
|
|
|
// Get chunk size
|
|
|
|
char *pos = (char*)installedObject + 16;
|
|
|
|
do {
|
|
|
|
pos++;
|
|
|
|
} while (*(pos - 1) != 0);
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-26 18:54:05 +02:00
|
|
|
// Read chunk
|
|
|
|
int chunkSize = *((uint32*)pos);
|
|
|
|
char *chunk;
|
2014-09-27 13:59:07 +02:00
|
|
|
|
2014-09-27 13:05:40 +02:00
|
|
|
if (chunkSize == 0xFFFFFFFF) {
|
2014-09-27 13:59:07 +02:00
|
|
|
chunk = rct2_malloc(0x600000);
|
2014-09-29 13:46:26 +02:00
|
|
|
chunkSize = sawyercoding_read_chunk(file, chunk);
|
2014-09-27 13:59:07 +02:00
|
|
|
chunk = rct2_realloc(chunk, chunkSize);
|
2014-09-27 13:05:40 +02:00
|
|
|
}
|
|
|
|
else {
|
2014-09-27 13:59:07 +02:00
|
|
|
chunk = rct2_malloc(chunkSize);
|
2014-09-29 13:46:26 +02:00
|
|
|
chunkSize = sawyercoding_read_chunk(file, chunk);
|
2014-09-27 13:05:40 +02:00
|
|
|
}
|
2014-09-26 18:54:05 +02:00
|
|
|
fclose(file);
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-26 18:54:05 +02:00
|
|
|
// Calculate and check checksum
|
|
|
|
if (object_calculate_checksum(&openedEntry, chunk, chunkSize) != openedEntry.checksum) {
|
|
|
|
RCT2_GLOBAL(0x00F42BD9, uint8) = 2;
|
2014-09-27 15:26:32 +02:00
|
|
|
rct2_free(chunk);
|
2014-09-26 18:54:05 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-27 13:05:40 +02:00
|
|
|
if (object_paint(openedEntry.flags & 0x0F, 2, 0, openedEntry.flags & 0x0F, 0, (int)chunk, 0, 0)) {
|
2014-09-27 13:59:07 +02:00
|
|
|
RCT2_GLOBAL(0x00F42BD9, uint8) = 3;
|
2014-09-27 15:26:32 +02:00
|
|
|
rct2_free(chunk);
|
2014-09-27 13:59:07 +02:00
|
|
|
return 0;
|
2014-09-26 18:54:05 +02:00
|
|
|
}
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-26 18:54:05 +02:00
|
|
|
int yyy = RCT2_GLOBAL(0x009ADAF0, uint32);
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-26 18:54:05 +02:00
|
|
|
if (yyy >= 0x4726E){
|
|
|
|
RCT2_GLOBAL(0x00F42BD9, uint8) = 4;
|
2014-09-27 15:26:32 +02:00
|
|
|
rct2_free(chunk);
|
2014-09-26 18:54:05 +02:00
|
|
|
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;
|
2014-09-27 15:26:32 +02:00
|
|
|
rct2_free(chunk);
|
2014-09-26 18:54:05 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2014-09-25 21:50:38 +02:00
|
|
|
}
|
|
|
|
}
|
2014-09-27 13:59:07 +02:00
|
|
|
((char**)esi)[ecx] = chunk;
|
2014-09-25 21:50:38 +02:00
|
|
|
|
2014-09-27 13:59:07 +02:00
|
|
|
int* edx = (int*)( ecx * 20 + RCT2_ADDRESS(0x98D980, uint32)[ebp * 2]);
|
2014-09-26 18:54:05 +02:00
|
|
|
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);
|
2014-09-25 21:50:38 +02:00
|
|
|
}
|
2014-09-25 19:34:51 +02:00
|
|
|
}
|
2014-09-25 21:50:38 +02:00
|
|
|
installedObject = object_get_next(installedObject);
|
2014-09-25 19:34:51 +02:00
|
|
|
}
|
|
|
|
//6a991f
|
2014-09-29 13:46:26 +02:00
|
|
|
// Installed Object can not be found.
|
|
|
|
return 0;
|
|
|
|
//return !(RCT2_CALLPROC_X(0x006A985D, 0, 0, groupIndex, 0, 0, 0, (int)entry) & 0x400);
|
2014-05-24 19:07:29 +02:00
|
|
|
}
|
|
|
|
|
2014-10-01 19:52:02 +02:00
|
|
|
/** 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
|
|
|
|
}
|
|
|
|
|
2014-09-29 20:07:25 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* 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){
|
2014-10-01 19:52:02 +02:00
|
|
|
if (object_entry_compare(entry, installedObject)){
|
2014-09-29 20:07:25 +02:00
|
|
|
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];
|
2014-09-30 19:04:17 +02:00
|
|
|
char objectPath[13] = { 0 };
|
2014-09-29 20:07:25 +02:00
|
|
|
for (int i = 0; i < 8; ++i){
|
|
|
|
if (entry->name[i] != ' ')
|
|
|
|
objectPath[i] = toupper(entry->name[i]);
|
|
|
|
else
|
|
|
|
objectPath[i] = '\0';
|
|
|
|
}
|
2014-09-30 19:04:17 +02:00
|
|
|
|
2014-09-29 20:07:25 +02:00
|
|
|
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath);
|
2014-09-30 19:04:17 +02:00
|
|
|
char* last_char = path + strlen(path);
|
|
|
|
strcat(path, ".DAT");
|
2014-10-01 19:52:02 +02:00
|
|
|
|
|
|
|
//
|
2014-09-30 19:04:17 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-01 19:52:02 +02:00
|
|
|
// 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;
|
|
|
|
//}
|
2014-09-29 20:07:25 +02:00
|
|
|
//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;
|
|
|
|
}
|
|
|
|
|
2014-05-24 19:07:29 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006A9CAF
|
|
|
|
*/
|
|
|
|
void object_unload(int groupIndex, rct_object_entry_extended *entry)
|
|
|
|
{
|
|
|
|
RCT2_CALLPROC_X(0x006A9CAF, 0, groupIndex, 0, 0, 0, 0, (int)entry);
|
2014-05-24 23:14:42 +02:00
|
|
|
}
|
|
|
|
|
2014-10-01 21:08:40 +02:00
|
|
|
int object_entry_compare(rct_object_entry *a, rct_object_entry *b)
|
2014-05-26 18:59:42 +02:00
|
|
|
{
|
|
|
|
if (a->flags & 0xF0) {
|
|
|
|
if ((a->flags & 0x0F) != (b->flags & 0x0F))
|
|
|
|
return 0;
|
|
|
|
if (*((uint32*)a->name) != *((uint32*)b->name))
|
|
|
|
return 0;
|
|
|
|
if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4])))
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
if (a->flags != b->flags)
|
|
|
|
return 0;
|
|
|
|
if (*((uint32*)a->name) != *((uint32*)b->name))
|
|
|
|
return 0;
|
|
|
|
if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4])))
|
|
|
|
return 0;
|
|
|
|
if (a->checksum != b->checksum)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-09-27 15:26:32 +02:00
|
|
|
int object_calculate_checksum(rct_object_entry *entry, char *data, int dataLength)
|
2014-05-26 18:59:42 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *eee = (char*)entry;
|
|
|
|
int checksum = 0xF369A75B;
|
|
|
|
char *ccc = (char*)&checksum;
|
|
|
|
|
|
|
|
*ccc ^= eee[0];
|
|
|
|
checksum = rol32(checksum, 11);
|
|
|
|
for (i = 4; i < 12; i++) {
|
|
|
|
*ccc ^= eee[i];
|
|
|
|
checksum = rol32(checksum, 11);
|
|
|
|
}
|
|
|
|
for (i = 0; i < dataLength; i++) {
|
|
|
|
*ccc ^= data[i];
|
|
|
|
checksum = rol32(checksum, 11);
|
|
|
|
}
|
|
|
|
|
|
|
|
return checksum;
|
|
|
|
}
|
|
|
|
|
2014-08-14 19:35:19 +02:00
|
|
|
/**
|
|
|
|
* rct2: 0x66B355 part
|
|
|
|
* If al is 0
|
|
|
|
* chunk : esi
|
|
|
|
*/
|
|
|
|
int object_scenario_load_custom_text(char* chunk){
|
2014-08-15 00:08:46 +02:00
|
|
|
int ebp = (int)(&((uint32*)chunk)[2]);
|
2014-08-14 19:35:19 +02:00
|
|
|
int edx = 0;
|
|
|
|
int eax, ebx, ecx, edi;
|
2014-08-15 00:08:46 +02:00
|
|
|
RCT2_CALLFUNC_X(0x6A9E24, &eax, &ebx, &ecx, &edx, (int*)&chunk, &edi, &ebp);
|
2014-08-14 19:35:19 +02:00
|
|
|
*((uint16*)chunk) = eax;
|
|
|
|
edx++;
|
2014-08-15 00:08:46 +02:00
|
|
|
RCT2_CALLFUNC_X(0x6A9E24, &eax, &ebx, &ecx, &edx, (int*)&chunk, &edi, &ebp);
|
2014-08-14 19:35:19 +02:00
|
|
|
*((uint16*)chunk + 1) = eax;
|
|
|
|
edx++;
|
2014-08-15 00:08:46 +02:00
|
|
|
RCT2_CALLFUNC_X(0x6A9E24, &eax, &ebx, &ecx, &edx, (int*)&chunk, &edi, &ebp);
|
2014-08-14 19:35:19 +02:00
|
|
|
*((uint16*)chunk + 2) = eax;
|
|
|
|
|
|
|
|
if (RCT2_GLOBAL(0x9ADAF4, int) == -1)return 0;
|
|
|
|
else *(RCT2_GLOBAL(0x9ADAF4, uint32*)) = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-05-26 18:59:42 +02:00
|
|
|
int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp)
|
2014-05-24 23:14:42 +02:00
|
|
|
{
|
2014-08-14 19:35:19 +02:00
|
|
|
if (type == 10){
|
|
|
|
if (eax == 0) return object_scenario_load_custom_text((char*)esi);
|
|
|
|
}
|
2014-09-27 13:59:07 +02:00
|
|
|
return RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098D9D4, uint32)[type], eax, ebx, ecx, edx, esi, edi, ebp) & 0x100;
|
2014-05-26 18:59:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006A9428
|
|
|
|
*/
|
|
|
|
int object_get_scenario_text(rct_object_entry *entry)
|
|
|
|
{
|
|
|
|
// RCT2_CALLPROC_X(0x006A9428, 0, 0, 0, 0, 0, 0, (int)entry); return;
|
|
|
|
|
|
|
|
int i;
|
2014-07-18 22:03:33 +02:00
|
|
|
rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
|
2014-05-26 18:59:42 +02:00
|
|
|
for (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 = 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);
|
|
|
|
RCT2_GLOBAL(0x009ADAF0, uint32) = 0x726E;
|
|
|
|
RCT2_GLOBAL(0x009ADAF8, uint32) = (int)chunk;
|
|
|
|
*((rct_object_entry*)0x00F42BC8) = openedEntry;
|
|
|
|
|
|
|
|
RCT2_GLOBAL(0x009ADAFC, uint8) = 255;
|
|
|
|
RCT2_GLOBAL(0x009ADAFD, uint8) = 1;
|
|
|
|
object_paint(openedEntry.flags & 0x0F, 0, 0, 0, 0, (int)chunk, 0, 0);
|
|
|
|
RCT2_GLOBAL(0x009ADAFC, uint8) = 0;
|
|
|
|
RCT2_GLOBAL(0x009ADAFD, uint8) = 0;
|
|
|
|
RCT2_GLOBAL(0x009ADAF0, uint32) = yyy;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
fclose(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
installedObject = object_get_next(installedObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT2_GLOBAL(0x00F42BD9, uint8) = 0;
|
2014-05-24 23:14:42 +02:00
|
|
|
return 0;
|
2014-05-26 18:59:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* rct2: 0x006A982D
|
|
|
|
*/
|
|
|
|
void object_free_scenario_text()
|
|
|
|
{
|
|
|
|
if (RCT2_GLOBAL(0x009ADAF8, void*) != NULL) {
|
|
|
|
free(RCT2_GLOBAL(0x009ADAF8, void*));
|
|
|
|
RCT2_GLOBAL(0x009ADAF8, void*) = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int object_get_length(rct_object_entry *entry)
|
|
|
|
{
|
|
|
|
return (int)object_get_next(entry) - (int)entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
rct_object_entry *object_get_next(rct_object_entry *entry)
|
|
|
|
{
|
|
|
|
char *pos = (char*)entry;
|
|
|
|
|
2014-09-27 13:59:07 +02:00
|
|
|
// Skip sizeof(rct_object_entry)
|
2014-05-26 18:59:42 +02:00
|
|
|
pos += 16;
|
|
|
|
|
|
|
|
// Skip filename
|
|
|
|
do {
|
|
|
|
pos++;
|
|
|
|
} while (*(pos - 1) != 0);
|
|
|
|
|
|
|
|
// Skip
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
// Skip name
|
|
|
|
do {
|
|
|
|
pos++;
|
|
|
|
} while (*(pos - 1) != 0);
|
|
|
|
|
2014-09-27 13:59:07 +02:00
|
|
|
// Skip size of chunk
|
2014-05-26 18:59:42 +02:00
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
// Skip
|
|
|
|
pos += *pos++ * 16;
|
|
|
|
|
|
|
|
// Skip theme objects
|
|
|
|
pos += *pos++ * 16;
|
|
|
|
|
|
|
|
// Skip
|
|
|
|
pos += 4;
|
|
|
|
|
|
|
|
return (rct_object_entry*)pos;
|
2014-09-29 13:46:26 +02:00
|
|
|
}
|