mirror of
https://github.com/holub/mame
synced 2025-05-18 03:35:03 +03:00

related APIs now take a device pointer instead of an index. All functions that take a CPU device are prefixed with cpu_* All functions that are globally related to cpu execution are prefixed with cpuexec_*. Below is a list of some of the mappings: cpu_boost_interleave -> cpuexec_boost_interleave cpunum_suspend -> cpu_suspend cpunum_resume -> cpu_resume cpunum_is_suspended -> cpu_is_suspended cpunum_get_clock -> cpu_get_clock cpunum_set_clock -> cpu_set_clock cpunum_get_clockscale -> cpu_get_clockscale cpunum_set_clockscale -> cpu_set_clockscale cpunum_get_localtime -> cpu_get_local_time cpunum_gettotalcycles -> cpu_get_total_cycles activecpu_eat_cycles -> cpu_eat_cycles activecpu_adjust_icount -> cpu_adjust_icount cpu_trigger -> cpuexec_trigger cpu_triggertime -> cpuexec_triggertime cpunum_set_input_line -> cpu_set_input_line cpunum_set_irq_callback -> cpu_set_irq_callback In addition, a number of functions retain the same name but now require a specific CPU parameter to be passed in: cpu_yield cpu_spin cpu_spinuntil_time cpu_spinuntil_int cpu_spinuntil_trigger cpu_triggerint Merged cpuint.c into cpuexec.c. One side-effect of this change is that driver reset callbacks are called AFTER the CPUs and devices are reset. This means that if you make changes to the CPU state and expect the reset vectors to recognize the changes in your reset routine, you will need to manually reset the CPU after making the change (since it has already been reset). Added a number of inline helper functions to cpuintrf.h for managing addresses Removed cpu_gettotalcpu(). This information is rarely needed outside of the core and can be obtained by looking at the machine->cpu[] array. Changed CPU interrupt acknowledge callbacks to pass a CPU device instead of machine/cpunum pair. Changed VBLANK and periodic timer callbacks to pass a CPU device instead of machine/cpunum pair. Renamed all information getters from cpu_* to cpu_get_* and from cputype_* to cputype_get_*.
2018 lines
63 KiB
C
2018 lines
63 KiB
C
/*********************************************************************
|
|
|
|
ui.c
|
|
|
|
Functions used to handle MAME's user interface.
|
|
|
|
Copyright Nicola Salmoria and the MAME Team.
|
|
Visit http://mamedev.org for licensing and usage restrictions.
|
|
|
|
*********************************************************************/
|
|
|
|
#include "driver.h"
|
|
#include "osdepend.h"
|
|
#include "video/vector.h"
|
|
#include "machine/laserdsc.h"
|
|
#include "profiler.h"
|
|
#include "cheat.h"
|
|
#include "render.h"
|
|
#include "rendfont.h"
|
|
#include "ui.h"
|
|
#include "uiinput.h"
|
|
#include "uimenu.h"
|
|
#include "uigfx.h"
|
|
|
|
#ifdef MESS
|
|
#include "mess.h"
|
|
#include "uimess.h"
|
|
#include "inputx.h"
|
|
#endif /* MESS */
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
CONSTANTS
|
|
***************************************************************************/
|
|
|
|
enum
|
|
{
|
|
INPUT_TYPE_DIGITAL = 0,
|
|
INPUT_TYPE_ANALOG = 1,
|
|
INPUT_TYPE_ANALOG_DEC = 2,
|
|
INPUT_TYPE_ANALOG_INC = 3
|
|
};
|
|
|
|
enum
|
|
{
|
|
ANALOG_ITEM_KEYSPEED = 0,
|
|
ANALOG_ITEM_CENTERSPEED,
|
|
ANALOG_ITEM_REVERSE,
|
|
ANALOG_ITEM_SENSITIVITY,
|
|
ANALOG_ITEM_COUNT
|
|
};
|
|
|
|
enum
|
|
{
|
|
LOADSAVE_NONE,
|
|
LOADSAVE_LOAD,
|
|
LOADSAVE_SAVE
|
|
};
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
GLOBAL VARIABLES
|
|
***************************************************************************/
|
|
|
|
/* font for rendering */
|
|
static render_font *ui_font;
|
|
|
|
/* current UI handler */
|
|
static UINT32 (*ui_handler_callback)(running_machine *, UINT32);
|
|
static UINT32 ui_handler_param;
|
|
|
|
/* flag to track single stepping */
|
|
static int single_step;
|
|
|
|
/* FPS counter display */
|
|
static int showfps;
|
|
static osd_ticks_t showfps_end;
|
|
|
|
/* profiler display */
|
|
static int show_profiler;
|
|
|
|
/* popup text display */
|
|
static osd_ticks_t popup_text_end;
|
|
|
|
/* messagebox buffer */
|
|
static astring *messagebox_text;
|
|
static rgb_t messagebox_backcolor;
|
|
|
|
/* slider info */
|
|
static slider_state *slider_list;
|
|
static slider_state *slider_current;
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
FUNCTION PROTOTYPES
|
|
***************************************************************************/
|
|
|
|
static void ui_exit(running_machine *machine);
|
|
|
|
/* text generators */
|
|
static astring *disclaimer_string(running_machine *machine, astring *buffer);
|
|
static astring *warnings_string(running_machine *machine, astring *buffer);
|
|
|
|
/* UI handlers */
|
|
static UINT32 handler_messagebox(running_machine *machine, UINT32 state);
|
|
static UINT32 handler_messagebox_ok(running_machine *machine, UINT32 state);
|
|
static UINT32 handler_messagebox_anykey(running_machine *machine, UINT32 state);
|
|
static UINT32 handler_ingame(running_machine *machine, UINT32 state);
|
|
static UINT32 handler_load_save(running_machine *machine, UINT32 state);
|
|
|
|
/* slider controls */
|
|
static slider_state *slider_alloc(const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg);
|
|
static slider_state *slider_init(running_machine *machine);
|
|
static INT32 slider_volume(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_mixervol(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_adjuster(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_overclock(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_refresh(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_brightness(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_contrast(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_gamma(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_xscale(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_yscale(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_xoffset(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_yoffset(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_overxscale(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_overyscale(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_overxoffset(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_overyoffset(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_flicker(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_beam(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static char *slider_get_screen_desc(const device_config *screen);
|
|
static char *slider_get_laserdisc_desc(const device_config *screen);
|
|
#ifdef MAME_DEBUG
|
|
static INT32 slider_crossscale(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
static INT32 slider_crossoffset(running_machine *machine, void *arg, astring *string, INT32 newval);
|
|
#endif
|
|
|
|
|
|
/***************************************************************************
|
|
INLINE FUNCTIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
ui_set_handler - set a callback/parameter
|
|
pair for the current UI handler
|
|
-------------------------------------------------*/
|
|
|
|
INLINE UINT32 ui_set_handler(UINT32 (*callback)(running_machine *, UINT32), UINT32 param)
|
|
{
|
|
ui_handler_callback = callback;
|
|
ui_handler_param = param;
|
|
return param;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
is_breakable_char - is a given unicode
|
|
character a possible line break?
|
|
-------------------------------------------------*/
|
|
|
|
INLINE int is_breakable_char(unicode_char ch)
|
|
{
|
|
/* regular spaces and hyphens are breakable */
|
|
if (ch == ' ' || ch == '-')
|
|
return TRUE;
|
|
|
|
/* In the following character sets, any character is breakable:
|
|
Hiragana (3040-309F)
|
|
Katakana (30A0-30FF)
|
|
Bopomofo (3100-312F)
|
|
Hangul Compatibility Jamo (3130-318F)
|
|
Kanbun (3190-319F)
|
|
Bopomofo Extended (31A0-31BF)
|
|
CJK Strokes (31C0-31EF)
|
|
Katakana Phonetic Extensions (31F0-31FF)
|
|
Enclosed CJK Letters and Months (3200-32FF)
|
|
CJK Compatibility (3300-33FF)
|
|
CJK Unified Ideographs Extension A (3400-4DBF)
|
|
Yijing Hexagram Symbols (4DC0-4DFF)
|
|
CJK Unified Ideographs (4E00-9FFF) */
|
|
if (ch >= 0x3040 && ch <= 0x9fff)
|
|
return TRUE;
|
|
|
|
/* Hangul Syllables (AC00-D7AF) are breakable */
|
|
if (ch >= 0xac00 && ch <= 0xd7af)
|
|
return TRUE;
|
|
|
|
/* CJK Compatibility Ideographs (F900-FAFF) are breakable */
|
|
if (ch >= 0xf900 && ch <= 0xfaff)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
CORE IMPLEMENTATION
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
ui_init - set up the user interface
|
|
-------------------------------------------------*/
|
|
|
|
int ui_init(running_machine *machine)
|
|
{
|
|
/* make sure we clean up after ourselves */
|
|
add_exit_callback(machine, ui_exit);
|
|
|
|
/* allocate the font and messagebox string */
|
|
ui_font = render_font_alloc("ui.bdf");
|
|
messagebox_text = astring_alloc();
|
|
|
|
/* initialize the other UI bits */
|
|
ui_menu_init(machine);
|
|
ui_gfx_init(machine);
|
|
|
|
/* reset globals */
|
|
single_step = FALSE;
|
|
ui_set_handler(handler_messagebox, 0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_exit - clean up ourselves on exit
|
|
-------------------------------------------------*/
|
|
|
|
static void ui_exit(running_machine *machine)
|
|
{
|
|
/* free the font */
|
|
if (ui_font != NULL)
|
|
render_font_free(ui_font);
|
|
ui_font = NULL;
|
|
|
|
/* free the messagebox string */
|
|
if (messagebox_text != NULL)
|
|
astring_free(messagebox_text);
|
|
messagebox_text = NULL;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_display_startup_screens - display the
|
|
various startup screens
|
|
-------------------------------------------------*/
|
|
|
|
int ui_display_startup_screens(running_machine *machine, int first_time, int show_disclaimer)
|
|
{
|
|
#ifdef MESS
|
|
const int maxstate = 4;
|
|
#else
|
|
const int maxstate = 3;
|
|
#endif
|
|
int str = options_get_int(mame_options(), OPTION_SECONDS_TO_RUN);
|
|
int show_gameinfo = !options_get_bool(mame_options(), OPTION_SKIP_GAMEINFO);
|
|
int show_warnings = TRUE;
|
|
int state;
|
|
|
|
/* disable everything if we are using -str for 300 or fewer seconds, or if we're the empty driver,
|
|
or if we are debugging */
|
|
if (!first_time || (str > 0 && str < 60*5) || machine->gamedrv == &driver_empty || (machine->debug_flags & DEBUG_FLAG_ENABLED) != 0)
|
|
show_gameinfo = show_warnings = show_disclaimer = FALSE;
|
|
|
|
/* initialize the on-screen display system */
|
|
slider_list = slider_current = slider_init(machine);
|
|
|
|
/* loop over states */
|
|
ui_set_handler(handler_ingame, 0);
|
|
for (state = 0; state < maxstate && !mame_is_scheduled_event_pending(machine) && !ui_menu_is_force_game_select(); state++)
|
|
{
|
|
/* default to standard colors */
|
|
messagebox_backcolor = UI_FILLCOLOR;
|
|
|
|
/* pick the next state */
|
|
switch (state)
|
|
{
|
|
case 0:
|
|
if (show_disclaimer && astring_len(disclaimer_string(machine, messagebox_text)) > 0)
|
|
ui_set_handler(handler_messagebox_ok, 0);
|
|
break;
|
|
|
|
case 1:
|
|
if (show_warnings && astring_len(warnings_string(machine, messagebox_text)) > 0)
|
|
{
|
|
ui_set_handler(handler_messagebox_ok, 0);
|
|
if (machine->gamedrv->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION))
|
|
messagebox_backcolor = UI_REDCOLOR;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
if (show_gameinfo && astring_len(game_info_astring(machine, messagebox_text)) > 0)
|
|
ui_set_handler(handler_messagebox_anykey, 0);
|
|
break;
|
|
#ifdef MESS
|
|
case 3:
|
|
break;
|
|
#endif
|
|
}
|
|
|
|
/* clear the input memory */
|
|
input_code_poll_switches(TRUE);
|
|
while (input_code_poll_switches(FALSE) != INPUT_CODE_INVALID) ;
|
|
|
|
/* loop while we have a handler */
|
|
while (ui_handler_callback != handler_ingame && !mame_is_scheduled_event_pending(machine) && !ui_menu_is_force_game_select())
|
|
video_frame_update(machine, FALSE);
|
|
|
|
/* clear the handler and force an update */
|
|
ui_set_handler(handler_ingame, 0);
|
|
video_frame_update(machine, FALSE);
|
|
}
|
|
|
|
/* if we're the empty driver, force the menus on */
|
|
if (ui_menu_is_force_game_select())
|
|
ui_set_handler(ui_menu_ui_handler, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_set_startup_text - set the text to display
|
|
at startup
|
|
-------------------------------------------------*/
|
|
|
|
void ui_set_startup_text(running_machine *machine, const char *text, int force)
|
|
{
|
|
static osd_ticks_t lastupdatetime = 0;
|
|
osd_ticks_t curtime = osd_ticks();
|
|
|
|
/* copy in the new text */
|
|
astring_cpyc(messagebox_text, text);
|
|
messagebox_backcolor = UI_FILLCOLOR;
|
|
|
|
/* don't update more than 4 times/second */
|
|
if (force || (curtime - lastupdatetime) > osd_ticks_per_second() / 4)
|
|
{
|
|
lastupdatetime = curtime;
|
|
video_frame_update(machine, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_update_and_render - update the UI and
|
|
render it; called by video.c
|
|
-------------------------------------------------*/
|
|
|
|
void ui_update_and_render(running_machine *machine)
|
|
{
|
|
/* always start clean */
|
|
render_container_empty(render_container_get_ui());
|
|
|
|
/* if we're paused, dim the whole screen */
|
|
if (mame_get_phase(machine) >= MAME_PHASE_RESET && (single_step || mame_is_paused(machine)))
|
|
{
|
|
int alpha = (1.0f - options_get_float(mame_options(), OPTION_PAUSE_BRIGHTNESS)) * 255.0f;
|
|
if (ui_menu_is_force_game_select())
|
|
alpha = 255;
|
|
if (alpha > 255)
|
|
alpha = 255;
|
|
if (alpha >= 0)
|
|
render_ui_add_rect(0.0f, 0.0f, 1.0f, 1.0f, MAKE_ARGB(alpha,0x00,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
|
}
|
|
|
|
/* render any cheat stuff at the bottom */
|
|
cheat_render_text(machine);
|
|
|
|
/* call the current UI handler */
|
|
assert(ui_handler_callback != NULL);
|
|
ui_handler_param = (*ui_handler_callback)(machine, ui_handler_param);
|
|
|
|
/* display any popup messages */
|
|
if (osd_ticks() < popup_text_end)
|
|
ui_draw_text_box(astring_c(messagebox_text), JUSTIFY_CENTER, 0.5f, 0.9f, messagebox_backcolor);
|
|
else
|
|
popup_text_end = 0;
|
|
|
|
/* cancel takes us back to the ingame handler */
|
|
if (ui_handler_param == UI_HANDLER_CANCEL)
|
|
ui_set_handler(handler_ingame, 0);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_get_font - return the UI font
|
|
-------------------------------------------------*/
|
|
|
|
render_font *ui_get_font(void)
|
|
{
|
|
return ui_font;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_get_line_height - return the current height
|
|
of a line
|
|
-------------------------------------------------*/
|
|
|
|
float ui_get_line_height(void)
|
|
{
|
|
INT32 raw_font_pixel_height = render_font_get_pixel_height(ui_font);
|
|
INT32 target_pixel_width, target_pixel_height;
|
|
float one_to_one_line_height;
|
|
float target_aspect;
|
|
float scale_factor;
|
|
|
|
/* get info about the UI target */
|
|
render_target_get_bounds(render_get_ui_target(), &target_pixel_width, &target_pixel_height, &target_aspect);
|
|
|
|
/* compute the font pixel height at the nominal size */
|
|
one_to_one_line_height = (float)raw_font_pixel_height / (float)target_pixel_height;
|
|
|
|
/* determine the scale factor */
|
|
scale_factor = UI_TARGET_FONT_HEIGHT / one_to_one_line_height;
|
|
|
|
/* if our font is small-ish, do integral scaling */
|
|
if (raw_font_pixel_height < 24)
|
|
{
|
|
/* do we want to scale smaller? only do so if we exceed the threshhold */
|
|
if (scale_factor <= 1.0f)
|
|
{
|
|
if (one_to_one_line_height < UI_MAX_FONT_HEIGHT || raw_font_pixel_height < 12)
|
|
scale_factor = 1.0f;
|
|
}
|
|
|
|
/* otherwise, just ensure an integral scale factor */
|
|
else
|
|
scale_factor = floor(scale_factor);
|
|
}
|
|
|
|
/* otherwise, just make sure we hit an even number of pixels */
|
|
else
|
|
{
|
|
INT32 height = scale_factor * one_to_one_line_height * (float)target_pixel_height;
|
|
scale_factor = (float)height / (one_to_one_line_height * (float)target_pixel_height);
|
|
}
|
|
|
|
return scale_factor * one_to_one_line_height;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_get_char_width - return the width of a
|
|
single character
|
|
-------------------------------------------------*/
|
|
|
|
float ui_get_char_width(unicode_char ch)
|
|
{
|
|
return render_font_get_char_width(ui_font, ui_get_line_height(), render_get_ui_aspect(), ch);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_get_string_width - return the width of a
|
|
character string
|
|
-------------------------------------------------*/
|
|
|
|
float ui_get_string_width(const char *s)
|
|
{
|
|
return render_font_get_utf8string_width(ui_font, ui_get_line_height(), render_get_ui_aspect(), s);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_draw_outlined_box - add primitives to draw
|
|
an outlined box with the given background
|
|
color
|
|
-------------------------------------------------*/
|
|
|
|
void ui_draw_outlined_box(float x0, float y0, float x1, float y1, rgb_t backcolor)
|
|
{
|
|
float hw = UI_LINE_WIDTH * 0.5f;
|
|
render_ui_add_rect(x0, y0, x1, y1, backcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
|
render_ui_add_line(x0 + hw, y0 + hw, x1 - hw, y0 + hw, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
|
render_ui_add_line(x1 - hw, y0 + hw, x1 - hw, y1 - hw, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
|
render_ui_add_line(x1 - hw, y1 - hw, x0 + hw, y1 - hw, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
|
render_ui_add_line(x0 + hw, y1 - hw, x0 + hw, y0 + hw, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_draw_text - simple text renderer
|
|
-------------------------------------------------*/
|
|
|
|
void ui_draw_text(const char *buf, float x, float y)
|
|
{
|
|
ui_draw_text_full(buf, x, y, 1.0f - x, JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_draw_text_full - full featured text
|
|
renderer with word wrapping, justification,
|
|
and full size computation
|
|
-------------------------------------------------*/
|
|
|
|
void ui_draw_text_full(const char *origs, float x, float y, float origwrapwidth, int justify, int wrap, int draw, rgb_t fgcolor, rgb_t bgcolor, float *totalwidth, float *totalheight)
|
|
{
|
|
float lineheight = ui_get_line_height();
|
|
const char *ends = origs + strlen(origs);
|
|
float wrapwidth = origwrapwidth;
|
|
const char *s = origs;
|
|
const char *linestart;
|
|
float cury = y;
|
|
float maxwidth = 0;
|
|
|
|
/* if we don't want wrapping, guarantee a huge wrapwidth */
|
|
if (wrap == WRAP_NEVER)
|
|
wrapwidth = 1000000.0f;
|
|
if (wrapwidth <= 0)
|
|
return;
|
|
|
|
/* loop over lines */
|
|
while (*s != 0)
|
|
{
|
|
const char *lastbreak = NULL;
|
|
int line_justify = justify;
|
|
unicode_char schar;
|
|
int scharcount;
|
|
float lastbreak_width = 0;
|
|
float curwidth = 0;
|
|
float curx = x;
|
|
|
|
/* get the current character */
|
|
scharcount = uchar_from_utf8(&schar, s, ends - s);
|
|
if (scharcount == -1)
|
|
break;
|
|
|
|
/* if the line starts with a tab character, center it regardless */
|
|
if (schar == '\t')
|
|
{
|
|
s += scharcount;
|
|
line_justify = JUSTIFY_CENTER;
|
|
}
|
|
|
|
/* remember the starting position of the line */
|
|
linestart = s;
|
|
|
|
/* loop while we have characters and are less than the wrapwidth */
|
|
while (*s != 0 && curwidth <= wrapwidth)
|
|
{
|
|
float chwidth;
|
|
|
|
/* get the current chcaracter */
|
|
scharcount = uchar_from_utf8(&schar, s, ends - s);
|
|
if (scharcount == -1)
|
|
break;
|
|
|
|
/* if we hit a newline, stop immediately */
|
|
if (schar == '\n')
|
|
break;
|
|
|
|
/* get the width of this character */
|
|
chwidth = ui_get_char_width(schar);
|
|
|
|
/* if we hit a space, remember the location and width *without* the space */
|
|
if (schar == ' ')
|
|
{
|
|
lastbreak = s;
|
|
lastbreak_width = curwidth;
|
|
}
|
|
|
|
/* add the width of this character and advance */
|
|
curwidth += chwidth;
|
|
s += scharcount;
|
|
|
|
/* if we hit any non-space breakable character, remember the location and width
|
|
*with* the breakable character */
|
|
if (schar != ' ' && is_breakable_char(schar) && curwidth <= wrapwidth)
|
|
{
|
|
lastbreak = s;
|
|
lastbreak_width = curwidth;
|
|
}
|
|
}
|
|
|
|
/* if we accumulated too much for the current width, we need to back off */
|
|
if (curwidth > wrapwidth)
|
|
{
|
|
/* if we're word wrapping, back up to the last break if we can */
|
|
if (wrap == WRAP_WORD)
|
|
{
|
|
/* if we hit a break, back up to there with the appropriate width */
|
|
if (lastbreak != NULL)
|
|
{
|
|
s = lastbreak;
|
|
curwidth = lastbreak_width;
|
|
}
|
|
|
|
/* if we didn't hit a break, back up one character */
|
|
else if (s > linestart)
|
|
{
|
|
/* get the previous character */
|
|
s = (const char *)utf8_previous_char(s);
|
|
scharcount = uchar_from_utf8(&schar, s, ends - s);
|
|
if (scharcount == -1)
|
|
break;
|
|
|
|
curwidth -= ui_get_char_width(schar);
|
|
}
|
|
}
|
|
|
|
/* if we're truncating, make sure we have enough space for the ... */
|
|
else if (wrap == WRAP_TRUNCATE)
|
|
{
|
|
/* add in the width of the ... */
|
|
curwidth += 3.0f * ui_get_char_width('.');
|
|
|
|
/* while we are above the wrap width, back up one character */
|
|
while (curwidth > wrapwidth && s > linestart)
|
|
{
|
|
/* get the previous character */
|
|
s = (const char *)utf8_previous_char(s);
|
|
scharcount = uchar_from_utf8(&schar, s, ends - s);
|
|
if (scharcount == -1)
|
|
break;
|
|
|
|
curwidth -= ui_get_char_width(schar);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* align according to the justfication */
|
|
if (line_justify == JUSTIFY_CENTER)
|
|
curx += (origwrapwidth - curwidth) * 0.5f;
|
|
else if (line_justify == JUSTIFY_RIGHT)
|
|
curx += origwrapwidth - curwidth;
|
|
|
|
/* track the maximum width of any given line */
|
|
if (curwidth > maxwidth)
|
|
maxwidth = curwidth;
|
|
|
|
/* if opaque, add a black box */
|
|
if (draw == DRAW_OPAQUE)
|
|
render_ui_add_rect(curx, cury, curx + curwidth, cury + lineheight, bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
|
|
|
/* loop from the line start and add the characters */
|
|
while (linestart < s)
|
|
{
|
|
/* get the current character */
|
|
unicode_char linechar;
|
|
int linecharcount = uchar_from_utf8(&linechar, linestart, ends - linestart);
|
|
if (linecharcount == -1)
|
|
break;
|
|
|
|
if (draw != DRAW_NONE)
|
|
{
|
|
render_ui_add_char(curx, cury, lineheight, render_get_ui_aspect(), fgcolor, ui_font, linechar);
|
|
curx += ui_get_char_width(linechar);
|
|
}
|
|
linestart += linecharcount;
|
|
}
|
|
|
|
/* append ellipses if needed */
|
|
if (wrap == WRAP_TRUNCATE && *s != 0 && draw != DRAW_NONE)
|
|
{
|
|
render_ui_add_char(curx, cury, lineheight, render_get_ui_aspect(), fgcolor, ui_font, '.');
|
|
curx += ui_get_char_width('.');
|
|
render_ui_add_char(curx, cury, lineheight, render_get_ui_aspect(), fgcolor, ui_font, '.');
|
|
curx += ui_get_char_width('.');
|
|
render_ui_add_char(curx, cury, lineheight, render_get_ui_aspect(), fgcolor, ui_font, '.');
|
|
curx += ui_get_char_width('.');
|
|
}
|
|
|
|
/* if we're not word-wrapping, we're done */
|
|
if (wrap != WRAP_WORD)
|
|
break;
|
|
|
|
/* advance by a row */
|
|
cury += lineheight;
|
|
|
|
/* skip past any spaces at the beginning of the next line */
|
|
scharcount = uchar_from_utf8(&schar, s, ends - s);
|
|
if (scharcount == -1)
|
|
break;
|
|
|
|
if (schar == '\n')
|
|
s += scharcount;
|
|
else
|
|
while (*s && isspace(schar))
|
|
{
|
|
s += scharcount;
|
|
scharcount = uchar_from_utf8(&schar, s, ends - s);
|
|
if (scharcount == -1)
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* report the width and height of the resulting space */
|
|
if (totalwidth)
|
|
*totalwidth = maxwidth;
|
|
if (totalheight)
|
|
*totalheight = cury - y;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_draw_text_box - draw a multiline text
|
|
message with a box around it
|
|
-------------------------------------------------*/
|
|
|
|
void ui_draw_text_box(const char *text, int justify, float xpos, float ypos, rgb_t backcolor)
|
|
{
|
|
float target_width, target_height;
|
|
float target_x, target_y;
|
|
|
|
/* compute the multi-line target width/height */
|
|
ui_draw_text_full(text, 0, 0, 1.0f - 2.0f * UI_BOX_LR_BORDER,
|
|
justify, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height);
|
|
if (target_height > 1.0f - 2.0f * UI_BOX_TB_BORDER)
|
|
target_height = floor((1.0f - 2.0f * UI_BOX_TB_BORDER) / ui_get_line_height()) * ui_get_line_height();
|
|
|
|
/* determine the target location */
|
|
target_x = xpos - 0.5f * target_width;
|
|
target_y = ypos - 0.5f * target_height;
|
|
|
|
/* make sure we stay on-screen */
|
|
if (target_x < UI_BOX_LR_BORDER)
|
|
target_x = UI_BOX_LR_BORDER;
|
|
if (target_x + target_width + UI_BOX_LR_BORDER > 1.0f)
|
|
target_x = 1.0f - UI_BOX_LR_BORDER - target_width;
|
|
if (target_y < UI_BOX_TB_BORDER)
|
|
target_y = UI_BOX_TB_BORDER;
|
|
if (target_y + target_height + UI_BOX_TB_BORDER > 1.0f)
|
|
target_y = 1.0f - UI_BOX_TB_BORDER - target_height;
|
|
|
|
/* add a box around that */
|
|
ui_draw_outlined_box(target_x - UI_BOX_LR_BORDER,
|
|
target_y - UI_BOX_TB_BORDER,
|
|
target_x + target_width + UI_BOX_LR_BORDER,
|
|
target_y + target_height + UI_BOX_TB_BORDER, backcolor);
|
|
ui_draw_text_full(text, target_x, target_y, target_width,
|
|
justify, WRAP_WORD, DRAW_NORMAL, ARGB_WHITE, ARGB_BLACK, NULL, NULL);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_popup_time - popup a message for a specific
|
|
amount of time
|
|
-------------------------------------------------*/
|
|
|
|
void CLIB_DECL ui_popup_time(int seconds, const char *text, ...)
|
|
{
|
|
va_list arg;
|
|
|
|
/* extract the text */
|
|
va_start(arg,text);
|
|
astring_vprintf(messagebox_text, text, arg);
|
|
messagebox_backcolor = UI_FILLCOLOR;
|
|
va_end(arg);
|
|
|
|
/* set a timer */
|
|
popup_text_end = osd_ticks() + osd_ticks_per_second() * seconds;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_show_fps_temp - show the FPS counter for
|
|
a specific period of time
|
|
-------------------------------------------------*/
|
|
|
|
void ui_show_fps_temp(double seconds)
|
|
{
|
|
if (!showfps)
|
|
showfps_end = osd_ticks() + seconds * osd_ticks_per_second();
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_set_show_fps - show/hide the FPS counter
|
|
-------------------------------------------------*/
|
|
|
|
void ui_set_show_fps(int show)
|
|
{
|
|
showfps = show;
|
|
if (!show)
|
|
{
|
|
showfps = 0;
|
|
showfps_end = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_get_show_fps - return the current FPS
|
|
counter visibility state
|
|
-------------------------------------------------*/
|
|
|
|
int ui_get_show_fps(void)
|
|
{
|
|
return showfps || (showfps_end != 0);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_set_show_profiler - show/hide the profiler
|
|
-------------------------------------------------*/
|
|
|
|
void ui_set_show_profiler(int show)
|
|
{
|
|
if (show)
|
|
{
|
|
show_profiler = TRUE;
|
|
profiler_start();
|
|
}
|
|
else
|
|
{
|
|
show_profiler = FALSE;
|
|
profiler_stop();
|
|
}
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_get_show_profiler - return the current
|
|
profiler visibility state
|
|
-------------------------------------------------*/
|
|
|
|
int ui_get_show_profiler(void)
|
|
{
|
|
return show_profiler;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_show_menu - show the menus
|
|
-------------------------------------------------*/
|
|
|
|
void ui_show_menu(void)
|
|
{
|
|
ui_set_handler(ui_menu_ui_handler, 0);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
ui_is_menu_active - return TRUE if the menu
|
|
UI handler is active
|
|
-------------------------------------------------*/
|
|
|
|
int ui_is_menu_active(void)
|
|
{
|
|
return (ui_handler_callback == ui_menu_ui_handler);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
TEXT GENERATORS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
disclaimer_string - print the disclaimer
|
|
text to the given buffer
|
|
-------------------------------------------------*/
|
|
|
|
static astring *disclaimer_string(running_machine *machine, astring *string)
|
|
{
|
|
astring_cpyc(string, "Usage of emulators in conjunction with ROMs you don't own is forbidden by copyright law.\n\n");
|
|
astring_catprintf(string, "IF YOU ARE NOT LEGALLY ENTITLED TO PLAY \"%s\" ON THIS EMULATOR, PRESS ESC.\n\n", machine->gamedrv->description);
|
|
astring_catc(string, "Otherwise, type OK or move the joystick left then right to continue");
|
|
return string;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
warnings_string - print the warning flags
|
|
text to the given buffer
|
|
-------------------------------------------------*/
|
|
|
|
static astring *warnings_string(running_machine *machine, astring *string)
|
|
{
|
|
#define WARNING_FLAGS ( GAME_NOT_WORKING | \
|
|
GAME_UNEMULATED_PROTECTION | \
|
|
GAME_WRONG_COLORS | \
|
|
GAME_IMPERFECT_COLORS | \
|
|
GAME_NO_SOUND | \
|
|
GAME_IMPERFECT_SOUND | \
|
|
GAME_IMPERFECT_GRAPHICS | \
|
|
GAME_NO_COCKTAIL)
|
|
int i;
|
|
|
|
astring_reset(string);
|
|
|
|
/* if no warnings, nothing to return */
|
|
if (rom_load_warnings() == 0 && !(machine->gamedrv->flags & WARNING_FLAGS))
|
|
return string;
|
|
|
|
/* add a warning if any ROMs were loaded with warnings */
|
|
if (rom_load_warnings() > 0)
|
|
{
|
|
astring_catc(string, "One or more ROMs/CHDs for this game are incorrect. The " GAMENOUN " may not run correctly.\n");
|
|
if (machine->gamedrv->flags & WARNING_FLAGS)
|
|
astring_catc(string, "\n");
|
|
}
|
|
|
|
/* if we have at least one warning flag, print the general header */
|
|
if (machine->gamedrv->flags & WARNING_FLAGS)
|
|
{
|
|
astring_catc(string, "There are known problems with this " GAMENOUN "\n\n");
|
|
|
|
/* add one line per warning flag */
|
|
#ifdef MESS
|
|
if (machine->gamedrv->flags & GAME_COMPUTER)
|
|
astring_catc(string, "The emulated system is a computer:\n\nThe keyboard emulation may not be 100% accurate.\n");
|
|
#endif
|
|
if (machine->gamedrv->flags & GAME_IMPERFECT_COLORS)
|
|
astring_catc(string, "The colors aren't 100% accurate.\n");
|
|
if (machine->gamedrv->flags & GAME_WRONG_COLORS)
|
|
astring_catc(string, "The colors are completely wrong.\n");
|
|
if (machine->gamedrv->flags & GAME_IMPERFECT_GRAPHICS)
|
|
astring_catc(string, "The video emulation isn't 100% accurate.\n");
|
|
if (machine->gamedrv->flags & GAME_IMPERFECT_SOUND)
|
|
astring_catc(string, "The sound emulation isn't 100% accurate.\n");
|
|
if (machine->gamedrv->flags & GAME_NO_SOUND)
|
|
astring_catc(string, "The game lacks sound.\n");
|
|
if (machine->gamedrv->flags & GAME_NO_COCKTAIL)
|
|
astring_catc(string, "Screen flipping in cocktail mode is not supported.\n");
|
|
|
|
/* if there's a NOT WORKING or UNEMULATED PROTECTION warning, make it stronger */
|
|
if (machine->gamedrv->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION))
|
|
{
|
|
const game_driver *maindrv;
|
|
const game_driver *clone_of;
|
|
int foundworking;
|
|
|
|
/* add the strings for these warnings */
|
|
if (machine->gamedrv->flags & GAME_NOT_WORKING)
|
|
astring_catc(string, "THIS " CAPGAMENOUN " DOESN'T WORK. You won't be able to make it work correctly. Don't bother.\n");
|
|
if (machine->gamedrv->flags & GAME_UNEMULATED_PROTECTION)
|
|
astring_catc(string, "The game has protection which isn't fully emulated.\n");
|
|
|
|
/* find the parent of this driver */
|
|
clone_of = driver_get_clone(machine->gamedrv);
|
|
if (clone_of != NULL && !(clone_of->flags & GAME_IS_BIOS_ROOT))
|
|
maindrv = clone_of;
|
|
else
|
|
maindrv = machine->gamedrv;
|
|
|
|
/* scan the driver list for any working clones and add them */
|
|
foundworking = 0;
|
|
for (i = 0; drivers[i] != NULL; i++)
|
|
if (drivers[i] == maindrv || driver_get_clone(drivers[i]) == maindrv)
|
|
if ((drivers[i]->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION)) == 0)
|
|
{
|
|
/* this one works, add a header and display the name of the clone */
|
|
if (foundworking == 0)
|
|
astring_catc(string, "\n\nThere are working clones of this game. They are:\n\n");
|
|
astring_catc(string, drivers[i]->name);
|
|
astring_catc(string, "\n");
|
|
foundworking = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* add the 'press OK' string */
|
|
astring_catc(string, "\n\nType OK or move the joystick left then right to continue");
|
|
return string;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
game_info_astring - populate an allocated
|
|
string with the game info text
|
|
-------------------------------------------------*/
|
|
|
|
astring *game_info_astring(running_machine *machine, astring *string)
|
|
{
|
|
int scrcount = video_screen_count(machine->config);
|
|
int cpunum, sndnum;
|
|
int count;
|
|
|
|
/* print description, manufacturer, and CPU: */
|
|
astring_printf(string, "%s\n%s %s\n\nCPU:\n", machine->gamedrv->description, machine->gamedrv->year, machine->gamedrv->manufacturer);
|
|
|
|
/* loop over all CPUs */
|
|
for (cpunum = 0; cpunum < MAX_CPU && machine->config->cpu[cpunum].type != CPU_DUMMY; cpunum += count)
|
|
{
|
|
cpu_type type = machine->config->cpu[cpunum].type;
|
|
int clock = machine->config->cpu[cpunum].clock;
|
|
|
|
/* count how many identical CPUs we have */
|
|
for (count = 1; cpunum + count < MAX_CPU; count++)
|
|
if (machine->config->cpu[cpunum + count].type != type ||
|
|
machine->config->cpu[cpunum + count].clock != clock)
|
|
break;
|
|
|
|
/* if more than one, prepend a #x in front of the CPU name */
|
|
if (count > 1)
|
|
astring_catprintf(string, "%d" UTF8_MULTIPLY, count);
|
|
astring_catc(string, cputype_get_name(type));
|
|
|
|
/* display clock in kHz or MHz */
|
|
if (clock >= 1000000)
|
|
astring_catprintf(string, " %d.%06d" UTF8_NBSP "MHz\n", clock / 1000000, clock % 1000000);
|
|
else
|
|
astring_catprintf(string, " %d.%03d" UTF8_NBSP "kHz\n", clock / 1000, clock % 1000);
|
|
}
|
|
|
|
/* loop over all sound chips */
|
|
for (sndnum = 0; sndnum < MAX_SOUND && machine->config->sound[sndnum].type != SOUND_DUMMY; sndnum += count)
|
|
{
|
|
sound_type type = machine->config->sound[sndnum].type;
|
|
int clock = sndnum_clock(sndnum);
|
|
|
|
/* append the Sound: string */
|
|
if (sndnum == 0)
|
|
astring_catc(string, "\nSound:\n");
|
|
|
|
/* count how many identical sound chips we have */
|
|
for (count = 1; sndnum + count < MAX_SOUND; count++)
|
|
if (machine->config->sound[sndnum + count].type != type ||
|
|
sndnum_clock(sndnum + count) != clock)
|
|
break;
|
|
|
|
/* if more than one, prepend a #x in front of the CPU name */
|
|
if (count > 1)
|
|
astring_catprintf(string, "%d" UTF8_MULTIPLY, count);
|
|
astring_catc(string, sndnum_name(sndnum));
|
|
|
|
/* display clock in kHz or MHz */
|
|
if (clock >= 1000000)
|
|
astring_catprintf(string, " %d.%06d" UTF8_NBSP "MHz\n", clock / 1000000, clock % 1000000);
|
|
else if (clock != 0)
|
|
astring_catprintf(string, " %d.%03d" UTF8_NBSP "kHz\n", clock / 1000, clock % 1000);
|
|
else
|
|
astring_catc(string, "\n");
|
|
}
|
|
|
|
/* display screen information */
|
|
astring_catc(string, "\nVideo:\n");
|
|
if (scrcount == 0)
|
|
astring_catc(string, "None\n");
|
|
else
|
|
{
|
|
const device_config *screen;
|
|
|
|
for (screen = video_screen_first(machine->config); screen != NULL; screen = video_screen_next(screen))
|
|
{
|
|
const screen_config *scrconfig = screen->inline_config;
|
|
|
|
if (scrcount > 1)
|
|
astring_catc(string, slider_get_screen_desc(screen));
|
|
|
|
if (scrconfig->type == SCREEN_TYPE_VECTOR)
|
|
astring_catc(string, "Vector\n");
|
|
else
|
|
{
|
|
const rectangle *visarea = video_screen_get_visible_area(screen);
|
|
|
|
astring_catprintf(string, "%d " UTF8_MULTIPLY " %d (%s) %f" UTF8_NBSP "Hz\n",
|
|
visarea->max_x - visarea->min_x + 1,
|
|
visarea->max_y - visarea->min_y + 1,
|
|
(machine->gamedrv->flags & ORIENTATION_SWAP_XY) ? "V" : "H",
|
|
ATTOSECONDS_TO_HZ(video_screen_get_frame_period(screen).attoseconds));
|
|
}
|
|
}
|
|
}
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
UI HANDLERS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
handler_messagebox - displays the current
|
|
messagebox_text string but handles no input
|
|
-------------------------------------------------*/
|
|
|
|
static UINT32 handler_messagebox(running_machine *machine, UINT32 state)
|
|
{
|
|
ui_draw_text_box(astring_c(messagebox_text), JUSTIFY_LEFT, 0.5f, 0.5f, messagebox_backcolor);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
handler_messagebox_ok - displays the current
|
|
messagebox_text string and waits for an OK
|
|
-------------------------------------------------*/
|
|
|
|
static UINT32 handler_messagebox_ok(running_machine *machine, UINT32 state)
|
|
{
|
|
/* draw a standard message window */
|
|
ui_draw_text_box(astring_c(messagebox_text), JUSTIFY_LEFT, 0.5f, 0.5f, messagebox_backcolor);
|
|
|
|
/* an 'O' or left joystick kicks us to the next state */
|
|
if (state == 0 && (input_code_pressed_once(KEYCODE_O) || ui_input_pressed(machine, IPT_UI_LEFT)))
|
|
state++;
|
|
|
|
/* a 'K' or right joystick exits the state */
|
|
else if (state == 1 && (input_code_pressed_once(KEYCODE_K) || ui_input_pressed(machine, IPT_UI_RIGHT)))
|
|
state = UI_HANDLER_CANCEL;
|
|
|
|
/* if the user cancels, exit out completely */
|
|
else if (ui_input_pressed(machine, IPT_UI_CANCEL))
|
|
{
|
|
mame_schedule_exit(machine);
|
|
state = UI_HANDLER_CANCEL;
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
handler_messagebox_anykey - displays the
|
|
current messagebox_text string and waits for
|
|
any keypress
|
|
-------------------------------------------------*/
|
|
|
|
static UINT32 handler_messagebox_anykey(running_machine *machine, UINT32 state)
|
|
{
|
|
/* draw a standard message window */
|
|
ui_draw_text_box(astring_c(messagebox_text), JUSTIFY_LEFT, 0.5f, 0.5f, messagebox_backcolor);
|
|
|
|
/* if the user cancels, exit out completely */
|
|
if (ui_input_pressed(machine, IPT_UI_CANCEL))
|
|
{
|
|
mame_schedule_exit(machine);
|
|
state = UI_HANDLER_CANCEL;
|
|
}
|
|
|
|
/* if any key is pressed, just exit */
|
|
else if (input_code_poll_switches(FALSE) != INPUT_CODE_INVALID)
|
|
state = UI_HANDLER_CANCEL;
|
|
|
|
return state;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
handler_ingame - in-game handler takes care
|
|
of the standard keypresses
|
|
-------------------------------------------------*/
|
|
|
|
static UINT32 handler_ingame(running_machine *machine, UINT32 state)
|
|
{
|
|
int is_paused = mame_is_paused(machine);
|
|
|
|
/* first draw the FPS counter */
|
|
if (showfps || osd_ticks() < showfps_end)
|
|
{
|
|
ui_draw_text_full(video_get_speed_text(machine), 0.0f, 0.0f, 1.0f,
|
|
JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL);
|
|
}
|
|
else
|
|
showfps_end = 0;
|
|
|
|
/* draw the profiler if visible */
|
|
if (show_profiler)
|
|
ui_draw_text_full(profiler_get_text(machine), 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL);
|
|
|
|
/* if we're single-stepping, pause now */
|
|
if (single_step)
|
|
{
|
|
mame_pause(machine, TRUE);
|
|
single_step = FALSE;
|
|
}
|
|
|
|
#ifdef MESS
|
|
if (ui_mess_handler_ingame(machine))
|
|
return 0;
|
|
#endif /* MESS */
|
|
|
|
/* if the user pressed ESC, stop the emulation */
|
|
if (ui_input_pressed(machine, IPT_UI_CANCEL))
|
|
mame_schedule_exit(machine);
|
|
|
|
/* turn on menus if requested */
|
|
if (ui_input_pressed(machine, IPT_UI_CONFIGURE))
|
|
return ui_set_handler(ui_menu_ui_handler, 0);
|
|
|
|
/* if the on-screen display isn't up and the user has toggled it, turn it on */
|
|
// if ((machine->debug_flags & DEBUG_FLAG_ENABLED) == 0 && ui_input_pressed(machine, IPT_UI_ON_SCREEN_DISPLAY))
|
|
// return ui_set_handler(ui_slider_ui_handler, 0);
|
|
|
|
/* handle a reset request */
|
|
if (ui_input_pressed(machine, IPT_UI_RESET_MACHINE))
|
|
mame_schedule_hard_reset(machine);
|
|
if (ui_input_pressed(machine, IPT_UI_SOFT_RESET))
|
|
mame_schedule_soft_reset(machine);
|
|
|
|
/* handle a request to display graphics/palette */
|
|
if (ui_input_pressed(machine, IPT_UI_SHOW_GFX))
|
|
{
|
|
if (!is_paused)
|
|
mame_pause(machine, TRUE);
|
|
return ui_set_handler(ui_gfx_ui_handler, is_paused);
|
|
}
|
|
|
|
/* handle a save state request */
|
|
if (ui_input_pressed(machine, IPT_UI_SAVE_STATE))
|
|
{
|
|
mame_pause(machine, TRUE);
|
|
return ui_set_handler(handler_load_save, LOADSAVE_SAVE);
|
|
}
|
|
|
|
/* handle a load state request */
|
|
if (ui_input_pressed(machine, IPT_UI_LOAD_STATE))
|
|
{
|
|
mame_pause(machine, TRUE);
|
|
return ui_set_handler(handler_load_save, LOADSAVE_LOAD);
|
|
}
|
|
|
|
/* handle a save snapshot request */
|
|
if (ui_input_pressed(machine, IPT_UI_SNAPSHOT))
|
|
video_save_active_screen_snapshots(machine);
|
|
|
|
/* toggle pause */
|
|
if (ui_input_pressed(machine, IPT_UI_PAUSE))
|
|
{
|
|
/* with a shift key, it is single step */
|
|
if (is_paused && (input_code_pressed(KEYCODE_LSHIFT) || input_code_pressed(KEYCODE_RSHIFT)))
|
|
{
|
|
single_step = TRUE;
|
|
mame_pause(machine, FALSE);
|
|
}
|
|
else
|
|
mame_pause(machine, !mame_is_paused(machine));
|
|
}
|
|
|
|
/* toggle movie recording */
|
|
if (ui_input_pressed(machine, IPT_UI_RECORD_MOVIE))
|
|
{
|
|
if (!video_mng_is_movie_active(machine))
|
|
{
|
|
video_mng_begin_recording(machine, NULL);
|
|
popmessage("REC START");
|
|
}
|
|
else
|
|
{
|
|
video_mng_end_recording(machine);
|
|
popmessage("REC STOP");
|
|
}
|
|
}
|
|
|
|
/* toggle profiler display */
|
|
if (ui_input_pressed(machine, IPT_UI_SHOW_PROFILER))
|
|
ui_set_show_profiler(!ui_get_show_profiler());
|
|
|
|
/* toggle FPS display */
|
|
if (ui_input_pressed(machine, IPT_UI_SHOW_FPS))
|
|
ui_set_show_fps(!ui_get_show_fps());
|
|
|
|
/* toggle crosshair display */
|
|
if (ui_input_pressed(machine, IPT_UI_TOGGLE_CROSSHAIR))
|
|
crosshair_toggle(machine);
|
|
|
|
/* increment frameskip? */
|
|
if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_INC))
|
|
{
|
|
/* get the current value and increment it */
|
|
int newframeskip = video_get_frameskip() + 1;
|
|
if (newframeskip > MAX_FRAMESKIP)
|
|
newframeskip = -1;
|
|
video_set_frameskip(newframeskip);
|
|
|
|
/* display the FPS counter for 2 seconds */
|
|
ui_show_fps_temp(2.0);
|
|
}
|
|
|
|
/* decrement frameskip? */
|
|
if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_DEC))
|
|
{
|
|
/* get the current value and decrement it */
|
|
int newframeskip = video_get_frameskip() - 1;
|
|
if (newframeskip < -1)
|
|
newframeskip = MAX_FRAMESKIP;
|
|
video_set_frameskip(newframeskip);
|
|
|
|
/* display the FPS counter for 2 seconds */
|
|
ui_show_fps_temp(2.0);
|
|
}
|
|
|
|
/* toggle throttle? */
|
|
if (ui_input_pressed(machine, IPT_UI_THROTTLE))
|
|
video_set_throttle(!video_get_throttle());
|
|
|
|
/* check for fast forward */
|
|
if (input_type_pressed(machine, IPT_UI_FAST_FORWARD, 0))
|
|
{
|
|
video_set_fastforward(TRUE);
|
|
ui_show_fps_temp(0.5);
|
|
}
|
|
else
|
|
video_set_fastforward(FALSE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
handler_load_save - leads the user through
|
|
specifying a game to save or load
|
|
-------------------------------------------------*/
|
|
|
|
static UINT32 handler_load_save(running_machine *machine, UINT32 state)
|
|
{
|
|
char filename[20];
|
|
input_code code;
|
|
char file = 0;
|
|
|
|
/* if we're not in the middle of anything, skip */
|
|
if (state == LOADSAVE_NONE)
|
|
return 0;
|
|
|
|
/* okay, we're waiting for a key to select a slot; display a message */
|
|
if (state == LOADSAVE_SAVE)
|
|
ui_draw_message_window("Select position to save to");
|
|
else
|
|
ui_draw_message_window("Select position to load from");
|
|
|
|
/* check for cancel key */
|
|
if (ui_input_pressed(machine, IPT_UI_CANCEL))
|
|
{
|
|
/* display a popup indicating things were cancelled */
|
|
if (state == LOADSAVE_SAVE)
|
|
popmessage("Save cancelled");
|
|
else
|
|
popmessage("Load cancelled");
|
|
|
|
/* reset the state */
|
|
mame_pause(machine, FALSE);
|
|
return UI_HANDLER_CANCEL;
|
|
}
|
|
|
|
/* check for A-Z or 0-9 */
|
|
for (code = KEYCODE_A; code <= (input_code)KEYCODE_Z; code++)
|
|
if (input_code_pressed_once(code))
|
|
file = code - KEYCODE_A + 'a';
|
|
if (file == 0)
|
|
for (code = KEYCODE_0; code <= (input_code)KEYCODE_9; code++)
|
|
if (input_code_pressed_once(code))
|
|
file = code - KEYCODE_0 + '0';
|
|
if (file == 0)
|
|
for (code = KEYCODE_0_PAD; code <= (input_code)KEYCODE_9_PAD; code++)
|
|
if (input_code_pressed_once(code))
|
|
file = code - KEYCODE_0_PAD + '0';
|
|
if (file == 0)
|
|
return state;
|
|
|
|
/* display a popup indicating that the save will proceed */
|
|
sprintf(filename, "%c", file);
|
|
if (state == LOADSAVE_SAVE)
|
|
{
|
|
popmessage("Save to position %c", file);
|
|
mame_schedule_save(machine, filename);
|
|
}
|
|
else
|
|
{
|
|
popmessage("Load from position %c", file);
|
|
mame_schedule_load(machine, filename);
|
|
}
|
|
|
|
/* remove the pause and reset the state */
|
|
mame_pause(machine, FALSE);
|
|
return UI_HANDLER_CANCEL;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
SLIDER CONTROLS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
ui_get_slider_list - get the list of sliders
|
|
-------------------------------------------------*/
|
|
|
|
const slider_state *ui_get_slider_list(void)
|
|
{
|
|
return slider_list;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_alloc - allocate a new slider entry
|
|
-------------------------------------------------*/
|
|
|
|
static slider_state *slider_alloc(const char *title, INT32 minval, INT32 defval, INT32 maxval, INT32 incval, slider_update update, void *arg)
|
|
{
|
|
int size = sizeof(slider_state) + strlen(title);
|
|
slider_state *state = auto_malloc(size);
|
|
memset(state, 0, size);
|
|
|
|
state->minval = minval;
|
|
state->defval = defval;
|
|
state->maxval = maxval;
|
|
state->incval = incval;
|
|
state->update = update;
|
|
state->arg = arg;
|
|
strcpy(state->description, title);
|
|
|
|
return state;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_init - initialize the list of slider
|
|
controls
|
|
-------------------------------------------------*/
|
|
|
|
static slider_state *slider_init(running_machine *machine)
|
|
{
|
|
const input_field_config *field;
|
|
const input_port_config *port;
|
|
const device_config *device;
|
|
slider_state *listhead = NULL;
|
|
slider_state **tailptr = &listhead;
|
|
astring *string = astring_alloc();
|
|
int numitems, item;
|
|
|
|
/* add overall volume */
|
|
*tailptr = slider_alloc("Master Volume", -32, 0, 0, 1, slider_volume, NULL);
|
|
tailptr = &(*tailptr)->next;
|
|
|
|
/* add per-channel volume */
|
|
numitems = sound_get_user_gain_count(machine);
|
|
for (item = 0; item < numitems; item++)
|
|
{
|
|
INT32 maxval = 2000;
|
|
INT32 defval = sound_get_default_gain(machine, item) * 1000.0f + 0.5f;
|
|
|
|
if (defval > 1000)
|
|
maxval = 2 * defval;
|
|
|
|
astring_printf(string, "%s Volume", sound_get_user_gain_name(machine, item));
|
|
*tailptr = slider_alloc(astring_c(string), 0, defval, maxval, 20, slider_mixervol, (void *)(FPTR)item);
|
|
tailptr = &(*tailptr)->next;
|
|
}
|
|
|
|
/* add analog adjusters */
|
|
for (port = machine->portconfig; port != NULL; port = port->next)
|
|
for (field = port->fieldlist; field != NULL; field = field->next)
|
|
if (field->type == IPT_ADJUSTER)
|
|
{
|
|
void *param = (void *)field;
|
|
*tailptr = slider_alloc(field->name, 0, field->defvalue, 100, 1, slider_adjuster, param);
|
|
tailptr = &(*tailptr)->next;
|
|
}
|
|
|
|
/* add CPU overclocking (cheat only) */
|
|
if (options_get_bool(mame_options(), OPTION_CHEAT))
|
|
{
|
|
for (item = 0; item < ARRAY_LENGTH(machine->cpu); item++)
|
|
if (machine->cpu[item] != NULL)
|
|
{
|
|
astring_printf(string, "Overclock CPU %s", machine->cpu[item]->tag);
|
|
*tailptr = slider_alloc(astring_c(string), 10, 1000, 2000, 1, slider_overclock, (void *)(FPTR)item);
|
|
tailptr = &(*tailptr)->next;
|
|
}
|
|
}
|
|
|
|
/* add screen parameters */
|
|
for (device = video_screen_first(machine->config); device != NULL; device = video_screen_next(device))
|
|
{
|
|
const screen_config *scrconfig = device->inline_config;
|
|
int defxscale = floor(scrconfig->xscale * 1000.0f + 0.5f);
|
|
int defyscale = floor(scrconfig->yscale * 1000.0f + 0.5f);
|
|
int defxoffset = floor(scrconfig->xoffset * 1000.0f + 0.5f);
|
|
int defyoffset = floor(scrconfig->yoffset * 1000.0f + 0.5f);
|
|
void *param = (void *)device;
|
|
|
|
/* add refresh rate tweaker */
|
|
if (options_get_bool(mame_options(), OPTION_CHEAT))
|
|
{
|
|
astring_printf(string, "%s Refresh Rate", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), -10000, 0, 10000, 1000, slider_refresh, param);
|
|
tailptr = &(*tailptr)->next;
|
|
}
|
|
|
|
/* add standard brightness/contrast/gamma controls per-screen */
|
|
astring_printf(string, "%s Brightness", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), 100, 1000, 2000, 10, slider_brightness, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Contrast", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), 100, 1000, 2000, 50, slider_contrast, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Gamma", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), 100, 1000, 3000, 50, slider_gamma, param);
|
|
tailptr = &(*tailptr)->next;
|
|
|
|
/* add scale and offset controls per-screen */
|
|
astring_printf(string, "%s Horiz Stretch", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, slider_xscale, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Horiz Position", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), -500, defxoffset, 500, 2, slider_xoffset, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Vert Stretch", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, slider_yscale, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Vert Position", slider_get_screen_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), -500, defyoffset, 500, 2, slider_yoffset, param);
|
|
tailptr = &(*tailptr)->next;
|
|
}
|
|
|
|
for (device = device_list_first(machine->config->devicelist, LASERDISC); device != NULL; device = device_list_next(device, LASERDISC))
|
|
{
|
|
const laserdisc_config *config = device->inline_config;
|
|
if (config->overupdate != NULL)
|
|
{
|
|
int defxscale = floor(config->overscalex * 1000.0f + 0.5f);
|
|
int defyscale = floor(config->overscaley * 1000.0f + 0.5f);
|
|
int defxoffset = floor(config->overposx * 1000.0f + 0.5f);
|
|
int defyoffset = floor(config->overposy * 1000.0f + 0.5f);
|
|
void *param = (void *)device;
|
|
|
|
/* add scale and offset controls per-overlay */
|
|
astring_printf(string, "%s Horiz Stretch", slider_get_laserdisc_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, slider_overxscale, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Horiz Position", slider_get_laserdisc_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), -500, defxoffset, 500, 2, slider_overxoffset, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Vert Stretch", slider_get_laserdisc_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, slider_overyscale, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "%s Vert Position", slider_get_laserdisc_desc(device));
|
|
*tailptr = slider_alloc(astring_c(string), -500, defyoffset, 500, 2, slider_overyoffset, param);
|
|
tailptr = &(*tailptr)->next;
|
|
}
|
|
}
|
|
|
|
for (device = video_screen_first(machine->config); device != NULL; device = video_screen_next(device))
|
|
{
|
|
const screen_config *scrconfig = device->inline_config;
|
|
if (scrconfig->type == SCREEN_TYPE_VECTOR)
|
|
{
|
|
/* add flicker control */
|
|
*tailptr = slider_alloc("Vector Flicker", 0, 0, 1000, 10, slider_flicker, NULL);
|
|
tailptr = &(*tailptr)->next;
|
|
*tailptr = slider_alloc("Beam Width", 10, 100, 1000, 10, slider_beam, NULL);
|
|
tailptr = &(*tailptr)->next;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef MAME_DEBUG
|
|
/* add crosshair adjusters */
|
|
for (port = machine->portconfig; port != NULL; port = port->next)
|
|
for (field = port->fieldlist; field != NULL; field = field->next)
|
|
if (field->crossaxis != CROSSHAIR_AXIS_NONE && field->player == 0)
|
|
{
|
|
void *param = (void *)field;
|
|
astring_printf(string, "Crosshair Scale %s", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y");
|
|
*tailptr = slider_alloc(astring_c(string), -3000, 1000, 3000, 100, slider_crossscale, param);
|
|
tailptr = &(*tailptr)->next;
|
|
astring_printf(string, "Crosshair Offset %s", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y");
|
|
*tailptr = slider_alloc(astring_c(string), -3000, 0, 3000, 100, slider_crossoffset, param);
|
|
tailptr = &(*tailptr)->next;
|
|
}
|
|
#endif
|
|
|
|
astring_free(string);
|
|
return listhead;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_volume - global volume slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_volume(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
if (newval != SLIDER_NOCHANGE)
|
|
sound_set_attenuation(newval);
|
|
if (string != NULL)
|
|
astring_printf(string, "%3ddB", sound_get_attenuation());
|
|
return sound_get_attenuation();
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_mixervol - single channel volume
|
|
slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_mixervol(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
int which = (FPTR)arg;
|
|
if (newval != SLIDER_NOCHANGE)
|
|
sound_set_user_gain(machine, which, (float)newval * 0.001f);
|
|
if (string != NULL)
|
|
astring_printf(string, "%4.2f", sound_get_user_gain(machine, which));
|
|
return floor(sound_get_user_gain(machine, which) * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_adjuster - analog adjuster slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_adjuster(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const input_field_config *field = arg;
|
|
input_field_user_settings settings;
|
|
|
|
input_field_get_user_settings(field, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.value = newval;
|
|
input_field_set_user_settings(field, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%d%%", settings.value);
|
|
return settings.value;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_overclock - CPU overclocker slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_overclock(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
int which = (FPTR)arg;
|
|
if (newval != SLIDER_NOCHANGE)
|
|
cpu_set_clockscale(machine->cpu[which], (float)newval * 0.001f);
|
|
if (string != NULL)
|
|
astring_printf(string, "%3.0f%%", floor(cpu_get_clockscale(machine->cpu[which]) * 100.0f + 0.5f));
|
|
return floor(cpu_get_clockscale(machine->cpu[which]) * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_refresh - refresh rate slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_refresh(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
const screen_config *scrconfig = screen->inline_config;
|
|
double defrefresh = ATTOSECONDS_TO_HZ(scrconfig->refresh);
|
|
double refresh;
|
|
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
int width = video_screen_get_width(screen);
|
|
int height = video_screen_get_height(screen);
|
|
const rectangle *visarea = video_screen_get_visible_area(screen);
|
|
|
|
video_screen_configure(screen, width, height, visarea, HZ_TO_ATTOSECONDS(defrefresh + (double)newval * 0.001));
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3ffps", ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds));
|
|
refresh = ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds);
|
|
return floor((refresh - defrefresh) * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_brightness - screen brightness slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_brightness(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
render_container *container = render_container_get_screen(screen);
|
|
render_container_user_settings settings;
|
|
|
|
render_container_get_user_settings(container, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.brightness = (float)newval * 0.001f;
|
|
render_container_set_user_settings(container, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.brightness);
|
|
return floor(settings.brightness * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_contrast - screen contrast slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_contrast(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
render_container *container = render_container_get_screen(screen);
|
|
render_container_user_settings settings;
|
|
|
|
render_container_get_user_settings(container, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.contrast = (float)newval * 0.001f;
|
|
render_container_set_user_settings(container, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.contrast);
|
|
return floor(settings.contrast * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_gamma - screen gamma slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_gamma(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
render_container *container = render_container_get_screen(screen);
|
|
render_container_user_settings settings;
|
|
|
|
render_container_get_user_settings(container, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.gamma = (float)newval * 0.001f;
|
|
render_container_set_user_settings(container, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.gamma);
|
|
return floor(settings.gamma * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_xscale - screen horizontal scale slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_xscale(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
render_container *container = render_container_get_screen(screen);
|
|
render_container_user_settings settings;
|
|
|
|
render_container_get_user_settings(container, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.xscale = (float)newval * 0.001f;
|
|
render_container_set_user_settings(container, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.xscale);
|
|
return floor(settings.xscale * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_yscale - screen vertical scale slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_yscale(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
render_container *container = render_container_get_screen(screen);
|
|
render_container_user_settings settings;
|
|
|
|
render_container_get_user_settings(container, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.yscale = (float)newval * 0.001f;
|
|
render_container_set_user_settings(container, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.yscale);
|
|
return floor(settings.yscale * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_xoffset - screen horizontal position
|
|
slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_xoffset(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
render_container *container = render_container_get_screen(screen);
|
|
render_container_user_settings settings;
|
|
|
|
render_container_get_user_settings(container, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.xoffset = (float)newval * 0.001f;
|
|
render_container_set_user_settings(container, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.xoffset);
|
|
return floor(settings.xoffset * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_yoffset - screen vertical position
|
|
slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_yoffset(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *screen = arg;
|
|
render_container *container = render_container_get_screen(screen);
|
|
render_container_user_settings settings;
|
|
|
|
render_container_get_user_settings(container, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.yoffset = (float)newval * 0.001f;
|
|
render_container_set_user_settings(container, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.yoffset);
|
|
return floor(settings.yoffset * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_overxscale - screen horizontal scale slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_overxscale(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *laserdisc = arg;
|
|
laserdisc_config settings;
|
|
|
|
laserdisc_get_config(laserdisc, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.overscalex = (float)newval * 0.001f;
|
|
laserdisc_set_config(laserdisc, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.overscalex);
|
|
return floor(settings.overscalex * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_overyscale - screen vertical scale slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_overyscale(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *laserdisc = arg;
|
|
laserdisc_config settings;
|
|
|
|
laserdisc_get_config(laserdisc, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.overscaley = (float)newval * 0.001f;
|
|
laserdisc_set_config(laserdisc, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.overscaley);
|
|
return floor(settings.overscaley * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_overxoffset - screen horizontal position
|
|
slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_overxoffset(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *laserdisc = arg;
|
|
laserdisc_config settings;
|
|
|
|
laserdisc_get_config(laserdisc, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.overposx = (float)newval * 0.001f;
|
|
laserdisc_set_config(laserdisc, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.overposx);
|
|
return floor(settings.overposx * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_overyoffset - screen vertical position
|
|
slider callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_overyoffset(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
const device_config *laserdisc = arg;
|
|
laserdisc_config settings;
|
|
|
|
laserdisc_get_config(laserdisc, &settings);
|
|
if (newval != SLIDER_NOCHANGE)
|
|
{
|
|
settings.overposy = (float)newval * 0.001f;
|
|
laserdisc_set_config(laserdisc, &settings);
|
|
}
|
|
if (string != NULL)
|
|
astring_printf(string, "%.3f", settings.overposy);
|
|
return floor(settings.overposy * 1000.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_flicker - vector flicker slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_flicker(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
if (newval != SLIDER_NOCHANGE)
|
|
vector_set_flicker((float)newval * 0.1f);
|
|
if (string != NULL)
|
|
astring_printf(string, "%1.2f", vector_get_flicker());
|
|
return floor(vector_get_flicker() * 10.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_beam - vector beam width slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
static INT32 slider_beam(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
if (newval != SLIDER_NOCHANGE)
|
|
vector_set_beam((float)newval * 0.01f);
|
|
if (string != NULL)
|
|
astring_printf(string, "%1.2f", vector_get_beam());
|
|
return floor(vector_get_beam() * 100.0f + 0.5f);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_get_screen_desc - returns the
|
|
description for a given screen
|
|
-------------------------------------------------*/
|
|
|
|
static char *slider_get_screen_desc(const device_config *screen)
|
|
{
|
|
int screen_count = video_screen_count(screen->machine->config);
|
|
static char descbuf[256];
|
|
|
|
if (screen_count > 1)
|
|
sprintf(descbuf, "Screen '%s'", screen->tag);
|
|
else
|
|
strcpy(descbuf, "Screen");
|
|
|
|
return descbuf;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_get_laserdisc_desc - returns the
|
|
description for a given laseridsc
|
|
-------------------------------------------------*/
|
|
|
|
static char *slider_get_laserdisc_desc(const device_config *laserdisc)
|
|
{
|
|
int ldcount = device_list_items(laserdisc->machine->config->devicelist, LASERDISC);
|
|
static char descbuf[256];
|
|
|
|
if (ldcount > 1)
|
|
sprintf(descbuf, "Laserdisc '%s'", laserdisc->tag);
|
|
else
|
|
strcpy(descbuf, "Laserdisc");
|
|
|
|
return descbuf;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_crossscale - crosshair scale slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
#ifdef MAME_DEBUG
|
|
static INT32 slider_crossscale(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
input_field_config *field = arg;
|
|
|
|
if (newval != SLIDER_NOCHANGE)
|
|
field->crossscale = (float)newval * 0.001f;
|
|
if (string != NULL)
|
|
astring_printf(string, "%s %s %1.3f", "Crosshair Scale", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y", (float)newval * 0.001f);
|
|
return floor(field->crossscale * 1000.0f + 0.5f);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*-------------------------------------------------
|
|
slider_crossoffset - crosshair scale slider
|
|
callback
|
|
-------------------------------------------------*/
|
|
|
|
#ifdef MAME_DEBUG
|
|
static INT32 slider_crossoffset(running_machine *machine, void *arg, astring *string, INT32 newval)
|
|
{
|
|
input_field_config *field = arg;
|
|
|
|
if (newval != SLIDER_NOCHANGE)
|
|
field->crossoffset = (float)newval * 0.001f;
|
|
if (string != NULL)
|
|
astring_printf(string, "%s %s %1.3f", "Crosshair Offset", (field->crossaxis == CROSSHAIR_AXIS_X) ? "X" : "Y", (float)newval * 0.001f);
|
|
return field->crossoffset;
|
|
}
|
|
#endif
|