summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitattributes6
-rw-r--r--src/emu/cpu/m68000/m68000.h1
-rw-r--r--src/emu/cpu/m68000/m68kcpu.c25
-rw-r--r--src/emu/debugint/debugint.c66
-rw-r--r--src/emu/dinetwork.c6
-rw-r--r--src/emu/dinetwork.h2
-rw-r--r--src/emu/drivers/empty.c1
-rw-r--r--src/emu/emu.h3
-rw-r--r--src/emu/emu.mak2
-rw-r--r--src/emu/imagedev/cassette.c4
-rw-r--r--src/emu/imagedev/floppy.c4
-rw-r--r--src/emu/machine.c2
-rw-r--r--src/emu/machine/mc68901.c10
-rw-r--r--src/emu/network.c91
-rw-r--r--src/emu/network.h23
-rw-r--r--src/emu/ui.c21
-rw-r--r--src/emu/uiimage.c660
-rw-r--r--src/emu/uiimage.h114
-rw-r--r--src/emu/uimain.c2762
-rw-r--r--src/emu/uimain.h367
-rw-r--r--src/emu/uimenu.c3531
-rw-r--r--src/emu/uimenu.h145
-rw-r--r--src/emu/uiswlist.c313
-rw-r--r--src/emu/uiswlist.h57
-rw-r--r--src/lib/formats/flopimg.c48
-rw-r--r--src/lib/formats/flopimg.h19
-rw-r--r--src/lib/formats/pasti_dsk.c615
-rw-r--r--src/lib/formats/pasti_dsk.h62
-rw-r--r--src/lib/lib.mak1
-rw-r--r--src/osd/osdnet.c20
-rw-r--r--src/osd/osdnet.h21
-rw-r--r--src/osd/sdl/netdev_pcap.c2
-rw-r--r--src/osd/sdl/netdev_tap.c2
-rw-r--r--src/osd/windows/netdev_pcap.c2
34 files changed, 5058 insertions, 3950 deletions
diff --git a/.gitattributes b/.gitattributes
index 3099d0ec1bb..c6a0c94c7df 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1005,6 +1005,8 @@ src/emu/mconfig.h svneol=native#text/plain
src/emu/memconv.h svneol=native#text/plain
src/emu/memory.c svneol=native#text/plain
src/emu/memory.h svneol=native#text/plain
+src/emu/network.c svneol=native#text/plain
+src/emu/network.h svneol=native#text/plain
src/emu/output.c svneol=native#text/plain
src/emu/output.h svneol=native#text/plain
src/emu/profiler.c svneol=native#text/plain
@@ -1289,6 +1291,8 @@ src/emu/uiimage.c svneol=native#text/plain
src/emu/uiimage.h svneol=native#text/plain
src/emu/uiinput.c svneol=native#text/plain
src/emu/uiinput.h svneol=native#text/plain
+src/emu/uimain.c svneol=native#text/plain
+src/emu/uimain.h svneol=native#text/plain
src/emu/uimenu.c svneol=native#text/plain
src/emu/uimenu.h svneol=native#text/plain
src/emu/uismall.png -text svneol=unset#image/png
@@ -1506,6 +1510,8 @@ src/lib/formats/oric_tap.c svneol=native#text/plain
src/lib/formats/oric_tap.h svneol=native#text/plain
src/lib/formats/p6001_cas.c svneol=native#text/plain
src/lib/formats/p6001_cas.h svneol=native#text/plain
+src/lib/formats/pasti_dsk.c svneol=native#text/plain
+src/lib/formats/pasti_dsk.h svneol=native#text/plain
src/lib/formats/pc_dsk.c svneol=native#text/plain
src/lib/formats/pc_dsk.h svneol=native#text/plain
src/lib/formats/pmd_pmd.c svneol=native#text/plain
diff --git a/src/emu/cpu/m68000/m68000.h b/src/emu/cpu/m68000/m68000.h
index 7013d465aa6..ff8d08c8a58 100644
--- a/src/emu/cpu/m68000/m68000.h
+++ b/src/emu/cpu/m68000/m68000.h
@@ -94,6 +94,7 @@ typedef int (*m68k_tas_func)(device_t *device);
DECLARE_LEGACY_CPU_DEVICE(M68000, m68000);
DECLARE_LEGACY_CPU_DEVICE(M68008, m68008);
+DECLARE_LEGACY_CPU_DEVICE(M68008PLCC, m68008plcc);
DECLARE_LEGACY_CPU_DEVICE(M68010, m68010);
DECLARE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
DECLARE_LEGACY_CPU_DEVICE(M68020, m68020);
diff --git a/src/emu/cpu/m68000/m68kcpu.c b/src/emu/cpu/m68000/m68kcpu.c
index d4ab1b08ab1..679a4a3b974 100644
--- a/src/emu/cpu/m68000/m68kcpu.c
+++ b/src/emu/cpu/m68000/m68kcpu.c
@@ -644,6 +644,7 @@ INLINE m68ki_cpu_core *get_safe_token(device_t *device)
assert(device != NULL);
assert(device->type() == M68000 ||
device->type() == M68008 ||
+ device->type() == M68008PLCC ||
device->type() == M68010 ||
device->type() == M68EC020 ||
device->type() == M68020 ||
@@ -1857,8 +1858,26 @@ CPU_GET_INFO( m68008 )
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
- case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
- case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 22; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 20; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68008); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "68008"); break;
+
+ default: CPU_GET_INFO_CALL(m68k); break;
+ }
+}
+
+CPU_GET_INFO( m68008plcc )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 22; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(m68008); break;
@@ -2506,6 +2525,7 @@ CPU_GET_INFO( mcf5206e )
DEFINE_LEGACY_CPU_DEVICE(M68000, m68000);
DEFINE_LEGACY_CPU_DEVICE(M68008, m68008);
+DEFINE_LEGACY_CPU_DEVICE(M68008PLCC, m68008plcc);
DEFINE_LEGACY_CPU_DEVICE(M68010, m68010);
DEFINE_LEGACY_CPU_DEVICE(M68EC020, m68ec020);
DEFINE_LEGACY_CPU_DEVICE(M68020, m68020);
@@ -2519,4 +2539,3 @@ DEFINE_LEGACY_CPU_DEVICE(M68040, m68040);
DEFINE_LEGACY_CPU_DEVICE(SCC68070, scc68070);
DEFINE_LEGACY_CPU_DEVICE(M68340, m68340);
DEFINE_LEGACY_CPU_DEVICE(MCF5206E, mcf5206e);
-
diff --git a/src/emu/debugint/debugint.c b/src/emu/debugint/debugint.c
index f02ef141acb..cd1df038cbc 100644
--- a/src/emu/debugint/debugint.c
+++ b/src/emu/debugint/debugint.c
@@ -1159,15 +1159,23 @@ static void render_editor(DView_edit *editor)
menu_main_populate - populate the main menu
-------------------------------------------------*/
+class ui_menu_what_the_hell : public ui_menu {
+public:
+ ui_menu_what_the_hell(running_machine &machine, render_container *container) : ui_menu(machine, container) {}
+ virtual ~ui_menu_what_the_hell() {}
+ virtual void populate() {}
+ virtual void handle() {}
+};
+
static void CreateMainMenu(running_machine &machine)
{
const char *subtext = "";
int rc;
astring title;
- if (menu != NULL)
- ui_menu_free(menu);
- menu = ui_menu_alloc(machine, &machine.render().ui_container(),NULL,NULL);
+ if (menu)
+ auto_free(machine, menu);
+ menu = auto_alloc_clear(machine, ui_menu_what_the_hell(machine, &machine.render().ui_container()));
switch (focus_view->type)
{
@@ -1188,8 +1196,8 @@ static void CreateMainMenu(running_machine &machine)
break;
}
- ui_menu_item_append(menu, title.cat(focus_view->title), NULL, MENU_FLAG_DISABLE, NULL);
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ menu->item_append(title.cat(focus_view->title), NULL, MENU_FLAG_DISABLE, NULL);
+ menu->item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
switch (focus_view->type)
{
@@ -1202,38 +1210,38 @@ static void CreateMainMenu(running_machine &machine)
case DASM_RIGHTCOL_ENCRYPTED: subtext = "Enc Opcodes"; break;
case DASM_RIGHTCOL_COMMENTS: subtext = "Comments"; break;
}
- ui_menu_item_append(menu, "View", subtext, MENU_FLAG_RIGHT_ARROW, (void *)on_view_opcodes_activate);
- ui_menu_item_append(menu, "Run to cursor", NULL, 0, (void *)on_run_to_cursor_activate);
+ menu->item_append("View", subtext, MENU_FLAG_RIGHT_ARROW, (void *)on_view_opcodes_activate);
+ menu->item_append("Run to cursor", NULL, 0, (void *)on_run_to_cursor_activate);
if (!dview_is_state(focus_view, VIEW_STATE_FOLLOW_CPU))
{
- ui_menu_item_append(menu, "CPU", focus_view->view->source()->name(), MENU_FLAG_RIGHT_ARROW, (void *)on_disasm_cpu_activate);
+ menu->item_append("CPU", focus_view->view->source()->name(), MENU_FLAG_RIGHT_ARROW, (void *)on_disasm_cpu_activate);
}
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ menu->item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
break;
}
}
/* add input menu items */
- ui_menu_item_append(menu, "New Memory Window", NULL, 0, (void *)on_memory_window_activate);
- ui_menu_item_append(menu, "New Disassembly Window", NULL, 0, (void *)on_disassembly_window_activate);
- ui_menu_item_append(menu, "New Error Log Window", NULL, 0, (void *)on_log_window_activate);
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
- ui_menu_item_append(menu, "Run", NULL, 0, (void *)on_run_activate);
- ui_menu_item_append(menu, "Run to Next CPU", NULL, 0, (void *)on_run_cpu_activate);
- ui_menu_item_append(menu, "Run until Next Interrupt on This CPU", NULL, 0, (void *)on_run_irq_activate);
- ui_menu_item_append(menu, "Run until Next VBLANK", NULL, 0, (void *)on_run_vbl_activate);
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
- ui_menu_item_append(menu, "Step Into", NULL, 0, (void *)on_step_into_activate);
- ui_menu_item_append(menu, "Step Over", NULL, 0, (void *)on_step_over_activate);
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
- ui_menu_item_append(menu, "Soft Reset", NULL, 0, (void *)on_soft_reset_activate);
- ui_menu_item_append(menu, "Hard Reset", NULL, 0, (void *)on_hard_reset_activate);
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ menu->item_append("New Memory Window", NULL, 0, (void *)on_memory_window_activate);
+ menu->item_append("New Disassembly Window", NULL, 0, (void *)on_disassembly_window_activate);
+ menu->item_append("New Error Log Window", NULL, 0, (void *)on_log_window_activate);
+ menu->item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ menu->item_append("Run", NULL, 0, (void *)on_run_activate);
+ menu->item_append("Run to Next CPU", NULL, 0, (void *)on_run_cpu_activate);
+ menu->item_append("Run until Next Interrupt on This CPU", NULL, 0, (void *)on_run_irq_activate);
+ menu->item_append("Run until Next VBLANK", NULL, 0, (void *)on_run_vbl_activate);
+ menu->item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ menu->item_append("Step Into", NULL, 0, (void *)on_step_into_activate);
+ menu->item_append("Step Over", NULL, 0, (void *)on_step_over_activate);
+ menu->item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ menu->item_append("Soft Reset", NULL, 0, (void *)on_soft_reset_activate);
+ menu->item_append("Hard Reset", NULL, 0, (void *)on_hard_reset_activate);
+ menu->item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
if (!dview_is_state(focus_view, VIEW_STATE_FOLLOW_CPU))
- ui_menu_item_append(menu, "Close Window", NULL, 0, (void *)on_close_activate);
- ui_menu_item_append(menu, "Exit", NULL, 0, (void *)on_exit_activate);
+ menu->item_append("Close Window", NULL, 0, (void *)on_close_activate);
+ menu->item_append("Exit", NULL, 0, (void *)on_exit_activate);
}
static int map_point(DView *dv, INT32 target_x, INT32 target_y, INT32 *mapped_x, INT32 *mapped_y)
@@ -1355,10 +1363,10 @@ static void handle_menus(running_machine &machine)
if (menu != NULL)
{
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ event = menu->process(0);
if (event != NULL && (event->iptkey == IPT_UI_SELECT || (event->iptkey == IPT_UI_RIGHT)))
{
- //ui_menu_free(menu);
+ //auto_free(machine, menu);
//menu = NULL;
((void (*)(DView *, const ui_menu_event *)) event->itemref)(focus_view, event);
//ui_menu_stack_push(ui_menu_alloc(machine, menu->container, (ui_menu_handler_func)event->itemref, NULL));
@@ -1366,7 +1374,7 @@ static void handle_menus(running_machine &machine)
}
else if (ui_input_pressed(machine, IPT_UI_CONFIGURE))
{
- ui_menu_free(menu);
+ auto_free(machine, menu);
menu = NULL;
}
}
diff --git a/src/emu/dinetwork.c b/src/emu/dinetwork.c
index eea164177e8..fa95739e038 100644
--- a/src/emu/dinetwork.c
+++ b/src/emu/dinetwork.c
@@ -8,6 +8,7 @@ device_network_interface::device_network_interface(const machine_config &mconfig
m_dev = NULL;
m_bandwidth = bandwidth;
set_mac("\0\0\0\0\0\0");
+ m_intf = 0;
}
device_network_interface::~device_network_interface()
@@ -46,6 +47,9 @@ void device_network_interface::set_mac(const char *mac)
void device_network_interface::set_interface(int id)
{
m_dev = open_netdev(id, this, (int)(m_bandwidth*1000000/8.0/1500));
- if(!m_dev)
+ if(!m_dev) {
logerror("Network interface %d not found\n", id);
+ id = -1;
+ }
+ m_intf = id;
}
diff --git a/src/emu/dinetwork.h b/src/emu/dinetwork.h
index f7f2e38218d..592853af78a 100644
--- a/src/emu/dinetwork.h
+++ b/src/emu/dinetwork.h
@@ -15,6 +15,7 @@ public:
const char *get_mac() { return m_mac; }
bool get_promisc() { return m_promisc; }
+ int get_interface() { return m_intf; }
int send(UINT8 *buf, int len);
virtual void recv_cb(UINT8 *buf, int len);
@@ -25,5 +26,6 @@ protected:
char m_mac[6];
float m_bandwidth;
class netdev *m_dev;
+ int m_intf;
};
#endif
diff --git a/src/emu/drivers/empty.c b/src/emu/drivers/empty.c
index d4ce7079f31..d89e8b84e43 100644
--- a/src/emu/drivers/empty.c
+++ b/src/emu/drivers/empty.c
@@ -12,6 +12,7 @@
#include "emu.h"
#include "render.h"
#include "uimenu.h"
+#include "uimain.h"
/*************************************
diff --git a/src/emu/emu.h b/src/emu/emu.h
index 7056c152808..5135b990f7b 100644
--- a/src/emu/emu.h
+++ b/src/emu/emu.h
@@ -114,6 +114,9 @@ typedef device_t * (*machine_config_constructor)(machine_config &config, device_
#include "softlist.h"
#include "image.h"
+// networking
+#include "network.h"
+
// the running machine
#include "machine.h"
#include "mame.h"
diff --git a/src/emu/emu.mak b/src/emu/emu.mak
index e77fe642d78..62d9517b973 100644
--- a/src/emu/emu.mak
+++ b/src/emu/emu.mak
@@ -86,6 +86,7 @@ EMUOBJS = \
$(EMUOBJ)/machine.o \
$(EMUOBJ)/mconfig.o \
$(EMUOBJ)/memory.o \
+ $(EMUOBJ)/network.o \
$(EMUOBJ)/output.o \
$(EMUOBJ)/render.o \
$(EMUOBJ)/rendfont.o \
@@ -105,6 +106,7 @@ EMUOBJS = \
$(EMUOBJ)/uiimage.o \
$(EMUOBJ)/uiinput.o \
$(EMUOBJ)/uiswlist.o \
+ $(EMUOBJ)/uimain.o \
$(EMUOBJ)/uimenu.o \
$(EMUOBJ)/validity.o \
$(EMUOBJ)/video.o \
diff --git a/src/emu/imagedev/cassette.c b/src/emu/imagedev/cassette.c
index e2061814d12..e99aa1ec9d0 100644
--- a/src/emu/imagedev/cassette.c
+++ b/src/emu/imagedev/cassette.c
@@ -275,10 +275,10 @@ bool cassette_image_device::call_load()
} else {
astring fname = astring(m_mame_file->filename());
int loc = fname.rchr(0,'.');
- if (loc!=-1) {
+ if (loc!=-1) {
extension = fname.substr(loc + 1,fname.len()-loc).cstr();
} else {
- extension = "";
+ extension = "";
}
}
err = cassette_open_choices((void *)image, &image_ioprocs, extension, m_formats, cassette_flags, &m_cassette);
diff --git a/src/emu/imagedev/floppy.c b/src/emu/imagedev/floppy.c
index d977fbf91a1..fba69efa598 100644
--- a/src/emu/imagedev/floppy.c
+++ b/src/emu/imagedev/floppy.c
@@ -392,6 +392,8 @@ void floppy_image_device::write_flux(attotime start, attotime end, int transitio
index = find_index(start_pos, buf, cells);
else {
index = 0;
+ image->set_track_size(cyl, ss, 1);
+ buf = image->get_buffer(cyl, ss);
buf[cells++] = floppy_image::MG_N | 200000000;
}
@@ -405,6 +407,8 @@ void floppy_image_device::write_flux(attotime start, attotime end, int transitio
UINT32 pos = start_pos;
int ti = 0;
while(pos != end_pos) {
+ if(image->get_track_size(cyl, ss) < cells+10)
+ image->set_track_size(cyl, ss, cells+200);
UINT32 next_pos;
if(ti != transition_count)
next_pos = trans_pos[ti++];
diff --git a/src/emu/machine.c b/src/emu/machine.c
index ce4a2ea9e19..4c8ada75b87 100644
--- a/src/emu/machine.c
+++ b/src/emu/machine.c
@@ -111,6 +111,7 @@
#include "cheat.h"
#include "ui.h"
#include "uimenu.h"
+#include "uimain.h"
#include "uiinput.h"
#include "crsshair.h"
#include "validity.h"
@@ -307,6 +308,7 @@ void running_machine::start()
image_init(*this);
tilemap_init(*this);
crosshair_init(*this);
+ network_init(*this);
// initialize the debugger
if ((debug_flags & DEBUG_FLAG_ENABLED) != 0)
diff --git a/src/emu/machine/mc68901.c b/src/emu/machine/mc68901.c
index 186b705e25b..b8bbe3517c7 100644
--- a/src/emu/machine/mc68901.c
+++ b/src/emu/machine/mc68901.c
@@ -19,18 +19,22 @@
However the fact that they indeed happen in the ST is quite interesting.
The MFP will generate a spurious interrupt if interrupts are disabled (by changing the IERA/IERB registers)
- at the ???precise point???. The precise point would be after the system (but not necessarily the CPU, see below)
+ at the 'precise point'. The precise point would be after the system (but not necessarily the CPU, see below)
triggered an MFP interrupt, and before the CPU drives the interrupt acknowledge cycle.
- If the MFP was connected directly to the CPU, spurious interrupts probably couldn???t happen. However in the
+ If the MFP was connected directly to the CPU, spurious interrupts probably couldn't happen. However in the
ST, GLUE seats in the middle and handles all the interrupt timing. It is possible that GLUE introduces a
delay between detecting a change in the MFP interrupt request signal and actually propagating the change to
the CPU IPL signals (it is even possible that GLUE make some kind of latching). This would create a window
- long enough for the ???precise point??? described above.
+ long enough for the 'precise point' described above.
"yes, the spurious interrupt occurs when i mask a timer. i did not notice an occurance of the SPI when changing data and control registers.
if i kill interrupts with the status reg before masking the timer interrupt, then the SPI occurs as soon as the status register is set to re-enable interrupts."
+ Well, more experiments show that it's somewhat incorrect, and
+ the GLUE is essentially invisible w.r.t IPL. The CPU and the
+ MFP manage to add the delays all by themselves.
+
- divide serial clock by 16
- synchronous mode
- 1.5/2 stop bits
diff --git a/src/emu/network.c b/src/emu/network.c
new file mode 100644
index 00000000000..a0581350f25
--- /dev/null
+++ b/src/emu/network.c
@@ -0,0 +1,91 @@
+/***************************************************************************
+
+ network.c
+
+ Core network functions and definitions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+#include <ctype.h>
+
+#include "emu.h"
+#include "emuopts.h"
+#include "network.h"
+#include "config.h"
+#include "xmlfile.h"
+
+/***************************************************************************
+ INITIALIZATION HELPERS
+***************************************************************************/
+
+static void network_load(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ xml_data_node *node;
+ device_network_interface *network = NULL;
+ if ((config_type == CONFIG_TYPE_GAME) && (parentnode != NULL))
+ {
+ for (node = xml_get_sibling(parentnode->child, "device"); node; node = xml_get_sibling(node->next, "device"))
+ {
+ const char *tag = xml_get_attribute_string(node, "tag", NULL);
+
+ if ((tag != NULL) && (tag[0] != '\0'))
+ {
+ for (bool gotone = machine.devicelist().first(network); gotone; gotone = network->next(network))
+ {
+ if (!strcmp(tag, network->device().tag())) {
+ int interface = xml_get_attribute_int(node, "interface", 0);
+ network->set_interface(interface);
+ const char *mac_addr = xml_get_attribute_string(node, "mac", NULL);
+ if (mac_addr != NULL && strlen(mac_addr)==17) {
+ char mac[7];
+ unsigned int mac_num[6];
+ sscanf (mac_addr,"%02x:%02x:%02x:%02x:%02x:%02x",&mac_num[0],&mac_num[1],&mac_num[2],&mac_num[3],&mac_num[4],&mac_num[5]);
+ for (int i=0;i<6;i++) mac[i]=mac_num[i];
+ network->set_mac(mac);
+ }
+
+ }
+ }
+ }
+ }
+ }
+}
+
+static void network_save(running_machine &machine, int config_type, xml_data_node *parentnode)
+{
+ xml_data_node *node;
+ device_network_interface *network = NULL;
+
+ /* only care about game-specific data */
+ if (config_type == CONFIG_TYPE_GAME)
+ {
+ for (bool gotone = machine.devicelist().first(network); gotone; gotone = network->next(network))
+ {
+ node = xml_add_child(parentnode, "device", NULL);
+ if (node != NULL)
+ {
+ xml_set_attribute(node, "tag", network->device().tag());
+ xml_set_attribute_int(node, "interface", network->get_interface());
+ const char *mac = network->get_mac();
+ char mac_addr[6*3];
+ sprintf(mac_addr,"%02x:%02x:%02x:%02x:%02x:%02x",(UINT8)mac[0],(UINT8)mac[1],(UINT8)mac[2],(UINT8)mac[3],(UINT8)mac[4],(UINT8)mac[5]);
+ xml_set_attribute(node, "mac", mac_addr);
+ }
+ }
+ }
+}
+
+/***************************************************************************
+ INITIALIZATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ network_init - start up the network system
+-------------------------------------------------*/
+
+void network_init(running_machine &machine)
+{
+ config_register(machine, "network", config_saveload_delegate(FUNC(network_load), &machine), config_saveload_delegate(FUNC(network_save), &machine));
+}
diff --git a/src/emu/network.h b/src/emu/network.h
new file mode 100644
index 00000000000..a52bf73b621
--- /dev/null
+++ b/src/emu/network.h
@@ -0,0 +1,23 @@
+/***************************************************************************
+
+ network.h
+
+ Core network interface functions and definitions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __NETWORK_H__
+#define __NETWORK_H__
+
+void network_init(running_machine &machine);
+
+#endif /* __NETWORK_H__ */
diff --git a/src/emu/ui.c b/src/emu/ui.c
index 46e9b8fb0fe..fcd24a90c6e 100644
--- a/src/emu/ui.c
+++ b/src/emu/ui.c
@@ -20,6 +20,7 @@
#include "ui.h"
#include "uiinput.h"
#include "uimenu.h"
+#include "uimain.h"
#include "uigfx.h"
#include <ctype.h>
@@ -241,7 +242,7 @@ int ui_init(running_machine &machine)
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ui_exit), &machine));
/* initialize the other UI bits */
- ui_menu_init(machine);
+ ui_menu::init(machine);
ui_gfx_init(machine);
/* reset globals */
@@ -289,7 +290,7 @@ int ui_display_startup_screens(running_machine &machine, int first_time, int sho
/* loop over states */
ui_set_handler(handler_ingame, 0);
- for (state = 0; state < maxstate && !machine.scheduled_event_pending() && !ui_menu_is_force_game_select(); state++)
+ for (state = 0; state < maxstate && !machine.scheduled_event_pending() && !ui_menu::stack_has_special_main_menu(); state++)
{
/* default to standard colors */
messagebox_backcolor = UI_BACKGROUND_COLOR;
@@ -324,7 +325,7 @@ int ui_display_startup_screens(running_machine &machine, int first_time, int sho
while (machine.input().poll_switches() != INPUT_CODE_INVALID) ;
/* loop while we have a handler */
- while (ui_handler_callback != handler_ingame && !machine.scheduled_event_pending() && !ui_menu_is_force_game_select())
+ while (ui_handler_callback != handler_ingame && !machine.scheduled_event_pending() && !ui_menu::stack_has_special_main_menu())
machine.video().frame_update();
/* clear the handler and force an update */
@@ -333,8 +334,8 @@ int ui_display_startup_screens(running_machine &machine, int first_time, int sho
}
/* 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);
+ if (ui_menu::stack_has_special_main_menu())
+ ui_set_handler(ui_menu::ui_handler, 0);
return 0;
}
@@ -377,7 +378,7 @@ void ui_update_and_render(running_machine &machine, render_container *container)
if (machine.phase() >= MACHINE_PHASE_RESET && (single_step || machine.paused()))
{
int alpha = (1.0f - machine.options().pause_brightness()) * 255.0f;
- if (ui_menu_is_force_game_select())
+ if (ui_menu::stack_has_special_main_menu())
alpha = 255;
if (alpha > 255)
alpha = 255;
@@ -856,7 +857,7 @@ int ui_get_show_profiler(void)
void ui_show_menu(void)
{
- ui_set_handler(ui_menu_ui_handler, 0);
+ ui_set_handler(ui_menu::ui_handler, 0);
}
@@ -867,7 +868,7 @@ void ui_show_menu(void)
int ui_is_menu_active(void)
{
- return (ui_handler_callback == ui_menu_ui_handler);
+ return (ui_handler_callback == ui_menu::ui_handler);
}
@@ -1380,11 +1381,11 @@ static UINT32 handler_ingame(running_machine &machine, render_container *contain
/* turn on menus if requested */
if (ui_input_pressed(machine, IPT_UI_CONFIGURE))
- return ui_set_handler(ui_menu_ui_handler, 0);
+ 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, 1);
+ return ui_set_handler(ui_menu_sliders::ui_handler, 1);
/* handle a reset request */
if (ui_input_pressed(machine, IPT_UI_RESET_MACHINE))
diff --git a/src/emu/uiimage.c b/src/emu/uiimage.c
index a140f8bde18..6af5e7f997f 100644
--- a/src/emu/uiimage.c
+++ b/src/emu/uiimage.c
@@ -22,6 +22,7 @@
#include "ui.h"
#include "uimenu.h"
#include "uiswlist.h"
+#include "uiimage.h"
#include "zippath.h"
#include "unicode.h"
#include "imagedev/cassette.h"
@@ -47,79 +48,6 @@
#define ITEMREF_NO ((void *) 0x0004)
#define ITEMREF_YES ((void *) 0x0005)
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* menu item type in the file selector */
-enum _file_selector_entry_type
-{
- SELECTOR_ENTRY_TYPE_EMPTY,
- SELECTOR_ENTRY_TYPE_CREATE,
- SELECTOR_ENTRY_TYPE_SOFTWARE_LIST,
- SELECTOR_ENTRY_TYPE_DRIVE,
- SELECTOR_ENTRY_TYPE_DIRECTORY,
- SELECTOR_ENTRY_TYPE_FILE
-};
-typedef enum _file_selector_entry_type file_selector_entry_type;
-
-
-
-/* an entry within the file manager */
-typedef struct _file_selector_entry file_selector_entry;
-struct _file_selector_entry
-{
- file_selector_entry *next;
-
- file_selector_entry_type type;
- const char *basename;
- const char *fullpath;
-};
-
-
-
-/* state of the file manager */
-typedef struct _file_manager_menu_state file_manager_menu_state;
-struct _file_manager_menu_state
-{
- device_image_interface *selected_device;
- astring *current_directory;
- astring *current_file;
-};
-
-
-
-/* state of the file selector menu */
-typedef struct _file_selector_menu_state file_selector_menu_state;
-struct _file_selector_menu_state
-{
- file_manager_menu_state *manager_menustate;
- file_selector_entry *entrylist;
- char filename_buffer[1024];
-};
-
-
-
-/* state of the file creator menu */
-typedef struct _file_create_menu_state file_create_menu_state;
-struct _file_create_menu_state
-{
- file_manager_menu_state *manager_menustate;
- const image_device_format *current_format;
- int confirm_save_as_yes;
- char filename_buffer[1024];
-};
-
-
-/* state of the confirm save as menu */
-typedef struct _confirm_save_as_menu_state confirm_save_as_menu_state;
-struct _confirm_save_as_menu_state
-{
- int *yes;
-};
-
/***************************************************************************
MENU HELPERS
***************************************************************************/
@@ -151,14 +79,14 @@ static void input_character(char *buffer, size_t buffer_length, unicode_char uni
or footer text
-------------------------------------------------*/
-static void extra_text_draw_box(render_container &ui_container, float origx1, float origx2, float origy, float yspan, const char *text, int direction)
+static void extra_text_draw_box(render_container *container, float origx1, float origx2, float origy, float yspan, const char *text, int direction)
{
float text_width, text_height;
float width, maxwidth;
float x1, y1, x2, y2, temp;
/* get the size of the text */
- ui_draw_text_full(&ui_container,text, 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD,
+ ui_draw_text_full(container,text, 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD,
DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &text_width, &text_height);
width = text_width + (2 * UI_BOX_LR_BORDER);
maxwidth = MAX(width, origx2 - origx1);
@@ -177,7 +105,7 @@ static void extra_text_draw_box(render_container &ui_container, float origx1, fl
}
/* draw a box */
- ui_draw_outlined_box(&ui_container,x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+ ui_draw_outlined_box(container,x1, y1, x2, y2, UI_BACKGROUND_COLOR);
/* take off the borders */
x1 += UI_BOX_LR_BORDER;
@@ -186,7 +114,7 @@ static void extra_text_draw_box(render_container &ui_container, float origx1, fl
y2 -= UI_BOX_TB_BORDER;
/* draw the text within it */
- ui_draw_text_full(&ui_container,text, x1, y1, text_width, JUSTIFY_LEFT, WRAP_WORD,
+ ui_draw_text_full(container,text, x1, y1, text_width, JUSTIFY_LEFT, WRAP_WORD,
DRAW_NORMAL, ARGB_WHITE, ARGB_BLACK, NULL, NULL);
}
@@ -197,7 +125,7 @@ static void extra_text_draw_box(render_container &ui_container, float origx1, fl
and footer text
-------------------------------------------------*/
-static void extra_text_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom,
+static void extra_text_render(render_container *container, float top, float bottom,
float origx1, float origy1, float origx2, float origy2,
const char *header, const char *footer)
{
@@ -205,9 +133,9 @@ static void extra_text_render(running_machine &machine, ui_menu *menu, void *sta
footer = ((footer != NULL) && (footer[0] != '\0')) ? footer : NULL;
if (header != NULL)
- extra_text_draw_box(machine.render().ui_container(), origx1, origx2, origy1, top, header, -1);
+ extra_text_draw_box(container, origx1, origx2, origy1, top, header, -1);
if (footer != NULL)
- extra_text_draw_box(machine.render().ui_container(), origx1, origx2, origy2, bottom, footer, +1);
+ extra_text_draw_box(container, origx1, origx2, origy2, bottom, footer, +1);
}
@@ -221,40 +149,40 @@ static void extra_text_render(running_machine &machine, ui_menu *menu, void *sta
confirm save as menu
-------------------------------------------------*/
-static void menu_confirm_save_as_populate(running_machine &machine, ui_menu *menu, void *state)
+ui_menu_confirm_save_as::ui_menu_confirm_save_as(running_machine &machine, render_container *container, int *_yes) : ui_menu(machine, container)
{
- ui_menu_item_append(menu, "File Already Exists - Overide?", NULL, MENU_FLAG_DISABLE, NULL);
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, MENU_FLAG_DISABLE, NULL);
- ui_menu_item_append(menu, "No", NULL, 0, ITEMREF_NO);
- ui_menu_item_append(menu, "Yes", NULL, 0, ITEMREF_YES);
+ yes = _yes;
}
+ui_menu_confirm_save_as::~ui_menu_confirm_save_as()
+{
+}
+void ui_menu_confirm_save_as::populate()
+{
+ item_append("File Already Exists - Overide?", NULL, MENU_FLAG_DISABLE, NULL);
+ item_append(MENU_SEPARATOR_ITEM, NULL, MENU_FLAG_DISABLE, NULL);
+ item_append("No", NULL, 0, ITEMREF_NO);
+ item_append("Yes", NULL, 0, ITEMREF_YES);
+}
/*-------------------------------------------------
menu_confirm_save_as - confirm save as menu
-------------------------------------------------*/
-static void menu_confirm_save_as(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu_confirm_save_as::handle()
{
- const ui_menu_event *event;
- confirm_save_as_menu_state *menustate = (confirm_save_as_menu_state *) state;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_confirm_save_as_populate(machine, menu, state);
-
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ const ui_menu_event *event = process(0);
/* process the event */
if ((event != NULL) && (event->iptkey == IPT_UI_SELECT))
{
if (event->itemref == ITEMREF_YES)
- *menustate->yes = TRUE;
+ *yes = TRUE;
/* no matter what, pop out */
- ui_menu_stack_pop(machine);
+ ui_menu::stack_pop(machine());
}
}
@@ -293,12 +221,10 @@ static int is_valid_filename_char(unicode_char unichar)
special rendering
-------------------------------------------------*/
-static void file_create_render_extra(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+void ui_menu_file_create::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
{
- file_create_menu_state *menustate = (file_create_menu_state *) state;
-
- extra_text_render(machine, menu, state, selectedref, top, bottom, origx1, origy1, origx2, origy2,
- astring_c(menustate->manager_menustate->current_directory),
+ extra_text_render(container, top, bottom, origx1, origy1, origx2, origy2,
+ astring_c(manager->current_directory),
NULL);
}
@@ -309,40 +235,47 @@ static void file_create_render_extra(running_machine &machine, ui_menu *menu, vo
creator menu
-------------------------------------------------*/
-static void menu_file_create_populate(running_machine &machine, ui_menu *menu, void *state, void *selection)
+ui_menu_file_create::ui_menu_file_create(running_machine &machine, render_container *container, ui_menu_file_manager *parent) : ui_menu(machine, container)
+{
+ manager = parent;
+}
+
+ui_menu_file_create::~ui_menu_file_create()
+{
+}
+
+void ui_menu_file_create::populate()
{
astring buffer;
- file_create_menu_state *menustate = (file_create_menu_state *) state;
- device_image_interface *device = menustate->manager_menustate->selected_device;
+ device_image_interface *device = manager->selected_device;
const image_device_format *format;
const char *new_image_name;
/* append the "New Image Name" item */
- if (selection == ITEMREF_NEW_IMAGE_NAME)
+ if (get_selection() == ITEMREF_NEW_IMAGE_NAME)
{
- astring_assemble_2(&buffer, menustate->filename_buffer, "_");
+ astring_assemble_2(&buffer, filename_buffer, "_");
new_image_name = astring_c(&buffer);
}
else
{
- new_image_name = menustate->filename_buffer;
+ new_image_name = filename_buffer;
}
- ui_menu_item_append(menu, "New Image Name:", new_image_name, 0, ITEMREF_NEW_IMAGE_NAME);
+ item_append("New Image Name:", new_image_name, 0, ITEMREF_NEW_IMAGE_NAME);
/* do we support multiple formats? */
format = device->device_get_creatable_formats();
if (ENABLE_FORMATS && (format != NULL))
{
- ui_menu_item_append(menu, "Image Format:", menustate->current_format->m_description, 0, ITEMREF_FORMAT);
- menustate->current_format = format;
+ item_append("Image Format:", current_format->m_description, 0, ITEMREF_FORMAT);
+ current_format = format;
}
/* finish up the menu */
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
- ui_menu_item_append(menu, "Create", NULL, 0, ITEMREF_CREATE);
+ item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ item_append("Create", NULL, 0, ITEMREF_CREATE);
- /* set up custom render proc */
- ui_menu_set_custom_render(menu, file_create_render_extra, ui_get_line_height(machine) + 3.0f * UI_BOX_TB_BORDER, 0);
+ customtop = ui_get_line_height(machine()) + 3.0f * UI_BOX_TB_BORDER;
}
@@ -351,15 +284,13 @@ static void menu_file_create_populate(running_machine &machine, ui_menu *menu, v
create_new_image - creates a new disk image
-------------------------------------------------*/
-static int create_new_image(device_image_interface *image, const char *directory, const char *filename, int *yes)
+int ui_menu_file_create::create_new_image(device_image_interface *image, const char *directory, const char *filename, int *yes)
{
astring *path;
osd_directory_entry *entry;
osd_dir_entry_type file_type;
int do_create, err;
int result = FALSE;
- ui_menu *child_menu;
- confirm_save_as_menu_state *child_menustate;
/* assemble the full path */
path = zippath_combine(astring_alloc(), directory, filename);
@@ -383,10 +314,7 @@ static int create_new_image(device_image_interface *image, const char *directory
case ENTTYPE_FILE:
/* a file exists here - ask for permission from the user */
- child_menu = ui_menu_alloc(image->device().machine(), &image->device().machine().render().ui_container(), menu_confirm_save_as, NULL);
- child_menustate = (confirm_save_as_menu_state*)ui_menu_alloc_state(child_menu, sizeof(*child_menustate), NULL);
- child_menustate->yes = yes;
- ui_menu_stack_push(child_menu);
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_confirm_save_as(machine(), container, yes)));
do_create = FALSE;
break;
@@ -424,21 +352,12 @@ static int create_new_image(device_image_interface *image, const char *directory
menu_file_create - file creator menu
-------------------------------------------------*/
-static void menu_file_create(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu_file_create::handle()
{
- void *selection;
const ui_menu_event *event;
ui_menu_event fake_event;
- file_create_menu_state *menustate = (file_create_menu_state *) state;
- /* identify the selection */
- selection = ui_menu_get_selection(menu);
-
- /* rebuild the menu */
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
- menu_file_create_populate(machine, menu, state, selection);
-
- if (menustate->confirm_save_as_yes)
+ if (confirm_save_as_yes)
{
/* we just returned from a "confirm save as" dialog and the user said "yes" - fake an event */
memset(&fake_event, 0, sizeof(fake_event));
@@ -449,7 +368,7 @@ static void menu_file_create(running_machine &machine, ui_menu *menu, void *para
else
{
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ event = process(0);
}
/* process the event */
@@ -462,24 +381,24 @@ static void menu_file_create(running_machine &machine, ui_menu *menu, void *para
if ((event->itemref == ITEMREF_CREATE) || (event->itemref == ITEMREF_NEW_IMAGE_NAME))
{
if (create_new_image(
- menustate->manager_menustate->selected_device,
- astring_c(menustate->manager_menustate->current_directory),
- menustate->filename_buffer,
- &menustate->confirm_save_as_yes))
+ manager->selected_device,
+ astring_c(manager->current_directory),
+ filename_buffer,
+ &confirm_save_as_yes))
{
/* success - pop out twice to device view */
- ui_menu_stack_pop(machine);
- ui_menu_stack_pop(machine);
+ ui_menu::stack_pop(machine());
+ ui_menu::stack_pop(machine());
}
}
break;
case IPT_SPECIAL:
- if (ui_menu_get_selection(menu) == ITEMREF_NEW_IMAGE_NAME)
+ if (get_selection() == ITEMREF_NEW_IMAGE_NAME)
{
input_character(
- menustate->filename_buffer,
- ARRAY_LENGTH(menustate->filename_buffer),
+ filename_buffer,
+ ARRAY_LENGTH(filename_buffer),
event->unichar,
is_valid_filename_char);
}
@@ -499,13 +418,11 @@ static void menu_file_create(running_machine &machine, ui_menu *menu, void *para
special rendering
-------------------------------------------------*/
-static void file_selector_render_extra(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+void ui_menu_file_selector::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
{
- file_selector_menu_state *menustate = (file_selector_menu_state *) state;
-
- extra_text_render(machine, menu, state, selectedref, top, bottom,
+ extra_text_render(container, top, bottom,
origx1, origy1, origx2, origy2,
- astring_c(menustate->manager_menustate->current_directory),
+ astring_c(manager->current_directory),
NULL);
}
@@ -516,7 +433,7 @@ static void file_selector_render_extra(running_machine &machine, ui_menu *menu,
for file selector entries
-------------------------------------------------*/
-static int compare_file_selector_entries(const file_selector_entry *e1, const file_selector_entry *e2)
+int ui_menu_file_selector::compare_entries(const file_selector_entry *e1, const file_selector_entry *e2)
{
int result;
const char *e1_basename = (e1->basename != NULL) ? e1->basename : "";
@@ -552,26 +469,26 @@ static int compare_file_selector_entries(const file_selector_entry *e1, const fi
/*-------------------------------------------------
- append_file_selector_entry - appends a new
+ append_entry - appends a new
file selector entry to an entry list
-------------------------------------------------*/
-static file_selector_entry *append_file_selector_entry(ui_menu *menu, file_selector_menu_state *menustate,
+ui_menu_file_selector::file_selector_entry *ui_menu_file_selector::append_entry(
file_selector_entry_type entry_type, const char *entry_basename, const char *entry_fullpath)
{
file_selector_entry *entry;
file_selector_entry **entryptr;
/* allocate a new entry */
- entry = (file_selector_entry *) ui_menu_pool_alloc(menu, sizeof(*entry));
+ entry = (file_selector_entry *) m_pool_alloc(sizeof(*entry));
memset(entry, 0, sizeof(*entry));
entry->type = entry_type;
- entry->basename = (entry_basename != NULL) ? ui_menu_pool_strdup(menu, entry_basename) : entry_basename;
- entry->fullpath = (entry_fullpath != NULL) ? ui_menu_pool_strdup(menu, entry_fullpath) : entry_fullpath;
+ entry->basename = (entry_basename != NULL) ? pool_strdup(entry_basename) : entry_basename;
+ entry->fullpath = (entry_fullpath != NULL) ? pool_strdup(entry_fullpath) : entry_fullpath;
/* find the end of the list */
- entryptr = &menustate->entrylist;
- while ((*entryptr != NULL) && (compare_file_selector_entries(entry, *entryptr) >= 0))
+ entryptr = &entrylist;
+ while ((*entryptr != NULL) && (compare_entries(entry, *entryptr) >= 0))
entryptr = &(*entryptr)->next;
/* insert the entry */
@@ -583,12 +500,11 @@ static file_selector_entry *append_file_selector_entry(ui_menu *menu, file_selec
/*-------------------------------------------------
- append_file_selector_entry_menu_item - appends
+ append_entry_menu_item - appends
a menu item for a file selector entry
-------------------------------------------------*/
-static file_selector_entry *append_dirent_file_selector_entry(ui_menu *menu, file_selector_menu_state *menustate,
- const osd_directory_entry *dirent)
+ui_menu_file_selector::file_selector_entry *ui_menu_file_selector::append_dirent_entry(const osd_directory_entry *dirent)
{
astring *buffer;
file_selector_entry_type entry_type;
@@ -612,13 +528,11 @@ static file_selector_entry *append_dirent_file_selector_entry(ui_menu *menu, fil
/* determine the full path */
buffer = zippath_combine(
astring_alloc(),
- astring_c(menustate->manager_menustate->current_directory),
+ astring_c(manager->current_directory),
dirent->name);
/* create the file selector entry */
- entry = append_file_selector_entry(
- menu,
- menustate,
+ entry = append_entry(
entry_type,
dirent->name,
astring_c(buffer));
@@ -630,11 +544,11 @@ static file_selector_entry *append_dirent_file_selector_entry(ui_menu *menu, fil
/*-------------------------------------------------
- append_file_selector_entry_menu_item - appends
+ append_entry_menu_item - appends
a menu item for a file selector entry
-------------------------------------------------*/
-static void append_file_selector_entry_menu_item(ui_menu *menu, const file_selector_entry *entry)
+void ui_menu_file_selector::append_entry_menu_item(const file_selector_entry *entry)
{
const char *text = NULL;
const char *subtext = NULL;
@@ -668,7 +582,7 @@ static void append_file_selector_entry_menu_item(ui_menu *menu, const file_selec
subtext = "[FILE]";
break;
}
- ui_menu_item_append(menu, text, subtext, 0, (void *) entry);
+ item_append(text, subtext, 0, (void *) entry);
}
@@ -677,7 +591,16 @@ static void append_file_selector_entry_menu_item(ui_menu *menu, const file_selec
allocates all menu items for a directory
-------------------------------------------------*/
-static file_error menu_file_selector_populate(running_machine &machine, ui_menu *menu, file_selector_menu_state *menustate)
+ui_menu_file_selector::ui_menu_file_selector(running_machine &machine, render_container *container, ui_menu_file_manager *parent) : ui_menu(machine, container)
+{
+ manager = parent;
+}
+
+ui_menu_file_selector::~ui_menu_file_selector()
+{
+}
+
+void ui_menu_file_selector::populate()
{
zippath_directory *directory = NULL;
file_error err = FILERR_NONE;
@@ -686,8 +609,8 @@ static file_error menu_file_selector_populate(running_machine &machine, ui_menu
const file_selector_entry *selected_entry = NULL;
int i;
const char *volume_name;
- device_image_interface *device = menustate->manager_menustate->selected_device;
- const char *path = astring_c(menustate->manager_menustate->current_directory);
+ device_image_interface *device = manager->selected_device;
+ const char *path = astring_c(manager->current_directory);
/* open the directory */
err = zippath_opendir(path, &directory);
@@ -695,25 +618,25 @@ static file_error menu_file_selector_populate(running_machine &machine, ui_menu
goto done;
/* clear out the menu entries */
- menustate->entrylist = NULL;
+ entrylist = NULL;
/* add the "[empty slot]" entry */
- append_file_selector_entry(menu, menustate, SELECTOR_ENTRY_TYPE_EMPTY, NULL, NULL);
+ append_entry(SELECTOR_ENTRY_TYPE_EMPTY, NULL, NULL);
if (device->is_creatable() && !zippath_is_zip(directory))
{
/* add the "[create]" entry */
- append_file_selector_entry(menu, menustate, SELECTOR_ENTRY_TYPE_CREATE, NULL, NULL);
+ append_entry(SELECTOR_ENTRY_TYPE_CREATE, NULL, NULL);
}
/* add the "[software list]" entry */
- append_file_selector_entry(menu, menustate, SELECTOR_ENTRY_TYPE_SOFTWARE_LIST, NULL, NULL);
+ append_entry(SELECTOR_ENTRY_TYPE_SOFTWARE_LIST, NULL, NULL);
/* add the drives */
i = 0;
while((volume_name = osd_get_volume_name(i))!=NULL)
{
- append_file_selector_entry(menu, menustate, SELECTOR_ENTRY_TYPE_DRIVE,
+ append_entry(SELECTOR_ENTRY_TYPE_DRIVE,
volume_name, volume_name);
i++;
}
@@ -722,7 +645,7 @@ static file_error menu_file_selector_populate(running_machine &machine, ui_menu
while((dirent = zippath_readdir(directory)) != NULL)
{
/* append a dirent entry */
- entry = append_dirent_file_selector_entry(menu, menustate, dirent);
+ entry = append_dirent_entry(dirent);
if (entry != NULL)
{
@@ -731,30 +654,27 @@ static file_error menu_file_selector_populate(running_machine &machine, ui_menu
selected_entry = entry;
/* do we have to select this file? */
- if (!mame_stricmp(astring_c(menustate->manager_menustate->current_file), dirent->name))
+ if (!mame_stricmp(astring_c(manager->current_file), dirent->name))
selected_entry = entry;
}
}
/* append all of the menu entries */
- for (entry = menustate->entrylist; entry != NULL; entry = entry->next)
- append_file_selector_entry_menu_item(menu, entry);
+ for (entry = entrylist; entry != NULL; entry = entry->next)
+ append_entry_menu_item(entry);
/* set the selection (if we have one) */
if (selected_entry != NULL)
- ui_menu_set_selection(menu, (void *) selected_entry);
+ set_selection((void *) selected_entry);
/* set up custom render proc */
- ui_menu_set_custom_render(menu, file_selector_render_extra, ui_get_line_height(machine) + 3.0f * UI_BOX_TB_BORDER, 0);
+ customtop = ui_get_line_height(machine()) + 3.0f * UI_BOX_TB_BORDER;
done:
if (directory != NULL)
zippath_closedir(directory);
- return err;
}
-
-
/*-------------------------------------------------
check_path - performs a quick check to see if
a path exists
@@ -771,35 +691,15 @@ static file_error check_path(const char *path)
menu_file_selector - file selector menu
-------------------------------------------------*/
-static void menu_file_selector(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu_file_selector::handle()
{
file_error err;
- const ui_menu_event *event;
- ui_menu *child_menu;
- file_selector_menu_state *menustate;
- file_create_menu_state *child_menustate;
const file_selector_entry *entry;
const file_selector_entry *selected_entry = NULL;
int bestmatch = 0;
- /* get menu state */
- menustate = (file_selector_menu_state *) state;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- {
- err = menu_file_selector_populate(machine, menu, menustate);
-
- /* pop out if there was an error */
- if (err != FILERR_NONE)
- {
- ui_menu_stack_pop(machine);
- return;
- }
- }
-
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ const ui_menu_event *event = process(0);
if (event != NULL && event->itemref != NULL)
{
/* handle selections */
@@ -810,20 +710,16 @@ static void menu_file_selector(running_machine &machine, ui_menu *menu, void *pa
{
case SELECTOR_ENTRY_TYPE_EMPTY:
/* empty slot - unload */
- menustate->manager_menustate->selected_device->unload();
- ui_menu_stack_pop(machine);
+ manager->selected_device->unload();
+ ui_menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_CREATE:
/* create */
- child_menu = ui_menu_alloc(machine, &machine.render().ui_container(), menu_file_create, NULL);
- child_menustate = (file_create_menu_state*)ui_menu_alloc_state(child_menu, sizeof(*child_menustate), NULL);
- child_menustate->manager_menustate = menustate->manager_menustate;
- ui_menu_stack_push(child_menu);
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_file_create(machine(), container, manager)));
break;
case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
- child_menu = ui_menu_alloc(machine, &machine.render().ui_container(), ui_image_menu_software, menustate->manager_menustate->selected_device);
- ui_menu_stack_push(child_menu);
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software(machine(), container, manager->selected_device)));
break;
case SELECTOR_ENTRY_TYPE_DRIVE:
case SELECTOR_ENTRY_TYPE_DIRECTORY:
@@ -835,60 +731,60 @@ static void menu_file_selector(running_machine &machine, ui_menu *menu, void *pa
ui_popup_time(1, "Error accessing %s", entry->fullpath);
break;
}
- astring_cpyc(menustate->manager_menustate->current_directory, entry->fullpath);
- ui_menu_reset(menu, (ui_menu_reset_options)0);
+ astring_cpyc(manager->current_directory, entry->fullpath);
+ reset((ui_menu_reset_options)0);
break;
case SELECTOR_ENTRY_TYPE_FILE:
/* file */
- menustate->manager_menustate->selected_device->load(entry->fullpath);
- ui_menu_stack_pop(machine);
+ manager->selected_device->load(entry->fullpath);
+ ui_menu::stack_pop(machine());
break;
}
// reset the char buffer when pressing IPT_UI_SELECT
- if (menustate->filename_buffer[0] != '\0')
- memset(menustate->filename_buffer, '\0', ARRAY_LENGTH(menustate->filename_buffer));
+ if (filename_buffer[0] != '\0')
+ memset(filename_buffer, '\0', ARRAY_LENGTH(filename_buffer));
}
else if (event->iptkey == IPT_SPECIAL)
{
- int buflen = strlen(menustate->filename_buffer);
+ int buflen = strlen(filename_buffer);
bool update_selected = FALSE;
/* if it's a backspace and we can handle it, do so */
if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
{
- *(char *)utf8_previous_char(&menustate->filename_buffer[buflen]) = 0;
+ *(char *)utf8_previous_char(&filename_buffer[buflen]) = 0;
update_selected = TRUE;
- if (ARRAY_LENGTH(menustate->filename_buffer) > 0)
- ui_popup_time(ERROR_MESSAGE_TIME, "%s", menustate->filename_buffer);
+ if (ARRAY_LENGTH(filename_buffer) > 0)
+ ui_popup_time(ERROR_MESSAGE_TIME, "%s", filename_buffer);
}
/* if it's any other key and we're not maxed out, update */
else if (event->unichar >= ' ' && event->unichar < 0x7f)
{
- buflen += utf8_from_uchar(&menustate->filename_buffer[buflen], ARRAY_LENGTH(menustate->filename_buffer) - buflen, event->unichar);
- menustate->filename_buffer[buflen] = 0;
+ buflen += utf8_from_uchar(&filename_buffer[buflen], ARRAY_LENGTH(filename_buffer) - buflen, event->unichar);
+ filename_buffer[buflen] = 0;
update_selected = TRUE;
- if (ARRAY_LENGTH(menustate->filename_buffer) > 0)
- ui_popup_time(ERROR_MESSAGE_TIME, "%s", menustate->filename_buffer);
+ if (ARRAY_LENGTH(filename_buffer) > 0)
+ ui_popup_time(ERROR_MESSAGE_TIME, "%s", filename_buffer);
}
if (update_selected)
{
- const file_selector_entry *cur_selected = (const file_selector_entry *)ui_menu_get_selection(menu);
+ const file_selector_entry *cur_selected = (const file_selector_entry *)get_selection();
// check for entries which matches our filename_buffer:
// from current entry to the end
for (entry = cur_selected; entry != NULL; entry = entry->next)
{
- if (entry->basename != NULL && menustate->filename_buffer != NULL)
+ if (entry->basename != NULL && filename_buffer != NULL)
{
int match = 0;
- for (int i = 0; i < ARRAY_LENGTH(menustate->filename_buffer); i++)
+ for (int i = 0; i < ARRAY_LENGTH(filename_buffer); i++)
{
- if (mame_strnicmp(entry->basename, menustate->filename_buffer, i) == 0)
+ if (mame_strnicmp(entry->basename, filename_buffer, i) == 0)
match = i;
}
@@ -900,14 +796,14 @@ static void menu_file_selector(running_machine &machine, ui_menu *menu, void *pa
}
}
// and from the first entry to current one
- for (entry = menustate->entrylist; entry != cur_selected; entry = entry->next)
+ for (entry = entrylist; entry != cur_selected; entry = entry->next)
{
- if (entry->basename != NULL && menustate->filename_buffer != NULL)
+ if (entry->basename != NULL && filename_buffer != NULL)
{
int match = 0;
- for (int i = 0; i < ARRAY_LENGTH(menustate->filename_buffer); i++)
+ for (int i = 0; i < ARRAY_LENGTH(filename_buffer); i++)
{
- if (mame_strnicmp(entry->basename, menustate->filename_buffer, i) == 0)
+ if (mame_strnicmp(entry->basename, filename_buffer, i) == 0)
match = i;
}
@@ -920,14 +816,14 @@ static void menu_file_selector(running_machine &machine, ui_menu *menu, void *pa
}
if (selected_entry != NULL && selected_entry != cur_selected)
- ui_menu_set_selection(menu, (void *) selected_entry);
+ set_selection((void *) selected_entry);
}
}
else if (event->iptkey == IPT_UI_CANCEL)
{
// reset the char buffer also in this case
- if (menustate->filename_buffer[0] != '\0')
- memset(menustate->filename_buffer, '\0', ARRAY_LENGTH(menustate->filename_buffer));
+ if (filename_buffer[0] != '\0')
+ memset(filename_buffer, '\0', ARRAY_LENGTH(filename_buffer));
}
}
}
@@ -944,7 +840,7 @@ static void menu_file_selector(running_machine &machine, ui_menu *menu, void *pa
"makes sense"
-------------------------------------------------*/
-static void fix_working_directory(device_image_interface *image)
+void ui_menu_file_manager::fix_working_directory(device_image_interface *image)
{
/* if the image exists, set the working directory to the parent directory */
if (image->exists())
@@ -967,15 +863,14 @@ static void fix_working_directory(device_image_interface *image)
special rendering
-------------------------------------------------*/
-static void file_manager_render_extra(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+void ui_menu_file_manager::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
{
- file_manager_menu_state *menustate = (file_manager_menu_state *) state;
const char *path;
/* access the path */
- path = (menustate->selected_device != NULL) ? menustate->selected_device->filename() : NULL;
- extra_text_render(machine, menu, state, selectedref, top, bottom,
- origx1, origy1, origx2, origy2, NULL, path);
+ path = selected_device ? selected_device->filename() : NULL;
+ extra_text_render(container, top, bottom,
+ origx1, origy1, origx2, origy2, NULL, path);
}
@@ -985,14 +880,20 @@ static void file_manager_render_extra(running_machine &machine, ui_menu *menu, v
file manager menu
-------------------------------------------------*/
-static void menu_file_manager_populate(running_machine &machine, ui_menu *menu, void *state)
+ui_menu_file_manager::ui_menu_file_manager(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+ current_directory = astring_alloc();
+ current_file = astring_alloc();
+}
+
+void ui_menu_file_manager::populate()
{
char buffer[2048];
device_image_interface *image = NULL;
astring tmp_name;
/* cycle through all devices for this system */
- for (bool gotone = machine.devicelist().first(image); gotone; gotone = image->next(image))
+ for (bool gotone = machine().devicelist().first(image); gotone; gotone = image->next(image))
{
/* get the image type/id */
snprintf(buffer, ARRAY_LENGTH(buffer),
@@ -1026,11 +927,10 @@ static void menu_file_manager_populate(running_machine &machine, ui_menu *menu,
tmp_name.cpy("---");
/* record the menu item */
- ui_menu_item_append(menu, buffer, tmp_name.cstr(), 0, (void *) image);
+ item_append(buffer, tmp_name.cstr(), 0, (void *) image);
}
- /* set up custom render proc */
- ui_menu_set_custom_render(menu, file_manager_render_extra, 0, ui_get_line_height(machine) + 3.0f * UI_BOX_TB_BORDER);
+ custombottom = ui_get_line_height(machine()) + 3.0f * UI_BOX_TB_BORDER;
}
@@ -1039,15 +939,10 @@ static void menu_file_manager_populate(running_machine &machine, ui_menu *menu,
file_manager_destroy_state - state destructor
-------------------------------------------------*/
-static void file_manager_destroy_state(ui_menu *menu, void *state)
+ui_menu_file_manager::~ui_menu_file_manager()
{
- file_manager_menu_state *menustate = (file_manager_menu_state *) state;
-
- if (menustate->current_directory != NULL)
- astring_free(menustate->current_directory);
-
- if (menustate->current_file != NULL)
- astring_free(menustate->current_file);
+ astring_free(current_directory);
+ astring_free(current_file);
}
@@ -1056,74 +951,58 @@ static void file_manager_destroy_state(ui_menu *menu, void *state)
menu_file_manager - main file manager menu
-------------------------------------------------*/
-void ui_image_menu_file_manager(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu_file_manager::handle()
{
- const ui_menu_event *event;
- file_manager_menu_state *menustate;
- ui_menu *child_menu;
- file_selector_menu_state *child_menustate;
-
- /* if no state, allocate now */
- if (state == NULL)
- {
- state = ui_menu_alloc_state(menu, sizeof(*menustate), file_manager_destroy_state);
- menustate = (file_manager_menu_state *) state;
-
- menustate->current_directory = astring_alloc();
- menustate->current_file = astring_alloc();
- }
- menustate = (file_manager_menu_state *) state;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_file_manager_populate(machine, menu, state);
-
/* update the selected device */
- menustate->selected_device = (device_image_interface *) ui_menu_get_selection(menu);
+ selected_device = (device_image_interface *) get_selection();
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ const ui_menu_event *event = process(0);
if (event != NULL && event->iptkey == IPT_UI_SELECT)
{
- menustate->selected_device = (device_image_interface *) event->itemref;
- if (menustate->selected_device != NULL)
+ selected_device = (device_image_interface *) event->itemref;
+ if (selected_device != NULL)
{
/* ensure that the working directory for this device exists */
- fix_working_directory(menustate->selected_device);
+ fix_working_directory(selected_device);
/* set up current_directory and current_file - depends on whether we have an image */
- astring_cpyc(menustate->current_directory, menustate->selected_device->working_directory());
- astring_cpyc(menustate->current_file, menustate->selected_device->exists() ? menustate->selected_device->basename() : "");
+ astring_cpyc(current_directory, selected_device->working_directory());
+ astring_cpyc(current_file, selected_device->exists() ? selected_device->basename() : "");
/* reset the existing menu */
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
/* push the menu */
- child_menu = ui_menu_alloc(machine, &machine.render().ui_container(), menu_file_selector, NULL);
- child_menustate = (file_selector_menu_state *)ui_menu_alloc_state(child_menu, sizeof(*child_menustate), NULL);
- child_menustate->manager_menustate = menustate;
- ui_menu_stack_push(child_menu);
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_file_selector(machine(), container, this)));
}
}
}
/*-------------------------------------------------
- ui_image_menu_image_info - menu that shows info
+ ui_menu_image_info - menu that shows info
on all loaded images
-------------------------------------------------*/
-void ui_image_menu_image_info(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+ui_menu_image_info::ui_menu_image_info(running_machine &machine, render_container *container) : ui_menu(machine, container)
{
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- {
- astring *tempstring = image_info_astring(machine, astring_alloc());
- ui_menu_item_append(menu, astring_c(tempstring), NULL, MENU_FLAG_MULTILINE, NULL);
- astring_free(tempstring);
- }
+}
+
+void ui_menu_image_info::populate()
+{
+ astring *tempstring = image_info_astring(machine(), astring_alloc());
+ item_append(astring_c(tempstring), NULL, MENU_FLAG_MULTILINE, NULL);
+ astring_free(tempstring);
+}
+
+ui_menu_image_info::~ui_menu_image_info()
+{
+}
+void ui_menu_image_info::handle()
+{
/* process the menu */
- ui_menu_process(machine, menu, 0);
+ process(0);
}
/***************************************************************************
@@ -1144,37 +1023,35 @@ void ui_image_menu_image_info(running_machine &machine, ui_menu *menu, void *par
#define BITBANGERCMD_TUNE ((void *) 0x0003)
-typedef struct _tape_control_menu_state tape_control_menu_state;
-struct _tape_control_menu_state
-{
- int index;
- device_image_interface *device;
-};
-
-
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
-typedef struct _bitbanger_control_menu_state bitbanger_control_menu_state;
-struct _bitbanger_control_menu_state
+ui_menu_mess_tape_control::ui_menu_mess_tape_control(running_machine &machine, render_container *container) : ui_menu(machine, container)
{
- int index;
- device_image_interface *device;
-};
+}
+ui_menu_mess_tape_control::~ui_menu_mess_tape_control()
+{
+}
+ui_menu_mess_bitbanger_control::ui_menu_mess_bitbanger_control(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
-/***************************************************************************
- IMPLEMENTATION
-***************************************************************************/
+ui_menu_mess_bitbanger_control::~ui_menu_mess_bitbanger_control()
+{
+}
/*-------------------------------------------------
cassette_count - returns the number of cassette
devices in the machine
-------------------------------------------------*/
-INLINE int cassette_count( running_machine &machine )
+int ui_menu_mess_tape_control::cassette_count()
{
int count = 0;
- device_t *device = machine.devicelist().first(CASSETTE);
+ device_t *device = machine().devicelist().first(CASSETTE);
while ( device )
{
@@ -1189,10 +1066,10 @@ INLINE int cassette_count( running_machine &machine )
devices in the machine
-------------------------------------------------*/
-INLINE int bitbanger_count( running_machine &machine )
+int ui_menu_mess_bitbanger_control::bitbanger_count()
{
int count = 0;
- device_t *device = machine.devicelist().first(BITBANGER);
+ device_t *device = machine().devicelist().first(BITBANGER);
while ( device )
{
@@ -1234,26 +1111,26 @@ astring *tapecontrol_gettime(astring *dest, cassette_image_device *cassette, int
main tape control menu
-------------------------------------------------*/
-static void menu_tape_control_populate(running_machine &machine, ui_menu *menu, tape_control_menu_state *menustate)
+void ui_menu_mess_tape_control::populate()
{
astring timepos;
cassette_state state;
- int count = cassette_count(machine);
+ int count = cassette_count();
UINT32 flags = 0;
if( count > 0 )
{
- if( menustate->index == (count-1) )
+ if( index == (count-1) )
flags |= MENU_FLAG_LEFT_ARROW;
else
flags |= MENU_FLAG_RIGHT_ARROW;
}
- if (menustate->device->exists())
+ if (device->exists())
{
double t0, t1;
UINT32 tapeflags = 0;
- cassette_image_device* cassette = dynamic_cast<cassette_image_device*>(&menustate->device->device());
+ cassette_image_device* cassette = dynamic_cast<cassette_image_device*>(&device->device());
t0 = cassette->get_position();
t1 = cassette->get_length();
@@ -1267,13 +1144,12 @@ static void menu_tape_control_populate(running_machine &machine, ui_menu *menu,
}
/* name of tape */
- ui_menu_item_append(menu, menustate->device->device().name(), menustate->device->filename(), flags, TAPECMD_SELECT);
+ item_append(device->device().name(), device->filename(), flags, TAPECMD_SELECT);
/* state */
tapecontrol_gettime(&timepos, cassette, NULL, NULL);
state = cassette->get_state();
- ui_menu_item_append(
- menu,
+ item_append(
(state & CASSETTE_MASK_UISTATE) == CASSETTE_STOPPED
? "stopped"
: ((state & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY
@@ -1285,24 +1161,24 @@ static void menu_tape_control_populate(running_machine &machine, ui_menu *menu,
TAPECMD_SLIDER);
/* pause or stop */
- ui_menu_item_append(menu, "Pause/Stop", NULL, 0, TAPECMD_STOP);
+ item_append("Pause/Stop", NULL, 0, TAPECMD_STOP);
/* play */
- ui_menu_item_append(menu, "Play", NULL, 0, TAPECMD_PLAY);
+ item_append("Play", NULL, 0, TAPECMD_PLAY);
/* record */
- ui_menu_item_append(menu, "Record", NULL, 0, TAPECMD_RECORD);
+ item_append("Record", NULL, 0, TAPECMD_RECORD);
/* rewind */
- ui_menu_item_append(menu, "Rewind", NULL, 0, TAPECMD_REWIND);
+ item_append("Rewind", NULL, 0, TAPECMD_REWIND);
/* fast forward */
- ui_menu_item_append(menu, "Fast Forward", NULL, 0, TAPECMD_FAST_FORWARD);
+ item_append("Fast Forward", NULL, 0, TAPECMD_FAST_FORWARD);
}
else
{
/* no tape loaded */
- ui_menu_item_append(menu, "No Tape Image loaded", NULL, flags, NULL);
+ item_append("No Tape Image loaded", NULL, flags, NULL);
}
}
@@ -1312,15 +1188,15 @@ static void menu_tape_control_populate(running_machine &machine, ui_menu *menu,
main bitbanger control menu
-------------------------------------------------*/
-static void menu_bitbanger_control_populate(running_machine &machine, ui_menu *menu, bitbanger_control_menu_state *menustate)
+void ui_menu_mess_bitbanger_control::populate()
{
- bitbanger_device *bitbanger = downcast<bitbanger_device *>(&menustate->device->device());
- int count = bitbanger_count(machine);
+ bitbanger_device *bitbanger = downcast<bitbanger_device *>(&device->device());
+ int count = bitbanger_count();
UINT32 flags = 0, mode_flags = 0, baud_flags = 0, tune_flags = 0;
if( count > 0 )
{
- if( menustate->index == (count-1) )
+ if( index == (count-1) )
flags |= MENU_FLAG_LEFT_ARROW;
else
flags |= MENU_FLAG_RIGHT_ARROW;
@@ -1345,19 +1221,19 @@ static void menu_bitbanger_control_populate(running_machine &machine, ui_menu *m
tune_flags |= MENU_FLAG_LEFT_ARROW;
- if (menustate->device->exists())
+ if (device->exists())
{
/* name of bitbanger file */
- ui_menu_item_append(menu, menustate->device->device().name(), menustate->device->filename(), flags, BITBANGERCMD_SELECT);
- ui_menu_item_append(menu, "Device Mode:", bitbanger->mode_string(), mode_flags, BITBANGERCMD_MODE);
- ui_menu_item_append(menu, "Baud:", bitbanger->baud_string(), baud_flags, BITBANGERCMD_BAUD);
- ui_menu_item_append(menu, "Baud Tune:", bitbanger->tune_string(), tune_flags, BITBANGERCMD_TUNE);
- ui_menu_item_append(menu, "Protocol:", "8-1-N", 0, NULL);
+ item_append(device->device().name(), device->filename(), flags, BITBANGERCMD_SELECT);
+ item_append("Device Mode:", bitbanger->mode_string(), mode_flags, BITBANGERCMD_MODE);
+ item_append("Baud:", bitbanger->baud_string(), baud_flags, BITBANGERCMD_BAUD);
+ item_append("Baud Tune:", bitbanger->tune_string(), tune_flags, BITBANGERCMD_TUNE);
+ item_append("Protocol:", "8-1-N", 0, NULL);
}
else
{
/* no tape loaded */
- ui_menu_item_append(menu, "No Bitbanger Image loaded", NULL, flags, NULL);
+ item_append("No Bitbanger Image loaded", NULL, flags, NULL);
}
}
@@ -1366,40 +1242,30 @@ static void menu_bitbanger_control_populate(running_machine &machine, ui_menu *m
menu_tape_control - main tape control menu
-------------------------------------------------*/
-void ui_mess_menu_tape_control(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu_mess_tape_control::handle()
{
- tape_control_menu_state *menustate;
- const ui_menu_event *event;
-
- /* if no state, allocate some */
- if (state == NULL)
- state = ui_menu_alloc_state(menu, sizeof(*menustate), NULL);
- menustate = (tape_control_menu_state *) state;
-
/* do we have to load the device? */
- if (menustate->device == NULL)
+ if (device == NULL)
{
- int index = menustate->index;
- device_image_interface *device = NULL;
- for (bool gotone = machine.devicelist().first(device); gotone; gotone = device->next(device))
+ int cindex = index;
+ for (bool gotone = machine().devicelist().first(device); gotone; gotone = device->next(device))
{
if(device->device().type() == CASSETTE) {
- if (index==0) break;
- index--;
+ if (cindex==0) break;
+ cindex--;
}
}
- menustate->device = device;
- ui_menu_reset(menu, (ui_menu_reset_options)0);
+ reset((ui_menu_reset_options)0);
}
/* rebuild the menu - we have to do this so that the counter updates */
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
- menu_tape_control_populate(machine, menu, (tape_control_menu_state*)state);
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ populate();
- cassette_image_device* cassette = dynamic_cast<cassette_image_device*>(&menustate->device->device());
+ cassette_image_device* cassette = dynamic_cast<cassette_image_device*>(&device->device());
/* process the menu */
- event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
+ const ui_menu_event *event = process(UI_MENU_PROCESS_LR_REPEAT);
if (event != NULL)
{
switch(event->iptkey)
@@ -1411,11 +1277,11 @@ void ui_mess_menu_tape_control(running_machine &machine, ui_menu *menu, void *pa
if (event->itemref==TAPECMD_SELECT)
{
/* left arrow - rotate left through cassette devices */
- if (menustate->index > 0)
- menustate->index--;
+ if (index > 0)
+ index--;
else
- menustate->index = cassette_count(machine) - 1;
- menustate->device = NULL;
+ index = cassette_count() - 1;
+ device = NULL;
}
break;
@@ -1426,11 +1292,11 @@ void ui_mess_menu_tape_control(running_machine &machine, ui_menu *menu, void *pa
if (event->itemref==TAPECMD_SELECT)
{
/* right arrow - rotate right through cassette devices */
- if (menustate->index < cassette_count(machine) - 1)
- menustate->index++;
+ if (index < cassette_count() - 1)
+ index++;
else
- menustate->index = 0;
- menustate->device = NULL;
+ index = 0;
+ device = NULL;
}
break;
@@ -1465,41 +1331,31 @@ void ui_mess_menu_tape_control(running_machine &machine, ui_menu *menu, void *pa
control menu
-------------------------------------------------*/
-void ui_mess_menu_bitbanger_control(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu_mess_bitbanger_control::handle()
{
- bitbanger_control_menu_state *menustate;
- const ui_menu_event *event;
-
- /* if no state, allocate some */
- if (state == NULL)
- state = ui_menu_alloc_state(menu, sizeof(*menustate), NULL);
- menustate = (bitbanger_control_menu_state *) state;
-
/* do we have to load the device? */
- if (menustate->device == NULL)
+ if (device == NULL)
{
- int index = menustate->index;
- device_image_interface *device = NULL;
- for (bool gotone = machine.devicelist().first(device); gotone; gotone = device->next(device))
+ int cindex = index;
+ for (bool gotone = machine().devicelist().first(device); gotone; gotone = device->next(device))
{
if(device->device().type() == BITBANGER) {
- if (index==0) break;
- index--;
+ if (cindex==0) break;
+ cindex--;
}
}
- menustate->device = device;
- ui_menu_reset(menu, (ui_menu_reset_options)0);
+ reset((ui_menu_reset_options)0);
}
/* get the bitbanger */
- bitbanger_device *bitbanger = downcast<bitbanger_device *>(menustate->device);
+ bitbanger_device *bitbanger = downcast<bitbanger_device *>(device);
/* rebuild the menu */
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
- menu_bitbanger_control_populate(machine, menu, (bitbanger_control_menu_state*)state);
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ populate();
/* process the menu */
- event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
+ const ui_menu_event *event = process(UI_MENU_PROCESS_LR_REPEAT);
if (event != NULL)
{
switch(event->iptkey)
@@ -1508,11 +1364,11 @@ void ui_mess_menu_bitbanger_control(running_machine &machine, ui_menu *menu, voi
if (event->itemref==BITBANGERCMD_SELECT)
{
/* left arrow - rotate left through cassette devices */
- if (menustate->index > 0)
- menustate->index--;
+ if (index > 0)
+ index--;
else
- menustate->index = bitbanger_count(machine) - 1;
- menustate->device = NULL;
+ index = bitbanger_count() - 1;
+ device = NULL;
}
else if (event->itemref==BITBANGERCMD_MODE)
{
@@ -1532,11 +1388,11 @@ void ui_mess_menu_bitbanger_control(running_machine &machine, ui_menu *menu, voi
if (event->itemref==BITBANGERCMD_SELECT)
{
/* right arrow - rotate right through cassette devices */
- if (menustate->index < bitbanger_count(machine) - 1)
- menustate->index++;
+ if (index < bitbanger_count() - 1)
+ index++;
else
- menustate->index = 0;
- menustate->device = NULL;
+ index = 0;
+ device = NULL;
}
else if (event->itemref==BITBANGERCMD_MODE)
{
diff --git a/src/emu/uiimage.h b/src/emu/uiimage.h
index 31881cdbdb9..1687500ee66 100644
--- a/src/emu/uiimage.h
+++ b/src/emu/uiimage.h
@@ -14,18 +14,118 @@
#ifndef __UIIMAGE_H__
#define __UIIMAGE_H__
+class ui_menu_image_info : public ui_menu {
+public:
+ ui_menu_image_info(running_machine &machine, render_container *container);
+ virtual ~ui_menu_image_info();
+ virtual void populate();
+ virtual void handle();
+};
+class ui_menu_file_manager : public ui_menu {
+public:
+ astring *current_directory;
+ astring *current_file;
+ device_image_interface *selected_device;
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+ ui_menu_file_manager(running_machine &machine, render_container *container);
+ virtual ~ui_menu_file_manager();
+ virtual void populate();
+ virtual void handle();
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
+
+private:
+ void fix_working_directory(device_image_interface *image);
+};
+
+class ui_menu_mess_tape_control : public ui_menu {
+public:
+ ui_menu_mess_tape_control(running_machine &machine, render_container *container);
+ virtual ~ui_menu_mess_tape_control();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ int index;
+ device_image_interface *device;
+ int cassette_count();
+};
+
+class ui_menu_mess_bitbanger_control : public ui_menu {
+public:
+ ui_menu_mess_bitbanger_control(running_machine &machine, render_container *container);
+ virtual ~ui_menu_mess_bitbanger_control();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ int index;
+ device_image_interface *device;
+ int bitbanger_count();
+};
+
+class ui_menu_confirm_save_as : public ui_menu {
+public:
+ ui_menu_confirm_save_as(running_machine &machine, render_container *container, int *yes);
+ virtual ~ui_menu_confirm_save_as();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ int *yes;
+};
+
+class ui_menu_file_create : public ui_menu {
+public:
+ ui_menu_file_create(running_machine &machine, render_container *container, ui_menu_file_manager *parent);
+ virtual ~ui_menu_file_create();
+ virtual void populate();
+ virtual void handle();
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
+
+private:
+ ui_menu_file_manager *manager;
+ const image_device_format *current_format;
+ int confirm_save_as_yes;
+ char filename_buffer[1024];
+
+ int create_new_image(device_image_interface *image, const char *directory, const char *filename, int *yes);
+};
+
+class ui_menu_file_selector : public ui_menu {
+public:
+ ui_menu_file_selector(running_machine &machine, render_container *container, ui_menu_file_manager *parent);
+ virtual ~ui_menu_file_selector();
+ virtual void populate();
+ virtual void handle();
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
+
+private:
+ enum file_selector_entry_type {
+ SELECTOR_ENTRY_TYPE_EMPTY,
+ SELECTOR_ENTRY_TYPE_CREATE,
+ SELECTOR_ENTRY_TYPE_SOFTWARE_LIST,
+ SELECTOR_ENTRY_TYPE_DRIVE,
+ SELECTOR_ENTRY_TYPE_DIRECTORY,
+ SELECTOR_ENTRY_TYPE_FILE
+ };
-void ui_image_menu_file_manager(running_machine &machine, ui_menu *menu, void *parameter, void *state);
+ struct file_selector_entry {
+ file_selector_entry *next;
-void ui_image_menu_image_info(running_machine &machine, ui_menu *menu, void *parameter, void *state);
+ file_selector_entry_type type;
+ const char *basename;
+ const char *fullpath;
+ };
-void ui_mess_menu_bitbanger_control(running_machine &machine, ui_menu *menu, void *parameter, void *state);
+ ui_menu_file_manager *manager;
+ file_selector_entry *entrylist;
+ char filename_buffer[1024];
-void ui_mess_menu_tape_control(running_machine &machine, ui_menu *menu, void *parameter, void *state);
+ int compare_entries(const file_selector_entry *e1, const file_selector_entry *e2);
+ file_selector_entry *append_entry(file_selector_entry_type entry_type, const char *entry_basename, const char *entry_fullpath);
+ file_selector_entry *append_dirent_entry(const osd_directory_entry *dirent);
+ void append_entry_menu_item(const file_selector_entry *entry);
+};
#endif /* __UIIMAGE_H__ */
diff --git a/src/emu/uimain.c b/src/emu/uimain.c
new file mode 100644
index 00000000000..fb0a924e6d9
--- /dev/null
+++ b/src/emu/uimain.c
@@ -0,0 +1,2762 @@
+/*********************************************************************
+
+ uimenu.c
+
+ Internal MAME menus for the user interface.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#include "emu.h"
+#include "osdnet.h"
+#include "emuopts.h"
+#include "ui.h"
+#include "rendutil.h"
+#include "cheat.h"
+#include "uiimage.h"
+#include "uiinput.h"
+#include "uimenu.h"
+#include "uimain.h"
+#include "audit.h"
+#include "crsshair.h"
+#include <ctype.h>
+#include "imagedev/cassette.h"
+#include "imagedev/bitbngr.h"
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define MAX_PHYSICAL_DIPS 10
+#define MAX_INPUT_PORTS 32
+#define MAX_BITS_PER_PORT 32
+
+/* DIP switch rendering parameters */
+#define DIP_SWITCH_HEIGHT 0.05f
+#define DIP_SWITCH_SPACING 0.01
+#define SINGLE_TOGGLE_SWITCH_FIELD_WIDTH 0.025f
+#define SINGLE_TOGGLE_SWITCH_WIDTH 0.020f
+/* make the switch 80% of the width space and 1/2 of the switch height */
+#define PERCENTAGE_OF_HALF_FIELD_USED 0.80f
+#define SINGLE_TOGGLE_SWITCH_HEIGHT ((DIP_SWITCH_HEIGHT / 2) * PERCENTAGE_OF_HALF_FIELD_USED)
+
+/*-------------------------------------------------
+ ui_slider_ui_handler - pushes the slider
+ menu on the stack and hands off to the
+ standard menu handler
+-------------------------------------------------*/
+
+UINT32 ui_menu_sliders::ui_handler(running_machine &machine, render_container *container, UINT32 state)
+{
+ UINT32 result;
+
+ /* if this is the first call, push the sliders menu */
+ if (state)
+ ui_menu::stack_push(auto_alloc_clear(machine, ui_menu_sliders(machine, container, true)));
+
+ /* handle standard menus */
+ result = ui_menu::ui_handler(machine, container, state);
+
+ /* if we are cancelled, pop the sliders menu */
+ if (result == UI_HANDLER_CANCEL)
+ ui_menu::stack_pop(machine);
+
+ ui_menu_sliders *uim = dynamic_cast<ui_menu_sliders *>(menu_stack);
+ return uim && uim->menuless_mode ? 0 : UI_HANDLER_CANCEL;
+}
+
+
+/*-------------------------------------------------
+ ui_menu_force_game_select - force the game
+ select menu to be visible and inescapable
+-------------------------------------------------*/
+
+void ui_menu_force_game_select(running_machine &machine, render_container *container)
+{
+ char *gamename = (char *)machine.options().system_name();
+
+ /* reset the menu stack */
+ ui_menu::stack_reset(machine);
+
+ /* add the quit entry followed by the game select entry */
+ ui_menu *quit = auto_alloc_clear(machine, ui_menu_quit_game(machine, container));
+ quit->set_special_main_menu(true);
+ ui_menu::stack_push(quit);
+ ui_menu::stack_push(auto_alloc_clear(machine, ui_menu_select_game(machine, container, gamename)));
+
+ /* force the menus on */
+ ui_show_menu();
+
+ /* make sure MAME is paused */
+ machine.pause();
+}
+
+
+/***************************************************************************
+ MENU HANDLERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ui_menu_main constructor - populate the main menu
+-------------------------------------------------*/
+
+ui_menu_main::ui_menu_main(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_main::populate()
+{
+ input_field_config *field;
+ input_port_config *port;
+ int has_configs = false;
+ int has_analog = false;
+ int has_dips = false;
+ astring menu_text;
+ /* scan the input port array to see what options we need to enable */
+ for (port = machine().m_portlist.first(); port != NULL; port = port->next())
+ for (field = port->fieldlist().first(); field != NULL; field = field->next())
+ {
+ if (field->type == IPT_DIPSWITCH)
+ has_dips = true;
+ if (field->type == IPT_CONFIG)
+ has_configs = true;
+ if (input_type_is_analog(field->type))
+ has_analog = true;
+ }
+
+ /* add input menu items */
+ item_append("Input (general)", NULL, 0, (void *)INPUT_GROUPS);
+
+ menu_text.printf("Input (this %s)",emulator_info::get_capstartgamenoun());
+ item_append(menu_text.cstr(), NULL, 0, (void *)INPUT_SPECIFIC);
+
+ /* add optional input-related menus */
+ if (has_dips)
+ item_append("Dip Switches", NULL, 0, (void *)SETTINGS_DIP_SWITCHES);
+ if (has_configs)
+ item_append("Driver Configuration", NULL, 0, (void *)SETTINGS_DRIVER_CONFIG);
+ if (has_analog)
+ item_append("Analog Controls", NULL, 0, (void *)ANALOG);
+
+ /* add bookkeeping menu */
+ item_append("Bookkeeping Info", NULL, 0, (void *)BOOKKEEPING);
+
+ /* add game info menu */
+ menu_text.printf("%s Information",emulator_info::get_capstartgamenoun());
+ item_append(menu_text.cstr(), NULL, 0, (void *)GAME_INFO);
+
+ device_image_interface *image = NULL;
+ if (machine().devicelist().first(image))
+ {
+ /* add image info menu */
+ item_append("Image Information", NULL, 0, (void *)IMAGE_MENU_IMAGE_INFO);
+
+ /* add file manager menu */
+ item_append("File Manager", NULL, 0, (void *)IMAGE_MENU_FILE_MANAGER);
+
+ /* add tape control menu */
+ if (machine().devicelist().first(CASSETTE))
+ item_append("Tape Control", NULL, 0, (void *)MESS_MENU_TAPE_CONTROL);
+
+ /* add bitbanger control menu */
+ if (machine().devicelist().first(BITBANGER))
+ item_append("Bitbanger Control", NULL, 0, (void *)MESS_MENU_BITBANGER_CONTROL);
+ }
+
+ device_slot_interface *slot = NULL;
+ if (machine().devicelist().first(slot))
+ {
+ /* add image info menu */
+ item_append("Slot Devices", NULL, 0, (void *)SLOT_DEVICES);
+ }
+
+ device_network_interface *network = NULL;
+ if (machine().devicelist().first(network))
+ {
+ /* add image info menu */
+ item_append("Network Devices", NULL, 0, (void*)NETWORK_DEVICES);
+ }
+
+ /* add keyboard mode menu */
+ if (input_machine_has_keyboard(machine()) && inputx_can_post(machine()))
+ item_append("Keyboard Mode", NULL, 0, (void *)KEYBOARD_MODE);
+
+ /* add sliders menu */
+ item_append("Slider Controls", NULL, 0, (void *)SLIDERS);
+
+ /* add video options menu */
+ item_append("Video Options", NULL, 0, (machine().render().target_by_index(1) != NULL) ? (void *)VIDEO_TARGETS : (void *)VIDEO_OPTIONS);
+
+ /* add crosshair options menu */
+ if (crosshair_get_usage(machine()))
+ item_append("Crosshair Options", NULL, 0, (void *)CROSSHAIR);
+
+ /* add cheat menu */
+ if (machine().options().cheat() && machine().cheat().first() != NULL)
+ item_append("Cheat", NULL, 0, (void *)CHEAT);
+
+ /* add memory card menu */
+ if (machine().config().m_memcard_handler != NULL)
+ item_append("Memory Card", NULL, 0, (void *)MEMORY_CARD);
+
+ /* add reset and exit menus */
+ menu_text.printf("Select New %s",emulator_info::get_capstartgamenoun());
+ item_append(menu_text.cstr(), NULL, 0, (void *)SELECT_GAME);
+}
+
+ui_menu_main::~ui_menu_main()
+{
+}
+
+/*-------------------------------------------------
+ menu_main - handle the main menu
+-------------------------------------------------*/
+
+void ui_menu_main::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT) {
+ switch((long long)(menu_event->itemref)) {
+ case INPUT_GROUPS:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_groups(machine(), container)));
+ break;
+
+ case INPUT_SPECIFIC:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_specific(machine(), container)));
+ break;
+
+ case SETTINGS_DIP_SWITCHES:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_settings_dip_switches(machine(), container)));
+ break;
+
+ case SETTINGS_DRIVER_CONFIG:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_settings_driver_config(machine(), container)));
+ break;
+
+ case ANALOG:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_analog(machine(), container)));
+ break;
+
+ case BOOKKEEPING:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_bookkeeping(machine(), container)));
+ break;
+
+ case GAME_INFO:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_game_info(machine(), container)));
+ break;
+
+ case IMAGE_MENU_IMAGE_INFO:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_image_info(machine(), container)));
+ break;
+
+ case IMAGE_MENU_FILE_MANAGER:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_file_manager(machine(), container)));
+ break;
+
+ case MESS_MENU_TAPE_CONTROL:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_mess_tape_control(machine(), container)));
+ break;
+
+ case MESS_MENU_BITBANGER_CONTROL:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_mess_bitbanger_control(machine(), container)));
+ break;
+
+ case SLOT_DEVICES:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_slot_devices(machine(), container)));
+ break;
+
+ case NETWORK_DEVICES:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_network_devices(machine(), container)));
+ break;
+
+ case KEYBOARD_MODE:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_keyboard_mode(machine(), container)));
+ break;
+
+ case SLIDERS:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_sliders(machine(), container, false)));
+ break;
+
+ case VIDEO_TARGETS:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_video_targets(machine(), container)));
+ break;
+
+ case VIDEO_OPTIONS:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_video_options(machine(), container, machine().render().first_target())));
+ break;
+
+ case CROSSHAIR:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_crosshair(machine(), container)));
+ break;
+
+ case CHEAT:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_cheat(machine(), container)));
+ break;
+
+ case MEMORY_CARD:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_memory_card(machine(), container)));
+ break;
+
+ case SELECT_GAME:
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_select_game(machine(), container, 0)));
+ break;
+
+ default:
+ abort();
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ ui_menu_keyboard_mode - menu that
+-------------------------------------------------*/
+
+ui_menu_keyboard_mode::ui_menu_keyboard_mode(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_keyboard_mode::populate()
+{
+ int natural = ui_get_use_natural_keyboard(machine());
+ item_append("Keyboard Mode:", natural ? "Natural" : "Emulated", natural ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, NULL);
+}
+
+ui_menu_keyboard_mode::~ui_menu_keyboard_mode()
+{
+}
+
+void ui_menu_keyboard_mode::handle()
+{
+ int natural = ui_get_use_natural_keyboard(machine());
+
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != NULL)
+ {
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) {
+ ui_set_use_natural_keyboard(machine(), natural ^ true);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ ui_slot_get_current_index - returns
+-------------------------------------------------*/
+int ui_menu_slot_devices::slot_get_current_index(device_slot_interface *slot)
+{
+ const char *current = machine().options().value(slot->device().tag());
+ const slot_interface* intf = slot->get_slot_interfaces();
+ int val = -1;
+ for (int i = 0; intf[i].name != NULL; i++) {
+ if (strcmp(current, intf[i].name) == 0) val = i;
+ }
+ return val;
+}
+
+/*-------------------------------------------------
+ ui_slot_get_length - returns
+-------------------------------------------------*/
+int ui_menu_slot_devices::slot_get_length(device_slot_interface *slot)
+{
+ const slot_interface* intf = slot->get_slot_interfaces();
+ int val = 0;
+ for (int i = 0; intf[i].name != NULL; i++) val++;
+ return val;
+}
+
+/*-------------------------------------------------
+ ui_slot_get_next - returns
+-------------------------------------------------*/
+const char *ui_menu_slot_devices::slot_get_next(device_slot_interface *slot)
+{
+ int idx = slot_get_current_index(slot) + 1;
+ if (idx==slot_get_length(slot)) return "";
+ return slot->get_slot_interfaces()[idx].name;
+}
+
+/*-------------------------------------------------
+ ui_slot_get_prev - returns
+-------------------------------------------------*/
+const char *ui_menu_slot_devices::slot_get_prev(device_slot_interface *slot)
+{
+ int idx = slot_get_current_index(slot) - 1;
+ if (idx==-1) return "";
+ if (idx==-2) idx = slot_get_length(slot) -1;
+ if (idx==-1) return "";
+ return slot->get_slot_interfaces()[idx].name;
+}
+
+/*-------------------------------------------------
+ ui_get_slot_device - returns
+-------------------------------------------------*/
+const char *ui_menu_slot_devices::get_slot_device(device_slot_interface *slot)
+{
+ return machine().options().value(slot->device().tag());
+}
+
+
+/*-------------------------------------------------
+ ui_set_use_natural_keyboard - specifies
+ whether the natural keyboard is active
+-------------------------------------------------*/
+
+void ui_menu_slot_devices::set_slot_device(device_slot_interface *slot, const char *val)
+{
+ astring error;
+ machine().options().set_value(slot->device().tag(), val, OPTION_PRIORITY_CMDLINE, error);
+ assert(!error);
+}
+
+/*-------------------------------------------------
+ menu_slot_devices_populate - populates the main
+ slot device menu
+-------------------------------------------------*/
+
+ui_menu_slot_devices::ui_menu_slot_devices(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_slot_devices::populate()
+{
+ device_slot_interface *slot = NULL;
+
+ /* cycle through all devices for this system */
+ for (bool gotone = machine().devicelist().first(slot); gotone; gotone = slot->next(slot))
+ {
+ /* record the menu item */
+ const char *title = get_slot_device(slot);
+ item_append(slot->device().tag(), strcmp(title,"")==0 ? "------" : title, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)slot);
+ }
+ item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ item_append("Reset", NULL, 0, NULL);
+}
+
+ui_menu_slot_devices::~ui_menu_slot_devices()
+{
+}
+
+/*-------------------------------------------------
+ ui_menu_slot_devices - menu that
+-------------------------------------------------*/
+
+void ui_menu_slot_devices::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) {
+ device_slot_interface *slot = (device_slot_interface *)menu_event->itemref;
+ const char *val = (menu_event->iptkey == IPT_UI_LEFT) ? slot_get_prev(slot) : slot_get_next(slot);
+ set_slot_device(slot,val);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ } else if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT) {
+ machine().schedule_hard_reset();
+ }
+}
+
+ui_menu_network_devices::ui_menu_network_devices(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_network_devices::~ui_menu_network_devices()
+{
+}
+
+/*-------------------------------------------------
+ menu_network_devices_populate - populates the main
+ network device menu
+-------------------------------------------------*/
+
+void ui_menu_network_devices::populate()
+{
+ device_network_interface *network = NULL;
+
+ /* cycle through all devices for this system */
+ for (bool gotone = machine().devicelist().first(network); gotone; gotone = network->next(network))
+ {
+ int curr = network->get_interface();
+ const char *title = NULL;
+ const netdev_entry_t *entry = netdev_first();
+ while(entry) {
+ if(entry->id==curr) {
+ title = entry->description;
+ break;
+ }
+ entry = entry->m_next;
+ }
+
+ item_append(network->device().tag(), (title) ? title : "------", MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)network);
+ }
+}
+
+/*-------------------------------------------------
+ ui_menu_network_devices - menu that
+-------------------------------------------------*/
+
+void ui_menu_network_devices::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) {
+ device_network_interface *network = (device_network_interface *)menu_event->itemref;
+ int curr = network->get_interface();
+ if (menu_event->iptkey == IPT_UI_LEFT) curr--; else curr++;
+ if (curr==-2) curr = netdev_count() - 1;
+ network->set_interface(curr);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+}
+
+/*-------------------------------------------------
+ menu_input_groups_populate - populate the
+ input groups menu
+-------------------------------------------------*/
+
+ui_menu_input_groups::ui_menu_input_groups(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_input_groups::populate()
+{
+ int player;
+
+ /* build up the menu */
+ item_append("User Interface", NULL, 0, (void *)(IPG_UI + 1));
+ for (player = 0; player < MAX_PLAYERS; player++)
+ {
+ char buffer[40];
+ sprintf(buffer, "Player %d Controls", player + 1);
+ item_append(buffer, NULL, 0, (void *)(FPTR)(IPG_PLAYER1 + player + 1));
+ }
+ item_append("Other Controls", NULL, 0, (void *)(FPTR)(IPG_OTHER + 1));
+}
+
+ui_menu_input_groups::~ui_menu_input_groups()
+{
+}
+
+/*-------------------------------------------------
+ menu_input_groups - handle the input groups
+ menu
+-------------------------------------------------*/
+
+void ui_menu_input_groups::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_general(machine(), container, int((long long)(menu_event->itemref)-1))));
+}
+
+
+
+/*-------------------------------------------------
+ menu_input_general - handle the general
+ input menu
+-------------------------------------------------*/
+
+ui_menu_input_general::ui_menu_input_general(running_machine &machine, render_container *container, int _group) : ui_menu_input(machine, container)
+{
+ group = _group;
+}
+
+void ui_menu_input_general::populate()
+{
+ input_item_data *itemlist = NULL;
+ int suborder[SEQ_TYPE_TOTAL];
+ astring tempstring;
+ int sortorder = 1;
+
+ /* create a mini lookup table for sort order based on sequence type */
+ suborder[SEQ_TYPE_STANDARD] = 0;
+ suborder[SEQ_TYPE_DECREMENT] = 1;
+ suborder[SEQ_TYPE_INCREMENT] = 2;
+
+ /* iterate over the input ports and add menu items */
+ for (input_type_entry *entry = input_type_list(machine()).first(); entry != NULL; entry = entry->next())
+
+ /* add if we match the group and we have a valid name */
+ if (entry->group == group && entry->name != NULL && entry->name[0] != 0)
+ {
+ input_seq_type seqtype;
+
+ /* loop over all sequence types */
+ sortorder++;
+ for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ {
+ /* build an entry for the standard sequence */
+ input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item));
+ memset(item, 0, sizeof(*item));
+ item->ref = entry;
+ item->seqtype = seqtype;
+ item->seq = input_type_seq(machine(), entry->type, entry->player, seqtype);
+ item->defseq = &entry->defseq[seqtype];
+ item->sortorder = sortorder * 4 + suborder[seqtype];
+ item->type = input_type_is_analog(entry->type) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
+ item->name = entry->name;
+ item->next = itemlist;
+ itemlist = item;
+
+ /* stop after one, unless we're analog */
+ if (item->type == INPUT_TYPE_DIGITAL)
+ break;
+ }
+ }
+
+ /* sort and populate the menu in a standard fashion */
+ populate_and_sort(itemlist);
+}
+
+ui_menu_input_general::~ui_menu_input_general()
+{
+}
+
+/*-------------------------------------------------
+ menu_input_specific - handle the game-specific
+ input menu
+-------------------------------------------------*/
+
+ui_menu_input_specific::ui_menu_input_specific(running_machine &machine, render_container *container) : ui_menu_input(machine, container)
+{
+}
+
+void ui_menu_input_specific::populate()
+{
+ input_item_data *itemlist = NULL;
+ input_field_config *field;
+ input_port_config *port;
+ int suborder[SEQ_TYPE_TOTAL];
+ astring tempstring;
+
+ /* create a mini lookup table for sort order based on sequence type */
+ suborder[SEQ_TYPE_STANDARD] = 0;
+ suborder[SEQ_TYPE_DECREMENT] = 1;
+ suborder[SEQ_TYPE_INCREMENT] = 2;
+
+ /* iterate over the input ports and add menu items */
+ for (port = machine().m_portlist.first(); port != NULL; port = port->next())
+ for (field = port->fieldlist().first(); field != NULL; field = field->next())
+ {
+ const char *name = input_field_name(field);
+
+ /* add if we match the group and we have a valid name */
+ if (name != NULL && input_condition_true(machine(), &field->condition, port->owner()) &&
+ ((field->type == IPT_OTHER && field->name != NULL) || input_type_group(machine(), field->type, field->player) != IPG_INVALID))
+ {
+ input_seq_type seqtype;
+ UINT16 sortorder;
+
+ /* determine the sorting order */
+ if (field->type >= IPT_START1 && field->type <= __ipt_analog_end)
+ sortorder = (field->type << 2) | (field->player << 12);
+ else
+ sortorder = field->type | 0xf000;
+
+ /* loop over all sequence types */
+ for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
+ {
+ /* build an entry for the standard sequence */
+ input_item_data *item = (input_item_data *)m_pool_alloc(sizeof(*item));
+ memset(item, 0, sizeof(*item));
+ item->ref = field;
+ item->seqtype = seqtype;
+ item->seq = input_field_seq(field, seqtype);
+ item->defseq = &get_field_default_seq(field, seqtype);
+ item->sortorder = sortorder + suborder[seqtype];
+ item->type = input_type_is_analog(field->type) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
+ item->name = name;
+ item->next = itemlist;
+ itemlist = item;
+
+ /* stop after one, unless we're analog */
+ if (item->type == INPUT_TYPE_DIGITAL)
+ break;
+ }
+ }
+ }
+
+ /* sort and populate the menu in a standard fashion */
+ populate_and_sort(itemlist);
+}
+
+ui_menu_input_specific::~ui_menu_input_specific()
+{
+}
+
+/*-------------------------------------------------
+ menu_input - display a menu for inputs
+-------------------------------------------------*/
+ui_menu_input::ui_menu_input(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_input::~ui_menu_input()
+{
+}
+
+/*-------------------------------------------------
+ toggle_none_default - toggle between "NONE"
+ and the default item
+-------------------------------------------------*/
+
+void ui_menu_input::toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq)
+{
+ /* if we used to be "none", toggle to the default value */
+ if (original_seq.length() == 0)
+ selected_seq = selected_defseq;
+
+ /* otherwise, toggle to "none" */
+ else
+ selected_seq.reset();
+}
+
+/*-------------------------------------------------
+ get_field_default_seq - return a pointer
+ to the default sequence for the given field
+-------------------------------------------------*/
+
+const input_seq &ui_menu_input::get_field_default_seq(input_field_config *field, input_seq_type seqtype)
+{
+ if (field->seq[seqtype].is_default())
+ return input_type_seq(field->machine(), field->type, field->player, seqtype);
+ else
+ return field->seq[seqtype];
+}
+
+void ui_menu_input::handle()
+{
+ input_item_data *seqchangeditem = NULL;
+ const ui_menu_event *menu_event;
+ int invalidate = false;
+
+ /* process the menu */
+ menu_event = process((pollingitem != NULL) ? UI_MENU_PROCESS_NOKEYS : 0);
+
+ /* if we are polling, handle as a special case */
+ if (pollingitem != NULL)
+ {
+ input_item_data *item = pollingitem;
+ input_seq newseq;
+
+ /* if UI_CANCEL is pressed, abort */
+ if (ui_input_pressed(machine(), IPT_UI_CANCEL))
+ {
+ pollingitem = NULL;
+ record_next = false;
+ toggle_none_default(item->seq, starting_seq, *item->defseq);
+ seqchangeditem = item;
+ }
+
+ /* poll again; if finished, update the sequence */
+ if (machine().input().seq_poll())
+ {
+ pollingitem = NULL;
+ record_next = true;
+ item->seq = machine().input().seq_poll_final();
+ seqchangeditem = item;
+ }
+ }
+
+ /* otherwise, handle the events */
+ else if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ input_item_data *item = (input_item_data *)menu_event->itemref;
+ switch (menu_event->iptkey)
+ {
+ /* an item was selected: begin polling */
+ case IPT_UI_SELECT:
+ pollingitem = item;
+ last_sortorder = item->sortorder;
+ starting_seq = item->seq;
+ machine().input().seq_poll_start((item->type == INPUT_TYPE_ANALOG) ? ITEM_CLASS_ABSOLUTE : ITEM_CLASS_SWITCH, record_next ? &item->seq : NULL);
+ invalidate = true;
+ break;
+
+ /* if the clear key was pressed, reset the selected item */
+ case IPT_UI_CLEAR:
+ toggle_none_default(item->seq, item->seq, *item->defseq);
+ record_next = false;
+ seqchangeditem = item;
+ break;
+ }
+
+ /* if the selection changed, reset the "record next" flag */
+ if (item->sortorder != last_sortorder)
+ record_next = false;
+ last_sortorder = item->sortorder;
+ }
+
+ /* if the sequence changed, update it */
+ if (seqchangeditem != NULL)
+ {
+ update_input(seqchangeditem);
+
+ /* invalidate the menu to force an update */
+ invalidate = true;
+ }
+
+ /* if the menu is invalidated, clear it now */
+ if (invalidate)
+ {
+ pollingref = NULL;
+ if (pollingitem != NULL)
+ pollingref = pollingitem->ref;
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+}
+
+void ui_menu_input_general::update_input(struct input_item_data *seqchangeditem)
+{
+ const input_type_entry *entry = (const input_type_entry *)seqchangeditem->ref;
+ input_type_set_seq(machine(), entry->type, entry->player, seqchangeditem->seqtype, &seqchangeditem->seq);
+}
+
+void ui_menu_input_specific::update_input(struct input_item_data *seqchangeditem)
+{
+ input_field_user_settings settings;
+
+ input_field_get_user_settings((input_field_config *)seqchangeditem->ref, &settings);
+ settings.seq[seqchangeditem->seqtype] = seqchangeditem->seq;
+ input_field_set_user_settings((input_field_config *)seqchangeditem->ref, &settings);
+}
+
+
+/*-------------------------------------------------
+ menu_input_compare_items - compare two
+ items for quicksort
+-------------------------------------------------*/
+
+int ui_menu_input::compare_items(const void *i1, const void *i2)
+{
+ const input_item_data * const *data1 = (const input_item_data * const *)i1;
+ const input_item_data * const *data2 = (const input_item_data * const *)i2;
+ if ((*data1)->sortorder < (*data2)->sortorder)
+ return -1;
+ if ((*data1)->sortorder > (*data2)->sortorder)
+ return 1;
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ menu_input_populate_and_sort - take a list
+ of input_item_data objects and build up the
+ menu from them
+-------------------------------------------------*/
+
+void ui_menu_input::populate_and_sort(input_item_data *itemlist)
+{
+ const char *nameformat[INPUT_TYPE_TOTAL] = { 0 };
+ input_item_data **itemarray, *item;
+ int numitems = 0, curitem;
+ astring subtext;
+ astring text;
+
+ /* create a mini lookup table for name format based on type */
+ nameformat[INPUT_TYPE_DIGITAL] = "%s";
+ nameformat[INPUT_TYPE_ANALOG] = "%s Analog";
+ nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc";
+ nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec";
+
+ /* first count the number of items */
+ for (item = itemlist; item != NULL; item = item->next)
+ numitems++;
+
+ /* now allocate an array of items and fill it up */
+ itemarray = (input_item_data **)m_pool_alloc(sizeof(*itemarray) * numitems);
+ for (item = itemlist, curitem = 0; item != NULL; item = item->next)
+ itemarray[curitem++] = item;
+
+ /* sort it */
+ qsort(itemarray, numitems, sizeof(*itemarray), compare_items);
+
+ /* build the menu */
+ for (curitem = 0; curitem < numitems; curitem++)
+ {
+ UINT32 flags = 0;
+
+ /* generate the name of the item itself, based off the base name and the type */
+ item = itemarray[curitem];
+ assert(nameformat[item->type] != NULL);
+ text.printf(nameformat[item->type], item->name);
+
+ /* if we're polling this item, use some spaces with left/right arrows */
+ if (pollingref == item->ref)
+ {
+ subtext.cpy(" ");
+ flags |= MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
+ }
+
+ /* otherwise, generate the sequence name and invert it if different from the default */
+ else
+ {
+ machine().input().seq_name(subtext, item->seq);
+ flags |= (item->seq != *item->defseq) ? MENU_FLAG_INVERT : 0;
+ }
+
+ /* add the item */
+ item_append(text, subtext, flags, item);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_settings_dip_switches - handle the DIP
+ switches menu
+-------------------------------------------------*/
+
+ui_menu_settings_dip_switches::ui_menu_settings_dip_switches(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_DIPSWITCH)
+{
+ custombottom = dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING;
+}
+
+ui_menu_settings_dip_switches::~ui_menu_settings_dip_switches()
+{
+}
+
+/*-------------------------------------------------
+ menu_settings_driver_config - handle the
+ driver config menu
+-------------------------------------------------*/
+
+ui_menu_settings_driver_config::ui_menu_settings_driver_config(running_machine &machine, render_container *container) : ui_menu_settings(machine, container, IPT_CONFIG)
+{
+}
+
+ui_menu_settings_driver_config::~ui_menu_settings_driver_config()
+{
+}
+
+/*-------------------------------------------------
+ menu_settings_common - handle one of the
+ switches menus
+-------------------------------------------------*/
+
+void ui_menu_settings::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+
+ /* handle events */
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ input_field_config *field = (input_field_config *)menu_event->itemref;
+ input_field_user_settings settings;
+ int changed = false;
+
+ switch (menu_event->iptkey)
+ {
+ /* if selected, reset to default value */
+ case IPT_UI_SELECT:
+ input_field_get_user_settings(field, &settings);
+ settings.value = field->defvalue;
+ input_field_set_user_settings(field, &settings);
+ changed = true;
+ break;
+
+ /* left goes to previous setting */
+ case IPT_UI_LEFT:
+ input_field_select_previous_setting(field);
+ changed = true;
+ break;
+
+ /* right goes to next setting */
+ case IPT_UI_RIGHT:
+ input_field_select_next_setting(field);
+ changed = true;
+ break;
+ }
+
+ /* if anything changed, rebuild the menu, trying to stay on the same field */
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_settings_populate - populate one of the
+ switches menus
+-------------------------------------------------*/
+
+ui_menu_settings::ui_menu_settings(running_machine &machine, render_container *container, UINT32 _type) : ui_menu(machine, container)
+{
+ type = _type;
+}
+
+void ui_menu_settings::populate()
+{
+ input_field_config *field;
+ input_port_config *port;
+ dip_descriptor **diplist_tailptr;
+
+ /* reset the dip switch tracking */
+ dipcount = 0;
+ diplist = NULL;
+ diplist_tailptr = &diplist;
+
+ /* loop over input ports and set up the current values */
+ for (port = machine().m_portlist.first(); port != NULL; port = port->next())
+ for (field = port->fieldlist().first(); field != NULL; field = field->next())
+ if (field->type == type && input_condition_true(machine(), &field->condition, port->owner()))
+ {
+ UINT32 flags = 0;
+
+ /* set the left/right flags appropriately */
+ if (input_field_has_previous_setting(field))
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (input_field_has_next_setting(field))
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* add the menu item */
+ item_append(input_field_name(field), input_field_setting_name(field), flags, (void *)field);
+
+ /* for DIP switches, build up the model */
+ if (type == IPT_DIPSWITCH && field->diploclist().count() != 0)
+ {
+ const input_field_diplocation *diploc;
+ input_field_user_settings settings;
+ UINT32 accummask = field->mask;
+
+ /* get current settings */
+ input_field_get_user_settings(field, &settings);
+
+ /* iterate over each bit in the field */
+ for (diploc = field->diploclist().first(); diploc != NULL; diploc = diploc->next())
+ {
+ UINT32 mask = accummask & ~(accummask - 1);
+ dip_descriptor *dip;
+
+ /* find the matching switch name */
+ for (dip = diplist; dip != NULL; dip = dip->next)
+ if (strcmp(dip->name, diploc->swname) == 0)
+ break;
+
+ /* allocate new if none */
+ if (dip == NULL)
+ {
+ dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip));
+ dip->next = NULL;
+ dip->name = diploc->swname;
+ dip->mask = dip->state = 0;
+ *diplist_tailptr = dip;
+ diplist_tailptr = &dip->next;
+ if (mame_stricmp(dip->name, "FAKE") != 0)
+ dipcount++;
+ }
+
+ /* apply the bits */
+ dip->mask |= 1 << (diploc->swnum - 1);
+ if (((settings.value & mask) != 0 && !diploc->invert) || ((settings.value & mask) == 0 && diploc->invert))
+ dip->state |= 1 << (diploc->swnum - 1);
+
+ /* clear the relevant bit in the accumulated mask */
+ accummask &= ~mask;
+ }
+ }
+ }
+}
+
+ui_menu_settings::~ui_menu_settings()
+{
+}
+
+/*-------------------------------------------------
+ menu_settings_custom_render - perform our special
+ rendering
+-------------------------------------------------*/
+
+void ui_menu_settings_dip_switches::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
+{
+ input_field_config *field = (input_field_config *)selectedref;
+ dip_descriptor *dip;
+
+ /* add borders */
+ y1 = y2 + UI_BOX_TB_BORDER;
+ y2 = y1 + bottom;
+
+ /* draw extra menu area */
+ ui_draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+ y1 += (float)DIP_SWITCH_SPACING;
+
+ /* iterate over DIP switches */
+ for (dip = diplist; dip != NULL; dip = dip->next)
+ {
+ if (mame_stricmp(dip->name, "FAKE") != 0)
+ {
+ const input_field_diplocation *diploc;
+ UINT32 selectedmask = 0;
+
+ /* determine the mask of selected bits */
+ if (field != NULL)
+ for (diploc = field->diploclist().first(); diploc != NULL; diploc = diploc->next())
+ if (strcmp(dip->name, diploc->swname) == 0)
+ selectedmask |= 1 << (diploc->swnum - 1);
+
+ /* draw one switch */
+ custom_render_one(x1, y1, x2, y1 + DIP_SWITCH_HEIGHT, dip, selectedmask);
+ y1 += (float)(DIP_SWITCH_SPACING + DIP_SWITCH_HEIGHT);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_settings_custom_render_one - draw a single
+ DIP switch
+-------------------------------------------------*/
+
+void ui_menu_settings_dip_switches::custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask)
+{
+ float switch_field_width = SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * container->manager().ui_aspect();
+ float switch_width = SINGLE_TOGGLE_SWITCH_WIDTH * container->manager().ui_aspect();
+ int numtoggles, toggle;
+ float switch_toggle_gap;
+ float y1_off, y1_on;
+
+ /* determine the number of toggles in the DIP */
+ numtoggles = 32 - count_leading_zeros(dip->mask);
+
+ /* center based on the number of switches */
+ x1 += (x2 - x1 - numtoggles * switch_field_width) / 2;
+
+ /* draw the dip switch name */
+ ui_draw_text_full( container,
+ dip->name,
+ 0,
+ y1 + (DIP_SWITCH_HEIGHT - UI_TARGET_FONT_HEIGHT) / 2,
+ x1 - ui_get_string_width(container->manager().machine(), " "),
+ JUSTIFY_RIGHT,
+ WRAP_NEVER,
+ DRAW_NORMAL,
+ UI_TEXT_COLOR,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA),
+ NULL ,
+ NULL);
+
+ /* compute top and bottom for on and off positions */
+ switch_toggle_gap = ((DIP_SWITCH_HEIGHT/2) - SINGLE_TOGGLE_SWITCH_HEIGHT)/2;
+ y1_off = y1 + UI_LINE_WIDTH + switch_toggle_gap;
+ y1_on = y1 + DIP_SWITCH_HEIGHT/2 + switch_toggle_gap;
+
+ /* iterate over toggles */
+ for (toggle = 0; toggle < numtoggles; toggle++)
+ {
+ float innerx1;
+
+ /* first outline the switch */
+ ui_draw_outlined_box(container, x1, y1, x1 + switch_field_width, y2, UI_BACKGROUND_COLOR);
+
+ /* compute x1/x2 for the inner filled in switch */
+ innerx1 = x1 + (switch_field_width - switch_width) / 2;
+
+ /* see if the switch is actually used */
+ if (dip->mask & (1 << toggle))
+ {
+ float innery1 = (dip->state & (1 << toggle)) ? y1_on : y1_off;
+ container->add_rect(innerx1, innery1, innerx1 + switch_width, innery1 + SINGLE_TOGGLE_SWITCH_HEIGHT,
+ (selectedmask & (1 << toggle)) ? UI_DIPSW_COLOR : UI_TEXT_COLOR,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+ else
+ {
+ container->add_rect(innerx1, y1_off, innerx1 + switch_width, y1_on + SINGLE_TOGGLE_SWITCH_HEIGHT,
+ UI_UNAVAILABLE_COLOR,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ }
+
+ /* advance to the next switch */
+ x1 += switch_field_width;
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_analog - handle the analog settings menu
+-------------------------------------------------*/
+
+void ui_menu_analog::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ /* handle events */
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ analog_item_data *data = (analog_item_data *)menu_event->itemref;
+ int newval = data->cur;
+
+ switch (menu_event->iptkey)
+ {
+ /* if selected, reset to default value */
+ case IPT_UI_SELECT:
+ newval = data->defvalue;
+ break;
+
+ /* left decrements */
+ case IPT_UI_LEFT:
+ newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ /* right increments */
+ case IPT_UI_RIGHT:
+ newval += machine().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)
+ {
+ input_field_user_settings settings;
+
+ /* get the settings and set the new value */
+ input_field_get_user_settings(data->field, &settings);
+ switch (data->type)
+ {
+ case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break;
+ case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break;
+ case ANALOG_ITEM_REVERSE: settings.reverse = newval; break;
+ case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break;
+ }
+ input_field_set_user_settings(data->field, &settings);
+
+ /* rebuild the menu */
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_analog_populate - populate the analog
+ settings menu
+-------------------------------------------------*/
+
+ui_menu_analog::ui_menu_analog(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_analog::populate()
+{
+ input_field_config *field;
+ input_port_config *port;
+ astring subtext;
+ astring text;
+
+ /* loop over input ports and add the items */
+ for (port = machine().m_portlist.first(); port != NULL; port = port->next())
+ for (field = port->fieldlist().first(); field != NULL; field = field->next())
+ if (input_type_is_analog(field->type) && input_condition_true(machine(), &field->condition, port->owner()))
+ {
+ input_field_user_settings settings;
+ int use_autocenter = false;
+ int type;
+
+ /* based on the type, determine if we enable autocenter */
+ switch (field->type)
+ {
+ case IPT_POSITIONAL:
+ case IPT_POSITIONAL_V:
+ if (field->flags & ANALOG_FLAG_WRAPS)
+ break;
+
+ case IPT_AD_STICK_X:
+ case IPT_AD_STICK_Y:
+ case IPT_AD_STICK_Z:
+ case IPT_PADDLE:
+ case IPT_PADDLE_V:
+ case IPT_PEDAL:
+ case IPT_PEDAL2:
+ case IPT_PEDAL3:
+ use_autocenter = true;
+ break;
+ }
+
+ /* get the user settings */
+ input_field_get_user_settings(field, &settings);
+
+ /* iterate over types */
+ for (type = 0; type < ANALOG_ITEM_COUNT; type++)
+ if (type != ANALOG_ITEM_CENTERSPEED || use_autocenter)
+ {
+ analog_item_data *data;
+ UINT32 flags = 0;
+
+ /* allocate a data item for tracking what this menu item refers to */
+ data = (analog_item_data *)m_pool_alloc(sizeof(*data));
+ data->field = field;
+ data->type = type;
+
+ /* determine the properties of this item */
+ switch (type)
+ {
+ default:
+ case ANALOG_ITEM_KEYSPEED:
+ text.printf("%s Digital Speed", input_field_name(field));
+ subtext.printf("%d", settings.delta);
+ data->min = 0;
+ data->max = 255;
+ data->cur = settings.delta;
+ data->defvalue = field->delta;
+ break;
+
+ case ANALOG_ITEM_CENTERSPEED:
+ text.printf("%s Autocenter Speed", input_field_name(field));
+ subtext.printf("%d", settings.centerdelta);
+ data->min = 0;
+ data->max = 255;
+ data->cur = settings.centerdelta;
+ data->defvalue = field->centerdelta;
+ break;
+
+ case ANALOG_ITEM_REVERSE:
+ text.printf("%s Reverse", input_field_name(field));
+ subtext.cpy(settings.reverse ? "On" : "Off");
+ data->min = 0;
+ data->max = 1;
+ data->cur = settings.reverse;
+ data->defvalue = ((field->flags & ANALOG_FLAG_REVERSE) != 0);
+ break;
+
+ case ANALOG_ITEM_SENSITIVITY:
+ text.printf("%s Sensitivity", input_field_name(field));
+ subtext.printf("%d", settings.sensitivity);
+ data->min = 1;
+ data->max = 255;
+ data->cur = settings.sensitivity;
+ data->defvalue = field->sensitivity;
+ break;
+ }
+
+ /* put on arrows */
+ if (data->cur > data->min)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (data->cur < data->max)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+
+ /* append a menu item */
+ item_append(text, subtext, flags, data);
+ }
+ }
+}
+
+ui_menu_analog::~ui_menu_analog()
+{
+}
+
+/*-------------------------------------------------
+ menu_bookkeeping - handle the bookkeeping
+ information menu
+-------------------------------------------------*/
+
+void ui_menu_bookkeeping::handle()
+{
+ attotime curtime;
+
+ /* if the time has rolled over another second, regenerate */
+ curtime = machine().time();
+ if (prevtime.seconds != curtime.seconds)
+ {
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ prevtime = curtime;
+ populate();
+ }
+
+ /* process the menu */
+ process(0);
+}
+
+
+/*-------------------------------------------------
+ menu_bookkeeping - handle the bookkeeping
+ information menu
+-------------------------------------------------*/
+ui_menu_bookkeeping::ui_menu_bookkeeping(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_bookkeeping::~ui_menu_bookkeeping()
+{
+}
+
+void ui_menu_bookkeeping::populate()
+{
+ int tickets = get_dispensed_tickets(machine());
+ astring tempstring;
+ int ctrnum;
+
+ /* show total time first */
+ if (prevtime.seconds >= 60 * 60)
+ tempstring.catprintf("Uptime: %d:%02d:%02d\n\n", prevtime.seconds / (60*60), (prevtime.seconds / 60) % 60, prevtime.seconds % 60);
+ else
+ tempstring.catprintf("Uptime: %d:%02d\n\n", (prevtime.seconds / 60) % 60, prevtime.seconds % 60);
+
+ /* show tickets at the top */
+ if (tickets > 0)
+ tempstring.catprintf("Tickets dispensed: %d\n\n", tickets);
+
+ /* loop over coin counters */
+ for (ctrnum = 0; ctrnum < COIN_COUNTERS; ctrnum++)
+ {
+ int count = coin_counter_get_count(machine(), ctrnum);
+
+ /* display the coin counter number */
+ tempstring.catprintf("Coin %c: ", ctrnum + 'A');
+
+ /* display how many coins */
+ if (count == 0)
+ tempstring.cat("NA");
+ else
+ tempstring.catprintf("%d", count);
+
+ /* display whether or not we are locked out */
+ if (coin_lockout_get_state(machine(), ctrnum))
+ tempstring.cat(" (locked)");
+ tempstring.cat("\n");
+ }
+
+ /* append the single item */
+ item_append(tempstring, NULL, MENU_FLAG_MULTILINE, NULL);
+}
+
+
+/*-------------------------------------------------
+ menu_game_info - handle the game information
+ menu
+-------------------------------------------------*/
+
+ui_menu_game_info::ui_menu_game_info(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_game_info::populate()
+{
+ astring tempstring;
+ item_append(game_info_astring(machine(), tempstring), NULL, MENU_FLAG_MULTILINE, NULL);
+}
+
+void ui_menu_game_info::handle()
+{
+ /* process the menu */
+ process(0);
+}
+
+ui_menu_game_info::~ui_menu_game_info()
+{
+}
+
+/*-------------------------------------------------
+ menu_cheat - handle the cheat menu
+-------------------------------------------------*/
+
+void ui_menu_cheat::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ /* handle events */
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ bool changed = false;
+
+ /* clear cheat comment on any movement or keypress */
+ popmessage(NULL);
+
+ /* handle reset all + reset all cheats for reload all option */
+ if ((FPTR)menu_event->itemref < 3 && menu_event->iptkey == IPT_UI_SELECT)
+ {
+ for (cheat_entry *curcheat = machine().cheat().first(); curcheat != NULL; curcheat = curcheat->next())
+ if (curcheat->select_default_state())
+ changed = true;
+ }
+
+
+ /* handle individual cheats */
+ else if ((FPTR)menu_event->itemref > 2)
+ {
+ cheat_entry *curcheat = reinterpret_cast<cheat_entry *>(menu_event->itemref);
+ const char *string;
+ switch (menu_event->iptkey)
+ {
+ /* if selected, activate a oneshot */
+ case IPT_UI_SELECT:
+ changed = curcheat->activate();
+ break;
+
+ /* if cleared, reset to default value */
+ case IPT_UI_CLEAR:
+ changed = curcheat->select_default_state();
+ break;
+
+ /* left decrements */
+ case IPT_UI_LEFT:
+ changed = curcheat->select_previous_state();
+ break;
+
+ /* right increments */
+ case IPT_UI_RIGHT:
+ changed = curcheat->select_next_state();
+ break;
+
+ /* bring up display comment if one exists */
+ case IPT_UI_DISPLAY_COMMENT:
+ case IPT_UI_UP:
+ case IPT_UI_DOWN:
+ string = curcheat->comment();
+ if (string != NULL && string[0] != 0)
+ popmessage("Cheat Comment:\n%s", string);
+ break;
+ }
+ }
+
+ /* handle reload all */
+ if ((FPTR)menu_event->itemref == 2 && menu_event->iptkey == IPT_UI_SELECT)
+ {
+ /* re-init cheat engine and thus reload cheats/cheats have already been turned off by here */
+ machine().cheat().reload();
+
+ /* display the reloaded cheats */
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ popmessage("All cheats reloaded");
+ }
+
+ /* if things changed, update */
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_cheat_populate - populate the cheat menu
+-------------------------------------------------*/
+
+ui_menu_cheat::ui_menu_cheat(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_cheat::populate()
+{
+ /* iterate over cheats */
+ astring text;
+ astring subtext;
+ for (cheat_entry *curcheat = machine().cheat().first(); curcheat != NULL; curcheat = curcheat->next())
+ {
+ UINT32 flags;
+ curcheat->menu_text(text, subtext, flags);
+ item_append(text, subtext, flags, curcheat);
+ }
+
+ /* add a separator */
+ item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+
+ /* add a reset all option */
+ item_append("Reset All", NULL, 0, (void *)1);
+
+ /* add a reload all cheats option */
+ item_append("Reload All", NULL, 0, (void *)2);
+}
+
+ui_menu_cheat::~ui_menu_cheat()
+{
+}
+
+/*-------------------------------------------------
+ menu_memory_card - handle the memory card
+ menu
+-------------------------------------------------*/
+
+void ui_menu_memory_card::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ /* if something was selected, act on it */
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ FPTR item = (FPTR)menu_event->itemref;
+
+ /* select executes actions on some of the items */
+ if (menu_event->iptkey == IPT_UI_SELECT)
+ {
+ switch (item)
+ {
+ /* handle card loading; if we succeed, clear the menus */
+ case MEMCARD_ITEM_LOAD:
+ if (memcard_insert(machine(), cardnum) == 0)
+ {
+ popmessage("Memory card loaded");
+ ui_menu::stack_reset(machine());
+ }
+ else
+ popmessage("Error loading memory card");
+ break;
+
+ /* handle card ejecting */
+ case MEMCARD_ITEM_EJECT:
+ memcard_eject(machine());
+ popmessage("Memory card ejected");
+ break;
+
+ /* handle card creating */
+ case MEMCARD_ITEM_CREATE:
+ if (memcard_create(machine(), cardnum, false) == 0)
+ popmessage("Memory card created");
+ else
+ popmessage("Error creating memory card\n(Card may already exist)");
+ break;
+ }
+ }
+
+ /* the select item has extra keys */
+ else if (item == MEMCARD_ITEM_SELECT)
+ {
+ switch (menu_event->iptkey)
+ {
+ /* left decrements the card number */
+ case IPT_UI_LEFT:
+ cardnum -= 1;
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ break;
+
+ /* right decrements the card number */
+ case IPT_UI_RIGHT:
+ cardnum += 1;
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ break;
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_memory_card_populate - populate the
+ memory card menu
+-------------------------------------------------*/
+
+ui_menu_memory_card::ui_menu_memory_card(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_memory_card::populate()
+{
+ char tempstring[20];
+ UINT32 flags = 0;
+
+ /* add the card select menu */
+ sprintf(tempstring, "%d", cardnum);
+ if (cardnum > 0)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (cardnum < 1000)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ item_append("Card Number:", tempstring, flags, (void *)MEMCARD_ITEM_SELECT);
+
+ /* add the remaining items */
+ item_append("Load Selected Card", NULL, 0, (void *)MEMCARD_ITEM_LOAD);
+ if (memcard_present(machine()) != -1)
+ item_append("Eject Current Card", NULL, 0, (void *)MEMCARD_ITEM_EJECT);
+ item_append("Create New Card", NULL, 0, (void *)MEMCARD_ITEM_CREATE);
+}
+
+ui_menu_memory_card::~ui_menu_memory_card()
+{
+}
+
+/*-------------------------------------------------
+ menu_sliders - handle the sliders menu
+-------------------------------------------------*/
+
+void ui_menu_sliders::handle()
+{
+ const ui_menu_event *menu_event;
+
+ /* process the menu */
+ menu_event = process(UI_MENU_PROCESS_LR_REPEAT | (hidden ? UI_MENU_PROCESS_CUSTOM_ONLY : 0));
+ if (menu_event != NULL)
+ {
+ /* handle keys if there is a valid item selected */
+ if (menu_event->itemref != NULL)
+ {
+ const slider_state *slider = (const slider_state *)menu_event->itemref;
+ INT32 curvalue = (*slider->update)(machine(), slider->arg, NULL, SLIDER_NOCHANGE);
+ INT32 increment = 0;
+
+ switch (menu_event->iptkey)
+ {
+ /* toggle visibility */
+ case IPT_UI_ON_SCREEN_DISPLAY:
+ if (menuless_mode)
+ ui_menu::stack_pop(machine());
+ else
+ hidden = !hidden;
+ break;
+
+ /* decrease value */
+ case IPT_UI_LEFT:
+ if (machine().input().code_pressed(KEYCODE_LALT) || machine().input().code_pressed(KEYCODE_RALT))
+ increment = -1;
+ else if (machine().input().code_pressed(KEYCODE_LSHIFT) || machine().input().code_pressed(KEYCODE_RSHIFT))
+ increment = (slider->incval > 10) ? -(slider->incval / 10) : -1;
+ else if (machine().input().code_pressed(KEYCODE_LCONTROL) || machine().input().code_pressed(KEYCODE_RCONTROL))
+ increment = -slider->incval * 10;
+ else
+ increment = -slider->incval;
+ break;
+
+ /* increase value */
+ case IPT_UI_RIGHT:
+ if (machine().input().code_pressed(KEYCODE_LALT) || machine().input().code_pressed(KEYCODE_RALT))
+ increment = 1;
+ else if (machine().input().code_pressed(KEYCODE_LSHIFT) || machine().input().code_pressed(KEYCODE_RSHIFT))
+ increment = (slider->incval > 10) ? (slider->incval / 10) : 1;
+ else if (machine().input().code_pressed(KEYCODE_LCONTROL) || machine().input().code_pressed(KEYCODE_RCONTROL))
+ increment = slider->incval * 10;
+ else
+ increment = slider->incval;
+ break;
+
+ /* restore default */
+ case IPT_UI_SELECT:
+ increment = slider->defval - curvalue;
+ break;
+ }
+
+ /* handle any changes */
+ if (increment != 0)
+ {
+ INT32 newvalue = curvalue + increment;
+
+ /* clamp within bounds */
+ if (newvalue < slider->minval)
+ newvalue = slider->minval;
+ if (newvalue > slider->maxval)
+ newvalue = slider->maxval;
+
+ /* update the slider and recompute the menu */
+ (*slider->update)(machine(), slider->arg, NULL, newvalue);
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ }
+ }
+
+ /* if we are selecting an invalid item and we are hidden, skip to the next one */
+ else if (hidden)
+ {
+ /* if we got here via up or page up, select the previous item */
+ if (menu_event->iptkey == IPT_UI_UP || menu_event->iptkey == IPT_UI_PAGE_UP)
+ {
+ selected = (selected + numitems - 1) % numitems;
+ validate_selection(-1);
+ }
+
+ /* otherwise select the next item */
+ else if (menu_event->iptkey == IPT_UI_DOWN || menu_event->iptkey == IPT_UI_PAGE_DOWN)
+ {
+ selected = (selected + 1) % numitems;
+ validate_selection(1);
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_sliders_populate - populate the sliders
+ menu
+-------------------------------------------------*/
+
+ui_menu_sliders::ui_menu_sliders(running_machine &machine, render_container *container, bool _menuless_mode) : ui_menu(machine, container)
+{
+ menuless_mode = hidden = _menuless_mode;
+}
+
+void ui_menu_sliders::populate()
+{
+ const slider_state *curslider;
+ astring tempstring;
+
+ /* add all sliders */
+ for (curslider = ui_get_slider_list(); curslider != NULL; curslider = curslider->next)
+ {
+ INT32 curval = (*curslider->update)(machine(), curslider->arg, &tempstring, SLIDER_NOCHANGE);
+ UINT32 flags = 0;
+ if (curval > curslider->minval)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (curval < curslider->maxval)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ item_append(curslider->description, tempstring, flags, (void *)curslider);
+
+ if (menuless_mode)
+ break;
+ }
+
+ /* add all sliders */
+ for (curslider = (slider_state*)machine().osd().get_slider_list(); curslider != NULL; curslider = curslider->next)
+ {
+ INT32 curval = (*curslider->update)(machine(), curslider->arg, &tempstring, SLIDER_NOCHANGE);
+ UINT32 flags = 0;
+ if (curval > curslider->minval)
+ flags |= MENU_FLAG_LEFT_ARROW;
+ if (curval < curslider->maxval)
+ flags |= MENU_FLAG_RIGHT_ARROW;
+ item_append(curslider->description, tempstring, flags, (void *)curslider);
+ }
+
+ custombottom = 2.0f * ui_get_line_height(machine()) + 2.0f * UI_BOX_TB_BORDER;
+}
+
+ui_menu_sliders::~ui_menu_sliders()
+{
+}
+
+/*-------------------------------------------------
+ menu_sliders_custom_render - perform our special
+ rendering
+-------------------------------------------------*/
+
+void ui_menu_sliders::custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
+{
+ const slider_state *curslider = (const slider_state *)selectedref;
+ if (curslider != NULL)
+ {
+ float bar_left, bar_area_top, bar_width, bar_area_height, bar_top, bar_bottom, default_x, current_x;
+ float line_height = ui_get_line_height(machine());
+ float percentage, default_percentage;
+ astring tempstring;
+ float text_height;
+ INT32 curval;
+
+ /* determine the current value and text */
+ curval = (*curslider->update)(machine(), curslider->arg, &tempstring, SLIDER_NOCHANGE);
+
+ /* compute the current and default percentages */
+ percentage = (float)(curval - curslider->minval) / (float)(curslider->maxval - curslider->minval);
+ default_percentage = (float)(curslider->defval - curslider->minval) / (float)(curslider->maxval - curslider->minval);
+
+ /* assemble the the text */
+ tempstring.ins(0, " ").ins(0, curslider->description);
+
+ /* move us to the bottom of the screen, and expand to full width */
+ y2 = 1.0f - UI_BOX_TB_BORDER;
+ y1 = y2 - bottom;
+ x1 = UI_BOX_LR_BORDER;
+ x2 = 1.0f - UI_BOX_LR_BORDER;
+
+ /* draw extra menu area */
+ ui_draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+ y1 += UI_BOX_TB_BORDER;
+
+ /* determine the text height */
+ ui_draw_text_full(container, tempstring, 0, 0, x2 - x1 - 2.0f * UI_BOX_LR_BORDER,
+ JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, NULL, &text_height);
+
+ /* draw the thermometer */
+ bar_left = x1 + UI_BOX_LR_BORDER;
+ bar_area_top = y1;
+ bar_width = x2 - x1 - 2.0f * UI_BOX_LR_BORDER;
+ bar_area_height = line_height;
+
+ /* compute positions */
+ bar_top = bar_area_top + 0.125f * bar_area_height;
+ bar_bottom = bar_area_top + 0.875f * bar_area_height;
+ default_x = bar_left + bar_width * default_percentage;
+ current_x = bar_left + bar_width * percentage;
+
+ /* fill in the percentage */
+ container->add_rect(bar_left, bar_top, current_x, bar_bottom, UI_SLIDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ /* draw the top and bottom lines */
+ container->add_line(bar_left, bar_top, bar_left + bar_width, bar_top, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(bar_left, bar_bottom, bar_left + bar_width, bar_bottom, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ /* draw default marker */
+ container->add_line(default_x, bar_area_top, default_x, bar_top, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(default_x, bar_bottom, default_x, bar_area_top + bar_area_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+
+ /* draw the actual text */
+ ui_draw_text_full(container, tempstring, x1 + UI_BOX_LR_BORDER, y1 + line_height, x2 - x1 - 2.0f * UI_BOX_LR_BORDER,
+ JUSTIFY_CENTER, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, &text_height);
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_video_targets - handle the video targets
+ menu
+-------------------------------------------------*/
+
+void ui_menu_video_targets::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT)
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_video_options(machine(), container, static_cast<render_target *>(menu_event->itemref))));
+}
+
+
+/*-------------------------------------------------
+ menu_video_targets_populate - populate the
+ video targets menu
+-------------------------------------------------*/
+
+ui_menu_video_targets::ui_menu_video_targets(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_video_targets::populate()
+{
+ int targetnum;
+
+ /* find the targets */
+ for (targetnum = 0; ; targetnum++)
+ {
+ render_target *target = machine().render().target_by_index(targetnum);
+ char buffer[40];
+
+ /* stop when we run out */
+ if (target == NULL)
+ break;
+
+ /* add a menu item */
+ sprintf(buffer, "Screen #%d", targetnum);
+ item_append(buffer, NULL, 0, target);
+ }
+}
+
+ui_menu_video_targets::~ui_menu_video_targets()
+{
+}
+
+/*-------------------------------------------------
+ menu_video_options - handle the video options
+ menu
+-------------------------------------------------*/
+
+void ui_menu_video_options::handle()
+{
+ bool changed = false;
+
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ switch ((FPTR)menu_event->itemref)
+ {
+ /* rotate adds rotation depending on the direction */
+ case VIDEO_ITEM_ROTATE:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ int delta = (menu_event->iptkey == IPT_UI_LEFT) ? ROT270 : ROT90;
+ target->set_orientation(orientation_add(delta, target->orientation()));
+ if (target->is_ui_target())
+ {
+ render_container::user_settings settings;
+ container->get_user_settings(settings);
+ settings.m_orientation = orientation_add(delta ^ ROT180, settings.m_orientation);
+ container->set_user_settings(settings);
+ }
+ changed = true;
+ }
+ break;
+
+ /* layer config bitmasks handle left/right keys the same (toggle) */
+ case VIDEO_ITEM_BACKDROPS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_backdrops_enabled(!target->backdrops_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_OVERLAYS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_overlays_enabled(!target->overlays_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_BEZELS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_bezels_enabled(!target->bezels_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_CPANELS:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_cpanels_enabled(!target->cpanels_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_MARQUEES:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_marquees_enabled(!target->marquees_enabled());
+ changed = true;
+ }
+ break;
+
+ case VIDEO_ITEM_ZOOM:
+ if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
+ {
+ target->set_zoom_to_screen(!target->zoom_to_screen());
+ changed = true;
+ }
+ break;
+
+ /* anything else is a view item */
+ default:
+ if (menu_event->iptkey == IPT_UI_SELECT && (int)(FPTR)menu_event->itemref >= VIDEO_ITEM_VIEW)
+ {
+ target->set_view((FPTR)menu_event->itemref - VIDEO_ITEM_VIEW);
+ changed = true;
+ }
+ break;
+ }
+ }
+
+ /* if something changed, rebuild the menu */
+ if (changed)
+ reset(UI_MENU_RESET_REMEMBER_REF);
+}
+
+
+/*-------------------------------------------------
+ menu_video_options_populate - populate the
+ video options menu
+-------------------------------------------------*/
+
+ui_menu_video_options::ui_menu_video_options(running_machine &machine, render_container *container, render_target *_target) : ui_menu(machine, container)
+{
+ target = _target;
+}
+
+void ui_menu_video_options::populate()
+{
+ const char *subtext = "";
+ astring tempstring;
+ int viewnum;
+ int enabled;
+
+ /* add items for each view */
+ for (viewnum = 0; ; viewnum++)
+ {
+ const char *name = target->view_name(viewnum);
+ if (name == NULL)
+ break;
+
+ /* create a string for the item, replacing underscores with spaces */
+ tempstring.cpy(name).replace(0, "_", " ");
+ item_append(tempstring, NULL, 0, (void *)(FPTR)(VIDEO_ITEM_VIEW + viewnum));
+ }
+
+ /* add a separator */
+ item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+
+ /* add a rotate item */
+ switch (target->orientation())
+ {
+ case ROT0: subtext = "None"; break;
+ case ROT90: subtext = "CW 90" UTF8_DEGREES; break;
+ case ROT180: subtext = "180" UTF8_DEGREES; break;
+ case ROT270: subtext = "CCW 90" UTF8_DEGREES; break;
+ }
+ item_append("Rotate", subtext, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_ROTATE);
+
+ /* backdrop item */
+ enabled = target->backdrops_enabled();
+ item_append("Backdrops", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_BACKDROPS);
+
+ /* overlay item */
+ enabled = target->overlays_enabled();
+ item_append("Overlays", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_OVERLAYS);
+
+ /* bezel item */
+ enabled = target->bezels_enabled();
+ item_append("Bezels", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_BEZELS);
+
+ /* cpanel item */
+ enabled = target->cpanels_enabled();
+ item_append("CPanels", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_CPANELS);
+
+ /* marquee item */
+ enabled = target->marquees_enabled();
+ item_append("Marquees", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_MARQUEES);
+
+ /* cropping */
+ enabled = target->zoom_to_screen();
+ item_append("View", enabled ? "Cropped" : "Full", enabled ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)VIDEO_ITEM_ZOOM);
+}
+
+ui_menu_video_options::~ui_menu_video_options()
+{
+}
+
+/*-------------------------------------------------
+ menu_crosshair - handle the crosshair settings
+ menu
+-------------------------------------------------*/
+
+void ui_menu_crosshair::handle()
+{
+ /* process the menu */
+ const ui_menu_event *menu_event = process(UI_MENU_PROCESS_LR_REPEAT);
+
+ /* handle events */
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ crosshair_user_settings settings;
+ crosshair_item_data *data = (crosshair_item_data *)menu_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 (menu_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 -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
+ break;
+
+ /* right increments */
+ case IPT_UI_RIGHT:
+ newval += machine().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 (menu_event->iptkey == IPT_UI_SELECT)
+ {
+ /* clear the name string to reset to default crosshair */
+ settings.name[0] = 0;
+ changed = true;
+ }
+ else if (menu_event->iptkey == IPT_UI_LEFT)
+ {
+ strcpy(settings.name, data->last_name);
+ changed = true;
+ }
+ else if (menu_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 */
+ reset(UI_MENU_RESET_REMEMBER_POSITION);
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ menu_crosshair_populate - populate the
+ crosshair settings menu
+-------------------------------------------------*/
+
+ui_menu_crosshair::ui_menu_crosshair(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+void ui_menu_crosshair::populate()
+{
+ crosshair_user_settings settings;
+ crosshair_item_data *data;
+ char temp_text[16];
+ int player;
+ UINT8 use_auto = false;
+ UINT32 flags = 0;
+
+ /* 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 = (crosshair_item_data *)m_pool_alloc(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);
+ item_append(temp_text, vis_text[settings.mode], flags, data);
+
+ /* CROSSHAIR_ITEM_PIC - allocate a data item and fill it */
+ data = (crosshair_item_data *)m_pool_alloc(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 */
+ file_enumerator path(machine().options().crosshair_path());
+ 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 = path.next()) != 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) &&
+ dir->name[length - 4] == '.' &&
+ tolower((UINT8)dir->name[length - 3]) == 'p' &&
+ tolower((UINT8)dir->name[length - 2]) == 'n' &&
+ tolower((UINT8)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);
+ item_append(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 = (crosshair_item_data *)m_pool_alloc(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);
+ item_append("Visible Delay", temp_text, flags, data);
+ }
+// else
+// /* leave a blank filler line when not in auto time so size does not rescale */
+// item_append("", "", NULL, NULL);
+}
+
+ui_menu_crosshair::~ui_menu_crosshair()
+{
+}
+
+/*-------------------------------------------------
+ menu_quit_game - handle the "menu" for
+ quitting the game
+-------------------------------------------------*/
+
+ui_menu_quit_game::ui_menu_quit_game(running_machine &machine, render_container *container) : ui_menu(machine, container)
+{
+}
+
+ui_menu_quit_game::~ui_menu_quit_game()
+{
+}
+
+void ui_menu_quit_game::populate()
+{
+}
+
+void ui_menu_quit_game::handle()
+{
+ /* request a reset */
+ machine().schedule_exit();
+
+ /* reset the menu stack */
+ ui_menu::stack_reset(machine());
+}
+
+
+/*-------------------------------------------------
+ menu_select_game - handle the game select
+ menu
+-------------------------------------------------*/
+
+void ui_menu_select_game::handle()
+{
+ /* ignore pause keys by swallowing them before we process the menu */
+ ui_input_pressed(machine(), IPT_UI_PAUSE);
+
+ /* process the menu */
+ const ui_menu_event *menu_event = process(0);
+ if (menu_event != NULL && menu_event->itemref != NULL)
+ {
+ /* reset the error on any future menu_event */
+ if (error)
+ error = false;
+
+ /* handle selections */
+ else if (menu_event->iptkey == IPT_UI_SELECT)
+ {
+ const game_driver *driver = (const game_driver *)menu_event->itemref;
+
+ /* special case for configure inputs */
+ if ((FPTR)driver == 1)
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_groups(machine(), container)));
+
+ /* anything else is a driver */
+ else
+ {
+ // audit the game first to see if we're going to work
+ driver_enumerator enumerator(machine().options(), *driver);
+ enumerator.next();
+ media_auditor auditor(enumerator);
+ media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
+
+ // if everything looks good, schedule the new driver
+ if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE)
+ {
+ machine().schedule_new_driver(*driver);
+ ui_menu::stack_reset(machine());
+ }
+
+ // otherwise, display an error
+ else
+ {
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ error = true;
+ }
+ }
+ }
+
+ /* escape pressed with non-empty text clears the text */
+ else if (menu_event->iptkey == IPT_UI_CANCEL && search[0] != 0)
+ {
+ /* since we have already been popped, we must recreate ourself from scratch */
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_select_game(machine(), container, NULL)));
+ }
+
+ /* typed characters append to the buffer */
+ else if (menu_event->iptkey == IPT_SPECIAL)
+ {
+ int buflen = strlen(search);
+
+ /* if it's a backspace and we can handle it, do so */
+ if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
+ {
+ *(char *)utf8_previous_char(&search[buflen]) = 0;
+ rerandomize = true;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+
+ /* if it's any other key and we're not maxed out, update */
+ else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
+ {
+ buflen += utf8_from_uchar(&search[buflen], ARRAY_LENGTH(search) - buflen, menu_event->unichar);
+ search[buflen] = 0;
+ reset(UI_MENU_RESET_SELECT_FIRST);
+ }
+ }
+ }
+
+ /* if we're in an error state, overlay an error message */
+ if (error)
+ ui_draw_text_box(container,
+ "The selected game is missing one or more required ROM or CHD images. "
+ "Please select a different game.\n\nPress any key to continue.",
+ JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR);
+}
+
+
+/*-------------------------------------------------
+ menu_select_game_populate - populate the game
+ select menu
+-------------------------------------------------*/
+driver_enumerator *ui_menu_select_game::drivlist;
+
+ui_menu_select_game::ui_menu_select_game(running_machine &machine, render_container *container, const char *gamename) : ui_menu(machine, container)
+{
+ driverlist = (const game_driver **)m_pool_alloc((driver_list::total()+1)*sizeof(const game_driver *));
+ build_driver_list();
+ if(gamename)
+ strcpy(search, gamename);
+ matchlist[0] = -1;
+}
+
+void ui_menu_select_game::populate()
+{
+ int matchcount;
+ int curitem;
+
+ for (curitem = matchcount = 0; driverlist[curitem] != NULL && matchcount < VISIBLE_GAMES_IN_LIST; curitem++)
+ if (!(driverlist[curitem]->flags & GAME_NO_STANDALONE))
+ matchcount++;
+
+ /* if nothing there, add a single multiline item and return */
+ if (matchcount == 0)
+ {
+ astring txt;
+ txt.printf("No %s found. Please check the rompath specified in the %s.ini file.\n\n"
+ "If this is your first time using %s, please see the config.txt file in "
+ "the docs directory for information on configuring %s.",
+ emulator_info::get_gamesnoun(),
+ emulator_info::get_configname(),
+ emulator_info::get_appname(),emulator_info::get_appname() );
+ item_append(txt.cstr(), NULL, MENU_FLAG_MULTILINE | MENU_FLAG_REDTEXT, NULL);
+ return;
+ }
+
+ /* otherwise, rebuild the match list */
+ assert(drivlist != NULL);
+ if (search[0] != 0 || matchlist[0] == -1 || rerandomize)
+ drivlist->find_approximate_matches(search, matchcount, matchlist);
+ rerandomize = false;
+
+ /* iterate over entries */
+ for (curitem = 0; curitem < matchcount; curitem++)
+ {
+ int curmatch = matchlist[curitem];
+ if (curmatch != -1)
+ {
+ int cloneof = drivlist->non_bios_clone(curmatch);
+ item_append(drivlist->driver(curmatch).name, drivlist->driver(curmatch).description, (cloneof == -1) ? 0 : MENU_FLAG_INVERT, (void *)&drivlist->driver(curmatch));
+ }
+ }
+
+ /* if we're forced into this, allow general input configuration as well */
+ if (ui_menu::stack_has_special_main_menu())
+ {
+ item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL);
+ item_append("Configure General Inputs", NULL, 0, (void *)1);
+ }
+
+ /* configure the custom rendering */
+ customtop = ui_get_line_height(machine()) + 3.0f * UI_BOX_TB_BORDER;
+ custombottom = 4.0f * ui_get_line_height(machine()) + 3.0f * UI_BOX_TB_BORDER;
+}
+
+ui_menu_select_game::~ui_menu_select_game()
+{
+ global_free(drivlist);
+}
+
+/*-------------------------------------------------
+ menu_select_game_build_driver_list - build a
+ list of available drivers
+-------------------------------------------------*/
+
+void ui_menu_select_game::build_driver_list()
+{
+ // start with an empty list
+ drivlist = global_alloc(driver_enumerator(machine().options()));
+ drivlist->exclude_all();
+
+ /* open a path to the ROMs and find them in the array */
+ file_enumerator path(machine().options().media_path());
+ const osd_directory_entry *dir;
+
+ /* iterate while we get new objects */
+ while ((dir = path.next()) != NULL)
+ {
+ char drivername[50];
+ char *dst = drivername;
+ const char *src;
+
+ /* build a name for it */
+ for (src = dir->name; *src != 0 && *src != '.' && dst < &drivername[ARRAY_LENGTH(drivername) - 1]; src++)
+ *dst++ = tolower((UINT8)*src);
+ *dst = 0;
+
+ int drivnum = drivlist->find(drivername);
+ if (drivnum != -1)
+ drivlist->include(drivnum);
+ }
+
+ /* now build the final list */
+ drivlist->reset();
+ int listnum = 0;
+ while (drivlist->next())
+ driverlist[listnum++] = &drivlist->driver();
+
+ /* NULL-terminate */
+ driverlist[listnum] = NULL;
+}
+
+
+/*-------------------------------------------------
+ menu_select_game_custom_render - perform our
+ special rendering
+-------------------------------------------------*/
+
+void ui_menu_select_game::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
+{
+ const game_driver *driver;
+ float width, maxwidth;
+ float x1, y1, x2, y2;
+ char tempbuf[4][256];
+ rgb_t color;
+ int line;
+
+ /* display the current typeahead */
+ if (search[0] != 0)
+ sprintf(&tempbuf[0][0], "Type name or select: %s_", search);
+ else
+ sprintf(&tempbuf[0][0], "Type name or select: (random)");
+
+ /* get the size of the text */
+ ui_draw_text_full(container, &tempbuf[0][0], 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, NULL);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(width, origx2 - origx1);
+
+ /* compute our bounds */
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy1 - top;
+ y2 = origy1 - UI_BOX_TB_BORDER;
+
+ /* draw a box */
+ ui_draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+
+ /* take off the borders */
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ /* draw the text within it */
+ ui_draw_text_full(container, &tempbuf[0][0], x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, NULL);
+
+ /* determine the text to render below */
+ driver = ((FPTR)selectedref > 1) ? (const game_driver *)selectedref : NULL;
+ if ((FPTR)driver > 1)
+ {
+ const char *gfxstat, *soundstat;
+
+ /* first line is game name */
+ sprintf(&tempbuf[0][0], "%-.100s", driver->description);
+
+ /* next line is year, manufacturer */
+ sprintf(&tempbuf[1][0], "%s, %-.100s", driver->year, driver->manufacturer);
+
+ /* next line is overall driver status */
+ if (driver->flags & GAME_NOT_WORKING)
+ strcpy(&tempbuf[2][0], "Overall: NOT WORKING");
+ else if (driver->flags & GAME_UNEMULATED_PROTECTION)
+ strcpy(&tempbuf[2][0], "Overall: Unemulated Protection");
+ else
+ strcpy(&tempbuf[2][0], "Overall: Working");
+
+ /* next line is graphics, sound status */
+ if (driver->flags & (GAME_IMPERFECT_GRAPHICS | GAME_WRONG_COLORS | GAME_IMPERFECT_COLORS))
+ gfxstat = "Imperfect";
+ else
+ gfxstat = "OK";
+
+ if (driver->flags & GAME_NO_SOUND)
+ soundstat = "Unimplemented";
+ else if (driver->flags & GAME_IMPERFECT_SOUND)
+ soundstat = "Imperfect";
+ else
+ soundstat = "OK";
+
+ sprintf(&tempbuf[3][0], "Gfx: %s, Sound: %s", gfxstat, soundstat);
+ }
+ else
+ {
+ const char *s = emulator_info::get_copyright();
+ line = 0;
+ int col = 0;
+
+ /* first line is version string */
+ sprintf(&tempbuf[line++][0], "%s %s", emulator_info::get_applongname(), build_version);
+
+ /* output message */
+ while (line < ARRAY_LENGTH(tempbuf))
+ {
+ if (*s == 0 || *s == '\n')
+ {
+ tempbuf[line++][col] = 0;
+ col = 0;
+ }
+ else
+ tempbuf[line][col++] = *s;
+
+ if (*s != 0)
+ s++;
+ }
+ }
+
+ /* get the size of the text */
+ maxwidth = origx2 - origx1;
+ for (line = 0; line < 4; line++)
+ {
+ ui_draw_text_full(container, &tempbuf[line][0], 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, NULL);
+ width += 2 * UI_BOX_LR_BORDER;
+ maxwidth = MAX(maxwidth, width);
+ }
+
+ /* compute our bounds */
+ x1 = 0.5f - 0.5f * maxwidth;
+ x2 = x1 + maxwidth;
+ y1 = origy2 + UI_BOX_TB_BORDER;
+ y2 = origy2 + bottom;
+
+ /* draw a box */
+ color = UI_BACKGROUND_COLOR;
+ if (driver != NULL)
+ color = UI_GREEN_COLOR;
+ if (driver != NULL && (driver->flags & (GAME_IMPERFECT_GRAPHICS | GAME_WRONG_COLORS | GAME_IMPERFECT_COLORS | GAME_NO_SOUND | GAME_IMPERFECT_SOUND)) != 0)
+ color = UI_YELLOW_COLOR;
+ if (driver != NULL && (driver->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION)) != 0)
+ color = UI_RED_COLOR;
+ ui_draw_outlined_box(container, x1, y1, x2, y2, color);
+
+ /* take off the borders */
+ x1 += UI_BOX_LR_BORDER;
+ x2 -= UI_BOX_LR_BORDER;
+ y1 += UI_BOX_TB_BORDER;
+ y2 -= UI_BOX_TB_BORDER;
+
+ /* draw all lines */
+ for (line = 0; line < 4; line++)
+ {
+ ui_draw_text_full(container, &tempbuf[line][0], x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
+ DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, NULL);
+ y1 += ui_get_line_height(machine());
+ }
+}
+
+
+
diff --git a/src/emu/uimain.h b/src/emu/uimain.h
new file mode 100644
index 00000000000..232b4d87f39
--- /dev/null
+++ b/src/emu/uimain.h
@@ -0,0 +1,367 @@
+/***************************************************************************
+
+ uimain.h
+
+ Internal MAME menus for the user interface.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UIMAIN_H__
+#define __UIMAIN_H__
+
+#include "crsshair.h"
+
+class ui_menu_main : public ui_menu {
+public:
+ ui_menu_main(running_machine &machine, render_container *container);
+ virtual ~ui_menu_main();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ enum {
+ INPUT_GROUPS,
+ INPUT_SPECIFIC,
+ SETTINGS_DIP_SWITCHES,
+ SETTINGS_DRIVER_CONFIG,
+ ANALOG,
+ BOOKKEEPING,
+ GAME_INFO,
+ IMAGE_MENU_IMAGE_INFO,
+ IMAGE_MENU_FILE_MANAGER,
+ MESS_MENU_TAPE_CONTROL,
+ MESS_MENU_BITBANGER_CONTROL,
+ SLOT_DEVICES,
+ NETWORK_DEVICES,
+ KEYBOARD_MODE,
+ SLIDERS,
+ VIDEO_TARGETS,
+ VIDEO_OPTIONS,
+ CROSSHAIR,
+ CHEAT,
+ MEMORY_CARD,
+ SELECT_GAME,
+ };
+};
+
+class ui_menu_keyboard_mode : public ui_menu {
+public:
+ ui_menu_keyboard_mode(running_machine &machine, render_container *container);
+ virtual ~ui_menu_keyboard_mode();
+ virtual void populate();
+ virtual void handle();
+};
+
+class ui_menu_slot_devices : public ui_menu {
+public:
+ ui_menu_slot_devices(running_machine &machine, render_container *container);
+ virtual ~ui_menu_slot_devices();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ int slot_get_current_index(device_slot_interface *slot);
+ int slot_get_length(device_slot_interface *slot);
+ const char *slot_get_next(device_slot_interface *slot);
+ const char *slot_get_prev(device_slot_interface *slot);
+ const char *get_slot_device(device_slot_interface *slot);
+ void set_slot_device(device_slot_interface *slot, const char *val);
+};
+
+class ui_menu_network_devices : public ui_menu {
+public:
+ ui_menu_network_devices(running_machine &machine, render_container *container);
+ virtual ~ui_menu_network_devices();
+ virtual void populate();
+ virtual void handle();
+};
+
+class ui_menu_input_groups : public ui_menu {
+public:
+ ui_menu_input_groups(running_machine &machine, render_container *container);
+ virtual ~ui_menu_input_groups();
+ virtual void populate();
+ virtual void handle();
+};
+
+class ui_menu_input : public ui_menu {
+public:
+ ui_menu_input(running_machine &machine, render_container *container);
+ virtual ~ui_menu_input();
+ virtual void handle();
+
+protected:
+ enum {
+ INPUT_TYPE_DIGITAL = 0,
+ INPUT_TYPE_ANALOG = 1,
+ INPUT_TYPE_ANALOG_DEC = INPUT_TYPE_ANALOG + SEQ_TYPE_DECREMENT,
+ INPUT_TYPE_ANALOG_INC = INPUT_TYPE_ANALOG + SEQ_TYPE_INCREMENT,
+ INPUT_TYPE_TOTAL = INPUT_TYPE_ANALOG + SEQ_TYPE_TOTAL
+ };
+
+ /* internal input menu item data */
+ struct input_item_data {
+ input_item_data * next; /* pointer to next item in the list */
+ const void * ref; /* reference to type description for global inputs or field for game inputs */
+ input_seq_type seqtype; /* sequence type */
+ input_seq seq; /* copy of the live sequence */
+ const input_seq * defseq; /* pointer to the default sequence */
+ const char * name; /* pointer to the base name of the item */
+ UINT16 sortorder; /* sorting information */
+ UINT8 type; /* type of port */
+ };
+
+ void populate_and_sort(struct input_item_data *itemlist);
+ virtual void update_input(struct input_item_data *seqchangeditem) = 0;
+ void toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq);
+ const input_seq &get_field_default_seq(input_field_config *field, input_seq_type seqtype);
+
+private:
+ UINT16 last_sortorder;
+ const void * pollingref;
+ input_item_data * pollingitem;
+ bool record_next;
+ input_seq starting_seq;
+
+ static int compare_items(const void *i1, const void *i2);
+};
+
+class ui_menu_input_general : public ui_menu_input {
+public:
+ ui_menu_input_general(running_machine &machine, render_container *container, int group);
+ virtual ~ui_menu_input_general();
+ virtual void populate();
+
+protected:
+ int group;
+ virtual void update_input(struct input_item_data *seqchangeditem);
+};
+
+class ui_menu_input_specific : public ui_menu_input {
+public:
+ ui_menu_input_specific(running_machine &machine, render_container *container);
+ virtual ~ui_menu_input_specific();
+ virtual void populate();
+
+protected:
+ virtual void update_input(struct input_item_data *seqchangeditem);
+};
+
+class ui_menu_settings : public ui_menu {
+public:
+ ui_menu_settings(running_machine &machine, render_container *container, UINT32 type);
+ virtual ~ui_menu_settings();
+ virtual void populate();
+ virtual void handle();
+
+protected:
+ /* DIP switch descriptor */
+ struct dip_descriptor {
+ dip_descriptor * next;
+ const char * name;
+ UINT32 mask;
+ UINT32 state;
+ };
+
+ dip_descriptor * diplist;
+ int dipcount;
+ int type;
+};
+
+class ui_menu_settings_dip_switches : public ui_menu_settings {
+public:
+ ui_menu_settings_dip_switches(running_machine &machine, render_container *container);
+ virtual ~ui_menu_settings_dip_switches();
+
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
+private:
+ void custom_render_one(float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask);
+};
+
+class ui_menu_settings_driver_config : public ui_menu_settings {
+public:
+ ui_menu_settings_driver_config(running_machine &machine, render_container *container);
+ virtual ~ui_menu_settings_driver_config();
+};
+
+class ui_menu_analog : public ui_menu {
+public:
+ ui_menu_analog(running_machine &machine, render_container *container);
+ virtual ~ui_menu_analog();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ enum {
+ ANALOG_ITEM_KEYSPEED = 0,
+ ANALOG_ITEM_CENTERSPEED,
+ ANALOG_ITEM_REVERSE,
+ ANALOG_ITEM_SENSITIVITY,
+ ANALOG_ITEM_COUNT
+ };
+
+ /* internal analog menu item data */
+ struct analog_item_data {
+ input_field_config *field;
+ int type;
+ int min, max;
+ int cur;
+ int defvalue;
+ };
+};
+
+class ui_menu_bookkeeping : public ui_menu {
+public:
+ ui_menu_bookkeeping(running_machine &machine, render_container *container);
+ virtual ~ui_menu_bookkeeping();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ attotime prevtime;
+};
+
+class ui_menu_game_info : public ui_menu {
+public:
+ ui_menu_game_info(running_machine &machine, render_container *container);
+ virtual ~ui_menu_game_info();
+ virtual void populate();
+ virtual void handle();
+};
+
+class ui_menu_cheat : public ui_menu {
+public:
+ ui_menu_cheat(running_machine &machine, render_container *container);
+ virtual ~ui_menu_cheat();
+ virtual void populate();
+ virtual void handle();
+};
+
+class ui_menu_memory_card : public ui_menu {
+public:
+ ui_menu_memory_card(running_machine &machine, render_container *container);
+ virtual ~ui_menu_memory_card();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ enum {
+ MEMCARD_ITEM_SELECT = 1,
+ MEMCARD_ITEM_LOAD,
+ MEMCARD_ITEM_EJECT,
+ MEMCARD_ITEM_CREATE
+ };
+
+ int cardnum;
+};
+
+class ui_menu_sliders : public ui_menu {
+public:
+ ui_menu_sliders(running_machine &machine, render_container *container, bool menuless_mode);
+ virtual ~ui_menu_sliders();
+ virtual void populate();
+ virtual void handle();
+
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
+
+ static UINT32 ui_handler(running_machine &machine, render_container *container, UINT32 state);
+
+private:
+ bool menuless_mode, hidden;
+};
+
+class ui_menu_video_targets : public ui_menu {
+public:
+ ui_menu_video_targets(running_machine &machine, render_container *container);
+ virtual ~ui_menu_video_targets();
+ virtual void populate();
+ virtual void handle();
+};
+
+class ui_menu_video_options : public ui_menu {
+public:
+ ui_menu_video_options(running_machine &machine, render_container *container, render_target *target);
+ virtual ~ui_menu_video_options();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ enum {
+ VIDEO_ITEM_ROTATE = 0x80000000,
+ VIDEO_ITEM_BACKDROPS,
+ VIDEO_ITEM_OVERLAYS,
+ VIDEO_ITEM_BEZELS,
+ VIDEO_ITEM_CPANELS,
+ VIDEO_ITEM_MARQUEES,
+ VIDEO_ITEM_ZOOM,
+ VIDEO_ITEM_VIEW
+ };
+
+ render_target *target;
+};
+
+class ui_menu_crosshair : public ui_menu {
+public:
+ ui_menu_crosshair(running_machine &machine, render_container *container);
+ virtual ~ui_menu_crosshair();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ enum {
+ CROSSHAIR_ITEM_VIS = 0,
+ CROSSHAIR_ITEM_PIC,
+ CROSSHAIR_ITEM_AUTO_TIME
+ };
+
+ /* internal crosshair menu 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];
+ };
+};
+
+class ui_menu_quit_game : public ui_menu {
+public:
+ ui_menu_quit_game(running_machine &machine, render_container *container);
+ virtual ~ui_menu_quit_game();
+ virtual void populate();
+ virtual void handle();
+};
+
+class ui_menu_select_game : public ui_menu {
+public:
+ ui_menu_select_game(running_machine &machine, render_container *container, const char *gamename);
+ virtual ~ui_menu_select_game();
+ virtual void populate();
+ virtual void handle();
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
+
+private:
+ enum { VISIBLE_GAMES_IN_LIST = 15 };
+ UINT8 error;
+ UINT8 rerandomize;
+ char search[40];
+ int matchlist[VISIBLE_GAMES_IN_LIST];
+ const game_driver **driverlist;
+
+ // Still a hack, but a vaguely clearner one
+ static driver_enumerator *drivlist;
+
+ void build_driver_list();
+};
+
+/* force game select menu */
+void ui_menu_force_game_select(running_machine &machine, render_container *container);
+
+#endif /* __UIMAIN_H__ */
diff --git a/src/emu/uimenu.c b/src/emu/uimenu.c
index f462433d521..29af82a5677 100644
--- a/src/emu/uimenu.c
+++ b/src/emu/uimenu.c
@@ -13,15 +13,10 @@
#include "emuopts.h"
#include "ui.h"
#include "rendutil.h"
-#include "cheat.h"
-#include "uiimage.h"
#include "uiinput.h"
-#include "uimenu.h"
-#include "audit.h"
-#include "crsshair.h"
+#include "cheat.h"
+#include "uimain.h"
#include <ctype.h>
-#include "imagedev/cassette.h"
-#include "imagedev/bitbngr.h"
@@ -32,335 +27,28 @@
#define UI_MENU_POOL_SIZE 65536
#define UI_MENU_ALLOC_ITEMS 256
-#define VISIBLE_GAMES_IN_LIST 15
-
-#define MAX_PHYSICAL_DIPS 10
-#define MAX_INPUT_PORTS 32
-#define MAX_BITS_PER_PORT 32
-
-/* DIP switch rendering parameters */
-#define DIP_SWITCH_HEIGHT 0.05f
-#define DIP_SWITCH_SPACING 0.01
-#define SINGLE_TOGGLE_SWITCH_FIELD_WIDTH 0.025f
-#define SINGLE_TOGGLE_SWITCH_WIDTH 0.020f
-/* make the switch 80% of the width space and 1/2 of the switch height */
-#define PERCENTAGE_OF_HALF_FIELD_USED 0.80f
-#define SINGLE_TOGGLE_SWITCH_HEIGHT ((DIP_SWITCH_HEIGHT / 2) * PERCENTAGE_OF_HALF_FIELD_USED)
-
-
-enum
-{
- INPUT_TYPE_DIGITAL = 0,
- INPUT_TYPE_ANALOG = 1,
- INPUT_TYPE_ANALOG_DEC = INPUT_TYPE_ANALOG + SEQ_TYPE_DECREMENT,
- INPUT_TYPE_ANALOG_INC = INPUT_TYPE_ANALOG + SEQ_TYPE_INCREMENT,
- INPUT_TYPE_TOTAL = INPUT_TYPE_ANALOG + SEQ_TYPE_TOTAL
-};
-
-enum
-{
- ANALOG_ITEM_KEYSPEED = 0,
- ANALOG_ITEM_CENTERSPEED,
- ANALOG_ITEM_REVERSE,
- ANALOG_ITEM_SENSITIVITY,
- ANALOG_ITEM_COUNT
-};
-
-enum
-{
- MEMCARD_ITEM_SELECT = 1,
- MEMCARD_ITEM_LOAD,
- MEMCARD_ITEM_EJECT,
- MEMCARD_ITEM_CREATE
-};
-
-enum
-{
- VIDEO_ITEM_ROTATE = 0x80000000,
- VIDEO_ITEM_BACKDROPS,
- VIDEO_ITEM_OVERLAYS,
- VIDEO_ITEM_BEZELS,
- VIDEO_ITEM_CPANELS,
- VIDEO_ITEM_MARQUEES,
- VIDEO_ITEM_ZOOM,
- VIDEO_ITEM_VIEW
-};
-
-
-enum
-{
- CROSSHAIR_ITEM_VIS = 0,
- CROSSHAIR_ITEM_PIC,
- CROSSHAIR_ITEM_AUTO_TIME
-};
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-typedef struct _ui_menu_pool ui_menu_pool;
-struct _ui_menu_pool
-{
- ui_menu_pool * next; /* chain to next one */
- UINT8 * top; /* top of the pool */
- UINT8 * end; /* end of the pool */
-};
-
-
-typedef struct _ui_menu_item ui_menu_item;
-struct _ui_menu_item
-{
- const char * text;
- const char * subtext;
- UINT32 flags;
- void * ref;
-};
-
-
-class ui_menu
-{
-public:
- ui_menu(running_machine &machine)
- : m_machine(machine) { }
-
- running_machine &machine() const { return m_machine; }
-
- render_container * container; /* render_container we render to */
- ui_menu_handler_func handler; /* handler callback */
- void * parameter; /* parameter */
- ui_menu_event menu_event; /* the UI menu_event that occurred */
- ui_menu * parent; /* pointer to parent menu */
- void * state; /* menu-specific state */
- ui_menu_destroy_state_func destroy_state; /* destroy state callback */
- int resetpos; /* reset position */
- void * resetref; /* reset reference */
- int selected; /* which item is selected */
- int hover; /* which item is being hovered over */
- int visitems; /* number of visible items */
- int numitems; /* number of items in the menu */
- int allocitems; /* allocated size of array */
- ui_menu_item * item; /* pointer to array of items */
- ui_menu_custom_func custom; /* callback for custom rendering */
- float customtop; /* amount of extra height to add at the top */
- float custombottom; /* amount of extra height to add at the bottom */
- ui_menu_pool * pool; /* list of memory pools */
-
-private:
- running_machine & m_machine; /* machine we are attached to */
-};
-
-
-/* internal input menu item data */
-typedef struct _input_item_data input_item_data;
-struct _input_item_data
-{
- input_item_data * next; /* pointer to next item in the list */
- const void * ref; /* reference to type description for global inputs or field for game inputs */
- input_seq_type seqtype; /* sequence type */
- input_seq seq; /* copy of the live sequence */
- const input_seq * defseq; /* pointer to the default sequence */
- const char * name; /* pointer to the base name of the item */
- UINT16 sortorder; /* sorting information */
- UINT8 type; /* type of port */
-};
-
-
-/* internal analog menu item data */
-typedef struct _analog_item_data analog_item_data;
-struct _analog_item_data
-{
- input_field_config *field;
- int type;
- int min, max;
- int cur;
- int defvalue;
-};
-
-
-/* DIP switch descriptor */
-typedef struct _dip_descriptor dip_descriptor;
-struct _dip_descriptor
-{
- dip_descriptor * next;
- const char * name;
- UINT32 mask;
- UINT32 state;
-};
-
-
-/* extended settings menu state */
-typedef struct _settings_menu_state settings_menu_state;
-struct _settings_menu_state
-{
- dip_descriptor * diplist;
-};
-
-
-/* extended input menu state */
-typedef struct _input_menu_state input_menu_state;
-struct _input_menu_state
-{
- UINT16 last_sortorder;
- const void * pollingref;
- input_item_data * pollingitem;
- UINT8 record_next;
- input_seq starting_seq;
-};
-
-
-/* extended select game menu state */
-typedef struct _select_game_state select_game_state;
-struct _select_game_state
-{
- UINT8 error;
- UINT8 rerandomize;
- char search[40];
- int matchlist[VISIBLE_GAMES_IN_LIST];
- const game_driver * driverlist[1];
-};
-
-
-/* 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
***************************************************************************/
-/* menu states */
-static ui_menu *menu_stack;
-static ui_menu *menu_free;
-
-static bitmap_t *hilight_bitmap;
-static render_texture *hilight_texture;
-
-static render_texture *arrow_texture;
-
-static const char priortext[] = "Return to Prior Menu";
-static const char exittext[] = "Exit";
-
-// temporary hack until this is C++-ified
-static driver_enumerator *drivlist;
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static void ui_menu_exit(running_machine &machine);
-
-/* internal menu processing */
-static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly);
-static void ui_menu_draw_text_box(ui_menu *menu);
-static void ui_menu_handle_events(ui_menu *menu);
-static void ui_menu_handle_keys(ui_menu *menu, UINT32 flags);
-static void ui_menu_validate_selection(ui_menu *menu, int scandir);
-static void ui_menu_clear_free_list(running_machine &machine);
-
-/* menu handlers */
-static void menu_main(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_main_populate(running_machine &machine, ui_menu *menu, void *state);
-static void menu_input_groups(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_input_groups_populate(running_machine &machine, ui_menu *menu, void *state);
-static void menu_input_general(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_input_general_populate(running_machine &machine, ui_menu *menu, input_menu_state *menustate, int group);
-static void menu_input_specific(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_input_specific_populate(running_machine &machine, ui_menu *menu, input_menu_state *menustate);
-static void menu_input_common(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static int CLIB_DECL menu_input_compare_items(const void *i1, const void *i2);
-static void menu_input_populate_and_sort(running_machine &machine, ui_menu *menu, input_item_data *itemlist, input_menu_state *menustate);
-static void menu_settings_dip_switches(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_settings_driver_config(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_settings_common(running_machine &machine, ui_menu *menu, void *state, UINT32 type);
-static void menu_settings_populate(running_machine &machine, ui_menu *menu, settings_menu_state *menustate, UINT32 type);
-static void menu_analog(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_analog_populate(running_machine &machine, ui_menu *menu);
-static void menu_bookkeeping(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_bookkeeping_populate(running_machine &machine, ui_menu *menu, attotime *curtime);
-static void menu_game_info(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_cheat(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_cheat_populate(running_machine &machine, ui_menu *menu);
-static void menu_memory_card(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_memory_card_populate(running_machine &machine, ui_menu *menu, int cardnum);
-static void menu_sliders(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-static void menu_sliders_populate(running_machine &machine, ui_menu *menu, int menuless_mode);
-static void menu_sliders_custom_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2);
-static void menu_video_targets(running_machine &machine, ui_menu *menu, void *parameter, void *state);
-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);
-static void menu_select_game_build_driver_list(ui_menu *menu, select_game_state *menustate);
-static void menu_select_game_custom_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
-
-/* menu helpers */
-static void menu_render_triangle(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
-static void menu_settings_custom_render_one(render_container *container, float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask);
-static void menu_settings_custom_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
-
-
+ui_menu *ui_menu::menu_stack;
+ui_menu *ui_menu::menu_free;
+bitmap_t *ui_menu::hilight_bitmap;
+render_texture *ui_menu::hilight_texture;
+render_texture *ui_menu::arrow_texture;
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
/*-------------------------------------------------
- get_field_default_seq - return a pointer
- to the default sequence for the given field
--------------------------------------------------*/
-
-INLINE const input_seq &get_field_default_seq(input_field_config *field, input_seq_type seqtype)
-{
- if (field->seq[seqtype].is_default())
- return input_type_seq(field->machine(), field->type, field->player, seqtype);
- else
- return field->seq[seqtype];
-}
-
-
-/*-------------------------------------------------
- toggle_none_default - toggle between "NONE"
- and the default item
--------------------------------------------------*/
-
-INLINE void toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq)
-{
- /* if we used to be "none", toggle to the default value */
- if (original_seq.length() == 0)
- selected_seq = selected_defseq;
-
- /* otherwise, toggle to "none" */
- else
- selected_seq.reset();
-}
-
-
-/*-------------------------------------------------
- item_is_selectable - return TRUE if the given
+ is_selectable - return TRUE if the given
item is selectable
-------------------------------------------------*/
-INLINE int item_is_selectable(const ui_menu_item *item)
+inline bool ui_menu_item::is_selectable() const
{
- return ((item->flags & (MENU_FLAG_MULTILINE | MENU_FLAG_DISABLE)) == 0 && strcmp(item->text, MENU_SEPARATOR_ITEM) != 0);
+ return ((flags & (MENU_FLAG_MULTILINE | MENU_FLAG_DISABLE)) == 0 && strcmp(text, MENU_SEPARATOR_ITEM) != 0);
}
@@ -370,14 +58,14 @@ INLINE int item_is_selectable(const ui_menu_item *item)
reported a key
-------------------------------------------------*/
-INLINE int exclusive_input_pressed(ui_menu *menu, int key, int repeat)
+inline bool ui_menu::exclusive_input_pressed(int key, int repeat)
{
- if (menu->menu_event.iptkey == IPT_INVALID && ui_input_pressed_repeat(menu->machine(), key, repeat))
+ if (menu_event.iptkey == IPT_INVALID && ui_input_pressed_repeat(machine(), key, repeat))
{
- menu->menu_event.iptkey = key;
- return TRUE;
+ menu_event.iptkey = key;
+ return true;
}
- return FALSE;
+ return false;
}
@@ -387,15 +75,15 @@ INLINE int exclusive_input_pressed(ui_menu *menu, int key, int repeat)
***************************************************************************/
/*-------------------------------------------------
- ui_menu_init - initialize the menu system
+ init - initialize the menu system
-------------------------------------------------*/
-void ui_menu_init(running_machine &machine)
+void ui_menu::init(running_machine &machine)
{
int x;
/* initialize the menu stack */
- ui_menu_stack_reset(machine);
+ ui_menu::stack_reset(machine);
/* create a texture for hilighting items */
hilight_bitmap = auto_bitmap_alloc(machine, 256, 1, BITMAP_FORMAT_ARGB32);
@@ -410,32 +98,26 @@ void ui_menu_init(running_machine &machine)
hilight_texture->set_bitmap(hilight_bitmap, NULL, TEXFORMAT_ARGB32);
/* create a texture for arrow icons */
- arrow_texture = machine.render().texture_alloc(menu_render_triangle);
+ arrow_texture = machine.render().texture_alloc(render_triangle);
/* add an exit callback to free memory */
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ui_menu_exit), &machine));
+ machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ui_menu::exit), &machine));
}
/*-------------------------------------------------
- ui_menu_exit - clean up after ourselves
+ exit - clean up after ourselves
-------------------------------------------------*/
-static void ui_menu_exit(running_machine &machine)
+void ui_menu::exit(running_machine &machine)
{
/* free menus */
- ui_menu_stack_reset(machine);
- ui_menu_clear_free_list(machine);
+ ui_menu::stack_reset(machine);
+ ui_menu::clear_free_list(machine);
/* free textures */
machine.render().texture_free(hilight_texture);
machine.render().texture_free(arrow_texture);
-
- if (drivlist)
- {
- global_free(drivlist);
- drivlist = NULL;
- }
}
@@ -445,299 +127,263 @@ static void ui_menu_exit(running_machine &machine)
***************************************************************************/
/*-------------------------------------------------
- ui_menu_alloc - allocate a new menu
+ ui_menu - menu constructor
-------------------------------------------------*/
-
-ui_menu *ui_menu_alloc(running_machine &machine, render_container *container, ui_menu_handler_func handler, void *parameter)
+ui_menu::ui_menu(running_machine &machine, render_container *_container) : m_machine(machine)
{
- ui_menu *menu;
-
- /* allocate and clear memory for the menu and the state */
- menu = auto_alloc_clear(machine, ui_menu(machine));
+ special_main_menu = false;
+ container = _container;
- /* initialize the state */
- menu->container = container;
- menu->handler = handler;
- menu->parameter = parameter;
-
- /* reset the menu (adds a default entry) */
- ui_menu_reset(menu, UI_MENU_RESET_SELECT_FIRST);
- return menu;
+ reset(UI_MENU_RESET_SELECT_FIRST);
}
/*-------------------------------------------------
- ui_menu_free - free a menu
+ ~ui_menu - menu destructor
-------------------------------------------------*/
-void ui_menu_free(ui_menu *menu)
+ui_menu::~ui_menu()
{
/* free the pools */
- while (menu->pool != NULL)
+ while (pool)
{
- ui_menu_pool *pool = menu->pool;
- menu->pool = pool->next;
- auto_free(menu->machine(), pool);
+ ui_menu_pool *ppool = pool;
+ pool = pool->next;
+ auto_free(machine(), ppool);
}
/* free the item array */
- if (menu->item != NULL)
- auto_free(menu->machine(), menu->item);
-
- /* free the state */
- if (menu->state != NULL)
- {
- if (menu->destroy_state != NULL)
- (*menu->destroy_state)(menu, menu->state);
- auto_free(menu->machine(), menu->state);
- }
-
- /* free the menu */
- auto_free(menu->machine(), menu);
+ if (item)
+ auto_free(machine(), item);
}
/*-------------------------------------------------
- ui_menu_reset - free all items in the menu,
+ reset - free all items in the menu,
and all memory allocated from the memory pool
-------------------------------------------------*/
-void ui_menu_reset(ui_menu *menu, ui_menu_reset_options options)
+void ui_menu::reset(ui_menu_reset_options options)
{
- ui_menu_pool *pool;
-
/* based on the reset option, set the reset info */
- menu->resetpos = 0;
- menu->resetref = NULL;
+ resetpos = 0;
+ resetref = NULL;
if (options == UI_MENU_RESET_REMEMBER_POSITION)
- menu->resetpos = menu->selected;
+ resetpos = selected;
else if (options == UI_MENU_RESET_REMEMBER_REF)
- menu->resetref = menu->item[menu->selected].ref;
+ resetref = item[selected].ref;
/* reset all the pools and the numitems back to 0 */
- for (pool = menu->pool; pool != NULL; pool = pool->next)
- pool->top = (UINT8 *)(pool + 1);
- menu->numitems = 0;
- menu->visitems = 0;
- menu->selected = 0;
+ for (ui_menu_pool *ppool = pool; ppool != NULL; ppool = ppool->next)
+ ppool->top = (UINT8 *)(ppool + 1);
+ numitems = 0;
+ visitems = 0;
+ selected = 0;
astring backtext;
backtext.printf("Return to %s",emulator_info::get_capstartgamenoun());
/* add an item to return */
- if (menu->parent == NULL)
- ui_menu_item_append(menu, backtext.cstr(), NULL, 0, NULL);
- else if (menu->parent->handler == menu_quit_game)
- ui_menu_item_append(menu, exittext, NULL, 0, NULL);
+ if (parent == NULL)
+ item_append(backtext.cstr(), NULL, 0, NULL);
+ else if (parent->is_special_main_menu())
+ item_append("Exit", NULL, 0, NULL);
else
- ui_menu_item_append(menu, priortext, NULL, 0, NULL);
+ item_append("Return to Prior Menu", NULL, 0, NULL);
+}
+
+
+/*-------------------------------------------------
+ is_special_main_menu - returns whether the
+ menu has special needs
+-------------------------------------------------*/
+bool ui_menu::is_special_main_menu() const
+{
+ return special_main_menu;
}
/*-------------------------------------------------
- ui_menu_populated - returns TRUE if the menu
+ set_special_main_menu - set whether the
+ menu has special needs
+-------------------------------------------------*/
+void ui_menu::set_special_main_menu(bool special)
+{
+ special_main_menu = special;
+}
+
+
+/*-------------------------------------------------
+ populated - returns true if the menu
has any non-default items in it
-------------------------------------------------*/
-int ui_menu_populated(ui_menu *menu)
+bool ui_menu::populated()
{
- return (menu->numitems > 1);
+ return numitems > 1;
}
/*-------------------------------------------------
- ui_menu_item_append - append a new item to the
+ item_append - append a new item to the
end of the menu
-------------------------------------------------*/
-void ui_menu_item_append(ui_menu *menu, const char *text, const char *subtext, UINT32 flags, void *ref)
+void ui_menu::item_append(const char *text, const char *subtext, UINT32 flags, void *ref)
{
- ui_menu_item *item;
+ ui_menu_item *pitem;
int index;
/* only allow multiline as the first item */
if ((flags & MENU_FLAG_MULTILINE) != 0)
- assert(menu->numitems == 1);
+ assert(numitems == 1);
/* only allow a single multi-line item */
- else if (menu->numitems >= 2)
- assert((menu->item[0].flags & MENU_FLAG_MULTILINE) == 0);
+ else if (numitems >= 2)
+ assert((item[0].flags & MENU_FLAG_MULTILINE) == 0);
/* realloc the item array if necessary */
- if (menu->numitems >= menu->allocitems)
+ if (numitems >= allocitems)
{
- int olditems = menu->allocitems;
- menu->allocitems += UI_MENU_ALLOC_ITEMS;
- ui_menu_item *newitems = auto_alloc_array(menu->machine(), ui_menu_item, menu->allocitems);
+ int olditems = allocitems;
+ allocitems += UI_MENU_ALLOC_ITEMS;
+ ui_menu_item *newitems = auto_alloc_array(machine(), ui_menu_item, allocitems);
for (int itemnum = 0; itemnum < olditems; itemnum++)
- newitems[itemnum] = menu->item[itemnum];
- auto_free(menu->machine(), menu->item);
- menu->item = newitems;
+ newitems[itemnum] = item[itemnum];
+ auto_free(machine(), item);
+ item = newitems;
}
- index = menu->numitems++;
+ index = numitems++;
/* copy the previous last item to the next one */
if (index != 0)
{
index--;
- menu->item[index + 1] = menu->item[index];
+ item[index + 1] = item[index];
}
/* allocate a new item and populte it */
- item = &menu->item[index];
- item->text = (text != NULL) ? ui_menu_pool_strdup(menu, text) : NULL;
- item->subtext = (subtext != NULL) ? ui_menu_pool_strdup(menu, subtext) : NULL;
- item->flags = flags;
- item->ref = ref;
+ pitem = &item[index];
+ pitem->text = (text != NULL) ? pool_strdup(text) : NULL;
+ pitem->subtext = (subtext != NULL) ? pool_strdup(subtext) : NULL;
+ pitem->flags = flags;
+ pitem->ref = ref;
/* update the selection if we need to */
- if (menu->resetpos == index || (menu->resetref != NULL && menu->resetref == ref))
- menu->selected = index;
- if (menu->resetpos == menu->numitems - 1)
- menu->selected = menu->numitems - 1;
+ if (resetpos == index || (resetref != NULL && resetref == ref))
+ selected = index;
+ if (resetpos == numitems - 1)
+ selected = numitems - 1;
}
/*-------------------------------------------------
- ui_menu_process - process a menu, drawing it
+ process - process a menu, drawing it
and returning any interesting events
-------------------------------------------------*/
-const ui_menu_event *ui_menu_process(running_machine &machine, ui_menu *menu, UINT32 flags)
+const ui_menu_event *ui_menu::process(UINT32 flags)
{
/* reset the menu_event */
- menu->menu_event.iptkey = IPT_INVALID;
+ menu_event.iptkey = IPT_INVALID;
/* first make sure our selection is valid */
- ui_menu_validate_selection(menu, 1);
+ validate_selection(1);
/* draw the menu */
- if (menu->numitems > 1 && (menu->item[0].flags & MENU_FLAG_MULTILINE) != 0)
- ui_menu_draw_text_box(menu);
+ if (numitems > 1 && (item[0].flags & MENU_FLAG_MULTILINE) != 0)
+ draw_text_box();
else
- ui_menu_draw(machine, menu, (flags & UI_MENU_PROCESS_CUSTOM_ONLY) != 0);
+ draw(flags & UI_MENU_PROCESS_CUSTOM_ONLY);
/* process input */
if (!(flags & UI_MENU_PROCESS_NOKEYS))
{
/* read events */
- ui_menu_handle_events(menu);
+ handle_events();
/* handle the keys if we don't already have an menu_event */
- if (menu->menu_event.iptkey == IPT_INVALID)
- ui_menu_handle_keys(menu, flags);
+ if (menu_event.iptkey == IPT_INVALID)
+ handle_keys(flags);
}
/* update the selected item in the menu_event */
- if (menu->menu_event.iptkey != IPT_INVALID && menu->selected >= 0 && menu->selected < menu->numitems)
+ if (menu_event.iptkey != IPT_INVALID && selected >= 0 && selected < numitems)
{
- menu->menu_event.itemref = menu->item[menu->selected].ref;
- return &menu->menu_event;
+ menu_event.itemref = item[selected].ref;
+ return &menu_event;
}
return NULL;
}
/*-------------------------------------------------
- ui_menu_set_custom_render - configure the menu
- for custom rendering
--------------------------------------------------*/
-
-void ui_menu_set_custom_render(ui_menu *menu, ui_menu_custom_func custom, float top, float bottom)
-{
- menu->custom = custom;
- menu->customtop = top;
- menu->custombottom = bottom;
-}
-
-
-/*-------------------------------------------------
- ui_menu_alloc_state - allocate permanent
- memory to represent the menu's state
--------------------------------------------------*/
-
-void *ui_menu_alloc_state(ui_menu *menu, size_t size, ui_menu_destroy_state_func destroy_state)
-{
- if (menu->state != NULL)
- {
- if (menu->destroy_state != NULL)
- (*menu->destroy_state)(menu, menu->state);
- auto_free(menu->machine(), menu->state);
- }
- menu->state = auto_alloc_array_clear(menu->machine(), UINT8, size);
- menu->destroy_state = destroy_state;
-
- return menu->state;
-}
-
-
-/*-------------------------------------------------
- ui_menu_pool_alloc - allocate temporary memory
+ m_pool_alloc - allocate temporary memory
from the menu's memory pool
-------------------------------------------------*/
-void *ui_menu_pool_alloc(ui_menu *menu, size_t size)
+void *ui_menu::m_pool_alloc(size_t size)
{
- ui_menu_pool *pool;
+ ui_menu_pool *ppool;
assert(size < UI_MENU_POOL_SIZE);
/* find a pool with enough room */
- for (pool = menu->pool; pool != NULL; pool = pool->next)
- if (pool->end - pool->top >= size)
+ for (ppool = pool; ppool != NULL; ppool = ppool->next)
+ if (ppool->end - ppool->top >= size)
{
- void *result = pool->top;
- pool->top += size;
+ void *result = ppool->top;
+ ppool->top += size;
return result;
}
/* allocate a new pool */
- pool = (ui_menu_pool *)auto_alloc_array_clear(menu->machine(), UINT8, sizeof(*pool) + UI_MENU_POOL_SIZE);
+ ppool = (ui_menu_pool *)auto_alloc_array_clear(machine(), UINT8, sizeof(*ppool) + UI_MENU_POOL_SIZE);
/* wire it up */
- pool->next = menu->pool;
- menu->pool = pool;
- pool->top = (UINT8 *)(pool + 1);
- pool->end = pool->top + UI_MENU_POOL_SIZE;
- return ui_menu_pool_alloc(menu, size);
+ ppool->next = pool;
+ pool = ppool;
+ ppool->top = (UINT8 *)(ppool + 1);
+ ppool->end = ppool->top + UI_MENU_POOL_SIZE;
+ return m_pool_alloc(size);
}
/*-------------------------------------------------
- ui_menu_pool_strdup - make a temporary string
+ pool_strdup - make a temporary string
copy in the menu's memory pool
-------------------------------------------------*/
-const char *ui_menu_pool_strdup(ui_menu *menu, const char *string)
+const char *ui_menu::pool_strdup(const char *string)
{
- return strcpy((char *)ui_menu_pool_alloc(menu, strlen(string) + 1), string);
+ return strcpy((char *)m_pool_alloc(strlen(string) + 1), string);
}
/*-------------------------------------------------
- ui_menu_get_selection - retrieves the index
+ get_selection - retrieves the index
of the currently selected menu item
-------------------------------------------------*/
-void *ui_menu_get_selection(ui_menu *menu)
+void *ui_menu::get_selection()
{
- return (menu->selected >= 0 && menu->selected < menu->numitems) ? menu->item[menu->selected].ref : NULL;
+ return (selected >= 0 && selected < numitems) ? item[selected].ref : NULL;
}
/*-------------------------------------------------
- ui_menu_set_selection - changes the index
+ set_selection - changes the index
of the currently selected menu item
-------------------------------------------------*/
-void ui_menu_set_selection(ui_menu *menu, void *selected_itemref)
+void ui_menu::set_selection(void *selected_itemref)
{
int itemnum;
- menu->selected = -1;
- for (itemnum = 0; itemnum < menu->numitems; itemnum++)
- if (menu->item[itemnum].ref == selected_itemref)
+ selected = -1;
+ for (itemnum = 0; itemnum < numitems; itemnum++)
+ if (item[itemnum].ref == selected_itemref)
{
- menu->selected = itemnum;
+ selected = itemnum;
break;
}
}
@@ -749,14 +395,14 @@ void ui_menu_set_selection(ui_menu *menu, void *selected_itemref)
***************************************************************************/
/*-------------------------------------------------
- ui_menu_draw - draw a menu
+ draw - draw a menu
-------------------------------------------------*/
-static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly)
+void ui_menu::draw(bool customonly)
{
- float line_height = ui_get_line_height(machine);
- float lr_arrow_width = 0.4f * line_height * machine.render().ui_aspect();
- float ud_arrow_width = line_height * machine.render().ui_aspect();
+ float line_height = ui_get_line_height(machine());
+ float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect();
+ float ud_arrow_width = line_height * machine().render().ui_aspect();
float gutter_width = lr_arrow_width * 1.3f;
float x1, y1, x2, y2;
@@ -776,17 +422,17 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
/* compute the width and height of the full menu */
visible_width = 0;
visible_main_menu_height = 0;
- for (itemnum = 0; itemnum < menu->numitems; itemnum++)
+ for (itemnum = 0; itemnum < numitems; itemnum++)
{
- const ui_menu_item *item = &menu->item[itemnum];
+ const ui_menu_item &pitem = item[itemnum];
float total_width;
/* compute width of left hand side */
- total_width = gutter_width + ui_get_string_width(machine, item->text) + gutter_width;
+ total_width = gutter_width + ui_get_string_width(machine(), pitem.text) + gutter_width;
/* add in width of right hand side */
- if (item->subtext)
- total_width += 2.0f * gutter_width + ui_get_string_width(machine, item->subtext);
+ if (pitem.subtext)
+ total_width += 2.0f * gutter_width + ui_get_string_width(machine(), pitem.subtext);
/* track the maximum */
if (total_width > visible_width)
@@ -797,7 +443,7 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
}
/* account for extra space at the top and bottom */
- visible_extra_menu_height = menu->customtop + menu->custombottom;
+ visible_extra_menu_height = customtop + custombottom;
/* add a little bit of slop for rounding */
visible_width += 0.01f;
@@ -819,7 +465,7 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f;
/* if the menu is at the bottom of the extra, adjust */
- visible_top += menu->customtop;
+ visible_top += customtop;
/* first add us a box */
x1 = visible_left - UI_BOX_LR_BORDER;
@@ -827,14 +473,14 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
x2 = visible_left + visible_width + UI_BOX_LR_BORDER;
y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER;
if (!customonly)
- ui_draw_outlined_box(menu->container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
+ ui_draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
/* determine the first visible line based on the current selection */
- top_line = menu->selected - visible_lines / 2;
+ top_line = selected - visible_lines / 2;
if (top_line < 0)
top_line = 0;
- if (top_line + visible_lines >= menu->numitems)
- top_line = menu->numitems - visible_lines;
+ if (top_line + visible_lines >= numitems)
+ top_line = numitems - visible_lines;
/* determine effective positions taking into account the hilighting arrows */
effective_width = visible_width - 2.0f * gutter_width;
@@ -845,21 +491,21 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
mouse_button = FALSE;
if (!customonly)
{
- mouse_target = ui_input_find_mouse(machine, &mouse_target_x, &mouse_target_y, &mouse_button);
+ mouse_target = ui_input_find_mouse(machine(), &mouse_target_x, &mouse_target_y, &mouse_button);
if (mouse_target != NULL)
- if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *menu->container, mouse_x, mouse_y))
+ if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y))
mouse_hit = TRUE;
}
/* loop over visible lines */
- menu->hover = menu->numitems + 1;
+ hover = numitems + 1;
if (!customonly)
for (linenum = 0; linenum < visible_lines; linenum++)
{
float line_y = visible_top + (float)linenum * line_height;
itemnum = top_line + linenum;
- const ui_menu_item *item = &menu->item[itemnum];
- const char *itemtext = item->text;
+ const ui_menu_item &pitem = item[itemnum];
+ const char *itemtext = pitem.text;
rgb_t fgcolor = UI_TEXT_COLOR;
rgb_t bgcolor = UI_TEXT_BG_COLOR;
rgb_t fgcolor2 = UI_SUBITEM_COLOR;
@@ -870,11 +516,11 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
float line_y1 = line_y + line_height;
/* set the hover if this is our item */
- if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && item_is_selectable(item))
- menu->hover = itemnum;
+ if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable())
+ hover = itemnum;
/* if we're selected, draw with a different background */
- if (itemnum == menu->selected)
+ if (itemnum == selected)
{
fgcolor = UI_SELECTED_COLOR;
bgcolor = UI_SELECTED_BG_COLOR;
@@ -883,7 +529,7 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
}
/* else if the mouse is over this item, draw with a different background */
- else if (itemnum == menu->hover)
+ else if (itemnum == hover)
{
fgcolor = UI_MOUSEOVER_COLOR;
bgcolor = UI_MOUSEOVER_BG_COLOR;
@@ -893,13 +539,13 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
/* if we have some background hilighting to do, add a quad behind everything else */
if (bgcolor != UI_TEXT_BG_COLOR)
- menu->container->add_quad(line_x0, line_y0, line_x1, line_y1, bgcolor, hilight_texture,
+ container->add_quad(line_x0, line_y0, line_x1, line_y1, bgcolor, hilight_texture,
PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
/* if we're on the top line, display the up arrow */
if (linenum == 0 && top_line != 0)
{
- menu->container->add_quad(
+ container->add_quad(
0.5f * (x1 + x2) - 0.5f * ud_arrow_width,
line_y + 0.25f * line_height,
0.5f * (x1 + x2) + 0.5f * ud_arrow_width,
@@ -907,14 +553,14 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
fgcolor,
arrow_texture,
PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT0));
- if (menu->hover == itemnum)
- menu->hover = -2;
+ if (hover == itemnum)
+ hover = -2;
}
/* if we're on the bottom line, display the down arrow */
- else if (linenum == visible_lines - 1 && itemnum != menu->numitems - 1)
+ else if (linenum == visible_lines - 1 && itemnum != numitems - 1)
{
- menu->container->add_quad(
+ container->add_quad(
0.5f * (x1 + x2) - 0.5f * ud_arrow_width,
line_y + 0.25f * line_height,
0.5f * (x1 + x2) + 0.5f * ud_arrow_width,
@@ -922,49 +568,49 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
fgcolor,
arrow_texture,
PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT0 ^ ORIENTATION_FLIP_Y));
- if (menu->hover == itemnum)
- menu->hover = -1;
+ if (hover == itemnum)
+ hover = -1;
}
/* if we're just a divider, draw a line */
else if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0)
- menu->container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
/* if we don't have a subitem, just draw the string centered */
- else if (item->subtext == NULL)
- ui_draw_text_full(menu->container, itemtext, effective_left, line_y, effective_width,
+ else if (pitem.subtext == NULL)
+ ui_draw_text_full(container, itemtext, effective_left, line_y, effective_width,
JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, NULL, NULL);
/* otherwise, draw the item on the left and the subitem text on the right */
else
{
- int subitem_invert = item->flags & MENU_FLAG_INVERT;
- const char *subitem_text = item->subtext;
+ int subitem_invert = pitem.flags & MENU_FLAG_INVERT;
+ const char *subitem_text = pitem.subtext;
float item_width, subitem_width;
/* draw the left-side text */
- ui_draw_text_full(menu->container, itemtext, effective_left, line_y, effective_width,
+ ui_draw_text_full(container, itemtext, effective_left, line_y, effective_width,
JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, &item_width, NULL);
/* give 2 spaces worth of padding */
item_width += 2.0f * gutter_width;
/* if the subitem doesn't fit here, display dots */
- if (ui_get_string_width(machine, subitem_text) > effective_width - item_width)
+ if (ui_get_string_width(machine(), subitem_text) > effective_width - item_width)
{
subitem_text = "...";
- if (itemnum == menu->selected)
+ if (itemnum == selected)
selected_subitem_too_big = TRUE;
}
/* draw the subitem right-justified */
- ui_draw_text_full(menu->container, subitem_text, effective_left + item_width, line_y, effective_width - item_width,
+ ui_draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width,
JUSTIFY_RIGHT, WRAP_TRUNCATE, DRAW_NORMAL, subitem_invert ? fgcolor3 : fgcolor2, bgcolor, &subitem_width, NULL);
/* apply arrows */
- if (itemnum == menu->selected && (item->flags & MENU_FLAG_LEFT_ARROW))
+ if (itemnum == selected && (pitem.flags & MENU_FLAG_LEFT_ARROW))
{
- menu->container->add_quad(
+ container->add_quad(
effective_left + effective_width - subitem_width - gutter_width,
line_y + 0.1f * line_height,
effective_left + effective_width - subitem_width - gutter_width + lr_arrow_width,
@@ -973,9 +619,9 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
arrow_texture,
PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X));
}
- if (itemnum == menu->selected && (item->flags & MENU_FLAG_RIGHT_ARROW))
+ if (itemnum == selected && (pitem.flags & MENU_FLAG_RIGHT_ARROW))
{
- menu->container->add_quad(
+ container->add_quad(
effective_left + effective_width + gutter_width - lr_arrow_width,
line_y + 0.1f * line_height,
effective_left + effective_width + gutter_width,
@@ -990,15 +636,15 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
/* if the selected subitem is too big, display it in a separate offset box */
if (selected_subitem_too_big)
{
- const ui_menu_item *item = &menu->item[menu->selected];
- int subitem_invert = item->flags & MENU_FLAG_INVERT;
- linenum = menu->selected - top_line;
+ const ui_menu_item &pitem = item[selected];
+ int subitem_invert = pitem.flags & MENU_FLAG_INVERT;
+ linenum = selected - top_line;
float line_y = visible_top + (float)linenum * line_height;
float target_width, target_height;
float target_x, target_y;
/* compute the multi-line target width/height */
- ui_draw_text_full(menu->container, item->subtext, 0, 0, visible_width * 0.75f,
+ ui_draw_text_full(container, pitem.subtext, 0, 0, visible_width * 0.75f,
JUSTIFY_RIGHT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height);
/* determine the target location */
@@ -1008,51 +654,50 @@ static void ui_menu_draw(running_machine &machine, ui_menu *menu, int customonly
target_y = line_y - target_height - UI_BOX_TB_BORDER;
/* add a box around that */
- ui_draw_outlined_box(menu->container, target_x - UI_BOX_LR_BORDER,
+ ui_draw_outlined_box(container, 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, subitem_invert ? UI_SELECTED_BG_COLOR : UI_BACKGROUND_COLOR);
- ui_draw_text_full(menu->container, item->subtext, target_x, target_y, target_width,
+ ui_draw_text_full(container, pitem.subtext, target_x, target_y, target_width,
JUSTIFY_RIGHT, WRAP_WORD, DRAW_NORMAL, UI_SELECTED_COLOR, UI_SELECTED_BG_COLOR, NULL, NULL);
}
- /* if there is something special to add, do it by calling the passed routine */
- if (menu->custom != NULL)
- {
- void *selectedref = (menu->selected >= 0 && menu->selected < menu->numitems) ? menu->item[menu->selected].ref : NULL;
- (*menu->custom)(menu->machine(), menu, menu->state, selectedref, menu->customtop, menu->custombottom, x1, y1, x2, y2);
- }
+ /* if there is something special to add, do it by calling the virtual method */
+ custom_render((selected >= 0 && selected < numitems) ? item[selected].ref : NULL, customtop, custombottom, x1, y1, x2, y2);
/* return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow */
- menu->visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != menu->numitems);
+ visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != numitems);
}
+void ui_menu::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2)
+{
+}
/*-------------------------------------------------
- ui_menu_draw_text_box - draw a multiline
+ draw_text_box - draw a multiline
word-wrapped text box with a menu item at the
bottom
-------------------------------------------------*/
-static void ui_menu_draw_text_box(ui_menu *menu)
+void ui_menu::draw_text_box()
{
- const char *text = menu->item[0].text;
- const char *backtext = menu->item[1].text;
- float line_height = ui_get_line_height(menu->machine());
- float lr_arrow_width = 0.4f * line_height * menu->machine().render().ui_aspect();
+ const char *text = item[0].text;
+ const char *backtext = item[1].text;
+ float line_height = ui_get_line_height(machine());
+ float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect();
float gutter_width = lr_arrow_width;
float target_width, target_height, prior_width;
float target_x, target_y;
/* compute the multi-line target width/height */
- ui_draw_text_full(menu->container, text, 0, 0, 1.0f - 2.0f * UI_BOX_LR_BORDER - 2.0f * gutter_width,
+ ui_draw_text_full(container, text, 0, 0, 1.0f - 2.0f * UI_BOX_LR_BORDER - 2.0f * gutter_width,
JUSTIFY_LEFT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height);
target_height += 2.0f * line_height;
if (target_height > 1.0f - 2.0f * UI_BOX_TB_BORDER)
target_height = floor((1.0f - 2.0f * UI_BOX_TB_BORDER) / line_height) * line_height;
/* maximum against "return to prior menu" text */
- prior_width = ui_get_string_width(menu->machine(), backtext) + 2.0f * gutter_width;
+ prior_width = ui_get_string_width(machine(), backtext) + 2.0f * gutter_width;
target_width = MAX(target_width, prior_width);
/* determine the target location */
@@ -1070,15 +715,15 @@ static void ui_menu_draw_text_box(ui_menu *menu)
target_y = 1.0f - UI_BOX_TB_BORDER - target_height;
/* add a box around that */
- ui_draw_outlined_box(menu->container, target_x - UI_BOX_LR_BORDER - gutter_width,
+ ui_draw_outlined_box(container, target_x - UI_BOX_LR_BORDER - gutter_width,
target_y - UI_BOX_TB_BORDER,
target_x + target_width + gutter_width + UI_BOX_LR_BORDER,
- target_y + target_height + UI_BOX_TB_BORDER, (menu->item[0].flags & MENU_FLAG_REDTEXT) ? UI_RED_COLOR : UI_BACKGROUND_COLOR);
- ui_draw_text_full(menu->container, text, target_x, target_y, target_width,
+ target_y + target_height + UI_BOX_TB_BORDER, (item[0].flags & MENU_FLAG_REDTEXT) ? UI_RED_COLOR : UI_BACKGROUND_COLOR);
+ ui_draw_text_full(container, text, target_x, target_y, target_width,
JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, NULL);
/* draw the "return to prior menu" text with a hilight behind it */
- menu->container->add_quad(
+ container->add_quad(
target_x + 0.5f * UI_LINE_WIDTH,
target_y + target_height - line_height,
target_x + target_width - 0.5f * UI_LINE_WIDTH,
@@ -1086,57 +731,57 @@ static void ui_menu_draw_text_box(ui_menu *menu)
UI_SELECTED_BG_COLOR,
hilight_texture,
PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE));
- ui_draw_text_full(menu->container, backtext, target_x, target_y + target_height - line_height, target_width,
+ ui_draw_text_full(container, backtext, target_x, target_y + target_height - line_height, target_width,
JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, UI_SELECTED_COLOR, UI_SELECTED_BG_COLOR, NULL, NULL);
/* artificially set the hover to the last item so a double-click exits */
- menu->hover = menu->numitems - 1;
+ hover = numitems - 1;
}
/*-------------------------------------------------
- ui_menu_handle_events - generically handle
+ handle_events - generically handle
input events for a menu
-------------------------------------------------*/
-static void ui_menu_handle_events(ui_menu *menu)
+void ui_menu::handle_events()
{
int stop = FALSE;
- ui_event menu_event;
+ ui_event local_menu_event;
/* loop while we have interesting events */
- while (ui_input_pop_event(menu->machine(), &menu_event) && !stop)
+ while (ui_input_pop_event(machine(), &local_menu_event) && !stop)
{
- switch (menu_event.event_type)
+ switch (local_menu_event.event_type)
{
/* if we are hovering over a valid item, select it with a single click */
case UI_EVENT_MOUSE_DOWN:
- if (menu->hover >= 0 && menu->hover < menu->numitems)
- menu->selected = menu->hover;
- else if (menu->hover == -2)
+ if (hover >= 0 && hover < numitems)
+ selected = hover;
+ else if (hover == -2)
{
- menu->selected -= menu->visitems - 1;
- ui_menu_validate_selection(menu, 1);
+ selected -= visitems - 1;
+ validate_selection(1);
}
- else if (menu->hover == -1)
+ else if (hover == -1)
{
- menu->selected += menu->visitems - 1;
- ui_menu_validate_selection(menu, 1);
+ selected += visitems - 1;
+ validate_selection(1);
}
break;
/* if we are hovering over a valid item, fake a UI_SELECT with a double-click */
case UI_EVENT_MOUSE_DOUBLE_CLICK:
- if (menu->hover >= 0 && menu->hover < menu->numitems)
+ if (hover >= 0 && hover < numitems)
{
- menu->selected = menu->hover;
- if (menu_event.event_type == UI_EVENT_MOUSE_DOUBLE_CLICK)
+ selected = hover;
+ if (local_menu_event.event_type == UI_EVENT_MOUSE_DOUBLE_CLICK)
{
- menu->menu_event.iptkey = IPT_UI_SELECT;
- if (menu->selected == menu->numitems - 1)
+ menu_event.iptkey = IPT_UI_SELECT;
+ if (selected == numitems - 1)
{
- menu->menu_event.iptkey = IPT_UI_CANCEL;
- ui_menu_stack_pop(menu->machine());
+ menu_event.iptkey = IPT_UI_CANCEL;
+ ui_menu::stack_pop(machine());
}
}
stop = TRUE;
@@ -1145,8 +790,8 @@ static void ui_menu_handle_events(ui_menu *menu)
/* translate CHAR events into specials */
case UI_EVENT_CHAR:
- menu->menu_event.iptkey = IPT_SPECIAL;
- menu->menu_event.unichar = menu_event.ch;
+ menu_event.iptkey = IPT_SPECIAL;
+ menu_event.unichar = local_menu_event.ch;
stop = TRUE;
break;
@@ -1159,152 +804,152 @@ static void ui_menu_handle_events(ui_menu *menu)
/*-------------------------------------------------
- ui_menu_handle_keys - generically handle
+ handle_keys - generically handle
keys for a menu
-------------------------------------------------*/
-static void ui_menu_handle_keys(ui_menu *menu, UINT32 flags)
+void ui_menu::handle_keys(UINT32 flags)
{
- int ignorepause = ui_menu_is_force_game_select();
+ int ignorepause = ui_menu::stack_has_special_main_menu();
int ignoreright = FALSE;
int ignoreleft = FALSE;
int code;
/* bail if no items */
- if (menu->numitems == 0)
+ if (numitems == 0)
return;
/* if we hit select, return TRUE or pop the stack, depending on the item */
- if (exclusive_input_pressed(menu, IPT_UI_SELECT, 0))
+ if (exclusive_input_pressed(IPT_UI_SELECT, 0))
{
- if (menu->selected == menu->numitems - 1)
+ if (selected == numitems - 1)
{
- menu->menu_event.iptkey = IPT_UI_CANCEL;
- ui_menu_stack_pop(menu->machine());
+ menu_event.iptkey = IPT_UI_CANCEL;
+ ui_menu::stack_pop(machine());
}
return;
}
/* hitting cancel also pops the stack */
- if (exclusive_input_pressed(menu, IPT_UI_CANCEL, 0))
+ if (exclusive_input_pressed(IPT_UI_CANCEL, 0))
{
- ui_menu_stack_pop(menu->machine());
+ ui_menu::stack_pop(machine());
return;
}
/* validate the current selection */
- ui_menu_validate_selection(menu, 1);
+ validate_selection(1);
/* swallow left/right keys if they are not appropriate */
- ignoreleft = ((menu->item[menu->selected].flags & MENU_FLAG_LEFT_ARROW) == 0);
- ignoreright = ((menu->item[menu->selected].flags & MENU_FLAG_RIGHT_ARROW) == 0);
+ ignoreleft = ((item[selected].flags & MENU_FLAG_LEFT_ARROW) == 0);
+ ignoreright = ((item[selected].flags & MENU_FLAG_RIGHT_ARROW) == 0);
/* accept left/right keys as-is with repeat */
- if (!ignoreleft && exclusive_input_pressed(menu, IPT_UI_LEFT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
+ if (!ignoreleft && exclusive_input_pressed(IPT_UI_LEFT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
return;
- if (!ignoreright && exclusive_input_pressed(menu, IPT_UI_RIGHT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
+ if (!ignoreright && exclusive_input_pressed(IPT_UI_RIGHT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0))
return;
/* up backs up by one item */
- if (exclusive_input_pressed(menu, IPT_UI_UP, 6))
+ if (exclusive_input_pressed(IPT_UI_UP, 6))
{
- menu->selected = (menu->selected + menu->numitems - 1) % menu->numitems;
- ui_menu_validate_selection(menu, -1);
+ selected = (selected + numitems - 1) % numitems;
+ validate_selection(-1);
}
/* down advances by one item */
- if (exclusive_input_pressed(menu, IPT_UI_DOWN, 6))
+ if (exclusive_input_pressed(IPT_UI_DOWN, 6))
{
- menu->selected = (menu->selected + 1) % menu->numitems;
- ui_menu_validate_selection(menu, 1);
+ selected = (selected + 1) % numitems;
+ validate_selection(1);
}
/* page up backs up by visitems */
- if (exclusive_input_pressed(menu, IPT_UI_PAGE_UP, 6))
+ if (exclusive_input_pressed(IPT_UI_PAGE_UP, 6))
{
- menu->selected -= menu->visitems - 1;
- ui_menu_validate_selection(menu, 1);
+ selected -= visitems - 1;
+ validate_selection(1);
}
/* page down advances by visitems */
- if (exclusive_input_pressed(menu, IPT_UI_PAGE_DOWN, 6))
+ if (exclusive_input_pressed(IPT_UI_PAGE_DOWN, 6))
{
- menu->selected += menu->visitems - 1;
- ui_menu_validate_selection(menu, -1);
+ selected += visitems - 1;
+ validate_selection(-1);
}
/* home goes to the start */
- if (exclusive_input_pressed(menu, IPT_UI_HOME, 0))
+ if (exclusive_input_pressed(IPT_UI_HOME, 0))
{
- menu->selected = 0;
- ui_menu_validate_selection(menu, 1);
+ selected = 0;
+ validate_selection(1);
}
/* end goes to the last */
- if (exclusive_input_pressed(menu, IPT_UI_END, 0))
+ if (exclusive_input_pressed(IPT_UI_END, 0))
{
- menu->selected = menu->numitems - 1;
- ui_menu_validate_selection(menu, -1);
+ selected = numitems - 1;
+ validate_selection(-1);
}
/* pause enables/disables pause */
- if (!ignorepause && exclusive_input_pressed(menu, IPT_UI_PAUSE, 0))
+ if (!ignorepause && exclusive_input_pressed(IPT_UI_PAUSE, 0))
{
- if (menu->machine().paused())
- menu->machine().resume();
+ if (machine().paused())
+ machine().resume();
else
- menu->machine().pause();
+ machine().pause();
}
/* handle a toggle cheats request */
- if (ui_input_pressed_repeat(menu->machine(), IPT_UI_TOGGLE_CHEAT, 0))
- menu->machine().cheat().set_enable(!menu->machine().cheat().enabled());
+ if (ui_input_pressed_repeat(machine(), IPT_UI_TOGGLE_CHEAT, 0))
+ machine().cheat().set_enable(!machine().cheat().enabled());
/* see if any other UI keys are pressed */
- if (menu->menu_event.iptkey == IPT_INVALID)
+ if (menu_event.iptkey == IPT_INVALID)
for (code = __ipt_ui_start; code <= __ipt_ui_end; code++)
{
if (code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause))
continue;
- if (exclusive_input_pressed(menu, code, 0))
+ if (exclusive_input_pressed(code, 0))
break;
}
}
/*-------------------------------------------------
- ui_menu_validate_selection - validate the
+ validate_selection - validate the
current selection and ensure it is on a
correct item
-------------------------------------------------*/
-static void ui_menu_validate_selection(ui_menu *menu, int scandir)
+void ui_menu::validate_selection(int scandir)
{
/* clamp to be in range */
- if (menu->selected < 0)
- menu->selected = 0;
- else if (menu->selected >= menu->numitems)
- menu->selected = menu->numitems - 1;
+ if (selected < 0)
+ selected = 0;
+ else if (selected >= numitems)
+ selected = numitems - 1;
/* skip past unselectable items */
- while (!item_is_selectable(&menu->item[menu->selected]))
- menu->selected = (menu->selected + menu->numitems + scandir) % menu->numitems;
+ while (!item[selected].is_selectable())
+ selected = (selected + numitems + scandir) % numitems;
}
/*-------------------------------------------------
- ui_menu_clear_free_list - clear out anything
+ clear_free_list - clear out anything
accumulated in the free list
-------------------------------------------------*/
-static void ui_menu_clear_free_list(running_machine &machine)
+void ui_menu::clear_free_list(running_machine &machine)
{
while (menu_free != NULL)
{
ui_menu *menu = menu_free;
menu_free = menu->parent;
- ui_menu_free(menu);
+ auto_free(machine, menu);
}
}
@@ -1315,35 +960,34 @@ static void ui_menu_clear_free_list(running_machine &machine)
***************************************************************************/
/*-------------------------------------------------
- ui_menu_stack_reset - reset the menu stack
+ ui_menu::stack_reset - reset the menu stack
-------------------------------------------------*/
-void ui_menu_stack_reset(running_machine &machine)
+void ui_menu::stack_reset(running_machine &machine)
{
while (menu_stack != NULL)
- ui_menu_stack_pop(machine);
+ ui_menu::stack_pop(machine);
}
/*-------------------------------------------------
- ui_menu_stack_push - push a new menu onto the
+ stack_push - push a new menu onto the
stack
-------------------------------------------------*/
-void ui_menu_stack_push(ui_menu *menu)
+void ui_menu::stack_push(ui_menu *menu)
{
menu->parent = menu_stack;
menu_stack = menu;
- ui_menu_reset(menu, UI_MENU_RESET_SELECT_FIRST);
ui_input_reset(menu->machine());
}
/*-------------------------------------------------
- ui_menu_stack_pop - pop a menu from the stack
+ stack_pop - pop a menu from the stack
-------------------------------------------------*/
-void ui_menu_stack_pop(running_machine &machine)
+void ui_menu::stack_pop(running_machine &machine)
{
if (menu_stack != NULL)
{
@@ -1356,2605 +1000,70 @@ void ui_menu_stack_pop(running_machine &machine)
}
-
-/***************************************************************************
- UI SYSTEM INTERACTION
-***************************************************************************/
-
/*-------------------------------------------------
- ui_menu_ui_handler - displays the current menu
- and calls the menu handler
+ ui_menu::stack_has_special_main_menu -
+ check in the special main menu is in the stack
-------------------------------------------------*/
-UINT32 ui_menu_ui_handler(running_machine &machine, render_container *container, UINT32 state)
-{
- /* if we have no menus stacked up, start with the main menu */
- if (menu_stack == NULL)
- ui_menu_stack_push(ui_menu_alloc(machine, container, menu_main, NULL));
-
- /* update the menu state */
- if (menu_stack != NULL)
- {
- ui_menu *menu = menu_stack;
- (*menu->handler)(machine, menu, menu->parameter, menu->state);
- }
-
- /* clear up anything pending to be released */
- ui_menu_clear_free_list(machine);
-
- /* if the menus are to be hidden, return a cancel here */
- if ((ui_input_pressed(machine, IPT_UI_CONFIGURE) && !ui_menu_is_force_game_select()) || menu_stack == NULL)
- return UI_HANDLER_CANCEL;
-
- return 0;
-}
-
-
-/*-------------------------------------------------
- ui_slider_ui_handler - pushes the slider
- menu on the stack and hands off to the
- standard menu handler
--------------------------------------------------*/
-
-UINT32 ui_slider_ui_handler(running_machine &machine, render_container *container, UINT32 state)
-{
- UINT32 result;
-
- /* if this is the first call, push the sliders menu */
- if (state)
- ui_menu_stack_push(ui_menu_alloc(machine, container, menu_sliders, (void *)1));
-
- /* handle standard menus */
- result = ui_menu_ui_handler(machine, container, state);
-
- /* if we are cancelled, pop the sliders menu */
- if (result == UI_HANDLER_CANCEL)
- ui_menu_stack_pop(machine);
-
- return (menu_stack != NULL && menu_stack->handler == menu_sliders && menu_stack->parameter != NULL) ? 0 : UI_HANDLER_CANCEL;
-}
-
-
-/*-------------------------------------------------
- ui_menu_force_game_select - force the game
- select menu to be visible and inescapable
--------------------------------------------------*/
-
-void ui_menu_force_game_select(running_machine &machine, render_container *container)
-{
- char *gamename = (char *)machine.options().system_name();
-
- /* reset the menu stack */
- ui_menu_stack_reset(machine);
-
- /* add the quit entry followed by the game select entry */
- ui_menu_stack_push(ui_menu_alloc(machine, container, menu_quit_game, NULL));
- ui_menu_stack_push(ui_menu_alloc(machine, container, menu_select_game, gamename));
-
- /* force the menus on */
- ui_show_menu();
-
- /* make sure MAME is paused */
- machine.pause();
-}
-
-
-/*-------------------------------------------------
- ui_menu_is_force_game_select - return true
- if we are currently in "force game select"
- mode
--------------------------------------------------*/
-
-int ui_menu_is_force_game_select(void)
+bool ui_menu::stack_has_special_main_menu()
{
ui_menu *menu;
for (menu = menu_stack; menu != NULL; menu = menu->parent)
- if (menu->handler == menu_quit_game && menu->parent == NULL)
- return TRUE;
+ if (menu->is_special_main_menu())
+ return true;
- return FALSE;
+ return false;
}
-
-
-/***************************************************************************
- MENU HANDLERS
-***************************************************************************/
-
-/*-------------------------------------------------
- menu_main - handle the main menu
--------------------------------------------------*/
-
-static void menu_main(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu::do_handle()
{
- const ui_menu_event *menu_event;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_main_populate(machine, menu, state);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
- if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT)
- ui_menu_stack_push(ui_menu_alloc(machine, menu->container, (ui_menu_handler_func)menu_event->itemref, NULL));
-}
-
-
-/*-------------------------------------------------
- ui_menu_keyboard_mode - menu that
--------------------------------------------------*/
-
-static void ui_menu_keyboard_mode(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- const ui_menu_event *menu_event;
- int natural = ui_get_use_natural_keyboard(machine);
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- {
- ui_menu_item_append(menu, "Keyboard Mode:", natural ? "Natural" : "Emulated", natural ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, NULL);
- }
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
-
- if (menu_event != NULL)
- {
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) {
- ui_set_use_natural_keyboard(machine, natural ^ TRUE);
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- }
- }
-}
-
-
-/*-------------------------------------------------
- ui_slot_get_current_index - returns
--------------------------------------------------*/
-int ui_slot_get_current_index(running_machine &machine, device_slot_interface *slot)
-{
- const char *current = machine.options().value(slot->device().tag());
- const slot_interface* intf = slot->get_slot_interfaces();
- int val = -1;
- for (int i = 0; intf[i].name != NULL; i++) {
- if (strcmp(current, intf[i].name) == 0) val = i;
- }
- return val;
-}
-
-/*-------------------------------------------------
- ui_slot_get_length - returns
--------------------------------------------------*/
-int ui_slot_get_length(running_machine &machine, device_slot_interface *slot)
-{
- const slot_interface* intf = slot->get_slot_interfaces();
- int val = 0;
- for (int i = 0; intf[i].name != NULL; i++) val++;
- return val;
-}
-
-/*-------------------------------------------------
- ui_slot_get_next - returns
--------------------------------------------------*/
-const char *ui_slot_get_next(running_machine &machine, device_slot_interface *slot)
-{
- int idx = ui_slot_get_current_index(machine, slot) + 1;
- if (idx==ui_slot_get_length(machine,slot)) return "";
- return slot->get_slot_interfaces()[idx].name;
-}
-
-/*-------------------------------------------------
- ui_slot_get_prev - returns
--------------------------------------------------*/
-const char *ui_slot_get_prev(running_machine &machine, device_slot_interface *slot)
-{
- int idx = ui_slot_get_current_index(machine, slot) - 1;
- if (idx==-1) return "";
- if (idx==-2) idx = ui_slot_get_length(machine,slot) -1;
- if (idx==-1) return "";
- return slot->get_slot_interfaces()[idx].name;
-}
-
-/*-------------------------------------------------
- ui_get_slot_device - returns
--------------------------------------------------*/
-const char *ui_get_slot_device(running_machine &machine, device_slot_interface *slot)
-{
- return machine.options().value(slot->device().tag());
-}
-
-
-/*-------------------------------------------------
- ui_set_use_natural_keyboard - specifies
- whether the natural keyboard is active
--------------------------------------------------*/
-
-void ui_set_slot_device(running_machine &machine, device_slot_interface *slot, const char *val)
-{
- astring error;
- machine.options().set_value(slot->device().tag(), val, OPTION_PRIORITY_CMDLINE, error);
- assert(!error);
-}
-
-/*-------------------------------------------------
- menu_slot_devices_populate - populates the main
- slot device menu
--------------------------------------------------*/
-
-static void menu_slot_devices_populate(running_machine &machine, ui_menu *menu, void *state)
-{
- device_slot_interface *slot = NULL;
-
- /* cycle through all devices for this system */
- for (bool gotone = machine.devicelist().first(slot); gotone; gotone = slot->next(slot))
- {
- /* record the menu item */
- const char *title = ui_get_slot_device(machine,slot);
- ui_menu_item_append(menu, slot->device().tag(), strcmp(title,"")==0 ? "------" : title, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)slot);
- }
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
- ui_menu_item_append(menu, "Reset", NULL, 0, NULL);
-}
-
-/*-------------------------------------------------
- ui_menu_slot_devices - menu that
--------------------------------------------------*/
-
-static void ui_menu_slot_devices(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- const ui_menu_event *menu_event;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- {
- menu_slot_devices_populate(machine, menu, state);
- }
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
-
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) {
- device_slot_interface *slot = (device_slot_interface *)menu_event->itemref;
- const char *val = (menu_event->iptkey == IPT_UI_LEFT) ? ui_slot_get_prev(machine,slot) : ui_slot_get_next(machine,slot);
- ui_set_slot_device(machine,slot,val);
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- }
- } else if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT) {
- machine.schedule_hard_reset();
- }
+ if(!populated())
+ populate();
+ handle();
}
-/*-------------------------------------------------
- menu_main_populate - populate the main menu
--------------------------------------------------*/
-
-static void menu_main_populate(running_machine &machine, ui_menu *menu, void *state)
-{
- input_field_config *field;
- input_port_config *port;
- int has_configs = FALSE;
- int has_analog = FALSE;
- int has_dips = FALSE;
- astring menu_text;
- /* scan the input port array to see what options we need to enable */
- for (port = machine.m_portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
- {
- if (field->type == IPT_DIPSWITCH)
- has_dips = TRUE;
- if (field->type == IPT_CONFIG)
- has_configs = TRUE;
- if (input_type_is_analog(field->type))
- has_analog = TRUE;
- }
-
- /* add input menu items */
- ui_menu_item_append(menu, "Input (general)", NULL, 0, (void *)menu_input_groups);
-
- menu_text.printf("Input (this %s)",emulator_info::get_capstartgamenoun());
- ui_menu_item_append(menu, menu_text.cstr(), NULL, 0, (void *)menu_input_specific);
-
- /* add optional input-related menus */
- if (has_dips)
- ui_menu_item_append(menu, "Dip Switches", NULL, 0, (void *)menu_settings_dip_switches);
- if (has_configs)
- ui_menu_item_append(menu, "Driver Configuration", NULL, 0, (void *)menu_settings_driver_config);
- if (has_analog)
- ui_menu_item_append(menu, "Analog Controls", NULL, 0, (void *)menu_analog);
-
- /* add bookkeeping menu */
- ui_menu_item_append(menu, "Bookkeeping Info", NULL, 0, (void *)menu_bookkeeping);
-
- /* add game info menu */
- menu_text.printf("%s Information",emulator_info::get_capstartgamenoun());
- ui_menu_item_append(menu, menu_text.cstr(), NULL, 0, (void *)menu_game_info);
-
- device_image_interface *image = NULL;
- if (machine.devicelist().first(image))
- {
- /* add image info menu */
- ui_menu_item_append(menu, "Image Information", NULL, 0, (void*)ui_image_menu_image_info);
-
- /* add file manager menu */
- ui_menu_item_append(menu, "File Manager", NULL, 0, (void*)ui_image_menu_file_manager);
-
- /* add tape control menu */
- if (machine.devicelist().first(CASSETTE))
- ui_menu_item_append(menu, "Tape Control", NULL, 0, (void*)ui_mess_menu_tape_control);
-
- /* add bitbanger control menu */
- if (machine.devicelist().first(BITBANGER))
- ui_menu_item_append(menu, "Bitbanger Control", NULL, 0, (void*)ui_mess_menu_bitbanger_control);
- }
-
- device_slot_interface *slot = NULL;
- if (machine.devicelist().first(slot))
- {
- /* add image info menu */
- ui_menu_item_append(menu, "Slot Devices", NULL, 0, (void*)ui_menu_slot_devices);
- }
-
- /* add keyboard mode menu */
- if (input_machine_has_keyboard(machine) && inputx_can_post(machine))
- ui_menu_item_append(menu, "Keyboard Mode", NULL, 0, (void *)ui_menu_keyboard_mode);
-
- /* add sliders menu */
- ui_menu_item_append(menu, "Slider Controls", NULL, 0, (void *)menu_sliders);
-
- /* add video options menu */
- ui_menu_item_append(menu, "Video Options", NULL, 0, (machine.render().target_by_index(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, (void *)menu_crosshair);
-
- /* add cheat menu */
- if (machine.options().cheat() && machine.cheat().first() != NULL)
- ui_menu_item_append(menu, "Cheat", NULL, 0, (void *)menu_cheat);
-
- /* add memory card menu */
- if (machine.config().m_memcard_handler != NULL)
- ui_menu_item_append(menu, "Memory Card", NULL, 0, (void *)menu_memory_card);
-
- /* add reset and exit menus */
- menu_text.printf("Select New %s",emulator_info::get_capstartgamenoun());
- ui_menu_item_append(menu, menu_text.cstr(), NULL, 0, (void *)menu_select_game);
-}
-
-
-/*-------------------------------------------------
- menu_input_groups - handle the input groups
- menu
--------------------------------------------------*/
-
-static void menu_input_groups(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- const ui_menu_event *menu_event;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_input_groups_populate(machine, menu, state);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
- if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT)
- ui_menu_stack_push(ui_menu_alloc(machine, menu->container, menu_input_general, menu_event->itemref));
-}
-
-
-/*-------------------------------------------------
- menu_input_groups_populate - populate the
- input groups menu
--------------------------------------------------*/
-
-static void menu_input_groups_populate(running_machine &machine, ui_menu *menu, void *state)
-{
- int player;
-
- /* build up the menu */
- ui_menu_item_append(menu, "User Interface", NULL, 0, (void *)(IPG_UI + 1));
- for (player = 0; player < MAX_PLAYERS; player++)
- {
- char buffer[40];
- sprintf(buffer, "Player %d Controls", player + 1);
- ui_menu_item_append(menu, buffer, NULL, 0, (void *)(FPTR)(IPG_PLAYER1 + player + 1));
- }
- ui_menu_item_append(menu, "Other Controls", NULL, 0, (void *)(FPTR)(IPG_OTHER + 1));
-}
-
-
-
-/*-------------------------------------------------
- menu_input_general - handle the general
- input menu
--------------------------------------------------*/
-
-static void menu_input_general(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- menu_input_common(machine, menu, parameter, state);
-}
-
-
-/*-------------------------------------------------
- menu_input_general_populate - populate the
- general input menu
--------------------------------------------------*/
-
-static void menu_input_general_populate(running_machine &machine, ui_menu *menu, input_menu_state *menustate, int group)
-{
- input_item_data *itemlist = NULL;
- int suborder[SEQ_TYPE_TOTAL];
- astring tempstring;
- int sortorder = 1;
-
- /* create a mini lookup table for sort order based on sequence type */
- suborder[SEQ_TYPE_STANDARD] = 0;
- suborder[SEQ_TYPE_DECREMENT] = 1;
- suborder[SEQ_TYPE_INCREMENT] = 2;
-
- /* iterate over the input ports and add menu items */
- for (input_type_entry *entry = input_type_list(machine).first(); entry != NULL; entry = entry->next())
-
- /* add if we match the group and we have a valid name */
- if (entry->group == group && entry->name != NULL && entry->name[0] != 0)
- {
- input_seq_type seqtype;
-
- /* loop over all sequence types */
- sortorder++;
- for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
- {
- /* build an entry for the standard sequence */
- input_item_data *item = (input_item_data *)ui_menu_pool_alloc(menu, sizeof(*item));
- memset(item, 0, sizeof(*item));
- item->ref = entry;
- item->seqtype = seqtype;
- item->seq = input_type_seq(machine, entry->type, entry->player, seqtype);
- item->defseq = &entry->defseq[seqtype];
- item->sortorder = sortorder * 4 + suborder[seqtype];
- item->type = input_type_is_analog(entry->type) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
- item->name = entry->name;
- item->next = itemlist;
- itemlist = item;
-
- /* stop after one, unless we're analog */
- if (item->type == INPUT_TYPE_DIGITAL)
- break;
- }
- }
-
- /* sort and populate the menu in a standard fashion */
- menu_input_populate_and_sort(machine, menu, itemlist, menustate);
-}
-
-
-/*-------------------------------------------------
- menu_input_specific - handle the game-specific
- input menu
--------------------------------------------------*/
-
-static void menu_input_specific(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- menu_input_common(machine, menu, NULL, state);
-}
-
-
-/*-------------------------------------------------
- menu_input_specific_populate - populate
- the input menu with game-specific items
--------------------------------------------------*/
-
-static void menu_input_specific_populate(running_machine &machine, ui_menu *menu, input_menu_state *menustate)
-{
- input_item_data *itemlist = NULL;
- input_field_config *field;
- input_port_config *port;
- int suborder[SEQ_TYPE_TOTAL];
- astring tempstring;
-
- /* create a mini lookup table for sort order based on sequence type */
- suborder[SEQ_TYPE_STANDARD] = 0;
- suborder[SEQ_TYPE_DECREMENT] = 1;
- suborder[SEQ_TYPE_INCREMENT] = 2;
-
- /* iterate over the input ports and add menu items */
- for (port = machine.m_portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
- {
- const char *name = input_field_name(field);
-
- /* add if we match the group and we have a valid name */
- if (name != NULL && input_condition_true(machine, &field->condition, port->owner()) &&
- ((field->type == IPT_OTHER && field->name != NULL) || input_type_group(machine, field->type, field->player) != IPG_INVALID))
- {
- input_seq_type seqtype;
- UINT16 sortorder;
-
- /* determine the sorting order */
- if (field->type >= IPT_START1 && field->type <= __ipt_analog_end)
- sortorder = (field->type << 2) | (field->player << 12);
- else
- sortorder = field->type | 0xf000;
-
- /* loop over all sequence types */
- for (seqtype = SEQ_TYPE_STANDARD; seqtype < SEQ_TYPE_TOTAL; seqtype++)
- {
- /* build an entry for the standard sequence */
- input_item_data *item = (input_item_data *)ui_menu_pool_alloc(menu, sizeof(*item));
- memset(item, 0, sizeof(*item));
- item->ref = field;
- item->seqtype = seqtype;
- item->seq = input_field_seq(field, seqtype);
- item->defseq = &get_field_default_seq(field, seqtype);
- item->sortorder = sortorder + suborder[seqtype];
- item->type = input_type_is_analog(field->type) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL;
- item->name = name;
- item->next = itemlist;
- itemlist = item;
-
- /* stop after one, unless we're analog */
- if (item->type == INPUT_TYPE_DIGITAL)
- break;
- }
- }
- }
-
- /* sort and populate the menu in a standard fashion */
- menu_input_populate_and_sort(machine, menu, itemlist, menustate);
-}
-
+/***************************************************************************
+ UI SYSTEM INTERACTION
+***************************************************************************/
/*-------------------------------------------------
- menu_input - display a menu for inputs
+ ui_menu_ui_handler - displays the current menu
+ and calls the menu handler
-------------------------------------------------*/
-static void menu_input_common(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+UINT32 ui_menu::ui_handler(running_machine &machine, render_container *container, UINT32 state)
{
- input_item_data *seqchangeditem = NULL;
- input_menu_state *menustate;
- const ui_menu_event *menu_event;
- int invalidate = FALSE;
-
- /* if no state, allocate now */
- if (state == NULL)
- state = ui_menu_alloc_state(menu, sizeof(*menustate), NULL);
- menustate = (input_menu_state *)state;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- {
- if (parameter != NULL)
- menu_input_general_populate(machine, menu, menustate, (FPTR)parameter - 1);
- else
- menu_input_specific_populate(machine, menu, menustate);
- }
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, (menustate->pollingitem != NULL) ? UI_MENU_PROCESS_NOKEYS : 0);
-
- /* if we are polling, handle as a special case */
- if (menustate->pollingitem != NULL)
- {
- input_item_data *item = menustate->pollingitem;
- input_seq newseq;
-
- /* if UI_CANCEL is pressed, abort */
- if (ui_input_pressed(machine, IPT_UI_CANCEL))
- {
- menustate->pollingitem = NULL;
- menustate->record_next = FALSE;
- toggle_none_default(item->seq, menustate->starting_seq, *item->defseq);
- seqchangeditem = item;
- }
-
- /* poll again; if finished, update the sequence */
- if (machine.input().seq_poll())
- {
- menustate->pollingitem = NULL;
- menustate->record_next = TRUE;
- item->seq = machine.input().seq_poll_final();
- seqchangeditem = item;
- }
- }
-
- /* otherwise, handle the events */
- else if (menu_event != NULL && menu_event->itemref != NULL)
- {
- input_item_data *item = (input_item_data *)menu_event->itemref;
- switch (menu_event->iptkey)
- {
- /* an item was selected: begin polling */
- case IPT_UI_SELECT:
- menustate->pollingitem = item;
- menustate->last_sortorder = item->sortorder;
- menustate->starting_seq = item->seq;
- machine.input().seq_poll_start((item->type == INPUT_TYPE_ANALOG) ? ITEM_CLASS_ABSOLUTE : ITEM_CLASS_SWITCH, menustate->record_next ? &item->seq : NULL);
- invalidate = TRUE;
- break;
-
- /* if the clear key was pressed, reset the selected item */
- case IPT_UI_CLEAR:
- toggle_none_default(item->seq, item->seq, *item->defseq);
- menustate->record_next = FALSE;
- seqchangeditem = item;
- break;
- }
-
- /* if the selection changed, reset the "record next" flag */
- if (item->sortorder != menustate->last_sortorder)
- menustate->record_next = FALSE;
- menustate->last_sortorder = item->sortorder;
- }
-
- /* if the sequence changed, update it */
- if (seqchangeditem != NULL)
- {
- /* update a general input */
- if (parameter != NULL)
- {
- const input_type_entry *entry = (const input_type_entry *)seqchangeditem->ref;
- input_type_set_seq(machine, entry->type, entry->player, seqchangeditem->seqtype, &seqchangeditem->seq);
- }
-
- /* update a game-specific input */
- else
- {
- input_field_user_settings settings;
-
- input_field_get_user_settings((input_field_config *)seqchangeditem->ref, &settings);
- settings.seq[seqchangeditem->seqtype] = seqchangeditem->seq;
- input_field_set_user_settings((input_field_config *)seqchangeditem->ref, &settings);
- }
-
- /* invalidate the menu to force an update */
- invalidate = TRUE;
- }
+ /* if we have no menus stacked up, start with the main menu */
+ if (menu_stack == NULL)
+ stack_push(auto_alloc_clear(machine, ui_menu_main(machine, container)));
- /* if the menu is invalidated, clear it now */
- if (invalidate)
- {
- menustate->pollingref = NULL;
- if (menustate->pollingitem != NULL)
- menustate->pollingref = menustate->pollingitem->ref;
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
- }
-}
+ /* update the menu state */
+ if (menu_stack != NULL)
+ menu_stack->do_handle();
+ /* clear up anything pending to be released */
+ clear_free_list(machine);
-/*-------------------------------------------------
- menu_input_compare_items - compare two
- items for quicksort
--------------------------------------------------*/
+ /* if the menus are to be hidden, return a cancel here */
+ if ((ui_input_pressed(machine, IPT_UI_CONFIGURE) && !stack_has_special_main_menu()) || menu_stack == NULL)
+ return UI_HANDLER_CANCEL;
-static int menu_input_compare_items(const void *i1, const void *i2)
-{
- const input_item_data * const *data1 = (const input_item_data * const *)i1;
- const input_item_data * const *data2 = (const input_item_data * const *)i2;
- if ((*data1)->sortorder < (*data2)->sortorder)
- return -1;
- if ((*data1)->sortorder > (*data2)->sortorder)
- return 1;
return 0;
}
-
-/*-------------------------------------------------
- menu_input_populate_and_sort - take a list
- of input_item_data objects and build up the
- menu from them
--------------------------------------------------*/
-
-static void menu_input_populate_and_sort(running_machine &machine, ui_menu *menu, input_item_data *itemlist, input_menu_state *menustate)
-{
- const char *nameformat[INPUT_TYPE_TOTAL] = { 0 };
- input_item_data **itemarray, *item;
- int numitems = 0, curitem;
- astring subtext;
- astring text;
-
- /* create a mini lookup table for name format based on type */
- nameformat[INPUT_TYPE_DIGITAL] = "%s";
- nameformat[INPUT_TYPE_ANALOG] = "%s Analog";
- nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc";
- nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec";
-
- /* first count the number of items */
- for (item = itemlist; item != NULL; item = item->next)
- numitems++;
-
- /* now allocate an array of items and fill it up */
- itemarray = (input_item_data **)ui_menu_pool_alloc(menu, sizeof(*itemarray) * numitems);
- for (item = itemlist, curitem = 0; item != NULL; item = item->next)
- itemarray[curitem++] = item;
-
- /* sort it */
- qsort(itemarray, numitems, sizeof(*itemarray), menu_input_compare_items);
-
- /* build the menu */
- for (curitem = 0; curitem < numitems; curitem++)
- {
- UINT32 flags = 0;
-
- /* generate the name of the item itself, based off the base name and the type */
- item = itemarray[curitem];
- assert(nameformat[item->type] != NULL);
- text.printf(nameformat[item->type], item->name);
-
- /* if we're polling this item, use some spaces with left/right arrows */
- if (menustate->pollingref == item->ref)
- {
- subtext.cpy(" ");
- flags |= MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW;
- }
-
- /* otherwise, generate the sequence name and invert it if different from the default */
- else
- {
- machine.input().seq_name(subtext, item->seq);
- flags |= (item->seq != *item->defseq) ? MENU_FLAG_INVERT : 0;
- }
-
- /* add the item */
- ui_menu_item_append(menu, text, subtext, flags, item);
- }
-}
-
-
-/*-------------------------------------------------
- menu_settings_dip_switches - handle the DIP
- switches menu
--------------------------------------------------*/
-
-static void menu_settings_dip_switches(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- menu_settings_common(machine, menu, state, IPT_DIPSWITCH);
-}
-
-
-/*-------------------------------------------------
- menu_settings_driver_config - handle the
- driver config menu
--------------------------------------------------*/
-
-static void menu_settings_driver_config(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- menu_settings_common(machine, menu, state, IPT_CONFIG);
-}
-
-
-/*-------------------------------------------------
- menu_settings_common - handle one of the
- switches menus
--------------------------------------------------*/
-
-static void menu_settings_common(running_machine &machine, ui_menu *menu, void *state, UINT32 type)
-{
- settings_menu_state *menustate;
- const ui_menu_event *menu_event;
-
- /* if no state, allocate now */
- if (state == NULL)
- state = ui_menu_alloc_state(menu, sizeof(*menustate), NULL);
- menustate = (settings_menu_state *)state;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_settings_populate(machine, menu, menustate, type);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
-
- /* handle events */
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- input_field_config *field = (input_field_config *)menu_event->itemref;
- input_field_user_settings settings;
- int changed = FALSE;
-
- switch (menu_event->iptkey)
- {
- /* if selected, reset to default value */
- case IPT_UI_SELECT:
- input_field_get_user_settings(field, &settings);
- settings.value = field->defvalue;
- input_field_set_user_settings(field, &settings);
- changed = TRUE;
- break;
-
- /* left goes to previous setting */
- case IPT_UI_LEFT:
- input_field_select_previous_setting(field);
- changed = TRUE;
- break;
-
- /* right goes to next setting */
- case IPT_UI_RIGHT:
- input_field_select_next_setting(field);
- changed = TRUE;
- break;
- }
-
- /* if anything changed, rebuild the menu, trying to stay on the same field */
- if (changed)
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- }
-}
-
-
-/*-------------------------------------------------
- menu_settings_populate - populate one of the
- switches menus
--------------------------------------------------*/
-
-static void menu_settings_populate(running_machine &machine, ui_menu *menu, settings_menu_state *menustate, UINT32 type)
-{
- input_field_config *field;
- input_port_config *port;
- dip_descriptor **diplist_tailptr;
- int dipcount = 0;
-
- /* reset the dip switch tracking */
- menustate->diplist = NULL;
- diplist_tailptr = &menustate->diplist;
-
- /* loop over input ports and set up the current values */
- for (port = machine.m_portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
- if (field->type == type && input_condition_true(machine, &field->condition, port->owner()))
- {
- UINT32 flags = 0;
-
- /* set the left/right flags appropriately */
- if (input_field_has_previous_setting(field))
- flags |= MENU_FLAG_LEFT_ARROW;
- if (input_field_has_next_setting(field))
- flags |= MENU_FLAG_RIGHT_ARROW;
-
- /* add the menu item */
- ui_menu_item_append(menu, input_field_name(field), input_field_setting_name(field), flags, (void *)field);
-
- /* for DIP switches, build up the model */
- if (type == IPT_DIPSWITCH && field->diploclist().count() != 0)
- {
- const input_field_diplocation *diploc;
- input_field_user_settings settings;
- UINT32 accummask = field->mask;
-
- /* get current settings */
- input_field_get_user_settings(field, &settings);
-
- /* iterate over each bit in the field */
- for (diploc = field->diploclist().first(); diploc != NULL; diploc = diploc->next())
- {
- UINT32 mask = accummask & ~(accummask - 1);
- dip_descriptor *dip;
-
- /* find the matching switch name */
- for (dip = menustate->diplist; dip != NULL; dip = dip->next)
- if (strcmp(dip->name, diploc->swname) == 0)
- break;
-
- /* allocate new if none */
- if (dip == NULL)
- {
- dip = (dip_descriptor *)ui_menu_pool_alloc(menu, sizeof(*dip));
- dip->next = NULL;
- dip->name = diploc->swname;
- dip->mask = dip->state = 0;
- *diplist_tailptr = dip;
- diplist_tailptr = &dip->next;
- if (mame_stricmp(dip->name, "FAKE") != 0)
- dipcount++;
- }
-
- /* apply the bits */
- dip->mask |= 1 << (diploc->swnum - 1);
- if (((settings.value & mask) != 0 && !diploc->invert) || ((settings.value & mask) == 0 && diploc->invert))
- dip->state |= 1 << (diploc->swnum - 1);
-
- /* clear the relevant bit in the accumulated mask */
- accummask &= ~mask;
- }
- }
- }
-
- /* configure the extra menu */
- if (type == IPT_DIPSWITCH && menustate->diplist != NULL)
- ui_menu_set_custom_render(menu, menu_settings_custom_render, 0.0f, dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING);
-}
-
-
-/*-------------------------------------------------
- menu_settings_custom_render - perform our special
- rendering
--------------------------------------------------*/
-
-static void menu_settings_custom_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
-{
- input_field_config *field = (input_field_config *)selectedref;
- settings_menu_state *menustate = (settings_menu_state *)state;
- dip_descriptor *dip;
-
- /* add borders */
- y1 = y2 + UI_BOX_TB_BORDER;
- y2 = y1 + bottom;
-
- /* draw extra menu area */
- ui_draw_outlined_box(menu->container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
- y1 += (float)DIP_SWITCH_SPACING;
-
- /* iterate over DIP switches */
- for (dip = menustate->diplist; dip != NULL; dip = dip->next)
- {
- if (mame_stricmp(dip->name, "FAKE") != 0)
- {
- const input_field_diplocation *diploc;
- UINT32 selectedmask = 0;
-
- /* determine the mask of selected bits */
- if (field != NULL)
- for (diploc = field->diploclist().first(); diploc != NULL; diploc = diploc->next())
- if (strcmp(dip->name, diploc->swname) == 0)
- selectedmask |= 1 << (diploc->swnum - 1);
-
- /* draw one switch */
- menu_settings_custom_render_one(menu->container, x1, y1, x2, y1 + DIP_SWITCH_HEIGHT, dip, selectedmask);
- y1 += (float)(DIP_SWITCH_SPACING + DIP_SWITCH_HEIGHT);
- }
- }
-}
-
-
-/*-------------------------------------------------
- menu_settings_custom_render_one - draw a single
- DIP switch
--------------------------------------------------*/
-
-static void menu_settings_custom_render_one(render_container *container, float x1, float y1, float x2, float y2, const dip_descriptor *dip, UINT32 selectedmask)
-{
- float switch_field_width = SINGLE_TOGGLE_SWITCH_FIELD_WIDTH * container->manager().ui_aspect();
- float switch_width = SINGLE_TOGGLE_SWITCH_WIDTH * container->manager().ui_aspect();
- int numtoggles, toggle;
- float switch_toggle_gap;
- float y1_off, y1_on;
-
- /* determine the number of toggles in the DIP */
- numtoggles = 32 - count_leading_zeros(dip->mask);
-
- /* center based on the number of switches */
- x1 += (x2 - x1 - numtoggles * switch_field_width) / 2;
-
- /* draw the dip switch name */
- ui_draw_text_full( container,
- dip->name,
- 0,
- y1 + (DIP_SWITCH_HEIGHT - UI_TARGET_FONT_HEIGHT) / 2,
- x1 - ui_get_string_width(container->manager().machine(), " "),
- JUSTIFY_RIGHT,
- WRAP_NEVER,
- DRAW_NORMAL,
- UI_TEXT_COLOR,
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA),
- NULL ,
- NULL);
-
- /* compute top and bottom for on and off positions */
- switch_toggle_gap = ((DIP_SWITCH_HEIGHT/2) - SINGLE_TOGGLE_SWITCH_HEIGHT)/2;
- y1_off = y1 + UI_LINE_WIDTH + switch_toggle_gap;
- y1_on = y1 + DIP_SWITCH_HEIGHT/2 + switch_toggle_gap;
-
- /* iterate over toggles */
- for (toggle = 0; toggle < numtoggles; toggle++)
- {
- float innerx1;
-
- /* first outline the switch */
- ui_draw_outlined_box(container, x1, y1, x1 + switch_field_width, y2, UI_BACKGROUND_COLOR);
-
- /* compute x1/x2 for the inner filled in switch */
- innerx1 = x1 + (switch_field_width - switch_width) / 2;
-
- /* see if the switch is actually used */
- if (dip->mask & (1 << toggle))
- {
- float innery1 = (dip->state & (1 << toggle)) ? y1_on : y1_off;
- container->add_rect(innerx1, innery1, innerx1 + switch_width, innery1 + SINGLE_TOGGLE_SWITCH_HEIGHT,
- (selectedmask & (1 << toggle)) ? UI_DIPSW_COLOR : UI_TEXT_COLOR,
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- }
- else
- {
- container->add_rect(innerx1, y1_off, innerx1 + switch_width, y1_on + SINGLE_TOGGLE_SWITCH_HEIGHT,
- UI_UNAVAILABLE_COLOR,
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- }
-
- /* advance to the next switch */
- x1 += switch_field_width;
- }
-}
-
-
-/*-------------------------------------------------
- menu_analog - handle the analog settings menu
--------------------------------------------------*/
-
-static void menu_analog(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- const ui_menu_event *menu_event;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_analog_populate(machine, menu);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
-
- /* handle events */
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- analog_item_data *data = (analog_item_data *)menu_event->itemref;
- int newval = data->cur;
-
- switch (menu_event->iptkey)
- {
- /* if selected, reset to default value */
- case IPT_UI_SELECT:
- newval = data->defvalue;
- break;
-
- /* left decrements */
- case IPT_UI_LEFT:
- newval -= machine.input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
-
- /* right increments */
- case IPT_UI_RIGHT:
- newval += machine.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)
- {
- input_field_user_settings settings;
-
- /* get the settings and set the new value */
- input_field_get_user_settings(data->field, &settings);
- switch (data->type)
- {
- case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break;
- case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break;
- case ANALOG_ITEM_REVERSE: settings.reverse = newval; break;
- case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break;
- }
- input_field_set_user_settings(data->field, &settings);
-
- /* rebuild the menu */
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_POSITION);
- }
- }
-}
-
-
-/*-------------------------------------------------
- menu_analog_populate - populate the analog
- settings menu
--------------------------------------------------*/
-
-static void menu_analog_populate(running_machine &machine, ui_menu *menu)
-{
- input_field_config *field;
- input_port_config *port;
- astring subtext;
- astring text;
-
- /* loop over input ports and add the items */
- for (port = machine.m_portlist.first(); port != NULL; port = port->next())
- for (field = port->fieldlist().first(); field != NULL; field = field->next())
- if (input_type_is_analog(field->type) && input_condition_true(machine, &field->condition, port->owner()))
- {
- input_field_user_settings settings;
- int use_autocenter = FALSE;
- int type;
-
- /* based on the type, determine if we enable autocenter */
- switch (field->type)
- {
- case IPT_POSITIONAL:
- case IPT_POSITIONAL_V:
- if (field->flags & ANALOG_FLAG_WRAPS)
- break;
-
- case IPT_AD_STICK_X:
- case IPT_AD_STICK_Y:
- case IPT_AD_STICK_Z:
- case IPT_PADDLE:
- case IPT_PADDLE_V:
- case IPT_PEDAL:
- case IPT_PEDAL2:
- case IPT_PEDAL3:
- use_autocenter = TRUE;
- break;
- }
-
- /* get the user settings */
- input_field_get_user_settings(field, &settings);
-
- /* iterate over types */
- for (type = 0; type < ANALOG_ITEM_COUNT; type++)
- if (type != ANALOG_ITEM_CENTERSPEED || use_autocenter)
- {
- analog_item_data *data;
- UINT32 flags = 0;
-
- /* allocate a data item for tracking what this menu item refers to */
- data = (analog_item_data *)ui_menu_pool_alloc(menu, sizeof(*data));
- data->field = field;
- data->type = type;
-
- /* determine the properties of this item */
- switch (type)
- {
- default:
- case ANALOG_ITEM_KEYSPEED:
- text.printf("%s Digital Speed", input_field_name(field));
- subtext.printf("%d", settings.delta);
- data->min = 0;
- data->max = 255;
- data->cur = settings.delta;
- data->defvalue = field->delta;
- break;
-
- case ANALOG_ITEM_CENTERSPEED:
- text.printf("%s Autocenter Speed", input_field_name(field));
- subtext.printf("%d", settings.centerdelta);
- data->min = 0;
- data->max = 255;
- data->cur = settings.centerdelta;
- data->defvalue = field->centerdelta;
- break;
-
- case ANALOG_ITEM_REVERSE:
- text.printf("%s Reverse", input_field_name(field));
- subtext.cpy(settings.reverse ? "On" : "Off");
- data->min = 0;
- data->max = 1;
- data->cur = settings.reverse;
- data->defvalue = ((field->flags & ANALOG_FLAG_REVERSE) != 0);
- break;
-
- case ANALOG_ITEM_SENSITIVITY:
- text.printf("%s Sensitivity", input_field_name(field));
- subtext.printf("%d", settings.sensitivity);
- data->min = 1;
- data->max = 255;
- data->cur = settings.sensitivity;
- data->defvalue = field->sensitivity;
- break;
- }
-
- /* put on arrows */
- if (data->cur > data->min)
- flags |= MENU_FLAG_LEFT_ARROW;
- if (data->cur < data->max)
- flags |= MENU_FLAG_RIGHT_ARROW;
-
- /* append a menu item */
- ui_menu_item_append(menu, text, subtext, flags, data);
- }
- }
-}
-
-
-/*-------------------------------------------------
- menu_bookkeeping - handle the bookkeeping
- information menu
--------------------------------------------------*/
-
-static void menu_bookkeeping(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- attotime *prevtime;
- attotime curtime;
-
- /* if no state, allocate some */
- if (state == NULL)
- state = ui_menu_alloc_state(menu, sizeof(*prevtime), NULL);
- prevtime = (attotime *)state;
-
- /* if the time has rolled over another second, regenerate */
- curtime = machine.time();
- if (prevtime->seconds != curtime.seconds)
- {
- ui_menu_reset(menu, UI_MENU_RESET_SELECT_FIRST);
- *prevtime = curtime;
- menu_bookkeeping_populate(machine, menu, prevtime);
- }
-
- /* process the menu */
- ui_menu_process(machine, menu, 0);
-}
-
-
-/*-------------------------------------------------
- menu_bookkeeping - handle the bookkeeping
- information menu
--------------------------------------------------*/
-
-static void menu_bookkeeping_populate(running_machine &machine, ui_menu *menu, attotime *curtime)
-{
- int tickets = get_dispensed_tickets(machine);
- astring tempstring;
- int ctrnum;
-
- /* show total time first */
- if (curtime->seconds >= 60 * 60)
- tempstring.catprintf("Uptime: %d:%02d:%02d\n\n", curtime->seconds / (60*60), (curtime->seconds / 60) % 60, curtime->seconds % 60);
- else
- tempstring.catprintf("Uptime: %d:%02d\n\n", (curtime->seconds / 60) % 60, curtime->seconds % 60);
-
- /* show tickets at the top */
- if (tickets > 0)
- tempstring.catprintf("Tickets dispensed: %d\n\n", tickets);
-
- /* loop over coin counters */
- for (ctrnum = 0; ctrnum < COIN_COUNTERS; ctrnum++)
- {
- int count = coin_counter_get_count(machine, ctrnum);
-
- /* display the coin counter number */
- tempstring.catprintf("Coin %c: ", ctrnum + 'A');
-
- /* display how many coins */
- if (count == 0)
- tempstring.cat("NA");
- else
- tempstring.catprintf("%d", count);
-
- /* display whether or not we are locked out */
- if (coin_lockout_get_state(machine, ctrnum))
- tempstring.cat(" (locked)");
- tempstring.cat("\n");
- }
-
- /* append the single item */
- ui_menu_item_append(menu, tempstring, NULL, MENU_FLAG_MULTILINE, NULL);
-}
-
-
-/*-------------------------------------------------
- menu_game_info - handle the game information
- menu
--------------------------------------------------*/
-
-static void menu_game_info(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- {
- astring tempstring;
- ui_menu_item_append(menu, game_info_astring(machine, tempstring), NULL, MENU_FLAG_MULTILINE, NULL);
- }
-
- /* process the menu */
- ui_menu_process(machine, menu, 0);
-}
-
-
-/*-------------------------------------------------
- menu_cheat - handle the cheat menu
--------------------------------------------------*/
-
-static void menu_cheat(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- const ui_menu_event *menu_event;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_cheat_populate(machine, menu);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
-
- /* handle events */
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- bool changed = false;
-
- /* clear cheat comment on any movement or keypress */
- popmessage(NULL);
-
- /* handle reset all + reset all cheats for reload all option */
- if ((FPTR)menu_event->itemref < 3 && menu_event->iptkey == IPT_UI_SELECT)
- {
- for (cheat_entry *curcheat = machine.cheat().first(); curcheat != NULL; curcheat = curcheat->next())
- if (curcheat->select_default_state())
- changed = true;
- }
-
-
- /* handle individual cheats */
- else if ((FPTR)menu_event->itemref > 2)
- {
- cheat_entry *curcheat = reinterpret_cast<cheat_entry *>(menu_event->itemref);
- const char *string;
- switch (menu_event->iptkey)
- {
- /* if selected, activate a oneshot */
- case IPT_UI_SELECT:
- changed = curcheat->activate();
- break;
-
- /* if cleared, reset to default value */
- case IPT_UI_CLEAR:
- changed = curcheat->select_default_state();
- break;
-
- /* left decrements */
- case IPT_UI_LEFT:
- changed = curcheat->select_previous_state();
- break;
-
- /* right increments */
- case IPT_UI_RIGHT:
- changed = curcheat->select_next_state();
- break;
-
- /* bring up display comment if one exists */
- case IPT_UI_DISPLAY_COMMENT:
- case IPT_UI_UP:
- case IPT_UI_DOWN:
- string = curcheat->comment();
- if (string != NULL && string[0] != 0)
- popmessage("Cheat Comment:\n%s", string);
- break;
- }
- }
-
- /* handle reload all */
- if ((FPTR)menu_event->itemref == 2 && menu_event->iptkey == IPT_UI_SELECT)
- {
- /* re-init cheat engine and thus reload cheats/cheats have already been turned off by here */
- machine.cheat().reload();
-
- /* display the reloaded cheats */
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- popmessage("All cheats reloaded");
- }
-
- /* if things changed, update */
- if (changed)
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- }
-}
-
-
-/*-------------------------------------------------
- menu_cheat_populate - populate the cheat menu
--------------------------------------------------*/
-
-static void menu_cheat_populate(running_machine &machine, ui_menu *menu)
-{
- /* iterate over cheats */
- astring text;
- astring subtext;
- for (cheat_entry *curcheat = machine.cheat().first(); curcheat != NULL; curcheat = curcheat->next())
- {
- UINT32 flags;
- curcheat->menu_text(text, subtext, flags);
- ui_menu_item_append(menu, text, subtext, flags, curcheat);
- }
-
- /* add a separator */
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
-
- /* add a reset all option */
- ui_menu_item_append(menu, "Reset All", NULL, 0, (void *)1);
-
- /* add a reload all cheats option */
- ui_menu_item_append(menu, "Reload All", NULL, 0, (void *)2);
-}
-
-
-/*-------------------------------------------------
- menu_memory_card - handle the memory card
- menu
--------------------------------------------------*/
-
-static void menu_memory_card(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- const ui_menu_event *menu_event;
- int *cardnum;
-
- /* if no state, allocate some */
- if (state == NULL)
- state = ui_menu_alloc_state(menu, sizeof(*cardnum), NULL);
- cardnum = (int *)state;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_memory_card_populate(machine, menu, *cardnum);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
-
- /* if something was selected, act on it */
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- FPTR item = (FPTR)menu_event->itemref;
-
- /* select executes actions on some of the items */
- if (menu_event->iptkey == IPT_UI_SELECT)
- {
- switch (item)
- {
- /* handle card loading; if we succeed, clear the menus */
- case MEMCARD_ITEM_LOAD:
- if (memcard_insert(menu->machine(), *cardnum) == 0)
- {
- popmessage("Memory card loaded");
- ui_menu_stack_reset(menu->machine());
- }
- else
- popmessage("Error loading memory card");
- break;
-
- /* handle card ejecting */
- case MEMCARD_ITEM_EJECT:
- memcard_eject(menu->machine());
- popmessage("Memory card ejected");
- break;
-
- /* handle card creating */
- case MEMCARD_ITEM_CREATE:
- if (memcard_create(menu->machine(), *cardnum, FALSE) == 0)
- popmessage("Memory card created");
- else
- popmessage("Error creating memory card\n(Card may already exist)");
- break;
- }
- }
-
- /* the select item has extra keys */
- else if (item == MEMCARD_ITEM_SELECT)
- {
- switch (menu_event->iptkey)
- {
- /* left decrements the card number */
- case IPT_UI_LEFT:
- *cardnum -= 1;
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- break;
-
- /* right decrements the card number */
- case IPT_UI_RIGHT:
- *cardnum += 1;
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- break;
- }
- }
- }
-}
-
-
-/*-------------------------------------------------
- menu_memory_card_populate - populate the
- memory card menu
--------------------------------------------------*/
-
-static void menu_memory_card_populate(running_machine &machine, ui_menu *menu, int cardnum)
-{
- char tempstring[20];
- UINT32 flags = 0;
-
- /* add the card select menu */
- sprintf(tempstring, "%d", cardnum);
- if (cardnum > 0)
- flags |= MENU_FLAG_LEFT_ARROW;
- if (cardnum < 1000)
- flags |= MENU_FLAG_RIGHT_ARROW;
- ui_menu_item_append(menu, "Card Number:", tempstring, flags, (void *)MEMCARD_ITEM_SELECT);
-
- /* add the remaining items */
- ui_menu_item_append(menu, "Load Selected Card", NULL, 0, (void *)MEMCARD_ITEM_LOAD);
- if (memcard_present(machine) != -1)
- ui_menu_item_append(menu, "Eject Current Card", NULL, 0, (void *)MEMCARD_ITEM_EJECT);
- ui_menu_item_append(menu, "Create New Card", NULL, 0, (void *)MEMCARD_ITEM_CREATE);
-}
-
-
-/*-------------------------------------------------
- menu_sliders - handle the sliders menu
--------------------------------------------------*/
-
-static void menu_sliders(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- int menuless_mode = (parameter != NULL);
- const ui_menu_event *menu_event;
- UINT8 *hidden = (UINT8 *)state;
-
- /* if no state, allocate some */
- if (hidden == NULL)
- hidden = (UINT8 *)ui_menu_alloc_state(menu, sizeof(*hidden), NULL);
- if (menuless_mode)
- *hidden = TRUE;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_sliders_populate(machine, menu, menuless_mode);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT | (*hidden ? UI_MENU_PROCESS_CUSTOM_ONLY : 0));
- if (menu_event != NULL)
- {
- /* handle keys if there is a valid item selected */
- if (menu_event->itemref != NULL)
- {
- const slider_state *slider = (const slider_state *)menu_event->itemref;
- INT32 curvalue = (*slider->update)(machine, slider->arg, NULL, SLIDER_NOCHANGE);
- INT32 increment = 0;
-
- switch (menu_event->iptkey)
- {
- /* toggle visibility */
- case IPT_UI_ON_SCREEN_DISPLAY:
- if (menuless_mode)
- ui_menu_stack_pop(machine);
- else
- *hidden = !*hidden;
- break;
-
- /* decrease value */
- case IPT_UI_LEFT:
- if (machine.input().code_pressed(KEYCODE_LALT) || machine.input().code_pressed(KEYCODE_RALT))
- increment = -1;
- else if (machine.input().code_pressed(KEYCODE_LSHIFT) || machine.input().code_pressed(KEYCODE_RSHIFT))
- increment = (slider->incval > 10) ? -(slider->incval / 10) : -1;
- else if (machine.input().code_pressed(KEYCODE_LCONTROL) || machine.input().code_pressed(KEYCODE_RCONTROL))
- increment = -slider->incval * 10;
- else
- increment = -slider->incval;
- break;
-
- /* increase value */
- case IPT_UI_RIGHT:
- if (machine.input().code_pressed(KEYCODE_LALT) || machine.input().code_pressed(KEYCODE_RALT))
- increment = 1;
- else if (machine.input().code_pressed(KEYCODE_LSHIFT) || machine.input().code_pressed(KEYCODE_RSHIFT))
- increment = (slider->incval > 10) ? (slider->incval / 10) : 1;
- else if (machine.input().code_pressed(KEYCODE_LCONTROL) || machine.input().code_pressed(KEYCODE_RCONTROL))
- increment = slider->incval * 10;
- else
- increment = slider->incval;
- break;
-
- /* restore default */
- case IPT_UI_SELECT:
- increment = slider->defval - curvalue;
- break;
- }
-
- /* handle any changes */
- if (increment != 0)
- {
- INT32 newvalue = curvalue + increment;
-
- /* clamp within bounds */
- if (newvalue < slider->minval)
- newvalue = slider->minval;
- if (newvalue > slider->maxval)
- newvalue = slider->maxval;
-
- /* update the slider and recompute the menu */
- (*slider->update)(machine, slider->arg, NULL, newvalue);
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- }
- }
-
- /* if we are selecting an invalid item and we are hidden, skip to the next one */
- else if (*hidden)
- {
- /* if we got here via up or page up, select the previous item */
- if (menu_event->iptkey == IPT_UI_UP || menu_event->iptkey == IPT_UI_PAGE_UP)
- {
- menu->selected = (menu->selected + menu->numitems - 1) % menu->numitems;
- ui_menu_validate_selection(menu, -1);
- }
-
- /* otherwise select the next item */
- else if (menu_event->iptkey == IPT_UI_DOWN || menu_event->iptkey == IPT_UI_PAGE_DOWN)
- {
- menu->selected = (menu->selected + 1) % menu->numitems;
- ui_menu_validate_selection(menu, 1);
- }
- }
- }
-}
-
-
-/*-------------------------------------------------
- menu_sliders_populate - populate the sliders
- menu
--------------------------------------------------*/
-
-static void menu_sliders_populate(running_machine &machine, ui_menu *menu, int menuless_mode)
-{
- const slider_state *curslider;
- astring tempstring;
-
- /* add all sliders */
- for (curslider = ui_get_slider_list(); curslider != NULL; curslider = curslider->next)
- {
- INT32 curval = (*curslider->update)(machine, curslider->arg, &tempstring, SLIDER_NOCHANGE);
- UINT32 flags = 0;
- if (curval > curslider->minval)
- flags |= MENU_FLAG_LEFT_ARROW;
- if (curval < curslider->maxval)
- flags |= MENU_FLAG_RIGHT_ARROW;
- ui_menu_item_append(menu, curslider->description, tempstring, flags, (void *)curslider);
-
- if (menuless_mode)
- break;
- }
-
- /* add all sliders */
- for (curslider = (slider_state*)machine.osd().get_slider_list(); curslider != NULL; curslider = curslider->next)
- {
- INT32 curval = (*curslider->update)(machine, curslider->arg, &tempstring, SLIDER_NOCHANGE);
- UINT32 flags = 0;
- if (curval > curslider->minval)
- flags |= MENU_FLAG_LEFT_ARROW;
- if (curval < curslider->maxval)
- flags |= MENU_FLAG_RIGHT_ARROW;
- ui_menu_item_append(menu, curslider->description, tempstring, flags, (void *)curslider);
- }
-
- ui_menu_set_custom_render(menu, menu_sliders_custom_render, 0.0f, 2.0f * ui_get_line_height(machine) + 2.0f * UI_BOX_TB_BORDER);
-}
-
-
-/*-------------------------------------------------
- menu_sliders_custom_render - perform our special
- rendering
--------------------------------------------------*/
-
-static void menu_sliders_custom_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2)
-{
- const slider_state *curslider = (const slider_state *)selectedref;
- if (curslider != NULL)
- {
- float bar_left, bar_area_top, bar_width, bar_area_height, bar_top, bar_bottom, default_x, current_x;
- float line_height = ui_get_line_height(machine);
- float percentage, default_percentage;
- astring tempstring;
- float text_height;
- INT32 curval;
-
- /* determine the current value and text */
- curval = (*curslider->update)(machine, curslider->arg, &tempstring, SLIDER_NOCHANGE);
-
- /* compute the current and default percentages */
- percentage = (float)(curval - curslider->minval) / (float)(curslider->maxval - curslider->minval);
- default_percentage = (float)(curslider->defval - curslider->minval) / (float)(curslider->maxval - curslider->minval);
-
- /* assemble the the text */
- tempstring.ins(0, " ").ins(0, curslider->description);
-
- /* move us to the bottom of the screen, and expand to full width */
- y2 = 1.0f - UI_BOX_TB_BORDER;
- y1 = y2 - bottom;
- x1 = UI_BOX_LR_BORDER;
- x2 = 1.0f - UI_BOX_LR_BORDER;
-
- /* draw extra menu area */
- ui_draw_outlined_box(menu->container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
- y1 += UI_BOX_TB_BORDER;
-
- /* determine the text height */
- ui_draw_text_full(menu->container, tempstring, 0, 0, x2 - x1 - 2.0f * UI_BOX_LR_BORDER,
- JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, NULL, &text_height);
-
- /* draw the thermometer */
- bar_left = x1 + UI_BOX_LR_BORDER;
- bar_area_top = y1;
- bar_width = x2 - x1 - 2.0f * UI_BOX_LR_BORDER;
- bar_area_height = line_height;
-
- /* compute positions */
- bar_top = bar_area_top + 0.125f * bar_area_height;
- bar_bottom = bar_area_top + 0.875f * bar_area_height;
- default_x = bar_left + bar_width * default_percentage;
- current_x = bar_left + bar_width * percentage;
-
- /* fill in the percentage */
- menu->container->add_rect(bar_left, bar_top, current_x, bar_bottom, UI_SLIDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- /* draw the top and bottom lines */
- menu->container->add_line(bar_left, bar_top, bar_left + bar_width, bar_top, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- menu->container->add_line(bar_left, bar_bottom, bar_left + bar_width, bar_bottom, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- /* draw default marker */
- menu->container->add_line(default_x, bar_area_top, default_x, bar_top, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- menu->container->add_line(default_x, bar_bottom, default_x, bar_area_top + bar_area_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
-
- /* draw the actual text */
- ui_draw_text_full(menu->container, tempstring, x1 + UI_BOX_LR_BORDER, y1 + line_height, x2 - x1 - 2.0f * UI_BOX_LR_BORDER,
- JUSTIFY_CENTER, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, &text_height);
- }
-}
-
-
-/*-------------------------------------------------
- menu_video_targets - handle the video targets
- menu
--------------------------------------------------*/
-
-static void menu_video_targets(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- const ui_menu_event *menu_event;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_video_targets_populate(machine, menu);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
- if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT)
- ui_menu_stack_push(ui_menu_alloc(machine, menu->container, menu_video_options, menu_event->itemref));
-}
-
-
-/*-------------------------------------------------
- menu_video_targets_populate - populate the
- video targets menu
--------------------------------------------------*/
-
-static void menu_video_targets_populate(running_machine &machine, ui_menu *menu)
-{
- int targetnum;
-
- /* find the targets */
- for (targetnum = 0; ; targetnum++)
- {
- render_target *target = machine.render().target_by_index(targetnum);
- char buffer[40];
-
- /* stop when we run out */
- if (target == NULL)
- break;
-
- /* add a menu item */
- sprintf(buffer, "Screen #%d", targetnum);
- ui_menu_item_append(menu, buffer, NULL, 0, target);
- }
-}
-
-
-/*-------------------------------------------------
- menu_video_options - handle the video options
- menu
--------------------------------------------------*/
-
-static void menu_video_options(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- render_target *target = (parameter != NULL) ? (render_target *)parameter : machine.render().first_target();
- const ui_menu_event *menu_event;
- int changed = FALSE;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_video_options_populate(machine, menu, target);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- switch ((FPTR)menu_event->itemref)
- {
- /* rotate adds rotation depending on the direction */
- case VIDEO_ITEM_ROTATE:
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
- {
- int delta = (menu_event->iptkey == IPT_UI_LEFT) ? ROT270 : ROT90;
- target->set_orientation(orientation_add(delta, target->orientation()));
- if (target->is_ui_target())
- {
- render_container::user_settings settings;
- menu->container->get_user_settings(settings);
- settings.m_orientation = orientation_add(delta ^ ROT180, settings.m_orientation);
- menu->container->set_user_settings(settings);
- }
- changed = TRUE;
- }
- break;
-
- /* layer config bitmasks handle left/right keys the same (toggle) */
- case VIDEO_ITEM_BACKDROPS:
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
- {
- target->set_backdrops_enabled(!target->backdrops_enabled());
- changed = TRUE;
- }
- break;
-
- case VIDEO_ITEM_OVERLAYS:
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
- {
- target->set_overlays_enabled(!target->overlays_enabled());
- changed = TRUE;
- }
- break;
-
- case VIDEO_ITEM_BEZELS:
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
- {
- target->set_bezels_enabled(!target->bezels_enabled());
- changed = TRUE;
- }
- break;
-
- case VIDEO_ITEM_CPANELS:
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
- {
- target->set_cpanels_enabled(!target->cpanels_enabled());
- changed = TRUE;
- }
- break;
-
- case VIDEO_ITEM_MARQUEES:
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
- {
- target->set_marquees_enabled(!target->marquees_enabled());
- changed = TRUE;
- }
- break;
-
- case VIDEO_ITEM_ZOOM:
- if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
- {
- target->set_zoom_to_screen(!target->zoom_to_screen());
- changed = TRUE;
- }
- break;
-
- /* anything else is a view item */
- default:
- if (menu_event->iptkey == IPT_UI_SELECT && (int)(FPTR)menu_event->itemref >= VIDEO_ITEM_VIEW)
- {
- target->set_view((FPTR)menu_event->itemref - VIDEO_ITEM_VIEW);
- changed = TRUE;
- }
- break;
- }
- }
-
- /* if something changed, rebuild the menu */
- if (changed)
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
-}
-
-
-/*-------------------------------------------------
- menu_video_options_populate - populate the
- video options menu
--------------------------------------------------*/
-
-static void menu_video_options_populate(running_machine &machine, ui_menu *menu, render_target *target)
-{
- const char *subtext = "";
- astring tempstring;
- int viewnum;
- int enabled;
-
- /* add items for each view */
- for (viewnum = 0; ; viewnum++)
- {
- const char *name = target->view_name(viewnum);
- if (name == NULL)
- break;
-
- /* create a string for the item, replacing underscores with spaces */
- tempstring.cpy(name).replace(0, "_", " ");
- ui_menu_item_append(menu, tempstring, NULL, 0, (void *)(FPTR)(VIDEO_ITEM_VIEW + viewnum));
- }
-
- /* add a separator */
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
-
- /* add a rotate item */
- switch (target->orientation())
- {
- case ROT0: subtext = "None"; break;
- case ROT90: subtext = "CW 90" UTF8_DEGREES; break;
- case ROT180: subtext = "180" UTF8_DEGREES; break;
- case ROT270: subtext = "CCW 90" UTF8_DEGREES; break;
- }
- ui_menu_item_append(menu, "Rotate", subtext, MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_ROTATE);
-
- /* backdrop item */
- enabled = target->backdrops_enabled();
- ui_menu_item_append(menu, "Backdrops", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_BACKDROPS);
-
- /* overlay item */
- enabled = target->overlays_enabled();
- ui_menu_item_append(menu, "Overlays", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_OVERLAYS);
-
- /* bezel item */
- enabled = target->bezels_enabled();
- ui_menu_item_append(menu, "Bezels", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_BEZELS);
-
- /* cpanel item */
- enabled = target->cpanels_enabled();
- ui_menu_item_append(menu, "CPanels", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_CPANELS);
-
- /* marquee item */
- enabled = target->marquees_enabled();
- ui_menu_item_append(menu, "Marquees", enabled ? "Enabled" : "Disabled", enabled ? MENU_FLAG_LEFT_ARROW : MENU_FLAG_RIGHT_ARROW, (void *)VIDEO_ITEM_MARQUEES);
-
- /* cropping */
- enabled = target->zoom_to_screen();
- ui_menu_item_append(menu, "View", enabled ? "Cropped" : "Full", enabled ? MENU_FLAG_RIGHT_ARROW : MENU_FLAG_LEFT_ARROW, (void *)VIDEO_ITEM_ZOOM);
-}
-
-
-/*-------------------------------------------------
- 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 *menu_event;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_crosshair_populate(machine, menu);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, UI_MENU_PROCESS_LR_REPEAT);
-
- /* handle events */
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- crosshair_user_settings settings;
- crosshair_item_data *data = (crosshair_item_data *)menu_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 (menu_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 -= machine.input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1;
- break;
-
- /* right increments */
- case IPT_UI_RIGHT:
- newval += machine.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 (menu_event->iptkey == IPT_UI_SELECT)
- {
- /* clear the name string to reset to default crosshair */
- settings.name[0] = 0;
- changed = TRUE;
- }
- else if (menu_event->iptkey == IPT_UI_LEFT)
- {
- strcpy(settings.name, data->last_name);
- changed = TRUE;
- }
- else if (menu_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;
-
- /* 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 = (crosshair_item_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 = (crosshair_item_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 */
- file_enumerator path(machine.options().crosshair_path());
- 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 = path.next()) != 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) &&
- dir->name[length - 4] == '.' &&
- tolower((UINT8)dir->name[length - 3]) == 'p' &&
- tolower((UINT8)dir->name[length - 2]) == 'n' &&
- tolower((UINT8)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 = (crosshair_item_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
--------------------------------------------------*/
-
-static void menu_quit_game(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- /* request a reset */
- machine.schedule_exit();
-
- /* reset the menu stack */
- ui_menu_stack_reset(machine);
-}
-
-
-/*-------------------------------------------------
- menu_select_game - handle the game select
- menu
--------------------------------------------------*/
-
-static void menu_select_game(running_machine &machine, ui_menu *menu, void *parameter, void *state)
-{
- select_game_state *menustate;
- const ui_menu_event *menu_event;
-
- /* if no state, allocate some */
- if (state == NULL)
- {
- state = ui_menu_alloc_state(menu, sizeof(*menustate) + sizeof(menustate->driverlist) * driver_list::total(), NULL);
- if (parameter != NULL)
- strcpy(((select_game_state *)state)->search, (const char *)parameter);
- ((select_game_state *)state)->matchlist[0] = -1;
- }
- menustate = (select_game_state *)state;
-
- /* if the menu isn't built, populate now */
- if (!ui_menu_populated(menu))
- menu_select_game_populate(machine, menu, menustate);
-
- /* ignore pause keys by swallowing them before we process the menu */
- ui_input_pressed(machine, IPT_UI_PAUSE);
-
- /* process the menu */
- menu_event = ui_menu_process(machine, menu, 0);
- if (menu_event != NULL && menu_event->itemref != NULL)
- {
- /* reset the error on any future menu_event */
- if (menustate->error)
- menustate->error = FALSE;
-
- /* handle selections */
- else if (menu_event->iptkey == IPT_UI_SELECT)
- {
- const game_driver *driver = (const game_driver *)menu_event->itemref;
-
- /* special case for configure inputs */
- if ((FPTR)driver == 1)
- ui_menu_stack_push(ui_menu_alloc(menu->machine(), menu->container, menu_input_groups, NULL));
-
- /* anything else is a driver */
- else
- {
- // audit the game first to see if we're going to work
- driver_enumerator enumerator(machine.options(), *driver);
- enumerator.next();
- media_auditor auditor(enumerator);
- media_auditor::summary summary = auditor.audit_media(AUDIT_VALIDATE_FAST);
-
- // if everything looks good, schedule the new driver
- if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE)
- {
- machine.schedule_new_driver(*driver);
- ui_menu_stack_reset(machine);
- }
-
- // otherwise, display an error
- else
- {
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- menustate->error = TRUE;
- }
- }
- }
-
- /* escape pressed with non-empty text clears the text */
- else if (menu_event->iptkey == IPT_UI_CANCEL && menustate->search[0] != 0)
- {
- /* since we have already been popped, we must recreate ourself from scratch */
- ui_menu_stack_push(ui_menu_alloc(menu->machine(), menu->container, menu_select_game, NULL));
- }
-
- /* typed characters append to the buffer */
- else if (menu_event->iptkey == IPT_SPECIAL)
- {
- int buflen = strlen(menustate->search);
-
- /* if it's a backspace and we can handle it, do so */
- if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
- {
- *(char *)utf8_previous_char(&menustate->search[buflen]) = 0;
- menustate->rerandomize = TRUE;
- ui_menu_reset(menu, UI_MENU_RESET_SELECT_FIRST);
- }
-
- /* if it's any other key and we're not maxed out, update */
- else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
- {
- buflen += utf8_from_uchar(&menustate->search[buflen], ARRAY_LENGTH(menustate->search) - buflen, menu_event->unichar);
- menustate->search[buflen] = 0;
- ui_menu_reset(menu, UI_MENU_RESET_SELECT_FIRST);
- }
- }
- }
-
- /* if we're in an error state, overlay an error message */
- if (menustate->error)
- ui_draw_text_box(menu->container,
- "The selected game is missing one or more required ROM or CHD images. "
- "Please select a different game.\n\nPress any key to continue.",
- JUSTIFY_CENTER, 0.5f, 0.5f, UI_RED_COLOR);
-}
-
-
-/*-------------------------------------------------
- menu_select_game_populate - populate the game
- select menu
--------------------------------------------------*/
-
-static void menu_select_game_populate(running_machine &machine, ui_menu *menu, select_game_state *menustate)
-{
- int matchcount;
- int curitem;
-
- /* update our driver list if necessary */
- if (menustate->driverlist[0] == NULL)
- menu_select_game_build_driver_list(menu, menustate);
- for (curitem = matchcount = 0; menustate->driverlist[curitem] != NULL && matchcount < VISIBLE_GAMES_IN_LIST; curitem++)
- if (!(menustate->driverlist[curitem]->flags & GAME_NO_STANDALONE))
- matchcount++;
-
- /* if nothing there, add a single multiline item and return */
- if (matchcount == 0)
- {
- astring txt;
- txt.printf("No %s found. Please check the rompath specified in the %s.ini file.\n\n"
- "If this is your first time using %s, please see the config.txt file in "
- "the docs directory for information on configuring %s.",
- emulator_info::get_gamesnoun(),
- emulator_info::get_configname(),
- emulator_info::get_appname(),emulator_info::get_appname() );
- ui_menu_item_append(menu, txt.cstr(), NULL, MENU_FLAG_MULTILINE | MENU_FLAG_REDTEXT, NULL);
- return;
- }
-
- /* otherwise, rebuild the match list */
- assert(drivlist != NULL);
- if (menustate->search[0] != 0 || menustate->matchlist[0] == -1 || menustate->rerandomize)
- drivlist->find_approximate_matches(menustate->search, matchcount, menustate->matchlist);
- menustate->rerandomize = FALSE;
-
- /* iterate over entries */
- for (curitem = 0; curitem < matchcount; curitem++)
- {
- int curmatch = menustate->matchlist[curitem];
- if (curmatch != -1)
- {
- int cloneof = drivlist->non_bios_clone(curmatch);
- ui_menu_item_append(menu, drivlist->driver(curmatch).name, drivlist->driver(curmatch).description, (cloneof == -1) ? 0 : MENU_FLAG_INVERT, (void *)&drivlist->driver(curmatch));
- }
- }
-
- /* if we're forced into this, allow general input configuration as well */
- if (ui_menu_is_force_game_select())
- {
- ui_menu_item_append(menu, MENU_SEPARATOR_ITEM, NULL, 0, NULL);
- ui_menu_item_append(menu, "Configure General Inputs", NULL, 0, (void *)1);
- }
-
- /* configure the custom rendering */
- ui_menu_set_custom_render(menu, menu_select_game_custom_render, ui_get_line_height(machine) + 3.0f * UI_BOX_TB_BORDER, 4.0f * ui_get_line_height(machine) + 3.0f * UI_BOX_TB_BORDER);
-}
-
-
-/*-------------------------------------------------
- menu_select_game_build_driver_list - build a
- list of available drivers
--------------------------------------------------*/
-
-static void menu_select_game_build_driver_list(ui_menu *menu, select_game_state *menustate)
-{
- // start with an empty list
- // hack alert: use new directly here to avoid reporting this one-time static memory as unfreed
- if (drivlist == NULL)
- drivlist = global_alloc(driver_enumerator(menu->machine().options()));
- drivlist->exclude_all();
-
- /* open a path to the ROMs and find them in the array */
- file_enumerator path(menu->machine().options().media_path());
- const osd_directory_entry *dir;
-
- /* iterate while we get new objects */
- while ((dir = path.next()) != NULL)
- {
- char drivername[50];
- char *dst = drivername;
- const char *src;
-
- /* build a name for it */
- for (src = dir->name; *src != 0 && *src != '.' && dst < &drivername[ARRAY_LENGTH(drivername) - 1]; src++)
- *dst++ = tolower((UINT8)*src);
- *dst = 0;
-
- int drivnum = drivlist->find(drivername);
- if (drivnum != -1)
- drivlist->include(drivnum);
- }
-
- /* now build the final list */
- drivlist->reset();
- int listnum = 0;
- while (drivlist->next())
- menustate->driverlist[listnum++] = &drivlist->driver();
-
- /* NULL-terminate */
- menustate->driverlist[listnum] = NULL;
-}
-
-
-/*-------------------------------------------------
- menu_select_game_custom_render - perform our
- special rendering
--------------------------------------------------*/
-
-static void menu_select_game_custom_render(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2)
-{
- select_game_state *menustate = (select_game_state *)state;
- const game_driver *driver;
- float width, maxwidth;
- float x1, y1, x2, y2;
- char tempbuf[4][256];
- rgb_t color;
- int line;
-
- /* display the current typeahead */
- if (menustate->search[0] != 0)
- sprintf(&tempbuf[0][0], "Type name or select: %s_", menustate->search);
- else
- sprintf(&tempbuf[0][0], "Type name or select: (random)");
-
- /* get the size of the text */
- ui_draw_text_full(menu->container, &tempbuf[0][0], 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, NULL);
- width += 2 * UI_BOX_LR_BORDER;
- maxwidth = MAX(width, origx2 - origx1);
-
- /* compute our bounds */
- x1 = 0.5f - 0.5f * maxwidth;
- x2 = x1 + maxwidth;
- y1 = origy1 - top;
- y2 = origy1 - UI_BOX_TB_BORDER;
-
- /* draw a box */
- ui_draw_outlined_box(menu->container, x1, y1, x2, y2, UI_BACKGROUND_COLOR);
-
- /* take off the borders */
- x1 += UI_BOX_LR_BORDER;
- x2 -= UI_BOX_LR_BORDER;
- y1 += UI_BOX_TB_BORDER;
- y2 -= UI_BOX_TB_BORDER;
-
- /* draw the text within it */
- ui_draw_text_full(menu->container, &tempbuf[0][0], x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, NULL);
-
- /* determine the text to render below */
- driver = ((FPTR)selectedref > 1) ? (const game_driver *)selectedref : NULL;
- if ((FPTR)driver > 1)
- {
- const char *gfxstat, *soundstat;
-
- /* first line is game name */
- sprintf(&tempbuf[0][0], "%-.100s", driver->description);
-
- /* next line is year, manufacturer */
- sprintf(&tempbuf[1][0], "%s, %-.100s", driver->year, driver->manufacturer);
-
- /* next line is overall driver status */
- if (driver->flags & GAME_NOT_WORKING)
- strcpy(&tempbuf[2][0], "Overall: NOT WORKING");
- else if (driver->flags & GAME_UNEMULATED_PROTECTION)
- strcpy(&tempbuf[2][0], "Overall: Unemulated Protection");
- else
- strcpy(&tempbuf[2][0], "Overall: Working");
-
- /* next line is graphics, sound status */
- if (driver->flags & (GAME_IMPERFECT_GRAPHICS | GAME_WRONG_COLORS | GAME_IMPERFECT_COLORS))
- gfxstat = "Imperfect";
- else
- gfxstat = "OK";
-
- if (driver->flags & GAME_NO_SOUND)
- soundstat = "Unimplemented";
- else if (driver->flags & GAME_IMPERFECT_SOUND)
- soundstat = "Imperfect";
- else
- soundstat = "OK";
-
- sprintf(&tempbuf[3][0], "Gfx: %s, Sound: %s", gfxstat, soundstat);
- }
- else
- {
- const char *s = emulator_info::get_copyright();
- line = 0;
- int col = 0;
-
- /* first line is version string */
- sprintf(&tempbuf[line++][0], "%s %s", emulator_info::get_applongname(), build_version);
-
- /* output message */
- while (line < ARRAY_LENGTH(tempbuf))
- {
- if (*s == 0 || *s == '\n')
- {
- tempbuf[line++][col] = 0;
- col = 0;
- }
- else
- tempbuf[line][col++] = *s;
-
- if (*s != 0)
- s++;
- }
- }
-
- /* get the size of the text */
- maxwidth = origx2 - origx1;
- for (line = 0; line < 4; line++)
- {
- ui_draw_text_full(menu->container, &tempbuf[line][0], 0.0f, 0.0f, 1.0f, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &width, NULL);
- width += 2 * UI_BOX_LR_BORDER;
- maxwidth = MAX(maxwidth, width);
- }
-
- /* compute our bounds */
- x1 = 0.5f - 0.5f * maxwidth;
- x2 = x1 + maxwidth;
- y1 = origy2 + UI_BOX_TB_BORDER;
- y2 = origy2 + bottom;
-
- /* draw a box */
- color = UI_BACKGROUND_COLOR;
- if (driver != NULL)
- color = UI_GREEN_COLOR;
- if (driver != NULL && (driver->flags & (GAME_IMPERFECT_GRAPHICS | GAME_WRONG_COLORS | GAME_IMPERFECT_COLORS | GAME_NO_SOUND | GAME_IMPERFECT_SOUND)) != 0)
- color = UI_YELLOW_COLOR;
- if (driver != NULL && (driver->flags & (GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION)) != 0)
- color = UI_RED_COLOR;
- ui_draw_outlined_box(menu->container, x1, y1, x2, y2, color);
-
- /* take off the borders */
- x1 += UI_BOX_LR_BORDER;
- x2 -= UI_BOX_LR_BORDER;
- y1 += UI_BOX_TB_BORDER;
- y2 -= UI_BOX_TB_BORDER;
-
- /* draw all lines */
- for (line = 0; line < 4; line++)
- {
- ui_draw_text_full(menu->container, &tempbuf[line][0], x1, y1, x2 - x1, JUSTIFY_CENTER, WRAP_TRUNCATE,
- DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, NULL, NULL);
- y1 += ui_get_line_height(machine);
- }
-}
-
-
-
/***************************************************************************
MENU HELPERS
***************************************************************************/
/*-------------------------------------------------
- menu_render_triangle - render a triangle that
+ render_triangle - render a triangle that
is used for up/down arrows and left/right
indicators
-------------------------------------------------*/
-static void menu_render_triangle(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param)
+void ui_menu::render_triangle(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param)
{
int halfwidth = dest.width / 2;
int height = dest.height;
diff --git a/src/emu/uimenu.h b/src/emu/uimenu.h
index e8d42e12e34..8b41ca764de 100644
--- a/src/emu/uimenu.h
+++ b/src/emu/uimenu.h
@@ -57,98 +57,139 @@ class ui_menu;
/* menu-related callback functions */
-typedef void (*ui_menu_handler_func)(running_machine &machine, ui_menu *menu, void *parameter, void *state);
typedef void (*ui_menu_custom_func)(running_machine &machine, ui_menu *menu, void *state, void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
-typedef void (*ui_menu_destroy_state_func)(ui_menu *menu, void *state);
/* menu-related events */
-typedef struct _ui_menu_event ui_menu_event;
-struct _ui_menu_event
+struct ui_menu_event
{
void * itemref; /* reference for the selected item */
int iptkey; /* one of the IPT_* values from inptport.h */
unicode_char unichar; /* unicode character if iptkey == IPT_SPECIAL */
};
+struct ui_menu_pool
+{
+ ui_menu_pool * next; /* chain to next one */
+ UINT8 * top; /* top of the pool */
+ UINT8 * end; /* end of the pool */
+};
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-
-/* ----- core system management ----- */
+class ui_menu_item
+{
+public:
+ const char * text;
+ const char * subtext;
+ UINT32 flags;
+ void * ref;
-/* initialization */
-void ui_menu_init(running_machine &machine);
+ inline bool is_selectable() const;
+};
+class ui_menu
+{
+public:
+ ui_menu(running_machine &machine, render_container *container);
+ virtual ~ui_menu();
+ running_machine &machine() const { return m_machine; }
-/* ----- core menu management ----- */
+ render_container * container; /* render_container we render to */
+ ui_menu_event menu_event; /* the UI menu_event that occurred */
+ ui_menu * parent; /* pointer to parent menu */
+ int resetpos; /* reset position */
+ void * resetref; /* reset reference */
+ int selected; /* which item is selected */
+ int hover; /* which item is being hovered over */
+ int visitems; /* number of visible items */
+ int numitems; /* number of items in the menu */
+ int allocitems; /* allocated size of array */
+ ui_menu_item * item; /* pointer to array of items */
+ float customtop; /* amount of extra height to add at the top */
+ float custombottom; /* amount of extra height to add at the bottom */
+ ui_menu_pool * pool; /* list of memory pools */
-/* allocate a new menu */
-ui_menu *ui_menu_alloc(running_machine &machine, render_container *container, ui_menu_handler_func handler, void *parameter);
+ /* free all items in the menu, and all memory allocated from the memory pool */
+ void reset(ui_menu_reset_options options);
-/* free a menu */
-void ui_menu_free(ui_menu *menu);
+ /* returns true if the menu has any non-default items in it */
+ bool populated();
-/* free all items in the menu, and all memory allocated from the memory pool */
-void ui_menu_reset(ui_menu *menu, ui_menu_reset_options options);
+ /* append a new item to the end of the menu */
+ void item_append(const char *text, const char *subtext, UINT32 flags, void *ref);
-/* returns TRUE if the menu has any non-default items in it */
-int ui_menu_populated(ui_menu *menu);
+ /* process a menu, drawing it and returning any interesting events */
+ const ui_menu_event *process(UINT32 flags);
-/* append a new item to the end of the menu */
-void ui_menu_item_append(ui_menu *menu, const char *text, const char *subtext, UINT32 flags, void *ref);
+ /* configure the menu for custom rendering */
+ virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2);
-/* process a menu, drawing it and returning any interesting events */
-const ui_menu_event *ui_menu_process(running_machine &machine, ui_menu *menu, UINT32 flags);
+ /* allocate temporary memory from the menu's memory pool */
+ void *m_pool_alloc(size_t size);
-/* configure the menu for custom rendering */
-void ui_menu_set_custom_render(ui_menu *menu, ui_menu_custom_func custom, float top, float bottom);
+ /* make a temporary string copy in the menu's memory pool */
+ const char *pool_strdup(const char *string);
-/* allocate permanent memory to represent the menu's state */
-void *ui_menu_alloc_state(ui_menu *menu, size_t size, ui_menu_destroy_state_func destroy_state);
+ /* retrieves the index of the currently selected menu item */
+ void *get_selection();
-/* allocate temporary memory from the menu's memory pool */
-void *ui_menu_pool_alloc(ui_menu *menu, size_t size);
+ /* changes the index of the currently selected menu item */
+ void set_selection(void *selected_itemref);
-/* make a temporary string copy in the menu's memory pool */
-const char *ui_menu_pool_strdup(ui_menu *menu, const char *string);
+ /* request the specific handling of the game selection main menu */
+ bool is_special_main_menu() const;
+ void set_special_main_menu(bool disable);
-/* retrieves the index of the currently selected menu item */
-void *ui_menu_get_selection(ui_menu *menu);
+ /* Global initialization */
+ static void init(running_machine &machine);
+ static void exit(running_machine &machine);
-/* changes the index of the currently selected menu item */
-void ui_menu_set_selection(ui_menu *menu, void *selected_itemref);
+ /* reset the menus, clearing everything */
+ static void stack_reset(running_machine &machine);
+ /* push a new menu onto the stack */
+ static void stack_push(ui_menu *menu);
+ /* pop a menu from the stack */
+ static void stack_pop(running_machine &machine);
-/* ----- menu stack management ----- */
+ /* test if one of the menus in the stack requires hide disable */
+ static bool stack_has_special_main_menu();
-/* reset the menus, clearing everything */
-void ui_menu_stack_reset(running_machine &machine);
+/* master handler */
+ static UINT32 ui_handler(running_machine &machine, render_container *container, UINT32 state);
-/* push a new menu onto the stack */
-void ui_menu_stack_push(ui_menu *menu);
+ /* Used by sliders */
+ void validate_selection(int scandir);
+ static ui_menu *menu_stack;
-/* pop a menu from the stack */
-void ui_menu_stack_pop(running_machine &machine);
+ void do_handle();
+ /* To be reimplemented in the menu subclass */
+ virtual void populate() = 0;
+ /* To be reimplemented in the menu subclass */
+ virtual void handle() = 0;
-/* ----- UI system interaction ----- */
+private:
+ static ui_menu *menu_free;
+ static bitmap_t *hilight_bitmap;
+ static render_texture *hilight_texture, *arrow_texture;
-/* master handler */
-UINT32 ui_menu_ui_handler(running_machine &machine, render_container *container, UINT32 state);
+ bool special_main_menu;
-/* slider handler */
-UINT32 ui_slider_ui_handler(running_machine &machine, render_container *container, UINT32 state);
+ running_machine & m_machine; /* machine we are attached to */
-/* force game select menu */
-void ui_menu_force_game_select(running_machine &machine, render_container *container);
-int ui_menu_is_force_game_select(void);
+ void draw(bool customonly);
+ void draw_text_box();
+ void handle_events();
+ void handle_keys(UINT32 flags);
+ void clear_free_list();
+ inline bool exclusive_input_pressed(int key, int repeat);
+ static void clear_free_list(running_machine &machine);
+ static void render_triangle(bitmap_t &dest, const bitmap_t &source, const rectangle &sbounds, void *param);
+};
#endif /* __UIMENU_H__ */
diff --git a/src/emu/uiswlist.c b/src/emu/uiswlist.c
index 9fffb999ded..a43734bd6dc 100644
--- a/src/emu/uiswlist.c
+++ b/src/emu/uiswlist.c
@@ -12,6 +12,7 @@
#include "emu.h"
#include "ui.h"
#include "uimenu.h"
+#include "uiswlist.h"
#include "softlist.h"
@@ -27,110 +28,72 @@
TYPE DEFINITIONS
***************************************************************************/
-/* state of a software entry */
-typedef struct _software_entry_state software_entry_state;
-struct _software_entry_state
+ui_menu_software_parts::ui_menu_software_parts(running_machine &machine, render_container *container, ui_menu_software_entry_info *_entry) : ui_menu(machine, container)
{
- software_entry_state *next;
-
- const char *short_name;
- const char *long_name;
- const char *interface;
- char *list_name;
- device_image_interface* image;
-};
-
-/* state of the software menu */
-typedef struct _software_menu_state software_menu_state;
-struct _software_menu_state
-{
- char *list_name; /* currently selected list */
- device_image_interface* image;
- software_entry_state *entrylist;
- char filename_buffer[1024];
- int ordered_by_shortname;
- int reorder;
-};
-
-/* state of a software part */
-typedef struct _software_part_state software_part_state;
-struct _software_part_state
-{
- const char *part_name;
- const char *interface;
-};
-
+ entry = _entry;
+}
-static void ui_mess_menu_populate_software_parts(running_machine &machine, ui_menu *menu, const char *swlist, const char *swinfo, const char *interface)
+void ui_menu_software_parts::populate()
{
- software_list *list = software_list_open(machine.options(), swlist, FALSE, NULL);
-
- if (list)
- {
- software_info *info = software_list_find(list, swinfo, NULL);
+ if(entry->list_name) {
+ software_list *list = software_list_open(machine().options(), entry->list_name, false, NULL);
- if (info)
+ if (list)
{
- for (software_part *swpart = software_find_part(info, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart))
+ software_info *info = software_list_find(list, entry->short_name, NULL);
+
+ if (info)
{
- if (strcmp(interface, swpart->interface_) == 0)
+ for (software_part *swpart = software_find_part(info, NULL, NULL); swpart != NULL; swpart = software_part_next(swpart))
{
- software_part_state *entry = (software_part_state *) ui_menu_pool_alloc(menu, sizeof(*entry));
- // check if the available parts have specific part_id to be displayed (e.g. "Map Disc", "Bonus Disc", etc.)
- // if not, we simply display "part_name"; if yes we display "part_name (part_id)"
- astring menu_part_name(swpart->name);
- if (software_part_get_feature(swpart, "part_id") != NULL)
+ if (strcmp(entry->interface, swpart->interface_) == 0)
{
- menu_part_name.cat(" (");
- menu_part_name.cat(software_part_get_feature(swpart, "part_id"));
- menu_part_name.cat(")");
+ software_part_info *entry = (software_part_info *) m_pool_alloc(sizeof(*entry));
+ // check if the available parts have specific part_id to be displayed (e.g. "Map Disc", "Bonus Disc", etc.)
+ // if not, we simply display "part_name"; if yes we display "part_name (part_id)"
+ astring menu_part_name(swpart->name);
+ if (software_part_get_feature(swpart, "part_id") != NULL)
+ {
+ menu_part_name.cat(" (");
+ menu_part_name.cat(software_part_get_feature(swpart, "part_id"));
+ menu_part_name.cat(")");
+ }
+ entry->part_name = pool_strdup(swpart->name); // part_name is later used to build up the filename to load, so we use swpart->name!
+ entry->interface = pool_strdup(swpart->interface_);
+ item_append(info->shortname, menu_part_name.cstr(), 0, entry);
}
- entry->part_name = ui_menu_pool_strdup(menu, swpart->name); // part_name is later used to build up the filename to load, so we use swpart->name!
- entry->interface = ui_menu_pool_strdup(menu, swpart->interface_);
- ui_menu_item_append(menu, info->shortname, menu_part_name.cstr(), 0, entry);
}
}
- }
- software_list_close(list);
+ software_list_close(list);
+ }
}
}
-void ui_mess_menu_software_parts(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+ui_menu_software_parts::~ui_menu_software_parts()
{
- const ui_menu_event *event;
- software_entry_state *sw_state = (software_entry_state *)state;
- const char *swlist = sw_state->list_name;
- const char *swinfo = sw_state->short_name;
- const char *interface = sw_state->interface;
-
- // generate list of available parts
- if (!ui_menu_populated(menu))
- {
- if (sw_state->list_name)
- {
- ui_mess_menu_populate_software_parts(machine, menu, swlist, swinfo, interface);
- }
- }
+}
+void ui_menu_software_parts::handle()
+{
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ const ui_menu_event *event = process(0);
if (event != NULL && event->iptkey == IPT_UI_SELECT && event->itemref != NULL)
{
- software_part_state *entry = (software_part_state *) event->itemref;
+ software_part_info *pentry = (software_part_info *) event->itemref;
// build the name for the part to be loaded
- astring temp_name(sw_state->short_name);
+ astring temp_name(entry->short_name);
temp_name.cat(":");
- temp_name.cat(entry->part_name);
+ temp_name.cat(pentry->part_name);
//printf("%s\n", temp_name.cstr());
- sw_state->image->load(temp_name.cstr());
+ entry->image->load(temp_name.cstr());
}
}
-static int compare_software_entries(const software_entry_state *e1, const software_entry_state *e2, int shortname)
+int ui_menu_software_list::compare_entries(const ui_menu_software_entry_info *e1, const ui_menu_software_entry_info *e2, bool shortname)
{
int result;
const char *e1_basename;
@@ -165,11 +128,10 @@ static int compare_software_entries(const software_entry_state *e1, const softwa
/* populate a specific list */
-static software_entry_state *append_software_entry(ui_menu *menu, software_menu_state *menustate,
- software_info *swinfo, char *list_name, device_image_interface* image)
+ui_menu_software_entry_info *ui_menu_software_list::append_software_entry(software_info *swinfo, char *list_name, device_image_interface* image)
{
- software_entry_state *entry = NULL;
- software_entry_state **entryptr;
+ ui_menu_software_entry_info *entry = NULL;
+ ui_menu_software_entry_info **entryptr;
const char *interface = image->image_interface();
// check if at least one of the parts has the correct interface and add a menu entry only in this case
@@ -178,21 +140,21 @@ static software_entry_state *append_software_entry(ui_menu *menu, software_menu_
if (strcmp(interface, swpart->interface_) == 0)
{
// allocate a new entry
- entry = (software_entry_state *) ui_menu_pool_alloc(menu, sizeof(*entry));
+ entry = (ui_menu_software_entry_info *) m_pool_alloc(sizeof(*entry));
memset(entry, 0, sizeof(*entry));
- entry->short_name = ui_menu_pool_strdup(menu, swinfo->shortname);
- entry->long_name = ui_menu_pool_strdup(menu, swinfo->longname);
+ entry->short_name = pool_strdup(swinfo->shortname);
+ entry->long_name = pool_strdup(swinfo->longname);
entry->list_name = list_name;
entry->image = image;
- entry->interface = ui_menu_pool_strdup(menu, swpart->interface_);
+ entry->interface = pool_strdup(swpart->interface_);
break;
}
}
// find the end of the list
- entryptr = &menustate->entrylist;
- while ((*entryptr != NULL) && (compare_software_entries(entry, *entryptr, menustate->ordered_by_shortname) >= 0))
+ entryptr = &entrylist;
+ while ((*entryptr != NULL) && (compare_entries(entry, *entryptr, ordered_by_shortname) >= 0))
entryptr = &(*entryptr)->next;
// insert the entry
@@ -202,29 +164,40 @@ static software_entry_state *append_software_entry(ui_menu *menu, software_menu_
return entry;
}
+ui_menu_software_list::ui_menu_software_list(running_machine &machine, render_container *container, char *_list_name, device_image_interface *_image) : ui_menu(machine, container)
+{
+ list_name = _list_name;
+ image = _image;
+ entrylist = NULL;
+ ordered_by_shortname = true;
+}
+
+ui_menu_software_list::~ui_menu_software_list()
+{
+}
-static void ui_mess_menu_populate_software_entries(running_machine &machine, ui_menu *menu, software_menu_state *menustate)
+void ui_menu_software_list::populate()
{
- software_list *list = software_list_open(machine.options(), menustate->list_name, FALSE, NULL);
+ software_list *list = software_list_open(machine().options(), list_name, false, NULL);
// build up the list of entries for the menu
if (list)
{
for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo))
- append_software_entry(menu, menustate, swinfo, menustate->list_name, menustate->image);
+ append_software_entry(swinfo, list_name, image);
software_list_close(list);
}
// add an entry to change ordering
- ui_menu_item_append(menu, "Switch Item Ordering", NULL, 0, (void *)1);
+ item_append("Switch Item Ordering", NULL, 0, (void *)1);
// append all of the menu entries
- for (software_entry_state *entry = menustate->entrylist; entry != NULL; entry = entry->next)
- ui_menu_item_append(menu, entry->short_name, entry->long_name, 0, entry);
+ for (ui_menu_software_entry_info *entry = entrylist; entry != NULL; entry = entry->next)
+ item_append(entry->short_name, entry->long_name, 0, entry);
}
-bool swinfo_has_multiple_parts(software_info *swinfo, const char *interface)
+bool ui_menu_software_list::swinfo_has_multiple_parts(software_info *swinfo, const char *interface)
{
int count = 0;
@@ -233,62 +206,50 @@ bool swinfo_has_multiple_parts(software_info *swinfo, const char *interface)
if (strcmp(interface, swpart->interface_) == 0)
count++;
}
- return (count > 1) ? TRUE : FALSE;
+ return (count > 1) ? true : false;
}
-void ui_mess_menu_software_list(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+void ui_menu_software_list::handle()
{
- const ui_menu_event *event;
- software_menu_state *sw_state = (software_menu_state *)state;
- const software_entry_state *entry;
- const software_entry_state *selected_entry = NULL;
+ const ui_menu_software_entry_info *entry;
+ const ui_menu_software_entry_info *selected_entry = NULL;
int bestmatch = 0;
- if (!ui_menu_populated(menu) || sw_state->reorder)
- {
- sw_state->reorder = 0;
-
- if (sw_state->list_name)
- {
- ui_mess_menu_populate_software_entries(machine, menu, sw_state);
- }
- }
-
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ const ui_menu_event *event = process(0);
if (event != NULL && event->itemref != NULL)
{
if ((FPTR)event->itemref == 1 && event->iptkey == IPT_UI_SELECT)
{
- sw_state->ordered_by_shortname ^= 1;
- sw_state->reorder = 1;
- sw_state->entrylist = NULL;
+ ordered_by_shortname = !ordered_by_shortname;
+ entrylist = NULL;
// reset the char buffer if we change ordering criterion
- memset(sw_state->filename_buffer, '\0', ARRAY_LENGTH(sw_state->filename_buffer));
+ memset(filename_buffer, '\0', ARRAY_LENGTH(filename_buffer));
// reload the menu with the new order
- ui_menu_reset(menu, UI_MENU_RESET_REMEMBER_REF);
- popmessage("Switched Order: entries now ordered by %s", sw_state->ordered_by_shortname ? "shortname" : "description");
+ reset(UI_MENU_RESET_REMEMBER_REF);
+ popmessage("Switched Order: entries now ordered by %s", ordered_by_shortname ? "shortname" : "description");
}
/* handle selections */
else if (event->iptkey == IPT_UI_SELECT)
{
- device_image_interface *image = sw_state->image;
- software_entry_state *entry = (software_entry_state *) event->itemref;
- software_list *tmp_list = software_list_open(machine.options(), sw_state->list_name, FALSE, NULL);
+ ui_menu_software_entry_info *entry = (ui_menu_software_entry_info *) event->itemref;
+ software_list *tmp_list = software_list_open(machine().options(), list_name, false, NULL);
software_info *tmp_info = software_list_find(tmp_list, entry->short_name, NULL);
// if the selected software has multiple parts that can be loaded, open the submenu
if (swinfo_has_multiple_parts(tmp_info, image->image_interface()))
{
+#if 0
ui_menu *child_menu = ui_menu_alloc(machine, &machine.render().ui_container(), ui_mess_menu_software_parts, entry);
- software_entry_state *child_menustate = (software_entry_state *)ui_menu_alloc_state(child_menu, sizeof(*child_menustate), NULL);
+ ui_menu_software_entry_info *child_menustate = (ui_menu_software_entry_info *)child_menu->alloc_state(sizeof(*child_menustate), NULL);
child_menustate->short_name = entry->short_name;
child_menustate->interface = image->image_interface();
- child_menustate->list_name = sw_state->list_name;
+ child_menustate->list_name = list_name;
child_menustate->image = image;
- ui_menu_stack_push(child_menu);
+ ui_menu::stack_push(child_menu);
+#endif
}
else
{
@@ -298,57 +259,57 @@ void ui_mess_menu_software_list(running_machine &machine, ui_menu *menu, void *p
software_list_close(tmp_list);
// reset the char buffer when pressing IPT_UI_SELECT
- if (sw_state->filename_buffer[0] != '\0')
- memset(sw_state->filename_buffer, '\0', ARRAY_LENGTH(sw_state->filename_buffer));
+ if (filename_buffer[0] != '\0')
+ memset(filename_buffer, '\0', ARRAY_LENGTH(filename_buffer));
}
else if (event->iptkey == IPT_SPECIAL)
{
- int buflen = strlen(sw_state->filename_buffer);
- bool update_selected = FALSE;
+ int buflen = strlen(filename_buffer);
+ bool update_selected = false;
/* if it's a backspace and we can handle it, do so */
if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
{
- *(char *)utf8_previous_char(&sw_state->filename_buffer[buflen]) = 0;
- update_selected = TRUE;
+ *(char *)utf8_previous_char(&filename_buffer[buflen]) = 0;
+ update_selected = true;
- if (ARRAY_LENGTH(sw_state->filename_buffer) > 0)
- ui_popup_time(ERROR_MESSAGE_TIME, "%s", sw_state->filename_buffer);
+ if (ARRAY_LENGTH(filename_buffer) > 0)
+ ui_popup_time(ERROR_MESSAGE_TIME, "%s", filename_buffer);
}
/* if it's any other key and we're not maxed out, update */
else if (event->unichar >= ' ' && event->unichar < 0x7f)
{
- buflen += utf8_from_uchar(&sw_state->filename_buffer[buflen], ARRAY_LENGTH(sw_state->filename_buffer) - buflen, event->unichar);
- sw_state->filename_buffer[buflen] = 0;
- update_selected = TRUE;
+ buflen += utf8_from_uchar(&filename_buffer[buflen], ARRAY_LENGTH(filename_buffer) - buflen, event->unichar);
+ filename_buffer[buflen] = 0;
+ update_selected = true;
- if (ARRAY_LENGTH(sw_state->filename_buffer) > 0)
- ui_popup_time(ERROR_MESSAGE_TIME, "%s", sw_state->filename_buffer);
+ if (ARRAY_LENGTH(filename_buffer) > 0)
+ ui_popup_time(ERROR_MESSAGE_TIME, "%s", filename_buffer);
}
if (update_selected)
{
- const software_entry_state *cur_selected;
+ const ui_menu_software_entry_info *cur_selected;
// if the current selection is a software entry, start search from here
if ((FPTR)event->itemref != 1)
- cur_selected= (const software_entry_state *)ui_menu_get_selection(menu);
+ cur_selected= (const ui_menu_software_entry_info *)get_selection();
// else (if we are on the 'Switch Order' entry) start from the beginning
else
- cur_selected= sw_state->entrylist;
+ cur_selected= entrylist;
// check for entries which matches our filename_buffer:
// from current entry to the end
for (entry = cur_selected; entry != NULL; entry = entry->next)
{
- const char *compare_name = sw_state->ordered_by_shortname ? entry->short_name : entry->long_name;
+ const char *compare_name = ordered_by_shortname ? entry->short_name : entry->long_name;
- if (compare_name != NULL && sw_state->filename_buffer != NULL)
+ if (compare_name != NULL && filename_buffer != NULL)
{
int match = 0;
- for (int i = 0; i < ARRAY_LENGTH(sw_state->filename_buffer); i++)
+ for (int i = 0; i < ARRAY_LENGTH(filename_buffer); i++)
{
- if (mame_strnicmp(compare_name, sw_state->filename_buffer, i) == 0)
+ if (mame_strnicmp(compare_name, filename_buffer, i) == 0)
match = i;
}
@@ -360,16 +321,16 @@ void ui_mess_menu_software_list(running_machine &machine, ui_menu *menu, void *p
}
}
// and from the first entry to current one
- for (entry = sw_state->entrylist; entry != cur_selected; entry = entry->next)
+ for (entry = entrylist; entry != cur_selected; entry = entry->next)
{
- const char *compare_name = sw_state->ordered_by_shortname ? entry->short_name : entry->long_name;
+ const char *compare_name = ordered_by_shortname ? entry->short_name : entry->long_name;
- if (compare_name != NULL && sw_state->filename_buffer != NULL)
+ if (compare_name != NULL && filename_buffer != NULL)
{
int match = 0;
- for (int i = 0; i < ARRAY_LENGTH(sw_state->filename_buffer); i++)
+ for (int i = 0; i < ARRAY_LENGTH(filename_buffer); i++)
{
- if (mame_strnicmp(compare_name, sw_state->filename_buffer, i) == 0)
+ if (mame_strnicmp(compare_name, filename_buffer, i) == 0)
match = i;
}
@@ -382,26 +343,31 @@ void ui_mess_menu_software_list(running_machine &machine, ui_menu *menu, void *p
}
if (selected_entry != NULL && selected_entry != cur_selected)
- ui_menu_set_selection(menu, (void *) selected_entry);
+ set_selection((void *) selected_entry);
}
}
else if (event->iptkey == IPT_UI_CANCEL)
{
// reset the char buffer also in this case
- if (sw_state->filename_buffer[0] != '\0')
- memset(sw_state->filename_buffer, '\0', ARRAY_LENGTH(sw_state->filename_buffer));
+ if (filename_buffer[0] != '\0')
+ memset(filename_buffer, '\0', ARRAY_LENGTH(filename_buffer));
}
}
}
/* list of available software lists - i.e. cartridges, floppies */
-static void ui_mess_menu_populate_software_list(running_machine &machine, ui_menu *menu, device_image_interface* image)
+ui_menu_software::ui_menu_software(running_machine &machine, render_container *container, device_image_interface* _image) : ui_menu(machine, container)
+{
+ image = _image;
+}
+
+void ui_menu_software::populate()
{
- bool haveCompatible = FALSE;
+ bool haveCompatible = false;
const char *interface = image->image_interface();
// Add original software lists for this system
- for (const device_t *dev = machine.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
+ for (const device_t *dev = machine().config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
{
software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config();
@@ -409,20 +375,20 @@ static void ui_mess_menu_populate_software_list(running_machine &machine, ui_men
{
if (swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_ORIGINAL_SYSTEM))
{
- software_list *list = software_list_open(machine.options(), swlist->list_name[i], FALSE, NULL);
+ software_list *list = software_list_open(machine().options(), swlist->list_name[i], false, NULL);
if (list)
{
- bool found = FALSE;
+ bool found = false;
for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo))
{
software_part *part = software_find_part(swinfo, NULL, NULL);
if (strcmp(interface,part->interface_)==0) {
- found = TRUE;
+ found = true;
}
}
if (found) {
- ui_menu_item_append(menu, list->description, NULL, 0, swlist->list_name[i]);
+ item_append(list->description, NULL, 0, swlist->list_name[i]);
}
software_list_close(list);
@@ -432,7 +398,7 @@ static void ui_mess_menu_populate_software_list(running_machine &machine, ui_men
}
// Add compatible software lists for this system
- for (const device_t *dev = machine.config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
+ for (const device_t *dev = machine().config().devicelist().first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
{
software_list_config *swlist = (software_list_config *)downcast<const legacy_device_base *>(dev)->inline_config();
@@ -440,26 +406,26 @@ static void ui_mess_menu_populate_software_list(running_machine &machine, ui_men
{
if (swlist->list_name[i] && (swlist->list_type == SOFTWARE_LIST_COMPATIBLE_SYSTEM))
{
- software_list *list = software_list_open(machine.options(), swlist->list_name[i], FALSE, NULL);
+ software_list *list = software_list_open(machine().options(), swlist->list_name[i], false, NULL);
if (list)
{
- bool found = FALSE;
+ bool found = false;
for (software_info *swinfo = software_list_find(list, "*", NULL); swinfo != NULL; swinfo = software_list_find(list, "*", swinfo))
{
software_part *part = software_find_part(swinfo, NULL, NULL);
if (strcmp(interface,part->interface_)==0) {
- found = TRUE;
+ found = true;
}
}
if (found) {
if (!haveCompatible) {
- ui_menu_item_append(menu, "[compatible lists]", NULL, MENU_FLAG_DISABLE, NULL);
+ item_append("[compatible lists]", NULL, MENU_FLAG_DISABLE, NULL);
}
- ui_menu_item_append(menu, list->description, NULL, 0, swlist->list_name[i]);
+ item_append(list->description, NULL, 0, swlist->list_name[i]);
}
- haveCompatible = TRUE;
+ haveCompatible = true;
software_list_close(list);
}
}
@@ -468,24 +434,15 @@ static void ui_mess_menu_populate_software_list(running_machine &machine, ui_men
}
-void ui_image_menu_software(running_machine &machine, ui_menu *menu, void *parameter, void *state)
+ui_menu_software::~ui_menu_software()
{
- const ui_menu_event *event;
- device_image_interface* image = (device_image_interface*)parameter;
- if (!ui_menu_populated(menu))
- ui_mess_menu_populate_software_list(machine, menu, image);
+}
+void ui_menu_software::handle()
+{
/* process the menu */
- event = ui_menu_process(machine, menu, 0);
+ const ui_menu_event *event = process(0);
if (event != NULL && event->iptkey == IPT_UI_SELECT)
- {
- ui_menu *child_menu = ui_menu_alloc(machine, &machine.render().ui_container(), ui_mess_menu_software_list, NULL);
- software_menu_state *child_menustate = (software_menu_state *)ui_menu_alloc_state(child_menu, sizeof(*child_menustate), NULL);
- child_menustate->list_name = (char *)event->itemref;
- child_menustate->image = image;
- child_menustate->entrylist = NULL;
- child_menustate->ordered_by_shortname = 1;
- ui_menu_stack_push(child_menu);
- }
+ ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container, (char *)event->itemref, image)));
}
diff --git a/src/emu/uiswlist.h b/src/emu/uiswlist.h
index 905edd5d7bf..52795423fa7 100644
--- a/src/emu/uiswlist.h
+++ b/src/emu/uiswlist.h
@@ -12,11 +12,60 @@
#ifndef __UISWLIST_H__
#define __UISWLIST_H__
+struct ui_menu_software_entry_info {
+ ui_menu_software_entry_info *next;
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+ const char *short_name;
+ const char *long_name;
+ const char *interface;
+ char *list_name;
+ device_image_interface* image;
+};
+
+class ui_menu_software_parts : public ui_menu {
+public:
+ ui_menu_software_parts(running_machine &machine, render_container *container, ui_menu_software_entry_info *entry);
+ virtual ~ui_menu_software_parts();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ struct software_part_info {
+ const char *part_name;
+ const char *interface;
+ };
+
+ ui_menu_software_entry_info *entry;
+};
+
+class ui_menu_software_list : public ui_menu {
+public:
+ ui_menu_software_list(running_machine &machine, render_container *container, char *list_name, device_image_interface *image);
+ virtual ~ui_menu_software_list();
+ virtual void populate();
+ virtual void handle();
+
+private:
+ char *list_name; /* currently selected list */
+ device_image_interface *image;
+ ui_menu_software_entry_info *entrylist;
+ char filename_buffer[1024];
+ bool ordered_by_shortname;
+
+ int compare_entries(const ui_menu_software_entry_info *e1, const ui_menu_software_entry_info *e2, bool shortname);
+ ui_menu_software_entry_info *append_software_entry(software_info *swinfo, char *list_name, device_image_interface* image);
+ bool swinfo_has_multiple_parts(software_info *swinfo, const char *interface);
+};
+
+class ui_menu_software : public ui_menu {
+public:
+ ui_menu_software(running_machine &machine, render_container *container, device_image_interface *device);
+ virtual ~ui_menu_software();
+ virtual void populate();
+ virtual void handle();
-void ui_image_menu_software(running_machine &machine, ui_menu *menu, void *parameter, void *state);
+private:
+ device_image_interface *image;
+};
#endif /* __UISWLIST_H__ */
diff --git a/src/lib/formats/flopimg.c b/src/lib/formats/flopimg.c
index 06e5b2455d1..4b75fc33e34 100644
--- a/src/lib/formats/flopimg.c
+++ b/src/lib/formats/flopimg.c
@@ -1078,48 +1078,45 @@ int floppy_image_format_t::crc_cells_size(int type) const
}
}
-bool floppy_image_format_t::bit_r(UINT8 *buffer, int offset)
+bool floppy_image_format_t::bit_r(const UINT32 *buffer, int offset)
{
- return (buffer[offset >> 3] >> ((offset & 7) ^ 7)) & 1;
+ return (buffer[offset] & floppy_image::MG_MASK) == MG_1;
}
-void floppy_image_format_t::bit_w(UINT8 *buffer, int offset, bool val)
+void floppy_image_format_t::bit_w(UINT32 *buffer, int offset, bool val, UINT32 size)
{
- if(val)
- buffer[offset >> 3] |= 0x80 >> (offset & 7);
- else
- buffer[offset >> 3] &= ~(0x80 >> (offset & 7));
+ buffer[offset] = (val ? MG_1 : MG_0) | size;
}
-void floppy_image_format_t::raw_w(UINT8 *buffer, int &offset, int n, UINT32 val)
+void floppy_image_format_t::raw_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size)
{
for(int i=n-1; i>=0; i--)
- bit_w(buffer, offset++, (val >> i) & 1);
+ bit_w(buffer, offset++, (val >> i) & 1, size);
}
-void floppy_image_format_t::mfm_w(UINT8 *buffer, int &offset, int n, UINT32 val)
+void floppy_image_format_t::mfm_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size)
{
int prec = offset ? bit_r(buffer, offset-1) : 0;
for(int i=n-1; i>=0; i--) {
int bit = (val >> i) & 1;
- bit_w(buffer, offset++, !(prec || bit));
- bit_w(buffer, offset++, bit);
+ bit_w(buffer, offset++, !(prec || bit), size);
+ bit_w(buffer, offset++, bit, size);
prec = bit;
}
}
-void floppy_image_format_t::mfm_half_w(UINT8 *buffer, int &offset, int start_bit, UINT32 val)
+void floppy_image_format_t::mfm_half_w(UINT32 *buffer, int &offset, int start_bit, UINT32 val, UINT32 size)
{
int prec = offset ? bit_r(buffer, offset-1) : 0;
for(int i=start_bit; i>=0; i-=2) {
int bit = (val >> i) & 1;
- bit_w(buffer, offset++, !(prec || bit));
- bit_w(buffer, offset++, bit);
+ bit_w(buffer, offset++, !(prec || bit), size);
+ bit_w(buffer, offset++, bit, size);
prec = bit;
}
}
-void floppy_image_format_t::fixup_crc_amiga(UINT8 *buffer, const gen_crc_info *crc)
+void floppy_image_format_t::fixup_crc_amiga(UINT32 *buffer, const gen_crc_info *crc)
{
UINT16 res = 0;
int size = crc->end - crc->start;
@@ -1131,22 +1128,27 @@ void floppy_image_format_t::fixup_crc_amiga(UINT8 *buffer, const gen_crc_info *c
mfm_w(buffer, offset, 16, res);
}
-void floppy_image_format_t::fixup_crc_ccitt(UINT8 *buffer, const gen_crc_info *crc)
+UINT16 floppy_image_format_t::calc_crc_ccitt(const UINT32 *buffer, int start, int end)
{
UINT32 res = 0xffff;
- int size = crc->end - crc->start;
+ int size = end - start;
for(int i=1; i<size; i+=2) {
res <<= 1;
- if(bit_r(buffer, crc->start + i))
+ if(bit_r(buffer, start + i))
res ^= 0x10000;
if(res & 0x10000)
res ^= 0x11021;
}
+ return res;
+}
+
+void floppy_image_format_t::fixup_crc_ccitt(UINT32 *buffer, const gen_crc_info *crc)
+{
int offset = crc->write;
- mfm_w(buffer, offset, 16, res);
+ mfm_w(buffer, offset, 16, calc_crc_ccitt(buffer, crc->start, crc->end));
}
-void floppy_image_format_t::fixup_crcs(UINT8 *buffer, gen_crc_info *crcs)
+void floppy_image_format_t::fixup_crcs(UINT32 *buffer, gen_crc_info *crcs)
{
for(int i=0; i != MAX_CRC_COUNT; i++)
if(crcs[i].write != -1) {
@@ -1183,7 +1185,7 @@ int floppy_image_format_t::calc_sector_index(int num, int interleave, int skew,
void floppy_image_format_t::generate_track(const desc_e *desc, int track, int head, const desc_s *sect, int sect_count, int track_size, floppy_image *image)
{
- UINT8 *buffer = global_alloc_array_clear(UINT8, (track_size+7)/8);
+ UINT32 *buffer = global_alloc_array_clear(UINT32, track_size);
gen_crc_info crcs[MAX_CRC_COUNT];
collect_crcs(desc, crcs);
@@ -1332,7 +1334,7 @@ void floppy_image_format_t::generate_track(const desc_e *desc, int track, int he
fixup_crcs(buffer, crcs);
- generate_track_from_bitstream(track, head, buffer, track_size, image);
+ generate_track_from_levels(track, head, buffer, track_size, 0, image);
global_free(buffer);
}
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index db776ac576a..95b38a139ea 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -410,6 +410,13 @@ protected:
// PC-type sectors with MFM encoding and fixed-size
void get_track_data_mfm_pc(int track, int head, floppy_image *image, int cell_size, int sector_size, int sector_count, UINT8 *sectdata);
+ bool bit_r(const UINT32 *buffer, int offset);
+ void bit_w(UINT32 *buffer, int offset, bool val, UINT32 size = 1000);
+ UINT16 calc_crc_ccitt(const UINT32 *buffer, int start, int end);
+ void raw_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000);
+ void mfm_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000);
+ void mfm_half_w(UINT32 *buffer, int &offset, int start_bit, UINT32 val, UINT32 size = 1000);
+
private:
enum { CRC_NONE, CRC_AMIGA, CRC_CCITT };
enum { MAX_CRC_COUNT = 64 };
@@ -421,16 +428,10 @@ private:
bool type_no_data(int type) const;
bool type_data_mfm(int type, int p1, const gen_crc_info *crcs) const;
- bool bit_r(UINT8 *buffer, int offset);
- void bit_w(UINT8 *buffer, int offset, bool val);
-
int crc_cells_size(int type) const;
- void fixup_crc_amiga(UINT8 *buffer, const gen_crc_info *crc);
- void fixup_crc_ccitt(UINT8 *buffer, const gen_crc_info *crc);
- void fixup_crcs(UINT8 *buffer, gen_crc_info *crcs);
- void raw_w(UINT8 *buffer, int &offset, int n, UINT32 val);
- void mfm_w(UINT8 *buffer, int &offset, int n, UINT32 val);
- void mfm_half_w(UINT8 *buffer, int &offset, int start_bit, UINT32 val);
+ void fixup_crc_amiga(UINT32 *buffer, const gen_crc_info *crc);
+ void fixup_crc_ccitt(UINT32 *buffer, const gen_crc_info *crc);
+ void fixup_crcs(UINT32 *buffer, gen_crc_info *crcs);
void collect_crcs(const desc_e *desc, gen_crc_info *crcs);
int sbit_r(const UINT8 *bitstream, int pos);
diff --git a/src/lib/formats/pasti_dsk.c b/src/lib/formats/pasti_dsk.c
new file mode 100644
index 00000000000..56dca8999ed
--- /dev/null
+++ b/src/lib/formats/pasti_dsk.c
@@ -0,0 +1,615 @@
+#include "pasti_dsk.h"
+#include "emu.h"
+
+// Pasti format supported using the documentation at
+// http://www.sarnau.info/atari:pasti_file_format
+
+// That format is an observational format, not a generative one. In
+// other terms, it encodes the raw responses of the WD1772 to the read
+// track, read ids and read sectors commands. So, in order to use it,
+// we have to build a physical representation which gives similar
+// enough results (read track varies even in the absence of fuzzy
+// bits).
+
+pasti_format::pasti_format()
+{
+}
+
+const char *pasti_format::name() const
+{
+ return "pasti";
+}
+
+const char *pasti_format::description() const
+{
+ return "Atari PASTI floppy disk image";
+}
+
+const char *pasti_format::extensions() const
+{
+ return "stx";
+}
+
+bool pasti_format::supports_save() const
+{
+ return false;
+}
+
+int pasti_format::identify(io_generic *io)
+{
+ UINT8 h[16];
+ io_generic_read(io, h, 0, 16);
+
+ if(!memcmp(h, "RSY\0\3\0", 6) &&
+ (1 || (h[10] >= 80 && h[10] <= 82) || (h[10] >= 160 && h[10] <= 164)))
+ return 100;
+
+ return 0;
+}
+
+static void hexdump(const UINT8 *d, int s)
+{
+ for(int i=0; i<s; i+=32) {
+ printf("%04x:", i);
+ for(int j=i; j<s && j<i+32; j++)
+ printf(" %02x", d[j]);
+ printf("\n");
+ }
+}
+
+bool pasti_format::load(io_generic *io, floppy_image *image)
+{
+ UINT8 fh[16];
+ io_generic_read(io, fh, 0, 16);
+
+ UINT8 *raw_track = 0;
+ int raw_track_size = 0;
+
+ int tracks = fh[10];
+ int heads = 1+(tracks >= 160);
+ tracks /= heads;
+
+ int pos = 16;
+
+ wd_obs obs;
+
+ for(int track=0; track < tracks; track++) {
+ for(int head=0; head < heads; head++) {
+ UINT8 th[16];
+ io_generic_read(io, th, pos, 16);
+ int entry_len = th[0] | (th[1] << 8) | (th[2] << 16) | (th[3] << 24);
+ int fuzz_len = th[4] | (th[5] << 8) | (th[6] << 16) | (th[7] << 24);
+ int sect = th[8] | (th[9] << 8);
+ int flags = th[10] | (th[11] << 8);
+ int track_len = th[12] | (th[13] << 8);
+ int track_num = th[14];
+ int flags2 = th[15];
+
+ if(entry_len-16 > raw_track_size) {
+ if(raw_track)
+ global_free(raw_track);
+ raw_track_size = entry_len-16;
+ raw_track = global_alloc_array(UINT8, entry_len-16);
+ }
+
+ io_generic_read(io, raw_track, pos+16, entry_len-16);
+
+ UINT8 *fuzz = fuzz_len ? raw_track+16*sect : 0;
+ UINT8 *bdata = fuzz ? fuzz+fuzz_len : raw_track+16*sect;
+ UINT8 *tdata = bdata;
+
+ int syncpos = -1;
+ if(flags & 0x0080) {
+ syncpos = tdata[0] | (tdata[1] << 8);
+ tdata += 2;
+ }
+
+ int tsize = 0;
+ if(flags & 0x0040) {
+ tsize = tdata[0] | (tdata[1] << 8);
+ tdata += 2;
+ } else
+ tdata = 0;
+
+ if(0) {
+ printf("Track %2d.%d: el=%d fl=%d sect=%d flags=%04x tlen=%d/%d tnum=%d flags2=%02x sync=%x\n",
+ track, head,
+ entry_len, fuzz_len, sect, flags, track_len, tsize, track_num, flags2, syncpos);
+ hexdump(raw_track+16*sect, entry_len-16-16*sect);
+ }
+
+ if(0 && tdata) {
+ hexdump(tdata, tsize);
+
+ for(int i=0; i<tsize-8; i++) {
+ if(tdata[i] == 0xa1 && tdata[i+1] == 0xa1 && tdata[i+2] != 0xa1)
+ printf(" header %5d: %02x %02x %02x %02x %02x %02x %02x\n",
+ i+2,
+ tdata[i+2], tdata[i+3], tdata[i+4], tdata[i+5], tdata[i+6], tdata[i+7], tdata[i+8]);
+ }
+ }
+
+ for(int s=0; s<sect; s++) {
+ UINT8 *sh = raw_track+16*s;
+ int s_off = sh[0] | (sh[1] << 8) | (sh[2] << 16) | (sh[3] << 24);
+ int s_pos = sh[4] | (sh[5] << 8);
+ int s_time = sh[6] | (sh[7] << 8);
+ int s_flags = sh[14] | (sh[15] << 8);
+
+ obs.sectors[s].data = bdata + s_off;
+ obs.sectors[s].fuzzy_mask = 0;
+ memcpy(obs.sectors[s].id, sh+8, 6);
+ obs.sectors[s].time_ratio = s_time ? s_time / 16384.0 : 1;
+ obs.sectors[s].position = s_pos/8-12;
+ if(0) {
+ printf(" sector %2d: off=%5d pos=%5d [%02x %02x] time=%04x flags=%04x id=%02x.%02x.%02x.%02x.%02x.%02x\n",
+ s, s_off, s_pos, tdata ? tdata[s_pos/8] : 0x00, tdata ? tdata[s_pos/8+1] : 0x00, s_time, s_flags,
+ sh[8], sh[9], sh[10], sh[11], sh[12], sh[13]);
+ hexdump(bdata+s_off, 128<<(sh[11] & 3));
+ }
+ }
+
+ obs.track_data = tdata;
+ obs.track_size = tsize;
+ obs.sector_count = sect;
+
+ wd_generate_track_from_observations(track, head, image, obs);
+
+ pos += entry_len;
+ }
+ }
+
+ return true;
+}
+
+const floppy_format_type FLOPPY_PASTI_FORMAT = &floppy_image_format_creator<pasti_format>;
+
+
+void pasti_format::wd_generate_track_from_observations(int track, int head, floppy_image *image, wd_obs &obs)
+{
+ if(!obs.track_data)
+ wd_generate_track_from_sectors_only(track, head, image, obs);
+ else
+ wd_generate_track_from_sectors_and_track(track, head, image, obs);
+}
+
+void pasti_format::wd_generate_unsynced_gap(UINT32 *track, int &pos, const wd_obs &obs, int tstart, int tend, UINT32 cell_size)
+{
+ for(int i=tstart; i != tend;) {
+ unsigned char v = obs.track_data[i];
+ int j;
+ for(j=i+1; j != tend && obs.track_data[j] == v; j++);
+ int size = j-i;
+ if(size < 4) {
+ mfm_w(track, pos, 8, v, cell_size);
+ i++;
+ continue;
+ }
+ if(v == 0xff || v == 0x00)
+ v = 0;
+ else if(v == 0x4e || v == 0x21 || v == 0x9c || v == 0x42 || v == 0x39 || v == 0x84 || v == 0x72 || v == 0x09 ||
+ v == 0xe4 || v == 0x12 || v == 0xc9 || v == 0x24 || v == 0x93 || v == 0x48 || v == 0x27 || v == 0x90)
+ v = 0x4e;
+ // Grab the transition byte too
+ if((v == 0 || v == 0x4e) && j != tend)
+ size++;
+ for(j=0; j != size; j++)
+ mfm_w(track, pos, 8, v, cell_size);
+ i += size;
+ }
+}
+
+void pasti_format::wd_generate_synced_gap(UINT32 *track, int &pos, const wd_obs &obs, int tstart, int tend, UINT32 cell_size)
+{
+ for(int i = tstart; i != tend; i++) {
+ unsigned char v = obs.track_data[i];
+ if((v == 0x14 || v == 0xa1 || v == 0xc2) && i+2 < tend && obs.track_data[i+1] == 0xa1 && obs.track_data[i+2] == 0xa1) {
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ i += 2;
+ } else if(pos && i != tend-1 && (((v == 0x14 || v == 0xc2) && (track[pos-1] & 0x1f) == 10) || (v == 0xa1 && (track[pos-1] & 0x1f) != 10)))
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ else if(i != tend-1 && (v == 0x14 || v == 0xc2))
+ raw_w(track, pos, 16, 0x5224, cell_size);
+ else
+ mfm_w(track, pos, 8, v, cell_size);
+ }
+}
+
+void pasti_format::wd_generate_gap(UINT32 *track, int &pos, const wd_obs &obs, int tstart, int tend, bool synced, UINT32 cell_size_start, UINT32 cell_size_end)
+{
+ int spos = pos;
+ if(!synced) {
+ int sync = -1;
+ for(int i = tstart; sync == -1 && i != tend; i++)
+ if(obs.track_data[i] == 0x14 || obs.track_data[i] == 0xa1 || obs.track_data[i] == 0xc2)
+ sync = i;
+ if(sync == -1)
+ sync = tend;
+ wd_generate_unsynced_gap(track, pos, obs, tstart, sync, cell_size_start);
+ tstart = sync;
+ }
+ if(tstart != tend)
+ wd_generate_synced_gap(track, pos, obs, tstart, tend, cell_size_start);
+
+ if(cell_size_end != cell_size_start) {
+ INT32 total_size = 0;
+ for(int i=spos; i != pos; i++)
+ total_size += track[i] & floppy_image::TIME_MASK;
+ INT64 cur_size = 0;
+ for(int i=spos; i != pos; i++) {
+ cur_size += track[i] & floppy_image::TIME_MASK;
+ track[i] = (track[i] & floppy_image::MG_MASK) |
+ (cur_size*int(cell_size_end-cell_size_start)/total_size + cell_size_start);
+ }
+ }
+}
+
+void pasti_format::wd_generate_sector_header(UINT32 *track, int &pos, const wd_obs &obs, int sector, int tstart, UINT32 cell_size)
+{
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ mfm_w(track, pos, 8, obs.track_data[tstart+3], cell_size);
+ for(int i=0; i != 6; i++)
+ mfm_w(track, pos, 8, obs.sectors[sector].id[i], cell_size);
+}
+
+void pasti_format::wd_generate_sector_data(UINT32 *track, int &pos, const wd_obs &obs, int sector, int tstart, UINT32 cell_size)
+{
+ const wd_sect &s = obs.sectors[sector];
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ raw_w(track, pos, 16, 0x4489, cell_size);
+ mfm_w(track, pos, 8, obs.track_data[tstart+3], cell_size);
+ for(int i=0; i<128 << (s.id[3] & 3); i++)
+ mfm_w(track, pos, 8, s.data[i], cell_size);
+ UINT16 crc = calc_crc_ccitt(track, pos - (2048 << (s.id[3] & 3)) - 16*4, pos);
+ mfm_w(track, pos, 8, crc >> 8, cell_size);
+ mfm_w(track, pos, 8, crc, cell_size);
+}
+
+void pasti_format::wd_generate_track_from_sectors_and_track(int track, int head, floppy_image *image, wd_obs &obs)
+{
+ if(0)
+ printf("Track %d head %d sectors %d\n", track, head, obs.sector_count);
+ UINT32 *trackbuf = global_alloc_array(UINT32, 200000);
+ int pos = 0;
+
+ wd_sect_info sect_infos[256];
+
+ if(0)
+ hexdump(obs.track_data, obs.track_size);
+ map_sectors_in_track(obs, sect_infos);
+
+ if(0)
+ for(int i=0; i != obs.sector_count; i++) {
+ wd_sect_info *s = sect_infos + i;
+ printf("%2d: %5d-%5d %c %02x %02x|%02x %02x %5d-%5d %c %02x %02x|%02x %02x %f\n",
+ i,
+ s->hstart, s->hend, s->hsynced ? 'S' : '-',
+ s->hstart == -1 ? 0 : obs.track_data[s->hstart],
+ s->hstart == -1 ? 0 : obs.track_data[s->hstart+1],
+ s->hend == -1 ? 0 : obs.track_data[s->hend],
+ s->hend == -1 ? 0 : obs.track_data[s->hend+1],
+
+ s->dstart, s->dend, s->dsynced ? 'S' : '-',
+ s->dstart == -1 ? 0 : obs.track_data[s->dstart],
+ s->dstart == -1 ? 0 : obs.track_data[s->dstart+1],
+ s->dend == -1 ? 0 : obs.track_data[s->dend],
+ s->dend == -1 ? 0 : obs.track_data[s->dend+1],
+
+ obs.sectors[i].time_ratio);
+ }
+
+ if(obs.sector_count) {
+ wd_sect_info *last = sect_infos + obs.sector_count-1;
+ if(last->dend != -1 && last->dend < last->hstart) {
+ logerror("pasti: Unsupported sector header/data over index, track %d head %d\n", track, head);
+ return;
+ }
+
+ UINT32 cell_size = UINT32(obs.sectors[0].time_ratio * 1000+0.5);
+ wd_generate_gap(trackbuf, pos, obs, 0, sect_infos[0].hstart, false, cell_size, cell_size);
+
+ for(int i=0; i != obs.sector_count; i++) {
+ wd_sect_info *s = sect_infos + i;
+ if(i+1 != obs.sector_count) {
+ if(s->dstart != -1 && s[1].hstart < s->dend) {
+ logerror("pasti: Unsupported sector overlap, track %d head %d\n", track, head);
+ return;
+ }
+ }
+
+ UINT32 ncell_size = UINT32(obs.sectors[i+1 != obs.sector_count ? i+1 : 0].time_ratio * 1000+0.5);
+
+ wd_generate_sector_header(trackbuf, pos, obs, i, s->hstart, cell_size);
+
+ if(s->dstart == -1) {
+ if(i == obs.sector_count-1)
+ wd_generate_gap(trackbuf, pos, obs, s->hend, obs.track_size, s->hsynced, cell_size, ncell_size);
+ else
+ wd_generate_gap(trackbuf, pos, obs, s->hend, s[1].hstart, s->hsynced, cell_size, ncell_size);
+ } else {
+ wd_generate_gap(trackbuf, pos, obs, s->hend, s->dstart, s->hsynced, cell_size, cell_size);
+ wd_generate_sector_data(trackbuf, pos, obs, i, s->dstart, cell_size);
+ if(i == obs.sector_count-1)
+ wd_generate_gap(trackbuf, pos, obs, s->dend, obs.track_size, s->dsynced, cell_size, ncell_size);
+ else
+ wd_generate_gap(trackbuf, pos, obs, s->dend, s[1].hstart, s->dsynced, cell_size, ncell_size);
+ }
+ cell_size = ncell_size;
+ }
+
+ } else
+ wd_generate_gap(trackbuf, pos, obs, 0, obs.track_size, false, 1000, 1000);
+
+ generate_track_from_levels(track, head, trackbuf, pos, 0, image);
+
+ global_free(trackbuf);
+}
+
+void pasti_format::wd_generate_track_from_sectors_only(int track, int head, floppy_image *image, wd_obs &obs)
+{
+ if(0) {
+ printf("Track %d head %d sectors %d\n", track, head, obs.sector_count);
+ for(int i=0; i != obs.sector_count; i++) {
+ const wd_sect &s = obs.sectors[i];
+
+ printf("%2d: %02x.%02x.%02x.%02x.%02x.%02x %d %f\n",
+ i,
+ s.id[0], s.id[1], s.id[2], s.id[3], s.id[4], s.id[5],
+ s.position,
+ s.time_ratio);
+ if(track==10 && i==0)
+ hexdump(s.data, 512);
+ }
+ }
+
+ UINT32 *tdata = global_alloc_array(UINT32, 200000);
+ int pos = 0;
+ for(int i=0; i != obs.sector_count; i++) {
+ const wd_sect &s = obs.sectors[i];
+ if(i+1 != obs.sector_count && obs.sectors[i+1].position < s.position+10+44+4+(128 << (s.id[3] & 3))) {
+ logerror("pasti: Unsupported sector data sharing, track %d head %d\n", track, head);
+ return;
+ }
+ if(pos >> 4 < s.position - 12) {
+ int count = s.position - 12 - (pos >> 4);
+ if(count & 1) {
+ mfm_w(tdata, pos, 8, 0x4e);
+ count--;
+ }
+ for(int j=0; j<count; j+=2)
+ mfm_w(tdata, pos, 8, 0x4e);
+ }
+ if(pos < s.position*16) {
+ int count = s.position - (pos >> 4);
+ if(count & 1) {
+ mfm_w(tdata, pos, 8, 0x00);
+ count--;
+ }
+ for(int j=0; j<count; j+=2)
+ mfm_w(tdata, pos, 8, 0x00);
+ }
+ raw_w(tdata, pos, 16, 0x4489);
+ raw_w(tdata, pos, 16, 0x4489);
+ raw_w(tdata, pos, 16, 0x4489);
+ mfm_w(tdata, pos, 8, 0xfe);
+ for(int j=0; j<6; j++)
+ mfm_w(tdata, pos, 8, s.id[j]);
+
+ if(!s.data)
+ continue;
+
+ for(int j=0; j<22; j++)
+ mfm_w(tdata, pos, 8, 0x4e);
+ for(int j=0; j<12; j++)
+ mfm_w(tdata, pos, 8, 0x00);
+
+ raw_w(tdata, pos, 16, 0x4489);
+ raw_w(tdata, pos, 16, 0x4489);
+ raw_w(tdata, pos, 16, 0x4489);
+ mfm_w(tdata, pos, 8, 0xfb);
+ for(int j=0; j<128 << (s.id[3] & 3); j++)
+ mfm_w(tdata, pos, 8, s.data[j]);
+ UINT16 crc = calc_crc_ccitt(tdata, pos - (2048 << (s.id[3] & 3)) - 16*4, pos);
+ mfm_w(tdata, pos, 8, crc >> 8);
+ mfm_w(tdata, pos, 8, crc);
+ }
+
+ int count = (100015 - pos) >> 16;
+ for(int i=0; i<count; i++)
+ mfm_w(tdata, pos, 8, 0x4e);
+
+ generate_track_from_levels(track, head, tdata, pos, 0, image);
+}
+
+UINT16 pasti_format::byte_to_mfm(UINT8 data, bool context)
+{
+ static const UINT8 expand[32] = {
+ 0xaa, 0xa9, 0xa4, 0xa5, 0x92, 0x91, 0x94, 0x95, 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55,
+ 0x2a, 0x29, 0x24, 0x25, 0x12, 0x11, 0x14, 0x15, 0x4a, 0x49, 0x44, 0x45, 0x52, 0x51, 0x54, 0x55,
+ };
+
+ return (expand[(data >> 4) | (context ? 16 : 0)] << 8) | expand[data & 0x1f];
+}
+
+void pasti_format::match_mfm_data(wd_obs &obs, int tpos, const UINT8 *data, int size, UINT8 context, int &bcount, int &tend, bool &synced)
+{
+ UINT16 shift = byte_to_mfm(context, true);
+ int bc = 0;
+ int bc_phase = 0;
+ int bi = 0;
+ UINT8 dbyte = 0;
+ bool ds_phase = false;
+ UINT16 inshift = byte_to_mfm(data[bi++], shift & 1);
+ synced = false;
+ for(;;) {
+ int bit = (inshift >> (15-bc)) & 1;
+ shift = (shift << 1) | bit;
+ if(ds_phase)
+ dbyte = (dbyte << 1) | bit;
+ // printf(" %04x %02x (%04x %02x)\n", shift, dbyte, inshift, data[bi-1]);
+ ds_phase = !ds_phase;
+ bc++;
+ if(shift == 0x4489 || shift == 0x5224) {
+ bc_phase = 16-bc;
+ ds_phase = false;
+ }
+ if(!((bc_phase + bc) & 15)) {
+ // printf("dbyte=%02x data=%02x in=%02x bc=%d bc_shift=%d ds_phase=%s\n", dbyte, obs.track_data[tpos], data[bi-1], bc, bc_phase, ds_phase ? "on" : "off");
+ if(dbyte != obs.track_data[tpos++]) {
+ bcount = bi-1;
+ tend = tpos-1;
+ return;
+ }
+ if(tpos == obs.track_size)
+ tpos = 0;
+ if(bi == size) {
+ bcount = bi;
+ tend = tpos;
+ synced = bc_phase == 0;
+ return;
+ }
+ }
+ if(bc == 16) {
+ inshift = byte_to_mfm(data[bi++], shift & 1);
+ bc = 0;
+ }
+ }
+}
+
+void pasti_format::match_raw_data(wd_obs &obs, int tpos, const UINT8 *data, int size, UINT8 context, int &bcount, int &tend)
+{
+ tend = tpos;
+ for(bcount=0; bcount != size; bcount++) {
+ if(data[bcount] != obs.track_data[tend])
+ return;
+ tend++;
+ if(tend == obs.track_size)
+ tend = 0;
+ }
+}
+
+UINT16 pasti_format::calc_crc(const UINT8 *data, int size, UINT16 crc1)
+{
+ UINT32 crc = crc1;
+ for(int i=0; i<size; i++) {
+ crc = (crc << 8) ^ (*data++ << 16);
+ if(crc & 0x800000) crc ^= 0x881080;
+ if(crc & 0x400000) crc ^= 0x440840;
+ if(crc & 0x200000) crc ^= 0x220420;
+ if(crc & 0x100000) crc ^= 0x110210;
+ if(crc & 0x080000) crc ^= 0x088108;
+ if(crc & 0x040000) crc ^= 0x044084;
+ if(crc & 0x020000) crc ^= 0x022042;
+ if(crc & 0x010000) crc ^= 0x011021;
+ }
+ return crc;
+}
+
+void pasti_format::map_sectors_in_track(wd_obs &obs, wd_sect_info *sect_infos)
+{
+ for(int i=0; i != obs.sector_count; i++) {
+ sect_infos[i].hstart = -1;
+ sect_infos[i].hend = -1;
+ sect_infos[i].dstart = -1;
+ sect_infos[i].dend = -1;
+ sect_infos[i].hsynced = false;
+ sect_infos[i].dsynced = false;
+ }
+
+ const UINT8 *tdata = obs.track_data;
+ int tsize = obs.track_size;
+
+ for(int i=0; i != tsize; i++)
+ if(tdata[i] == 0xa1 &&
+ tdata[(i+1) % tsize] == 0xa1 &&
+ (tdata[(i+2) % tsize] == 0xfe ||
+ tdata[(i+2) % tsize] == 0xff)) {
+
+ UINT8 hbyte = tdata[(i+2) % tsize];
+ int hpos = (i+3) % tsize;
+ int j;
+ bool synced = false;
+ int bcount, tend;
+ int best_bcount=0, best_j=0;
+ for(j=0; j != obs.sector_count; j++) {
+ match_mfm_data(obs, hpos, obs.sectors[j].id, 6, hbyte, bcount, tend, synced);
+ if(bcount > best_bcount) {
+ best_bcount = bcount;
+ best_j = j;
+ }
+ if(bcount == 6)
+ break;
+ match_raw_data(obs, hpos, obs.sectors[j].id, 6, hbyte, bcount, tend);
+ if(bcount > best_bcount) {
+ best_bcount = bcount;
+ best_j = j;
+ }
+ if(bcount == 6) {
+ synced = true;
+ break;
+ }
+ }
+
+ j = best_j;
+ if(best_bcount < 4) {
+ if(0)
+ printf("sector header at %x no match [%02x %02x %02x %02x %02x %02x]\n", i,
+ tdata[hpos], tdata[hpos+1], tdata[hpos+2], tdata[hpos+3], tdata[hpos+4], tdata[hpos+5]);
+ } else {
+ if(0)
+ printf("sector header at %x matches %d [%02x %02x %02x %02x %02x %02x] [%02x] - %d %s\n", i, j,
+ tdata[hpos], tdata[hpos+1], tdata[hpos+2], tdata[hpos+3], tdata[hpos+4], tdata[hpos+5], tdata[tend],
+ obs.sectors[j].position, synced ? "synced" : "unsynced");
+
+ sect_infos[j].hstart = hpos - 4;
+ sect_infos[j].hend = tend + (6-bcount);
+ sect_infos[j].hsynced = synced;
+
+ int dpos = -1;
+ if(obs.sectors[j].data)
+ for(int j=35; j<45; j++) {
+ if(tdata[(hpos+j) % tsize] == 0xa1 &&
+ tdata[(hpos+j+1) % tsize] == 0xa1 &&
+ tdata[(hpos+j+2) % tsize] >= 0xfa &&
+ tdata[(hpos+j+2) % tsize] <= 0xfd) {
+ dpos = (hpos+j+3) % tsize;
+ break;
+ }
+ }
+ if(dpos != -1) {
+ int bcount2, tend2;
+ UINT8 dhbyte = tdata[(dpos+tsize-1) % tsize];
+ int ssize = 128 << (obs.sectors[j].id[3] & 3);
+ match_mfm_data(obs, dpos, obs.sectors[j].data, ssize, dhbyte, bcount, tend, synced);
+ if(bcount < ssize) {
+ match_raw_data(obs, dpos, obs.sectors[j].data, ssize, dhbyte, bcount2, tend2);
+ if(bcount2 > bcount) {
+ bcount = bcount2;
+ tend = tend2;
+ if(bcount == ssize)
+ synced = true;
+ }
+ }
+ UINT16 crc = calc_crc(obs.sectors[j].data, ssize, calc_crc(tdata+((dpos+tsize-1) % tsize), 1, 0xcdb4));
+ if(synced && tdata[tend] == (crc >> 8) && tdata[(tend+1) % tsize] == (crc & 0xff)) {
+ tend = (tend+2) % tsize;
+ bcount += 2;
+ }
+
+ if(0)
+ printf(" associated data at %d, match %d [%02x %02x %02x] %04x, %s\n", dpos, bcount, tdata[tend], tdata[tend+1], tdata[tend+2], crc, synced ? "synced" : "unsynced");
+
+ sect_infos[j].dstart = dpos - 4;
+ sect_infos[j].dend = tend + (ssize+2-bcount);
+ sect_infos[j].dsynced = synced;
+
+ }
+ }
+ }
+
+}
diff --git a/src/lib/formats/pasti_dsk.h b/src/lib/formats/pasti_dsk.h
new file mode 100644
index 00000000000..1fc47d5ac33
--- /dev/null
+++ b/src/lib/formats/pasti_dsk.h
@@ -0,0 +1,62 @@
+#ifndef PASTI_DSK_H_
+#define PASTI_DSK_H_
+
+#include "flopimg.h"
+
+class pasti_format : public floppy_image_format_t
+{
+public:
+ pasti_format();
+
+ virtual int identify(io_generic *io);
+ virtual bool load(io_generic *io, floppy_image *image);
+
+ virtual const char *name() const;
+ virtual const char *description() const;
+ virtual const char *extensions() const;
+ virtual bool supports_save() const;
+
+ static const desc_e xdesc[];
+
+protected:
+ struct wd_sect {
+ const UINT8 *data;
+ const UINT8 *fuzzy_mask;
+ UINT8 id[6];
+ int position;
+ double time_ratio;
+ };
+
+ struct wd_obs {
+ const UINT8 *track_data;
+ wd_sect sectors[256];
+ int track_size, sector_count;
+ };
+
+ void wd_generate_track_from_observations(int track, int head, floppy_image *image, wd_obs &obs);
+
+private:
+ struct wd_sect_info {
+ int hstart, hend;
+ int dstart, dend;
+ bool hsynced, dsynced;
+ };
+
+ void map_sectors_in_track(wd_obs &obs, wd_sect_info *sect_infos);
+ void match_mfm_data(wd_obs &obs, int tpos, const UINT8 *data, int size, UINT8 context, int &bcount, int &ccount, bool &synced);
+ void match_raw_data(wd_obs &obs, int tpos, const UINT8 *data, int size, UINT8 context, int &bcount, int &ccount);
+ UINT16 byte_to_mfm(UINT8 data, bool context);
+ UINT16 calc_crc(const UINT8 *data, int size, UINT16 crc);
+
+ void wd_generate_unsynced_gap(UINT32 *track, int &pos, const wd_obs &obs, int tstart, int tend, UINT32 cell_size);
+ void wd_generate_synced_gap(UINT32 *track, int &pos, const wd_obs &obs, int tstart, int tend, UINT32 cell_size);
+ void wd_generate_gap(UINT32 *track, int &pos, const wd_obs &obs, int tstart, int tend, bool synced, UINT32 cell_size_start, UINT32 cell_size_end);
+ void wd_generate_sector_header(UINT32 *track, int &pos, const wd_obs &obs, int sector, int tstart, UINT32 cell_size);
+ void wd_generate_sector_data(UINT32 *track, int &pos, const wd_obs &obs, int sector, int tstart, UINT32 cell_size);
+ void wd_generate_track_from_sectors_and_track(int track, int head, floppy_image *image, wd_obs &obs);
+ void wd_generate_track_from_sectors_only(int track, int head, floppy_image *image, wd_obs &obs);
+};
+
+extern const floppy_format_type FLOPPY_PASTI_FORMAT;
+
+#endif /*PASTI_DSK_H_*/
diff --git a/src/lib/lib.mak b/src/lib/lib.mak
index 6b0b179d8fe..b09a8b748c3 100644
--- a/src/lib/lib.mak
+++ b/src/lib/lib.mak
@@ -129,6 +129,7 @@ FORMATSOBJS = \
$(LIBOBJ)/formats/oric_dsk.o \
$(LIBOBJ)/formats/oric_tap.o \
$(LIBOBJ)/formats/p6001_cas.o \
+ $(LIBOBJ)/formats/pasti_dsk.o \
$(LIBOBJ)/formats/pc_dsk.o \
$(LIBOBJ)/formats/pmd_pmd.o \
$(LIBOBJ)/formats/primoptp.o \
diff --git a/src/osd/osdnet.c b/src/osd/osdnet.c
index 2df27d6cde5..21c8774ea03 100644
--- a/src/osd/osdnet.c
+++ b/src/osd/osdnet.c
@@ -1,22 +1,16 @@
#include "emu.h"
#include "osdnet.h"
-typedef struct netdev_entry
-{
- int id;
- char name[256];
- create_netdev func;
- struct netdev_entry *m_next;
-} netdev_entry_t;
-
static class simple_list<netdev_entry_t> netdev_list;
-void add_netdev(const char *name, create_netdev func)
+void add_netdev(const char *name, const char *description, create_netdev func)
{
netdev_entry_t *entry = global_alloc_clear(netdev_entry_t);
entry->id = netdev_list.count();
strncpy(entry->name, name, 255);
entry->name[255] = '\0';
+ strncpy(entry->description, description, 255);
+ entry->description[255] = '\0';
entry->func = func;
netdev_list.append(*entry);
}
@@ -26,6 +20,10 @@ void clear_netdev()
netdev_list.reset();
}
+const netdev_entry_t *netdev_first() {
+ return netdev_list.first();
+}
+
class netdev *open_netdev(int id, class device_network_interface *ifdev, int rate)
{
netdev_entry_t *entry = netdev_list.first();
@@ -97,3 +95,7 @@ const char *netdev::get_mac()
return "\0\0\0\0\0\0";
}
+int netdev_count()
+{
+ return netdev_list.count();
+}
diff --git a/src/osd/osdnet.h b/src/osd/osdnet.h
index aca6f75b5e4..74c75c3781a 100644
--- a/src/osd/osdnet.h
+++ b/src/osd/osdnet.h
@@ -3,6 +3,20 @@
#ifndef __OSDNET_H__
#define __OSDNET_H__
+class netdev;
+
+#define CREATE_NETDEV(name) class netdev *name(const char *ifname, class device_network_interface *ifdev, int rate)
+typedef class netdev *(*create_netdev)(const char *ifname, class device_network_interface *ifdev, int rate);
+
+typedef struct netdev_entry
+{
+ int id;
+ char name[256];
+ char description[256];
+ create_netdev func;
+ struct netdev_entry *m_next;
+} netdev_entry_t;
+
class netdev
{
public:
@@ -25,10 +39,9 @@ private:
class device_network_interface *m_dev;
};
-#define CREATE_NETDEV(name) class netdev *name(const char *ifname, class device_network_interface *ifdev, int rate)
-typedef class netdev *(*create_netdev)(const char *ifname, class device_network_interface *ifdev, int rate);
-
class netdev *open_netdev(int id, class device_network_interface *ifdev, int rate);
-void add_netdev(const char *name, create_netdev func);
+void add_netdev(const char *name, const char *description, create_netdev func);
void clear_netdev();
+const netdev_entry_t *netdev_first();
+int netdev_count();
#endif
diff --git a/src/osd/sdl/netdev_pcap.c b/src/osd/sdl/netdev_pcap.c
index ef74a2e02c6..f8ae41853f5 100644
--- a/src/osd/sdl/netdev_pcap.c
+++ b/src/osd/sdl/netdev_pcap.c
@@ -88,7 +88,7 @@ void init_pcap()
{
while(devs->next)
{
- add_netdev(devs->name, create_pcap);
+ add_netdev(devs->name, devs->description, create_pcap);
devs = devs->next;
}
}
diff --git a/src/osd/sdl/netdev_tap.c b/src/osd/sdl/netdev_tap.c
index cc68c97c229..3e024a4285a 100644
--- a/src/osd/sdl/netdev_tap.c
+++ b/src/osd/sdl/netdev_tap.c
@@ -94,7 +94,7 @@ static CREATE_NETDEV(create_tap)
void init_tap()
{
- add_netdev("tap", create_tap);
+ add_netdev("tap", "TAP/TUN Device", create_tap);
}
void deinit_tap()
diff --git a/src/osd/windows/netdev_pcap.c b/src/osd/windows/netdev_pcap.c
index 02887f3a831..d3d0b113609 100644
--- a/src/osd/windows/netdev_pcap.c
+++ b/src/osd/windows/netdev_pcap.c
@@ -127,7 +127,7 @@ void init_pcap()
{
while(devs->next)
{
- add_netdev(devs->name, create_pcap);
+ add_netdev(devs->name, devs->description, create_pcap);
devs = devs->next;
}
}