예제 #1
0
파일: menu.cpp 프로젝트: toughkidcst/mame
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);
}
예제 #2
0
파일: swlist.cpp 프로젝트: goofwear/mame
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);
		}
	}
}
예제 #3
0
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);
}
예제 #4
0
파일: filesel.cpp 프로젝트: robsonfr/mame
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;
}
예제 #5
0
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;
}
예제 #6
0
파일: inputmap.c 프로젝트: h0tw1r3/mewui
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);
					}
			}
}
예제 #7
0
파일: inputmap.c 프로젝트: h0tw1r3/mewui
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);
}
예제 #8
0
파일: inputmap.c 프로젝트: h0tw1r3/mewui
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);
	}
}
예제 #9
0
파일: inputmap.c 프로젝트: h0tw1r3/mewui
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);
}
예제 #10
0
파일: menu.cpp 프로젝트: toughkidcst/mame
const char *ui_menu::pool_strdup(const char *string)
{
	return strcpy((char *)m_pool_alloc(strlen(string) + 1), string);
}
예제 #11
0
파일: miscmenu.cpp 프로젝트: ndpduc/mame
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);
}
예제 #12
0
파일: inputmap.cpp 프로젝트: RJRetro/mame
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);
}