From e5a474fa397f150f3d93cbda22285d0fddc83a8b Mon Sep 17 00:00:00 2001 From: etabeta78 Date: Wed, 14 Jan 2015 07:48:38 +0100 Subject: ui: split code for input mapping and slot option menus from miscmenu. nw. --- src/emu/emu.mak | 8 +- src/emu/ui/inputmap.c | 946 +++++++++++++++++++++++++++++++++++++++++ src/emu/ui/inputmap.h | 156 +++++++ src/emu/ui/mainmenu.c | 6 +- src/emu/ui/miscmenu.c | 1109 ------------------------------------------------- src/emu/ui/miscmenu.h | 154 ------- src/emu/ui/selgame.c | 1 + src/emu/ui/slotopt.c | 199 +++++++++ src/emu/ui/slotopt.h | 36 ++ 9 files changed, 1347 insertions(+), 1268 deletions(-) create mode 100644 src/emu/ui/inputmap.c create mode 100644 src/emu/ui/inputmap.h create mode 100644 src/emu/ui/slotopt.c create mode 100644 src/emu/ui/slotopt.h diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 37c0631fb44..71d20b40168 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -116,16 +116,18 @@ EMUOBJS = \ $(EMUOBJ)/timer.o \ $(EMUOBJ)/uiinput.o \ $(EMUOBJ)/ui/ui.o \ - $(EMUOBJ)/ui/swlist.o \ $(EMUOBJ)/ui/menu.o \ $(EMUOBJ)/ui/mainmenu.o \ $(EMUOBJ)/ui/miscmenu.o \ - $(EMUOBJ)/ui/selgame.o \ + $(EMUOBJ)/ui/barcode.o \ $(EMUOBJ)/ui/filemngr.o \ $(EMUOBJ)/ui/filesel.o \ $(EMUOBJ)/ui/imgcntrl.o \ $(EMUOBJ)/ui/imginfo.o \ - $(EMUOBJ)/ui/barcode.o \ + $(EMUOBJ)/ui/inputmap.o \ + $(EMUOBJ)/ui/selgame.o \ + $(EMUOBJ)/ui/slotopt.o \ + $(EMUOBJ)/ui/swlist.o \ $(EMUOBJ)/ui/tapectrl.o \ $(EMUOBJ)/ui/viewgfx.o \ $(EMUOBJ)/validity.o \ diff --git a/src/emu/ui/inputmap.c b/src/emu/ui/inputmap.c new file mode 100644 index 00000000000..e949a48deaa --- /dev/null +++ b/src/emu/ui/inputmap.c @@ -0,0 +1,946 @@ +/********************************************************************* + + ui/inputmap.c + + Internal menus for input mappings. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +*********************************************************************/ + +#include "emu.h" + +#include "uiinput.h" +#include "ui/ui.h" +#include "ui/inputmap.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) + + + +/*------------------------------------------------- + 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 = machine().ioport().first_type(); 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; + if(pollingitem && pollingref == entry && pollingseq == seqtype) + pollingitem = item; + item->seqtype = seqtype; + item->seq = machine().ioport().type_seq(entry->type(), entry->player(), seqtype); + item->defseq = &entry->defseq(seqtype); + item->sortorder = sortorder * 4 + suborder[seqtype]; + item->type = ioport_manager::type_is_analog(entry->type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; + item->name = entry->name(); + item->owner_name = NULL; + 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; + ioport_field *field; + ioport_port *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().ioport().first_port(); port != NULL; port = port->next()) + for (field = port->first_field(); field != NULL; field = field->next()) + { + const char *name = field->name(); + + /* add if we match the group and we have a valid name */ + if (name != NULL && field->enabled() && + ((field->type() == IPT_OTHER && field->name() != NULL) || machine().ioport().type_group(field->type(), field->player()) != IPG_INVALID)) + { + input_seq_type seqtype; + UINT32 sortorder; + + /* determine the sorting order */ + if (field->type() >= IPT_START1 && field->type() < IPT_ANALOG_LAST) + { + sortorder = (field->type() << 2) | (field->player() << 12); + if (strcmp(field->device().tag(), ":")) + sortorder |= 0x10000; + } + 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; + if(pollingitem && pollingref == field && pollingseq == seqtype) + pollingitem = item; + item->seq = field->seq(seqtype); + item->defseq = &field->defseq(seqtype); + item->sortorder = sortorder + suborder[seqtype]; + item->type = field->is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; + item->name = name; + item->owner_name = field->device().tag(); + 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) +{ + pollingitem = 0; + pollingref = 0; + pollingseq = SEQ_TYPE_STANDARD; +} + +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(); +} + +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; + pollingseq = pollingitem->seqtype; + } + 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; + machine().ioport().set_type_seq(entry->type(), entry->player(), seqchangeditem->seqtype, seqchangeditem->seq); +} + +void ui_menu_input_specific::update_input(struct input_item_data *seqchangeditem) +{ + ioport_field::user_settings settings; + + ((ioport_field *)seqchangeditem->ref)->get_user_settings(settings); + settings.seq[seqchangeditem->seqtype] = seqchangeditem->seq; + ((ioport_field *)seqchangeditem->ref)->set_user_settings(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 text; + astring subtext; + astring prev_owner; + bool first_entry = true; + + /* 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); + + if (strcmp(item->owner_name, prev_owner.cstr()) != 0) + { + if (first_entry) + first_entry = false; + else + item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); + text.printf("[root%s]", item->owner_name); + item_append(text, NULL, 0, NULL); + prev_owner.cpy(item->owner_name); + } + + 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) +{ +} + +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) + { + // reset + if ((FPTR)menu_event->itemref == 1) + { + if (menu_event->iptkey == IPT_UI_SELECT) + machine().schedule_hard_reset(); + } + // actual settings + else + { + ioport_field *field = (ioport_field *)menu_event->itemref; + ioport_field::user_settings settings; + int changed = false; + + switch (menu_event->iptkey) + { + /* if selected, reset to default value */ + case IPT_UI_SELECT: + field->get_user_settings(settings); + settings.value = field->defvalue(); + field->set_user_settings(settings); + changed = true; + break; + + /* left goes to previous setting */ + case IPT_UI_LEFT: + field->select_previous_setting(); + changed = true; + break; + + /* right goes to next setting */ + case IPT_UI_RIGHT: + field->select_next_setting(); + 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() +{ + ioport_field *field; + ioport_port *port; + dip_descriptor **diplist_tailptr; + astring prev_owner; + bool first_entry = true; + + /* 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().ioport().first_port(); port != NULL; port = port->next()) + for (field = port->first_field(); field != NULL; field = field->next()) + if (field->type() == type && field->enabled()) + { + UINT32 flags = 0; + astring name; + + /* set the left/right flags appropriately */ + if (field->has_previous_setting()) + flags |= MENU_FLAG_LEFT_ARROW; + if (field->has_next_setting()) + flags |= MENU_FLAG_RIGHT_ARROW; + + /* add the menu item */ + if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) + { + if (first_entry) + first_entry = false; + else + item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); + name.printf("[root%s]", field->device().tag()); + item_append(name, NULL, 0, NULL); + prev_owner.cpy(field->device().tag()); + } + + name.cpy(field->name()); + + item_append(name, field->setting_name(), flags, (void *)field); + + /* for DIP switches, build up the model */ + if (type == IPT_DIPSWITCH && field->first_diplocation() != NULL) + { + const ioport_diplocation *diploc; + ioport_field::user_settings settings; + UINT32 accummask = field->mask(); + + /* get current settings */ + field->get_user_settings(settings); + + /* iterate over each bit in the field */ + for (diploc = field->first_diplocation(); 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->name()) == 0) + break; + + /* allocate new if none */ + if (dip == NULL) + { + dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip)); + dip->next = NULL; + dip->name = diploc->name(); + dip->mask = dip->state = 0; + *diplist_tailptr = dip; + diplist_tailptr = &dip->next; + dipcount++; + } + + /* apply the bits */ + dip->mask |= 1 << (diploc->number() - 1); + if (((settings.value & mask) != 0 && !diploc->inverted()) || ((settings.value & mask) == 0 && diploc->inverted())) + dip->state |= 1 << (diploc->number() - 1); + + /* clear the relevant bit in the accumulated mask */ + accummask &= ~mask; + } + } + } + if (type == IPT_DIPSWITCH) + custombottom = dipcount ? dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING : 0; + + item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); + item_append("Reset", NULL, 0, (void *)1); +} + +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) +{ + // catch if no diploc has to be drawn + if (bottom == 0) + return; + + // add borders + y1 = y2 + UI_BOX_TB_BORDER; + y2 = y1 + bottom; + + // draw extra menu area + machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); + y1 += (float)DIP_SWITCH_SPACING; + + // iterate over DIP switches + for (dip_descriptor *dip = diplist; dip != NULL; dip = dip->next) + { + const ioport_diplocation *diploc; + UINT32 selectedmask = 0; + + // determine the mask of selected bits + if ((FPTR)selectedref != 1) + { + ioport_field *field = (ioport_field *)selectedref; + + if (field != NULL && field->first_diplocation() != NULL) + for (diploc = field->first_diplocation(); diploc != NULL; diploc = diploc->next()) + if (strcmp(dip->name, diploc->name()) == 0) + selectedmask |= 1 << (diploc->number() - 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 */ + machine().ui().draw_text_full( container, + dip->name, + 0, + y1 + (DIP_SWITCH_HEIGHT - UI_TARGET_FONT_HEIGHT) / 2, + x1 - machine().ui().get_string_width(" "), + 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 */ + machine().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) + { + ioport_field::user_settings settings; + + /* get the settings and set the new value */ + data->field->get_user_settings(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; + } + data->field->set_user_settings(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() +{ + ioport_field *field; + ioport_port *port; + astring text; + astring subtext; + astring prev_owner; + bool first_entry = true; + + /* loop over input ports and add the items */ + for (port = machine().ioport().first_port(); port != NULL; port = port->next()) + for (field = port->first_field(); field != NULL; field = field->next()) + if (field->is_analog() && field->enabled()) + { + ioport_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->analog_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; + + default: + break; + } + + /* get the user settings */ + field->get_user_settings(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; + astring name; + if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) + { + if (first_entry) + first_entry = false; + else + item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); + name.printf("[root%s]", field->device().tag()); + item_append(name, NULL, 0, NULL); + prev_owner.cpy(field->device().tag()); + } + + name.cpy(field->name()); + + /* 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", name.cstr()); + 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", name.cstr()); + 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", name.cstr()); + subtext.cpy(settings.reverse ? "On" : "Off"); + data->min = 0; + data->max = 1; + data->cur = settings.reverse; + data->defvalue = field->analog_reverse(); + break; + + case ANALOG_ITEM_SENSITIVITY: + text.printf("%s Sensitivity", name.cstr()); + 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() +{ +} diff --git a/src/emu/ui/inputmap.h b/src/emu/ui/inputmap.h new file mode 100644 index 00000000000..2759b3adabc --- /dev/null +++ b/src/emu/ui/inputmap.h @@ -0,0 +1,156 @@ +/*************************************************************************** + + ui/inputmap.h + + Internal menus for input mappings. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#pragma once + +#ifndef __UI_INPUTMAP_H__ +#define __UI_INPUTMAP_H__ + +//#include "drivenum.h" + +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 */ + const char * owner_name; /* pointer to the name of the owner of the item */ + UINT32 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); + +protected: + const void * pollingref; + input_seq_type pollingseq; + input_item_data * pollingitem; + +private: + UINT16 last_sortorder; + 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 { + ioport_field *field; + int type; + int min, max; + int cur; + int defvalue; + }; +}; + +#endif /* __UI_INPUTMAP_H__ */ diff --git a/src/emu/ui/mainmenu.c b/src/emu/ui/mainmenu.c index c0cd67e27f1..90418814e21 100644 --- a/src/emu/ui/mainmenu.c +++ b/src/emu/ui/mainmenu.c @@ -19,11 +19,13 @@ #include "ui/filemngr.h" #include "ui/filesel.h" #include "ui/barcode.h" -#include "ui/tapectrl.h" +#include "ui/imginfo.h" +#include "ui/inputmap.h" #include "ui/mainmenu.h" #include "ui/miscmenu.h" -#include "ui/imginfo.h" #include "ui/selgame.h" +#include "ui/slotopt.h" +#include "ui/tapectrl.h" #include "audit.h" #include "crsshair.h" #include diff --git a/src/emu/ui/miscmenu.c b/src/emu/ui/miscmenu.c index f4b83ea6273..bd3b2812e27 100644 --- a/src/emu/ui/miscmenu.c +++ b/src/emu/ui/miscmenu.c @@ -24,23 +24,6 @@ #include "ui/filemngr.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 @@ -107,189 +90,6 @@ void ui_menu_keyboard_mode::handle() } -/*------------------------------------------------- - ui_slot_get_current_option - returns --------------------------------------------------*/ -device_slot_option *ui_menu_slot_devices::slot_get_current_option(device_slot_interface *slot) -{ - const char *current; - if (slot->fixed()) - { - current = slot->default_option(); - } - else - { - astring temp; - current = machine().options().main_value(temp, slot->device().tag() + 1); - } - - return slot->option(current); -} - -/*------------------------------------------------- - ui_slot_get_current_index - returns --------------------------------------------------*/ -int ui_menu_slot_devices::slot_get_current_index(device_slot_interface *slot) -{ - const device_slot_option *current = slot_get_current_option(slot); - - if (current != NULL) - { - int val = 0; - for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) - { - if (option == current) - return val; - - if (option->selectable()) - val++; - } - } - - return -1; -} - -/*------------------------------------------------- - ui_slot_get_length - returns --------------------------------------------------*/ -int ui_menu_slot_devices::slot_get_length(device_slot_interface *slot) -{ - int val = 0; - for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) - if (option->selectable()) - 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); - if (idx < 0) - idx = 0; - else - idx++; - - if (idx >= slot_get_length(slot)) - return ""; - - return slot_get_option(slot, idx); -} - -/*------------------------------------------------- - 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); - if (idx < 0) - idx = slot_get_length(slot) - 1; - else - idx--; - - if (idx < 0) - return ""; - - return slot_get_option(slot, idx); -} - -/*------------------------------------------------- - ui_slot_get_option - returns --------------------------------------------------*/ -const char *ui_menu_slot_devices::slot_get_option(device_slot_interface *slot, int index) -{ - if (index >= 0) - { - int val = 0; - for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) - { - if (val == index) - return option->name(); - - if (option->selectable()) - val++; - } - } - - return ""; -} - - -/*------------------------------------------------- - 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()+1, 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() -{ - /* cycle through all devices for this system */ - slot_interface_iterator iter(machine().root_device()); - for (device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) - { - /* record the menu item */ - const device_slot_option *option = slot_get_current_option(slot); - astring opt_name; - if (option == NULL) - opt_name.cpy("------"); - else - { - opt_name.cpy(option->name()); - if (slot->fixed() || slot_get_length(slot) == 0) - opt_name.cat(" [internal]"); - } - - item_append(slot->device().tag() + 1, opt_name, (slot->fixed() || slot_get_length(slot) == 0) ? 0 : (MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW), (void *)slot); - } - item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); - item_append("Reset", NULL, 0, (void *)1); -} - -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 ((FPTR)menu_event->itemref == 1 && menu_event->iptkey == IPT_UI_SELECT) - machine().schedule_hard_reset(); - else 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); - } - } -} - /*------------------------------------------------- ui_menu_bios_selection - populates the main bios selection menu @@ -426,915 +226,6 @@ void ui_menu_network_devices::handle() } } -/*------------------------------------------------- - 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 = machine().ioport().first_type(); 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; - if(pollingitem && pollingref == entry && pollingseq == seqtype) - pollingitem = item; - item->seqtype = seqtype; - item->seq = machine().ioport().type_seq(entry->type(), entry->player(), seqtype); - item->defseq = &entry->defseq(seqtype); - item->sortorder = sortorder * 4 + suborder[seqtype]; - item->type = ioport_manager::type_is_analog(entry->type()) ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; - item->name = entry->name(); - item->owner_name = NULL; - 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; - ioport_field *field; - ioport_port *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().ioport().first_port(); port != NULL; port = port->next()) - for (field = port->first_field(); field != NULL; field = field->next()) - { - const char *name = field->name(); - - /* add if we match the group and we have a valid name */ - if (name != NULL && field->enabled() && - ((field->type() == IPT_OTHER && field->name() != NULL) || machine().ioport().type_group(field->type(), field->player()) != IPG_INVALID)) - { - input_seq_type seqtype; - UINT32 sortorder; - - /* determine the sorting order */ - if (field->type() >= IPT_START1 && field->type() < IPT_ANALOG_LAST) - { - sortorder = (field->type() << 2) | (field->player() << 12); - if (strcmp(field->device().tag(), ":")) - sortorder |= 0x10000; - } - 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; - if(pollingitem && pollingref == field && pollingseq == seqtype) - pollingitem = item; - item->seq = field->seq(seqtype); - item->defseq = &field->defseq(seqtype); - item->sortorder = sortorder + suborder[seqtype]; - item->type = field->is_analog() ? (INPUT_TYPE_ANALOG + seqtype) : INPUT_TYPE_DIGITAL; - item->name = name; - item->owner_name = field->device().tag(); - 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) -{ - pollingitem = 0; - pollingref = 0; - pollingseq = SEQ_TYPE_STANDARD; -} - -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(); -} - -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; - pollingseq = pollingitem->seqtype; - } - 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; - machine().ioport().set_type_seq(entry->type(), entry->player(), seqchangeditem->seqtype, seqchangeditem->seq); -} - -void ui_menu_input_specific::update_input(struct input_item_data *seqchangeditem) -{ - ioport_field::user_settings settings; - - ((ioport_field *)seqchangeditem->ref)->get_user_settings(settings); - settings.seq[seqchangeditem->seqtype] = seqchangeditem->seq; - ((ioport_field *)seqchangeditem->ref)->set_user_settings(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 text; - astring subtext; - astring prev_owner; - bool first_entry = true; - - /* 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); - - if (strcmp(item->owner_name, prev_owner.cstr()) != 0) - { - if (first_entry) - first_entry = false; - else - item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); - text.printf("[root%s]", item->owner_name); - item_append(text, NULL, 0, NULL); - prev_owner.cpy(item->owner_name); - } - - 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) -{ -} - -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) - { - // reset - if ((FPTR)menu_event->itemref == 1) - { - if (menu_event->iptkey == IPT_UI_SELECT) - machine().schedule_hard_reset(); - } - // actual settings - else - { - ioport_field *field = (ioport_field *)menu_event->itemref; - ioport_field::user_settings settings; - int changed = false; - - switch (menu_event->iptkey) - { - /* if selected, reset to default value */ - case IPT_UI_SELECT: - field->get_user_settings(settings); - settings.value = field->defvalue(); - field->set_user_settings(settings); - changed = true; - break; - - /* left goes to previous setting */ - case IPT_UI_LEFT: - field->select_previous_setting(); - changed = true; - break; - - /* right goes to next setting */ - case IPT_UI_RIGHT: - field->select_next_setting(); - 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() -{ - ioport_field *field; - ioport_port *port; - dip_descriptor **diplist_tailptr; - astring prev_owner; - bool first_entry = true; - - /* 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().ioport().first_port(); port != NULL; port = port->next()) - for (field = port->first_field(); field != NULL; field = field->next()) - if (field->type() == type && field->enabled()) - { - UINT32 flags = 0; - astring name; - - /* set the left/right flags appropriately */ - if (field->has_previous_setting()) - flags |= MENU_FLAG_LEFT_ARROW; - if (field->has_next_setting()) - flags |= MENU_FLAG_RIGHT_ARROW; - - /* add the menu item */ - if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) - { - if (first_entry) - first_entry = false; - else - item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); - name.printf("[root%s]", field->device().tag()); - item_append(name, NULL, 0, NULL); - prev_owner.cpy(field->device().tag()); - } - - name.cpy(field->name()); - - item_append(name, field->setting_name(), flags, (void *)field); - - /* for DIP switches, build up the model */ - if (type == IPT_DIPSWITCH && field->first_diplocation() != NULL) - { - const ioport_diplocation *diploc; - ioport_field::user_settings settings; - UINT32 accummask = field->mask(); - - /* get current settings */ - field->get_user_settings(settings); - - /* iterate over each bit in the field */ - for (diploc = field->first_diplocation(); 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->name()) == 0) - break; - - /* allocate new if none */ - if (dip == NULL) - { - dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip)); - dip->next = NULL; - dip->name = diploc->name(); - dip->mask = dip->state = 0; - *diplist_tailptr = dip; - diplist_tailptr = &dip->next; - dipcount++; - } - - /* apply the bits */ - dip->mask |= 1 << (diploc->number() - 1); - if (((settings.value & mask) != 0 && !diploc->inverted()) || ((settings.value & mask) == 0 && diploc->inverted())) - dip->state |= 1 << (diploc->number() - 1); - - /* clear the relevant bit in the accumulated mask */ - accummask &= ~mask; - } - } - } - if (type == IPT_DIPSWITCH) - custombottom = dipcount ? dipcount * (DIP_SWITCH_HEIGHT + DIP_SWITCH_SPACING) + DIP_SWITCH_SPACING : 0; - - item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); - item_append("Reset", NULL, 0, (void *)1); -} - -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) -{ - // catch if no diploc has to be drawn - if (bottom == 0) - return; - - // add borders - y1 = y2 + UI_BOX_TB_BORDER; - y2 = y1 + bottom; - - // draw extra menu area - machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - y1 += (float)DIP_SWITCH_SPACING; - - // iterate over DIP switches - for (dip_descriptor *dip = diplist; dip != NULL; dip = dip->next) - { - const ioport_diplocation *diploc; - UINT32 selectedmask = 0; - - // determine the mask of selected bits - if ((FPTR)selectedref != 1) - { - ioport_field *field = (ioport_field *)selectedref; - - if (field != NULL && field->first_diplocation() != NULL) - for (diploc = field->first_diplocation(); diploc != NULL; diploc = diploc->next()) - if (strcmp(dip->name, diploc->name()) == 0) - selectedmask |= 1 << (diploc->number() - 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 */ - machine().ui().draw_text_full( container, - dip->name, - 0, - y1 + (DIP_SWITCH_HEIGHT - UI_TARGET_FONT_HEIGHT) / 2, - x1 - machine().ui().get_string_width(" "), - 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 */ - machine().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) - { - ioport_field::user_settings settings; - - /* get the settings and set the new value */ - data->field->get_user_settings(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; - } - data->field->set_user_settings(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() -{ - ioport_field *field; - ioport_port *port; - astring text; - astring subtext; - astring prev_owner; - bool first_entry = true; - - /* loop over input ports and add the items */ - for (port = machine().ioport().first_port(); port != NULL; port = port->next()) - for (field = port->first_field(); field != NULL; field = field->next()) - if (field->is_analog() && field->enabled()) - { - ioport_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->analog_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; - - default: - break; - } - - /* get the user settings */ - field->get_user_settings(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; - astring name; - if (strcmp(field->device().tag(), prev_owner.cstr()) != 0) - { - if (first_entry) - first_entry = false; - else - item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); - name.printf("[root%s]", field->device().tag()); - item_append(name, NULL, 0, NULL); - prev_owner.cpy(field->device().tag()); - } - - name.cpy(field->name()); - - /* 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", name.cstr()); - 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", name.cstr()); - 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", name.cstr()); - subtext.cpy(settings.reverse ? "On" : "Off"); - data->min = 0; - data->max = 1; - data->cur = settings.reverse; - data->defvalue = field->analog_reverse(); - break; - - case ANALOG_ITEM_SENSITIVITY: - text.printf("%s Sensitivity", name.cstr()); - 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 diff --git a/src/emu/ui/miscmenu.h b/src/emu/ui/miscmenu.h index a0dfbb003d1..dc4898bb920 100644 --- a/src/emu/ui/miscmenu.h +++ b/src/emu/ui/miscmenu.h @@ -25,23 +25,6 @@ public: 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: - device_slot_option *slot_get_current_option(device_slot_interface *slot); - 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 *slot_get_option(device_slot_interface *slot, int index); - 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); @@ -50,143 +33,6 @@ public: 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 */ - const char * owner_name; /* pointer to the name of the owner of the item */ - UINT32 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); - -protected: - const void * pollingref; - input_seq_type pollingseq; - input_item_data * pollingitem; - -private: - UINT16 last_sortorder; - 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 { - ioport_field *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); diff --git a/src/emu/ui/selgame.c b/src/emu/ui/selgame.c index 0d2b76c7d27..ac35d0b0dae 100644 --- a/src/emu/ui/selgame.c +++ b/src/emu/ui/selgame.c @@ -17,6 +17,7 @@ #include "cheat.h" #include "uiinput.h" #include "ui/selgame.h" +#include "ui/inputmap.h" #include "ui/miscmenu.h" #include "audit.h" #include "crsshair.h" diff --git a/src/emu/ui/slotopt.c b/src/emu/ui/slotopt.c new file mode 100644 index 00000000000..e7258897130 --- /dev/null +++ b/src/emu/ui/slotopt.c @@ -0,0 +1,199 @@ +/********************************************************************* + + ui/slotopt.c + + Internal menu for the slot options. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +*********************************************************************/ + +#include "emu.h" + +#include "ui/ui.h" +#include "ui/slotopt.h" + + +/*------------------------------------------------- + ui_slot_get_current_option - returns +-------------------------------------------------*/ +device_slot_option *ui_menu_slot_devices::slot_get_current_option(device_slot_interface *slot) +{ + const char *current; + if (slot->fixed()) + { + current = slot->default_option(); + } + else + { + astring temp; + current = machine().options().main_value(temp, slot->device().tag() + 1); + } + + return slot->option(current); +} + +/*------------------------------------------------- + ui_slot_get_current_index - returns +-------------------------------------------------*/ +int ui_menu_slot_devices::slot_get_current_index(device_slot_interface *slot) +{ + const device_slot_option *current = slot_get_current_option(slot); + + if (current != NULL) + { + int val = 0; + for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) + { + if (option == current) + return val; + + if (option->selectable()) + val++; + } + } + + return -1; +} + +/*------------------------------------------------- + ui_slot_get_length - returns +-------------------------------------------------*/ +int ui_menu_slot_devices::slot_get_length(device_slot_interface *slot) +{ + int val = 0; + for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) + if (option->selectable()) + 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); + if (idx < 0) + idx = 0; + else + idx++; + + if (idx >= slot_get_length(slot)) + return ""; + + return slot_get_option(slot, idx); +} + +/*------------------------------------------------- + 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); + if (idx < 0) + idx = slot_get_length(slot) - 1; + else + idx--; + + if (idx < 0) + return ""; + + return slot_get_option(slot, idx); +} + +/*------------------------------------------------- + ui_slot_get_option - returns +-------------------------------------------------*/ +const char *ui_menu_slot_devices::slot_get_option(device_slot_interface *slot, int index) +{ + if (index >= 0) + { + int val = 0; + for (const device_slot_option *option = slot->first_option(); option != NULL; option = option->next()) + { + if (val == index) + return option->name(); + + if (option->selectable()) + val++; + } + } + + return ""; +} + + +/*------------------------------------------------- + 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()+1, 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() +{ + /* cycle through all devices for this system */ + slot_interface_iterator iter(machine().root_device()); + for (device_slot_interface *slot = iter.first(); slot != NULL; slot = iter.next()) + { + /* record the menu item */ + const device_slot_option *option = slot_get_current_option(slot); + astring opt_name; + if (option == NULL) + opt_name.cpy("------"); + else + { + opt_name.cpy(option->name()); + if (slot->fixed() || slot_get_length(slot) == 0) + opt_name.cat(" [internal]"); + } + + item_append(slot->device().tag() + 1, opt_name, (slot->fixed() || slot_get_length(slot) == 0) ? 0 : (MENU_FLAG_LEFT_ARROW | MENU_FLAG_RIGHT_ARROW), (void *)slot); + } + item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); + item_append("Reset", NULL, 0, (void *)1); +} + +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 ((FPTR)menu_event->itemref == 1 && menu_event->iptkey == IPT_UI_SELECT) + machine().schedule_hard_reset(); + else 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); + } + } +} diff --git a/src/emu/ui/slotopt.h b/src/emu/ui/slotopt.h new file mode 100644 index 00000000000..9f73e608fdd --- /dev/null +++ b/src/emu/ui/slotopt.h @@ -0,0 +1,36 @@ +/*************************************************************************** + + ui/slotopt.h + + Internal menu for the slot options. + + Copyright Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#pragma once + +#ifndef __UI_SLOTOPT_H__ +#define __UI_SLOTOPT_H__ + +//#include "drivenum.h" + +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: + device_slot_option *slot_get_current_option(device_slot_interface *slot); + 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 *slot_get_option(device_slot_interface *slot, int index); + void set_slot_device(device_slot_interface *slot, const char *val); +}; + +#endif /* __UI_SLOTOPT_H__ */ -- cgit v1.2.3