/** * * rct2: 0x00678998 */ void gfx_load_g1() { HANDLE hFile; DWORD bytesRead; DWORD header[2]; int i; int g1BufferSize; void* g1Buffer; rct_g1_element *g1Elements = RCT2_ADDRESS(RCT2_ADDRESS_G1_ELEMENTS, rct_g1_element); hFile = CreateFile(get_file_path(PATH_ID_G1), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { ReadFile(hFile, header, 8, &bytesRead, NULL); if (bytesRead == 8) { g1BufferSize = header[1]; g1Buffer = rct2_malloc(g1BufferSize); ReadFile(hFile, g1Elements, 29294 * sizeof(rct_g1_element), &bytesRead, NULL); ReadFile(hFile, g1Buffer, g1BufferSize, &bytesRead, NULL); CloseHandle(hFile); for (i = 0; i < 29294; i++) g1Elements[i].offset += (int)g1Buffer; return; } } // exit with error fprintf(stderr, "Unable to load g1.dat"); assert(0); }
/** * * rct2: 0x0068C88A */ void window_map_open() { rct_window* w; int* var; // Check if window is already open w = window_bring_to_front_by_id(WC_MAP, 0); if (w != NULL) { w->selected_tab = 0; w->var_490 = 0; return; } var = (int*)rct2_malloc(0x40000); if (var == NULL) return; RCT2_GLOBAL(0x00F1AD68, uint32) = (uint32)var; w = window_create_auto_pos(245, 259, (uint32*)window_map_events, WC_MAP, 0x0400); w->widgets = window_map_widgets; w->enabled_widgets = (1 << 2) | (1 << 4) | (1 << 5) | (1 << 8) | (1 << 9) | (1 << 14) | (1 << 15) | (1 << 10) | (1 << 16) | (1 << 17) | (1 << 18) | (1 << 19) | (1 << 11) | (1 << 20) | (1 << 12); //TODO: .text:0068C943 or dword ptr [esi+20h], 300h window_init_scroll_widgets(w); w->var_480 = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_ROTATION, uint16); RCT2_CALLPROC_EBPSAFE(0x0068CA6C); RCT2_GLOBAL(0x00F64F05, uint8) = 0; RCT2_CALLPROC_EBPSAFE(0x0068C990); w->colours[0] = 12; w->colours[1] = 24; }
/** * * rct2: 0x006A8B40 */ void object_list_load() { HANDLE hFindFile; WIN32_FIND_DATAA findFileData; int totalFiles = 0, totalFileSize = 0, fileDateModifiedChecksum = 0; char pluginPath[MAX_PATH]; get_plugin_path(pluginPath); // Enumerate through each object in the directory hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), &findFileData); if (hFindFile != INVALID_HANDLE_VALUE) { do { totalFiles++; totalFileSize += findFileData.nFileSizeLow; fileDateModifiedChecksum ^= findFileData.ftLastWriteTime.dwLowDateTime ^ findFileData.ftLastWriteTime.dwHighDateTime; fileDateModifiedChecksum = ror32(fileDateModifiedChecksum, 5); } while (FindNextFile(hFindFile, &findFileData)); FindClose(hFindFile); } totalFiles = ror32(totalFiles, 24); totalFiles = (totalFiles & ~0xFF) | 1; totalFiles = rol32(totalFiles, 24); // Read plugin header rct_plugin_header pluginHeader; FILE *file = fopen(pluginPath, "rb"); if (file != NULL) { if (fread(&pluginHeader, sizeof(pluginHeader), 1, file) == 1) { // Check if object repository has changed in anyway if ( totalFiles == pluginHeader.total_files && totalFileSize == pluginHeader.total_file_size && fileDateModifiedChecksum == pluginHeader.date_modified_checksum ) { // Dispose installed object list if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; } // Read installed object list RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(pluginHeader.object_list_size); if (fread(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), pluginHeader.object_list_size, 1, file) == 1) { RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) = pluginHeader.object_list_no_items; fclose(file); sub_6A9FC0(); object_list_examine(); return; } } } fclose(file); } // Reload object list RCT2_GLOBAL(0x00F42B94, uint32) = totalFiles; RCT2_GLOBAL(0x00F42B98, uint32) = totalFileSize; RCT2_GLOBAL(0x00F42B9C, uint32) = fileDateModifiedChecksum; //RCT2_CALLPROC_EBPSAFE(0x006A8D8F); int eax = 3161; if (RCT2_GLOBAL(0x9AA00D, uint8) != 0){ eax = 3160; RCT2_GLOBAL(0x9AA00D, uint8) = 0; } // File count removed and replaced by variable // RCT2_GLOBAL(0xF42BA8, uint32) = 0; uint32 file_count = 0; // Progress bar related. RCT2_GLOBAL(0xF42BD8, uint8) = 0; sub_6A9FC0(); // Dispose installed object list if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; } RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(4096); if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){ RCT2_CALLPROC_X(0x006E3838, 0x343, 0xC5A, 0, 0, 0, 0, 0); return; } uint32 installed_buffer_size = 0x1000; uint32 current_item_offset = 0; hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), &findFileData); if (hFindFile == INVALID_HANDLE_VALUE){ //6a92ea This hasn't been implemented but there isn't much point. // It would make a empty object file if no files found. return; } for (uint8 first_time = 1; first_time || FindNextFile(hFindFile, &findFileData);){ first_time = 0; RCT2_GLOBAL(0x9ABD98, HANDLE) = hFindFile; file_count++; // update progress bar. eax = (file_count << 8) / ((RCT2_GLOBAL(0xF42B94, uint32) & 0xFFFFFF) + 1); if ((eax & 0xFF) != RCT2_GLOBAL(0xF42BD8, uint8)){ RCT2_GLOBAL(0xF42BD8, uint8) = eax & 0xFF; // update progress bar } if ((installed_buffer_size - current_item_offset) <= 2842){ installed_buffer_size += 0x1000; RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size); if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){ RCT2_CALLPROC_X(0x006E3838, 0x343, 0xC5A, 0, 0, 0, 0, 0); return; } } char path[260]; subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), findFileData.cFileName); FILE *obj_file = fopen(path, "rb"); if (obj_file == NULL){ continue; } rct_object_entry* entry = RCT2_ADDRESS(0xF42B74, rct_object_entry); if (fread(entry, sizeof(rct_object_entry), 1, obj_file) != 1){ fclose(obj_file); continue; } fclose(obj_file); RCT2_GLOBAL(0xF42BC4, uint32) = current_item_offset; uint8* installed_entry_pointer = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset; memcpy(installed_entry_pointer, entry, sizeof(rct_object_entry)); installed_entry_pointer += sizeof(rct_object_entry); strcpy(installed_entry_pointer, findFileData.cFileName); while (*installed_entry_pointer++); *((sint32*)installed_entry_pointer) = -1; *(installed_entry_pointer + 4) = 0; *((sint32*)(installed_entry_pointer + 5)) = 0; *((uint16*)(installed_entry_pointer + 9)) = 0; *((uint32*)(installed_entry_pointer + 11)) = 0; RCT2_GLOBAL(0x9ADAF0, uint32) = 0xF26E; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; // This is a variable used by object_load to decide if it should // use object_paint on the entry. RCT2_GLOBAL(0x9ADAFD, uint8) = 1; // Probably used by object paint. RCT2_GLOBAL(0x9ADAF4, uint32) = 0xF42BDB; int chunk_size; if (!object_load(-1, entry, &chunk_size)){ RCT2_GLOBAL(0x9ADAF4, sint32) = -1; RCT2_GLOBAL(0x9ADAFD, uint8) = 0; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; continue; } // See above note RCT2_GLOBAL(0x9ADAF4, sint32) = -1; RCT2_GLOBAL(0x9ADAFD, uint8) = 0; if ((entry->flags & 0xF0) == 0x80){ RCT2_GLOBAL(0xF42B70, uint32)++; if (RCT2_GLOBAL(0xF42B70, uint32) > 772){ RCT2_GLOBAL(0xF42B70, uint32)--; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; continue; } } *((sint32*)installed_entry_pointer) = chunk_size; installed_entry_pointer += 4; uint8* chunk = RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*); // Loaded in object_load // When made of two parts i.e Wooden Roller Coaster (Dream Woodie Cars); if ((entry->flags & 0xF) == 0 && !(*((uint32*)(chunk + 8)) & 0x1000)){ rct_string_id obj_string = chunk[12]; if (obj_string == 0xFF){ obj_string = chunk[13]; if (obj_string == 0xFF){ obj_string = chunk[14]; } } obj_string += 2; format_string(installed_entry_pointer, obj_string, 0); strcat(installed_entry_pointer, "\t ("); strcat(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0xF42BBC, uint32))); strcat(installed_entry_pointer, ")"); while (*installed_entry_pointer++); } else{ strcpy(installed_entry_pointer, language_get_string(RCT2_GLOBAL(0xF42BBC, uint32))); while (*installed_entry_pointer++); } *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0x9ADAF0, uint32) - 0xF26E; installed_entry_pointer += 4; uint8* esi = RCT2_ADDRESS(0xF42BDB, uint8); int cl = *esi++; *installed_entry_pointer++ = cl; if (cl){ memcpy(installed_entry_pointer, esi, cl*sizeof(rct_object_entry)); installed_entry_pointer += cl*sizeof(rct_object_entry); } cl = *esi++; *installed_entry_pointer++ = cl; if (cl){ memcpy(installed_entry_pointer, esi, cl*sizeof(rct_object_entry)); installed_entry_pointer += cl*sizeof(rct_object_entry); } *((uint32*)installed_entry_pointer) = RCT2_GLOBAL(0xF433DD, uint32); installed_entry_pointer += 4; int size_of_object = installed_entry_pointer - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) - current_item_offset; object_unload(entry->flags & 0xF, (rct_object_entry_extended*)entry); // Return pointer to start of entry installed_entry_pointer -= size_of_object; uint8* copied_entry = RCT2_ADDRESS(0x140E9AC, uint8); size_of_object = object_copy(copied_entry, installed_entry_pointer); RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; copied_entry += sizeof(rct_object_entry); // Skip filename while (*copied_entry++); // Skip copied_entry += 4; installed_entry_pointer = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*); for (uint32 i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); ++i){ uint8* temp_installed_entry = installed_entry_pointer; temp_installed_entry += sizeof(rct_object_entry); // Skip filename while (*temp_installed_entry++); // Skip temp_installed_entry += 4; if (strcmp(temp_installed_entry, copied_entry) <= 0)break; installed_entry_pointer = (uint8*)(object_get_next((rct_object_entry*)installed_entry_pointer)); } // Difference to new location int no_bytes_to_move = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset - installed_entry_pointer; uint8* curr_location = installed_entry_pointer; uint8* move_location = installed_entry_pointer + size_of_object; if (no_bytes_to_move){ memmove(move_location, curr_location, no_bytes_to_move); } copied_entry = RCT2_ADDRESS(0x140E9AC, uint8); memcpy(installed_entry_pointer, copied_entry, size_of_object); current_item_offset += size_of_object; RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; }
/** * * rct2: 0x006A8B40 */ void object_list_load() { HANDLE hFindFile; WIN32_FIND_DATAA findFileData; int totalFiles = 0, totalFileSize = 0, fileDateModifiedChecksum = 0; // Enumerate through each object in the directory hFindFile = FindFirstFile(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), &findFileData); if (hFindFile != INVALID_HANDLE_VALUE) { do { totalFiles++; totalFileSize += findFileData.nFileSizeLow; fileDateModifiedChecksum ^= findFileData.ftLastWriteTime.dwLowDateTime ^ findFileData.ftLastWriteTime.dwHighDateTime; fileDateModifiedChecksum = ror32(fileDateModifiedChecksum, 5); } while (FindNextFile(hFindFile, &findFileData)); FindClose(hFindFile); } totalFiles = ror32(totalFiles, 24); totalFiles = (totalFiles & ~0xFF) | 1; totalFiles = rol32(totalFiles, 24); // Read plugin header rct_plugin_header pluginHeader; FILE *file = fopen(get_file_path(PATH_ID_PLUGIN), "rb"); if (file != NULL) { if (fread(&pluginHeader, sizeof(pluginHeader), 1, file) == 1) { // Check if object repository has changed in anyway if ( totalFiles == pluginHeader.total_files && totalFileSize == pluginHeader.total_file_size && fileDateModifiedChecksum == pluginHeader.date_modified_checksum ) { // Dispose installed object list if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; } // Read installed object list RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(pluginHeader.object_list_size); if (fread(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), pluginHeader.object_list_size, 1, file) == 1) { RCT2_GLOBAL(0x00F42B6C, uint32) = pluginHeader.var_10; fclose(file); RCT2_CALLPROC_EBPSAFE(0x006A9FC0); object_list_examine(); return; } } } fclose(file); } // Reload object list RCT2_GLOBAL(0x00F42B94, uint32) = totalFiles; RCT2_GLOBAL(0x00F42B98, uint32) = totalFileSize; RCT2_GLOBAL(0x00F42B9C, uint32) = fileDateModifiedChecksum; RCT2_CALLPROC_EBPSAFE(0x006A8D8F); }