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
This commit is contained in:
hap 2025-05-30 19:18:24 +02:00
parent c908c209a6
commit 73b7cdabef
9 changed files with 56 additions and 19 deletions

View File

@ -946,7 +946,7 @@ Sets the startup volume. It can later be changed with the user interface
.\" SDL specific .\" SDL specific
.\" +++++++++++++++++++++++++++++++++++++++++++++++++++++++ .\" +++++++++++++++++++++++++++++++++++++++++++++++++++++++
.TP .TP
.B \-audio_latency \fIvalue .B \-audio_latency, \-alat \fIvalue
This controls the amount of latency in seconds built into the audio streaming. This controls the amount of latency in seconds built into the audio streaming.
Smaller values provide less audio delay while requiring better system Smaller values provide less audio delay while requiring better system
performance. Higher values increase audio delay but may help avoid performance. Higher values increase audio delay but may help avoid

View File

@ -1936,8 +1936,10 @@ Core Performance Options
run the system at its normal speed, a *<factor>* of ``0.5`` means run at run the system at its normal speed, a *<factor>* of ``0.5`` means run at
half speed, and a *<factor>* of 2.0 means run at double speed. Note that half speed, and a *<factor>* of 2.0 means run at double speed. Note that
changing this value affects sound playback as well, which will scale in changing this value affects sound playback as well, which will scale in
pitch accordingly. The internal precision of the fraction is two decimal pitch accordingly. A very low speed will introduce sound glitches, this
places, so a *<factor>* of ``1.002`` is rounded to ``1.00``. can be prevented by increasing **-audio_latency**. The internal precision
of the fraction is two decimal places, so a *<factor>* of ``1.002`` is
rounded to ``1.00``.
The default is ``1.0`` (normal speed). The default is ``1.0`` (normal speed).
@ -3062,7 +3064,7 @@ Core Sound Options
.. _mame-commandline-audiolatency: .. _mame-commandline-audiolatency:
**-audio_latency** *<value>* **-audio_latency** *<value>* / **-alat** *<value>*
Audio latency in seconds, up to a maximum of 0.5 seconds. Smaller values Audio latency in seconds, up to a maximum of 0.5 seconds. Smaller values
provide less audio delay while requiring better system performance. Larger 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 Activates the cheat menu with autofire options and other tricks from the
cheat database, if present. This also activates additional options on 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 *Be advised that savestates created with cheats on may not work correctly
with this turned off and vice-versa.* with this turned off and vice-versa.*

View File

@ -113,43 +113,51 @@ attotime &attotime::operator/=(u32 factor)
const char *attotime::as_string(int precision) const const char *attotime::as_string(int precision) const
{ {
static char buffers[8][30]; static char buffers[8][32];
static int nextbuf; static int nextbuf;
char *buffer = &buffers[nextbuf++ % 8][0]; char *buffer = &buffers[nextbuf++ % 8][0];
attotime t = *this;
const char *sign = "";
if (t < attotime::zero)
{
t = attotime::zero - t;
sign = "-";
}
// special case: never // special case: never
if (*this == never) if (*this == never)
snprintf(buffer, 30, "%-*s", precision, "(never)"); snprintf(buffer, 32, "%-*s", precision, "(never)");
// case 1: we want no precision; seconds only // case 1: we want no precision; seconds only
else if (precision == 0) 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 // case 2: we want 9 or fewer digits of precision
else if (precision <= 9) else if (precision <= 9)
{ {
u32 upper = m_attoseconds / ATTOSECONDS_PER_SECOND_SQRT; u32 upper = t.attoseconds() / ATTOSECONDS_PER_SECOND_SQRT;
int temp = precision; int temp = precision;
while (temp < 9) while (temp < 9)
{ {
upper /= 10; upper /= 10;
temp++; 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 // case 3: more than 9 digits of precision
else else
{ {
u32 lower; 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; int temp = precision;
while (temp < 18) while (temp < 18)
{ {
lower /= 10; lower /= 10;
temp++; 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; return buffer;
} }
@ -163,10 +171,11 @@ std::string attotime::to_string() const
{ {
attotime t = *this; attotime t = *this;
const char *sign = ""; const char *sign = "";
if(t.seconds() < 0) { if (t < attotime::zero)
t = attotime::zero-t; {
t = attotime::zero - t;
sign = "-"; sign = "-";
} }
int nsec = t.attoseconds() / ATTOSECONDS_PER_NANOSECOND; 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);
} }

View File

@ -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_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_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_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_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" }, { OPTION_LOWLATENCY ";lolat", "0", core_options::option_type::BOOLEAN, "draws new frame before throttling to reduce input latency" },

View File

@ -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 // between 0 and 1/10th of a second ... anything outside of this range is obviously
// wrong and requires a resync // wrong and requires a resync
attoseconds_t emu_delta_attoseconds = (emutime - m_throttle_emutime).as_attoseconds(); 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) if (LOG_THROTTLE)
machine().logerror("Resync due to weird emutime delta: %s\n", attotime(0, emu_delta_attoseconds).as_string(18)); machine().logerror("Resync due to weird emutime delta: %s\n", attotime(0, emu_delta_attoseconds).as_string(18));

View File

@ -60,6 +60,7 @@ public:
void set_throttle_rate(float throttle_rate) { m_throttle_rate = throttle_rate; } void set_throttle_rate(float throttle_rate) { m_throttle_rate = throttle_rate; }
void set_fastforward(bool ffwd) { m_fastforward = ffwd; } void set_fastforward(bool ffwd) { m_fastforward = ffwd; }
void set_output_changed() { m_output_changed = true; } void set_output_changed() { m_output_changed = true; }
void set_speed_factor(int speed) { m_speed = speed; }
// misc // misc
void toggle_record_movie(movie_recording::format format); void toggle_record_movie(movie_recording::format format);

View File

@ -1888,9 +1888,11 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine
} }
} }
// add CPU overclocking (cheat only) // add speed and CPU overclocking (cheat only)
if (machine.options().cheat()) 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())) for (device_execute_interface &exec : execute_interface_enumerator(machine.root_device()))
{ {
std::string str = string_format(_("Overclock CPU %1$s"), exec.device().tag()); 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 // slider_overclock - CPU overclocker slider
// callback // callback

View File

@ -350,6 +350,7 @@ private:
int32_t slider_devvol(device_sound_interface *snd, std::string *str, int32_t newval); 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_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_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_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_refresh(screen_device &screen, std::string *str, int32_t newval);
int32_t slider_brightness(screen_device &screen, std::string *str, int32_t newval); int32_t slider_brightness(screen_device &screen, std::string *str, int32_t newval);

View File

@ -144,7 +144,7 @@ const options_entry osd_options::s_option_entries[] =
{ nullptr, nullptr, core_options::option_type::HEADER, "OSD SOUND OPTIONS" }, { nullptr, nullptr, core_options::option_type::HEADER, "OSD SOUND OPTIONS" },
{ OSDOPTION_SOUND, OSDOPTVAL_AUTO, core_options::option_type::STRING, "sound output method: " }, { 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 #ifdef SDLMAME_MACOSX
{ nullptr, nullptr, core_options::option_type::HEADER, "CoreAudio-SPECIFIC OPTIONS" }, { nullptr, nullptr, core_options::option_type::HEADER, "CoreAudio-SPECIFIC OPTIONS" },