summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Derrick Renaud <derrickr@mamedev.org>2009-03-28 22:55:34 +0000
committer Derrick Renaud <derrickr@mamedev.org>2009-03-28 22:55:34 +0000
commit01962d4fc5c6f881632421f773d9f21fa9ea1a3b (patch)
treeb2490e5fc42a76665da7351341df7ffbc55892d4
parent9c63c950435a3d896cfb5d0d8cb639d55f559819 (diff)
Crosshair update
* Added Crosshair Options menu - ability to individually enable/disable crosshairs - ability for them to automatically disappear after a set amount of time - ability to select crosshair graphic - all settings are saved in the cfg file * Removed F1 toggle for crosshairs * Added new command option -crsshairpath - store all selectable graphics here - see config.txt for further info OSD NOTE: render_load_png() has been changed to no longer force usage of the artwork directory. Do a search for "render_load_png(" and replace with "render_load_png(OPTION_ARTPATH, " if needed. ---------------------------- F1 is now free to use for something new. I was thinking it would be perfect for a context sensitive help file. Each menu item could have a help tag, that it would look up and display info from an HTML file.
-rw-r--r--docs/config.txt26
-rw-r--r--src/emu/crsshair.c315
-rw-r--r--src/emu/crsshair.h38
-rw-r--r--src/emu/emuopts.c1
-rw-r--r--src/emu/emuopts.h1
-rw-r--r--src/emu/fileio.h1
-rw-r--r--src/emu/inptport.h1
-rw-r--r--src/emu/inpttype.h1
-rw-r--r--src/emu/rendlay.c4
-rw-r--r--src/emu/rendutil.c4
-rw-r--r--src/emu/rendutil.h2
-rw-r--r--src/emu/ui.c21
-rw-r--r--src/emu/uimenu.c291
-rw-r--r--src/osd/windows/drawd3d.c4
-rw-r--r--src/osd/windows/video.c2
15 files changed, 617 insertions, 95 deletions
diff --git a/docs/config.txt b/docs/config.txt
index bc1a14062d4..a3ca21a1fac 100644
--- a/docs/config.txt
+++ b/docs/config.txt
@@ -64,9 +64,6 @@ P Pauses the game.
Shift+P While paused, advances to next frame.
-F1 Toggle crosshairs for games that use them. Each subsequent
- press will enable crosshairs for one more player.
-
F2 Service Mode for games that support it.
F3 Resets the game.
@@ -332,6 +329,15 @@ Core search path options
paths can be specified by separating them with semicolons. The default
is '.' (that is, search in the same directory as the MAME executable).
+-crsshairpath <path>
+
+ Specifies a list of paths within which to find crosshair files. Multiple
+ paths can be specified by separating them with semicolons. The default
+ is 'crsshair' (that is, a directory "crsshair" in the same directory as
+ the MAME executable). If the Crosshair is set to default in the menu,
+ MAME will look for gamename\cross#.png and then cross#.png in the
+ specified crsshairpath, where # is the player number. Failing that,
+ MAME will use built-in default crosshairs.
Core Output Directory Options
@@ -467,17 +473,17 @@ Core state/playback options
and names the snapshots under it starting with 0000 and increasing
from there.
--snapsize <width>x<height>
+-snapsize <width>x<height>
Hard-codes the size for snapshots and movie recording. By default,
MAME will create snapshots at the game's current resolution in raw
pixels, and will create movies at the game's starting resolution in
raw pixels. If you specify this option, then MAME will create both
snapshots and movies at the size specified, and will bilinear filter
- the result. Note that this size does not automatically rotate if the
+ the result. Note that this size does not automatically rotate if the
game is vertically oriented. The default is 'auto'.
--snapview <viewname>
+-snapview <viewname>
Specifies the view to use when rendering snapshots and movies. By
default, both use a special 'internal' view, which renders a separate
@@ -486,8 +492,8 @@ Core state/playback options
select a single view that will apply to all snapshots and movies.
Note that <viewname> does not need to be a perfect match; rather, it
will select the first view whose name matches all the characters
- specified by <viewname>. For example, -snapview native will match the
- "Native (15:14)" view even though it is not a perfect match.
+ specified by <viewname>. For example, -snapview native will match the
+ "Native (15:14)" view even though it is not a perfect match.
<viewname> can also be 'auto', which selects the first view with all
screens present. The default value is 'internal'.
@@ -940,8 +946,8 @@ Debugging options
-[no]debug
- Activates the integrated debugger. By default, the debugger is entered
- by pressing the tilde (~) key during emulation. It is also entered
+ Activates the integrated debugger. By default, the debugger is entered
+ by pressing the tilde (~) key during emulation. It is also entered
immediately at startup. The default is OFF (-nodebug).
-debugscript <filename>
diff --git a/src/emu/crsshair.c b/src/emu/crsshair.c
index b56e04afdfb..6b780a6b00e 100644
--- a/src/emu/crsshair.c
+++ b/src/emu/crsshair.c
@@ -11,6 +11,8 @@
#include "driver.h"
#include "rendutil.h"
+#include "config.h"
+#include "xmlfile.h"
@@ -29,15 +31,22 @@
typedef struct _crosshair_global crosshair_global;
struct _crosshair_global
{
+ UINT8 usage; /* true if any crosshairs are used */
UINT8 used[MAX_PLAYERS]; /* usage per player */
+ UINT8 mode[MAX_PLAYERS]; /* visibility mode per player */
UINT8 visible[MAX_PLAYERS]; /* visibility per player */
bitmap_t * bitmap[MAX_PLAYERS]; /* bitmap per player */
render_texture * texture[MAX_PLAYERS]; /* texture per player */
const device_config *screen[MAX_PLAYERS]; /* the screen on which this player's crosshair is drawn */
float x[MAX_PLAYERS]; /* current X position */
float y[MAX_PLAYERS]; /* current Y position */
+ float last_x[MAX_PLAYERS]; /* last X position */
+ float last_y[MAX_PLAYERS]; /* last Y position */
UINT8 fade; /* color fading factor */
UINT8 animation_counter; /* animation frame index */
+ UINT16 auto_time; /* time in seconds to turn invisible */
+ UINT16 time[MAX_PLAYERS]; /* time since last movement */
+ char name[MAX_PLAYERS][CROSSHAIR_PIC_NAME_LENGTH + 1]; /* name of crosshair png file */
};
@@ -121,6 +130,9 @@ static const rgb_t crosshair_colors[] =
***************************************************************************/
static void crosshair_exit(running_machine *machine);
+static void crosshair_load(running_machine *machine, int config_type, xml_data_node *parentnode);
+static void crosshair_save(running_machine *machine, int config_type, xml_data_node *parentnode);
+
static void animate(const device_config *device, void *param, int vblank_state);
@@ -134,44 +146,57 @@ static void animate(const device_config *device, void *param, int vblank_state);
structures for the given player
-------------------------------------------------*/
-static void create_bitmap(int player)
+static void create_bitmap(running_machine *machine, int player)
{
- /* if we don't have a bitmap for this player yet */
- if (global.bitmap[player] == NULL)
- {
- int x, y;
- char filename[20];
- rgb_t color = crosshair_colors[player];
+ int x, y;
+ char filename[20];
+ rgb_t color = crosshair_colors[player];
- /* first try to load a bitmap for the crosshair */
- sprintf(filename, "cross%d.png", player);
- global.bitmap[player] = render_load_png(NULL, filename, NULL, NULL);
+ /* if we have a bitmap for this player, kill it */
+ if (global.bitmap[player] != NULL)
+ free(global.bitmap[player]);
- /* if that didn't work, use the built-in one */
+ if (global.name[player][0] != 0)
+ {
+ /* look for user specified file */
+ sprintf(filename, "%s.png", global.name[player]);
+ global.bitmap[player] = render_load_png(OPTION_CRSSHAIRPATH, NULL, filename, NULL, NULL);
+ }
+ else
+ {
+ /* look for default cross?.png in crsshair\game dir */
+ sprintf(filename, "cross%d.png", player + 1);
+ global.bitmap[player] = render_load_png(OPTION_CRSSHAIRPATH, machine->gamedrv->name, filename, NULL, NULL);
+
+ /* look for default cross?.png in crsshair dir */
if (global.bitmap[player] == NULL)
- {
- /* allocate a blank bitmap to start with */
- global.bitmap[player] = bitmap_alloc(CROSSHAIR_RAW_SIZE, CROSSHAIR_RAW_SIZE, BITMAP_FORMAT_ARGB32);
- bitmap_fill(global.bitmap[player], NULL, MAKE_ARGB(0x00,0xff,0xff,0xff));
+ global.bitmap[player] = render_load_png(OPTION_CRSSHAIRPATH, NULL, filename, NULL, NULL);
+ }
- /* extract the raw source data to it */
- for (y = 0; y < CROSSHAIR_RAW_SIZE / 2; y++)
- {
- /* assume it is mirrored vertically */
- UINT32 *dest0 = BITMAP_ADDR32(global.bitmap[player], y, 0);
- UINT32 *dest1 = BITMAP_ADDR32(global.bitmap[player], CROSSHAIR_RAW_SIZE - 1 - y, 0);
-
- /* extract to two rows simultaneously */
- for (x = 0; x < CROSSHAIR_RAW_SIZE; x++)
- if ((crosshair_raw_top[y * CROSSHAIR_RAW_ROWBYTES + x / 8] << (x % 8)) & 0x80)
- dest0[x] = dest1[x] = MAKE_ARGB(0xff,0x00,0x00,0x00) | color;
- }
- }
+ /* if that didn't work, use the built-in one */
+ if (global.bitmap[player] == NULL)
+ {
+ /* allocate a blank bitmap to start with */
+ global.bitmap[player] = bitmap_alloc(CROSSHAIR_RAW_SIZE, CROSSHAIR_RAW_SIZE, BITMAP_FORMAT_ARGB32);
+ bitmap_fill(global.bitmap[player], NULL, MAKE_ARGB(0x00,0xff,0xff,0xff));
- /* create a texture to reference the bitmap */
- global.texture[player] = render_texture_alloc(render_texture_hq_scale, NULL);
- render_texture_set_bitmap(global.texture[player], global.bitmap[player], NULL, TEXFORMAT_ARGB32, NULL);
+ /* extract the raw source data to it */
+ for (y = 0; y < CROSSHAIR_RAW_SIZE / 2; y++)
+ {
+ /* assume it is mirrored vertically */
+ UINT32 *dest0 = BITMAP_ADDR32(global.bitmap[player], y, 0);
+ UINT32 *dest1 = BITMAP_ADDR32(global.bitmap[player], CROSSHAIR_RAW_SIZE - 1 - y, 0);
+
+ /* extract to two rows simultaneously */
+ for (x = 0; x < CROSSHAIR_RAW_SIZE; x++)
+ if ((crosshair_raw_top[y * CROSSHAIR_RAW_ROWBYTES + x / 8] << (x % 8)) & 0x80)
+ dest0[x] = dest1[x] = MAKE_ARGB(0xff,0x00,0x00,0x00) | color;
+ }
}
+
+ /* create a texture to reference the bitmap */
+ global.texture[player] = render_texture_alloc(render_texture_hq_scale, NULL);
+ render_texture_set_bitmap(global.texture[player], global.bitmap[player], NULL, TEXFORMAT_ARGB32, NULL);
}
@@ -191,6 +216,9 @@ void crosshair_init(running_machine *machine)
/* clear all the globals */
memset(&global, 0, sizeof(global));
+ /* setup the default auto visibility time */
+ global.auto_time = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
+
/* determine who needs crosshairs */
for (port = machine->portconfig; port != NULL; port = port->next)
for (field = port->fieldlist; field != NULL; field = field->next)
@@ -200,16 +228,22 @@ void crosshair_init(running_machine *machine)
assert(player < MAX_PLAYERS);
- /* mark as used and visible */
+ /* mark as used and set the default visibility and mode */
+ global.usage = TRUE;
global.used[player] = TRUE;
- global.visible[player] = TRUE;
+ global.mode[player] = CROSSHAIR_VISIBILITY_DEFAULT;
+ global.visible[player] = (CROSSHAIR_VISIBILITY_DEFAULT == CROSSHAIR_VISIBILITY_OFF) ? FALSE : TRUE;
/* for now, use the main screen */
global.screen[player] = machine->primary_screen;
- create_bitmap(player);
+ create_bitmap(machine, player);
}
+ /* register callbacks for when we load/save configurations */
+ if (global.usage)
+ config_register(machine, "crosshairs", crosshair_load, crosshair_save);
+
/* register the animation callback */
if (machine->primary_screen != NULL)
video_screen_register_vblank_callback(machine->primary_screen, animate, NULL);
@@ -240,31 +274,54 @@ static void crosshair_exit(running_machine *machine)
/*-------------------------------------------------
- crosshair_toggle - toggle crosshair
- visibility
+ crosshair_get_usage - return TRUE
+ if any crosshairs are used
-------------------------------------------------*/
-void crosshair_toggle(running_machine *machine)
+int crosshair_get_usage(running_machine *machine)
{
- int player;
- int first_hidden_player = -1;
+ return global.usage;
+}
- /* find the first invisible crosshair */
- for (player = 0; player < MAX_PLAYERS; player++)
- if (global.used[player] && !global.visible[player])
- {
- first_hidden_player = player;
- break;
- }
- /* if all visible, turn all off */
- if (first_hidden_player == -1)
- for (player = 0; player < MAX_PLAYERS; player++)
- global.visible[player] = FALSE;
+/*-------------------------------------------------
+ crosshair_get_user_settings - return the
+ current crosshair settings for a player
+ Note: auto_time is common for all players
+-------------------------------------------------*/
- /* otherwise, turn on the first one that isn't currently on */
- else
- global.visible[first_hidden_player] = TRUE;
+void crosshair_get_user_settings(running_machine *machine, UINT8 player, crosshair_user_settings *settings)
+{
+ settings->auto_time = global.auto_time;
+ settings->used = global.used[player];
+ settings->mode = global.mode[player];
+ strcpy(settings->name, global.name[player]);
+}
+
+
+/*-------------------------------------------------
+ crosshair_set_user_settings - modify the
+ current crosshair settings for a player
+ Note: auto_time is common for all players
+-------------------------------------------------*/
+
+void crosshair_set_user_settings(running_machine *machine, UINT8 player, crosshair_user_settings *settings)
+{
+ int changed = FALSE;
+
+ global.auto_time = settings->auto_time;
+ global.used[player] = settings->used;
+ global.mode[player] = settings->mode;
+
+ /* set visibility as specified by mode */
+ /* auto mode starts with visibility off */
+ global.visible[player] = (settings->mode == CROSSHAIR_VISIBILITY_ON) ? TRUE : FALSE;
+
+ /* update bitmap if name has changed */
+ changed = strcmp(settings->name, global.name[player]);
+ strcpy(global.name[player], settings->name);
+ if (changed)
+ create_bitmap(machine, player);
}
@@ -285,10 +342,39 @@ static void animate(const device_config *device, void *param, int vblank_state)
else
global.fade = 0xa0 + (0x60 * (~global.animation_counter & 0x7f) / 0x80);
- /* read all the lightgun values */
for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ /* read all the lightgun values */
if (global.used[player])
input_port_get_crosshair_position(device->machine, player, &global.x[player], &global.y[player]);
+
+ /* auto visibility */
+ if (global.mode[player] == CROSSHAIR_VISIBILITY_AUTO)
+ {
+ if ((global.x[player] != global.last_x[player]) || (global.y[player] != global.last_y[player]))
+ {
+ /* crosshair has moved, keep crosshair visible */
+ global.visible[player] = TRUE;
+ global.last_x[player] = global.x[player];
+ global.last_y[player] = global.y[player];
+ global.time[player] = 0;
+ }
+ else
+ {
+ /* see if the player has been motionless for time specified */
+ /* note that the animate() routine is called twice per frame */
+ /* slightly confusing formula, but the effect is: */
+ /* auto_time = 1 makes the crosshair barely visible while moved */
+ /* every increment in auto_time is about .2s at 60Hz */
+ if (global.time[player] > global.auto_time * 24 - 20)
+ /* time exceeded so turn crosshair invisible */
+ global.visible[player] = FALSE;
+
+ /* increment player visibility time */
+ global.time[player]++;
+ }
+ }
+ }
}
@@ -325,3 +411,124 @@ void crosshair_set_screen(running_machine *machine, int player, const device_con
{
global.screen[player] = screen;
}
+
+
+/*-------------------------------------------------
+ crosshair_load - read and apply data from the
+ configuration file
+-------------------------------------------------*/
+
+static void crosshair_load(running_machine *machine, int config_type, xml_data_node *parentnode)
+{
+ /* Note: crosshair_load() is only registered if croshairs are used */
+
+ xml_data_node *crosshairnode;
+ int auto_time;
+
+ /* we only care about game files */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ /* might not have any data */
+ if (parentnode == NULL)
+ return;
+
+ /* loop and get player crosshair info */
+ for (crosshairnode = xml_get_sibling(parentnode->child, "crosshair"); crosshairnode; crosshairnode = xml_get_sibling(crosshairnode->next, "crosshair"))
+ {
+ int player, mode;
+
+ player = xml_get_attribute_int(crosshairnode, "player", -1);
+
+ /* check to make sure we have a valid player */
+ /* also check if the player really uses a crosshair */
+ if (player >=0 && player < MAX_PLAYERS && global.used[player])
+ {
+ /* get, check, and store visibility mode */
+ mode = xml_get_attribute_int(crosshairnode, "mode", CROSSHAIR_VISIBILITY_DEFAULT);
+ if (mode >= CROSSHAIR_VISIBILITY_OFF && mode <= CROSSHAIR_VISIBILITY_AUTO)
+ {
+ global.mode[player] = (UINT8)mode;
+ /* set visibility as specified by mode */
+ /* auto mode starts with visibility off */
+ global.visible[player] = (mode == CROSSHAIR_VISIBILITY_ON) ? TRUE : FALSE;
+ }
+
+ /* get and store crosshair pic name, truncate name to max length */
+ strncpy(global.name[player], xml_get_attribute_string(crosshairnode, "pic", ""), CROSSHAIR_PIC_NAME_LENGTH);
+ /* update bitmap */
+ create_bitmap(machine, player);
+ }
+ }
+
+ /* get, check, and store auto visibility time */
+ crosshairnode = xml_get_sibling(parentnode->child, "autotime");
+ if (crosshairnode != NULL)
+ {
+ auto_time = xml_get_attribute_int(crosshairnode, "val", CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT);
+ if ((auto_time >= CROSSHAIR_VISIBILITY_AUTOTIME_MIN) && (auto_time <= CROSSHAIR_VISIBILITY_AUTOTIME_MAX))
+ global.auto_time = (UINT8)auto_time;
+ }
+}
+
+
+/*-------------------------------------------------
+ crosshair_save - save data to the
+ configuration file
+-------------------------------------------------*/
+
+static void crosshair_save(running_machine *machine, int config_type, xml_data_node *parentnode)
+{
+ /* Note: crosshair_save() is only registered if crosshairs are used */
+
+ xml_data_node *crosshairnode;
+ int player;
+
+ /* we only care about game files */
+ if (config_type != CONFIG_TYPE_GAME)
+ return;
+
+ for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ if (global.used[player])
+ {
+ /* create a node */
+ crosshairnode = xml_add_child(parentnode, "crosshair", NULL);
+
+ if (crosshairnode != NULL)
+ {
+ int changed = FALSE;
+
+ xml_set_attribute_int(crosshairnode, "player", player);
+
+ if (global.visible[player] != CROSSHAIR_VISIBILITY_DEFAULT)
+ {
+ xml_set_attribute_int(crosshairnode, "mode", global.mode[player]);
+ changed = TRUE;
+ }
+
+ /* the default graphic name is "", so only save if not */
+ if (strlen(global.name[player]) > 0)
+ {
+ xml_set_attribute(crosshairnode, "pic", global.name[player]);
+ changed = TRUE;
+ }
+
+ /* if nothing changed, kill the node */
+ if (!changed)
+ xml_delete_node(crosshairnode);
+ }
+ }
+ }
+
+ /* always store autotime so that it stays at the user value if it is needed */
+ if (global.auto_time != CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT)
+ {
+ /* create a node */
+ crosshairnode = xml_add_child(parentnode, "autotime", NULL);
+
+ if (crosshairnode != NULL)
+ xml_set_attribute_int(crosshairnode, "val", global.auto_time);
+ }
+
+}
diff --git a/src/emu/crsshair.h b/src/emu/crsshair.h
index 691784546b1..4d4c6c2f741 100644
--- a/src/emu/crsshair.h
+++ b/src/emu/crsshair.h
@@ -22,6 +22,36 @@
#define CROSSHAIR_SCREEN_NONE ((const device_config *) 0)
#define CROSSHAIR_SCREEN_ALL ((const device_config *) ~0)
+/* user settings for visibility mode */
+#define CROSSHAIR_VISIBILITY_OFF 0
+#define CROSSHAIR_VISIBILITY_ON 1
+#define CROSSHAIR_VISIBILITY_AUTO 2
+#define CROSSHAIR_VISIBILITY_DEFAULT CROSSHAIR_VISIBILITY_ON
+
+/* range allowed for auto visibility */
+#define CROSSHAIR_VISIBILITY_AUTOTIME_MIN 1 /* do not change without changing formula */
+#define CROSSHAIR_VISIBILITY_AUTOTIME_MAX 50
+#define CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT 15
+
+/* maximum crosshair pic filename size */
+#define CROSSHAIR_PIC_NAME_LENGTH 12
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+/* user-controllable settings for a player */
+typedef struct _crosshair_user_settings crosshair_user_settings;
+struct _crosshair_user_settings
+{
+ UINT8 used; /* is used */
+ UINT8 mode; /* visibility mode */
+ UINT8 auto_time; /* time in seconds to blank crosshair if no movement */
+ char name[CROSSHAIR_PIC_NAME_LENGTH + 1]; /* bitmap name */
+};
+
/***************************************************************************
@@ -40,6 +70,14 @@ void crosshair_toggle(running_machine *machine);
/* sets the screen(s) for a given player's crosshair */
void crosshair_set_screen(running_machine *machine, int player, const device_config *screen);
+/* return TRUE if any crosshairs are used */
+int crosshair_get_usage(running_machine *machine);
+
+/* return the current crosshair settings for the given player */
+void crosshair_get_user_settings(running_machine *machine, UINT8 player, crosshair_user_settings *settings);
+
+/* modify the current crosshair settings for the given player */
+void crosshair_set_user_settings(running_machine *machine, UINT8 player, crosshair_user_settings *settings);
#endif /* __CRSSHAIR_H__ */
diff --git a/src/emu/emuopts.c b/src/emu/emuopts.c
index 4cd69904ead..24d134044dc 100644
--- a/src/emu/emuopts.c
+++ b/src/emu/emuopts.c
@@ -43,6 +43,7 @@ const options_entry mame_core_options[] =
{ "inipath", ".;ini", 0, "path to ini files" },
{ "fontpath", ".", 0, "path to font files" },
{ "cheatpath", "cheat", 0, "path to cheat files" },
+ { "crsshairpath", "crsshair", 0, "path to crosshair files" },
/* output directory options */
{ NULL, NULL, OPTION_HEADER, "CORE OUTPUT DIRECTORY OPTIONS" },
diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h
index 4be2100fefd..b7f57b5a7b8 100644
--- a/src/emu/emuopts.h
+++ b/src/emu/emuopts.h
@@ -45,6 +45,7 @@
#define OPTION_INIPATH "inipath"
#define OPTION_FONTPATH "fontpath"
#define OPTION_CHEATPATH "cheatpath"
+#define OPTION_CRSSHAIRPATH "crsshairpath"
/* core directory options */
#define OPTION_CFG_DIRECTORY "cfg_directory"
diff --git a/src/emu/fileio.h b/src/emu/fileio.h
index fbe58dbbfa7..d0b32355b0c 100644
--- a/src/emu/fileio.h
+++ b/src/emu/fileio.h
@@ -45,6 +45,7 @@
#define SEARCHPATH_INI OPTION_INIPATH
#define SEARCHPATH_FONT OPTION_FONTPATH
#define SEARCHPATH_CHEAT OPTION_CHEATPATH
+#define SEARCHPATH_CRSSHAIRPATH OPTION_CRSSHAIRPATH
#define SEARCHPATH_IMAGE_DIFF OPTION_DIFF_DIRECTORY
#define SEARCHPATH_NVRAM OPTION_NVRAM_DIRECTORY
diff --git a/src/emu/inptport.h b/src/emu/inptport.h
index 9e1b939c716..b8f7007ead7 100644
--- a/src/emu/inptport.h
+++ b/src/emu/inptport.h
@@ -287,7 +287,6 @@ enum
IPT_UI_PASTE,
IPT_UI_SAVE_STATE,
IPT_UI_LOAD_STATE,
- IPT_UI_TOGGLE_CROSSHAIR,
/* additional OSD-specified UI port types (up to 16) */
IPT_OSD_1,
diff --git a/src/emu/inpttype.h b/src/emu/inpttype.h
index 141050b0526..bb2b1f08bb0 100644
--- a/src/emu/inpttype.h
+++ b/src/emu/inpttype.h
@@ -563,7 +563,6 @@ static const input_type_desc core_types[] =
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_DEBUG, "Toggle Debugger", SEQ_DEF_1(KEYCODE_F5) )
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE, "Save State", SEQ_DEF_2(KEYCODE_F7, KEYCODE_LSHIFT) )
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LOAD_STATE, "Load State", SEQ_DEF_3(KEYCODE_F7, SEQCODE_NOT, KEYCODE_LSHIFT) )
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_CROSSHAIR, "Toggle Crosshair", SEQ_DEF_1(KEYCODE_F1) )
INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_1, NULL, SEQ_DEF_0 )
INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_2, NULL, SEQ_DEF_0 )
diff --git a/src/emu/rendlay.c b/src/emu/rendlay.c
index f11c5bf075e..f3b0d0cbf66 100644
--- a/src/emu/rendlay.c
+++ b/src/emu/rendlay.c
@@ -1882,11 +1882,11 @@ static bitmap_t *load_component_bitmap(const char *dirname, const char *file, co
bitmap_t *bitmap;
/* load the basic bitmap */
- bitmap = render_load_png(dirname, file, NULL, hasalpha);
+ bitmap = render_load_png(OPTION_ARTPATH, dirname, file, NULL, hasalpha);
if (bitmap != NULL && alphafile != NULL)
/* load the alpha bitmap if specified */
- if (render_load_png(dirname, alphafile, bitmap, hasalpha) == NULL)
+ if (render_load_png(OPTION_ARTPATH, dirname, alphafile, bitmap, hasalpha) == NULL)
{
bitmap_free(bitmap);
bitmap = NULL;
diff --git a/src/emu/rendutil.c b/src/emu/rendutil.c
index cb7f5eabd68..16e91d9aa2d 100644
--- a/src/emu/rendutil.c
+++ b/src/emu/rendutil.c
@@ -559,7 +559,7 @@ void render_line_to_quad(const render_bounds *bounds, float width, render_bounds
bitmap_t
-------------------------------------------------*/
-bitmap_t *render_load_png(const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha)
+bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha)
{
bitmap_t *bitmap = NULL;
file_error filerr;
@@ -573,7 +573,7 @@ bitmap_t *render_load_png(const char *dirname, const char *filename, bitmap_t *a
fname = astring_dupc(filename);
else
fname = astring_assemble_3(astring_alloc(), dirname, PATH_SEPARATOR, filename);
- filerr = mame_fopen(SEARCHPATH_ARTWORK, astring_c(fname), OPEN_FLAG_READ, &file);
+ filerr = mame_fopen(path, astring_c(fname), OPEN_FLAG_READ, &file);
astring_free(fname);
if (filerr != FILERR_NONE)
return NULL;
diff --git a/src/emu/rendutil.h b/src/emu/rendutil.h
index c43af275df0..279276186d7 100644
--- a/src/emu/rendutil.h
+++ b/src/emu/rendutil.h
@@ -29,7 +29,7 @@ void render_resample_argb_bitmap_hq(void *dest, UINT32 drowpixels, UINT32 dwidth
int render_clip_line(render_bounds *bounds, const render_bounds *clip);
int render_clip_quad(render_bounds *bounds, const render_bounds *clip, render_quad_texuv *texcoords);
void render_line_to_quad(const render_bounds *bounds, float width, render_bounds *bounds0, render_bounds *bounds1);
-bitmap_t *render_load_png(const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha);
+bitmap_t *render_load_png(const char *path, const char *dirname, const char *filename, bitmap_t *alphadest, int *hasalpha);
diff --git a/src/emu/ui.c b/src/emu/ui.c
index efa8c8032b3..c6bad41f5f1 100644
--- a/src/emu/ui.c
+++ b/src/emu/ui.c
@@ -38,23 +38,6 @@
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
@@ -1276,10 +1259,6 @@ static UINT32 handler_ingame(running_machine *machine, UINT32 state)
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))
{
diff --git a/src/emu/uimenu.c b/src/emu/uimenu.c
index fa887449495..20f5e484d3f 100644
--- a/src/emu/uimenu.c
+++ b/src/emu/uimenu.c
@@ -85,6 +85,12 @@ enum
VIDEO_ITEM_VIEW
};
+enum
+{
+ CROSSHAIR_ITEM_VIS = 0,
+ CROSSHAIR_ITEM_PIC,
+ CROSSHAIR_ITEM_AUTO_TIME
+};
/***************************************************************************
@@ -203,6 +209,20 @@ struct _select_game_state
};
+/* internal crosshair menu item data */
+typedef struct _crosshair_item_data crosshair_item_data;
+struct _crosshair_item_data
+{
+ UINT8 type;
+ UINT8 player;
+ UINT8 min, max;
+ UINT8 cur;
+ UINT8 defvalue;
+ char last_name[CROSSHAIR_PIC_NAME_LENGTH + 1];
+ char next_name[CROSSHAIR_PIC_NAME_LENGTH + 1];
+};
+
+
/***************************************************************************
GLOBAL VARIABLES
@@ -281,6 +301,8 @@ static void menu_video_targets(running_machine *machine, ui_menu *menu, void *pa
static void menu_video_targets_populate(running_machine *machine, ui_menu *menu);
static void menu_video_options(running_machine *machine, ui_menu *menu, void *parameter, void *state);
static void menu_video_options_populate(running_machine *machine, ui_menu *menu, render_target *target);
+static void menu_crosshair(running_machine *machine, ui_menu *menu, void *parameter, void *state);
+static void menu_crosshair_populate(running_machine *machine, ui_menu *menu);
static void menu_quit_game(running_machine *machine, ui_menu *menu, void *parameter, void *state);
static void menu_select_game(running_machine *machine, ui_menu *menu, void *parameter, void *state);
static void menu_select_game_populate(running_machine *machine, ui_menu *menu, select_game_state *menustate);
@@ -1489,6 +1511,10 @@ static void menu_main_populate(running_machine *machine, ui_menu *menu, void *st
/* add video options menu */
ui_menu_item_append(menu, "Video Options", NULL, 0, (render_target_get_indexed(1) != NULL) ? (void *)menu_video_targets : (void *)menu_video_options);
+ /* add crosshair options menu */
+ if (crosshair_get_usage(machine))
+ ui_menu_item_append(menu, "Crosshair Options", NULL, 0, menu_crosshair);
+
/* add cheat menu */
if (options_get_bool(mame_options(), OPTION_CHEAT) && cheat_get_next_menu_entry(machine, NULL, NULL, NULL, NULL) != NULL)
ui_menu_item_append(menu, "Cheat", NULL, 0, (void *)menu_cheat);
@@ -3030,6 +3056,271 @@ static void menu_video_options_populate(running_machine *machine, ui_menu *menu,
/*-------------------------------------------------
+ menu_crosshair - handle the crosshair settings
+ menu
+-------------------------------------------------*/
+
+static void menu_crosshair(running_machine *machine, ui_menu *menu, void *parameter, void *state)
+{
+ const ui_menu_event *event;
+
+ /* if the menu isn't built, populate now */
+ if (!ui_menu_populated(menu))
+ menu_crosshair_populate(machine, menu);
+
+ /* process the menu */
+ event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
+
+ /* handle events */
+ if (event != NULL && event->itemref != NULL)
+ {
+ crosshair_user_settings settings;
+ crosshair_item_data *data = event->itemref;
+ int changed = FALSE;
+ int set_def = FALSE;
+ int newval = data->cur;
+
+ /* retreive the user settings */
+ crosshair_get_user_settings(machine, data->player, &settings);
+
+ switch (event->iptkey)
+ {
+ /* if selected, reset to default value */
+ case IPT_UI_SELECT:
+ newval = data->defvalue;
+ set_def = TRUE;
+ break;
+
+ /* left decrements */
+ case IPT_UI_LEFT:
+ newval -= input_code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ /* right increments */
+ case IPT_UI_RIGHT:
+ newval += input_code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+ }
+
+ /* clamp to range */
+ if (newval < data->min)
+ newval = data->min;
+ if (newval > data->max)
+ newval = data->max;
+
+ /* if things changed, update */
+ if (newval != data->cur)
+ {
+ switch (data->type)
+ {
+ /* visibility state */
+ case CROSSHAIR_ITEM_VIS:
+ settings.mode = newval;
+ changed = TRUE;
+ break;
+
+ /* auto time */
+ case CROSSHAIR_ITEM_AUTO_TIME:
+ settings.auto_time = newval;
+ changed = TRUE;
+ break;
+ }
+ }
+
+ /* crosshair graphic name */
+ if (data->type == CROSSHAIR_ITEM_PIC)
+ {
+ if (event->iptkey == IPT_UI_SELECT)
+ {
+ /* clear the name string to reset to default crosshair */
+ settings.name[0] = 0;
+ changed = TRUE;
+ }
+ else if (event->iptkey == IPT_UI_LEFT)
+ {
+ strcpy(settings.name, data->last_name);
+ changed = TRUE;
+ }
+ else if (event->iptkey == IPT_UI_RIGHT)
+ {
+ strcpy(settings.name, data->next_name);
+ changed = TRUE;
+ }
+ }
+
+ if (changed)
+ {
+ /* save the user settings */
+ crosshair_set_user_settings(machine, data->player, &settings);
+
+ /* rebuild the menu */
+ ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_crosshair_populate - populate the
+ crosshair settings menu
+-------------------------------------------------*/
+
+static void menu_crosshair_populate(running_machine *machine, ui_menu *menu)
+{
+ crosshair_user_settings settings;
+ crosshair_item_data *data;
+ char temp_text[16];
+ int player;
+ UINT8 use_auto = FALSE;
+ UINT32 flags = 0;
+ mame_path *path;
+
+ /* loop over player and add the manual items */
+ for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ /* get the user settings */
+ crosshair_get_user_settings(machine, player, &settings);
+
+ /* add menu items for usable crosshairs */
+ if (settings.used)
+ {
+ /* Make sure to keep these matched to the CROSSHAIR_VISIBILITY_xxx types */
+ static const char *const vis_text[] = { "Off", "On", "Auto" };
+
+ /* track if we need the auto time menu */
+ if (settings.mode == CROSSHAIR_VISIBILITY_AUTO) use_auto = TRUE;
+
+ /* CROSSHAIR_ITEM_VIS - allocate a data item and fill it */
+ data = ui_menu_pool_alloc(menu, sizeof(*data));
+ data->type = CROSSHAIR_ITEM_VIS;
+ data->player = player;
+ data->min = CROSSHAIR_VISIBILITY_OFF;
+ data->max = CROSSHAIR_VISIBILITY_AUTO;
+ data->defvalue = CROSSHAIR_VISIBILITY_DEFAULT;
+ data->cur = settings.mode;
+
+ /* put on arrows */
+ if (data->cur > data->min)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (data->cur < data->max)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* add CROSSHAIR_ITEM_VIS menu */
+ sprintf(temp_text, "P%d Visibility", player + 1);
+ ui_menu_item_append(menu, temp_text, vis_text[settings.mode], flags, data);
+
+ /* CROSSHAIR_ITEM_PIC - allocate a data item and fill it */
+ data = ui_menu_pool_alloc(menu, sizeof(*data));
+ data->type = CROSSHAIR_ITEM_PIC;
+ data->player = player;
+ data->last_name[0] = 0;
+ /* other data item not used by this menu */
+
+ /* search for crosshair graphics */
+
+ /* open a path to the crosshairs */
+ path = mame_openpath(mame_options(), OPTION_CRSSHAIRPATH);
+ if (path != NULL)
+ {
+ const osd_directory_entry *dir;
+
+ /* reset search flags */
+ int using_default = FALSE;
+ int finished = FALSE;
+ int found = FALSE;
+
+ /* if we are using the default, then we just need to find the first in the list */
+ if (strlen(settings.name) == 0)
+ using_default = TRUE;
+
+ /* look for the current name, then remember the name before */
+ /* and find the next name */
+ while (((dir = mame_readpath(path)) != NULL) && !finished)
+ {
+ int length = strlen(dir->name);
+
+ /* look for files ending in .png with a name not larger then 9 chars*/
+ if ((length > 4) && (length <= CROSSHAIR_PIC_NAME_LENGTH + 4) &&
+ tolower(dir->name[length - 4] == '.') &&
+ tolower(dir->name[length - 3] == 'p') &&
+ tolower(dir->name[length - 2] == 'n') &&
+ tolower(dir->name[length - 1] == 'g'))
+
+ {
+ /* remove .png from length */
+ length -= 4;
+
+ if (found || using_default)
+ {
+ /* get the next name */
+ strncpy(data->next_name, dir->name, length);
+ data->next_name[length] = 0;
+ finished = TRUE;
+ }
+ else if (!strncmp(dir->name, settings.name, length))
+ {
+ /* we found the current name */
+ /* so loop once more to find the next name */
+ found = TRUE;
+ }
+ else
+ /* remember last name */
+ /* we will do it here in case files get added to the directory */
+ {
+ strncpy(data->last_name, dir->name, length);
+ data->last_name[length] = 0;
+ }
+ }
+ }
+ /* if name not found then next item is DEFAULT */
+ if (!found && !using_default)
+ {
+ data->next_name[0] = 0;
+ finished = TRUE;
+ }
+ /* setup the selection flags */
+ flags = 0;
+ if (finished)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ if (found)
+ flags |= MENU_FLAG_LEFT_ARROW;
+
+ /* add CROSSHAIR_ITEM_PIC menu */
+ sprintf(temp_text, "P%d Crosshair", player + 1);
+ ui_menu_item_append(menu, temp_text, using_default ? "DEFAULT" : settings.name, flags, data);
+ }
+ }
+ }
+ if (use_auto)
+ {
+ /* any player can be used to get the autotime */
+ crosshair_get_user_settings(machine, 0, &settings);
+
+ /* CROSSHAIR_ITEM_AUTO_TIME - allocate a data item and fill it */
+ data = ui_menu_pool_alloc(menu, sizeof(*data));
+ data->type = CROSSHAIR_ITEM_AUTO_TIME;
+ data->min = CROSSHAIR_VISIBILITY_AUTOTIME_MIN;
+ data->max = CROSSHAIR_VISIBILITY_AUTOTIME_MAX;
+ data->defvalue = CROSSHAIR_VISIBILITY_AUTOTIME_DEFAULT;
+ data->cur = settings.auto_time;
+
+ /* put on arrows in visible menu */
+ if (data->cur > data->min)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (data->cur < data->max)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* add CROSSHAIR_ITEM_AUTO_TIME menu */
+ sprintf(temp_text, "%d", settings.auto_time);
+ ui_menu_item_append(menu, "Visible Delay", temp_text, flags, data);
+ }
+// else
+// /* leave a blank filler line when not in auto time so size does not rescale */
+// ui_menu_item_append(menu, "", "", NULL, NULL);
+}
+
+
+/*-------------------------------------------------
menu_quit_game - handle the "menu" for
quitting the game
-------------------------------------------------*/
diff --git a/src/osd/windows/drawd3d.c b/src/osd/windows/drawd3d.c
index 99f0bff8e14..570822ef5bd 100644
--- a/src/osd/windows/drawd3d.c
+++ b/src/osd/windows/drawd3d.c
@@ -506,11 +506,11 @@ static int drawd3d_window_init(win_window_info *window)
// experimental: load a PNG to use for vector rendering; it is treated
// as a brightness map
- d3d->vector_bitmap = render_load_png(NULL, "vector.png", NULL, NULL);
+ d3d->vector_bitmap = render_load_png(OPTION_ARTPATH, NULL, "vector.png", NULL, NULL);
if (d3d->vector_bitmap != NULL)
{
bitmap_fill(d3d->vector_bitmap, NULL, MAKE_ARGB(0xff,0xff,0xff,0xff));
- d3d->vector_bitmap = render_load_png(NULL, "vector.png", d3d->vector_bitmap, NULL);
+ d3d->vector_bitmap = render_load_png(OPTION_ARTPATH, NULL, "vector.png", d3d->vector_bitmap, NULL);
}
// configure the adapter for the mode we want
diff --git a/src/osd/windows/video.c b/src/osd/windows/video.c
index 38c8b837a35..49fe4475268 100644
--- a/src/osd/windows/video.c
+++ b/src/osd/windows/video.c
@@ -450,7 +450,7 @@ static void load_effect_overlay(running_machine *machine, const char *filename)
strcpy(dest, ".png");
// load the file
- effect_bitmap = render_load_png(NULL, tempstr, NULL, NULL);
+ effect_bitmap = render_load_png(OPTION_ARTPATH, NULL, tempstr, NULL, NULL);
if (effect_bitmap == NULL)
{
mame_printf_error("Unable to load PNG file '%s'\n", tempstr);