diff --git a/src/localisation/language.c b/src/localisation/language.c index 690fa6db47..a7de019308 100644 --- a/src/localisation/language.c +++ b/src/localisation/language.c @@ -20,6 +20,7 @@ #include "../addresses.h" #include "localisation.h" +#include "../object.h" const char *language_names[LANGUAGE_COUNT] = { "", // LANGUAGE_UNDEFINED @@ -224,3 +225,64 @@ void language_close() gCurrentLanguage = LANGUAGE_UNDEFINED; } + +const int OpenRCT2LangIdToObjectLangId[] = { + 0, 0, 1, 3, 6, 2, 0, 0, 4, 7 +}; + +//0x006A9E24 +rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/*ecx*/, int index/*ebx*/, int tableindex/*edx*/) +{ + char* pString; + int result = 0; + while (true) + { + uint8_t language_code = ((uint8_t*)*pStringTable)[0]; + (*pStringTable)++; + if (language_code == 0xFF) //end of string table + break; + if (language_code == OpenRCT2LangIdToObjectLangId[gCurrentLanguage])//1) + { + pString = *pStringTable; + result |= 1; + } + if (language_code == 0 && !(result & 1)) + { + pString = *pStringTable; + result |= 2; + } + if (!(result & 7)) + { + pString = *pStringTable; + result |= 4; + } + while (true) + { + uint8_t character = ((uint8_t*)*pStringTable)[0]; + (*pStringTable)++; + if (character == 0) break; + } + } + if (RCT2_GLOBAL(0x9ADAFC, uint8_t) == 0) + { + int stringid = 0xD87; + int i; + for (i = 0; i < type; i++) + { + int nrobjects = object_entry_group_counts[i]; + int nrstringtables = RCT2_GLOBAL(0x98DA16 + i * 2, uint16_t);//the number of string tables in a type + stringid += nrobjects * nrstringtables; + } + stringid += index * RCT2_GLOBAL(0x98DA16 + type * 2, uint16_t); + RCT2_GLOBAL(0x00F42BBC, uint32) = stringid; + stringid += tableindex; + RCT2_GLOBAL(0x009BF2D4 + stringid * 4, char*) = pString;//put pointer in stringtable + return stringid; + } + else + { + int stringid = 0xD77 + tableindex; + RCT2_GLOBAL(0x009BF2D4 + stringid * 4, char*) = pString;//put pointer in stringtable + return stringid; + } +} \ No newline at end of file diff --git a/src/localisation/language.h b/src/localisation/language.h index d7973d071f..860d821dce 100644 --- a/src/localisation/language.h +++ b/src/localisation/language.h @@ -44,4 +44,6 @@ const char *language_get_string(rct_string_id id); int language_open(int id); void language_close(); +rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/*ecx*/, int index/*ebx*/, int tableindex/*edx*/); + #endif diff --git a/src/object.c b/src/object.c index 3637bda5ed..b30d0cccbd 100644 --- a/src/object.c +++ b/src/object.c @@ -8,12 +8,12 @@ * 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 . *****************************************************************************/ @@ -23,11 +23,12 @@ #include "object.h" #include "platform/platform.h" #include "util/sawyercoding.h" +#include "drawing/drawing.h" int object_load_entry(const char *path, rct_object_entry *outEntry) { FILE *file; - + file = fopen(path, "rb"); if (file == NULL) return 0; @@ -70,7 +71,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi // Read chunk size *chunkSize = *((uint32*)installedObject_pointer); char *chunk; - + if (*chunkSize == 0xFFFFFFFF) { chunk = rct2_malloc(0x600000); *chunkSize = sawyercoding_read_chunk(file, chunk); @@ -82,7 +83,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi } fclose(file); - + // Calculate and check checksum if (object_calculate_checksum(&openedEntry, chunk, *chunkSize) != openedEntry.checksum) { @@ -109,7 +110,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi 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++) { @@ -136,7 +137,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi } /** - * + * * rct2: 0x006A985D */ int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize) @@ -166,7 +167,7 @@ int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize) return 0; } -/** rct2: 0x006a9f42 +/** rct2: 0x006a9f42 * ebx : file * ebp : entry */ @@ -176,7 +177,7 @@ int sub_6A9F42(FILE *file, rct_object_entry* entry){ 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); @@ -184,7 +185,7 @@ int sub_6A9F42(FILE *file, rct_object_entry* entry){ uint32 size_dst = sizeof(rct_object_entry); - sawyercoding_chunk_header chunkHeader; + sawyercoding_chunk_header chunkHeader; // Encoding type (not used anymore) RCT2_GLOBAL(0x9E3CBD, uint8) = object_entry_group_encoding[type]; @@ -328,7 +329,7 @@ int object_load_packed(FILE *file) } /** - * + * * rct2: 0x006A9CAF */ void object_unload(int groupIndex, rct_object_entry_extended *entry) @@ -345,7 +346,8 @@ int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b) return 0; if (*((uint32*)(&a->name[4])) != *((uint32*)(&b->name[4]))) return 0; - } else { + } + else { if (a->flags != b->flags) return 0; if (*((uint32*)a->name) != *((uint32*)b->name)) @@ -380,27 +382,240 @@ int object_calculate_checksum(const rct_object_entry *entry, const char *data, i return checksum; } -/** - * rct2: 0x66B355 part - * If al is 0 - * chunk : esi - */ -int object_scenario_load_custom_text(char* chunk){ - int ebp = (int)(&((uint32*)chunk)[2]); +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 esi = eax; + esi *= 0x10; int edx = 0; - int eax, ebx, ecx, edi; - RCT2_CALLFUNC_X(0x6A9E24, &eax, &ebx, &ecx, &edx, (int*)&chunk, &edi, &ebp); - *((uint16*)chunk) = eax; - edx++; - RCT2_CALLFUNC_X(0x6A9E24, &eax, &ebx, &ecx, &edx, (int*)&chunk, &edi, &ebp); - *((uint16*)chunk + 1) = eax; - edx++; - RCT2_CALLFUNC_X(0x6A9E24, &eax, &ebx, &ecx, &edx, (int*)&chunk, &edi, &ebp); - *((uint16*)chunk + 2) = eax; + while (true) + { + RCT2_GLOBAL(RCT2_ADDRESS_G1_ELEMENTS + esi, uint32_t) = ((uint32_t*)(edx + (*ebp)))[0]; + RCT2_GLOBAL(RCT2_ADDRESS_G1_ELEMENTS + esi + 4, uint32_t) = ((uint32_t*)(edx + (*ebp)))[1]; + RCT2_GLOBAL(RCT2_ADDRESS_G1_ELEMENTS + esi + 8, uint32_t) = ((uint32_t*)(edx + (*ebp)))[2]; + RCT2_GLOBAL(RCT2_ADDRESS_G1_ELEMENTS + esi + 0xC, uint32_t) = ((uint32_t*)(edx + (*ebp)))[3]; + RCT2_GLOBAL(RCT2_ADDRESS_G1_ELEMENTS + esi, uint32_t) += ebx; + esi += 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; +} - if (RCT2_GLOBAL(0x9ADAF4, int) == -1)return 0; - else *(RCT2_GLOBAL(0x9ADAF4, uint32*)) = 0; - return 1; +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* ebp = esi + 0xE; + ((rct_string_id*)esi)[0] = object_get_localised_text(&ebp, ecx, ebx, 0); + int a = sub_6A9ED1(&ebp); + ((uint32_t*)(esi + 2))[0] = a; + a += 0x6D; + ((uint32_t*)(esi + 6))[0] = a; + 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 (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 (((uint8_t*)(esi + 0xA))[0] >= 2) return 1;//actually the carry bit should be set (stc) + else return 0; + } + } + else + { + ((rct_string_id*)esi)[0] = 0; + ((uint32_t*)(esi + 2))[0] = 0; + ((uint32_t*)(esi + 6))[0] = 0; + return flags; + } + } + else + { + if (!((flags >> 8) & 0xFF)) + { + //Draws preview for scenario editor! + int b = ((uint32_t*)(ebp + 2))[0]; + b += 0x47; + ecx -= 0x31; + edx -= 0x11; + gfx_draw_sprite(dpi, b, ecx, edx, ebp); + b++; + ecx += 0x35; + gfx_draw_sprite(dpi, b, ecx, edx, 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* ebp = esi + 8; + ((rct_string_id*)esi)[0] = object_get_localised_text(&ebp, ecx, ebx, 0); + int a = sub_6A9ED1(&ebp); + ((uint32_t*)(esi + 2))[0] = a; + 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 - 0x38, 0x70, edx - 0x38, 0x70); + if (dpi == NULL) return flags; + int b = ((uint32_t*)(ebp + 2))[0]; + gfx_draw_sprite(dpi, b + 1, 0x18, 0x44, ebp); + gfx_draw_sprite(dpi, b, 0x38, 0x54, ebp); + gfx_draw_sprite(dpi, b + 2, 0x58, 0x64, 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* ebp = esi + 0x10; + ((rct_string_id*)esi)[0] = object_get_localised_text(&ebp, ecx, ebx, 0); + int a = sub_6A9ED1(&ebp); + ((uint32_t*)(esi + 2))[0] = a; + a++; + ((uint32_t*)(esi + 6))[0] = a; + a += 3; + ((uint32_t*)(esi + 0xA))[0] = a; + 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, 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* ebp = esi + 8; + ((rct_string_id*)esi)[0] = object_get_localised_text(&ebp, ecx, ebx, 0); + ((rct_string_id*)esi)[1] = object_get_localised_text(&ebp, ecx, ebx, 1); + ((rct_string_id*)esi)[2] = object_get_localised_text(&ebp, 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_string_id*)esi)[0] = 0; + ((rct_string_id*)esi)[1] = 0; + ((rct_string_id*)esi)[2] = 0; + return flags; + } + } + else//3 + { + if (!((flags >> 8) & 0xFF)) + { + gfx_draw_string_centred(dpi, 0xCFE, ecx, edx, 0, esi); + } + else + { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = *((uint16_t*)(ebp + 4)); + int width = *((uint16_t*)(esi + 0x2C)); + width += *((uint16_t*)(esi + 0x30)); + width -= 4; + width -= ecx; + gfx_draw_string_left_wrapped(dpi, 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) @@ -408,11 +623,25 @@ int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, //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; + //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_PATHS: + return paint_path_entry(eax, ebx, ecx, edx, edi, esi, ebp); + case OBJECT_TYPE_PARK_ENTRANCE: + return paint_park_entrance_entry(eax, ebx, ecx, edx, edi, esi, ebp); + case OBJECT_TYPE_WATER: + return paint_water_entry(eax, ebx, ecx, edx, edi, esi, ebp); + case OBJECT_TYPE_SCENARIO_TEXT: + return paint_stex_entry(eax, ebx, ecx, edx, 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) @@ -444,8 +673,9 @@ int object_get_scenario_text(rct_object_entry *entry) if (chunkSize == 0xFFFFFFFF) { chunk = malloc(0x600000); chunkSize = sawyercoding_read_chunk(file, chunk); - chunk = realloc(chunk, chunkSize); - } else { + chunk = realloc(chunk, chunkSize); + } + else { chunk = malloc(chunkSize); sawyercoding_read_chunk(file, chunk); } @@ -488,7 +718,7 @@ int object_get_scenario_text(rct_object_entry *entry) } /** - * + * * rct2: 0x006A982D */ void object_free_scenario_text() diff --git a/src/scenario.c b/src/scenario.c index 663426b104..b0dd74652a 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -171,7 +171,7 @@ int scenario_load(const char *path) // Check expansion pack // RCT2_CALLPROC_EBPSAFE(0x006757E6); - RCT2_CALLPROC_EBPSAFE(0x006A9FC0); + sub_6A9FC0(); map_update_tile_pointers(); reset_0x69EBE4();// RCT2_CALLPROC_EBPSAFE(0x0069EBE4); return 1;