diff --git a/src/addresses.h b/src/addresses.h index c33db9330d..970abf8f8c 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -253,6 +253,11 @@ #define RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX 0x00F43908 +#define RCT2_ADDRESS_TRACK_LIST 0x00F44105 +#define RCT2_ADDRESS_TRACK_LIST_CACHE 0x00F44109 +#define RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX 0x00F44119 + + #define RCT2_ADDRESS_CURRENT_MONTH_YEAR 0x00F663A8 #define RCT2_ADDRESS_CURRENT_MONTH_TICKS 0x00F663AA #define RCT2_ADDRESS_SCENARIO_TICKS 0x00F663AC @@ -500,21 +505,6 @@ #pragma endregion -static void RCT2_CALLPROC_EBPSAFE(int address) -{ - #ifdef _MSC_VER - __asm push ebp - __asm call address - __asm pop ebp - #else - __asm__ ( "\ - push ebp \n\ - call %[address] \n\ - pop ebp \n\ - " : [address] "+m" (address) ); - #endif -} - /* Returns the flags register * *Flags register is as follows: @@ -569,45 +559,9 @@ static int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx, #endif } -static void RCT2_CALLPROC_X_EBPSAFE(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp) +static int RCT2_CALLPROC_EBPSAFE(int address) { - #ifdef _MSC_VER - __asm { - push ebp - push address - mov eax, _eax - mov ebx, _ebx - mov ecx, _ecx - mov edx, _edx - mov esi, _esi - mov edi, _edi - mov ebp, _ebp - call[esp] - add esp, 4 - pop ebp - } - #else - __asm__ ( "\ - \n\ - push ebx \n\ - push ebp \n\ - push %[address] \n\ - mov eax, %[_eax] \n\ - mov ebx, %[_ebx] \n\ - mov ecx, %[_ecx] \n\ - mov edx, %[_edx] \n\ - mov esi, %[_esi] \n\ - mov edi, %[_edi] \n\ - mov ebp, %[_ebp] \n\ - call [esp] \n\ - add esp, 4 \n\ - pop ebp \n\ - pop ebx \n\ - " : [address] "+m" (address), [_eax] "+m" (_eax), [_ebx] "+m" (_ebx), [_ecx] "+m" (_ecx), [_edx] "+m" (_edx), [_esi] "+m" (_esi), [_edi] "+m" (_edi), [_ebp] "+m" (_ebp) - : - : "eax","ecx","edx","esi","edi" - ); - #endif + return RCT2_CALLPROC_X(address, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB); } /* Returns the flags register diff --git a/src/ride/track.c b/src/ride/track.c index 7124bb6f9a..c3956d0ab8 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -240,26 +240,16 @@ static void read(void *dst, void **src, int length) * rct2: 0x0067726A * path: 0x0141EF68 */ -int sub_67726A(const char *path) +rct_track_design* load_track_design(const char *path) { FILE *fp; long fpLength; - const char *ch; - char trackFilename[MAX_PATH], *fpBuffer, *decoded, *src, *dst; + char *fpBuffer, *decoded, *src; int i, decodedLength; uint8* edi; RCT2_GLOBAL(0x009AAC54, uint8) = 1; - // Get filename - ch = strrchr(path, '\\'); - ch = ch == NULL ? path : ch + 1; - dst = trackFilename; - while (*ch != 0 && *ch != '.') { - *dst++ = *ch++; - } - *dst = 0; - fp = fopen(path, "rb"); if (fp == NULL) return 0; @@ -280,98 +270,111 @@ int sub_67726A(const char *path) realloc(decoded, decodedLength); free(fpBuffer); + rct_track_design* track_design = RCT2_ADDRESS(0x009D8178, rct_track_design); // Read decoded data src = decoded; - memset((void*)0x009D81D8, 0, 67); - read((void*)0x009D8178, &src, 32); + // Clear top of track_design as this is not loaded from the file + memset(&track_design->pad_60, 0, 67); + // Read start of track_design + read(track_design, &src, 32); - uint8 al = RCT2_GLOBAL(0x009D817F, uint8) >> 2; + uint8 al = track_design->var_07 >> 2; if (al >= 2) - read((void*)0x009D8198, &src, 40); + read(&track_design->pad_20, &src, 40); - read((void*)0x009D81C0, &src, 24); - al = RCT2_GLOBAL(0x009D817F, uint8) >> 2; + read(&track_design->pad_48, &src, 24); + al = track_design->var_07 >> 2; if (al != 0) - read((void*)0x009D81D8, &src, al == 1 ? 140 : 67); + read(&track_design->pad_60, &src, al == 1 ? 140 : 67); - read((void*)0x009D821B, &src, 24572); - al = RCT2_GLOBAL(0x009D817F, uint8) >> 2; + read(&track_design->preview, &src, 24572); + al = track_design->var_07 >> 2; if (al < 2) { - if (RCT2_GLOBAL(0x009D8178, uint8) == 20) { - edi = (uint8*)0x009D821B; + if (track_design->type == RIDE_TYPE_MAZE) { + edi = (uint8*)(&track_design->preview); while (*edi != 0) { edi += 4; } edi += 4; - memset(edi, 255, (uint8*)0x009DE217 - edi); + memset(edi, 255, ((uint8*)&track_design->pad_9F) - edi); } else { - edi = (uint8*)0x009D821B; + edi = (uint8*)(&track_design->preview); while (*edi != 255) { edi += 2; } edi++; - memset(edi, 255, (uint8*)0x009DE217 - edi); + memset(edi, 255, ((uint8*)&track_design->pad_9F) - edi); } } free(decoded); // - al = RCT2_GLOBAL(0x009D817F, uint8) >> 2; + al = track_design->var_07 >> 2; if (al > 2) - return 0; + return NULL; if (al <= 1) { - edi = (uint8*)0x009D8180; + edi = (uint8*)&track_design->pad_08; for (i = 0; i < 67; i++) *edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi]; - edi = (uint8*)0x009D81D8; + edi = (uint8*)&track_design->pad_60; for (i = 0; i < 12; i++) *edi++ = RCT2_ADDRESS(0x0097F0BC, uint8)[*edi]; - RCT2_GLOBAL(0x009D81D2, uint8) >>= 1; + track_design->highest_drop_height >>= 1; if (!RCT2_CALLPROC_X(0x00677530, 0, 0, 0, 0, 0, 0, 0)) - RCT2_GLOBAL(0x009D8178, uint8) = 255; + track_design->type = 255; - if (RCT2_GLOBAL(0x009D8178, uint8) == 4) - RCT2_GLOBAL(0x009D8178, uint8) = 255; + if (track_design->type == RIDE_TYPE_JUNIOR_ROLLER_COASTER) + track_design->type = RIDE_TYPE_NULL; - if (RCT2_GLOBAL(0x009D8178, uint8) == 0) - RCT2_GLOBAL(0x009D8178, uint8) = 52; + if (track_design->type == RIDE_TYPE_SPIRAL_ROLLER_COASTER) + track_design->type = RIDE_TYPE_WOODEN_ROLLER_COASTER; - if (RCT2_GLOBAL(0x009D8178, uint8) == 19) { - if (RCT2_GLOBAL(0x009D817E, uint8) == 3) - RCT2_GLOBAL(0x009D817E, uint8) = 35; - if (RCT2_GLOBAL(0x009D8179, uint8) == 79) { - if (RCT2_GLOBAL(0x009D817E, uint8) == 2) - RCT2_GLOBAL(0x009D817E, uint8) = 1; + if (track_design->type == RIDE_TYPE_CORKSCREW_ROLLER_COASTER) { + if (track_design->var_06 == 3) + track_design->var_06 = 35; + if (track_design->var_01 == 79) { + if (track_design->var_06 == 2) + track_design->var_06 = 1; } } - int unk1 = RCT2_GLOBAL(0x009D8179, uint8); - if (RCT2_GLOBAL(0x009D8178, uint8) == 20) { - unk1 = 0x0097F66C; + rct_object_entry* vehicle_object; + if (track_design->type == RIDE_TYPE_MAZE) { + vehicle_object = RCT2_ADDRESS(0x0097F66C, rct_object_entry); } else { - if (unk1 == 3 && RCT2_GLOBAL(0x009D8178, uint8) == 3) - unk1 = 80; - unk1 = 0x0097F0DC + (unk1 * 16); + int var_01 = track_design->var_01; + if (var_01 == 3 && track_design->type == 3) + var_01 = 80; + vehicle_object = &RCT2_ADDRESS(0x0097F0DC, rct_object_entry)[var_01]; } - memcpy((void*)0x009D81E8, (void*)unk1, 16); + memcpy(&track_design->vehicle_object, vehicle_object, sizeof(rct_object_entry)); for (i = 0; i < 32; i++) - RCT2_ADDRESS(0x009D81FA, uint8)[i] = RCT2_ADDRESS(0x009D8181, uint8)[i * 2]; + track_design->pad_82[i] = track_design->pad_08[1 + i * 2]; - RCT2_GLOBAL(0x009D81F8, uint8) = 255; - RCT2_GLOBAL(0x009D81F9, uint8) = 255; - RCT2_GLOBAL(0x009D821A, uint8) = 5; + track_design->space_required_x = 255; + track_design->space_required_y = 255; + track_design->var_A2 = 5; } - RCT2_GLOBAL(0x009D81C8, uint8) = min( - RCT2_GLOBAL(0x009D81C8, uint8), - RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (RCT2_GLOBAL(0x009D8178, uint8) * 8), uint8) + track_design->var_50 = min( + track_design->var_50, + RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (track_design->type * 8), uint8) ); - return 1; + return track_design; +} + +/* rct2: 0x006D1DCE*/ +void reset_track_list_cache(){ + int* track_list_cache = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST_CACHE, int); + for (int i = 0; i < 4; ++i){ + track_list_cache[i] = -1; + } + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32) = 0; } /** @@ -389,30 +392,39 @@ rct_track_design *track_get_info(int index, uint8** preview) // Check if track design has already been loaded for (i = 0; i < 4; i++) { - if (index == RCT2_ADDRESS(0x00F44109, uint32)[i]) { - trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i]; + if (index == RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST_CACHE, uint32)[i]) { + trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, rct_track_design*)[i]; break; } } if (trackDesign == NULL) { // Load track design - i = RCT2_GLOBAL(0x00F44119, uint32); - RCT2_GLOBAL(0x00F44119, uint32)++; - if (RCT2_GLOBAL(0x00F44119, uint32) >= 4) - RCT2_GLOBAL(0x00F44119, uint32) = 0; + i = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32)++; + if (RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32) >= 4) + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST_NEXT_INDEX, uint32) = 0; - RCT2_ADDRESS(0x00F44109, uint32)[i] = index; - subsitute_path((char*)0x0141EF68, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignList + (index * 128)); - if (!sub_67726A((char*)0x0141EF68)) { + RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST_CACHE, uint32)[i] = index; + + char track_path[MAX_PATH] = { 0 }; + subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignList + (index * 128)); + + rct_track_design* loaded_design = NULL; + + log_verbose("Loading track: %s", trackDesignList + (index * 128)); + + if (!(loaded_design = load_track_design(track_path))) { if (preview != NULL) *preview = NULL; + log_error("Failed to load track: %s", trackDesignList + (index * 128)); return NULL; } - trackDesign = &RCT2_GLOBAL(0x00F44105, rct_track_design*)[i]; + trackDesign = &RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, rct_track_design*)[i]; - memcpy(trackDesign, (void*)0x009D8178, 163); - RCT2_CALLPROC_EBPSAFE(0x006D1EF0); + // Copy the track design apart from the preview image + memcpy(trackDesign, loaded_design, 163); + // Load in a new preview image, calculate cost variable, calculate var_06 + RCT2_CALLPROC_X(0x006D1EF0, 0, 0, 0, 0, 0, (int)&trackDesign->preview, 0); trackDesign->cost = RCT2_GLOBAL(0x00F4411D, money32); trackDesign->var_06 = RCT2_GLOBAL(0x00F44151, uint8) & 7; diff --git a/src/ride/track.h b/src/ride/track.h index b4c89ef6e8..10d66427e7 100644 --- a/src/ride/track.h +++ b/src/ride/track.h @@ -23,6 +23,7 @@ #include "../common.h" #include "ride.h" +#include "../object.h" typedef struct { uint8 type; @@ -42,13 +43,16 @@ typedef struct { */ typedef struct { uint8 type; // 0x00 - uint8 pad_01; + uint8 var_01; money32 cost; // 0x02 uint8 var_06; uint8 var_07; - uint8 pad_08[0x42]; + uint8 pad_08[0x18]; + uint8 pad_20[40]; + uint8 pad_48[2]; uint8 total_air_time; // 0x4A - uint8 pad_4B[0x06]; + uint8 pad_4B[0x05]; + uint8 var_50; uint8 max_speed; // 0x51 uint8 average_speed; // 0x52 uint16 ride_length; // 0x53 @@ -64,12 +68,15 @@ typedef struct { uint8 excitement; // 0x5B uint8 intensity; // 0x5C uint8 nausea; // 0x5D - uint8 pad_5E[0x0E]; + uint8 pad_5E[2]; + uint8 pad_60[0xC]; uint32 var_6C; - uint8 pad_70[0x10]; + rct_object_entry vehicle_object; // 0x70 uint8 space_required_x; // 0x80 uint8 space_required_y; // 0x81 - uint8 pad_82[0x21]; + uint8 pad_82[0x1D]; + uint8 pad_9F[3]; + uint8 var_A2; uint8 preview[4][TRACK_PREVIEW_IMAGE_SIZE]; // 0xA3 } rct_track_design; @@ -135,5 +142,6 @@ int sub_67726A(const char *path); rct_track_design *track_get_info(int index, uint8** preview); int track_rename(const char *text); int track_delete(); +void reset_track_list_cache(); #endif \ No newline at end of file diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c index 71033da7db..58911a4a1b 100644 --- a/src/windows/editor_bottom_toolbar.c +++ b/src/windows/editor_bottom_toolbar.c @@ -166,8 +166,8 @@ void window_editor_bottom_toolbar_jump_back_to_object_selection() { */ void window_editor_bottom_toolbar_jump_back_to_landscape_editor() { window_close_all(); - RCT2_CALLPROC(0x006DFED0); - RCT2_CALLPROC(0x006DFEE4); + RCT2_CALLPROC_EBPSAFE(0x006DFED0); + RCT2_CALLPROC_EBPSAFE(0x006DFEE4); g_editor_step = EDITOR_STEP_LANDSCAPE_EDITOR; window_map_open(); gfx_invalidate_screen(); diff --git a/src/windows/editor_top_toolbar.c b/src/windows/editor_top_toolbar.c index 936e532458..f525b6a8e2 100644 --- a/src/windows/editor_top_toolbar.c +++ b/src/windows/editor_top_toolbar.c @@ -296,7 +296,7 @@ void window_editor_top_toolbar_dropdown() { if (dropdownIndex == DDIDX_SE_LOAD_LANDSCAPE) { game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 0, 0); } else if (dropdownIndex == DDIDX_SE_SAVE_LANDSCAPE) { - RCT2_CALLPROC(0x0066FE2A); + RCT2_CALLPROC_EBPSAFE(0x0066FE2A); } else if (dropdownIndex == DDIDX_SE_ABOUT) { window_about_open(); } else if (dropdownIndex == DDIDX_SE_OPTIONS) { diff --git a/src/windows/guest.c b/src/windows/guest.c index 584f5e87b9..3b082eb783 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -568,7 +568,7 @@ void window_guest_overview_resize(){ window_get_register(w); window_guest_disable_widgets(w); - RCT2_CALLPROC_EBPSAFE(w->event_handlers[WE_INVALIDATE]); + RCT2_CALLPROC_X(w->event_handlers[WE_INVALIDATE], 0, 0, 0, 0, (int)w, 0, 0); widget_invalidate(w, WIDX_MARQUEE); diff --git a/src/windows/ride.c b/src/windows/ride.c index fdb82255de..e0e948d631 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -2398,7 +2398,7 @@ static void window_ride_vehicle_invalidate() // Vehicle type window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].image = rideEntry->name; - if (var_496(w) <= 1 || (w->enabled_widgets & (1 << WIDX_TAB_10))) { + if (var_496(w) <= 1 || (rideEntry->var_008 & (1 << 13))) { window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE].type = WWT_14; window_ride_vehicle_widgets[WIDX_VEHICLE_TYPE_DROPDOWN].type = WWT_EMPTY; w->enabled_widgets &= ~(1 << WIDX_VEHICLE_TYPE); diff --git a/src/windows/track_list.c b/src/windows/track_list.c index 555a263d3d..c996df281b 100644 --- a/src/windows/track_list.c +++ b/src/windows/track_list.c @@ -126,8 +126,8 @@ void window_track_list_open(ride_list_item item) if (mem == NULL) return; - RCT2_GLOBAL(0x00F44105, void*) = mem; - RCT2_CALLPROC_EBPSAFE(0x006D1DCE); + RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, void*) = mem; + reset_track_list_cache(); if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) { x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2 - 300; @@ -200,6 +200,7 @@ static void window_track_list_select(rct_window *w, int index) } trackDesign = track_get_info(index, NULL); + if (trackDesign == NULL) return; if (trackDesign->var_06 & 4) window_error_open(STR_THIS_DESIGN_WILL_BE_BUILT_WITH_AN_ALTERNATIVE_VEHICLE_TYPE, -1); @@ -236,7 +237,7 @@ static int window_track_list_get_list_item_index_from_position(int x, int y) */ static void window_track_list_close() { - free(RCT2_GLOBAL(0x00F44105, void*)); + free(RCT2_GLOBAL(RCT2_ADDRESS_TRACK_LIST, void*)); } /** @@ -398,7 +399,7 @@ static void window_track_list_paint() rct_window *w; rct_drawpixelinfo *dpi; rct_widget *widget; - rct_track_design *trackDesign; + rct_track_design *trackDesign = NULL; uint8 *image, *trackDesignList = (uint8*)0x00F441EC; uint16 holes, speed, drops, dropHeight, inversions; fixed32_2dp rating; diff --git a/src/windows/track_place.c b/src/windows/track_place.c index 676f1a99a9..6f935f2b48 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -218,7 +218,7 @@ static void window_track_place_draw_mini_preview() } else { pixelX = 80 + ((y / 32) - (x / 32)) * 4; pixelY = 38 + ((y / 32) + (x / 32)) * 2; - if (pixelX <= 160 && pixelY <= 75) { + if (pixelX >= 0 && pixelY >= 0 && pixelX <= 160 && pixelY <= 75) { pixel = &_window_track_place_mini_preview[pixelY * TRACK_MINI_PREVIEW_WIDTH + pixelX]; bits = trackBlock->var_08 << (rotation & 3);