summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui
diff options
context:
space:
mode:
author Vas Crabb <cuavas@users.noreply.github.com>2022-05-20 18:26:14 +1000
committer GitHub <noreply@github.com>2022-05-20 18:26:14 +1000
commitffab5b98fae1b86b198ccca26a82ebaad2274f7b (patch)
treec9b2b9e6e4f4d4e9a6b320bc0c8980d54f841b17 /src/frontend/mame/ui
parent56702e42172274b6f7a869a958935139311376f5 (diff)
ui/viewgfx.cpp: Added ability to restrict tiles to integer scale factors. (#9783)
Also encapsulated things a bit more and made the UI manager hold onto the storage rather than keeping it in file statics.
Diffstat (limited to 'src/frontend/mame/ui')
-rw-r--r--src/frontend/mame/ui/ui.cpp2
-rw-r--r--src/frontend/mame/ui/viewgfx.cpp1946
-rw-r--r--src/frontend/mame/ui/viewgfx.h6
3 files changed, 981 insertions, 973 deletions
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp
index 6c2f0d35286..3dd550169db 100644
--- a/src/frontend/mame/ui/ui.cpp
+++ b/src/frontend/mame/ui/ui.cpp
@@ -203,8 +203,6 @@ void mame_ui_manager::init()
ui::system_list::instance().cache_data(options());
// initialize the other UI bits
- ui_gfx_init(machine());
-
m_ui_colors.refresh(options());
// update font row info from setting
diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp
index 8c51413607a..f60fefd20c6 100644
--- a/src/frontend/mame/ui/viewgfx.cpp
+++ b/src/frontend/mame/ui/viewgfx.cpp
@@ -21,403 +21,815 @@
#include "uiinput.h"
#include <cmath>
+#include <vector>
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+namespace {
-enum ui_gfx_modes
+class gfx_viewer
{
- UI_GFX_PALETTE = 0,
- UI_GFX_GFXSET,
- UI_GFX_TILEMAP
-};
+public:
+ gfx_viewer(running_machine &machine) :
+ m_machine(machine),
+ m_palette(machine),
+ m_gfxset(machine)
+ {
+ uint8_t const rotate = machine.system().flags & machine_flags::MASK_ORIENTATION;
-constexpr uint8_t MAX_GFX_DECODERS = 8;
-constexpr int MAX_ZOOM_LEVEL = 8;
-constexpr int MIN_ZOOM_LEVEL = 8;
+ // set initial tilemap rotation to match system orientation
+ m_tilemap.m_rotate = rotate;
+ }
+ // copy constructor needed to make std::any happy
+ gfx_viewer(gfx_viewer const &that) :
+ gfx_viewer(that.m_machine)
+ {
+ }
+ ~gfx_viewer()
+ {
+ if (m_texture)
+ m_machine.render().texture_free(m_texture);
+ }
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+ uint32_t handle(mame_ui_manager &mui, render_container &container, bool uistate)
+ {
+ // implicitly cancel if there's nothing to display
+ if (!is_relevant())
+ return cancel(uistate);
-// information about a single gfx device
-struct ui_gfx_info
-{
- device_gfx_interface *interface; // pointer to device's gfx interface
- uint8_t setcount; // how many gfx sets device has
- uint8_t rotate[MAX_GFX_ELEMENTS]; // current rotation (orientation) value
- uint8_t columns[MAX_GFX_ELEMENTS]; // number of items per row
- int offset[MAX_GFX_ELEMENTS]; // current offset of top,left item
- int color[MAX_GFX_ELEMENTS]; // current color selected
- device_palette_interface *palette[MAX_GFX_ELEMENTS]; // associated palette (maybe multiple choice one day?)
- int color_count[MAX_GFX_ELEMENTS]; // Range of color values
-};
+ // always mark the bitmap dirty if not paused
+ if (!m_machine.paused())
+ m_bitmap_dirty = true;
-struct ui_gfx_state
-{
- bool started; // have we called ui_gfx_count_devices() yet?
- uint8_t mode; // which mode are we in?
+ // try to display the selected view
+ while (true)
+ {
+ switch (m_mode)
+ {
+ case view::PALETTE:
+ if (m_palette.interface())
+ return handle_palette(mui, container, uistate);
+ m_mode = view::GFXSET;
+ break;
- // intermediate bitmaps
- bool bitmap_dirty; // is the bitmap dirty?
- bitmap_rgb32 bitmap; // bitmap for drawing gfx and tilemaps
- render_texture *texture; // texture for rendering the above bitmap
+ case view::GFXSET:
+ if (m_gfxset.has_gfx())
+ return handle_gfxset(mui, container, uistate);
+ m_mode = view::TILEMAP;
+ break;
- // palette-specific data
- struct
+ case view::TILEMAP:
+ if (m_machine.tilemap().count())
+ return handle_tilemap(mui, container, uistate);
+ m_mode = view::PALETTE;
+ break;
+ }
+ }
+ }
+
+private:
+ enum class view
{
- device_palette_interface *interface; // pointer to current palette
- int devcount; // how many palette devices exist
- int devindex; // which palette device is visible
- uint8_t which; // which subset (pens or indirect colors)?
- uint8_t columns; // number of items per row
- int offset; // current offset of top left item
- } palette;
-
- // graphics-specific data
- struct
+ PALETTE,
+ GFXSET,
+ TILEMAP
+ };
+
+ class palette
{
- uint8_t devcount; // how many gfx devices exist
- uint8_t devindex; // which device is visible
- uint8_t set; // which set is visible
- } gfxset;
+ public:
+ enum class subset
+ {
+ PENS,
+ INDIRECT
+ };
- // information about each gfx device
- ui_gfx_info gfxdev[MAX_GFX_DECODERS];
+ palette(running_machine &machine) :
+ m_count(palette_interface_enumerator(machine.root_device()).count())
+ {
+ if (m_count)
+ set_device(machine);
+ }
- // tilemap-specific data
- struct
- {
- int which; // which tilemap are we viewing?
- int xoffs; // current X offset
- int yoffs; // current Y offset
- int zoom; // zoom factor, either x or 1/x
- bool zoom_frac; // zoom via reciprocal fractions
- bool auto_zoom; // auto-zoom toggle
- uint8_t rotate; // current rotation (orientation) value
- uint32_t flags; // render flags
- } tilemap;
-};
+ device_palette_interface *interface() const noexcept
+ {
+ return m_interface;
+ }
+ bool indirect() const noexcept
+ {
+ return subset::INDIRECT == m_which;
+ }
+ unsigned columns() const noexcept
+ {
+ return m_columns;
+ }
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
+ unsigned index(unsigned x, unsigned y) const noexcept
+ {
+ return m_offset + (y * m_columns) + x;
+ }
-static ui_gfx_state ui_gfx;
+ void handle_keys(running_machine &machine);
+ private:
+ void set_device(running_machine &machine)
+ {
+ m_interface = palette_interface_enumerator(machine.root_device()).byindex(m_index);
+ }
+ void next_group(running_machine &machine) noexcept
+ {
+ if ((subset::PENS == m_which) && m_interface->indirect_entries())
+ {
+ m_which = subset::INDIRECT;
+ }
+ else if ((m_count - 1) > m_index)
+ {
+ ++m_index;
+ set_device(machine);
+ m_which = subset::PENS;
+ }
+ }
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+ void prev_group(running_machine &machine) noexcept
+ {
+ if (subset::INDIRECT == m_which)
+ {
+ m_which = subset::PENS;
+ }
+ else if (0 < m_index)
+ {
+ --m_index;
+ set_device(machine);
+ m_which = m_interface->indirect_entries() ? subset::INDIRECT : subset::PENS;
+ }
+ }
-static void ui_gfx_count_devices(running_machine &machine, ui_gfx_state &state);
-static void ui_gfx_exit(running_machine &machine);
+ device_palette_interface *m_interface = nullptr;
+ unsigned const m_count;
+ unsigned m_index = 0U;
+ subset m_which = subset::PENS;
+ unsigned m_columns = 16U;
+ int m_offset = 0;
+ };
-// palette handling
-static void palette_set_device(running_machine &machine, ui_gfx_state &state);
-static void palette_handle_keys(running_machine &machine, ui_gfx_state &state);
-static void palette_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state);
+ class gfxset
+ {
+ public:
+ struct setinfo
+ {
+ void next_color() noexcept
+ {
+ if ((m_color_count - 1) > m_color)
+ ++m_color;
+ else
+ m_color = 0U;
+ }
-// graphics set handling
-static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, int xcells, int ycells);
-static void gfxset_draw_item(running_machine &machine, gfx_element &gfx, int index, bitmap_rgb32 &bitmap, int dstx, int dsty, int color, int rotate, device_palette_interface *dpalette);
-static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, int xcells, int ycells, gfx_element &gfx);
-static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state);
+ void prev_color() noexcept
+ {
+ if (m_color)
+ --m_color;
+ else
+ m_color = m_color_count - 1;
+ }
-// tilemap handling
-static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, float pixelscale);
-static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, int width, int height);
-static void tilemap_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state);
+ device_palette_interface *m_palette = nullptr;
+ int m_offset = 0;
+ unsigned m_color = 0;
+ unsigned m_color_count = 0U;
+ uint8_t m_rotate = 0U;
+ uint8_t m_columns = 16U;
+ bool m_integer_scale = false;
+ };
+ struct devinfo
+ {
+ device_gfx_interface *m_interface = nullptr;
+ unsigned m_setcount = 0U;
+ setinfo m_sets[MAX_GFX_ELEMENTS];
+ };
+ gfxset(running_machine &machine)
+ {
+ // get useful defaults
+ uint8_t const rotate = machine.system().flags & machine_flags::MASK_ORIENTATION;
+ device_palette_interface *const first_palette = palette_interface_enumerator(machine.root_device()).first();
-/***************************************************************************
- CORE IMPLEMENTATION
-***************************************************************************/
+ // iterate over graphics decoders
+ for (device_gfx_interface &interface : gfx_interface_enumerator(machine.root_device()))
+ {
+ // count exposed graphics sets
+ unsigned count = 0U;
+ while ((MAX_GFX_ELEMENTS > count) && interface.gfx(count))
+ ++count;
-//-------------------------------------------------
-// ui_gfx_init - initialize the graphics viewer
-//-------------------------------------------------
+ // if there are any exposed graphics sets, add the device
+ if (count)
+ {
+ devinfo &info = m_devices.emplace_back();
+ info.m_interface = &interface;
+ info.m_setcount = count;
+ for (unsigned slot = 0U; count > slot; ++slot)
+ {
+ auto &gfx = *interface.gfx(slot);
+ if (gfx.has_palette())
+ {
+ info.m_sets[slot].m_palette = &gfx.palette();
+ info.m_sets[slot].m_color_count = gfx.colors();
+ }
+ else
+ {
+ info.m_sets[slot].m_palette = first_palette;
+ info.m_sets[slot].m_color_count = first_palette->entries() / gfx.granularity();
+ if (!info.m_sets[slot].m_color_count)
+ info.m_sets[slot].m_color_count = 1U;
+ }
+ info.m_sets[slot].m_rotate = rotate;
+ }
+ }
+ }
+ }
-void ui_gfx_init(running_machine &machine)
-{
- ui_gfx_state &state = ui_gfx;
- uint8_t rotate = machine.system().flags & machine_flags::MASK_ORIENTATION;
-
- // make sure we clean up after ourselves
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&ui_gfx_exit, &machine));
-
- // initialize our global state
- state.started = false;
- state.mode = 0;
- state.bitmap_dirty = false;
- state.bitmap.reset();
- state.texture = nullptr;
- state.gfxset.devcount = 0;
- state.gfxset.devindex = 0;
- state.gfxset.set = 0;
-
- // set up the palette state
- state.palette.interface = nullptr;
- state.palette.devcount = 0;
- state.palette.devindex = 0;
- state.palette.which = 0;
- state.palette.columns = 16;
-
- // set up the graphics state
- for (uint8_t i = 0; i < MAX_GFX_DECODERS; i++)
- {
- state.gfxdev[i].interface = nullptr;
- state.gfxdev[i].setcount = 0;
- for (uint8_t j = 0; j < MAX_GFX_ELEMENTS; j++)
+ bool has_gfx() const noexcept
{
- state.gfxdev[i].rotate[j] = rotate;
- state.gfxdev[i].columns[j] = 16;
- state.gfxdev[i].offset[j] = 0;
- state.gfxdev[i].color[j] = 0;
- state.gfxdev[i].palette[j] = nullptr;
- state.gfxdev[i].color_count[j] = 0;
+ return !m_devices.empty();
}
- }
-
- // set up the tilemap state
- state.tilemap.which = 0;
- state.tilemap.xoffs = 0;
- state.tilemap.yoffs = 0;
- state.tilemap.zoom = 1;
- state.tilemap.zoom_frac = false;
- state.tilemap.auto_zoom = true;
- state.tilemap.rotate = rotate;
- state.tilemap.flags = TILEMAP_DRAW_ALL_CATEGORIES;
-}
+ bool handle_keys(running_machine &machine, int xcells, int ycells);
-//-------------------------------------------------
-// ui_gfx_count_devices - count the palettes,
-// gfx decoders and gfx sets in the machine
-//-------------------------------------------------
+ std::vector<devinfo> m_devices;
+ unsigned m_device = 0U;
+ unsigned m_set = 0U;
-static void ui_gfx_count_devices(running_machine &machine, ui_gfx_state &state)
-{
- // count the palette devices
- state.palette.devcount = palette_interface_enumerator(machine.root_device()).count();
+ private:
+ bool next_group() noexcept
+ {
+ if ((m_devices[m_device].m_setcount - 1) > m_set)
+ {
+ ++m_set;
+ return true;
+ }
+ else if ((m_devices.size() - 1) > m_device)
+ {
+ ++m_device;
+ m_set = 0U;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
- // set the pointer to the first palette
- if (state.palette.devcount > 0)
- palette_set_device(machine, state);
+ bool prev_group() noexcept
+ {
+ if (m_set)
+ {
+ --m_set;
+ return true;
+ }
+ else if (m_device)
+ {
+ m_set = m_devices[--m_device].m_setcount - 1;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ };
- // count the gfx devices
- state.gfxset.devcount = 0;
- for (device_gfx_interface &interface : gfx_interface_enumerator(machine.root_device()))
+ class tilemap
{
- // count the gfx sets in each device, skipping devices with none
- uint8_t count = 0;
- while (count < MAX_GFX_ELEMENTS && interface.gfx(count) != nullptr)
- count++;
+ public:
+ bool handle_keys(running_machine &machine, float pixelscale);
+
+ unsigned m_index = 0U;
+ int m_xoffs = 0;
+ int m_yoffs = 0;
+ unsigned m_zoom = 1U;
+ bool m_zoom_frac = false;
+ bool m_auto_zoom = true;
+ uint8_t m_rotate = 0U;
+ uint32_t m_flags = TILEMAP_DRAW_ALL_CATEGORIES;
+
+ private:
+ static constexpr int MAX_ZOOM_LEVEL = 8; // maximum tilemap zoom ratio screen:native
+ static constexpr int MIN_ZOOM_LEVEL = 8; // minimum tilemap zoom ratio native:screen
+
+ bool zoom_in(float pixelscale) noexcept
+ {
+ if (m_auto_zoom)
+ {
+ // auto zoom never uses fractional factors
+ m_zoom = std::min<int>(std::lround(pixelscale) + 1, MAX_ZOOM_LEVEL);
+ m_zoom_frac = false;
+ m_auto_zoom = false;
+ return true;
+ }
+ else if (m_zoom_frac || (MAX_ZOOM_LEVEL > m_zoom))
+ {
+ if (!m_zoom_frac)
+ {
+ // remaining in integer zoom range
+ m_zoom++;
+ }
+ else if (m_zoom == 2)
+ {
+ // entering integer zoom range
+ m_zoom--;
+ m_zoom_frac = false;
+ }
+ else
+ {
+ // remaining in fractional zoom range
+ m_zoom--;
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
- // count = index of first nullptr
- if (count > 0)
+ bool zoom_out(float pixelscale) noexcept
{
- state.gfxdev[state.gfxset.devcount].interface = &interface;
- state.gfxdev[state.gfxset.devcount].setcount = count;
- for (uint8_t slot = 0; slot != count; slot++) {
- auto gfx = interface.gfx(slot);
- if (gfx->has_palette())
+ if (m_auto_zoom)
+ {
+ // auto zoom never uses fractional factors
+ m_zoom = std::lround(pixelscale) - 1;
+ m_zoom_frac = !m_zoom;
+ if (m_zoom_frac)
+ m_zoom = 2;
+ m_auto_zoom = false;
+ return true;
+ }
+ else if (!m_zoom_frac || (MIN_ZOOM_LEVEL > m_zoom))
+ {
+ if (m_zoom_frac)
+ {
+ // remaining in fractional zoom range
+ m_zoom++;
+ }
+ else if (m_zoom == 1)
{
- state.gfxdev[state.gfxset.devcount].palette[slot] = &gfx->palette();
- state.gfxdev[state.gfxset.devcount].color_count[slot] = gfx->colors();
+ // entering fractional zoom range
+ m_zoom++;
+ m_zoom_frac = true;
}
else
{
- state.gfxdev[state.gfxset.devcount].palette[slot] = state.palette.interface;
- state.gfxdev[state.gfxset.devcount].color_count[slot] = state.palette.interface->entries() / gfx->granularity();
- if (!state.gfxdev[state.gfxset.devcount].color_count[slot])
- state.gfxdev[state.gfxset.devcount].color_count[slot] = 1;
+ // remaining in integer zoom range
+ m_zoom--;
}
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool next_category() noexcept
+ {
+ if (TILEMAP_DRAW_ALL_CATEGORIES == m_flags)
+ {
+ m_flags = 0U;
+ return true;
+ }
+ else if (TILEMAP_DRAW_CATEGORY_MASK > m_flags)
+ {
+ ++m_flags;
+ return true;
+ }
+ else
+ {
+ return false;
}
- if (++state.gfxset.devcount == MAX_GFX_DECODERS)
- break;
}
+
+ bool prev_catagory() noexcept
+ {
+ if (!m_flags)
+ {
+ m_flags = TILEMAP_DRAW_ALL_CATEGORIES;
+ return true;
+ }
+ else if (TILEMAP_DRAW_ALL_CATEGORIES != m_flags)
+ {
+ --m_flags;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ static int scroll_step(running_machine &machine) noexcept
+ {
+ auto &input = machine.input();
+ if (input.code_pressed(KEYCODE_LCONTROL) || input.code_pressed(KEYCODE_RCONTROL))
+ return 64;
+ else if (input.code_pressed(KEYCODE_LSHIFT) || input.code_pressed(KEYCODE_RSHIFT))
+ return 1;
+ else
+ return 8;
+ }
+ };
+
+ bool is_relevant() const noexcept
+ {
+ return m_palette.interface() || m_gfxset.has_gfx() || m_machine.tilemap().count();
}
- state.started = true;
-}
+ uint32_t handle_general_keys(bool uistate)
+ {
+ auto &input = m_machine.ui_input();
+ // UI select cycles through views
+ if (input.pressed(IPT_UI_SELECT))
+ {
+ m_mode = view((int(m_mode) + 1) % 3);
+ m_bitmap_dirty = true;
+ }
-//-------------------------------------------------
-// ui_gfx_exit - clean up after ourselves
-//-------------------------------------------------
+ // pause does what you'd expect
+ if (input.pressed(IPT_UI_PAUSE))
+ {
+ if (m_machine.paused())
+ m_machine.resume();
+ else
+ m_machine.pause();
+ }
-static void ui_gfx_exit(running_machine &machine)
-{
- // free the texture
- machine.render().texture_free(ui_gfx.texture);
- ui_gfx.texture = nullptr;
+ // cancel or graphics viewer dismisses the viewer
+ if (input.pressed(IPT_UI_CANCEL) || input.pressed(IPT_UI_SHOW_GFX))
+ return cancel(uistate);
- // free the bitmap
- ui_gfx.bitmap.reset();
-}
+ return uistate;
+ }
+ uint32_t cancel(bool uistate)
+ {
+ if (!uistate)
+ m_machine.resume();
+ m_bitmap_dirty = true;
+ return UI_HANDLER_CANCEL;
+ }
-//-------------------------------------------------
-// ui_gfx_is_relevant - returns 'true' if the
-// internal graphics viewer has relevance
-//
-// NOTE: this must not be called before machine
-// initialization is complete, as some drivers
-// create or modify gfx sets in VIDEO_START
-//-------------------------------------------------
+ uint32_t handle_palette(mame_ui_manager &mui, render_container &container, bool uistate);
+ uint32_t handle_gfxset(mame_ui_manager &mui, render_container &container, bool uistate);
+ uint32_t handle_tilemap(mame_ui_manager &mui, render_container &container, bool uistate);
-bool ui_gfx_is_relevant(running_machine &machine)
-{
- ui_gfx_state &state = ui_gfx;
+ void update_gfxset_bitmap(int xcells, int ycells, gfx_element &gfx);
+ void update_tilemap_bitmap(int width, int height);
- if (!state.started)
- ui_gfx_count_devices(machine, state);
+ void gfxset_draw_item(gfx_element &gfx, int index, int dstx, int dsty, gfxset::setinfo const &info);
- return state.palette.devcount > 0
- || state.gfxset.devcount > 0
- || machine.tilemap().count() > 0;
-}
+ void resize_bitmap(int32_t width, int32_t height)
+ {
+ if (!m_bitmap.valid() || !m_texture || (m_bitmap.width() != width) || (m_bitmap.height() != height))
+ {
+ // free the old stuff
+ if (m_texture)
+ m_machine.render().texture_free(m_texture);
+ // allocate new stuff
+ m_bitmap.resize(width, height);
+ m_texture = m_machine.render().texture_alloc();
+ m_texture->set_bitmap(m_bitmap, m_bitmap.cliprect(), TEXFORMAT_ARGB32);
-//-------------------------------------------------
-// ui_gfx_ui_handler - primary UI handler
-//-------------------------------------------------
+ // force a redraw
+ m_bitmap_dirty = true;
+ }
+ }
-uint32_t ui_gfx_ui_handler(render_container &container, mame_ui_manager &mui, bool uistate)
+ bool map_mouse(render_container &container, render_bounds const &clip, float &x, float &y) const
+ {
+ int32_t target_x, target_y;
+ bool button;
+ render_target *const target = m_machine.ui_input().find_mouse(&target_x, &target_y, &button);
+ if (!target)
+ return false;
+ else if (!target->map_point_container(target_x, target_y, container, x, y))
+ return false;
+ else
+ return clip.includes(x, y);
+ }
+
+ running_machine &m_machine;
+ view m_mode = view::PALETTE;
+
+ bitmap_rgb32 m_bitmap;
+ render_texture *m_texture = nullptr;
+ bool m_bitmap_dirty = false;
+
+ palette m_palette;
+ gfxset m_gfxset;
+ tilemap m_tilemap;
+};
+
+
+void gfx_viewer::palette::handle_keys(running_machine &machine)
{
- ui_gfx_state &state = ui_gfx;
+ auto &input = machine.ui_input();
- // if we have nothing, implicitly cancel
- if (!ui_gfx_is_relevant(mui.machine()))
- goto cancel;
+ // handle zoom (minus,plus)
+ if (input.pressed(IPT_UI_ZOOM_OUT))
+ m_columns = std::min<unsigned>(m_columns * 2, 64);
+ if (input.pressed(IPT_UI_ZOOM_IN))
+ m_columns = std::max<unsigned>(m_columns / 2, 4);
+ if (input.pressed(IPT_UI_ZOOM_DEFAULT))
+ m_columns = 16;
- // if we're not paused, mark the bitmap dirty
- if (!mui.machine().paused())
- state.bitmap_dirty = true;
+ // handle colormap selection (open bracket,close bracket)
+ if (input.pressed(IPT_UI_PREV_GROUP))
+ prev_group(machine);
+ if (input.pressed(IPT_UI_NEXT_GROUP))
+ next_group(machine);
- // switch off the state to display something
-again:
- switch (state.mode)
- {
- case UI_GFX_PALETTE:
- // if we have a palette, display it
- if (state.palette.devcount > 0)
- {
- palette_handler(mui, container, state);
- break;
- }
+ // cache some info in locals
+ int const total = (subset::INDIRECT == m_which) ? m_interface->indirect_entries() : m_interface->entries();
- state.mode++;
- [[fallthrough]];
- case UI_GFX_GFXSET:
- // if we have graphics sets, display them
- if (state.gfxset.devcount > 0)
- {
- gfxset_handler(mui, container, state);
- break;
- }
+ // determine number of entries per row and total
+ int const rowcount = m_columns;
+ int const screencount = rowcount * rowcount;
- state.mode++;
- [[fallthrough]];
- case UI_GFX_TILEMAP:
- // if we have tilemaps, display them
- if (mui.machine().tilemap().count() > 0)
- {
- tilemap_handler(mui, container, state);
- break;
- }
+ // handle keyboard navigation
+ if (input.pressed_repeat(IPT_UI_UP, 4))
+ m_offset -= rowcount;
+ if (input.pressed_repeat(IPT_UI_DOWN, 4))
+ m_offset += rowcount;
+ if (input.pressed_repeat(IPT_UI_PAGE_UP, 6))
+ m_offset -= screencount;
+ if (input.pressed_repeat(IPT_UI_PAGE_DOWN, 6))
+ m_offset += screencount;
+ if (input.pressed_repeat(IPT_UI_HOME, 4))
+ m_offset = 0;
+ if (input.pressed_repeat(IPT_UI_END, 4))
+ m_offset = total;
- state.mode = UI_GFX_PALETTE;
- goto again;
+ // clamp within range
+ if (m_offset + screencount > ((total + rowcount - 1) / rowcount) * rowcount)
+ m_offset = ((total + rowcount - 1) / rowcount) * rowcount - screencount;
+ if (m_offset < 0)
+ m_offset = 0;
+}
+
+
+bool gfx_viewer::gfxset::handle_keys(running_machine &machine, int xcells, int ycells)
+{
+ auto &input = machine.ui_input();
+ bool const shift_pressed = machine.input().code_pressed(KEYCODE_LSHIFT) || machine.input().code_pressed(KEYCODE_RSHIFT);
+ bool result = false;
+
+ // handle previous/next group
+ if (input.pressed(IPT_UI_PREV_GROUP) && prev_group())
+ result = true;
+ if (input.pressed(IPT_UI_NEXT_GROUP) && next_group())
+ result = true;
+
+ auto &info = m_devices[m_device];
+ auto &set = info.m_sets[m_set];
+ auto &gfx = *info.m_interface->gfx(m_set);
+
+ // handle cells per line (0/-/=)
+ if (input.pressed(IPT_UI_ZOOM_OUT) && (xcells < 128))
+ {
+ set.m_columns = xcells + 1;
+ set.m_integer_scale = shift_pressed;
+ result = true;
+ }
+ if (input.pressed(IPT_UI_ZOOM_IN) && (xcells > 2))
+ {
+ set.m_columns = xcells - 1;
+ set.m_integer_scale = shift_pressed;
+ result = true;
+ }
+ if (input.pressed(IPT_UI_ZOOM_DEFAULT) && ((xcells != 16) || (set.m_integer_scale != shift_pressed)))
+ {
+ set.m_columns = 16;
+ set.m_integer_scale = shift_pressed;
+ result = true;
}
- // handle keys
- if (mui.machine().ui_input().pressed(IPT_UI_SELECT))
+ // handle rotation (R)
+ if (input.pressed(IPT_UI_ROTATE))
{
- state.mode = (state.mode + 1) % 3;
- state.bitmap_dirty = true;
+ set.m_rotate = orientation_add(ROT90, set.m_rotate);
+ result = true;
}
- if (mui.machine().ui_input().pressed(IPT_UI_PAUSE))
+ // handle navigation within the cells (up,down,pgup,pgdown)
+ if (input.pressed_repeat(IPT_UI_UP, 4))
{
- if (mui.machine().paused())
- mui.machine().resume();
- else
- mui.machine().pause();
+ set.m_offset -= xcells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_DOWN, 4))
+ {
+ set.m_offset += xcells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_PAGE_UP, 6))
+ {
+ set.m_offset -= xcells * ycells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_PAGE_DOWN, 6))
+ {
+ set.m_offset += xcells * ycells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_HOME, 4))
+ {
+ set.m_offset = 0;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_END, 4))
+ {
+ set.m_offset = gfx.elements();
+ result = true;
}
- if (mui.machine().ui_input().pressed(IPT_UI_CANCEL) || mui.machine().ui_input().pressed(IPT_UI_SHOW_GFX))
- goto cancel;
+ // clamp within range
+ if (set.m_offset + xcells * ycells > ((gfx.elements() + xcells - 1) / xcells) * xcells)
+ {
+ set.m_offset = ((gfx.elements() + xcells - 1) / xcells) * xcells - xcells * ycells;
+ result = true;
+ }
+ if (set.m_offset < 0)
+ {
+ set.m_offset = 0;
+ result = true;
+ }
- return uistate;
+ // handle color selection (left,right)
+ if (input.pressed_repeat(IPT_UI_LEFT, 4))
+ {
+ set.prev_color();
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_RIGHT, 4))
+ {
+ set.next_color();
+ result = true;
+ }
-cancel:
- if (!uistate)
- mui.machine().resume();
- state.bitmap_dirty = true;
- return UI_HANDLER_CANCEL;
+ return result;
}
+bool gfx_viewer::tilemap::handle_keys(running_machine &machine, float pixelscale)
+{
+ auto &input = machine.ui_input();
+ bool result = false;
-/***************************************************************************
- PALETTE VIEWER
-***************************************************************************/
+ // handle tilemap selection (open bracket,close bracket)
+ if (input.pressed(IPT_UI_PREV_GROUP) && m_index > 0)
+ {
+ m_index--;
+ result = true;
+ }
+ if (input.pressed(IPT_UI_NEXT_GROUP) && m_index < machine.tilemap().count() - 1)
+ {
+ m_index++;
+ result = true;
+ }
-//-------------------------------------------------
-// palette_set_device - set the pointer to the
-// current palette device
-//-------------------------------------------------
+ // handle zoom (minus,plus)
+ if (input.pressed(IPT_UI_ZOOM_OUT) && zoom_out(pixelscale))
+ {
+ result = true;
+ machine.popmessage(m_zoom_frac ? _("Zoom = 1/%1$d") : _("Zoom = %1$d"), m_zoom);
+ }
+ if (input.pressed(IPT_UI_ZOOM_IN) && zoom_in(pixelscale))
+ {
+ result = true;
+ machine.popmessage(m_zoom_frac ? _("Zoom = 1/%1$d") : _("Zoom = %1$d"), m_zoom);
+ }
+ if (input.pressed(IPT_UI_ZOOM_DEFAULT) && !m_auto_zoom)
+ {
+ m_auto_zoom = true;
+ machine.popmessage(_("Expand to fit"));
+ }
-static void palette_set_device(running_machine &machine, ui_gfx_state &state)
-{
- palette_interface_enumerator pal_iter(machine.root_device());
- state.palette.interface = pal_iter.byindex(state.palette.devindex);
-}
+ // handle rotation (R)
+ if (input.pressed(IPT_UI_ROTATE))
+ {
+ m_rotate = orientation_add(ROT90, m_rotate);
+ result = true;
+ }
+ // return to (0,0) (HOME)
+ if (input.pressed(IPT_UI_HOME))
+ {
+ m_xoffs = 0;
+ m_yoffs = 0;
+ result = true;
+ }
+
+ // handle flags (category)
+ if (input.pressed(IPT_UI_PAGE_UP) && prev_catagory())
+ {
+ result = true;
+ if (TILEMAP_DRAW_ALL_CATEGORIES == m_flags)
+ machine.popmessage("Category All");
+ else
+ machine.popmessage("Category = %d", m_flags);
+ }
+ if (input.pressed(IPT_UI_PAGE_DOWN) && next_category())
+ {
+ result = true;
+ machine.popmessage("Category = %d", m_flags);
+ }
+
+ // handle navigation (up,down,left,right), taking orientation into account
+ int const step = scroll_step(machine); // this may be applied more than once if multiple directions are pressed
+ if (input.pressed_repeat(IPT_UI_UP, 4))
+ {
+ if (m_rotate & ORIENTATION_SWAP_XY)
+ m_xoffs -= (m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ else
+ m_yoffs -= (m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_DOWN, 4))
+ {
+ if (m_rotate & ORIENTATION_SWAP_XY)
+ m_xoffs += (m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ else
+ m_yoffs += (m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_LEFT, 6))
+ {
+ if (m_rotate & ORIENTATION_SWAP_XY)
+ m_yoffs -= (m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ else
+ m_xoffs -= (m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_RIGHT, 6))
+ {
+ if (m_rotate & ORIENTATION_SWAP_XY)
+ m_yoffs += (m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ else
+ m_xoffs += (m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ result = true;
+ }
+
+ // cache some info in locals
+ tilemap_t *const tilemap = machine.tilemap().find(m_index);
+ uint32_t const mapwidth = tilemap->width();
+ uint32_t const mapheight = tilemap->height();
+
+ // clamp within range
+ while (m_xoffs < 0)
+ m_xoffs += mapwidth;
+ while (m_xoffs >= mapwidth)
+ m_xoffs -= mapwidth;
+ while (m_yoffs < 0)
+ m_yoffs += mapheight;
+ while (m_yoffs >= mapheight)
+ m_yoffs -= mapheight;
+
+ return result;
+}
-//-------------------------------------------------
-// palette_handler - handler for the palette
-// viewer
-//-------------------------------------------------
-static void palette_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state)
+uint32_t gfx_viewer::handle_palette(mame_ui_manager &mui, render_container &container, bool uistate)
{
- device_palette_interface *palette = state.palette.interface;
- palette_device *paldev = dynamic_cast<palette_device *>(&palette->device());
+ device_palette_interface &palette = *m_palette.interface();
+ palette_device *const paldev = dynamic_cast<palette_device *>(&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 = mui.get_font();
- float titlewidth;
- float x0, y0;
- render_bounds cellboxbounds;
- render_bounds boxbounds;
- int skip;
+ bool const indirect = m_palette.indirect();
+ unsigned const total = indirect ? palette.indirect_entries() : palette.entries();
+ rgb_t const *const raw_color = palette.palette()->entry_list_raw();
+ render_font *const ui_font = mui.get_font();
// add a half character padding for the box
- const float aspect = mui.machine().render().ui_aspect(&container);
- const float chheight = mui.get_line_height();
- const float chwidth = ui_font->char_width(chheight, 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;
+ float const aspect = m_machine.render().ui_aspect(&container);
+ float const chheight = mui.get_line_height();
+ float const chwidth = ui_font->char_width(chheight, aspect, '0');
+ render_bounds const boxbounds{
+ 0.0f + (0.5f * chwidth),
+ 0.0f + (0.5f * chheight),
+ 1.0f - (0.5f * chwidth),
+ 1.0f - (0.5f * chheight) };
// the character cell box bounds starts a half character in from the box
- cellboxbounds = boxbounds;
+ render_bounds cellboxbounds = boxbounds;
cellboxbounds.x0 += 0.5f * chwidth;
- cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y0 += 0.5f * chheight;
+ cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y1 -= 0.5f * chheight;
// add space on the left for 5 characters of text, plus a half character of padding
@@ -427,41 +839,38 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u
cellboxbounds.y0 += 3.0f * chheight;
// compute the cell size
- const float cellwidth = (cellboxbounds.x1 - cellboxbounds.x0) / float(state.palette.columns);
- const float cellheight = (cellboxbounds.y1 - cellboxbounds.y0) / float(state.palette.columns);
+ float const cellwidth = (cellboxbounds.x1 - cellboxbounds.x0) / float(m_palette.columns());
+ float const cellheight = (cellboxbounds.y1 - cellboxbounds.y0) / float(m_palette.columns());
// figure out the title
std::ostringstream title_buf;
- util::stream_format(title_buf, "'%s'", palette->device().tag());
- if (palette->indirect_entries() > 0)
- title_buf << (state.palette.which ? _(" COLORS") : _(" PENS"));
+ util::stream_format(title_buf, "'%s'", palette.device().tag());
+ if (palette.indirect_entries() > 0)
+ title_buf << (indirect ? _(" COLORS") : _(" PENS"));
// if the mouse pointer is over one of our cells, add some info about the corresponding palette entry
- int32_t mouse_target_x, mouse_target_y;
float mouse_x, mouse_y;
- bool mouse_button;
- render_target *const mouse_target = mui.machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target != nullptr && mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)
- && cellboxbounds.x0 <= mouse_x && cellboxbounds.x1 > mouse_x
- && cellboxbounds.y0 <= mouse_y && cellboxbounds.y1 > mouse_y)
+ if (map_mouse(container, cellboxbounds, mouse_x, mouse_y))
{
- int index = state.palette.offset + int((mouse_x - cellboxbounds.x0) / cellwidth) + int((mouse_y - cellboxbounds.y0) / cellheight) * state.palette.columns;
+ int const index = m_palette.index(int((mouse_x - cellboxbounds.x0) / cellwidth), int((mouse_y - cellboxbounds.y0) / cellheight));
if (index < total)
{
util::stream_format(title_buf, " #%X", index);
- if (palette->indirect_entries() > 0 && !state.palette.which)
- util::stream_format(title_buf, " => %X", palette->pen_indirect(index));
- else if (paldev != nullptr && paldev->basemem().base() != nullptr)
+ if (palette.indirect_entries() && indirect)
+ util::stream_format(title_buf, " => %X", palette.pen_indirect(index));
+ else if (paldev && paldev->basemem().base())
util::stream_format(title_buf, " = %X", paldev->read_entry(index));
- rgb_t col = state.palette.which ? palette->indirect_color(index) : raw_color[index];
+ rgb_t const col = indirect ? palette.indirect_color(index) : raw_color[index];
util::stream_format(title_buf, " (A:%X R:%X G:%X B:%X)", col.a(), col.r(), col.g(), col.b());
}
}
+ float x0, y0;
+
// expand the outer box to fit the title
- const std::string title = title_buf.str();
- titlewidth = ui_font->string_width(chheight, aspect, title);
+ std::string const title = std::move(title_buf).str();
+ float const titlewidth = ui_font->string_width(chheight, aspect, title);
x0 = 0.0f;
if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));
@@ -479,177 +888,95 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u
}
// draw the top column headers
- skip = int(chwidth / cellwidth);
- for (int x = 0; x < state.palette.columns; x += 1 + skip)
+ int const rowskip = int(chwidth / cellwidth);
+ for (int x = 0; x < m_palette.columns(); x += 1 + rowskip)
{
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, aspect, rgb_t::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)
+ // if we're skipping, draw a point between the character and the box to indicate which one it's referring to
+ if (rowskip)
container.add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + cellboxbounds.y0), UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
// draw the side column headers
- skip = int(chheight / cellheight);
- for (int y = 0; y < state.palette.columns; y += 1 + skip)
-
+ int const colskip = int(chheight / cellheight);
+ for (int y = 0; y < m_palette.columns(); y += 1 + colskip)
+ {
// only display if there is data to show
- if (state.palette.offset + y * state.palette.columns < total)
+ unsigned const index = m_palette.index(0, y);
+ if (index < 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)
+ if (colskip != 0)
container.add_point(0.5f * (x0 + cellboxbounds.x0), y0 + 0.5f * cellheight, UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
// draw the row header
- sprintf(buffer, "%5X", state.palette.offset + y * state.palette.columns);
+ char buffer[10];
+ sprintf(buffer, "%5X", index);
for (int x = 4; x >= 0; x--)
{
x0 -= ui_font->char_width(chheight, aspect, buffer[x]);
container.add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, aspect, rgb_t::white(), *ui_font, buffer[x]);
}
}
+ }
// now add the rectangles for the colors
- for (int y = 0; y < state.palette.columns; y++)
- for (int x = 0; x < state.palette.columns; x++)
+ for (int y = 0; y < m_palette.columns(); y++)
+ {
+ for (int x = 0; x < m_palette.columns(); x++)
{
- int index = state.palette.offset + y * state.palette.columns + x;
+ int const index = m_palette.index(x, y);
if (index < total)
{
- const 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));
+ pen_t const pen = indirect ? 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(mui.machine(), state);
-}
-
-
-//-------------------------------------------------
-// palette_handle_keys - handle key inputs for
-// the palette viewer
-//-------------------------------------------------
-
-static void palette_handle_keys(running_machine &machine, ui_gfx_state &state)
-{
- device_palette_interface *palette = state.palette.interface;
- // handle zoom (minus,plus)
- if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT))
- state.palette.columns = std::min<uint8_t>(state.palette.columns * 2, 64);
- if (machine.ui_input().pressed(IPT_UI_ZOOM_IN))
- state.palette.columns = std::max<uint8_t>(state.palette.columns / 2, 4);
- if (machine.ui_input().pressed(IPT_UI_ZOOM_DEFAULT))
- state.palette.columns = 16;
-
- // handle colormap selection (open bracket,close bracket)
- if (machine.ui_input().pressed(IPT_UI_PREV_GROUP))
- {
- if (state.palette.which)
- state.palette.which = 0;
- else if (state.palette.devindex > 0)
- {
- state.palette.devindex--;
- palette_set_device(machine, state);
- palette = state.palette.interface;
- state.palette.which = (palette->indirect_entries() > 0);
- }
- }
- if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP))
- {
- if (!state.palette.which && palette->indirect_entries() > 0)
- state.palette.which = 1;
- else if (state.palette.devindex < state.palette.devcount - 1)
- {
- state.palette.devindex++;
- palette_set_device(machine, state);
- palette = state.palette.interface;
- state.palette.which = 0;
- }
}
- // cache some info in locals
- const int total = state.palette.which ? palette->indirect_entries() : palette->entries();
-
- // determine number of entries per row and total
- const int rowcount = state.palette.columns;
- const int screencount = rowcount * rowcount;
-
- // handle keyboard navigation
- if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
- state.palette.offset -= rowcount;
- if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
- state.palette.offset += rowcount;
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_UP, 6))
- state.palette.offset -= screencount;
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_DOWN, 6))
- state.palette.offset += screencount;
- if (machine.ui_input().pressed_repeat(IPT_UI_HOME, 4))
- state.palette.offset = 0;
- if (machine.ui_input().pressed_repeat(IPT_UI_END, 4))
- state.palette.offset = total;
-
- // clamp within range
- if (state.palette.offset + screencount > ((total + rowcount - 1) / rowcount) * rowcount)
- state.palette.offset = ((total + rowcount - 1) / rowcount) * rowcount - screencount;
- if (state.palette.offset < 0)
- state.palette.offset = 0;
+ // handle keys
+ m_palette.handle_keys(m_machine);
+ return handle_general_keys(uistate);
}
-
-/***************************************************************************
- GRAPHICS VIEWER
-***************************************************************************/
-
-//-------------------------------------------------
-// gfxset_handler - handler for the graphics
-// viewer
-//-------------------------------------------------
-
-static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state)
+uint32_t gfx_viewer::handle_gfxset(mame_ui_manager &mui, render_container &container, bool uistate)
{
- render_font *ui_font = mui.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 x0, y0;
- render_bounds cellboxbounds;
- render_bounds boxbounds;
- float cellboxwidth, cellboxheight;
- int targwidth = mui.machine().render().ui_target().width();
- int targheight = mui.machine().render().ui_target().height();
- int cellxpix, cellypix;
- int xcells;
- float pixelscale = 0.0f;
- int skip;
+ // get graphics info
+ auto &info = m_gfxset.m_devices[m_gfxset.m_device];
+ auto &set = info.m_sets[m_gfxset.m_set];
+ device_gfx_interface &interface = *info.m_interface;
+ gfx_element &gfx = *interface.gfx(m_gfxset.m_set);
+
+ // get some UI metrics
+ render_font *const ui_font = mui.get_font();
+ int const targwidth = m_machine.render().ui_target().width();
+ int const targheight = m_machine.render().ui_target().height();
+ float const aspect = m_machine.render().ui_aspect(&container);
+ float const chheight = mui.get_line_height();
+ float const chwidth = ui_font->char_width(chheight, aspect, '0');
// add a half character padding for the box
- const float aspect = mui.machine().render().ui_aspect(&container);
- const float chheight = mui.get_line_height();
- const float chwidth = ui_font->char_width(chheight, 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;
+ render_bounds boxbounds{
+ 0.0f + (0.5f * chwidth),
+ 0.0f + (0.5f * chheight),
+ 1.0f - (0.5f * chwidth),
+ 1.0f - (0.5f * chheight) };
// the character cell box bounds starts a half character in from the box
- cellboxbounds = boxbounds;
+ render_bounds cellboxbounds = boxbounds;
cellboxbounds.x0 += 0.5f * chwidth;
- cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y0 += 0.5f * chheight;
+ cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y1 -= 0.5f * chheight;
// add space on the left for 5 characters of text, plus a half character of padding
@@ -659,92 +986,90 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui
cellboxbounds.y0 += 3.0f * chheight;
// convert back to pixels
- cellboxwidth = (cellboxbounds.x1 - cellboxbounds.x0) * float(targwidth);
- cellboxheight = (cellboxbounds.y1 - cellboxbounds.y0) * float(targheight);
+ float cellboxwidth = cellboxbounds.width() * float(targwidth);
+ float cellboxheight = cellboxbounds.height() * 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());
+ int const cellxpix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
+ int const cellypix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
// compute the largest pixel scale factor that still fits
- xcells = info.columns[set];
+ int xcells = set.m_columns;
+ float pixelscale = 0.0f;
while (xcells > 1)
{
pixelscale = (cellboxwidth / xcells) / cellxpix;
- if (pixelscale != 0)
+ if (set.m_integer_scale)
+ pixelscale = std::floor(pixelscale);
+ if (0.25f <= pixelscale)
break;
xcells--;
}
- info.columns[set] = xcells;
-
- if (pixelscale <= 0.0f)
- pixelscale = 1.0f;
+ set.m_columns = xcells;
// in the Y direction, we just display as many as we can
- const int ycells = int(cellboxheight / (pixelscale * cellypix));
+ int const ycells = int(cellboxheight / (pixelscale * cellypix));
// now determine the actual cellbox size
cellboxwidth = std::min(cellboxwidth, xcells * pixelscale * cellxpix);
cellboxheight = std::min(cellboxheight, ycells * pixelscale * cellypix);
// compute the size of a single cell at this pixel scale factor
- const float cellwidth = (cellboxwidth / xcells) / targwidth;
- const float cellheight = (cellboxheight / ycells) / targheight;
+ float const cellwidth = (cellboxwidth / xcells) / targwidth;
+ float const cellheight = (cellboxheight / ycells) / targheight;
// working from the new width/height, recompute the boxbounds
- const float fullwidth = cellboxwidth / targwidth + 6.5f * chwidth;
- const float fullheight = cellboxheight / targheight + 4.0f * chheight;
+ float const fullwidth = cellboxwidth / targwidth + 6.5f * chwidth;
+ float const fullheight = cellboxheight / 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.x1 = boxbounds.x0 + fullwidth;
boxbounds.y1 = boxbounds.y0 + fullheight;
// recompute cellboxbounds
cellboxbounds.x0 = boxbounds.x0 + 6.0f * chwidth;
- cellboxbounds.x1 = cellboxbounds.x0 + cellboxwidth / float(targwidth);
cellboxbounds.y0 = boxbounds.y0 + 3.5f * chheight;
+ cellboxbounds.x1 = cellboxbounds.x0 + cellboxwidth / float(targwidth);
cellboxbounds.y1 = cellboxbounds.y0 + cellboxheight / float(targheight);
// figure out the title
std::ostringstream title_buf;
- util::stream_format(title_buf, "'%s' %d/%d", interface.device().tag(), set, info.setcount - 1);
+ util::stream_format(title_buf, "'%s' %d/%d", interface.device().tag(), m_gfxset.m_set, info.m_setcount - 1);
// if the mouse pointer is over a pixel in a tile, add some info about the tile and pixel
bool found_pixel = false;
- int32_t mouse_target_x, mouse_target_y;
float mouse_x, mouse_y;
- bool mouse_button;
- render_target *const mouse_target = mui.machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target != nullptr && mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)
- && cellboxbounds.x0 <= mouse_x && cellboxbounds.x1 > mouse_x
- && cellboxbounds.y0 <= mouse_y && cellboxbounds.y1 > mouse_y)
+ if (map_mouse(container, cellboxbounds, mouse_x, mouse_y))
{
- int code = info.offset[set] + int((mouse_x - cellboxbounds.x0) / cellwidth) + int((mouse_y - cellboxbounds.y0) / cellheight) * xcells;
+ int const code = set.m_offset + int((mouse_x - cellboxbounds.x0) / cellwidth) + int((mouse_y - cellboxbounds.y0) / cellheight) * xcells;
int xpixel = int((mouse_x - cellboxbounds.x0) / (cellwidth / cellxpix)) % cellxpix;
int ypixel = int((mouse_y - cellboxbounds.y0) / (cellheight / cellypix)) % cellypix;
- if (code < gfx.elements() && xpixel < (cellxpix - 1) && ypixel < (cellypix - 1))
+ if ((code < gfx.elements()) && (xpixel < (cellxpix - 1)) && (ypixel < (cellypix - 1)))
{
found_pixel = true;
- if (info.rotate[set] & ORIENTATION_FLIP_X)
+ if (set.m_rotate & ORIENTATION_FLIP_X)
xpixel = (cellxpix - 2) - xpixel;
- if (info.rotate[set] & ORIENTATION_FLIP_Y)
+ if (set.m_rotate & ORIENTATION_FLIP_Y)
ypixel = (cellypix - 2) - ypixel;
- if (info.rotate[set] & ORIENTATION_SWAP_XY)
+ if (set.m_rotate & ORIENTATION_SWAP_XY)
std::swap(xpixel, ypixel);
- uint8_t pixdata = gfx.get_data(code)[xpixel + ypixel * gfx.rowbytes()];
+ uint8_t const pixdata = gfx.get_data(code)[xpixel + ypixel * gfx.rowbytes()];
util::stream_format(title_buf, " #%X:%X @ %d,%d = %X",
- code, info.color[set], xpixel, ypixel,
- gfx.colorbase() + info.color[set] * gfx.granularity() + pixdata);
+ code, set.m_color,
+ xpixel, ypixel,
+ gfx.colorbase() + (set.m_color * gfx.granularity()) + pixdata);
}
}
if (!found_pixel)
- util::stream_format(title_buf, " %dx%d COLOR %X/%X", gfx.width(), gfx.height(), info.color[set], info.color_count[set]);
+ util::stream_format(title_buf, " %dx%d COLOR %X/%X", gfx.width(), gfx.height(), set.m_color, set.m_color_count);
+
+ float x0, y0;
// expand the outer box to fit the title
- const std::string title = title_buf.str();
- const float titlewidth = ui_font->string_width(chheight, aspect, title);
+ std::string const title = std::move(title_buf).str();
+ float const titlewidth = ui_font->string_width(chheight, aspect, title);
x0 = 0.0f;
if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));
@@ -762,303 +1087,83 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui
}
// draw the top column headers
- skip = int(chwidth / cellwidth);
- for (int x = 0; x < xcells; x += 1 + skip)
+ int const colskip = int(chwidth / cellwidth);
+ for (int x = 0; x < xcells; x += 1 + colskip)
{
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, aspect, rgb_t::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)
+ // if we're skipping, draw a point between the character and the box to indicate which one it's referring to
+ if (colskip)
container.add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + boxbounds.y0 + 3.5f * chheight), UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
// draw the side column headers
- skip = int(chheight / cellheight);
- for (int y = 0; y < ycells; y += 1 + skip)
-
+ int const rowskip = int(chheight / cellheight);
+ for (int y = 0; y < ycells; y += 1 + rowskip)
+ {
// only display if there is data to show
- if (info.offset[set] + y * xcells < gfx.elements())
+ if (set.m_offset + (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
+ // 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)
+ if (rowskip)
container.add_point(0.5f * (x0 + boxbounds.x0 + 6.0f * chwidth), y0 + 0.5f * cellheight, UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
// draw the row header
- sprintf(buffer, "%5X", info.offset[set] + y * xcells);
+ char buffer[10];
+ sprintf(buffer, "%5X", set.m_offset + (y * xcells));
for (int x = 4; x >= 0; x--)
{
x0 -= ui_font->char_width(chheight, aspect, buffer[x]);
container.add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, aspect, rgb_t::white(), *ui_font, buffer[x]);
}
}
+ }
// update the bitmap
- gfxset_update_bitmap(mui.machine(), state, xcells, ycells, gfx);
+ update_gfxset_bitmap(xcells, ycells, gfx);
// add the final quad
- container.add_quad(cellboxbounds.x0, cellboxbounds.y0, cellboxbounds.x1, cellboxbounds.y1,
- rgb_t::white(), state.texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container.add_quad(
+ cellboxbounds.x0, cellboxbounds.y0, cellboxbounds.x1, cellboxbounds.y1,
+ rgb_t::white(), m_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
// handle keyboard navigation before drawing
- gfxset_handle_keys(mui.machine(), state, xcells, ycells);
-}
-
-
-//-------------------------------------------------
-// gfxset_handle_keys - handle keys for the
-// graphics viewer
-//-------------------------------------------------
-
-static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, int xcells, int ycells)
-{
- // handle gfxset selection (open bracket,close bracket)
- if (machine.ui_input().pressed(IPT_UI_PREV_GROUP))
- {
- if (state.gfxset.set > 0)
- state.gfxset.set--;
- else if (state.gfxset.devindex > 0)
- {
- state.gfxset.devindex--;
- state.gfxset.set = state.gfxdev[state.gfxset.devindex].setcount - 1;
- }
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP))
- {
- if (state.gfxset.set < state.gfxdev[state.gfxset.devindex].setcount - 1)
- state.gfxset.set++;
- else if (state.gfxset.devindex < state.gfxset.devcount - 1)
- {
- state.gfxset.devindex++;
- state.gfxset.set = 0;
- }
- state.bitmap_dirty = true;
- }
-
- // cache some info in locals
- int dev = state.gfxset.devindex;
- int set = state.gfxset.set;
- ui_gfx_info &info = state.gfxdev[dev];
- gfx_element &gfx = *info.interface->gfx(set);
-
- // handle cells per line (minus,plus)
- if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && (xcells < 128))
- { info.columns[set] = xcells + 1; state.bitmap_dirty = true; }
-
- if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && (xcells > 2))
- { info.columns[set] = xcells - 1; state.bitmap_dirty = true; }
-
- if (machine.ui_input().pressed(IPT_UI_ZOOM_DEFAULT) && (xcells != 16))
- { info.columns[set] = 16; state.bitmap_dirty = true; }
-
- // handle rotation (R)
- if (machine.ui_input().pressed(IPT_UI_ROTATE))
- {
- info.rotate[set] = orientation_add(ROT90, info.rotate[set]);
- state.bitmap_dirty = true;
- }
-
- // handle navigation within the cells (up,down,pgup,pgdown)
- if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
- { info.offset[set] -= xcells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
- { info.offset[set] += xcells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_UP, 6))
- { info.offset[set] -= xcells * ycells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_DOWN, 6))
- { info.offset[set] += xcells * ycells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_HOME, 4))
- { info.offset[set] = 0; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_END, 4))
- { info.offset[set] = gfx.elements(); state.bitmap_dirty = true; }
-
- // clamp within range
- if (info.offset[set] + xcells * ycells > ((gfx.elements() + xcells - 1) / xcells) * xcells)
- {
- info.offset[set] = ((gfx.elements() + xcells - 1) / xcells) * xcells - xcells * ycells;
- state.bitmap_dirty = true;
- }
- if (info.offset[set] < 0)
- { info.offset[set] = 0; state.bitmap_dirty = true; }
-
- // handle color selection (left,right)
- if (machine.ui_input().pressed_repeat(IPT_UI_LEFT, 4))
- { info.color[set] -= 1; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_RIGHT, 4))
- { info.color[set] += 1; state.bitmap_dirty = true; }
-
- // clamp within range
- if (info.color[set] >= info.color_count[set])
- { info.color[set] = info.color_count[set] - 1; state.bitmap_dirty = true; }
- if (info.color[set] < 0)
- { info.color[set] = 0; state.bitmap_dirty = true; }
-}
-
-
-//-------------------------------------------------
-// gfxset_update_bitmap - redraw the current
-// graphics view bitmap
-//-------------------------------------------------
-
-static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, int xcells, int ycells, gfx_element &gfx)
-{
- const int dev = state.gfxset.devindex;
- const int set = state.gfxset.set;
- ui_gfx_info &info = state.gfxdev[dev];
-
- // compute the number of source pixels in a cell
- const int cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
- const int cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
-
- // realloc the bitmap if it is too small
- if (!state.bitmap.valid() || !state.texture || state.bitmap.width() != cellxpix * xcells || state.bitmap.height() != cellypix * ycells)
- {
- // free the old stuff
- machine.render().texture_free(state.texture);
- state.bitmap.reset();
-
- // allocate new stuff
- state.bitmap.allocate(cellxpix * xcells, cellypix * ycells);
- state.texture = machine.render().texture_alloc();
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_ARGB32);
-
- // force a redraw
- state.bitmap_dirty = true;
- }
-
- // handle the redraw
- if (state.bitmap_dirty)
- {
- // loop over rows
- for (int y = 0, index = info.offset[set]; y < ycells; y++)
- {
- // make a rect that covers this row
- rectangle cellbounds(0, state.bitmap.width() - 1, y * cellypix, (y + 1) * cellypix - 1);
-
- // only display if there is data to show
- if (index < gfx.elements())
- {
- // draw the individual cells
- for (int x = 0; x < xcells; x++, index++)
- {
- // update the bounds for this cell
- cellbounds.min_x = x * cellxpix;
- cellbounds.max_x = (x + 1) * cellxpix - 1;
-
- if (index < gfx.elements()) // only render if there is data
- gfxset_draw_item(machine, gfx, index, state.bitmap, cellbounds.min_x, cellbounds.min_y, info.color[set], info.rotate[set], info.palette[set]);
- else // otherwise, fill with transparency
- state.bitmap.fill(0, cellbounds);
- }
- }
- else // otherwise, fill with transparency
- state.bitmap.fill(0, cellbounds);
- }
-
- // reset the texture to force an update
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_ARGB32);
- state.bitmap_dirty = false;
- }
-}
-
-
-//-------------------------------------------------
-// gfxset_draw_item - draw a single item into
-// the view
-//-------------------------------------------------
-
-static void gfxset_draw_item(running_machine &machine, gfx_element &gfx, int index, bitmap_rgb32 &bitmap, int dstx, int dsty, int color, int rotate, device_palette_interface *dpalette)
-{
- int width = (rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width();
- int height = (rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height();
- rgb_t const *const palette = dpalette->palette()->entry_list_raw() + gfx.colorbase() + color * gfx.granularity();
-
- // loop over rows in the cell
- for (int y = 0; y < height; y++)
- {
- uint32_t *dest = &bitmap.pix(dsty + y, dstx);
- const uint8_t *src = gfx.get_data(index);
-
- // loop over columns in the cell
- for (int x = 0; x < width; x++)
- {
- int effx = x, effy = y;
- const uint8_t *s;
-
- // compute effective x,y values after rotation
- if (!(rotate & ORIENTATION_SWAP_XY))
- {
- if (rotate & ORIENTATION_FLIP_X)
- effx = gfx.width() - 1 - effx;
- if (rotate & ORIENTATION_FLIP_Y)
- effy = gfx.height() - 1 - effy;
- }
- else
- {
- if (rotate & ORIENTATION_FLIP_X)
- effx = gfx.height() - 1 - effx;
- if (rotate & ORIENTATION_FLIP_Y)
- effy = gfx.width() - 1 - effy;
- std::swap(effx, effy);
- }
-
- // get a pointer to the start of this source row
- s = src + effy * gfx.rowbytes();
-
- // extract the pixel
- *dest++ = 0xff000000 | palette[s[effx]];
- }
- }
+ if (m_gfxset.handle_keys(m_machine, xcells, ycells))
+ m_bitmap_dirty = true;
+ return handle_general_keys(uistate);
}
-
-/***************************************************************************
- TILEMAP VIEWER
-***************************************************************************/
-
-//-------------------------------------------------
-// tilemap_handler - handler for the tilemap
-// viewer
-//-------------------------------------------------
-
-static void tilemap_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state)
+uint32_t gfx_viewer::handle_tilemap(mame_ui_manager &mui, render_container &container, bool uistate)
{
- render_font *ui_font = mui.get_font();
- render_bounds mapboxbounds;
- render_bounds boxbounds;
- const int targwidth = mui.machine().render().ui_target().width();
- const int targheight = mui.machine().render().ui_target().height();
- float titlewidth;
- float x0, y0;
- int mapboxwidth, mapboxheight;
+ // get some UI metrics
+ render_font *const ui_font = mui.get_font();
+ int const targwidth = m_machine.render().ui_target().width();
+ int const targheight = m_machine.render().ui_target().height();
+ float const aspect = m_machine.render().ui_aspect(&container);
+ float const chheight = mui.get_line_height();
+ float const chwidth = ui_font->char_width(chheight, aspect, '0');
// get the size of the tilemap itself
- tilemap_t *tilemap = mui.machine().tilemap().find(state.tilemap.which);
- uint32_t mapwidth = tilemap->width();
- uint32_t mapheight = tilemap->height();
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
+ tilemap_t &tilemap = *m_machine.tilemap().find(m_tilemap.m_index);
+ uint32_t mapwidth = tilemap.width();
+ uint32_t mapheight = tilemap.height();
+ if (m_tilemap.m_rotate & ORIENTATION_SWAP_XY)
std::swap(mapwidth, mapheight);
// add a half character padding for the box
- const float aspect = mui.machine().render().ui_aspect(&container);
- const float chheight = mui.get_line_height();
- const float chwidth = ui_font->char_width(chheight, 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;
+ render_bounds boxbounds{
+ 0.0f + (0.5f * chwidth),
+ 0.0f + (0.5f * chheight),
+ 1.0f - (0.5f * chwidth),
+ 1.0f - (0.5f * chheight) };
// the tilemap box bounds starts a half character in from the box
- mapboxbounds = boxbounds;
+ render_bounds mapboxbounds = boxbounds;
mapboxbounds.x0 += 0.5f * chwidth;
mapboxbounds.x1 -= 0.5f * chwidth;
mapboxbounds.y0 += 0.5f * chheight;
@@ -1068,11 +1173,11 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u
mapboxbounds.y0 += 1.5f * chheight;
// convert back to pixels
- mapboxwidth = (mapboxbounds.x1 - mapboxbounds.x0) * float(targwidth);
- mapboxheight = (mapboxbounds.y1 - mapboxbounds.y0) * float(targheight);
+ int mapboxwidth = mapboxbounds.width() * float(targwidth);
+ int mapboxheight = mapboxbounds.height() * float(targheight);
float pixelscale;
- if (state.tilemap.auto_zoom)
+ if (m_tilemap.m_auto_zoom)
{
// determine the maximum integral scaling factor
pixelscale = std::min(std::floor(mapboxwidth / mapwidth), std::floor(mapboxheight / mapheight));
@@ -1080,7 +1185,7 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u
}
else
{
- pixelscale = state.tilemap.zoom_frac ? (1.0f / state.tilemap.zoom) : float(state.tilemap.zoom);
+ pixelscale = m_tilemap.m_zoom_frac ? (1.0f / m_tilemap.m_zoom) : float(m_tilemap.m_zoom);
}
// recompute the final box size
@@ -1101,43 +1206,40 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u
// figure out the title
std::ostringstream title_buf;
- util::stream_format(title_buf, "TILEMAP %d/%d", state.tilemap.which + 1, mui.machine().tilemap().count());
+ util::stream_format(title_buf, "TILEMAP %d/%d", m_tilemap.m_index + 1, m_machine.tilemap().count());
// if the mouse pointer is over a tile, add some info about its coordinates and color
- int32_t mouse_target_x, mouse_target_y;
float mouse_x, mouse_y;
- bool mouse_button;
- render_target *const mouse_target = mui.machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target != nullptr && mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)
- && mapboxbounds.x0 <= mouse_x && mapboxbounds.x1 > mouse_x
- && mapboxbounds.y0 <= mouse_y && mapboxbounds.y1 > mouse_y)
+ if (map_mouse(container, mapboxbounds, mouse_x, mouse_y))
{
int xpixel = (mouse_x - mapboxbounds.x0) * targwidth;
int ypixel = (mouse_y - mapboxbounds.y0) * targheight;
- if (state.tilemap.rotate & ORIENTATION_FLIP_X)
+ if (m_tilemap.m_rotate & ORIENTATION_FLIP_X)
xpixel = (mapboxwidth - 1) - xpixel;
- if (state.tilemap.rotate & ORIENTATION_FLIP_Y)
+ if (m_tilemap.m_rotate & ORIENTATION_FLIP_Y)
ypixel = (mapboxheight - 1) - ypixel;
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
+ if (m_tilemap.m_rotate & ORIENTATION_SWAP_XY)
std::swap(xpixel, ypixel);
- uint32_t col = ((std::lround(xpixel / pixelscale) + state.tilemap.xoffs) / tilemap->tilewidth()) % tilemap->cols();
- uint32_t row = ((std::lround(ypixel / pixelscale) + state.tilemap.yoffs) / tilemap->tileheight()) % tilemap->rows();
+ uint32_t const col = ((std::lround(xpixel / pixelscale) + m_tilemap.m_xoffs) / tilemap.tilewidth()) % tilemap.cols();
+ uint32_t const row = ((std::lround(ypixel / pixelscale) + m_tilemap.m_yoffs) / tilemap.tileheight()) % tilemap.rows();
uint8_t gfxnum;
uint32_t code, color;
- tilemap->get_info_debug(col, row, gfxnum, code, color);
- util::stream_format(title_buf, " @ %d,%d = GFX%d #%X:%X",
- col * tilemap->tilewidth(), row * tilemap->tileheight(),
- int(gfxnum), code, color);
+ tilemap.get_info_debug(col, row, gfxnum, code, color);
+ util::stream_format(title_buf, " @ %u,%u = GFX%u #%X:%X",
+ col * tilemap.tilewidth(), row * tilemap.tileheight(),
+ gfxnum, code, color);
}
else
- util::stream_format(title_buf, " %dx%d OFFS %d,%d", tilemap->width(), tilemap->height(), state.tilemap.xoffs, state.tilemap.yoffs);
+ {
+ util::stream_format(title_buf, " %dx%d OFFS %d,%d", tilemap.width(), tilemap.height(), m_tilemap.m_xoffs, m_tilemap.m_yoffs);
+ }
- if (state.tilemap.flags != TILEMAP_DRAW_ALL_CATEGORIES)
- util::stream_format(title_buf, " CAT %d", state.tilemap.flags);
+ if (m_tilemap.m_flags != TILEMAP_DRAW_ALL_CATEGORIES)
+ util::stream_format(title_buf, " CAT %u", m_tilemap.m_flags);
// expand the outer box to fit the title
- const std::string title = title_buf.str();
- titlewidth = ui_font->string_width(chheight, aspect, title);
+ std::string const title = std::move(title_buf).str();
+ float const titlewidth = ui_font->string_width(chheight, aspect, title);
if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
{
boxbounds.x0 = 0.5f - 0.5f * (titlewidth + chwidth);
@@ -1148,8 +1250,8 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u
mui.draw_outlined_box(container, boxbounds.x0, boxbounds.y0, boxbounds.x1, boxbounds.y1, mui.colors().gfxviewer_bg_color());
// draw the title
- x0 = 0.5f - 0.5f * titlewidth;
- y0 = boxbounds.y0 + 0.5f * chheight;
+ float x0 = 0.5f - 0.5f * titlewidth;
+ float y0 = boxbounds.y0 + 0.5f * chheight;
for (auto ch : title)
{
container.add_char(x0, y0, chheight, aspect, rgb_t::white(), *ui_font, ch);
@@ -1157,241 +1259,155 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u
}
// update the bitmap
- tilemap_update_bitmap(mui.machine(), state, std::lround(mapboxwidth / pixelscale), std::lround(mapboxheight / pixelscale));
+ update_tilemap_bitmap(std::lround(mapboxwidth / pixelscale), std::lround(mapboxheight / pixelscale));
// add the final quad
- container.add_quad(mapboxbounds.x0, mapboxbounds.y0,
- mapboxbounds.x1, mapboxbounds.y1,
- rgb_t::white(), state.texture,
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(state.tilemap.rotate));
+ container.add_quad(
+ mapboxbounds.x0, mapboxbounds.y0,
+ mapboxbounds.x1, mapboxbounds.y1,
+ rgb_t::white(), m_texture,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(m_tilemap.m_rotate));
// handle keyboard input
- tilemap_handle_keys(mui.machine(), state, pixelscale);
+ if (m_tilemap.handle_keys(m_machine, pixelscale))
+ m_bitmap_dirty = true;
+ return handle_general_keys(uistate);
}
-//-------------------------------------------------
-// tilemap_handle_keys - handle keys for the
-// tilemap view
-//-------------------------------------------------
-
-static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, float pixelscale)
+void gfx_viewer::update_gfxset_bitmap(int xcells, int ycells, gfx_element &gfx)
{
- // handle tilemap selection (open bracket,close bracket)
- if (machine.ui_input().pressed(IPT_UI_PREV_GROUP) && state.tilemap.which > 0)
- { state.tilemap.which--; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP) && state.tilemap.which < machine.tilemap().count() - 1)
- { state.tilemap.which++; state.bitmap_dirty = true; }
+ auto const &info = m_gfxset.m_devices[m_gfxset.m_device];
+ auto const &set = info.m_sets[m_gfxset.m_set];
- // cache some info in locals
- tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
- uint32_t mapwidth = tilemap->width();
- uint32_t mapheight = tilemap->height();
+ // compute the number of source pixels in a cell
+ int const cellxpix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
+ int const cellypix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
- const bool at_max_zoom = !state.tilemap.auto_zoom && !state.tilemap.zoom_frac && state.tilemap.zoom == MAX_ZOOM_LEVEL;
- const bool at_min_zoom = !state.tilemap.auto_zoom && state.tilemap.zoom_frac && state.tilemap.zoom == MIN_ZOOM_LEVEL;
+ // reallocate the bitmap if it is too small
+ resize_bitmap(cellxpix * xcells, cellypix * ycells);
- // handle zoom (minus,plus)
- if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && !at_min_zoom)
+ // handle the redraw
+ if (m_bitmap_dirty)
{
- if (state.tilemap.auto_zoom)
- {
- // auto zoom never uses fractional factors
- state.tilemap.zoom = std::lround(pixelscale) - 1;
- state.tilemap.zoom_frac = !state.tilemap.zoom;
- if (state.tilemap.zoom_frac)
- state.tilemap.zoom = 2;
- state.tilemap.auto_zoom = false;
- }
- else if (state.tilemap.zoom_frac)
- {
- // remaining in fractional zoom range
- state.tilemap.zoom++;
- }
- else if (state.tilemap.zoom == 1)
- {
- // entering fractional zoom range
- state.tilemap.zoom++;
- state.tilemap.zoom_frac = true;
- }
- else
+ // pre-fill with transparency
+ m_bitmap.fill(0);
+
+ // loop over rows
+ for (int y = 0, index = set.m_offset; y < ycells; y++)
{
- // remaining in integer zoom range
- state.tilemap.zoom--;
- }
+ // make a rectangle that covers this row
+ rectangle cellbounds(0, m_bitmap.width() - 1, y * cellypix, (y + 1) * cellypix - 1);
- state.bitmap_dirty = true;
+ // only display if there is data to show
+ if (index < gfx.elements())
+ {
+ // draw the individual cells
+ for (int x = 0; x < xcells; x++, index++)
+ {
+ // update the bounds for this cell
+ cellbounds.min_x = x * cellxpix;
+ cellbounds.max_x = (x + 1) * cellxpix - 1;
- machine.popmessage(state.tilemap.zoom_frac ? _("Zoom = 1/%1$d") : _("Zoom = %1$d"), state.tilemap.zoom);
+ if (index < gfx.elements()) // only render if there is data
+ gfxset_draw_item(gfx, index, cellbounds.min_x, cellbounds.min_y, set);
+ else // otherwise, fill with transparency
+ m_bitmap.fill(0, cellbounds);
+ }
+ }
+ }
+
+ // reset the texture to force an update
+ m_texture->set_bitmap(m_bitmap, m_bitmap.cliprect(), TEXFORMAT_ARGB32);
+ m_bitmap_dirty = false;
}
+}
- if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && !at_max_zoom)
- {
- if (state.tilemap.auto_zoom)
- {
- // auto zoom never uses fractional factors
- state.tilemap.zoom = std::min<int>(std::lround(pixelscale) + 1, MAX_ZOOM_LEVEL);
- state.tilemap.zoom_frac = false;
- state.tilemap.auto_zoom = false;
- }
- else if (!state.tilemap.zoom_frac)
- {
- // remaining in integer zoom range
- state.tilemap.zoom++;
- }
- else if (state.tilemap.zoom == 2)
- {
- // entering integer zoom range
- state.tilemap.zoom--;
- state.tilemap.zoom_frac = false;
- }
- else
- {
- // remaining in fractional zoom range
- state.tilemap.zoom--;
- }
- state.bitmap_dirty = true;
+void gfx_viewer::update_tilemap_bitmap(int width, int height)
+{
+ // swap the coordinates back if they were talking about a rotated surface
+ if (m_tilemap.m_rotate & ORIENTATION_SWAP_XY)
+ std::swap(width, height);
- machine.popmessage(state.tilemap.zoom_frac ? _("Zoom = 1/%1$d") : _("Zoom = %1$d"), state.tilemap.zoom);
- }
+ // reallocate the bitmap if it is too small
+ resize_bitmap(width, height);
- if (machine.ui_input().pressed(IPT_UI_ZOOM_DEFAULT) && !state.tilemap.auto_zoom)
+ // handle the redraw
+ if (m_bitmap_dirty)
{
- state.tilemap.auto_zoom = true;
+ m_bitmap.fill(0);
+ tilemap_t &tilemap = *m_machine.tilemap().find(m_tilemap.m_index);
+ screen_device *const first_screen = screen_device_enumerator(m_machine.root_device()).first();
+ if (first_screen)
+ tilemap.draw_debug(*first_screen, m_bitmap, m_tilemap.m_xoffs, m_tilemap.m_yoffs, m_tilemap.m_flags);
- machine.popmessage(_("Expand to fit"));
+ // reset the texture to force an update
+ m_texture->set_bitmap(m_bitmap, m_bitmap.cliprect(), TEXFORMAT_RGB32);
+ m_bitmap_dirty = false;
}
+}
- // handle rotation (R)
- if (machine.ui_input().pressed(IPT_UI_ROTATE))
- {
- state.tilemap.rotate = orientation_add(ROT90, state.tilemap.rotate);
- state.bitmap_dirty = true;
- }
- // return to (0,0) (HOME)
- if (machine.ui_input().pressed(IPT_UI_HOME))
- {
- state.tilemap.xoffs = 0;
- state.tilemap.yoffs = 0;
- state.bitmap_dirty = true;
- }
+void gfx_viewer::gfxset_draw_item(gfx_element &gfx, int index, int dstx, int dsty, gfxset::setinfo const &info)
+{
+ int const width = (info.m_rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width();
+ int const height = (info.m_rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height();
+ rgb_t const *const palette = info.m_palette->palette()->entry_list_raw() + gfx.colorbase() + info.m_color * gfx.granularity();
+ uint8_t const *const src = gfx.get_data(index);
- // handle flags (category)
- if (machine.ui_input().pressed(IPT_UI_PAGE_UP) && state.tilemap.flags != TILEMAP_DRAW_ALL_CATEGORIES)
+ // loop over rows in the cell
+ for (int y = 0; y < height; y++)
{
- if (state.tilemap.flags > 0)
- {
- state.tilemap.flags--;
- machine.popmessage("Category = %d", state.tilemap.flags);
- }
- else
+ uint32_t *dest = &m_bitmap.pix(dsty + y, dstx);
+
+ // loop over columns in the cell
+ for (int x = 0; x < width; x++)
{
- state.tilemap.flags = TILEMAP_DRAW_ALL_CATEGORIES;
- machine.popmessage("Category All");
+ // compute effective x,y values after rotation
+ int effx = x, effy = y;
+ if (!(info.m_rotate & ORIENTATION_SWAP_XY))
+ {
+ if (info.m_rotate & ORIENTATION_FLIP_X)
+ effx = gfx.width() - 1 - effx;
+ if (info.m_rotate & ORIENTATION_FLIP_Y)
+ effy = gfx.height() - 1 - effy;
+ }
+ else
+ {
+ if (info.m_rotate & ORIENTATION_FLIP_X)
+ effx = gfx.height() - 1 - effx;
+ if (info.m_rotate & ORIENTATION_FLIP_Y)
+ effy = gfx.width() - 1 - effy;
+ std::swap(effx, effy);
+ }
+
+ // get a pointer to the start of this source row
+ uint8_t const *const s = src + (effy * gfx.rowbytes());
+
+ // extract the pixel
+ *dest++ = 0xff000000 | palette[s[effx]];
}
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed(IPT_UI_PAGE_DOWN) && (state.tilemap.flags < TILEMAP_DRAW_CATEGORY_MASK || (state.tilemap.flags == TILEMAP_DRAW_ALL_CATEGORIES)))
- {
- if (state.tilemap.flags == TILEMAP_DRAW_ALL_CATEGORIES)
- state.tilemap.flags = 0;
- else
- state.tilemap.flags++;
- state.bitmap_dirty = true;
- machine.popmessage("Category = %d", state.tilemap.flags);
}
+}
- // handle navigation (up,down,left,right), taking orientation into account
- int step = 8; // this may be applied more than once if multiple directions are pressed
- if (machine.input().code_pressed(KEYCODE_LSHIFT)) step = 1;
- if (machine.input().code_pressed(KEYCODE_LCONTROL)) step = 64;
- if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.xoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- else
- state.tilemap.yoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.xoffs += (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- else
- state.tilemap.yoffs += (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed_repeat(IPT_UI_LEFT, 6))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.yoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- else
- state.tilemap.xoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed_repeat(IPT_UI_RIGHT, 6))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.yoffs += (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- else
- state.tilemap.xoffs += (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- state.bitmap_dirty = true;
- }
+} // anonymous namespace
- // clamp within range
- while (state.tilemap.xoffs < 0)
- state.tilemap.xoffs += mapwidth;
- while (state.tilemap.xoffs >= mapwidth)
- state.tilemap.xoffs -= mapwidth;
- while (state.tilemap.yoffs < 0)
- state.tilemap.yoffs += mapheight;
- while (state.tilemap.yoffs >= mapheight)
- state.tilemap.yoffs -= mapheight;
-}
+/***************************************************************************
+ MAIN ENTRY POINT
+***************************************************************************/
+
//-------------------------------------------------
-// tilemap_update_bitmap - update the bitmap
-// for the tilemap view
+// ui_gfx_ui_handler - primary UI handler
+//
+// NOTE: this must not be called before machine
+// initialization is complete, as some drivers
+// create or modify gfx sets in VIDEO_START
//-------------------------------------------------
-static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, int width, int height)
+uint32_t ui_gfx_ui_handler(render_container &container, mame_ui_manager &mui, bool uistate)
{
- // swap the coordinates back if they were talking about a rotated surface
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- std::swap(width, height);
-
- // realloc the bitmap if it is too small
- if (!state.bitmap.valid() || !state.texture || state.bitmap.width() != width || state.bitmap.height() != height)
- {
- // free the old stuff
- machine.render().texture_free(state.texture);
- state.bitmap.reset();
-
- // allocate new stuff
- state.bitmap.allocate(width, height);
- state.texture = machine.render().texture_alloc();
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_RGB32);
-
- // force a redraw
- state.bitmap_dirty = true;
- }
-
- // handle the redraw
- if (state.bitmap_dirty)
- {
- state.bitmap.fill(0);
- tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
- screen_device *first_screen = screen_device_enumerator(machine.root_device()).first();
- if (first_screen)
- {
- tilemap->draw_debug(*first_screen, state.bitmap, state.tilemap.xoffs, state.tilemap.yoffs, state.tilemap.flags);
- }
-
- // reset the texture to force an update
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_RGB32);
- state.bitmap_dirty = false;
- }
+ return mui.get_session_data<gfx_viewer, gfx_viewer>(mui.machine()).handle(mui, container, uistate);
}
diff --git a/src/frontend/mame/ui/viewgfx.h b/src/frontend/mame/ui/viewgfx.h
index 765384b4bea..cb368efc91c 100644
--- a/src/frontend/mame/ui/viewgfx.h
+++ b/src/frontend/mame/ui/viewgfx.h
@@ -20,12 +20,6 @@
FUNCTION PROTOTYPES
***************************************************************************/
-// initialization
-void ui_gfx_init(running_machine &machine);
-
-// returns 'true' if the internal graphics viewer has relevance
-bool ui_gfx_is_relevant(running_machine &machine);
-
// master handler
uint32_t ui_gfx_ui_handler(render_container &container, mame_ui_manager &mui, bool uistate);