diff --git dataobj/environment.cc dataobj/environment.cc index 520fd6441..72afe9eb7 100644 --- dataobj/environment.cc +++ dataobj/environment.cc @@ -122,6 +122,7 @@ plainstring env_t::river_type[10]; uint8 env_t::river_types; sint32 env_t::autosave; uint32 env_t::fps; +uint32 env_t::ff_fps; sint16 env_t::max_acceleration; uint8 env_t::num_threads; bool env_t::show_tooltips; @@ -226,11 +227,10 @@ void env_t::init() // autosave every x months (0=off) autosave = 0; - // default: make 25 frames per second (if possible) - fps=25; + fps = 25; + ff_fps = 25; - // maximum speedup set to 1000 (effectively no limit) - max_acceleration=50; + max_acceleration = 50; #ifdef MULTI_THREAD num_threads = 4; @@ -350,6 +350,9 @@ void env_t::rdwr(loadsave_t *file) file->rdwr_long( autosave ); file->rdwr_long( fps ); + if (file->is_version_atleast(121, 1)) { + file->rdwr_long(ff_fps); + } file->rdwr_short( max_acceleration ); file->rdwr_bool( road_user_info ); diff --git dataobj/environment.h dataobj/environment.h index dc8e21fd4..4d1443438 100644 --- dataobj/environment.h +++ dataobj/environment.h @@ -362,8 +362,10 @@ public: */ /// @{ - /// set the frame rate for the display - static uint32 fps; + static uint32 fps; ///< target frame rate + static uint32 ff_fps; ///< target fps during fast forward + static const uint32 min_fps = 10; ///< minimum target fps (actual fps may be lower for large zoom out on slow machines) + static const uint32 max_fps = 100; /// maximum acceleration with fast forward static sint16 max_acceleration; diff --git dataobj/settings.cc dataobj/settings.cc index cc62e4dde..e57bbfc8c 100644 --- dataobj/settings.cc +++ dataobj/settings.cc @@ -701,7 +701,7 @@ void settings_t::rdwr(loadsave_t *file) random_counter = get_random_seed( ); file->rdwr_long( random_counter ); if( !env_t::networkmode || env_t::server ) { - frames_per_second = clamp(env_t::fps,5,100 ); // update it on the server to the current setting + frames_per_second = env_t::fps; // update it on the server to the current setting frames_per_step = env_t::network_frames_per_step; } file->rdwr_long( frames_per_second ); @@ -901,7 +901,8 @@ void settings_t::parse_simuconf(tabfile_t& simuconf, sint16& disp_width, sint16& env_t::show_names = contents.get_int("show_names", env_t::show_names ); env_t::show_month = contents.get_int("show_month", env_t::show_month ); env_t::max_acceleration = contents.get_int("fast_forward", env_t::max_acceleration ); - env_t::fps = contents.get_int("frames_per_second",env_t::fps ); + env_t::fps = clamp(contents.get_int("frames_per_second", env_t::fps), env_t::min_fps, env_t::max_fps); + env_t::ff_fps = clamp(contents.get_int("ff_frames_per_second", env_t::ff_fps), env_t::min_fps, env_t::max_fps); env_t::num_threads = clamp( contents.get_int("threads", env_t::num_threads ), 1, MAX_THREADS ); env_t::simple_drawing_default = contents.get_int("simple_drawing_tile_size",env_t::simple_drawing_default ); env_t::simple_drawing_fast_forward = contents.get_int("simple_drawing_fast_forward",env_t::simple_drawing_fast_forward ); diff --git gui/display_settings.cc gui/display_settings.cc index ce2ea1492..a78b9acb8 100644 --- gui/display_settings.cc +++ gui/display_settings.cc @@ -135,7 +135,7 @@ void gui_settings_t::draw(scr_coord offset) idle_time_value_label.update(); // fps_label - uint32 target_fps = world()->is_fast_forward() ? 10 : env_t::fps; + uint32 target_fps = world()->is_fast_forward() ? env_t::ff_fps : env_t::fps; uint32 loops = world()->get_realFPS(); PIXVAL color = SYSCOL_TEXT_HIGHLIGHT; if( loops < (target_fps*16*3)/4 ) { diff --git gui/settings_stats.cc gui/settings_stats.cc index 2ceabcf1f..f34779fc7 100644 --- gui/settings_stats.cc +++ gui/settings_stats.cc @@ -153,7 +153,8 @@ void settings_general_stats_t::read(settings_t* const sets) void settings_display_stats_t::init(settings_t const* const) { INIT_INIT - INIT_NUM( "frames_per_second",env_t::fps, 10, 25, gui_numberinput_t::AUTOLINEAR, false ); + INIT_NUM( "frames_per_second",env_t::fps, env_t::min_fps, env_t::max_fps, gui_numberinput_t::AUTOLINEAR, false ); + INIT_NUM( "ff_frames_per_second", env_t::ff_fps, env_t::min_fps, env_t::max_fps, gui_numberinput_t::AUTOLINEAR, false); INIT_NUM( "simple_drawing_tile_size",env_t::simple_drawing_default, 2, 256, gui_numberinput_t::POWER2, false ); INIT_BOOL( "simple_drawing_fast_forward",env_t::simple_drawing_fast_forward ); INIT_NUM( "water_animation_ms", env_t::water_animation, 0, 1000, 25, false ); @@ -185,6 +186,7 @@ void settings_display_stats_t::read(settings_t* const) READ_INIT // all visual stuff READ_NUM_VALUE( env_t::fps ); + READ_NUM_VALUE( env_t::ff_fps ); READ_NUM_VALUE( env_t::simple_drawing_default ); READ_BOOL_VALUE( env_t::simple_drawing_fast_forward ); READ_NUM_VALUE( env_t::water_animation ); diff --git simintr.cc simintr.cc index 852c851eb..c80fc1d2c 100644 --- simintr.cc +++ simintr.cc @@ -27,7 +27,9 @@ static main_view_t *welt_ansicht = NULL; static uint32 last_time; static bool enabled = false; -#define FRAME_TIME_MULTI (16) +#define FRAME_TIME_PRECISION_BITS (4) +#define FRAME_TIME_MULTI (1 << FRAME_TIME_PRECISION_BITS) + // pause between two frames static uint32 frame_time = 36*FRAME_TIME_MULTI; @@ -35,39 +37,45 @@ static uint32 frame_time = 36*FRAME_TIME_MULTI; bool reduce_frame_time() { - if(frame_time > 10*FRAME_TIME_MULTI) { + if( frame_time > 150*FRAME_TIME_MULTI ) { // < ~6.6fps + frame_time -= 8; + return true; + } + else if(frame_time > (FRAME_TIME_MULTI*1000)/env_t::max_fps) { frame_time -= 1; - if( frame_time>150*FRAME_TIME_MULTI ) { - frame_time -= 8; - } return true; } else { - frame_time = 10*FRAME_TIME_MULTI; + frame_time = (FRAME_TIME_MULTI*1000)/env_t::max_fps; return false; } } + bool increase_frame_time() { - if(frame_time < 255*FRAME_TIME_MULTI) { + if(frame_time > (FRAME_TIME_MULTI*1000)/4) { // < 4 fps + return false; + } + else { frame_time ++; return true; - } else { - return false; } } + uint32 get_frame_time() { return frame_time/FRAME_TIME_MULTI; } + void set_frame_time(uint32 time) { - frame_time = clamp( time, 10, 250 )*FRAME_TIME_MULTI; + frame_time = clamp( time, 1000/env_t::max_fps, 1000/env_t::min_fps )*FRAME_TIME_MULTI; } + void intr_refresh_display(bool dirty) { wasser_t::prepare_for_refresh(); @@ -88,24 +96,28 @@ void intr_refresh_display(bool dirty) void interrupt_check(const char* caller_info) { DBG_DEBUG4("interrupt_check", "called from (%s)", caller_info); - if(enabled) { - static uint32 last_ms = 0; - if( !welt_modell->is_fast_forward() || welt_modell->get_ticks() != last_ms ) { - const uint32 now = dr_time(); - if((now-last_time)*FRAME_TIME_MULTI < frame_time) { - return; - } - const sint32 diff = (( (sint32)now - (sint32)last_time)*welt_modell->get_time_multiplier())/16; - if( diff>0 ) { - enabled = false; - last_time = now; - welt_modell->sync_step( diff, !welt_modell->is_fast_forward(), true ); - enabled = true; - } + (void)caller_info; + + if( !enabled ) { + return; + } + + static uint32 last_ms = 0; + if( !welt_modell->is_fast_forward() || welt_modell->get_ticks() != last_ms ) { + const uint32 now = dr_time(); + if((now-last_time)*FRAME_TIME_MULTI < frame_time) { + return; + } + + const sint32 diff = (( (sint32)now - (sint32)last_time)*welt_modell->get_time_multiplier())/16; + if( diff>0 ) { + enabled = false; + last_time = now; + welt_modell->sync_step( diff, !welt_modell->is_fast_forward(), true ); + enabled = true; } - last_ms = welt_modell->get_ticks(); } - (void)caller_info; + last_ms = welt_modell->get_ticks(); } diff --git simintr.h simintr.h index 2964aa050..22f1c4731 100644 --- simintr.h +++ simintr.h @@ -13,10 +13,14 @@ class karte_t; class main_view_t; +/// Try to increase fps bool reduce_frame_time(); + +/// Try to decrease fps bool increase_frame_time(); + uint32 get_frame_time(); -void set_frame_time(uint32 time); +void set_frame_time(uint32 ms); void intr_refresh_display(bool dirty); diff --git simmain.cc simmain.cc index efe945c0a..bbfbd4893 100644 --- simmain.cc +++ simmain.cc @@ -454,7 +454,7 @@ int simu_main(int argc, char** argv) " -easyserver set up every for server (query own IP, port forwarding)\n" " -freeplay play with endless money\n" " -fullscreen starts simutrans in fullscreen mode\n" - " -fps COUNT framerate (from 5 to 100)\n" + " -fps COUNT framerate (from %d to %d)\n" " -h | -help | --help displays this help\n" " -lang CODE starts with specified language\n" " -load NAME loads savegame with name 'NAME' from Simutrans 'save' directory\n" @@ -494,7 +494,9 @@ int simu_main(int argc, char** argv) " -times does some simple profiling\n" " -until YEAR.MONTH quits when MONTH of YEAR starts\n" #endif - " -use_workdir use current dir as basedir\n" + " -use_workdir use current dir as basedir\n", + + env_t::min_fps, env_t::max_fps ); return 0; } diff --git simutrans/config/simuconf.tab simutrans/config/simuconf.tab index c2e19ad02..4ea8c6ccb 100644 --- simutrans/config/simuconf.tab +++ simutrans/config/simuconf.tab @@ -634,6 +634,9 @@ autosave = 0 # (depends very much on computer, game complexity and graphics driver) frames_per_second = 25 +# Same as frames_per_second, but for fast forward +ff_frames_per_second = 25 + # during zooming out simutrans may get slow due to the very high number # of tiles visible. If the tiles become equal or smaller than the tile size # below, a simpler clipping algorithm will be used, which will give some diff --git simutrans/history.txt simutrans/history.txt index 2db3a5f5a..4bb206296 100644 --- simutrans/history.txt +++ simutrans/history.txt @@ -1,3 +1,5 @@ + ADD: Fast Forward fps now configurable (ff_frames_per_second in simuconf.tab) + FIX: Permanent fps drop when opening settings window with fps > 25 FIX: Rotation of multi-tile buildings at street corners ADD: different volumes for different sounds, realistic distance scaling (independent from screen size) CHG: Fade sounds with one over square root distance, and remove the dependency from display and tile size diff --git simversion.h simversion.h index c312b2f42..1b530dc21 100644 --- simversion.h +++ simversion.h @@ -24,7 +24,7 @@ // Beware: SAVEGAME minor is often ahead of version minor when there were patches. // ==> These have no direct connection at all! #define SIM_SAVE_MINOR 0 -#define SIM_SERVER_MINOR 0 +#define SIM_SERVER_MINOR 1 // NOTE: increment before next release to enable save/load of new features #define MAKEOBJ_VERSION "60.4" diff --git simworld.cc simworld.cc index b4fbf606d..13ad33734 100644 --- simworld.cc +++ simworld.cc @@ -3690,9 +3690,11 @@ void karte_t::update_frame_sleep_time() } } } - else { // here only with fyst forward ... + else { + assert(step_mode == FAST_FORWARD); + // try to get 10 fps or lower rate (if set) - uint32 frame_intervall = max( 100, 1000/env_t::fps ); + const uint32 frame_intervall = 1000/env_t::ff_fps; if(get_frame_time()>frame_intervall) { reduce_frame_time(); } @@ -6135,7 +6137,7 @@ void karte_t::reset_timer() else if(step_mode==FAST_FORWARD) { next_step_time = last_tick_sync+1; idle_time = 0; - set_frame_time( 100 ); + set_frame_time( 1000 / env_t::ff_fps ); time_multiplier = 16; intr_enable(); }