void *ui_menu::m_pool_alloc(size_t size) { ui_menu_pool *ppool; assert(size < UI_MENU_POOL_SIZE); // find a pool with enough room for (ppool = pool; ppool != nullptr; ppool = ppool->next) if (ppool->end - ppool->top >= size) { void *result = ppool->top; ppool->top += size; return result; } // allocate a new pool ppool = (ui_menu_pool *)auto_alloc_array_clear(machine(), UINT8, sizeof(*ppool) + UI_MENU_POOL_SIZE); // wire it up ppool->next = pool; pool = ppool; ppool->top = (UINT8 *)(ppool + 1); ppool->end = ppool->top + UI_MENU_POOL_SIZE; return m_pool_alloc(size); }
void menu_software_parts::populate() { if (m_other_opt) { software_part_menu_entry *entry1 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry1)); entry1->type = result::EMPTY; entry1->part = nullptr; item_append(_("[empty slot]"), "", 0, entry1); software_part_menu_entry *entry2 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry2)); entry2->type = result::FMGR; entry2->part = nullptr; item_append(_("[file manager]"), "", 0, entry2); software_part_menu_entry *entry3 = (software_part_menu_entry *) m_pool_alloc(sizeof(*entry3)); entry3->type = result::SWLIST; entry3->part = nullptr; item_append(_("[software list]"), "", 0, entry3); } for (const software_part &swpart : m_info->parts()) { if (swpart.matches_interface(m_interface)) { software_part_menu_entry *entry = (software_part_menu_entry *) 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)" std::string menu_part_name(swpart.name()); if (swpart.feature("part_id") != nullptr) menu_part_name.append(" (").append(swpart.feature("part_id")).append(")"); entry->type = result::ENTRY; entry->part = &swpart; item_append(m_info->shortname(), menu_part_name, 0, entry); } } }
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_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 *) m_pool_alloc(sizeof(*entry)); memset(entry, 0, sizeof(*entry)); entry->type = entry_type; 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 = &m_entrylist; while ((*entryptr != NULL) && (compare_entries(entry, *entryptr) >= 0)) entryptr = &(*entryptr)->next; // insert the entry entry->next = *entryptr; *entryptr = entry; return entry; }
menu_software_list::entry_info *menu_software_list::append_software_entry(const software_info &swinfo) { entry_info *entry = nullptr; entry_info **entryptr; bool entry_updated = FALSE; // check if at least one of the parts has the correct interface and add a menu entry only in this case for (const software_part &swpart : swinfo.parts()) { if (swpart.matches_interface(m_interface) && swpart.is_compatible(*m_swlist) == SOFTWARE_IS_COMPATIBLE) { entry_updated = TRUE; // allocate a new entry entry = (entry_info *) m_pool_alloc(sizeof(*entry)); memset(entry, 0, sizeof(*entry)); entry->short_name = pool_strdup(swinfo.shortname()); entry->long_name = pool_strdup(swinfo.longname()); break; } } // skip this if no new entry has been allocated (e.g. if the software has no matching interface for this image device) if (entry_updated) { // find the end of the list entryptr = &m_entrylist; while ((*entryptr != nullptr) && (compare_entries(entry, *entryptr, m_ordered_by_shortname) >= 0)) entryptr = &(*entryptr)->next; // insert the entry entry->next = *entryptr; *entryptr = entry; } return entry; }
void ui_menu_analog::populate() { ioport_field *field; ioport_port *port; std::string text; std::string subtext; std::string 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; std::string name; if (strcmp(field->device().tag(), prev_owner.c_str()) != 0) { if (first_entry) first_entry = false; else item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); strprintf(name,"[root%s]", field->device().tag()); item_append(name.c_str(), NULL, 0, NULL); prev_owner.assign(field->device().tag()); } name.assign(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: strprintf(text, "%s Digital Speed", name.c_str()); strprintf(subtext, "%d", settings.delta); data->min = 0; data->max = 255; data->cur = settings.delta; data->defvalue = field->delta(); break; case ANALOG_ITEM_CENTERSPEED: strprintf(text, "%s Autocenter Speed", name.c_str()); strprintf(subtext, "%d", settings.centerdelta); data->min = 0; data->max = 255; data->cur = settings.centerdelta; data->defvalue = field->centerdelta(); break; case ANALOG_ITEM_REVERSE: strprintf(text, "%s Reverse", name.c_str()); subtext.assign(settings.reverse ? "On" : "Off"); data->min = 0; data->max = 1; data->cur = settings.reverse; data->defvalue = field->analog_reverse(); break; case ANALOG_ITEM_SENSITIVITY: strprintf(text, "%s Sensitivity", name.c_str()); strprintf(subtext, "%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.c_str(), subtext.c_str(), flags, data); } } }
void ui_menu_settings::populate() { ioport_field *field; ioport_port *port; dip_descriptor **diplist_tailptr; std::string 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; std::string 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.c_str()) != 0) { if (first_entry) first_entry = false; else item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); strprintf(name, "[root%s]", field->device().tag()); item_append(name.c_str(), NULL, 0, NULL); prev_owner.assign(field->device().tag()); } name.assign(field->name()); item_append(name.c_str(), 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); }
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; std::string text; std::string subtext; std::string 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 (item->owner_name && strcmp(item->owner_name, prev_owner.c_str()) != 0) { if (first_entry) first_entry = false; else item_append(MENU_SEPARATOR_ITEM, NULL, 0, NULL); strprintf(text, "[root%s]", item->owner_name); item_append(text.c_str(), NULL, 0, NULL); prev_owner.assign(item->owner_name); } strprintf(text, nameformat[item->type], item->name); /* if we're polling this item, use some spaces with left/right arrows */ if (pollingref == item->ref) { subtext.assign(" "); 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.c_str(), subtext.c_str(), flags, item); } }
void ui_menu_input_specific::populate() { input_item_data *itemlist = NULL; int suborder[SEQ_TYPE_TOTAL]; int port_count = 0; /* 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 (ioport_port *port = machine().ioport().first_port(); port != NULL; port = port->next()) { port_count++; for (ioport_field *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 |= (port_count & 0xfff) * 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); }
const char *ui_menu::pool_strdup(const char *string) { return strcpy((char *)m_pool_alloc(strlen(string) + 1), string); }
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 */ machine().crosshair().get_user_settings(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 */ bool using_default = false; bool finished = false; bool found = false; /* if we are using the default, then we just need to find the first in the list */ if (*(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()) != nullptr) && !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 */ machine().crosshair().get_user_settings(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); }
void ui_menu_settings::populate() { dip_descriptor **diplist_tailptr; std::string prev_owner; bool first_entry = true; /* reset the dip switch tracking */ dipcount = 0; diplist = nullptr; diplist_tailptr = &diplist; /* loop over input ports and set up the current values */ for (ioport_port &port : machine().ioport().ports()) for (ioport_field &field : port.fields()) if (field.type() == type && field.enabled()) { UINT32 flags = 0; /* 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.c_str()) != 0) { if (first_entry) first_entry = false; else item_append(ui_menu_item_type::SEPARATOR); string_format("[root%s]", field.device().tag()); item_append(string_format("[root%s]", field.device().tag()).c_str(), nullptr, 0, nullptr); prev_owner.assign(field.device().tag()); } item_append(field.name(), field.setting_name(), flags, (void *)&field); /* for DIP switches, build up the model */ if (type == IPT_DIPSWITCH && !field.diplocations().empty()) { 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 (const ioport_diplocation &diploc : field.diplocations()) { UINT32 mask = accummask & ~(accummask - 1); dip_descriptor *dip; /* find the matching switch name */ for (dip = diplist; dip != nullptr; dip = dip->next) if (strcmp(dip->name, diploc.name()) == 0) break; /* allocate new if none */ if (dip == nullptr) { dip = (dip_descriptor *)m_pool_alloc(sizeof(*dip)); dip->next = nullptr; 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(ui_menu_item_type::SEPARATOR); item_append(_("Reset"), nullptr, 0, (void *)1); }