1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 19:13:07 +01:00
Files
OpenRCT2/src/object.c
2015-02-26 15:58:13 +01:00

1149 lines
30 KiB
C

/*****************************************************************************
* 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/>.
*****************************************************************************/
#include "addresses.h"
#include "localisation/localisation.h"
#include "object.h"
#include "platform/platform.h"
#include "util/sawyercoding.h"
#include "drawing/drawing.h"
#include "world/footpath.h"
#include "scenario.h"
int object_load_entry(const char *path, rct_object_entry *outEntry)
{
FILE *file;
file = fopen(path, "rb");
if (file == NULL)
return 0;
if (fread(outEntry, sizeof(rct_object_entry), 1, file) != 1) {
fclose(file);
return 0;
}
fclose(file);
return 1;
}
int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSize, const rct_object_entry *installedObject)
{
uint8 objectType;
rct_object_entry openedEntry;
char path[260];
FILE *file;
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), (char*)installedObject + 16);
log_verbose("loading object, %s", path);
file = fopen(path, "rb");
if (file == NULL)
return 0;
fread(&openedEntry, sizeof(rct_object_entry), 1, file);
if (!object_entry_compare(&openedEntry, entry)) {
fclose(file);
return 0;
}
// Get chunk size
uint8 *installedObject_pointer = (uint8*)installedObject + 16;
// Skip file name
while (*installedObject_pointer++);
// Read chunk size
*chunkSize = *((uint32*)installedObject_pointer);
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) {
log_error("Object Load failed due to checksum failure.");
RCT2_GLOBAL(0x00F42BD9, uint8) = 2;
rct2_free(chunk);
return 0;
}
objectType = openedEntry.flags & 0x0F;
if (object_paint(objectType, 2, 0, objectType, 0, (int)chunk, 0, 0)) {
log_error("Object Load failed due to paint failure.");
RCT2_GLOBAL(0x00F42BD9, uint8) = 3;
rct2_free(chunk);
return 0;
}
int yyy = RCT2_GLOBAL(0x009ADAF0, uint32);
if (yyy >= 0x4726E){
log_error("Object Load failed due to yyy failure.");
RCT2_GLOBAL(0x00F42BD9, uint8) = 4;
rct2_free(chunk);
return 0;
}
uint8** chunk_list = object_entry_groups[objectType].chunks;
if (groupIndex == -1) {
for (groupIndex = 0; chunk_list[groupIndex] != (uint8*)-1; groupIndex++) {
if (groupIndex + 1 >= object_entry_group_counts[objectType]) {
log_error("Object Load failed due to too many objects of a certain type.");
RCT2_GLOBAL(0x00F42BD9, uint8) = 5;
rct2_free(chunk);
return 0;
}
}
}
chunk_list[groupIndex] = chunk;
rct_object_entry_extended* extended_entry = &object_entry_groups[objectType].entries[groupIndex];
memcpy(extended_entry, &openedEntry, sizeof(rct_object_entry));
extended_entry->chunk_size = *chunkSize;
RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, char*) = chunk;
if (RCT2_GLOBAL(0x9ADAFD, uint8) != 0)
object_paint(objectType, 0, groupIndex, objectType, 0, (int)chunk, 0, 0);
return 1;
}
/**
*
* rct2: 0x006A985D
*/
int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize)
{
// Alow chunkSize to be null
int tempChunkSize;
if (chunkSize == NULL)
chunkSize = &tempChunkSize;
RCT2_GLOBAL(0xF42B64, uint32) = groupIndex;
if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) == 0) {
RCT2_GLOBAL(0xF42BD9, uint8) = 0;
log_error("Object Load failed due to no items installed check.");
return 1;
}
rct_object_entry *installedObject = object_list_find(entry);
if (installedObject == NULL) {
log_error("object not installed");
return 0;
}
if (object_load_file(groupIndex, entry, chunkSize, installedObject))
return 1;
return 0;
}
/** 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_extended* installed_entry = &object_entry_groups[type].entries[entryGroupIndex];
uint8* dst_buffer = malloc(0x600000);
memcpy(dst_buffer, (uint8*)installed_entry, sizeof(rct_object_entry));
uint32 size_dst = sizeof(rct_object_entry);
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 = installed_entry->chunk_size;
size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), (uint8*)chunk, chunkHeader);
fwrite(dst_buffer, 1, size_dst, file);
free(dst_buffer);
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 (object_entry_groups[type].chunks[entryGroupIndex] == (uint8*)-1){
break;
}
}
if (entryGroupIndex == object_entry_group_counts[type]){
rct2_free(chunk);
return 0;
}
object_entry_groups[type].chunks[entryGroupIndex] = chunk;
rct_object_entry_extended* edx = &object_entry_groups[type].entries[entryGroupIndex];
memcpy(edx, (int*)entry, sizeof(rct_object_entry));
edx->chunk_size = chunkSize;
//esi
rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)){
for (uint32 i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, 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 (; platform_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.
log_verbose("Function might not be finished.");
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 1;
}
/**
*
* rct2: 0x006A9CAF
*/
void object_unload(int groupIndex, rct_object_entry_extended *entry)
{
RCT2_CALLPROC_X(0x006A9CAF, 0, groupIndex, 0, 0, 0, 0, (int)entry);
}
int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b)
{
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;
}
int object_calculate_checksum(const rct_object_entry *entry, const char *data, int dataLength)
{
int i;
const 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;
}
int sub_6A9ED1(uint8_t** ebp)
{
int result;
int eax = result = RCT2_GLOBAL(0x9ADAF0, uint32_t);
int ecx = ((uint32_t*)(*ebp))[0];
int ebx = ecx;
ebx += eax;
RCT2_GLOBAL(0x9ADAF0, uint32_t) = ebx;
ebx = ecx;
ebx *= 0x10;
(*ebp) += 8;
ebx += (uint32_t)(*ebp);
int g1_offset = eax;
g1_offset *= 0x10;
int edx = 0;
while (true)
{
RCT2_GLOBAL(RCT2_ADDRESS_G1_ELEMENTS + g1_offset, rct_g1_element) = ((rct_g1_element*)(edx + (*ebp)))[0];
RCT2_GLOBAL(RCT2_ADDRESS_G1_ELEMENTS + g1_offset, rct_g1_element).offset += ebx;
g1_offset += 0x10;
edx += 0x10;
ecx--;
if (ecx == 0) break;
}
ebx = ((uint32_t*)((*ebp) - 8))[0];
ebx *= 0x10;
(*ebp) += ((uint32_t*)((*ebp) - 4))[0];
(*ebp) += ebx;
return result;
}
int paint_ride_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp)
{
if ((flags & 0xFF) != 3)
{
if ((flags & 0xFF) != 1)
{
if ((flags & 0xFF) <= 1)//0
{
uint8_t* ebp = (uint8_t*)(esi + 0x1C2);
((rct_ride_type*)esi)->name = object_get_localised_text(&ebp, ecx, ebx, 0);
((rct_ride_type*)esi)->description = object_get_localised_text(&ebp, ecx, ebx, 1);
object_get_localised_text(&ebp, ecx, ebx, 2);
((uint32_t*)(esi + 0x1AE))[0] = (uint32_t)ebp;
if (ebp[0] != 0xFF)
{
int a = ebp[0];
ebp++;
ebp += a * 3;
}
else ebp += 0x61;
uint8_t* ebp_tmp = ebp;
int d = 4;
while (true)
{
int a = *ebp;
ebp++;
if (a == 0xFF)
{
a = ((uint16_t*)ebp)[0];
ebp += 2;
}
ebp += a;
d--;
if (d == 0) break;
}
int a = sub_6A9ED1(&ebp);
((uint32_t*)(esi + 4))[0] = a;
a += 3;
uint8_t* tmp = ebp;
ebp = ebp_tmp;
ebp_tmp = tmp;
int a_tmp = a;
int b_tmp = ebx;
int c_tmp = ecx;
d = 0;
int di = 0;
while (true)
{
if (((uint16_t*)(di + esi + 0x26))[0] & 1)
{
int al = 1;
if (((uint16_t*)(di + esi + 0x2E))[0] & 2)
{
int ax = ((uint16_t*)(di + esi + 0x2E))[0];
ax &= 0x820;
al = 0xD;
if (ax != 0x820)
{
al = 7;
if (!(((uint16_t*)(di + esi + 0x2E))[0] & 0x20))
{
if (!(((uint16_t*)(di + esi + 0x2E))[0] & 0x800))
{
al = 5;
if (((uint16_t*)(di + esi + 0x2E))[0] & 0x200) al = 3;
}
}
}
}
((uint8_t*)(di + esi + 0x1D))[0] = al;
al = 0x20;
if (!(((uint16_t*)(di + esi + 0x2C))[0] & 0x4000))
{
al = 1;
if (((uint16_t*)(di + esi + 0x2E))[0] & 0x80)
{
if (((uint8_t*)(di + esi + 0x2B))[0] != 6)
{
al = 2;
if (!(((uint16_t*)(di + esi + 0x2C))[0] & 0x80)) al = 4;
}
}
}
if (((uint16_t*)(di + esi + 0x2C))[0] & 0x1000) al = ((uint8_t*)(di + esi + 0x7A))[0];
((uint8_t*)(di + esi + 0x1C))[0] = al;
int a = ((uint8_t*)(di + esi + 0x1C))[0];
int b = ((uint8_t*)(di + esi + 0x1D))[0];
b *= a;
((uint16_t*)(di + esi + 0x30))[0] = b;
a = a_tmp;
((uint32_t*)(di + esi + 0x32))[0] = a;
if (((uint8_t*)(di + esi + 0x77))[0] != 4)
{
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x20;
if (((uint16_t*)(di + esi + 0x2C))[0] & 0x800) b >>= 1;
if (((uint16_t*)(di + esi + 0x26))[0] & 0x8000) b >>= 3;
a += b;
if (((uint16_t*)(di + esi + 0x26))[0] & 2)
{
((uint32_t*)(di + esi + 0x3A))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x48;
if (((uint16_t*)(di + esi + 0x2C))[0] & 0x4000)
{
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x10;
}
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 4)
{
((uint32_t*)(di + esi + 0x3E))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x50;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 8)
{
((uint32_t*)(di + esi + 0x42))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x74;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x10)
{
((uint32_t*)(di + esi + 0x46))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x18;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x20)
{
((uint32_t*)(di + esi + 0x4A))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x50;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x40)
{
((uint32_t*)(di + esi + 0x4E))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x28;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x80)
{
((uint32_t*)(di + esi + 0x52))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x80;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x100)
{
((uint32_t*)(di + esi + 0x56))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x10;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x200)
{
((uint32_t*)(di + esi + 0x5A))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x10;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x400)
{
((uint32_t*)(di + esi + 0x5E))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x80;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x800)
{
((uint32_t*)(di + esi + 0x62))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x10;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x1000)
{
((uint32_t*)(di + esi + 0x66))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x50;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x2000)
{
((uint32_t*)(di + esi + 0x36))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0xC;
a += b;
}
if (((uint16_t*)(di + esi + 0x26))[0] & 0x4000)
{
((uint32_t*)(di + esi + 0x66))[0] = a;
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x20;
a += b;
}
}
else
{
b = ((uint16_t*)(di + esi + 0x30))[0];
b *= 0x24;
a += b;
}
a -= a_tmp;
((uint32_t*)(di + esi + 0x6A))[0] = a;
a_tmp += a;
int c = ((uint8_t*)(di + esi + 0x6E))[0];
c *= a;
a_tmp += c;
if (!(((uint16_t*)(di + esi + 0x2C))[0] & 0x400))
{
c = a_tmp;
b = ((uint32_t*)(di + esi + 0x32))[0];
c -= b;
if (((uint16_t*)(di + esi + 0x2C))[0] & 0x2000) c <<= 1;
int d_tmp = d;
RCT2_CALLFUNC_X(0x6847BA, &a, &b, &c, &d, &esi, &di, (int*)&ebp);
if (((uint16_t*)(di + esi + 0x2C))[0] & 0x2000) b += 0x10;
((uint8_t*)(di + esi + 0x28))[0] = a;
((uint8_t*)(di + esi + 0x29))[0] = b & 0xFF;
((uint8_t*)(di + esi + 0x2A))[0] = (b >> 8) & 0xFF;
d = d_tmp;
}
a = ((uint8_t*)ebp)[0];
ebp++;
if (a == 0xFF)
{
a = ((uint16_t*)ebp)[0];
ebp += 2;
}
((uint32_t*)(di + esi + 0x7B))[0] = (uint32_t)ebp;
ebp += a;
}
d++;
di += 0x65;
if (d >= 4) break;
}
if (RCT2_GLOBAL(0x9ADAFD, uint8_t) == 0)
{
a = 0;
while (true)
{
int d = ((uint8_t*)(a + esi + 0xC))[0];
if (d != 0xFF)
{
uint8_t* di = (uint8_t*)0x9E32F8;
while (true)
{
if (di[0] != 0xFF)
{
di++;
continue;
}
d--;
if (d < 0) break;
di++;
}
d = b_tmp;
while (true)
{
int tmp = di[0];
di[0] = d;
d = tmp;
di++;
if ((uint32_t)di >= 0x9E34E4) break;
}
}
a++;
if (a >= 3) break;
}
}
if (RCT2_GLOBAL(0x9ADAF4, uint32_t) != 0xFFFFFFFF) RCT2_GLOBAL(0x9ADAF4, uint16_t*)[0] = 0;
di = ((uint32_t*)(esi + 0xC))[0] & 0xFFFFFF;
if (((uint32_t*)(esi + 8))[0] & 0x1000) di |= 0x1000000;
RCT2_GLOBAL(0xF433DD, uint32_t) = di;
return 0;// flags;
}
else
{
int d = 0;
int di = 0;
while (true)
{
/*if (!(((uint16_t*)(di + esi + 0x26))[0] & 1))*/
d++;
di += 0x65;
if (d >= 4) break;
}
if (((uint8_t*)(esi + 0x1B2))[0] > 0x4B) return 1;
if (((uint8_t*)(esi + 0x1B3))[0] > 0x4B) return 1;
if (((uint8_t*)(esi + 0x1B4))[0] > 0x4B) return 1;
return 0;
}
}
else
{
((rct_ride_type*)esi)->name = 0;
((rct_ride_type*)esi)->description = 0;
((rct_ride_type*)esi)->var_004 = 0;
int d = 0;
int di = 0;
while (true)
{
((uint32_t*)(esi + di + 0x32))[0] = 0;
((uint32_t*)(esi + di + 0x36))[0] = 0;
((uint32_t*)(esi + di + 0x3A))[0] = 0;
((uint32_t*)(esi + di + 0x3E))[0] = 0;
((uint32_t*)(esi + di + 0x42))[0] = 0;
((uint32_t*)(esi + di + 0x46))[0] = 0;
((uint32_t*)(esi + di + 0x4A))[0] = 0;
((uint32_t*)(esi + di + 0x4E))[0] = 0;
((uint32_t*)(esi + di + 0x52))[0] = 0;
((uint32_t*)(esi + di + 0x56))[0] = 0;
((uint32_t*)(esi + di + 0x5A))[0] = 0;
((uint32_t*)(esi + di + 0x5E))[0] = 0;
((uint32_t*)(esi + di + 0x66))[0] = 0;
((uint32_t*)(esi + di + 0x62))[0] = 0;
((uint32_t*)(esi + di + 0x6A))[0] = 0;
((uint16_t*)(esi + di + 0x30))[0] = 0;
if (((uint16_t*)(esi + di + 0x2C))[0] & 0x400)
{
((uint8_t*)(esi + di + 0x28))[0] = 0;
((uint8_t*)(esi + di + 0x29))[0] = 0;
((uint8_t*)(esi + di + 0x2A))[0] = 0;
}
((uint8_t*)(esi + di + 0x1C))[0] = 0;
((uint8_t*)(esi + di + 0x1D))[0] = 0;
((uint32_t*)(esi + di + 0x7B))[0] = 0;
d++;
di += 0x65;
if (d >= 4) break;
}
((uint32_t*)(esi + 0x1AE))[0] = 0;
return flags;
}
}
else
{
if (!((flags >> 8) & 0xFF))
{
int image_id = ((rct_ride_type*)ebp)->var_004;
if (((rct_ride_type*)ebp)->var_00C == 0xFF)
{
image_id++;
if (((rct_ride_type*)ebp)->var_00D == 0xFF) image_id++;
}
gfx_draw_sprite(dpi, image_id, ecx - 56, edx - 56, ebp);
return flags;
}
else
{
int width = ((uint16_t*)(esi + 0x30))[0];
width += ((uint16_t*)(esi + 0x2C))[0];
width -= ecx;
width -= 4;
int format_args = ((rct_ride_type*)ebp)->description;
if (!(((rct_ride_type*)ebp)->var_008 & 0x1000))
{
format_args = ((rct_ride_type*)ebp)->var_00C;
if ((format_args & 0xFF) == 0xFF)
{
format_args = ((rct_ride_type*)ebp)->var_00D;
if ((format_args & 0xFF) == 0xFF) format_args = ((rct_ride_type*)ebp)->var_00E;
}
format_args += 0x200;
}
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = format_args;
gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, ecx, edx + 5, width, 1191, 0);
return flags;
}
}
}
int paint_path_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp)
{
if ((flags & 0xFF) != 3)
{
if ((flags & 0xFF) != 1)
{
if ((flags & 0xFF) <= 1)//0
{
uint8_t* pStringTable = (uint8_t*)(esi + 0xE);
((rct_path_type*)esi)->pad_00 = object_get_localised_text(&pStringTable, ecx, ebx, 0);
int image_id = sub_6A9ED1(&pStringTable);
((rct_path_type*)esi)->image = image_id;
image_id += 0x6D;
((rct_path_type*)esi)->pad_06 = image_id;
if (RCT2_GLOBAL(0x9ADAF4, uint32_t) != 0xFFFFFFFF) RCT2_GLOBAL(0x9ADAF4, uint16_t*)[0] = 0;
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = 0;
int b = -1;
while (true)
{
b++;
if (b >= 0x10) break;
uint8_t* edi = object_entry_groups[5].chunks[ebx];
if ((uint32_t)edi == 0xFFFFFFFF) continue;
if (!(edi[0xB] & 4))
{
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = ebx;
break;
}
RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = ebx;
}
return flags;
}
else
{
if (((rct_path_type*)esi)->pad_0A >= 2) return 1;//actually the carry bit should be set (stc)
else return 0;
}
}
else
{
((rct_path_type*)esi)->pad_00 = 0;
((rct_path_type*)esi)->image = 0;
((rct_path_type*)esi)->pad_06 = 0;
return flags;
}
}
else
{
if (!((flags >> 8) & 0xFF))
{
//Draws preview for scenario editor!
gfx_draw_sprite(dpi, ((rct_path_type*)ebp)->image + 71, ecx - 49, edx - 17, ebp);
gfx_draw_sprite(dpi, ((rct_path_type*)ebp)->image + 72, ecx + 4, edx - 17, ebp);
}
return flags;
}
}
int paint_park_entrance_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp)
{
if ((flags & 0xFF) != 3)
{
if ((flags & 0xFF) != 1)
{
if ((flags & 0xFF) <= 1)//0
{
uint8_t* pStringTable = (uint8_t*)(esi + 8);
((rct_string_id*)esi)[0] = object_get_localised_text(&pStringTable, ecx, ebx, 0);
int image_id = sub_6A9ED1(&pStringTable);
((uint32_t*)(esi + 2))[0] = image_id;
if (RCT2_GLOBAL(0x9ADAF4, uint32_t) != 0xFFFFFFFF) RCT2_GLOBAL(0x9ADAF4, uint16_t*)[0] = 0;
return flags;
}
else
{
return 0;
}
}
else
{
((rct_string_id*)esi)[0] = 0;
((uint32_t*)(esi + 2))[0] = 0;
return flags;
}
}
else
{
if (!((flags >> 8) & 0xFF))
{
dpi = clip_drawpixelinfo(dpi, ecx - 56, 112, edx - 56, 112);
if (dpi == NULL) return flags;
int image_id = ((uint32_t*)(ebp + 2))[0];
gfx_draw_sprite(dpi, image_id + 1, 24, 68, ebp);
gfx_draw_sprite(dpi, image_id, 56, 84, ebp);
gfx_draw_sprite(dpi, image_id + 2, 88, 100, ebp);
}
return flags;
}
}
int paint_water_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp)
{
if ((flags & 0xFF) != 3)
{
if ((flags & 0xFF) != 1)
{
if ((flags & 0xFF) <= 1)//0
{
uint8_t* pStringTable = (uint8_t*)(esi + 0x10);
((rct_string_id*)esi)[0] = object_get_localised_text(&pStringTable, ecx, ebx, 0);
int image_id = sub_6A9ED1(&pStringTable);
((uint32_t*)(esi + 2))[0] = image_id;
image_id++;
((uint32_t*)(esi + 6))[0] = image_id;
image_id += 3;
((uint32_t*)(esi + 0xA))[0] = image_id;
if (RCT2_GLOBAL(0x9ADAF4, uint32_t) != 0xFFFFFFFF) RCT2_GLOBAL(0x9ADAF4, uint16_t*)[0] = 0;
if (RCT2_GLOBAL(0x9ADAFD, uint8_t) == 0)
{
load_palette();
gfx_invalidate_screen();
}
return flags;
}
else
{
return 0;
}
}
else
{
((rct_string_id*)esi)[0] = 0;
((uint32_t*)(esi + 2))[0] = 0;
((uint32_t*)(esi + 6))[0] = 0;
((uint32_t*)(esi + 0xA))[0] = 0;
return flags;
}
}
else
{
if (!((flags >> 8) & 0xFF)) gfx_draw_string_centred(dpi, 3326, ecx, edx, 0, (void*)esi);
return flags;
}
}
//0x0066B355
int paint_stex_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp)
{
if ((flags & 0xFF) != 3)
{
if ((flags & 0xFF) != 1)
{
if ((flags & 0xFF) <= 1)//0
{
uint8_t* pStringTable = (uint8_t*)(esi + 8);
((rct_stex_entry*)esi)->scenario_name = object_get_localised_text(&pStringTable, ecx, ebx, 0);
((rct_stex_entry*)esi)->park_name = object_get_localised_text(&pStringTable, ecx, ebx, 1);
((rct_stex_entry*)esi)->details = object_get_localised_text(&pStringTable, ecx, ebx, 2);
if (RCT2_GLOBAL(0x9ADAF4, int) != -1) RCT2_GLOBAL(0x9ADAF4, uint16_t*)[0] = 0;
return flags;
}
else//2
{
return 0;
}
}
else//1
{
((rct_stex_entry*)esi)->scenario_name = 0;
((rct_stex_entry*)esi)->park_name = 0;
((rct_stex_entry*)esi)->details = 0;
return flags;
}
}
else//3
{
if (!((flags >> 8) & 0xFF)) gfx_draw_string_centred(dpi, 0xCFE, ecx, edx, 0, (void*)esi);
else
{
RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = ((rct_stex_entry*)ebp)->details;
int width = *((uint16_t*)(esi + 0x2C));
width += *((uint16_t*)(esi + 0x30));
width -= 4;
width -= ecx;
gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, ecx, edx, width, 3168, 0);
}
return flags;
}
}
int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp)
{
//if (type == OBJECT_TYPE_SCENARIO_TEXT){
// 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) & 0x100;
//just use the rct2 function as long as this is not complete!
switch (type)
{
case OBJECT_TYPE_RIDE:
return paint_ride_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
case OBJECT_TYPE_PATHS:
return paint_path_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
case OBJECT_TYPE_PARK_ENTRANCE:
return paint_park_entrance_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
case OBJECT_TYPE_WATER:
return paint_water_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
case OBJECT_TYPE_SCENARIO_TEXT:
return paint_stex_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
default:
return RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098D9D4, uint32)[type], eax, ebx, ecx, edx, esi, edi, ebp) & 0x100;
}
}
/**
*
* 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;
rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
for (i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, 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;
// Skip file name
while (*pos++);
// 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;
return 0;
}
/**
*
* rct2: 0x006A982D
*/
void object_free_scenario_text()
{
if (RCT2_GLOBAL(0x009ADAF8, void*) != NULL) {
rct2_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)
{
uint8 *pos = (uint8*)entry;
// Skip sizeof(rct_object_entry)
pos += 16;
// Skip filename
while (*pos++);
// Skip
pos += 4;
// Skip name
while (*pos++);
// Skip size of chunk
pos += 4;
// Skip
pos += *pos++ * 16;
// Skip theme objects
pos += *pos++ * 16;
// Skip
pos += 4;
return (rct_object_entry*)pos;
}
char *object_get_name(rct_object_entry *entry)
{
uint8 *pos = (uint8*)entry;
// Skip sizeof(rct_object_entry)
pos += 16;
// Skip filename
while (*pos++);
// Skip
pos += 4;
return pos;
}