diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index dc258f115e..0286be4816 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -3787,3 +3787,4 @@ STR_5450 :Increase game speed STR_5451 :Open cheats window STR_5452 :Toggle visibility of toolbars STR_5453 :Select another ride +STR_5454 :Uncap FPS \ No newline at end of file diff --git a/src/config.c b/src/config.c index 75e9c1dde0..de68b5ef6a 100644 --- a/src/config.c +++ b/src/config.c @@ -175,6 +175,7 @@ config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, window_snap_proximity), "window_snap_proximity", CONFIG_VALUE_TYPE_UINT8, 5, NULL }, { offsetof(general_configuration, window_width), "window_width", CONFIG_VALUE_TYPE_SINT32, -1, NULL }, { offsetof(general_configuration, hardware_display), "hardware_display", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + { offsetof(general_configuration, uncap_fps), "uncap_fps", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, test_unfinished_tracks), "test_unfinished_tracks", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, no_test_crashes), "no_test_crashes", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, date_format), "date_format", CONFIG_VALUE_TYPE_UINT8, DATE_FORMAT_DMY, _dateFormatEnum }, diff --git a/src/config.h b/src/config.h index 8c70b4b64b..160630f2a3 100644 --- a/src/config.h +++ b/src/config.h @@ -146,6 +146,7 @@ typedef struct { uint8 window_snap_proximity; uint8 autosave_frequency; uint8 hardware_display; + uint8 uncap_fps; uint8 test_unfinished_tracks; uint8 no_test_crashes; uint8 date_format; diff --git a/src/game.c b/src/game.c index 3febe86643..3ba4e54996 100644 --- a/src/game.c +++ b/src/game.c @@ -219,9 +219,6 @@ void game_update() { int i, numUpdates; - // Handles picked-up peep and rain redraw - redraw_peep_and_rain(); - // 0x006E3AEC // screen_game_process_mouse_input(); screenshot_check(); game_handle_keyboard_input(); @@ -288,7 +285,6 @@ void game_update() RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) &= ~(1 << 2); window_map_tooltip_update_visibility(); - window_update_all(); RCT2_GLOBAL(0x01388698, uint16)++; @@ -296,11 +292,6 @@ void game_update() RCT2_GLOBAL(0x0141F568, uint8) = RCT2_GLOBAL(0x0013CA740, uint8); game_handle_input(); - update_palette_effects(); - update_rain_animation(); - - stop_completed_sounds(); // removes other sounds that are no longer playing, this is normally called somewhere in rct2_init - if (RCT2_GLOBAL(0x009AAC73, uint8) != 255) { RCT2_GLOBAL(0x009AAC73, uint8)++; if (RCT2_GLOBAL(0x009AAC73, uint8) == 255) diff --git a/src/openrct2.c b/src/openrct2.c index d5589b8d0e..40e09b9ba0 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -24,6 +24,7 @@ #include "cmdline.h" #include "config.h" #include "editor.h" +#include "interface/window.h" #include "localisation/localisation.h" #include "network/http.h" #include "openrct2.h" @@ -236,24 +237,80 @@ void openrct2_dispose() static void openrct2_loop() { uint32 currentTick, ticksElapsed, lastTick = 0; + static uint32 uncapTick; + static int fps = 0; + static uint32 secondTick = 0; + static int uncappedinitialized = 0; + static struct { sint16 x, y, z; } spritelocations1[MAX_SPRITES], spritelocations2[MAX_SPRITES]; log_verbose("begin openrct2 loop"); _finished = 0; do { - currentTick = SDL_GetTicks(); - ticksElapsed = currentTick - lastTick; - if (ticksElapsed < 25) { - if (ticksElapsed < 15) - SDL_Delay(15 - ticksElapsed); - continue; + if (gConfigGeneral.uncap_fps) { + currentTick = SDL_GetTicks(); + if (!uncappedinitialized) { + uncapTick = SDL_GetTicks(); + for (uint16 i = 0; i < MAX_SPRITES; i++) { + spritelocations1[i].x = spritelocations2[i].x = g_sprite_list[i].unknown.x; + spritelocations1[i].y = spritelocations2[i].y = g_sprite_list[i].unknown.y; + spritelocations1[i].z = spritelocations2[i].z = g_sprite_list[i].unknown.z; + } + uncappedinitialized = 1; + } + while (uncapTick <= currentTick && currentTick - uncapTick > 25) { + for (uint16 i = 0; i < MAX_SPRITES; i++) { + spritelocations1[i].x = g_sprite_list[i].unknown.x; + spritelocations1[i].y = g_sprite_list[i].unknown.y; + spritelocations1[i].z = g_sprite_list[i].unknown.z; + } + rct2_update(); + for (uint16 i = 0; i < MAX_SPRITES; i++) { + spritelocations2[i].x = g_sprite_list[i].unknown.x; + spritelocations2[i].y = g_sprite_list[i].unknown.y; + spritelocations2[i].z = g_sprite_list[i].unknown.z; + } + uncapTick += 25; + } + float nudge = 1 - ((float)(currentTick - uncapTick) / 25); + for (uint16 i = 0; i < MAX_SPRITES; i++) { + if (!(g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_VEHICLE || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_PEEP || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_UNKNOWN)) { + continue; + } + sprite_move(spritelocations2[i].x + (sint16)((spritelocations1[i].x - spritelocations2[i].x) * nudge), spritelocations2[i].y + (sint16)((spritelocations1[i].y - spritelocations2[i].y) * nudge), spritelocations2[i].z + (sint16)((spritelocations1[i].z - spritelocations2[i].z) * nudge), &g_sprite_list[i]); + invalidate_sprite(&g_sprite_list[i]); + } + platform_process_messages(); + rct2_draw(); + platform_draw(); + fps++; + if (SDL_GetTicks() - secondTick >= 1000) { + fps = 0; + secondTick = SDL_GetTicks(); + } + for (uint16 i = 0; i < MAX_SPRITES; i++) { + if (!(g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_VEHICLE || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_PEEP || g_sprite_list[i].unknown.linked_list_type_offset == SPRITE_LINKEDLIST_OFFSET_UNKNOWN)) { + continue; + } + sprite_move(spritelocations2[i].x, spritelocations2[i].y, spritelocations2[i].z, &g_sprite_list[i]); + } + } else { + uncappedinitialized = 0; + currentTick = SDL_GetTicks(); + ticksElapsed = currentTick - lastTick; + if (ticksElapsed < 25) { + if (ticksElapsed < 15) + SDL_Delay(15 - ticksElapsed); + continue; + } + + lastTick = currentTick; + + platform_process_messages(); + rct2_update(); + rct2_draw(); + platform_draw(); } - - lastTick = currentTick; - - platform_process_messages(); - rct2_update(); - platform_draw(); } while (!_finished); } diff --git a/src/platform/shared.c b/src/platform/shared.c index 77418e2137..529b7ce9cd 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -737,7 +737,7 @@ void platform_refresh_video() if (gConfigGeneral.hardware_display) { if (gRenderer == NULL) - gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED); + gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (gBufferTexture != NULL) SDL_DestroyTexture(gBufferTexture); diff --git a/src/rct2.c b/src/rct2.c index c2efdc4e92..b5b475e126 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -214,6 +214,29 @@ void rct2_update() rct2_update_2(); } +void rct2_draw() +{ + // Handles picked-up peep and rain redraw + redraw_peep_and_rain(); + + gfx_draw_all_dirty_blocks(); + + console_draw(RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo)); + + if (RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) != 0) { + //intro + } else if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) { + //title + DrawOpenRCT2(0, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 20); + } else { + //game + } + + window_update_all(); + update_rain_animation(); + update_palette_effects(); +} + int rct2_open_file(const char *path) { char *extension = strrchr(path, '.'); @@ -350,9 +373,10 @@ void rct2_update_2() else game_update(); + stop_completed_sounds(); // removes other sounds that are no longer playing in directsound + twitch_update(); console_update(); - console_draw(RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo)); } void rct2_endupdate() diff --git a/src/rct2.h b/src/rct2.h index 9421c31888..30b4d7156d 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -305,6 +305,7 @@ static const struct file_to_check int rct2_init(); void rct2_update(); +void rct2_draw(); void rct2_endupdate(); void subsitute_path(char *dest, const char *path, const char *filename); int check_mutex(); diff --git a/src/title.c b/src/title.c index 310dba3c7e..11b819e756 100644 --- a/src/title.c +++ b/src/title.c @@ -420,7 +420,7 @@ static void title_update_showcase() } while (gTitleScriptSkipTo != -1 && gTitleScriptSkipLoad == -1); } -static void DrawOpenRCT2(int x, int y) +void DrawOpenRCT2(int x, int y) { char buffer[256]; rct_drawpixelinfo *dpi = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); @@ -470,17 +470,12 @@ void title_update() window_map_tooltip_update_visibility(); window_dispatch_update_all(); - window_update_all(); - DrawOpenRCT2(0, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 20); RCT2_GLOBAL(0x01388698, uint16)++; // Input game_handle_input(); - update_palette_effects(); - update_rain_animation(); - if (RCT2_GLOBAL(0x009AAC73, uint8) != 255) { RCT2_GLOBAL(0x009AAC73, uint8)++; if (RCT2_GLOBAL(0x009AAC73, uint8) == 255) diff --git a/src/title.h b/src/title.h index b788e9e4aa..a07ee2e59b 100644 --- a/src/title.h +++ b/src/title.h @@ -45,5 +45,6 @@ void title_update(); void title_skip_from_beginning(); void title_script_get_line(FILE *file, char *parts); bool title_refresh_sequence(); +void DrawOpenRCT2(int x, int y); #endif diff --git a/src/windows/options.c b/src/windows/options.c index 86621a0836..a038be8344 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -78,6 +78,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX { WIDX_TILE_SMOOTHING_CHECKBOX, WIDX_GRIDLINES_CHECKBOX, WIDX_HARDWARE_DISPLAY_CHECKBOX, + WIDX_UNCAP_FPS_CHECKBOX, WIDX_MINIMIZE_FOCUS_LOSS, WIDX_CONSTRUCTION_MARKER, WIDX_CONSTRUCTION_MARKER_DROPDOWN, @@ -163,6 +164,7 @@ static rct_widget window_options_display_widgets[] = { { WWT_CHECKBOX, 1, 10, 290, 84, 95, STR_TILE_SMOOTHING, STR_TILE_SMOOTHING_TIP }, // landscape smoothing { WWT_CHECKBOX, 1, 10, 290, 99, 110, STR_GRIDLINES, STR_GRIDLINES_TIP }, // gridlines { WWT_CHECKBOX, 1, 10, 290, 114, 125, 5154, STR_NONE }, // hardware display + { WWT_CHECKBOX, 1, 155, 290, 114, 125, 5454, STR_NONE }, // uncap fps { WWT_CHECKBOX, 1, 10, 290, 129, 140, 5440, STR_NONE }, // minimize fullscreen focus loss { WWT_DROPDOWN, 1, 155, 299, 143, 154, STR_NONE, STR_NONE }, // construction marker { WWT_DROPDOWN_BUTTON, 1, 288, 298, 144, 153, 876, STR_NONE }, @@ -327,6 +329,7 @@ static uint32 window_options_page_enabled_widgets[] = { (1 << WIDX_TILE_SMOOTHING_CHECKBOX) | (1 << WIDX_GRIDLINES_CHECKBOX) | (1 << WIDX_HARDWARE_DISPLAY_CHECKBOX) | + (1 << WIDX_UNCAP_FPS_CHECKBOX) | (1 << WIDX_MINIMIZE_FOCUS_LOSS) | (1 << WIDX_CONSTRUCTION_MARKER) | (1 << WIDX_CONSTRUCTION_MARKER_DROPDOWN) | @@ -463,6 +466,11 @@ static void window_options_mouseup() config_save_default(); window_invalidate(w); break; + case WIDX_UNCAP_FPS_CHECKBOX: + gConfigGeneral.uncap_fps ^= 1; + config_save_default(); + window_invalidate(w); + break; case WIDX_MINIMIZE_FOCUS_LOSS: gConfigGeneral.minimize_fullscreen_focus_loss ^= 1; platform_refresh_video(); @@ -1066,6 +1074,7 @@ static void window_options_invalidate() widget_set_checkbox_value(w, WIDX_TILE_SMOOTHING_CHECKBOX, (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE) == 0); widget_set_checkbox_value(w, WIDX_GRIDLINES_CHECKBOX, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES); widget_set_checkbox_value(w, WIDX_HARDWARE_DISPLAY_CHECKBOX, gConfigGeneral.hardware_display); + widget_set_checkbox_value(w, WIDX_UNCAP_FPS_CHECKBOX, gConfigGeneral.uncap_fps); widget_set_checkbox_value(w, WIDX_MINIMIZE_FOCUS_LOSS, gConfigGeneral.minimize_fullscreen_focus_loss); // construction marker: celsius/fahrenheit @@ -1080,6 +1089,7 @@ static void window_options_invalidate() window_options_display_widgets[WIDX_CONSTRUCTION_MARKER].type = WWT_DROPDOWN; window_options_display_widgets[WIDX_CONSTRUCTION_MARKER_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_options_display_widgets[WIDX_HARDWARE_DISPLAY_CHECKBOX].type = WWT_CHECKBOX; + window_options_display_widgets[WIDX_UNCAP_FPS_CHECKBOX].type = WWT_CHECKBOX; window_options_display_widgets[WIDX_MINIMIZE_FOCUS_LOSS].type = WWT_CHECKBOX; window_options_display_widgets[WIDX_THEMES].type = WWT_DROPDOWN; window_options_display_widgets[WIDX_THEMES_DROPDOWN].type = WWT_DROPDOWN_BUTTON;