diff --git a/apple2e.cpp b/apple2e.cpp index 5b197fd..7d175f1 100644 --- a/apple2e.cpp +++ b/apple2e.cpp @@ -41,6 +41,9 @@ volatile bool exit_on_memory_fallthrough = true; volatile bool run_fast = false; volatile bool pause_cpu = false; +bool run_rate_limited = false; +int rate_limit_millis; + // XXX - this should be handled through a function passed to MAINboard APPLE2Einterface::ModeHistory mode_history; @@ -3053,8 +3056,14 @@ enum APPLE2Einterface::EventType process_events(MAINboard *board, bus_frontend& pause_cpu = e.value; } else if(e.type == APPLE2Einterface::SPEED) { run_fast = e.value; - } else if(e.type == APPLE2Einterface::QUIT) - return e.type; + } else if(e.type == APPLE2Einterface::QUIT) { + return e.type; + } else if(e.type == APPLE2Einterface::REQUEST_ITERATION_PERIOD_IN_MILLIS) { + run_rate_limited = true; + rate_limit_millis = e.value; + } else if(e.type == APPLE2Einterface::WITHDRAW_ITERATION_PERIOD_REQUEST) { + run_rate_limited = false; + } } return APPLE2Einterface::NONE; } @@ -3215,10 +3224,13 @@ int main(int argc, char **argv) if(pause_cpu) clocks_per_slice = 0; else { - if(run_fast) + if(run_rate_limited) { + clocks_per_slice = machine_clock_rate / 1000 * rate_limit_millis; + } else if(run_fast) { clocks_per_slice = machine_clock_rate / 5; - else + } else { clocks_per_slice = millis_per_slice * machine_clock_rate / 1000 * 1.05; + } } clk_t prev_clock = clk; while(clk - prev_clock < clocks_per_slice) { @@ -3243,7 +3255,7 @@ int main(int argc, char **argv) auto elapsed_millis = chrono::duration_cast(now - then); if(!run_fast || pause_cpu) - this_thread::sleep_for(chrono::milliseconds(millis_per_slice) - elapsed_millis); + this_thread::sleep_for(chrono::milliseconds(clocks_per_slice * 1000 / machine_clock_rate) - elapsed_millis); then = now; diff --git a/interface.cpp b/interface.cpp index 2950fff..aad0d50 100644 --- a/interface.cpp +++ b/interface.cpp @@ -179,6 +179,7 @@ render_target::render_target(int w, int h) const int apple2_screen_width = 280; const int apple2_screen_height = 192; const int recording_scale = 2; +const int recording_frame_duration_hundredths = 5; chrono::time_point start_time; @@ -1753,6 +1754,7 @@ static void stop_record() if (gif_recording) { GifEnd(&gif_writer); gif_recording = false; + event_queue.push_back({WITHDRAW_ITERATION_PERIOD_REQUEST, 0}); } } @@ -1769,7 +1771,8 @@ static void start_record() rendertarget_for_recording = new render_target(apple2_screen_width * recording_scale, apple2_screen_height * recording_scale); } - GifBegin(&gif_writer, "out.gif", apple2_screen_width * recording_scale, apple2_screen_height * recording_scale, 5); + GifBegin(&gif_writer, "out.gif", apple2_screen_width * recording_scale, apple2_screen_height * recording_scale, recording_frame_duration_hundredths); + event_queue.push_back({REQUEST_ITERATION_PERIOD_IN_MILLIS, recording_frame_duration_hundredths * 10}); gif_recording = true; } @@ -1886,7 +1889,7 @@ void add_rendertarget_to_gif(double now, render_target *rt) save_rgba_to_ppm(image_recorded, apple2_screen_width * recording_scale, apple2_screen_height * recording_scale, "screen.ppm"); } - GifWriteFrame(&gif_writer, image_recorded, apple2_screen_width * recording_scale, apple2_screen_height * recording_scale, 5, 8, true); + GifWriteFrame(&gif_writer, image_recorded, apple2_screen_width * recording_scale, apple2_screen_height * recording_scale, recording_frame_duration_hundredths, 8, true); rt->stop_reading(); } diff --git a/interface.h b/interface.h index 68fbf3b..bd5b9d2 100644 --- a/interface.h +++ b/interface.h @@ -3,7 +3,13 @@ namespace APPLE2Einterface { -enum EventType {NONE, KEYDOWN, KEYUP, RESET, REBOOT, PASTE, SPEED, QUIT, PAUSE, EJECT_FLOPPY, INSERT_FLOPPY}; + +enum EventType +{ + NONE, KEYDOWN, KEYUP, RESET, REBOOT, PASTE, SPEED, QUIT, PAUSE, EJECT_FLOPPY, INSERT_FLOPPY, + REQUEST_ITERATION_PERIOD_IN_MILLIS, /* request fixed simulation time period between calls to iterate() */ + WITHDRAW_ITERATION_PERIOD_REQUEST, /* withdraw request for fixed simulation time */ +}; const int LEFT_SHIFT = 340; const int LEFT_CONTROL = 341;