From 73b7cdabef578c6fa28e7f44204e16e69ecac9fb Mon Sep 17 00:00:00 2001 From: hap Date: Fri, 30 May 2025 19:18:24 +0200 Subject: [PATCH] attotime: fix lockup with as_string and negative attotime, video: fix issue with throttling when mame runs at slow motion (-speed lower than 0.2) options: change mimimum speed setting from 0.01 to 0.1 (mame would crash with very low value, and besides, video throttle still fails below 0.1), ui: add speed slider when cheats are enabled --- docs/man/mame.6 | 2 +- docs/source/commandline/commandline-all.rst | 10 ++++--- src/emu/attotime.cpp | 29 ++++++++++++++------- src/emu/emuopts.cpp | 2 +- src/emu/video.cpp | 2 +- src/emu/video.h | 1 + src/frontend/mame/ui/ui.cpp | 26 +++++++++++++++++- src/frontend/mame/ui/ui.h | 1 + src/osd/modules/lib/osdobj_common.cpp | 2 +- 9 files changed, 56 insertions(+), 19 deletions(-) diff --git a/docs/man/mame.6 b/docs/man/mame.6 index 05316275026..e45985a3011 100644 --- a/docs/man/mame.6 +++ b/docs/man/mame.6 @@ -946,7 +946,7 @@ Sets the startup volume. It can later be changed with the user interface .\" SDL specific .\" +++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TP -.B \-audio_latency \fIvalue +.B \-audio_latency, \-alat \fIvalue This controls the amount of latency in seconds built into the audio streaming. Smaller values provide less audio delay while requiring better system performance. Higher values increase audio delay but may help avoid diff --git a/docs/source/commandline/commandline-all.rst b/docs/source/commandline/commandline-all.rst index bc4fe1c1042..e9a0d79b2df 100644 --- a/docs/source/commandline/commandline-all.rst +++ b/docs/source/commandline/commandline-all.rst @@ -1936,8 +1936,10 @@ Core Performance Options run the system at its normal speed, a ** of ``0.5`` means run at half speed, and a ** of 2.0 means run at double speed. Note that changing this value affects sound playback as well, which will scale in - pitch accordingly. The internal precision of the fraction is two decimal - places, so a ** of ``1.002`` is rounded to ``1.00``. + pitch accordingly. A very low speed will introduce sound glitches, this + can be prevented by increasing **-audio_latency**. The internal precision + of the fraction is two decimal places, so a ** of ``1.002`` is + rounded to ``1.00``. The default is ``1.0`` (normal speed). @@ -3062,7 +3064,7 @@ Core Sound Options .. _mame-commandline-audiolatency: -**-audio_latency** ** +**-audio_latency** ** / **-alat** ** Audio latency in seconds, up to a maximum of 0.5 seconds. Smaller values provide less audio delay while requiring better system performance. Larger @@ -3973,7 +3975,7 @@ Core Misc Options Activates the cheat menu with autofire options and other tricks from the cheat database, if present. This also activates additional options on the - slider menu for overclocking/underclocking. + slider menu for overall speed and overclocking/underclocking. *Be advised that savestates created with cheats on may not work correctly with this turned off and vice-versa.* diff --git a/src/emu/attotime.cpp b/src/emu/attotime.cpp index 030c3193551..87e1ebe0136 100644 --- a/src/emu/attotime.cpp +++ b/src/emu/attotime.cpp @@ -113,43 +113,51 @@ attotime &attotime::operator/=(u32 factor) const char *attotime::as_string(int precision) const { - static char buffers[8][30]; + static char buffers[8][32]; static int nextbuf; char *buffer = &buffers[nextbuf++ % 8][0]; + attotime t = *this; + const char *sign = ""; + if (t < attotime::zero) + { + t = attotime::zero - t; + sign = "-"; + } + // special case: never if (*this == never) - snprintf(buffer, 30, "%-*s", precision, "(never)"); + snprintf(buffer, 32, "%-*s", precision, "(never)"); // case 1: we want no precision; seconds only else if (precision == 0) - snprintf(buffer, 30, "%d", m_seconds); + snprintf(buffer, 32, "%s%d", sign, t.seconds()); // case 2: we want 9 or fewer digits of precision else if (precision <= 9) { - u32 upper = m_attoseconds / ATTOSECONDS_PER_SECOND_SQRT; + u32 upper = t.attoseconds() / ATTOSECONDS_PER_SECOND_SQRT; int temp = precision; while (temp < 9) { upper /= 10; temp++; } - snprintf(buffer, 30, "%d.%0*d", m_seconds, precision, upper); + snprintf(buffer, 32, "%s%d.%0*d", sign, t.seconds(), precision, upper); } // case 3: more than 9 digits of precision else { u32 lower; - u32 upper = divu_64x32_rem(m_attoseconds, ATTOSECONDS_PER_SECOND_SQRT, lower); + u32 upper = divu_64x32_rem(t.attoseconds(), ATTOSECONDS_PER_SECOND_SQRT, lower); int temp = precision; while (temp < 18) { lower /= 10; temp++; } - snprintf(buffer, 30, "%d.%09d%0*d", m_seconds, upper, precision - 9, lower); + snprintf(buffer, 32, "%s%d.%09d%0*d", sign, t.seconds(), upper, precision - 9, lower); } return buffer; } @@ -163,10 +171,11 @@ std::string attotime::to_string() const { attotime t = *this; const char *sign = ""; - if(t.seconds() < 0) { - t = attotime::zero-t; + if (t < attotime::zero) + { + t = attotime::zero - t; sign = "-"; } int nsec = t.attoseconds() / ATTOSECONDS_PER_NANOSECOND; - return util::string_format("%s%04d.%03d,%03d,%03d", sign, int(t.seconds()), nsec/1000000, (nsec/1000)%1000, nsec % 1000); + return util::string_format("%s%04d.%03d,%03d,%03d", sign, int(t.seconds()), nsec / 1000000, (nsec / 1000) % 1000, nsec % 1000); } diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp index 29c19283406..834710c9eb0 100644 --- a/src/emu/emuopts.cpp +++ b/src/emu/emuopts.cpp @@ -92,7 +92,7 @@ const options_entry emu_options::s_option_entries[] = { OPTION_SECONDS_TO_RUN ";str", "0", core_options::option_type::INTEGER, "number of emulated seconds to run before automatically exiting" }, { OPTION_THROTTLE, "1", core_options::option_type::BOOLEAN, "throttle emulation to keep system running in sync with real time" }, { OPTION_SLEEP, "1", core_options::option_type::BOOLEAN, "enable sleeping, which gives time back to other applications when idle" }, - { OPTION_SPEED "(0.01-100)", "1.0", core_options::option_type::FLOAT, "controls the speed of gameplay, relative to realtime; smaller numbers are slower" }, + { OPTION_SPEED "(0.1-100)", "1.0", core_options::option_type::FLOAT, "controls the speed of gameplay, relative to realtime; smaller numbers are slower" }, { OPTION_REFRESHSPEED ";rs", "0", core_options::option_type::BOOLEAN, "automatically adjust emulation speed to keep the emulated refresh rate slower than the host screen" }, { OPTION_LOWLATENCY ";lolat", "0", core_options::option_type::BOOLEAN, "draws new frame before throttling to reduce input latency" }, diff --git a/src/emu/video.cpp b/src/emu/video.cpp index 06a16b76cda..75ba128df91 100644 --- a/src/emu/video.cpp +++ b/src/emu/video.cpp @@ -727,7 +727,7 @@ void video_manager::update_throttle(attotime emutime) // between 0 and 1/10th of a second ... anything outside of this range is obviously // wrong and requires a resync attoseconds_t emu_delta_attoseconds = (emutime - m_throttle_emutime).as_attoseconds(); - if (emu_delta_attoseconds < 0 || emu_delta_attoseconds > ATTOSECONDS_PER_SECOND / 10) + if (emu_delta_attoseconds < 0 || emu_delta_attoseconds >= (ATTOSECONDS_PER_SECOND / (m_speed ? m_speed : 1000)) * 100) { if (LOG_THROTTLE) machine().logerror("Resync due to weird emutime delta: %s\n", attotime(0, emu_delta_attoseconds).as_string(18)); diff --git a/src/emu/video.h b/src/emu/video.h index efc819ae793..6517c90d170 100644 --- a/src/emu/video.h +++ b/src/emu/video.h @@ -60,6 +60,7 @@ public: void set_throttle_rate(float throttle_rate) { m_throttle_rate = throttle_rate; } void set_fastforward(bool ffwd) { m_fastforward = ffwd; } void set_output_changed() { m_output_changed = true; } + void set_speed_factor(int speed) { m_speed = speed; } // misc void toggle_record_movie(movie_recording::format format); diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 251ce604efa..d706e6922a6 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -1888,9 +1888,11 @@ std::vector mame_ui_manager::slider_init(running_machine &machine } } - // add CPU overclocking (cheat only) + // add speed and CPU overclocking (cheat only) if (machine.options().cheat()) { + slider_alloc(_("Speed Factor"), 100, 1000, 10000, 10, std::bind(&mame_ui_manager::slider_speed, this, _1, _2)); + for (device_execute_interface &exec : execute_interface_enumerator(machine.root_device())) { std::string str = string_format(_("Overclock CPU %1$s"), exec.device().tag()); @@ -2105,6 +2107,28 @@ int32_t mame_ui_manager::slider_adjuster(ioport_field &field, std::string *str, } +//------------------------------------------------- +// slider_speed - speed factor slider callback +//------------------------------------------------- + +int32_t mame_ui_manager::slider_speed(std::string *str, int32_t newval) +{ + if (newval != SLIDER_NOCHANGE) + machine().video().set_speed_factor(newval); + + int32_t curval = machine().video().speed_factor(); + if (str) + { + if (curval % 10) + *str = string_format(_("%1$.1f%%"), float(curval) * 0.1f); + else + *str = string_format(_("%1$3d%%"), curval / 10); + } + + return curval; +} + + //------------------------------------------------- // slider_overclock - CPU overclocker slider // callback diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index ed5fa97156d..f64f43f0df3 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -350,6 +350,7 @@ private: int32_t slider_devvol(device_sound_interface *snd, std::string *str, int32_t newval); int32_t slider_devvol_chan(device_sound_interface *snd, int channel, std::string *str, int32_t newval); int32_t slider_adjuster(ioport_field &field, std::string *str, int32_t newval); + int32_t slider_speed(std::string *str, int32_t newval); int32_t slider_overclock(device_t &device, std::string *str, int32_t newval); int32_t slider_refresh(screen_device &screen, std::string *str, int32_t newval); int32_t slider_brightness(screen_device &screen, std::string *str, int32_t newval); diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index 83a571da8cc..192b8a7d131 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -144,7 +144,7 @@ const options_entry osd_options::s_option_entries[] = { nullptr, nullptr, core_options::option_type::HEADER, "OSD SOUND OPTIONS" }, { OSDOPTION_SOUND, OSDOPTVAL_AUTO, core_options::option_type::STRING, "sound output method: " }, - { OSDOPTION_AUDIO_LATENCY "(0.0-0.5)", "0.0", core_options::option_type::FLOAT, "audio latency in seconds, 0.0 for default (increase to reduce glitches, decrease for responsiveness)" }, + { OSDOPTION_AUDIO_LATENCY ";alat(0.0-0.5)", "0.0", core_options::option_type::FLOAT, "audio latency in seconds, 0.0 for default (increase to reduce glitches, decrease for responsiveness)" }, #ifdef SDLMAME_MACOSX { nullptr, nullptr, core_options::option_type::HEADER, "CoreAudio-SPECIFIC OPTIONS" },