コード例 #1
0
ファイル: miscmenu.cpp プロジェクト: ndpduc/mame
ui_menu_misc_options::ui_menu_misc_options(running_machine &machine, render_container *container) : ui_menu(machine, container)
{
	for (int d = 1; d < ARRAY_LENGTH(m_options); ++d)
		if (machine.ui().options().exists(m_options[d].option))
			m_options[d].status = machine.ui().options().bool_value(m_options[d].option);
		else
			m_options[d].status = machine.options().bool_value(m_options[d].option);
}
コード例 #2
0
ui_menu_remove_folder::ui_menu_remove_folder(running_machine &machine, render_container *container, int ref) : ui_menu(machine, container)
{
	m_ref = ref - 1;
	if (machine.ui().options().exists(s_folders_entry[m_ref].option)) {
		m_searchpath.assign(machine.ui().options().value(s_folders_entry[m_ref].option));
	}
	else {
		m_searchpath.assign(machine.options().value(s_folders_entry[m_ref].option));
	}

}
コード例 #3
0
void sdlwindow_modify_prescale(running_machine &machine, sdl_window_info *window, int dir)
{
	worker_param wp;
	int new_prescale = window->prescale;

	clear_worker_param(&wp);

	wp.window = window;
	wp.m_machine = &machine;

	if (dir > 0 && window->prescale < 3)
		new_prescale = window->prescale + 1;
	if (dir < 0 && window->prescale > 1)
		new_prescale = window->prescale - 1;

	if (new_prescale != window->prescale)
	{
		if (window->fullscreen && video_config.switchres)
		{
			execute_async_wait(&sdlwindow_video_window_destroy_wt, &wp);

			window->prescale = new_prescale;

			execute_async_wait(&complete_create_wt, &wp);

		}
		else
		{
			execute_async_wait(destroy_all_textures_wt, &wp);
			window->prescale = new_prescale;
		}
		machine.ui().popup_time(1, "Prescale %d", window->prescale);
	}
}
コード例 #4
0
ファイル: video.cpp プロジェクト: gregdickhudl/mame
static void check_osd_inputs(running_machine &machine)
{
	sdl_window_info *window = sdlinput_get_focus_window();

	// check for toggling fullscreen mode
	if (machine.ui_input().pressed(IPT_OSD_1))
	{
		sdl_window_info *curwin = sdl_window_list;

		while (curwin != (sdl_window_info *)NULL)
		{
			curwin->toggle_full_screen();
			curwin = curwin->m_next;
		}
	}

	if (machine.ui_input().pressed(IPT_OSD_2))
	{
		//FIXME: on a per window basis
		video_config.fullstretch = !video_config.fullstretch;
		machine.ui().popup_time(1, "Uneven stretch %s", video_config.fullstretch? "enabled":"disabled");
	}

	if (machine.ui_input().pressed(IPT_OSD_4))
	{
		//FIXME: on a per window basis
		video_config.keepaspect = !video_config.keepaspect;
		machine.ui().popup_time(1, "Keepaspect %s", video_config.keepaspect? "enabled":"disabled");
	}

	#if (USE_OPENGL || SDLMAME_SDL2)
		//FIXME: on a per window basis
		if (machine.ui_input().pressed(IPT_OSD_5))
		{
			video_config.filter = !video_config.filter;
			machine.ui().popup_time(1, "Filter %s", video_config.filter? "enabled":"disabled");
		}
	#endif

	if (machine.ui_input().pressed(IPT_OSD_6))
		window->modify_prescale(-1);

	if (machine.ui_input().pressed(IPT_OSD_7))
		window->modify_prescale(1);
}
コード例 #5
0
static void check_osd_inputs(running_machine &machine)
{
	sdl_window_info *window = sdlinput_get_focus_window(machine);

	// check for toggling fullscreen mode
	if (ui_input_pressed(machine, IPT_OSD_1))
		sdlwindow_toggle_full_screen(machine, window);

	if (ui_input_pressed(machine, IPT_OSD_2))
	{
		//FIXME: on a per window basis
		video_config.fullstretch = !video_config.fullstretch;
		machine.ui().popup_time(1, "Uneven stretch %s", video_config.fullstretch? "enabled":"disabled");
	}

	if (ui_input_pressed(machine, IPT_OSD_4))
	{
		//FIXME: on a per window basis
		video_config.keepaspect = !video_config.keepaspect;
		machine.ui().popup_time(1, "Keepaspect %s", video_config.keepaspect? "enabled":"disabled");
	}

	#if (USE_OPENGL || SDLMAME_SDL2)
		//FIXME: on a per window basis
		if (ui_input_pressed(machine, IPT_OSD_5))
		{
			video_config.filter = !video_config.filter;
			machine.ui().popup_time(1, "Filter %s", video_config.filter? "enabled":"disabled");
		}
	#endif

	if (ui_input_pressed(machine, IPT_OSD_6))
		sdlwindow_modify_prescale(machine, window, -1);

	if (ui_input_pressed(machine, IPT_OSD_7))
		sdlwindow_modify_prescale(machine, window, 1);
}
コード例 #6
0
ファイル: filemngr.cpp プロジェクト: robsonfr/mame
// force file manager menu
void ui_menu_file_manager::force_file_manager(running_machine &machine, render_container *container, const char *warnings)
{
	// reset the menu stack
	ui_menu::stack_reset(machine);

	// add the quit entry followed by the game select entry
	ui_menu *quit = auto_alloc_clear(machine, ui_menu_quit_game(machine, container));
	quit->set_special_main_menu(true);
	ui_menu::stack_push(quit);
	ui_menu::stack_push(auto_alloc_clear(machine, ui_menu_file_manager(machine, container, warnings)));

	// force the menus on
	machine.ui().show_menu();

	// make sure MAME is paused
	machine.pause();
}
コード例 #7
0
ファイル: menu.cpp プロジェクト: toughkidcst/mame
UINT32 ui_menu::ui_handler(running_machine &machine, render_container *container, UINT32 state)
{
	// if we have no menus stacked up, start with the main menu
	if (menu_stack == nullptr)
		stack_push(auto_alloc_clear(machine, ui_menu_main(machine, container)));

	// update the menu state
	if (menu_stack != nullptr)
		menu_stack->do_handle();

	// clear up anything pending to be released
	clear_free_list(machine);

	// if the menus are to be hidden, return a cancel here
	if (machine.ui().is_menu_active() && ((ui_input_pressed(machine, IPT_UI_CONFIGURE) && !stack_has_special_main_menu()) || menu_stack == nullptr))
		return UI_HANDLER_CANCEL;

	return 0;
}
コード例 #8
0
ファイル: selgame.c プロジェクト: mbcoguno/mame
void ui_menu_select_game::force_game_select(running_machine &machine, render_container *container)
{
	char *gamename = (char *)machine.options().system_name();

	// reset the menu stack
	ui_menu::stack_reset(machine);

	// add the quit entry followed by the game select entry
	ui_menu *quit = auto_alloc_clear(machine, ui_menu_quit_game(machine, container));
	quit->set_special_main_menu(true);
	ui_menu::stack_push(quit);
	ui_menu::stack_push(auto_alloc_clear(machine, ui_menu_select_game(machine, container, gamename)));

	// force the menus on
	machine.ui().show_menu();

	// make sure MAME is paused
	machine.pause();
}
コード例 #9
0
ファイル: datfile.cpp プロジェクト: WinCoder/mame
//-------------------------------------------------
// ctor
//-------------------------------------------------
datfile_manager::datfile_manager(running_machine &machine) : m_machine(machine)
{
	if (machine.ui().options().enabled_dats() && first_run)
	{
		first_run = false;
		if (parseopen("mameinfo.dat"))
		{
			init_mameinfo();
			parseclose();
		}

		if (parseopen("command.dat"))
		{
			init_command();
			parseclose();
		}

		if (parseopen("story.dat"))
		{
			init_storyinfo();
			parseclose();
		}

		if (parseopen("messinfo.dat"))
		{
			init_messinfo();
			parseclose();
		}

		if (parseopen("sysinfo.dat"))
		{
			init_sysinfo();
			parseclose();
		}

		if (parseopen("history.dat"))
		{
			init_history();
			parseclose();
		}
	}
}
コード例 #10
0
ファイル: custui.cpp プロジェクト: p0nley/mame
ui_menu_font_ui::ui_menu_font_ui(running_machine &machine, render_container *container) : ui_menu(machine, container)
{
	ui_options &moptions = machine.ui().options();
#ifdef UI_WINDOWS

	std::string name(machine.options().ui_font());
	list();

	m_bold = (strreplace(name, "[B]", "") + strreplace(name, "[b]", "") > 0);
	m_italic = (strreplace(name, "[I]", "") + strreplace(name, "[i]", "") > 0);
	m_actual = 0;

	for (size_t index = 0; index < m_fonts.size(); index++)
	{
		if (m_fonts[index] == name)
		{
			m_actual = index;
			break;
		}
	}
#endif

	m_info_size = moptions.infos_size();
	m_font_size = moptions.font_rows();

	for (ui_options::entry *f_entry = moptions.first(); f_entry != nullptr; f_entry = f_entry->next())
	{
		const char *name = f_entry->name();
		if (name && strlen(name) && !strcmp(OPTION_INFOS_SIZE, f_entry->name()))
		{
			m_info_max = atof(f_entry->maximum());
			m_info_min = atof(f_entry->minimum());
		}
		else if (name && strlen(name) && !strcmp(OPTION_FONT_ROWS, f_entry->name()))
		{
			m_font_max = atof(f_entry->maximum());
			m_font_min = atof(f_entry->minimum());
		}
	}

}
コード例 #11
0
ファイル: viewgfx.cpp プロジェクト: ursine/mame
static void tilemap_handler(running_machine &machine, render_container *container, ui_gfx_state &state)
{
	render_font *ui_font = machine.ui().get_font();
	float chwidth, chheight;
	render_bounds mapboxbounds;
	render_bounds boxbounds;
	int targwidth = machine.render().ui_target().width();
	int targheight = machine.render().ui_target().height();
	float titlewidth;
	float x0, y0;
	int mapboxwidth, mapboxheight;
	int maxxscale, maxyscale;
	UINT32 mapwidth, mapheight;
	int x, pixelscale;
	char title[100];

	// get the size of the tilemap itself
	tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
	mapwidth = tilemap->width();
	mapheight = tilemap->height();
	if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
		{ UINT32 temp = mapwidth; mapwidth = mapheight; mapheight = temp; }

	// add a half character padding for the box
	chheight = machine.ui().get_line_height();
	chwidth = ui_font->char_width(chheight, machine.render().ui_aspect(), '0');
	boxbounds.x0 = 0.0f + 0.5f * chwidth;
	boxbounds.x1 = 1.0f - 0.5f * chwidth;
	boxbounds.y0 = 0.0f + 0.5f * chheight;
	boxbounds.y1 = 1.0f - 0.5f * chheight;

	// the tilemap box bounds starts a half character in from the box
	mapboxbounds = boxbounds;
	mapboxbounds.x0 += 0.5f * chwidth;
	mapboxbounds.x1 -= 0.5f * chwidth;
	mapboxbounds.y0 += 0.5f * chheight;
	mapboxbounds.y1 -= 0.5f * chheight;

	// add space on the top for a title and a half line of padding
	mapboxbounds.y0 += 1.5f * chheight;

	// convert back to pixels
	mapboxwidth = (mapboxbounds.x1 - mapboxbounds.x0) * (float)targwidth;
	mapboxheight = (mapboxbounds.y1 - mapboxbounds.y0) * (float)targheight;

	// determine the maximum integral scaling factor
	pixelscale = state.tilemap.zoom;
	if (pixelscale == 0)
	{
		for (maxxscale = 1; mapwidth * (maxxscale + 1) < mapboxwidth; maxxscale++) { }
		for (maxyscale = 1; mapheight * (maxyscale + 1) < mapboxheight; maxyscale++) { }
		pixelscale = MIN(maxxscale, maxyscale);
	}

	// recompute the final box size
	mapboxwidth = MIN(mapboxwidth, mapwidth * pixelscale);
	mapboxheight = MIN(mapboxheight, mapheight * pixelscale);

	// recompute the bounds, centered within the existing bounds
	mapboxbounds.x0 += 0.5f * ((mapboxbounds.x1 - mapboxbounds.x0) - (float)mapboxwidth / (float)targwidth);
	mapboxbounds.x1 = mapboxbounds.x0 + (float)mapboxwidth / (float)targwidth;
	mapboxbounds.y0 += 0.5f * ((mapboxbounds.y1 - mapboxbounds.y0) - (float)mapboxheight / (float)targheight);
	mapboxbounds.y1 = mapboxbounds.y0 + (float)mapboxheight / (float)targheight;

	// now recompute the outer box against this new info
	boxbounds.x0 = mapboxbounds.x0 - 0.5f * chwidth;
	boxbounds.x1 = mapboxbounds.x1 + 0.5f * chwidth;
	boxbounds.y0 = mapboxbounds.y0 - 2.0f * chheight;
	boxbounds.y1 = mapboxbounds.y1 + 0.5f * chheight;

	// figure out the title and expand the outer box to fit
	sprintf(title, "TILEMAP %d/%d %dx%d OFFS %d,%d", state.tilemap.which, machine.tilemap().count() - 1, mapwidth, mapheight, state.tilemap.xoffs, state.tilemap.yoffs);
	titlewidth = ui_font->string_width(chheight, machine.render().ui_aspect(), title);
	if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
	{
		boxbounds.x0 = 0.5f - 0.5f * (titlewidth + chwidth);
		boxbounds.x1 = boxbounds.x0 + titlewidth + chwidth;
	}

	// go ahead and draw the outer box now
	machine.ui().draw_outlined_box(container, boxbounds.x0, boxbounds.y0, boxbounds.x1, boxbounds.y1, UI_GFXVIEWER_BG_COLOR);

	// draw the title
	x0 = 0.5f - 0.5f * titlewidth;
	y0 = boxbounds.y0 + 0.5f * chheight;
	for (x = 0; title[x] != 0; x++)
	{
		container->add_char(x0, y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]);
		x0 += ui_font->char_width(chheight, machine.render().ui_aspect(), title[x]);
	}

	// update the bitmap
	tilemap_update_bitmap(machine, state, mapboxwidth / pixelscale, mapboxheight / pixelscale);

	// add the final quad
	container->add_quad(mapboxbounds.x0, mapboxbounds.y0,
						mapboxbounds.x1, mapboxbounds.y1,
						ARGB_WHITE, state.texture,
						PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(state.tilemap.rotate));

	// handle keyboard input
	tilemap_handle_keys(machine, state, mapboxwidth, mapboxheight);
}
コード例 #12
0
ファイル: viewgfx.cpp プロジェクト: ursine/mame
static void gfxset_handler(running_machine &machine, render_container *container, ui_gfx_state &state)
{
	render_font *ui_font = machine.ui().get_font();
	int dev = state.gfxset.devindex;
	int set = state.gfxset.set;
	ui_gfx_info &info = state.gfxdev[dev];
	device_gfx_interface &interface = *info.interface;
	gfx_element &gfx = *interface.gfx(set);
	float fullwidth, fullheight;
	float cellwidth, cellheight;
	float chwidth, chheight;
	float titlewidth;
	//float cellaspect;
	float x0, y0;
	render_bounds cellboxbounds;
	render_bounds boxbounds;
	int cellboxwidth, cellboxheight;
	int targwidth = machine.render().ui_target().width();
	int targheight = machine.render().ui_target().height();
	int cellxpix, cellypix;
	int xcells, ycells;
	int pixelscale = 0;
	int x, y, skip;
	char title[100];

	// add a half character padding for the box
	chheight = machine.ui().get_line_height();
	chwidth = ui_font->char_width(chheight, machine.render().ui_aspect(), '0');
	boxbounds.x0 = 0.0f + 0.5f * chwidth;
	boxbounds.x1 = 1.0f - 0.5f * chwidth;
	boxbounds.y0 = 0.0f + 0.5f * chheight;
	boxbounds.y1 = 1.0f - 0.5f * chheight;

	// the character cell box bounds starts a half character in from the box
	cellboxbounds = boxbounds;
	cellboxbounds.x0 += 0.5f * chwidth;
	cellboxbounds.x1 -= 0.5f * chwidth;
	cellboxbounds.y0 += 0.5f * chheight;
	cellboxbounds.y1 -= 0.5f * chheight;

	// add space on the left for 5 characters of text, plus a half character of padding
	cellboxbounds.x0 += 5.5f * chwidth;

	// add space on the top for a title, a half line of padding, a header, and another half line
	cellboxbounds.y0 += 3.0f * chheight;

	// convert back to pixels
	cellboxwidth = (cellboxbounds.x1 - cellboxbounds.x0) * (float)targwidth;
	cellboxheight = (cellboxbounds.y1 - cellboxbounds.y0) * (float)targheight;

	// compute the number of source pixels in a cell
	cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
	cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());

	// compute the largest pixel scale factor that still fits
	xcells = info.columns[set];
	while (xcells > 1)
	{
		pixelscale = (cellboxwidth / xcells) / cellxpix;
		if (pixelscale != 0)
			break;
		xcells--;
	}
	info.columns[set] = xcells;

	// worst case, we need a pixel scale of 1
	pixelscale = MAX(1, pixelscale);

	// in the Y direction, we just display as many as we can
	ycells = cellboxheight / (pixelscale * cellypix);

	// now determine the actual cellbox size
	cellboxwidth = MIN(cellboxwidth, xcells * pixelscale * cellxpix);
	cellboxheight = MIN(cellboxheight, ycells * pixelscale * cellypix);

	// compute the size of a single cell at this pixel scale factor, as well as the aspect ratio
	cellwidth = (cellboxwidth / (float)xcells) / (float)targwidth;
	cellheight = (cellboxheight / (float)ycells) / (float)targheight;
	//cellaspect = cellwidth / cellheight;

	// working from the new width/height, recompute the boxbounds
	fullwidth = (float)cellboxwidth / (float)targwidth + 6.5f * chwidth;
	fullheight = (float)cellboxheight / (float)targheight + 4.0f * chheight;

	// recompute boxbounds from this
	boxbounds.x0 = (1.0f - fullwidth) * 0.5f;
	boxbounds.x1 = boxbounds.x0 + fullwidth;
	boxbounds.y0 = (1.0f - fullheight) * 0.5f;
	boxbounds.y1 = boxbounds.y0 + fullheight;

	// figure out the title and expand the outer box to fit
	sprintf(title, "'%s' %d/%d %dx%d COLOR %X",
					interface.device().tag(),
					set, info.setcount - 1,
					gfx.width(), gfx.height(),
					info.color[set]);
	titlewidth = ui_font->string_width(chheight, machine.render().ui_aspect(), title);
	x0 = 0.0f;
	if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
		x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));

	// go ahead and draw the outer box now
	machine.ui().draw_outlined_box(container, boxbounds.x0 - x0, boxbounds.y0, boxbounds.x1 + x0, boxbounds.y1, UI_GFXVIEWER_BG_COLOR);

	// draw the title
	x0 = 0.5f - 0.5f * titlewidth;
	y0 = boxbounds.y0 + 0.5f * chheight;
	for (x = 0; title[x] != 0; x++)
	{
		container->add_char(x0, y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]);
		x0 += ui_font->char_width(chheight, machine.render().ui_aspect(), title[x]);
	}

	// draw the top column headers
	skip = (int)(chwidth / cellwidth);
	for (x = 0; x < xcells; x += 1 + skip)
	{
		x0 = boxbounds.x0 + 6.0f * chwidth + (float)x * cellwidth;
		y0 = boxbounds.y0 + 2.0f * chheight;
		container->add_char(x0 + 0.5f * (cellwidth - chwidth), y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, "0123456789ABCDEF"[x & 0xf]);

		// if we're skipping, draw a point between the character and the box to indicate which
		// one it's referring to
		if (skip != 0)
			container->add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + boxbounds.y0 + 3.5f * chheight), UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
	}

	// draw the side column headers
	skip = (int)(chheight / cellheight);
	for (y = 0; y < ycells; y += 1 + skip)

		// only display if there is data to show
		if (info.offset[set] + y * xcells < gfx.elements())
		{
			char buffer[10];

			// if we're skipping, draw a point between the character and the box to indicate which
			// one it's referring to
			x0 = boxbounds.x0 + 5.5f * chwidth;
			y0 = boxbounds.y0 + 3.5f * chheight + (float)y * cellheight;
			if (skip != 0)
				container->add_point(0.5f * (x0 + boxbounds.x0 + 6.0f * chwidth), y0 + 0.5f * cellheight, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));

			// draw the row header
			sprintf(buffer, "%5X", info.offset[set] + y * xcells);
			for (x = 4; x >= 0; x--)
			{
				x0 -= ui_font->char_width(chheight, machine.render().ui_aspect(), buffer[x]);
				container->add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, buffer[x]);
			}
		}

	// update the bitmap
	gfxset_update_bitmap(machine, state, xcells, ycells, gfx);

	// add the final quad
	container->add_quad(boxbounds.x0 + 6.0f * chwidth, boxbounds.y0 + 3.5f * chheight,
						boxbounds.x0 + 6.0f * chwidth + (float)cellboxwidth / (float)targwidth,
						boxbounds.y0 + 3.5f * chheight + (float)cellboxheight / (float)targheight,
						ARGB_WHITE, state.texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));

	// handle keyboard navigation before drawing
	gfxset_handle_keys(machine, state, xcells, ycells);
}
コード例 #13
0
ファイル: viewgfx.cpp プロジェクト: ursine/mame
static void palette_handler(running_machine &machine, render_container *container, ui_gfx_state &state)
{
	palette_device *palette = state.palette.device;

	int total = state.palette.which ? palette->indirect_entries() : palette->entries();
	const rgb_t *raw_color = palette->palette()->entry_list_raw();
	render_font *ui_font = machine.ui().get_font();
	float cellwidth, cellheight;
	float chwidth, chheight;
	float titlewidth;
	float x0, y0;
	render_bounds cellboxbounds;
	render_bounds boxbounds;
	int x, y, skip;
	char title[100];

	// add a half character padding for the box
	chheight = machine.ui().get_line_height();
	chwidth = ui_font->char_width(chheight, machine.render().ui_aspect(), '0');
	boxbounds.x0 = 0.0f + 0.5f * chwidth;
	boxbounds.x1 = 1.0f - 0.5f * chwidth;
	boxbounds.y0 = 0.0f + 0.5f * chheight;
	boxbounds.y1 = 1.0f - 0.5f * chheight;

	// the character cell box bounds starts a half character in from the box
	cellboxbounds = boxbounds;
	cellboxbounds.x0 += 0.5f * chwidth;
	cellboxbounds.x1 -= 0.5f * chwidth;
	cellboxbounds.y0 += 0.5f * chheight;
	cellboxbounds.y1 -= 0.5f * chheight;

	// add space on the left for 5 characters of text, plus a half character of padding
	cellboxbounds.x0 += 5.5f * chwidth;

	// add space on the top for a title, a half line of padding, a header, and another half line
	cellboxbounds.y0 += 3.0f * chheight;

	// figure out the title and expand the outer box to fit
	const char *suffix = palette->indirect_entries() == 0 ? "" : state.palette.which ? " COLORS" : " PENS";
	sprintf(title, "'%s'%s", palette->tag(), suffix);
	titlewidth = ui_font->string_width(chheight, machine.render().ui_aspect(), title);
	x0 = 0.0f;
	if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
		x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));

	// go ahead and draw the outer box now
	machine.ui().draw_outlined_box(container, boxbounds.x0 - x0, boxbounds.y0, boxbounds.x1 + x0, boxbounds.y1, UI_GFXVIEWER_BG_COLOR);

	// draw the title
	x0 = 0.5f - 0.5f * titlewidth;
	y0 = boxbounds.y0 + 0.5f * chheight;
	for (x = 0; title[x] != 0; x++)
	{
		container->add_char(x0, y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, title[x]);
		x0 += ui_font->char_width(chheight, machine.render().ui_aspect(), title[x]);
	}

	// compute the cell size
	cellwidth = (cellboxbounds.x1 - cellboxbounds.x0) / (float)state.palette.columns;
	cellheight = (cellboxbounds.y1 - cellboxbounds.y0) / (float)state.palette.columns;

	// draw the top column headers
	skip = (int)(chwidth / cellwidth);
	for (x = 0; x < state.palette.columns; x += 1 + skip)
	{
		x0 = boxbounds.x0 + 6.0f * chwidth + (float)x * cellwidth;
		y0 = boxbounds.y0 + 2.0f * chheight;
		container->add_char(x0 + 0.5f * (cellwidth - chwidth), y0, chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, "0123456789ABCDEF"[x & 0xf]);

		// if we're skipping, draw a point between the character and the box to indicate which
		// one it's referring to
		if (skip != 0)
			container->add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + cellboxbounds.y0), UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
	}

	// draw the side column headers
	skip = (int)(chheight / cellheight);
	for (y = 0; y < state.palette.columns; y += 1 + skip)

		// only display if there is data to show
		if (state.palette.offset + y * state.palette.columns < total)
		{
			char buffer[10];

			// if we're skipping, draw a point between the character and the box to indicate which
			// one it's referring to
			x0 = boxbounds.x0 + 5.5f * chwidth;
			y0 = boxbounds.y0 + 3.5f * chheight + (float)y * cellheight;
			if (skip != 0)
				container->add_point(0.5f * (x0 + cellboxbounds.x0), y0 + 0.5f * cellheight, UI_LINE_WIDTH, ARGB_WHITE, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));

			// draw the row header
			sprintf(buffer, "%5X", state.palette.offset + y * state.palette.columns);
			for (x = 4; x >= 0; x--)
			{
				x0 -= ui_font->char_width(chheight, machine.render().ui_aspect(), buffer[x]);
				container->add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, machine.render().ui_aspect(), ARGB_WHITE, *ui_font, buffer[x]);
			}
		}

	// now add the rectangles for the colors
	for (y = 0; y < state.palette.columns; y++)
		for (x = 0; x < state.palette.columns; x++)
		{
			int index = state.palette.offset + y * state.palette.columns + x;
			if (index < total)
			{
				pen_t pen = state.palette.which ? palette->indirect_color(index) : raw_color[index];
				container->add_rect(cellboxbounds.x0 + x * cellwidth, cellboxbounds.y0 + y * cellheight,
									cellboxbounds.x0 + (x + 1) * cellwidth, cellboxbounds.y0 + (y + 1) * cellheight,
									0xff000000 | pen, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
			}
		}

	// handle keys
	palette_handle_keys(machine, state);
}