summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--docs/source/techspecs/luaengine.rst10
-rw-r--r--docs/source/techspecs/luareference.rst608
-rw-r--r--plugins/cheat/init.lua12
-rw-r--r--plugins/gdbstub/init.lua16
-rw-r--r--src/devices/cpu/arm7/arm7.h72
-rw-r--r--src/devices/cpu/arm7/arm7drc.hxx83
-rw-r--r--src/devices/imagedev/cassette.h8
-rw-r--r--src/emu/devcb.h30
-rw-r--r--src/emu/diimage.cpp14
-rw-r--r--src/emu/diimage.h11
-rw-r--r--src/emu/emumem.h2
-rw-r--r--src/emu/emuopts.cpp2
-rw-r--r--src/emu/inpttype.ipp15
-rw-r--r--src/emu/inputdev.cpp50
-rw-r--r--src/emu/inputdev.h7
-rw-r--r--src/emu/ioport.h1
-rw-r--r--src/emu/render.cpp18
-rw-r--r--src/emu/video.cpp20
-rw-r--r--src/emu/video.h3
-rw-r--r--src/frontend/mame/iptseqpoll.cpp182
-rw-r--r--src/frontend/mame/iptseqpoll.h4
-rw-r--r--src/frontend/mame/luaengine.cpp803
-rw-r--r--src/frontend/mame/luaengine.h2
-rw-r--r--src/frontend/mame/luaengine.ipp85
-rw-r--r--src/frontend/mame/luaengine_render.cpp150
-rw-r--r--src/frontend/mame/ui/barcode.cpp18
-rw-r--r--src/frontend/mame/ui/devctrl.h10
-rw-r--r--src/frontend/mame/ui/devopt.cpp4
-rw-r--r--src/frontend/mame/ui/info.cpp28
-rw-r--r--src/frontend/mame/ui/inifile.cpp8
-rw-r--r--src/frontend/mame/ui/mainmenu.cpp4
-rw-r--r--src/frontend/mame/ui/menu.cpp57
-rw-r--r--src/frontend/mame/ui/menu.h3
-rw-r--r--src/frontend/mame/ui/miscmenu.cpp31
-rw-r--r--src/frontend/mame/ui/tapectrl.cpp8
-rw-r--r--src/frontend/mame/ui/videoopt.cpp111
-rw-r--r--src/frontend/mame/ui/videoopt.h6
-rw-r--r--src/lib/util/strformat.h119
-rw-r--r--src/mame/drivers/goldnpkr.cpp55
-rw-r--r--src/mame/layout/goldnpkr.lay124
40 files changed, 1635 insertions, 1159 deletions
diff --git a/docs/source/techspecs/luaengine.rst b/docs/source/techspecs/luaengine.rst
index 22981fe79e6..68790f108ae 100644
--- a/docs/source/techspecs/luaengine.rst
+++ b/docs/source/techspecs/luaengine.rst
@@ -129,7 +129,7 @@ is tagged as ``:screen``, and we can further inspect it:
[MAME]> -- keep a reference to the main screen in a variable
[MAME]> s = manager:machine().screens[":screen"]
- [MAME]> print(s:width() .. "x" .. s:height())
+ [MAME]> print(s.width .. "x" .. s.height)
320x224
We have several methods to draw a HUD on the screen composed of lines, boxes and
@@ -139,11 +139,11 @@ text:
[MAME]> -- we define a HUD-drawing function, and then call it
[MAME]> function draw_hud()
- [MAME]>> s:draw_text(40, 40, "foo"); -- (x0, y0, msg)
- [MAME]>> s:draw_box(20, 20, 80, 80, 0, 0xff00ffff); -- (x0, y0, x1, y1, fill-color, line-color)
- [MAME]>> s:draw_line(20, 20, 80, 80, 0xff00ffff); -- (x0, y0, x1, y1, line-color)
+ [MAME]>> s:draw_text(40, 40, "foo") -- (x0, y0, msg)
+ [MAME]>> s:draw_box(20, 20, 80, 80, 0xff00ffff, 0) -- (x0, y0, x1, y1, line-color, fill-color)
+ [MAME]>> s:draw_line(20, 20, 80, 80, 0xff00ffff) -- (x0, y0, x1, y1, line-color)
[MAME]>> end
- [MAME]> draw_hud();
+ [MAME]> draw_hud()
This will draw some useless art on the screen. However, when resuming the game,
your HUD needs to be refreshed otherwise it will just disappear. In order to do
diff --git a/docs/source/techspecs/luareference.rst b/docs/source/techspecs/luareference.rst
index c61939daf0b..cd3f6af4b73 100644
--- a/docs/source/techspecs/luareference.rst
+++ b/docs/source/techspecs/luareference.rst
@@ -58,6 +58,603 @@ c:index_of(v)
value.
+.. _luareference-dev:
+
+Devices
+-------
+
+Several device classes and device mix-ins classes are exposed to Lua. Devices
+can be looked up by tag or enumerated.
+
+.. _luareference-dev-enum:
+
+Device enumerators
+~~~~~~~~~~~~~~~~~~
+
+Device enumerators are special containers that allow iterating over devices and
+looking up devices by tag. A device enumerator can be created to find any kind
+of device, to find devices of a particular type, or to find devices that
+implement a particular interface. When iterating using ``pairs`` or ``ipairs``,
+devices are returned by walking the device tree depth-first in creation order.
+
+The index get operator looks up a device by tag. It returns ``nil`` no device
+with the specified tag is found, or if the device with the specified tag does
+not meet the type/interface requirements of the device enumerator. The
+complexity is O(1) if the result is cached, but an uncached device lookup is
+expensive. The ``at`` method has O(n) complexity.
+
+If you create a device enumerator with a starting point other than the root
+machine device, passing an absolute tag or a tag containing parent references to
+the index operator may return a device that would not be discovered by
+iteration. If you create a device enumerator with restricted depth, devices
+that would not be found due to being too deep in the hierarchy can still be
+looked up by tag.
+
+Creating a device enumerator with depth restricted to zero can be used to
+downcast a device or test whether a device implements a certain interface. For
+example this will test whether a device implements the media image interface:
+
+.. code-block:: Lua
+
+ image_intf = emu.image_enumerator(device, 0):at(1)
+ if image_intf then
+ print(string.format("Device %s mounts images", device.tag))
+ end
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().devices
+ Returns a device enumerator that will iterate over
+ :ref:`devices <luareference-dev-device>` in the system.
+manager:machine().screens
+ Returns a device enumerator that will iterate over
+ :ref:`screen devices <luareference-dev-screen>` in the system.
+manager:machine().cassettes
+ Returns a device enumerator that will iterate over
+ :ref:`cassette devices <luareference-dev-cass>` in the system.
+manager:machine().images
+ Returns a device enumerator that will iterate over
+ :ref:`media image devices <luareference-dev-diimage>` in the system.
+manager:machine().slots
+ Returns a device enumerator that will iterate over
+ :ref:`slot devices <luareference-dev-dislot>` in the system.
+emu.device_enumerator(device, [depth])
+ Returns a device enumerator that will iterate over
+ :ref:`devices <luareference-dev-device>` in the sub-tree starting at the
+ specified device. The specified device will be included. If the depth is
+ provided, it must be an integer specifying the maximum number of levels to
+ iterate below the specified device (i.e. 1 will limit iteration to the
+ device and its immediate children).
+emu.screen_enumerator(device, [depth])
+ Returns a device enumerator that will iterate over
+ :ref:`screen devices <luareference-dev-screen>` in the sub-tree starting at
+ the specified device. The specified device will be included if it is a
+ screen device. If the depth is provided, it must be an integer specifying
+ the maximum number of levels to iterate below the specified device (i.e. 1
+ will limit iteration to the device and its immediate children).
+emu.cassette_enumerator(device, [depth])
+ Returns a device enumerator that will iterate over
+ :ref:`cassette devices <luareference-dev-cass>` in the sub-tree starting at
+ the specified device. The specified device will be included if it is a
+ cassette device. If the depth is provided, it must be an integer specifying
+ the maximum number of levels to iterate below the specified device (i.e. 1
+ will limit iteration to the device and its immediate children).
+emu.image_enumerator(device, [depth])
+ Returns a device enumerator that will iterate over
+ :ref:`media image devices <luareference-dev-diimage>` in the sub-tree
+ starting at the specified device. The specified device will be included if
+ it is a media image device. If the depth is provided, it must be an integer
+ specifying the maximum number of levels to iterate below the specified
+ device (i.e. 1 will limit iteration to the device and its immediate
+ children).
+emu.slot_enumerator(device, [depth])
+ Returns a device enumerator that will iterate over
+ :ref:`slot devices <luareference-dev-dislot>` in the sub-tree starting at
+ the specified device. The specified device will be included if it is a
+ slot device. If the depth is provided, it must be an integer specifying the
+ maximum number of levels to iterate below the specified device (i.e. 1 will
+ limit iteration to the device and its immediate children).
+
+.. _luareference-dev-device:
+
+Device
+~~~~~~
+
+Wraps MAME’s ``device_t`` class, which is a base of all device classes.
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().devices[tag]
+ Gets a device by tag relative to the root machine device, or ``nil`` if no
+ such device exists.
+manager:machine().devices[tag]:subdevice(tag)
+ Gets a device by tag relative to another arbitrary device, or ``nil`` if no
+ such device exists.
+
+Methods
+^^^^^^^
+
+device:subtag(tag)
+ Converts a tag relative to the device to an absolute tag.
+device:siblingtag(tag)
+ Converts a tag relative to the device’s parent device to an absolute tag.
+device:memshare(tag)
+ Gets a :ref:`memory share <luareference-mem-share>` by tag relative to the
+ device, or ``nil`` if no such memory share exists.
+device:membank(tag)
+ Gets a :ref:`memory bank <luareference-mem-bank>` by tag relative to the
+ device, or ``nil`` if no such memory bank exists.
+device:memregion(tag)
+ Gets a :ref:`memory region <luareference-mem-region>` by tag relative to the
+ device, or ``nil`` if no such memory region exists.
+device:ioport(tag)
+ Gets an :ref:`I/O port <luareference-input-ioport>` by tag relative to the
+ device, or ``nil`` if no such I/O port exists.
+device:subdevice(tag)
+ Gets a device by tag relative to the device.
+device:siblingdevice(tag)
+ Gets a device by tag relative to the device’s parent.
+
+Properties
+^^^^^^^^^^
+
+device.tag (read-only)
+ The device’s absolute tag in canonical form.
+device.basetag (read-only)
+ The last component of the device’s tag (i.e. its tag relative to its
+ immediate parent), or ``"root"`` for the root machine device.
+device.name (read-only)
+ The full display name for the device’s type.
+device.shortname (read-only)
+ The short name of the devices type (this is used, e.g. on the command line,
+ when looking for resource like ROMs or artwork, and in various data files).
+device.owner (read-only)
+ The device’s immediate parent in the device tree, or ``nil`` for the root
+ machine device.
+device.configured (read-only)
+ A Boolean indicating whether the device has completed configuration.
+device.started (read-only)
+ A Boolean indicating whether the device has completed starting.
+device.debug (read-only)
+ The :ref:`debugger interface <luareference-debug-devdebug>` to the device if
+ it is a CPU device, or ``nil`` if it is not a CPU device or the debugger is
+ not enabled.
+device.spaces[] (read-only)
+ A table of the device’s :ref:`address spaces <luareference-mem-space>`,
+ indexed by name. Only valid for devices that implement the memory
+ interface. Note that the names are specific to the device type and have no
+ special significance.
+
+.. _luareference-dev-screen:
+
+Screen device
+~~~~~~~~~~~~~
+
+Wraps MAME’s ``screen_device`` class, which represents an emulated video output.
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().screens[tag]
+ Gets a screen device by tag relative to the root machine device, or ``nil``
+ if no such device exists or it is not a screen device.
+
+Base classes
+^^^^^^^^^^^^
+
+* :ref:`luareference-dev-device`
+
+Methods
+^^^^^^^
+
+screen:orientation()
+ Returns the rotation angle in degrees (will be one of 0, 90, 180 or 270),
+ whether the screen is flipped left-to-right, and whether the screen is
+ flipped top-to-bottom.
+screen:time_until_pos(v, [h])
+ Gets the time remaining until the raster reaches the specified position. If
+ the horizontal component of the position is not specified, it defaults to
+ zero (0, i.e. the beginning of the line). The result is a floating-point
+ number in units of seconds.
+screen:time_until_vblank_start()
+ Gets the time remaining until the start of the vertical blanking interval.
+ The result is a floating-point number in units of seconds.
+screen:time_until_vblank_end()
+ Gets the time remaining until the end of the vertical blanking interval.
+ The result is a floating-point number in units of seconds.
+screen:snapshot([filename])
+ Saves a screen snapshot in PNG format. If no filename is supplied, the
+ configured snapshot path and name format will be used. If the supplied
+ filename is not an absolute path, it is interpreted relative to the first
+ configured snapshot path. The filename may contain conversion specifiers
+ that will be replaced by the system name or an incrementing number.
+
+ Returns a file error if opening the snapshot file failed, or ``nil``
+ otherwise.
+screen:pixel(x, y)
+ Gets the pixel at the specified location. Coordinates are in pixels, with
+ the origin at the top left corner of the visible area, increasing to the
+ right and down. Returns either a palette index or a colour in RGB format
+ packed into a 32-bit integer. Returns zero (0) if the specified point is
+ outside the visible area.
+screen:pixels()
+ Returns all visible pixels as 32-bit integers packed into a binary string in
+ host Endian order. Pixels are organised in row-major order, from left to
+ right then top to bottom. Pixels values are either palette indices or
+ colours in RGB format packed into 32-bit integers.
+screen:draw_box(left, top, right, bottom, [line], [fill])
+ Draws an outlined rectangle with edges at the specified positions.
+
+ Coordinates are floating-point numbers in units of screen pixels, with the
+ origin at (0, 0). Note that screen pixels often aren’t square. The
+ coordinate system is rotated if the screen is rotated, which is usually the
+ case for vertical-format screens. Before rotation, the origin is at the top
+ left, and coordinates increase to the right and downwards. Coordinates are
+ limited to the screen area.
+
+ The fill and line colours are in alpha/red/green/blue (ARGB) format.
+ Channel values are in the range 0 (transparent or off) to 255 (opaque or
+ full intensity), inclusive. Colour channel values are not pre-multiplied by
+ the alpha value. The channel values must be packed into the bytes of a
+ 32-bit unsigned integer, in the order alpha, red, green, blue from
+ most-significant to least-significant byte. If the line colour is not
+ provided, the UI text colour is used; if the fill colour is not provided,
+ the UI background colour is used.
+screen:draw_line(x1, y1, x2, y2, bottom, [color])
+ Draws a line from (x1, y1) to (x2, y2).
+
+ Coordinates are floating-point numbers in units of screen pixels, with the
+ origin at (0, 0). Note that screen pixels often aren’t square. The
+ coordinate system is rotated if the screen is rotated, which is usually the
+ case for vertical-format screens. Before rotation, the origin is at the top
+ left, and coordinates increase to the right and downwards. Coordinates are
+ limited to the screen area.
+
+ The line colour is in alpha/red/green/blue (ARGB) format. Channel values
+ are in the range 0 (transparent or off) to 255 (opaque or full intensity),
+ inclusive. Colour channel values are not pre-multiplied by the alpha value.
+ The channel values must be packed into the bytes of a 32-bit unsigned
+ integer, in the order alpha, red, green, blue from most-significant to
+ least-significant byte. If the line colour is not provided, the UI text
+ colour is used.
+screen:draw_text(x|justify, y, text, [foreground], [background])
+ Draws text at the specified position. If the screen is rotated the text
+ will be rotated.
+
+ If the first argument is a number, the text will be left-aligned at this X
+ coordinate. If the first argument is a string, it must be ``"left"``,
+ ``"center"`` or ``"right"`` to draw the text left-aligned at the
+ left edge of the screen, horizontally centred on the screen, or
+ right-aligned at the right edge of the screen, respectively. The second
+ argument specifies the Y coordinate of the maximum ascent of the text.
+
+ Coordinates are floating-point numbers in units of screen pixels, with the
+ origin at (0, 0). Note that screen pixels often aren’t square. The
+ coordinate system is rotated if the screen is rotated, which is usually the
+ case for vertical-format screens. Before rotation, the origin is at the top
+ left, and coordinates increase to the right and downwards. Coordinates are
+ limited to the screen area.
+
+ The foreground and background colours is in alpha/red/green/blue (ARGB)
+ format. Channel values are in the range 0 (transparent or off) to 255 (opaque or full intensity),
+ inclusive. Colour channel values are not pre-multiplied by the alpha value.
+ The channel values must be packed into the bytes of a 32-bit unsigned
+ integer, in the order alpha, red, green, blue from most-significant to
+ least-significant byte. If the foreground colour is not provided, the UI
+ text colour is used; if the background colour is not provided, the UI
+ background colour is used.
+
+Properties
+^^^^^^^^^^
+
+screen.width (read-only)
+ The width of the bitmap produced by the emulated screen in pixels.
+screen.height (read-only)
+ The height of the bitmap produced by the emulated screen in pixels.
+screen.refresh (read-only)
+ The screen’s configured refresh rate in Hertz (this may not reflect the
+ current value).
+screen.refresh_attoseconds (read-only)
+ The screen’s configured refresh interval in attoseconds (this may not
+ reflect the current value).
+screen.xoffset (read-only)
+ The screen’s default X position offset. This is a floating-point number
+ where one (1) corresponds to the X size of the screen’s container. This may
+ be useful for restoring the default after adjusting the X offset via the
+ screen’s container.
+screen.yoffset (read-only)
+ The screen’s default Y position offset. This is a floating-point number
+ where one (1) corresponds to the Y size of the screen’s container. This may
+ be useful for restoring the default after adjusting the Y offset via the
+ screen’s container.
+screen.xscale (read-only)
+ The screen’s default X scale factor, as a floating-point number. This may
+ be useful for restoring the default after adjusting the X scale via the
+ screen’s container.
+screen.yscale (read-only)
+ The screen’s default Y scale factor, as a floating-point number. This may
+ be useful for restoring the default after adjusting the Y scale via the
+ screen’s container.
+screen.pixel_period (read-only)
+ The interval taken to draw a horizontal pixel, as a floating-point number in
+ units of seconds.
+screen.scan_period (read-only)
+ The interval taken to draw a scan line (including the horizontal blanking
+ interval), as a floating-point number in units of seconds.
+screen.pixel_period (read-only)
+ The interval taken to draw a complete frame (including blanking intervals),
+ as a floating-point number in units of seconds.
+screen.frame_number (read-only)
+ The current frame number for the screen. This increments monotonically each
+ frame interval.
+screen.container (read-only)
+ The :ref:`render container <luareference-render-container>` used to draw the
+ screen.
+
+.. _luareference-dev-cass:
+
+Cassette image device
+~~~~~~~~~~~~~~~~~~~~~
+
+Wraps MAME’s ``cassette_image_device`` class, representing a compact cassette
+mechanism typically used by a home computer for program storage.
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().cassettes[tag]
+ Gets a cassette image device by tag relative to the root machine device, or
+ ``nil`` if no such device exists or it is not a cassette image device.
+
+Base classes
+^^^^^^^^^^^^
+
+* :ref:`luareference-dev-device`
+* :ref:`luareference-dev-diimage`
+
+Methods
+^^^^^^^
+
+cassette:stop()
+ Disables playback.
+cassette:play()
+ Enables playback. The cassette will play if the motor is enabled.
+cassette:forward()
+ Sets forward play direction.
+cassette:reverse()
+ Sets reverse play direction.
+cassette:seek(time, whence)
+ Jump to the specified position on the tape. The time is a floating-point
+ number in units of seconds, relative to the point specified by the whence
+ argument. The whence argument must be one of ``"set"``, ``"cur"`` or
+ ``"end"`` to seek relative to the start of the tape, the current position,
+ or the end of the tape, respectively.
+
+Properties
+^^^^^^^^^^
+
+cassette.is_stopped (read-only)
+ A Boolean indicating whether the cassette is stopped (i.e. not recording and
+ not playing).
+cassette.is_playing (read-only)
+ A Boolean indicating whether playback is enabled (i.e. the cassette will
+ play if the motor is enabled).
+cassette.is_recording (read-only)
+ A Boolean indicating whether recording is enabled (i.e. the cassette will
+ record if the motor is enabled).
+cassette.motor_state (read/write)
+ A Boolean indicating whether the cassette motor is enabled.
+cassette.speaker_state (read/write)
+ A Boolean indicating whether the cassette speaker is enabled.
+cassette.position (read-only)
+ The current position as a floating-point number in units of seconds relative
+ to the start of the tape.
+cassette.length (read-only)
+ The length of the tape as a floating-point number in units of seconds, or
+ zero (0) if no tape image is mounted.
+
+.. _luareference-dev-diimage:
+
+Image device interface
+~~~~~~~~~~~~~~~~~~~~~~
+
+Wraps MAME’s ``device_image_interface`` class which is a mix-in implemented by
+devices that can load media image files.
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().images[tag]
+ Gets an image device by tag relative to the root machine device, or ``nil``
+ if no such device exists or it is not a media image device.
+
+Methods
+^^^^^^^
+
+image:load(filename)
+ Loads the specified file as a media image. Returns ``"pass"`` or
+ ``"fail"``.
+image:load_software(name)
+ Loads a media image described in a software list. Returns ``"pass"`` or
+ ``"fail"``.
+image:unload()
+ Unloads the mounted image.
+image:create(filename)
+ Creates and mounts a media image file with the specified name. Returns
+ ``"pass"`` or ``"fail"``.
+image:display()
+ Returns a “front panel display” string for the device, if supported. This
+ can be used to show status information, like the current head position or
+ motor state.
+
+Properties
+^^^^^^^^^^
+
+image.is_readable (read-only)
+ A Boolean indicating whether the device supports reading.
+image.is_writeable (read-only)
+ A Boolean indicating whether the device supports writing.
+image.must_be_loaded (read-only)
+ A Boolean indicating whether the device requires a media image to be loaded
+ in order to start.
+image.is_reset_on_load (read-only)
+ A Boolean indicating whether the device requires a hard reset to change
+ media images (usually for cartridge slots that contain hardware in addition
+ to memory chips).
+image.image_type_name (read-only)
+ A string for categorising the media device.
+image.instance_name (read-only)
+ The instance name of the device in the current configuration. This is used
+ for setting the media image to load on the command line or in INI files.
+ This is not stable, it may have a number appended that may change depending
+ on slot configuration.
+image.brief_instance_name (read-only)
+ The brief instance name of the device in the current configuration. This is
+ used for setting the media image to load on the command line or in INI
+ files. This is not stable, it may have a number appended that may change
+ depending on slot configuration.
+image.formatlist[] (read-only)
+ The :ref:`media image formats <luareference-dev-imagefmt>` supported by the
+ device, indexed by name. The index operator and ``index_of`` methods have
+ O(n) complexity; all other supported operations have O(1) complexity.
+image.exists (read-only)
+ A Boolean indicating whether a media image file is mounted.
+image.readonly (read-only)
+ A Boolean indicating whether a media image file is mounted in read-only
+ mode.
+image.filename (read-only)
+ The full path to the mounted media image file, or ``nil`` if no media image
+ is mounted.
+image.crc (read-only)
+ The 32-bit cyclic redundancy check of the content of the mounted image file
+ if the mounted media image was not loaded from a software list, is mounted
+ read-only and is not a CD-ROM, or zero (0) otherwise.
+image.loaded_through_softlist (read-only)
+ A Boolean indicating whether the mounted media image was loaded from a
+ software list, or ``false`` if no media image is mounted.
+image.software_list_name (read-only)
+ The short name of the software list if the mounted media image was loaded
+ from a software list.
+image.software_longname (read-only)
+ The full name of the software item if the mounted media image was loaded
+ from a software list, or ``nil`` otherwise.
+image.software_publisher (read-only)
+ The publisher of the software item if the mounted media image was loaded
+ from a software list, or ``nil`` otherwise.
+image.software_year (read-only)
+ The release year of the software item if the mounted media image was loaded
+ from a software list, or ``nil`` otherwise.
+image.software_parent (read-only)
+ The short name of the parent software item if the mounted media image was
+ loaded from a software list, or ``nil`` otherwise.
+image.device (read-only)
+ The underlying :ref:`device <luareference-dev-device>`.
+
+.. _luareference-dev-dislot:
+
+Slot device interface
+~~~~~~~~~~~~~~~~~~~~~
+
+Wraps MAME’s ``device_slot_interface`` class which is a mix-in implemented by
+devices that instantiate a user-specified child device.
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().slots[tag]
+ Gets an slot device by tag relative to the root machine device, or ``nil``
+ if no such device exists or it is not a slot device.
+
+Properties
+^^^^^^^^^^
+
+slot.fixed (read-only)
+ A Boolean indicating whether this is a slot with a card specified in machine
+ configuration that cannot be changed by the user.
+slot.has_selectable_options (read-only)
+ A Boolean indicating whether the slot has any user-selectable options (as
+ opposed to options that can only be selected programmatically, typically for
+ fixed slots or to load media images).
+slot.options[] (read-only)
+ The :ref:`slot options <luareference-dev-slotopt>` describing the child
+ devices that can be instantiated by the slot, indexed by option value. The
+ ``at`` and ``index_of`` methods have O(n) complexity; all other supported
+ operations have O(1) complexity.
+slot.device (read-only)
+ The underlying :ref:`device <luareference-dev-device>`.
+
+.. _luareference-dev-imagefmt:
+
+Media image format
+~~~~~~~~~~~~~~~~~~
+
+Wraps MAME’s ``image_device_format`` class, which describes a media file format
+supported by a :ref:`media image device <luareference-dev-diimage>`.
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().images[tag].formatlist[name]
+ Gets a media image format supported by a given device by name.
+
+Properties
+^^^^^^^^^^
+
+format.name (read-only)
+ An abbreviated name used to identify the format. This often matches the
+ primary filename extension used for the format.
+format.description (read-only)
+ The full display name of the format.
+format.extensions[] (read-only)
+ Yields a table of filename extensions used for the format.
+format.option_spec (read-only)
+ A string describing options available when creating a media image using this
+ format. The string is not intended to be human-readable.
+
+.. _luareference-dev-slotopt:
+
+Slot option
+~~~~~~~~~~~
+
+Wraps MAME’s ``device_slot_interface::slot_option`` class, which represents a
+child device that a :ref:`slot device <luareference-dev-dislot>` slot device can
+be configured to instantiate.
+
+Instantiation
+^^^^^^^^^^^^^
+
+manager:machine().slots[tag].options[name]
+ Gets a slot option for a given :ref:`slot device <luareference-dev-dislot>`
+ by name (i.e. the value used to select the option).
+
+Properties
+^^^^^^^^^^
+
+option.name (read-only)
+ The name of the slot option. This is the value used to select this option
+ on the command line or in an INI file.
+option.device_fullname (read-only)
+ The full display name of the device type instantiated by this option.
+option.device_shortname (read-only)
+ The short name of the device type instantiated by this option.
+option.selectable (read-only)
+ A Boolean indicating whether the option may be selected by the user (options
+ that are not user-selectable are typically used for fixed slots or to load
+ media images).
+option.default_bios (read-only)
+ The default BIOS setting for the device instantiated using this option, or
+ ``nil`` if the default BIOS specified in the device’s ROM definitions will
+ be used.
+option.clock (read-only)
+ The configured clock frequency for the device instantiated using this
+ option. This is an unsigned 32-bit integer. If the eight most-significant
+ bits are all set, it is a ratio of the parent device’s clock frequency, with
+ the numerator in bits 12-23 and the denominator in bits 0-11. If the eight
+ most-significant bits are not all set, it is a frequency in Hertz.
+
+
.. _luareference-mem:
Memory system
@@ -172,7 +769,7 @@ Properties
space.name (read-only)
The display name for the address space.
space.shift (read-only)
- The address address granularity for the address space specified as the shift
+ The address granularity for the address space specified as the shift
required to translate a byte address to a native address. Positive values
shift towards the most significant bit (left) and negative values shift
towards the least significant bit (right).
@@ -243,7 +840,7 @@ entry.address_end (read-only)
End address of the entry’s range (inclusive).
entry.address_mirror (read-only)
Address mirror bits.
-entry.address_end (read-only)
+entry.address_mask (read-only)
Address mask bits. Only valid for handlers.
entry.mask (read-only)
Lane mask, indicating which data lines on the bus are connected to the
@@ -258,8 +855,9 @@ entry.write (read-only)
handler.
entry.share (read-only)
Memory share tag for making RAM entries accessible or ``nil``.
-entry.address_end (read-only)
- Explicit memory region tag for ROM entries, or ``nil``.
+entry.region (read-only)
+ Explicit memory region tag for ROM entries, or ``nil``. For ROM entries,
+ ``nil`` infers the region from the device tag.
entry.region_offset (read-only)
Starting offset in memory region for ROM entries.
@@ -1545,7 +2143,7 @@ item.bounds (read-only)
coordinates.
item.color (read-only)
The item’s colour for the current state. The colour of the screen or
- element texture is multiplied by this colour. This is a
+ element texture is multiplied by this colour. This is a
:ref:`render colour <luareference-render-color>` object.
item.blend_mode (read-only)
Get the item’s blend mode. This is an integer value, where 0 means no
diff --git a/plugins/cheat/init.lua b/plugins/cheat/init.lua
index 2acb377192f..83dbdc7bfb1 100644
--- a/plugins/cheat/init.lua
+++ b/plugins/cheat/init.lua
@@ -295,7 +295,7 @@ function cheat.startplugin()
error("bpset not permitted in oneshot cheat")
return
end
- local idx = dev:debug():bpset(addr)
+ local idx = dev.debug:bpset(addr)
breaks[idx] = {cheat = cheat, func = func, dev = dev}
end
@@ -308,7 +308,7 @@ function cheat.startplugin()
error("bad space in wpset")
return
end
- local idx = dev.debug():wpset(space, wptype, addr, len)
+ local idx = dev.debug:wpset(space, wptype, addr, len)
watches[idx] = {cheat = cheat, func = func, dev = dev}
end
@@ -318,12 +318,12 @@ function cheat.startplugin()
end
for num, bp in pairs(breaks) do
if cheat == bp.cheat then
- bp.dev.debug():bpclr(num)
+ bp.dev.debug:bpclr(num)
end
end
for num, wp in pairs(watches) do
if cheat == wp.cheat then
- wp.dev.debug():wpclr(num)
+ wp.dev.debug:wpclr(num)
end
end
end
@@ -485,7 +485,7 @@ function cheat.startplugin()
for name, tag in pairs(cheat.cpu) do
if manager:machine():debugger() then
local dev = manager:machine().devices[tag]
- if not dev or not dev:debug() then
+ if not dev or not dev.debug then
cheat_error(cheat, "missing or invalid device " .. tag)
return
end
@@ -895,7 +895,7 @@ function cheat.startplugin()
elseif draw.type == "line" then
draw.scr:draw_line(draw.x1, draw.y1, draw.x2, draw.y2, draw.color)
elseif draw.type == "box" then
- draw.scr:draw_box(draw.x1, draw.y1, draw.x2, draw.y2, draw.bgcolor, draw.linecolor)
+ draw.scr:draw_box(draw.x1, draw.y1, draw.x2, draw.y2, draw.linecolor, draw.bgcolor)
end
end
output = {}
diff --git a/plugins/gdbstub/init.lua b/plugins/gdbstub/init.lua
index e850e62ae5b..afc5428dd22 100644
--- a/plugins/gdbstub/init.lua
+++ b/plugins/gdbstub/init.lua
@@ -195,7 +195,7 @@ function gdbstub.startplugin()
end
elseif cmd == "s" then
if #packet == 1 then
- cpu:debug():step()
+ cpu.debug:step()
socket:write("+$OK#9a")
socket:write("$S05#B8")
running = false
@@ -204,7 +204,7 @@ function gdbstub.startplugin()
end
elseif cmd == "c" then
if #packet == 1 then
- cpu:debug():go()
+ cpu.debug:go()
socket:write("+$OK#9a")
else
socket:write("+$E00#a5")
@@ -219,7 +219,7 @@ function gdbstub.startplugin()
socket:write("+$E00#a5")
return
end
- local idx = cpu:debug():bpset(addr)
+ local idx = cpu.debug:bpset(addr)
breaks.byaddr[addr] = idx
breaks.byidx[idx] = addr
socket:write("+$OK#9a")
@@ -228,7 +228,7 @@ function gdbstub.startplugin()
socket:write("+$E00#a5")
return
end
- local idx = cpu:debug():wpset(cpu.spaces["program"], "w", addr, 1)
+ local idx = cpu.debug:wpset(cpu.spaces["program"], "w", addr, 1)
watches.byaddr[addr] = idx
watches.byidx[idx] = {addr = addr, type = "watch"}
socket:write("+$OK#9a")
@@ -237,7 +237,7 @@ function gdbstub.startplugin()
socket:write("+$E00#a5")
return
end
- local idx = cpu:debug():wpset(cpu.spaces["program"], "r", addr, 1)
+ local idx = cpu.debug:wpset(cpu.spaces["program"], "r", addr, 1)
watches.byaddr[addr] = idx
watches.byidx[idx] = {addr = addr, type = "rwatch"}
socket:write("+$OK#9a")
@@ -246,7 +246,7 @@ function gdbstub.startplugin()
socket:write("+$E00#a5")
return
end
- local idx = cpu:debug():wpset(cpu.spaces["program"], "rw", addr, 1)
+ local idx = cpu.debug:wpset(cpu.spaces["program"], "rw", addr, 1)
watches.byaddr[addr] = idx
watches.byidx[idx] = {addr = addr, type = "awatch"}
socket:write("+$OK#9a")
@@ -262,7 +262,7 @@ function gdbstub.startplugin()
return
end
local idx = breaks.byaddr[addr]
- cpu:debug():bpclr(idx)
+ cpu.debug:bpclr(idx)
breaks.byaddr[addr] = nil
breaks.byidx[idx] = nil
socket:write("+$OK#9a")
@@ -272,7 +272,7 @@ function gdbstub.startplugin()
return
end
local idx = watches.byaddr[addr]
- cpu:debug():wpclr(idx)
+ cpu.debug:wpclr(idx)
watches.byaddr[addr] = nil
watches.byidx[idx] = nil
socket:write("+$OK#9a")
diff --git a/src/devices/cpu/arm7/arm7.h b/src/devices/cpu/arm7/arm7.h
index 80757afe13b..b303d515a8c 100644
--- a/src/devices/cpu/arm7/arm7.h
+++ b/src/devices/cpu/arm7/arm7.h
@@ -368,17 +368,17 @@ protected:
/* fast RAM info */
struct fast_ram_info
{
- offs_t start; /* start of the RAM block */
- offs_t end; /* end of the RAM block */
- bool readonly; /* true if read-only */
- void * base; /* base in memory where the RAM lives */
+ offs_t start = 0; /* start of the RAM block */
+ offs_t end = 0; /* end of the RAM block */
+ bool readonly = false; /* true if read-only */
+ void * base = nullptr; /* base in memory where the RAM lives */
};
struct hotspot_info
{
- uint32_t pc;
- uint32_t opcode;
- uint32_t cycles;
+ uint32_t pc = 0;
+ uint32_t opcode = 0;
+ uint32_t cycles = 0;
};
/* internal compiler state */
@@ -386,9 +386,9 @@ protected:
{
compiler_state &operator=(compiler_state const &) = delete;
- uint32_t cycles; /* accumulated cycles */
- uint8_t checkints; /* need to check interrupts before next instruction */
- uint8_t checksoftints; /* need to check software interrupts before next instruction */
+ uint32_t cycles = 0; /* accumulated cycles */
+ uint8_t checkints = 0; /* need to check interrupts before next instruction */
+ uint8_t checksoftints = 0; /* need to check software interrupts before next instruction */
uml::code_label labelnum; /* index for local labels */
};
@@ -396,45 +396,45 @@ protected:
struct arm7imp_state
{
/* core state */
- drc_cache * cache; /* pointer to the DRC code cache */
- drcuml_state * drcuml; /* DRC UML generator state */
- //arm7_frontend * drcfe; /* pointer to the DRC front-end state */
- uint32_t drcoptions; /* configurable DRC options */
+ std::unique_ptr<drc_cache> cache; /* pointer to the DRC code cache */
+ std::unique_ptr<drcuml_state> drcuml; /* DRC UML generator state */
+ //arm7_frontend * drcfe = nullptr; /* pointer to the DRC front-end state */
+ uint32_t drcoptions = 0; /* configurable DRC options */
/* internal stuff */
- uint8_t cache_dirty; /* true if we need to flush the cache */
- uint32_t jmpdest; /* destination jump target */
+ uint8_t cache_dirty = 0; /* true if we need to flush the cache */
+ uint32_t jmpdest = 0; /* destination jump target */
/* parameters for subroutines */
- uint64_t numcycles; /* return value from gettotalcycles */
- uint32_t mode; /* current global mode */
- const char * format; /* format string for print_debug */
- uint32_t arg0; /* print_debug argument 1 */
- uint32_t arg1; /* print_debug argument 2 */
+ uint64_t numcycles = 0; /* return value from gettotalcycles */
+ uint32_t mode = 0; /* current global mode */
+ const char * format = nullptr; /* format string for print_debug */
+ uint32_t arg0 = 0; /* print_debug argument 1 */
+ uint32_t arg1 = 0; /* print_debug argument 2 */
/* register mappings */
- uml::parameter regmap[/*NUM_REGS*/37]; /* parameter to register mappings for all 16 integer registers */
+ uml::parameter regmap[/*NUM_REGS*/37]; /* parameter to register mappings for all 16 integer registers */
/* subroutines */
- uml::code_handle * entry; /* entry point */
- uml::code_handle * nocode; /* nocode exception handler */
- uml::code_handle * out_of_cycles; /* out of cycles exception handler */
- uml::code_handle * tlb_translate; /* tlb translation handler */
- uml::code_handle * detect_fault; /* tlb fault detection handler */
- uml::code_handle * check_irq; /* irq check handler */
- uml::code_handle * read8; /* read byte */
- uml::code_handle * write8; /* write byte */
- uml::code_handle * read16; /* read half */
- uml::code_handle * write16; /* write half */
- uml::code_handle * read32; /* read word */
- uml::code_handle * write32; /* write word */
+ uml::code_handle * entry = nullptr; /* entry point */
+ uml::code_handle * nocode = nullptr; /* nocode exception handler */
+ uml::code_handle * out_of_cycles = nullptr; /* out of cycles exception handler */
+ uml::code_handle * tlb_translate = nullptr; /* tlb translation handler */
+ uml::code_handle * detect_fault = nullptr; /* tlb fault detection handler */
+ uml::code_handle * check_irq = nullptr; /* irq check handler */
+ uml::code_handle * read8 = nullptr; /* read byte */
+ uml::code_handle * write8 = nullptr; /* write byte */
+ uml::code_handle * read16 = nullptr; /* read half */
+ uml::code_handle * write16 = nullptr; /* write half */
+ uml::code_handle * read32 = nullptr; /* read word */
+ uml::code_handle * write32 = nullptr; /* write word */
/* fast RAM */
- uint32_t fastram_select;
+ uint32_t fastram_select = 0;
fast_ram_info fastram[ARM7_MAX_FASTRAM];
/* hotspots */
- uint32_t hotspot_select;
+ uint32_t hotspot_select = 0;
hotspot_info hotspot[ARM7_MAX_HOTSPOTS];
} m_impstate;
diff --git a/src/devices/cpu/arm7/arm7drc.hxx b/src/devices/cpu/arm7/arm7drc.hxx
index 621c0a7f0f8..8edd44438bd 100644
--- a/src/devices/cpu/arm7/arm7drc.hxx
+++ b/src/devices/cpu/arm7/arm7drc.hxx
@@ -127,21 +127,18 @@ void arm7_cpu_device::save_fast_iregs(drcuml_block &block)
void arm7_cpu_device::arm7_drc_init()
{
- drc_cache *cache;
drcbe_info beinfo;
uint32_t flags = 0;
/* allocate enough space for the cache and the core */
- cache = auto_alloc(machine(), drc_cache(CACHE_SIZE));
- if (cache == nullptr)
- fatalerror("Unable to allocate cache of size %d\n", (uint32_t)(CACHE_SIZE));
/* allocate the implementation-specific state from the full cache */
- memset(&m_impstate, 0, sizeof(m_impstate));
- m_impstate.cache = cache;
+ m_impstate = arm7imp_state();
+ try { m_impstate.cache = std::make_unique<drc_cache>(CACHE_SIZE); }
+ catch (std::bad_alloc const &) { throw emu_fatalerror("Unable to allocate cache of size %d\n", (uint32_t)(CACHE_SIZE)); }
/* initialize the UML generator */
- m_impstate.drcuml = new drcuml_state(*this, *cache, flags, 1, 32, 1);
+ m_impstate.drcuml = std::make_unique<drcuml_state>(*this, *m_impstate.cache, flags, 1, 32, 1);
/* add symbols for our stuff */
m_impstate.drcuml->symbol_add(&m_icount, sizeof(m_icount), "icount");
@@ -158,7 +155,7 @@ void arm7_cpu_device::arm7_drc_init()
//m_impstate.drcuml->symbol_add(&m_impstate.fpmode, sizeof(m_impstate.fpmode), "fpmode"); // TODO
/* initialize the front-end helper */
- //m_impstate.drcfe = auto_alloc(machine(), arm7_frontend(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE));
+ //m_impstate.drcfe = std::make_unique<arm7_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
/* allocate memory for cache-local state and initialize it */
//memcpy(&m_impstate.fpmode, fpmode_source, sizeof(fpmode_source)); // TODO
@@ -199,7 +196,7 @@ void arm7_cpu_device::arm7_drc_init()
void arm7_cpu_device::execute_run_drc()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
int execute_result;
/* reset the cache if dirty */
@@ -211,7 +208,7 @@ void arm7_cpu_device::execute_run_drc()
do
{
/* run as much as we can */
- execute_result = drcuml->execute(*m_impstate.entry);
+ execute_result = drcuml.execute(*m_impstate.entry);
/* if we need to recompile, do it */
if (execute_result == EXECUTE_MISSING_CODE)
@@ -231,9 +228,9 @@ void arm7_cpu_device::execute_run_drc()
void arm7_cpu_device::arm7_drc_exit()
{
/* clean up the DRC */
- //auto_free(machine(), m_impstate.drcfe);
- delete m_impstate.drcuml;
- auto_free(machine(), m_impstate.cache);
+ //m_impstate.drcfe.reset();
+ m_impstate.drcuml.reset();
+ m_impstate.cache.reset();
}
@@ -328,7 +325,7 @@ void arm7_cpu_device::code_flush_cache()
void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
compiler_state compiler = { 0 };
const opcode_desc *seqlast;
bool override = false;
@@ -338,7 +335,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
/* get a description of this sequence */
// TODO FIXME
const opcode_desc *desclist = nullptr; //m_impstate.drcfe->describe_code(pc); // TODO
-// if (drcuml->logging() || drcuml->logging_native())
+// if (drcuml.logging() || drcuml.logging_native())
// log_opcode_desc(drcuml, desclist, 0);
/* if we get an error back, flush the cache and try again */
@@ -348,7 +345,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
try
{
/* start the block */
- drcuml_block &block(drcuml->begin_block(4096));
+ drcuml_block &block(drcuml.begin_block(4096));
/* loop until we get through all instruction sequences */
for (const opcode_desc *seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
@@ -357,7 +354,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
uint32_t nextpc;
/* add a code log entry */
- if (drcuml->logging())
+ if (drcuml.logging())
block.append_comment("-------------------------"); // comment
/* determine the last instruction in this sequence */
@@ -367,7 +364,7 @@ void arm7_cpu_device::code_compile_block(uint8_t mode, offs_t pc)
assert(seqlast != nullptr);
/* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
- if (override || !drcuml->hash_exists(mode, seqhead->pc))
+ if (override || !drcuml.hash_exists(mode, seqhead->pc))
UML_HASH(block, mode, seqhead->pc); // hash mode,pc
/* if we already have a hash, and this is the first sequence, assume that we */
@@ -470,17 +467,17 @@ void arm7_cpu_device::cfunc_unimplemented()
void arm7_cpu_device::static_generate_entry_point()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
- drcuml_block &block(drcuml->begin_block(110));
+ drcuml_block &block(drcuml.begin_block(110));
/* forward references */
- //alloc_handle(*drcuml, &m_impstate.exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover");
- alloc_handle(*drcuml, m_impstate.nocode, "nocode");
- alloc_handle(*drcuml, m_impstate.detect_fault, "detect_fault");
- alloc_handle(*drcuml, m_impstate.tlb_translate, "tlb_translate");
+ //alloc_handle(drcuml, &m_impstate.exception_norecover[EXCEPTION_INTERRUPT], "interrupt_norecover");
+ alloc_handle(drcuml, m_impstate.nocode, "nocode");
+ alloc_handle(drcuml, m_impstate.detect_fault, "detect_fault");
+ alloc_handle(drcuml, m_impstate.tlb_translate, "tlb_translate");
- alloc_handle(*drcuml, m_impstate.entry, "entry");
+ alloc_handle(drcuml, m_impstate.entry, "entry");
UML_HANDLE(block, *m_impstate.entry); // handle entry
/* load fast integer registers */
@@ -501,7 +498,7 @@ void arm7_cpu_device::static_generate_entry_point()
void arm7_cpu_device::static_generate_check_irq()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
uml::code_label noirq;
int nodabt = 0;
int nopabt = 0;
@@ -513,10 +510,10 @@ void arm7_cpu_device::static_generate_check_irq()
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(120));
+ drcuml_block &block(drcuml.begin_block(120));
/* generate a hash jump via the current mode and PC */
- alloc_handle(*drcuml, m_impstate.check_irq, "check_irq");
+ alloc_handle(drcuml, m_impstate.check_irq, "check_irq");
UML_HANDLE(block, *m_impstate.check_irq); // handle check_irq
/* Exception priorities:
@@ -669,13 +666,13 @@ void arm7_cpu_device::static_generate_check_irq()
void arm7_cpu_device::static_generate_nocode_handler()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(10));
+ drcuml_block &block(drcuml.begin_block(10));
/* generate a hash jump via the current mode and PC */
- alloc_handle(*drcuml, m_impstate.nocode, "nocode");
+ alloc_handle(drcuml, m_impstate.nocode, "nocode");
UML_HANDLE(block, *m_impstate.nocode); // handle nocode
UML_GETEXP(block, uml::I0); // getexp i0
UML_MOV(block, uml::mem(&R15), uml::I0); // mov [pc],i0
@@ -693,13 +690,13 @@ void arm7_cpu_device::static_generate_nocode_handler()
void arm7_cpu_device::static_generate_out_of_cycles()
{
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(10));
+ drcuml_block &block(drcuml.begin_block(10));
/* generate a hash jump via the current mode and PC */
- alloc_handle(*drcuml, m_impstate.out_of_cycles, "out_of_cycles");
+ alloc_handle(drcuml, m_impstate.out_of_cycles, "out_of_cycles");
UML_HANDLE(block, *m_impstate.out_of_cycles); // handle out_of_cycles
UML_GETEXP(block, uml::I0); // getexp i0
UML_MOV(block, uml::mem(&R15), uml::I0); // mov <pc>,i0
@@ -718,16 +715,16 @@ void arm7_cpu_device::static_generate_detect_fault(uml::code_handle **handleptr)
{
/* on entry, flags are in I2, vaddr is in I3, desc_lvl1 is in I4, ap is in R5 */
/* on exit, fault result is in I6 */
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
int donefault = 0;
int checkuser = 0;
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(1024));
+ drcuml_block &block(drcuml.begin_block(1024));
/* add a global entry for this */
- alloc_handle(*drcuml, m_impstate.detect_fault, "detect_fault");
+ alloc_handle(drcuml, m_impstate.detect_fault, "detect_fault");
UML_HANDLE(block, *m_impstate.detect_fault); // handle detect_fault
UML_ROLAND(block, uml::I6, uml::I4, 32-4, 0x0f<<1); // roland i6, i4, 32-4, 0xf<<1
@@ -796,7 +793,7 @@ void arm7_cpu_device::static_generate_tlb_translate(uml::code_handle **handleptr
/* on entry, address is in I0 and flags are in I2 */
/* on exit, translated address is in I0 and success/failure is in I2 */
/* routine trashes I4-I7 */
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
uml::code_label smallfault;
uml::code_label smallprefetch;
int nopid = 0;
@@ -815,9 +812,9 @@ void arm7_cpu_device::static_generate_tlb_translate(uml::code_handle **handleptr
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(170));
+ drcuml_block &block(drcuml.begin_block(170));
- alloc_handle(*drcuml, m_impstate.tlb_translate, "tlb_translate");
+ alloc_handle(drcuml, m_impstate.tlb_translate, "tlb_translate");
UML_HANDLE(block, *m_impstate.tlb_translate); // handle tlb_translate
// I3: vaddr
@@ -1004,15 +1001,15 @@ void arm7_cpu_device::static_generate_memory_accessor(int size, bool istlb, bool
/* on entry, address is in I0; data for writes is in I1, fetch type in I2 */
/* on exit, read result is in I0 */
/* routine trashes I0-I3 */
- drcuml_state *drcuml = m_impstate.drcuml;
+ drcuml_state &drcuml = *m_impstate.drcuml;
//int tlbmiss = 0;
int label = 1;
/* begin generating */
- drcuml_block &block(drcuml->begin_block(1024));
+ drcuml_block &block(drcuml.begin_block(1024));
/* add a global entry for this */
- alloc_handle(*drcuml, handleptr, name);
+ alloc_handle(drcuml, handleptr, name);
UML_HANDLE(block, *handleptr); // handle *handleptr
if (istlb)
diff --git a/src/devices/imagedev/cassette.h b/src/devices/imagedev/cassette.h
index 5310bb546d3..48e10cdbdb4 100644
--- a/src/devices/imagedev/cassette.h
+++ b/src/devices/imagedev/cassette.h
@@ -87,10 +87,10 @@ public:
bool is_playing() { return (m_state & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY; }
bool is_recording() { return (m_state & CASSETTE_MASK_UISTATE) == CASSETTE_RECORD; }
- void set_motor(int state) { change_state(state ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); } // aka remote control
- int motor_on() { return ((m_state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED) ? 1 : 0; }
- void set_speaker(int state) { change_state(state ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); }
- int speaker_on() { return ((m_state & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_ENABLED) ? 1 : 0; }
+ void set_motor(bool state) { change_state(state ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR); } // aka remote control
+ bool motor_on() { return (m_state & CASSETTE_MASK_MOTOR) == CASSETTE_MOTOR_ENABLED; }
+ void set_speaker(bool state) { change_state(state ? CASSETTE_SPEAKER_ENABLED : CASSETTE_SPEAKER_MUTED, CASSETTE_MASK_SPEAKER); }
+ bool speaker_on() { return (m_state & CASSETTE_MASK_SPEAKER) == CASSETTE_SPEAKER_ENABLED; }
cassette_image *get_image() { return m_cassette.get(); }
double get_position();
diff --git a/src/emu/devcb.h b/src/emu/devcb.h
index fd966a7afc1..cdfa9321a5b 100644
--- a/src/emu/devcb.h
+++ b/src/emu/devcb.h
@@ -88,16 +88,16 @@ protected:
template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form4 { static constexpr bool value = false; };
template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form5 { static constexpr bool value = false; };
template <typename Input, typename Result, typename Func, typename Enable = void> struct is_transform_form6 { static constexpr bool value = false; };
- template <typename Input, typename Result, typename Func> struct is_transform_form3<Input, Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t &, Input, std::make_unsigned_t<Input> &)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Input, typename Result, typename Func> struct is_transform_form4<Input, Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t &, Input)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Input, typename Result, typename Func> struct is_transform_form6<Input, Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (Input)>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Input, typename Result, typename Func> struct is_transform_form3<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t &, Input, std::make_unsigned_t<Input> &>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Input, typename Result, typename Func> struct is_transform_form4<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t &, Input>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Input, typename Result, typename Func> struct is_transform_form6<Input, Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, Input>, Result>::value> > { static constexpr bool value = true; };
template <typename Input, typename Result, typename Func> struct is_transform { static constexpr bool value = is_transform_form1<Input, Result, Func>::value || is_transform_form2<Input, Result, Func>::value || is_transform_form3<Input, Result, Func>::value || is_transform_form4<Input, Result, Func>::value || is_transform_form5<Input, Result, Func>::value || is_transform_form6<Input, Result, Func>::value; };
// Determining the result type of a transform function
template <typename Input, typename Result, typename Func, typename Enable = void> struct transform_result;
- template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form3<Input, Result, Func>::value> > { using type = std::result_of_t<Func (offs_t &, Input, std::make_unsigned_t<Input> &)>; };
- template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form4<Input, Result, Func>::value> > { using type = std::result_of_t<Func (offs_t &, Input)>; };
- template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form6<Input, Result, Func>::value> > { using type = std::result_of_t<Func (Input)>; };
+ template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form3<Input, Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t &, Input, std::make_unsigned_t<Input> &>; };
+ template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form4<Input, Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t &, Input>; };
+ template <typename Input, typename Result, typename Func> struct transform_result<Input, Result, Func, std::enable_if_t<is_transform_form6<Input, Result, Func>::value> > { using type = std::invoke_result_t<Func, Input>; };
template <typename Input, typename Result, typename Func> using transform_result_t = typename transform_result<Input, Result, Func>::type;
// Mapping method types to delegate types
@@ -214,16 +214,16 @@ protected:
template <typename Result, typename Func, typename Enable = void> struct is_read_form1 { static constexpr bool value = false; };
template <typename Result, typename Func, typename Enable = void> struct is_read_form2 { static constexpr bool value = false; };
template <typename Result, typename Func, typename Enable = void> struct is_read_form3 { static constexpr bool value = false; };
- template <typename Result, typename Func> struct is_read_form1<Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t, Result)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Result, typename Func> struct is_read_form2<Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func (offs_t)>, Result>::value> > { static constexpr bool value = true; };
- template <typename Result, typename Func> struct is_read_form3<Result, Func, std::enable_if_t<std::is_convertible<std::result_of_t<Func ()>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Result, typename Func> struct is_read_form1<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t, Result>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Result, typename Func> struct is_read_form2<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func, offs_t>, Result>::value> > { static constexpr bool value = true; };
+ template <typename Result, typename Func> struct is_read_form3<Result, Func, std::enable_if_t<std::is_convertible<std::invoke_result_t<Func>, Result>::value> > { static constexpr bool value = true; };
template <typename Result, typename Func> struct is_read { static constexpr bool value = is_read_form1<Result, Func>::value || is_read_form2<Result, Func>::value || is_read_form3<Result, Func>::value; };
// Determining the result type of a read function
template <typename Result, typename Func, typename Enable = void> struct read_result;
- template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form1<Result, Func>::value> > { using type = std::result_of_t<Func (offs_t, std::make_unsigned_t<Result>)>; };
- template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form2<Result, Func>::value> > { using type = std::result_of_t<Func (offs_t)>; };
- template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form3<Result, Func>::value> > { using type = std::result_of_t<Func ()>; };
+ template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form1<Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t, std::make_unsigned_t<Result>>; };
+ template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form2<Result, Func>::value> > { using type = std::invoke_result_t<Func, offs_t>; };
+ template <typename Result, typename Func> struct read_result<Result, Func, std::enable_if_t<is_read_form3<Result, Func>::value> > { using type = std::invoke_result_t<Func>; };
template <typename Result, typename Func> using read_result_t = typename read_result<Result, Func>::type;
// Detecting candidates for read delegates
@@ -278,9 +278,9 @@ protected:
template <typename Input, typename Func, typename Enable = void> struct is_write_form1 { static constexpr bool value = false; };
template <typename Input, typename Func, typename Enable = void> struct is_write_form2 { static constexpr bool value = false; };
template <typename Input, typename Func, typename Enable = void> struct is_write_form3 { static constexpr bool value = false; };
- template <typename Input, typename Func> struct is_write_form1<Input, Func, void_t<std::result_of_t<Func (offs_t, Input, std::make_unsigned_t<Input>)> > > { static constexpr bool value = true; };
- template <typename Input, typename Func> struct is_write_form2<Input, Func, void_t<std::result_of_t<Func (offs_t, Input)> > > { static constexpr bool value = true; };
- template <typename Input, typename Func> struct is_write_form3<Input, Func, void_t<std::result_of_t<Func (Input)> > > { static constexpr bool value = true; };
+ template <typename Input, typename Func> struct is_write_form1<Input, Func, void_t<std::invoke_result_t<Func, offs_t, Input, std::make_unsigned_t<Input>> > > { static constexpr bool value = true; };
+ template <typename Input, typename Func> struct is_write_form2<Input, Func, void_t<std::invoke_result_t<Func, offs_t, Input> > > { static constexpr bool value = true; };
+ template <typename Input, typename Func> struct is_write_form3<Input, Func, void_t<std::invoke_result_t<Func, Input> > > { static constexpr bool value = true; };
template <typename Input, typename Func> struct is_write { static constexpr bool value = is_write_form1<Input, Func>::value || is_write_form2<Input, Func>::value || is_write_form3<Input, Func>::value; };
// Detecting candidates for write delegates
diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp
index 0b78816c8e5..4a61fcdecc3 100644
--- a/src/emu/diimage.cpp
+++ b/src/emu/diimage.cpp
@@ -94,7 +94,6 @@ device_image_interface::device_image_interface(const machine_config &mconfig, de
, m_file()
, m_mame_file()
, m_software_part_ptr(nullptr)
- , m_supported(0)
, m_readonly(false)
, m_created(false)
, m_create_format(0)
@@ -576,7 +575,8 @@ u32 device_image_interface::crc()
u32 crc = 0;
image_checkhash();
- m_hash.crc(crc);
+ if (!m_hash.crc(crc))
+ crc = 0;
return crc;
}
@@ -1073,11 +1073,6 @@ image_init_result device_image_interface::load_software(const std::string &softw
if (swinfo.longname().empty() || swinfo.publisher().empty() || swinfo.year().empty())
fatalerror("Each entry in an XML list must have all of the following fields: description, publisher, year!\n");
- // store
- m_longname = swinfo.longname();
- m_manufacturer = swinfo.publisher();
- m_year = swinfo.year();
-
// set file type
std::string filename = (m_mame_file != nullptr) && (m_mame_file->filename() != nullptr)
? m_mame_file->filename()
@@ -1204,9 +1199,6 @@ void device_image_interface::clear()
m_create_format = 0;
m_create_args = nullptr;
- m_longname.clear();
- m_manufacturer.clear();
- m_year.clear();
m_basename.clear();
m_basename_noext.clear();
m_filetype.clear();
@@ -1214,6 +1206,8 @@ void device_image_interface::clear()
m_full_software_name.clear();
m_software_part_ptr = nullptr;
m_software_list_name.clear();
+
+ m_hash.reset();
}
diff --git a/src/emu/diimage.h b/src/emu/diimage.h
index 9ec748c3bed..e9292f2f472 100644
--- a/src/emu/diimage.h
+++ b/src/emu/diimage.h
@@ -175,11 +175,6 @@ public:
void *ptr() {check_for_file(); return const_cast<void *>(m_file->buffer()); }
// configuration access
- const std::string &longname() const noexcept { return m_longname; }
- const std::string &manufacturer() const noexcept { return m_manufacturer; }
- const std::string &year() const noexcept { return m_year; }
- u32 supported() const noexcept { return m_supported; }
-
const software_info *software_entry() const noexcept;
const software_part *part_entry() const noexcept { return m_software_part_ptr; }
const char *software_list_name() const noexcept { return m_software_list_name.c_str(); }
@@ -301,12 +296,6 @@ private:
// working directory; persists across mounts
std::string m_working_directory;
- // info read from the hash file/software list
- std::string m_longname;
- std::string m_manufacturer;
- std::string m_year;
- u32 m_supported;
-
// flags
bool m_readonly;
bool m_created;
diff --git a/src/emu/emumem.h b/src/emu/emumem.h
index 5e419241162..b51e0a25c97 100644
--- a/src/emu/emumem.h
+++ b/src/emu/emumem.h
@@ -167,7 +167,7 @@ namespace emu::detail {
template <typename... T> struct void_wrapper { using type = void; };
template <typename... T> using void_t = typename void_wrapper<T...>::type;
-template <typename D, typename T, typename Enable = void> struct rw_device_class { };
+template <typename D, typename T, typename Enable = void> struct rw_device_class { };
template <typename D, typename T, typename Ret, typename... Params>
struct rw_device_class<D, Ret (T::*)(Params...), std::enable_if_t<std::is_constructible<D, device_t &, const char *, Ret (T::*)(Params...), const char *>::value> > { using type = T; };
diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp
index ceda32dbbcc..9885b42b880 100644
--- a/src/emu/emuopts.cpp
+++ b/src/emu/emuopts.cpp
@@ -74,7 +74,7 @@ const options_entry emu_options::s_option_entries[] =
{ OPTION_WAVWRITE, nullptr, OPTION_STRING, "optional filename to write a WAV file of the current session" },
{ OPTION_SNAPNAME, "%g/%i", OPTION_STRING, "override of the default snapshot/movie naming; %g == gamename, %i == index" },
{ OPTION_SNAPSIZE, "auto", OPTION_STRING, "specify snapshot/movie resolution (<width>x<height>) or 'auto' to use minimal size " },
- { OPTION_SNAPVIEW, "internal", OPTION_STRING, "specify snapshot/movie view or 'internal' to use internal pixel-aspect views" },
+ { OPTION_SNAPVIEW, "", OPTION_STRING, "specify snapshot/movie view or 'native' to use internal pixel-aspect views" },
{ OPTION_SNAPBILINEAR, "1", OPTION_BOOLEAN, "specify if the snapshot/movie should have bilinear filtering applied" },
{ OPTION_STATENAME, "%g", OPTION_STRING, "override of the default state subfolder naming; %g == gamename" },
{ OPTION_BURNIN, "0", OPTION_BOOLEAN, "create burn-in snapshots for each screen" },
diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp
index f16677cf5c9..ff7b17f757b 100644
--- a/src/emu/inpttype.ipp
+++ b/src/emu/inpttype.ipp
@@ -803,14 +803,14 @@ namespace {
#define CORE_INPUT_TYPES_UI \
CORE_INPUT_TYPES_BEGIN(ui) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY,"On Screen Display", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, "Break in Debugger", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY,"On Screen Display", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, "Break in Debugger", input_seq(KEYCODE_TILDE, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CONFIGURE, "Config Menu", input_seq(KEYCODE_TAB) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE, "Pause", input_seq(KEYCODE_P, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE_SINGLE, "Pause - Single Step", input_seq(KEYCODE_P, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE_SINGLE, "Pause - Single Step", input_seq(KEYCODE_P, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_P, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_REWIND_SINGLE, "Rewind - Single Step", input_seq(KEYCODE_TILDE, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RESET_MACHINE, "Reset Machine", input_seq(KEYCODE_F3, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SOFT_RESET, "Soft Reset", input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RESET_MACHINE, "Reset Machine", input_seq(KEYCODE_F3, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_F3, KEYCODE_RSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SOFT_RESET, "Soft Reset", input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_GFX, "Show Gfx", input_seq(KEYCODE_F4) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_DEC, "Frameskip Dec", input_seq(KEYCODE_F8) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_INC, "Frameskip Inc", input_seq(KEYCODE_F9) ) \
@@ -830,8 +830,8 @@ namespace {
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_END, "UI End", input_seq(KEYCODE_END) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_UP, "UI Page Up", input_seq(KEYCODE_PGUP) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, "UI Page Down", input_seq(KEYCODE_PGDN) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, "UI Focus Next", input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT) ) \
- INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, "UI Focus Previous", input_seq(KEYCODE_TAB, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_NEXT, "UI Focus Next", input_seq(KEYCODE_TAB, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_RSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FOCUS_PREV, "UI Focus Previous", input_seq(KEYCODE_TAB, KEYCODE_LSHIFT, input_seq::or_code, KEYCODE_TAB, KEYCODE_RSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, "UI Select", input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0), input_seq::or_code, KEYCODE_ENTER_PAD) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, "UI Cancel", input_seq(KEYCODE_ESC) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DISPLAY_COMMENT, "UI Display Comment", input_seq(KEYCODE_SPACE) ) \
@@ -843,6 +843,7 @@ namespace {
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ROTATE, "UI Rotate", input_seq(KEYCODE_R) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_PROFILER, "Show Profiler", input_seq(KEYCODE_F11, KEYCODE_LSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_UI, "UI Toggle", input_seq(KEYCODE_SCRLOCK, input_seq::not_code, KEYCODE_LSHIFT) ) \
+ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RELEASE_POINTER, "UI Release Pointer", input_seq(KEYCODE_RCONTROL, KEYCODE_RALT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PASTE, "UI Paste Text", input_seq(KEYCODE_SCRLOCK, KEYCODE_LSHIFT) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_DEBUG, "Toggle Debugger", input_seq(KEYCODE_F5) ) \
INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE, "Save State", input_seq(KEYCODE_F7, KEYCODE_LSHIFT) ) \
diff --git a/src/emu/inputdev.cpp b/src/emu/inputdev.cpp
index 4c2afdd7e7a..66a0794f6cd 100644
--- a/src/emu/inputdev.cpp
+++ b/src/emu/inputdev.cpp
@@ -31,7 +31,7 @@ public:
virtual s32 read_as_switch(input_item_modifier modifier) override;
virtual s32 read_as_relative(input_item_modifier modifier) override;
virtual s32 read_as_absolute(input_item_modifier modifier) override;
- virtual bool item_check_axis(input_item_modifier modifier) override;
+ virtual bool item_check_axis(input_item_modifier modifiers, s32 memory) override;
// steadykey helper
bool steadykey_changed();
@@ -57,7 +57,7 @@ public:
virtual s32 read_as_switch(input_item_modifier modifier) override;
virtual s32 read_as_relative(input_item_modifier modifier) override;
virtual s32 read_as_absolute(input_item_modifier modifier) override;
- virtual bool item_check_axis(input_item_modifier modifier) override;
+ virtual bool item_check_axis(input_item_modifier modifier, s32 memory) override;
};
@@ -74,7 +74,7 @@ public:
virtual s32 read_as_switch(input_item_modifier modifier) override;
virtual s32 read_as_relative(input_item_modifier modifier) override;
virtual s32 read_as_absolute(input_item_modifier modifier) override;
- virtual bool item_check_axis(input_item_modifier modifier) override;
+ virtual bool item_check_axis(input_item_modifier modifier, s32 memory) override;
};
@@ -675,16 +675,17 @@ input_device_item::input_device_item(input_device &device, const char *name, voi
m_itemid(itemid),
m_itemclass(itemclass),
m_getstate(getstate),
- m_current(0),
- m_memory(0)
+ m_current(0)
{
- // use a standard token name for know item IDs
const char *standard_token = manager().standard_token(itemid);
- if (standard_token != nullptr)
+ if (standard_token)
+ {
+ // use a standard token name for know item IDs
m_token.assign(standard_token);
-
- // otherwise, create a tokenized name
- else {
+ }
+ else
+ {
+ // otherwise, create a tokenized name
m_token.assign(name);
strmakeupper(m_token);
strdelchr(m_token, ' ');
@@ -707,19 +708,10 @@ input_device_item::~input_device_item()
// to trigger a read when polling
//-------------------------------------------------
-bool input_device_item::check_axis(input_item_modifier modifier)
+bool input_device_item::check_axis(input_item_modifier modifier, s32 memory)
{
- // if we've already reported this one, don't bother
- if (m_memory == INVALID_AXIS_VALUE)
- return false;
-
- if (item_check_axis(modifier))
- {
- m_memory = INVALID_AXIS_VALUE;
- return true;
- }
-
- return false;
+ // use INVALID_AXIS_VALUE as a short-circuit
+ return (memory != INVALID_AXIS_VALUE) && item_check_axis(modifier, memory);
}
@@ -801,7 +793,7 @@ s32 input_device_switch_item::read_as_absolute(input_item_modifier modifier)
// enough to trigger a read when polling
//-------------------------------------------------
-bool input_device_switch_item::item_check_axis(input_item_modifier modifier)
+bool input_device_switch_item::item_check_axis(input_item_modifier modifier, s32 memory)
{
return false;
}
@@ -889,12 +881,12 @@ s32 input_device_relative_item::read_as_absolute(input_item_modifier modifier)
// enough to trigger a read when polling
//-------------------------------------------------
-bool input_device_relative_item::item_check_axis(input_item_modifier modifier)
+bool input_device_relative_item::item_check_axis(input_item_modifier modifier, s32 memory)
{
- s32 curval = read_as_relative(modifier);
+ const s32 curval = read_as_relative(modifier);
// for relative axes, look for ~20 pixels movement
- return std::abs(curval - memory()) > 20 * INPUT_RELATIVE_PER_PIXEL;
+ return std::abs(curval - memory) > (20 * INPUT_RELATIVE_PER_PIXEL);
}
@@ -1002,15 +994,15 @@ s32 input_device_absolute_item::read_as_absolute(input_item_modifier modifier)
// enough to trigger a read when polling
//-------------------------------------------------
-bool input_device_absolute_item::item_check_axis(input_item_modifier modifier)
+bool input_device_absolute_item::item_check_axis(input_item_modifier modifier, s32 memory)
{
// ignore min/max for lightguns
// so the selection will not be affected by a gun going out of range
- s32 curval = read_as_absolute(modifier);
+ const s32 curval = read_as_absolute(modifier);
if (m_device.devclass() == DEVICE_CLASS_LIGHTGUN &&
(curval == INPUT_ABSOLUTE_MAX || curval == INPUT_ABSOLUTE_MIN))
return false;
// for absolute axes, look for 25% of maximum
- return std::abs(curval - memory()) > (INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN) / 4;
+ return std::abs(curval - memory) > ((INPUT_ABSOLUTE_MAX - INPUT_ABSOLUTE_MIN) / 4);
}
diff --git a/src/emu/inputdev.h b/src/emu/inputdev.h
index ecae0532be0..9c9f63c3961 100644
--- a/src/emu/inputdev.h
+++ b/src/emu/inputdev.h
@@ -105,18 +105,16 @@ public:
input_code code() const;
const char *token() const { return m_token.c_str(); }
s32 current() const { return m_current; }
- s32 memory() const { return m_memory; }
// helpers
s32 update_value();
- void set_memory(s32 value) { m_memory = value; }
- bool check_axis(input_item_modifier modifier);
+ bool check_axis(input_item_modifier modifier, s32 memory);
// readers
virtual s32 read_as_switch(input_item_modifier modifier) = 0;
virtual s32 read_as_relative(input_item_modifier modifier) = 0;
virtual s32 read_as_absolute(input_item_modifier modifier) = 0;
- virtual bool item_check_axis(input_item_modifier modifier) = 0;
+ virtual bool item_check_axis(input_item_modifier modifier, s32 memory) = 0;
protected:
// internal state
@@ -130,7 +128,6 @@ protected:
// live state
s32 m_current; // current raw value
- s32 m_memory; // "memory" value, to remember where we started during polling
};
diff --git a/src/emu/ioport.h b/src/emu/ioport.h
index 72add6abb41..376df1347be 100644
--- a/src/emu/ioport.h
+++ b/src/emu/ioport.h
@@ -358,6 +358,7 @@ enum ioport_type
IPT_UI_ROTATE,
IPT_UI_SHOW_PROFILER,
IPT_UI_TOGGLE_UI,
+ IPT_UI_RELEASE_POINTER,
IPT_UI_TOGGLE_DEBUG,
IPT_UI_PASTE,
IPT_UI_SAVE_STATE,
diff --git a/src/emu/render.cpp b/src/emu/render.cpp
index 26b7057ffb3..6b9a1e76f18 100644
--- a/src/emu/render.cpp
+++ b/src/emu/render.cpp
@@ -3366,17 +3366,21 @@ void render_manager::config_save(config_type cfg_type, util::xml::data_node *par
}
// iterate over targets
- for (int targetnum = 0; targetnum < 1000; targetnum++)
+ for (int targetnum = 0; ; ++targetnum)
{
// get this target and break when we fail
render_target *target = target_by_index(targetnum);
- if (target == nullptr)
+ if (!target)
+ {
break;
-
- // create a node
- util::xml::data_node *const targetnode = parentnode->add_child("target", nullptr);
- if (targetnode && !target->config_save(*targetnode))
- targetnode->delete_node();
+ }
+ else if (!target->hidden())
+ {
+ // create a node
+ util::xml::data_node *const targetnode = parentnode->add_child("target", nullptr);
+ if (targetnode && !target->config_save(*targetnode))
+ targetnode->delete_node();
+ }
}
// iterate over screen containers
diff --git a/src/emu/video.cpp b/src/emu/video.cpp
index 26b7fe1d2c2..3d6ffa43dea 100644
--- a/src/emu/video.cpp
+++ b/src/emu/video.cpp
@@ -120,7 +120,7 @@ video_manager::video_manager(running_machine &machine)
// create a render target for snapshots
const char *viewname = machine.options().snap_view();
- m_snap_native = !no_screens && (viewname[0] == 0 || strcmp(viewname, "native") == 0);
+ m_snap_native = !no_screens && !strcmp(viewname, "native");
if (m_snap_native)
{
@@ -426,13 +426,13 @@ void video_manager::begin_recording_screen(const std::string &filename, uint32_t
// create the emu_file
bool is_absolute_path = !filename.empty() && osd_is_absolute_path(filename);
std::unique_ptr<emu_file> movie_file = std::make_unique<emu_file>(
- is_absolute_path ? "" : machine().options().snapshot_directory(),
- OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ is_absolute_path ? "" : machine().options().snapshot_directory(),
+ OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
// and open the actual file
osd_file::error filerr = filename.empty()
- ? open_next(*movie_file, extension)
- : movie_file->open(filename);
+ ? open_next(*movie_file, extension)
+ : movie_file->open(filename);
if (filerr != osd_file::error::NONE)
{
osd_printf_error("Error creating movie, osd_file::error=%d\n", int(filerr));
@@ -554,16 +554,6 @@ void video_manager::postload()
//-------------------------------------------------
-// is_recording - returns whether or not any
-// screen is currently recording
-//-------------------------------------------------
-
-bool video_manager::is_recording() const
-{
- return !m_movie_recordings.empty();
-}
-
-//-------------------------------------------------
// effective_autoframeskip - return the effective
// autoframeskip value, accounting for fast
// forward
diff --git a/src/emu/video.h b/src/emu/video.h
index 0dec74fa5a7..bcd0d4e4394 100644
--- a/src/emu/video.h
+++ b/src/emu/video.h
@@ -51,7 +51,6 @@ public:
bool throttled() const { return m_throttled; }
float throttle_rate() const { return m_throttle_rate; }
bool fastforward() const { return m_fastforward; }
- bool is_recording() const;
// setters
void set_frameskip(int frameskip);
@@ -76,6 +75,7 @@ public:
int effective_frameskip() const;
// snapshots
+ render_target &snapshot_target() { return *m_snap_target; }
void save_snapshot(screen_device *screen, emu_file &file);
void save_active_screen_snapshots();
void save_input_timecode();
@@ -84,6 +84,7 @@ public:
void begin_recording(const char *name, movie_recording::format format);
void end_recording();
void add_sound_to_recording(const s16 *sound, int numsamples);
+ bool is_recording() const { return !m_movie_recordings.empty(); }
void set_timecode_enabled(bool value) { m_timecode_enabled = value; }
bool get_timecode_enabled() { return m_timecode_enabled; }
diff --git a/src/frontend/mame/iptseqpoll.cpp b/src/frontend/mame/iptseqpoll.cpp
index 145c64f033a..83883e5d970 100644
--- a/src/frontend/mame/iptseqpoll.cpp
+++ b/src/frontend/mame/iptseqpoll.cpp
@@ -11,7 +11,8 @@
input_code_poller::input_code_poller(input_manager &manager) noexcept :
- m_manager(manager)
+ m_manager(manager),
+ m_axis_memory()
{
}
@@ -24,26 +25,31 @@ input_code_poller::~input_code_poller()
void input_code_poller::reset()
{
// iterate over device classes and devices
+ m_axis_memory.clear();
for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno)
{
input_class &devclass(m_manager.device_class(classno));
- for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
+ if (devclass.enabled())
{
- // fetch the device; ignore if nullptr
- input_device *const device(devclass.device(devnum));
- if (device)
+ for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
{
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
+ // fetch the device; ignore if nullptr
+ input_device *const device(devclass.device(devnum));
+ if (device)
{
- // for any non-switch items, set memory to the current value
- input_device_item *const item(device->item(itemid));
- if (item && (item->itemclass() != ITEM_CLASS_SWITCH))
- item->set_memory(m_manager.code_value(item->code()));
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
+ {
+ // for any non-switch items, set memory to the current value
+ input_device_item *const item(device->item(itemid));
+ if (item && (item->itemclass() != ITEM_CLASS_SWITCH))
+ m_axis_memory.emplace_back(item, m_manager.code_value(item->code()));
+ }
}
}
}
}
+ std::sort(m_axis_memory.begin(), m_axis_memory.end());
}
@@ -62,7 +68,7 @@ void switch_code_poller_base::reset()
}
-bool switch_code_poller_base::code_pressed_once(input_code code)
+bool switch_code_poller_base::code_pressed_once(input_code code, bool moved)
{
// look for the code in the memory
bool const pressed(m_manager.code_pressed(code));
@@ -78,7 +84,7 @@ bool switch_code_poller_base::code_pressed_once(input_code code)
}
// if we get here, we were not previously pressed; if still not pressed, return false
- if (!pressed)
+ if (!pressed || !moved)
return false;
// otherwise, add the code to the memory and return true
@@ -96,31 +102,14 @@ axis_code_poller::axis_code_poller(input_manager &manager) noexcept :
input_code axis_code_poller::poll()
{
- // iterate over device classes and devices, skipping disabled classes
- for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno)
+ // iterate over the axis items we found
+ for (auto memory = m_axis_memory.begin(); m_axis_memory.end() != memory; ++memory)
{
- input_class &devclass(m_manager.device_class(classno));
- if (devclass.enabled())
+ input_code const code = memory->first->code();
+ if (memory->first->check_axis(code.item_modifier(), memory->second))
{
- for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
- {
- // fetch the device; ignore if nullptr
- input_device *const device(devclass.device(devnum));
- if (device)
- {
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
- {
- input_device_item *const item(device->item(itemid));
- if (item && (item->itemclass() != ITEM_CLASS_SWITCH))
- {
- input_code const code = item->code();
- if (item->check_axis(code.item_modifier()))
- return code;
- }
- }
- }
- }
+ m_axis_memory.erase(memory);
+ return code;
}
}
@@ -142,64 +131,73 @@ input_code switch_code_poller::poll()
for (input_device_class classno = DEVICE_CLASS_FIRST_VALID; DEVICE_CLASS_LAST_VALID >= classno; ++classno)
{
input_class &devclass(m_manager.device_class(classno));
- if (devclass.enabled())
+ if (!devclass.enabled())
+ continue;
+
+ for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
{
- for (int devnum = 0; devclass.maxindex() >= devnum; ++devnum)
+ // fetch the device; ignore if nullptr
+ input_device *const device(devclass.device(devnum));
+ if (!device)
+ continue;
+
+ // iterate over items within each device
+ for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
{
- // fetch the device; ignore if nullptr
- input_device *const device(devclass.device(devnum));
- if (device)
+ input_device_item *const item(device->item(itemid));
+ if (!item)
+ continue;
+
+ input_code code = item->code();
+ if (item->itemclass() == ITEM_CLASS_SWITCH)
{
- // iterate over items within each device
- for (input_item_id itemid = ITEM_ID_FIRST_VALID; device->maxitem() >= itemid; ++itemid)
- {
- input_device_item *const item(device->item(itemid));
- if (item)
- {
- input_code code = item->code();
- if (item->itemclass() == ITEM_CLASS_SWITCH)
- {
- // item is natively a switch, poll it
- if (code_pressed_once(code))
- return code;
- }
- else if (item->check_axis(code.item_modifier()))
- {
- // poll axes digitally
- code.set_item_class(ITEM_CLASS_SWITCH);
- if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_XAXIS))
- {
- // joystick X axis - check with left/right modifiers
- code.set_item_modifier(ITEM_MODIFIER_LEFT);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_RIGHT);
- if (code_pressed_once(code))
- return code;
- }
- else if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_YAXIS))
- {
- // if this is a joystick Y axis, check with up/down modifiers
- code.set_item_modifier(ITEM_MODIFIER_UP);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_DOWN);
- if (code_pressed_once(code))
- return code;
- }
- else
- {
- // any other axis, check with pos/neg modifiers
- code.set_item_modifier(ITEM_MODIFIER_POS);
- if (code_pressed_once(code))
- return code;
- code.set_item_modifier(ITEM_MODIFIER_NEG);
- if (code_pressed_once(code))
- return code;
- }
- }
- }
- }
+ // item is natively a switch, poll it
+ if (code_pressed_once(code, true))
+ return code;
+ else
+ continue;
+ }
+
+ auto const memory(std::lower_bound(
+ m_axis_memory.begin(),
+ m_axis_memory.end(),
+ item,
+ [] (auto const &x, auto const &y) { return x.first < y; }));
+ if ((m_axis_memory.end() == memory) || (item != memory->first))
+ continue;
+
+ // poll axes digitally
+ bool const moved(item->check_axis(code.item_modifier(), memory->second));
+ code.set_item_class(ITEM_CLASS_SWITCH);
+ if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_XAXIS))
+ {
+ // joystick X axis - check with left/right modifiers
+ code.set_item_modifier(ITEM_MODIFIER_LEFT);
+ if (code_pressed_once(code, moved))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_RIGHT);
+ if (code_pressed_once(code, moved))
+ return code;
+ }
+ else if ((classno == DEVICE_CLASS_JOYSTICK) && (code.item_id() == ITEM_ID_YAXIS))
+ {
+ // if this is a joystick Y axis, check with up/down modifiers
+ code.set_item_modifier(ITEM_MODIFIER_UP);
+ if (code_pressed_once(code, moved))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_DOWN);
+ if (code_pressed_once(code, moved))
+ return code;
+ }
+ else
+ {
+ // any other axis, check with pos/neg modifiers
+ code.set_item_modifier(ITEM_MODIFIER_POS);
+ if (code_pressed_once(code, moved))
+ return code;
+ code.set_item_modifier(ITEM_MODIFIER_NEG);
+ if (code_pressed_once(code, moved))
+ return code;
}
}
}
@@ -237,7 +235,7 @@ input_code keyboard_code_poller::poll()
if (item && (item->itemclass() == ITEM_CLASS_SWITCH))
{
input_code const code = item->code();
- if (code_pressed_once(code))
+ if (code_pressed_once(code, true))
return code;
}
}
diff --git a/src/frontend/mame/iptseqpoll.h b/src/frontend/mame/iptseqpoll.h
index 13c0d9c6484..b9f31f70477 100644
--- a/src/frontend/mame/iptseqpoll.h
+++ b/src/frontend/mame/iptseqpoll.h
@@ -12,6 +12,7 @@
#pragma once
+#include <utility>
#include <vector>
@@ -27,6 +28,7 @@ protected:
input_code_poller(input_manager &manager) noexcept;
input_manager &m_manager;
+ std::vector<std::pair<input_device_item *, s32> > m_axis_memory;
};
@@ -38,7 +40,7 @@ public:
protected:
switch_code_poller_base(input_manager &manager) noexcept;
- bool code_pressed_once(input_code code);
+ bool code_pressed_once(input_code code, bool moved);
private:
std::vector<input_code> m_switch_memory;
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 4e7fb5412da..98f00a219d0 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -47,7 +47,7 @@ int luaopen_lsqlite3(lua_State *L);
template <typename T>
struct lua_engine::devenum
{
- devenum(device_t &d) : device(d), iter(d) { }
+ template <typename... U> devenum(device_t &d, U &&... args) : device(d), iter(d, std::forward<U>(args)...) { }
device_t &device;
T iter;
@@ -55,18 +55,85 @@ struct lua_engine::devenum
};
-template <typename T>
-struct lua_engine::object_ptr_vector_wrapper
+namespace {
+
+void do_draw_box(screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t fgcolor, uint32_t bgcolor)
+{
+ float const sc_width(sdev.visible_area().width());
+ float const sc_height(sdev.visible_area().height());
+ x1 = std::min(std::max(0.0f, x1), sc_width) / sc_width;
+ y1 = std::min(std::max(0.0f, y1), sc_height) / sc_height;
+ x2 = std::min(std::max(0.0f, x2), sc_width) / sc_width;
+ y2 = std::min(std::max(0.0f, y2), sc_height) / sc_height;
+ mame_machine_manager::instance()->ui().draw_outlined_box(sdev.container(), x1, y1, x2, y2, fgcolor, bgcolor);
+}
+
+void do_draw_line(screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t color)
+{
+ float const sc_width(sdev.visible_area().width());
+ float const sc_height(sdev.visible_area().height());
+ x1 = std::min(std::max(0.0f, x1), sc_width) / sc_width;
+ y1 = std::min(std::max(0.0f, y1), sc_height) / sc_height;
+ x2 = std::min(std::max(0.0f, x2), sc_width) / sc_width;
+ y2 = std::min(std::max(0.0f, y2), sc_height) / sc_height;
+ sdev.container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+}
+
+void do_draw_text(lua_State *L, screen_device &sdev, sol::object &xobj, float y, const char *msg, rgb_t fgcolor, rgb_t bgcolor)
+{
+ float const sc_width(sdev.visible_area().width());
+ float const sc_height(sdev.visible_area().height());
+ auto justify = ui::text_layout::LEFT;
+ float x = 0;
+ if (xobj.is<float>())
+ {
+ x = std::min(std::max(0.0f, xobj.as<float>()), sc_width) / sc_width;
+ }
+ else if (xobj.is<char const *>())
+ {
+ char const *const justifystr(xobj.as<char const *>());
+ if (!strcmp(justifystr, "left"))
+ justify = ui::text_layout::LEFT;
+ else if (!strcmp(justifystr, "right"))
+ justify = ui::text_layout::RIGHT;
+ else if (!strcmp(justifystr, "center"))
+ justify = ui::text_layout::CENTER;
+ }
+ else
+ {
+ luaL_error(L, "Error in param 1 to draw_text");
+ return;
+ }
+ y = std::min(std::max(0.0f, y), sc_height) / sc_height;
+ mame_machine_manager::instance()->ui().draw_text_full(
+ sdev.container(),
+ msg,
+ x, y, (1.0f - x),
+ justify, ui::text_layout::WORD,
+ mame_ui_manager::OPAQUE_, fgcolor, bgcolor);
+}
+
+
+struct image_interface_formats
{
- object_ptr_vector_wrapper(std::vector<std::unique_ptr<T>> const &v) : vec(v) { }
+ image_interface_formats(device_image_interface &i) : image(i) { }
+ device_image_interface::formatlist_type const &items() { return image.formatlist(); }
+
+ static image_device_format const &unwrap(device_image_interface::formatlist_type::const_iterator const &it) { return **it; }
+ static int push_key(lua_State *L, device_image_interface::formatlist_type::const_iterator const &it, std::size_t ix) { return sol::stack::push_reference(L, (*it)->name()); }
- std::vector<std::unique_ptr<T>> const &vec;
+ device_image_interface &image;
};
+} // anonymous namespace
+
namespace sol
{
+template <> struct is_container<image_interface_formats> : std::true_type { };
+
+
sol::buffer *sol_lua_get(sol::types<buffer *>, lua_State *L, int index, sol::stack::record &tracking)
{
return new sol::buffer(stack::get<int>(L, index), L);
@@ -181,74 +248,30 @@ public:
};
-template <typename T>
-struct usertype_container<lua_engine::object_ptr_vector_wrapper<T> > : lua_engine::immutable_collection_helper<lua_engine::object_ptr_vector_wrapper<T>, std::vector<std::unique_ptr<T>> const, typename std::vector<std::unique_ptr<T>>::const_iterator>
+template <>
+struct usertype_container<image_interface_formats> : lua_engine::immutable_sequence_helper<image_interface_formats, device_image_interface::formatlist_type const, device_image_interface::formatlist_type::const_iterator>
{
private:
- static int next_pairs(lua_State *L)
- {
- typename usertype_container::indexed_iterator &i(stack::unqualified_get<user<typename usertype_container::indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- result = stack::push(L, i.ix + 1);
- result += stack::push_reference(L, i.it->get());
- ++i;
- return result;
- }
+ using format_list = device_image_interface::formatlist_type;
public:
- static int at(lua_State *L)
- {
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.vec.size() < index))
- return stack::push(L, lua_nil);
- return stack::push_reference(L, self.vec[index - 1].get());
- }
-
- static int get(lua_State *L) { return at(L); }
- static int index_get(lua_State *L) { return at(L); }
-
- static int index_of(lua_State *L)
+ static int get(lua_State *L)
{
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- T &target(stack::unqualified_get<T>(L, 2));
- auto it(self.vec.begin());
- std::ptrdiff_t ix(0);
- while ((self.vec.end() != it) && (it->get() != &target))
- {
- ++it;
- ++ix;
- }
- if (self.vec.end() == it)
- return stack::push(L, lua_nil);
+ image_interface_formats &self(get_self(L));
+ char const *const name(stack::unqualified_get<char const *>(L));
+ auto const found(std::find_if(
+ self.image.formatlist().begin(),
+ self.image.formatlist().end(),
+ [&name] (std::unique_ptr<image_device_format> const &v) { return v->name() == name; }));
+ if (self.image.formatlist().end() != found)
+ return stack::push_reference(L, **found);
else
- return stack::push(L, ix + 1);
- }
-
- static int size(lua_State *L)
- {
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- return stack::push(L, self.vec.size());
- }
-
- static int empty(lua_State *L)
- {
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- return stack::push(L, self.vec.empty());
+ return stack::push(L, lua_nil);
}
- static int next(lua_State *L) { return stack::push(L, next_pairs); }
- static int pairs(lua_State *L) { return ipairs(L); }
-
- static int ipairs(lua_State *L)
+ static int index_get(lua_State *L)
{
- lua_engine::object_ptr_vector_wrapper<T> &self(usertype_container::get_self(L));
- stack::push(L, next_pairs);
- stack::push<user<typename usertype_container::indexed_iterator> >(L, self.vec, self.vec.begin());
- stack::push(L, lua_nil);
- return 3;
+ return get(L);
}
};
@@ -300,6 +323,40 @@ bool sol_lua_check(sol::types<osd_file::error>, lua_State *L, int index, Handler
}
+int sol_lua_push(sol::types<screen_type_enum>, lua_State *L, screen_type_enum &&value)
+{
+ switch (value)
+ {
+ case SCREEN_TYPE_INVALID: return sol::stack::push(L, "invalid");
+ case SCREEN_TYPE_RASTER: return sol::stack::push(L, "raster");
+ case SCREEN_TYPE_VECTOR: return sol::stack::push(L, "vector");
+ case SCREEN_TYPE_LCD: return sol::stack::push(L, "svg");
+ case SCREEN_TYPE_SVG: return sol::stack::push(L, "none");
+ }
+ return sol::stack::push(L, "unknown");
+}
+
+int sol_lua_push(sol::types<image_init_result>, lua_State *L, image_init_result &&value)
+{
+ switch (value)
+ {
+ case image_init_result::PASS: return sol::stack::push(L, "pass");
+ case image_init_result::FAIL: return sol::stack::push(L, "fail");
+ }
+ return sol::stack::push(L, "invalid");
+}
+
+int sol_lua_push(sol::types<image_verify_result>, lua_State *L, image_verify_result &&value)
+{
+ switch (value)
+ {
+ case image_verify_result::PASS: return sol::stack::push(L, "pass");
+ case image_verify_result::FAIL: return sol::stack::push(L, "fail");
+ }
+ return sol::stack::push(L, "invalid");
+}
+
+
//-------------------------------------------------
// process_snapshot_filename - processes a snapshot
// filename
@@ -558,14 +615,6 @@ void lua_engine::initialize()
};
- static const enum_parser<ui::text_layout::text_justify, 3> s_text_justify_parser =
- {
- { "left", ui::text_layout::LEFT },
- { "right", ui::text_layout::RIGHT },
- { "center", ui::text_layout::CENTER },
- };
-
-
static const enum_parser<int, 3> s_seek_parser =
{
{ "set", SEEK_SET },
@@ -617,6 +666,7 @@ void lua_engine::initialize()
* emu.device_enumerator(dev) - get device enumerator starting at arbitrary point in tree
* emu.screen_enumerator(dev) - get screen device enumerator starting at arbitrary point in tree
* emu.image_enumerator(dev) - get image interface enumerator starting at arbitrary point in tree
+ * emu.image_enumerator(dev) - get image interface enumerator starting at arbitrary point in tree
*/
sol::table emu = sol().create_named_table("emu");
@@ -712,9 +762,21 @@ void lua_engine::initialize()
osd_subst_env(result, str);
return result;
};
- emu["device_enumerator"] = [] (device_t &d) { return devenum<device_enumerator>(d); };
- emu["screen_enumerator"] = [] (device_t &d) { return devenum<screen_device_enumerator>(d); };
- emu["image_enumerator"] = [] (device_t &d) { return devenum<image_interface_enumerator>(d); };
+ emu["device_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<device_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<device_enumerator>(dev, maxdepth); });
+ emu["screen_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<screen_device_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<screen_device_enumerator>(dev, maxdepth); });
+ emu["cassette_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<cassette_device_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<cassette_device_enumerator>(dev, maxdepth); });
+ emu["image_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<image_interface_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<image_interface_enumerator>(dev, maxdepth); });
+ emu["slot_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<slot_interface_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<slot_interface_enumerator>(dev, maxdepth); });
/* emu_file library
@@ -1313,33 +1375,6 @@ void lua_engine::initialize()
game_driver_type["is_incomplete"] = sol::property([] (game_driver const &driver) { return (driver.flags & machine_flags::IS_INCOMPLETE) != 0; });
-/* device_t library
- *
- * manager:machine().devices[device_tag]
- *
- * device:subtag(tag) - get absolute tag relative to this device
- * device:siblingtag(tag) - get absolute tag relative to this device
- * device:memregion(tag) - get memory region
- * device:memshare(tag) - get memory share
- * device:membank(tag) - get memory bank
- * device:ioport(tag) - get I/O port
- * device:subdevice(tag) - get subdevice
- * device:siblingdevice(tag) - get sibling device
- * device:debug() - debug interface, CPUs only
- *
- * device.tag - device tree tag
- * device.basetag - last component of tag ("root" for root device)
- * device.name - device type full name
- * device.shortname - device type short name
- * device.owner - parent device (nil for root device)
- * device.configured - whether configuration is complete
- * device.started - whether the device has been started
- * device.spaces[] - device address spaces table (k=name, v=addr_space)
- * device.state[] - device state entries table (k=name, v=device_state_entry)
- * device.items[] - device save state items table (k=name, v=index)
- * device.roms[] - device rom entry table (k=name, v=rom_entry)
- */
-
auto device_type = sol().registry().new_usertype<device_t>("device", sol::no_constructor);
device_type["subtag"] = &device_t::subtag;
device_type["siblingtag"] = &device_t::siblingtag;
@@ -1349,13 +1384,6 @@ void lua_engine::initialize()
device_type["ioport"] = &device_t::ioport;
device_type["subdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::subdevice);
device_type["siblingdevice"] = static_cast<device_t *(device_t::*)(char const *) const>(&device_t::siblingdevice);
- device_type["debug"] =
- [this] (device_t &dev) -> sol::object
- {
- if (!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
- return sol::make_object(sol(), sol::lua_nil);
- return sol::make_object(sol(), dev.debug());
- };
device_type["tag"] = sol::property(&device_t::tag);
device_type["basetag"] = sol::property(&device_t::basetag);
device_type["name"] = sol::property(&device_t::name);
@@ -1363,20 +1391,28 @@ void lua_engine::initialize()
device_type["owner"] = sol::property(&device_t::owner);
device_type["configured"] = sol::property(&device_t::configured);
device_type["started"] = sol::property(&device_t::started);
+ device_type["debug"] = sol::property(
+ [this] (device_t &dev) -> sol::object
+ {
+ if (!(dev.machine().debug_flags & DEBUG_FLAG_ENABLED) || !dynamic_cast<cpu_device *>(&dev)) // debugger not enabled or not cpu
+ return sol::make_object(sol(), sol::lua_nil);
+ return sol::make_object(sol(), dev.debug());
+ });
device_type["spaces"] = sol::property(
[this] (device_t &dev)
{
- device_memory_interface *memdev = dynamic_cast<device_memory_interface *>(&dev);
+ device_memory_interface *const memdev = dynamic_cast<device_memory_interface *>(&dev);
sol::table sp_table = sol().create_table();
- if(!memdev)
+ if (!memdev)
return sp_table;
- for(int sp = 0; sp < memdev->max_space_count(); ++sp)
+ for (int sp = 0; sp < memdev->max_space_count(); ++sp)
{
- if(memdev->has_space(sp))
+ if (memdev->has_space(sp))
sp_table[memdev->space(sp).name()] = addr_space(memdev->space(sp), *memdev);
}
return sp_table;
});
+ // FIXME: improve this
device_type["state"] = sol::property(
[this] (device_t &dev)
{
@@ -1388,41 +1424,246 @@ void lua_engine::initialize()
st_table[s->symbol()] = s.get();
return st_table;
});
+ // FIXME: turn into a wrapper - it's stupid slow to walk on every property access
+ // also, this mixes up things like RAM areas with stuff saved by the device itself, so there's potential for key conflicts
device_type["items"] = sol::property(
[this] (device_t &dev)
{
sol::table table = sol().create_table();
- std::string tag = dev.tag();
- // 10000 is enough?
- for(int i = 0; i < 10000; i++)
+ std::string const tag = dev.tag();
+ for (int i = 0; ; i++)
{
- std::string name;
- const char *item;
+ char const *item;
void *base;
uint32_t size, valcount, blockcount, stride;
item = dev.machine().save().indexed_item(i, base, size, valcount, blockcount, stride);
- if(!item)
+ if (!item)
break;
- name = &(strchr(item, '/')[1]);
- if(name.substr(0, name.find('/')) == tag)
- {
- name = name.substr(name.find('/') + 1, std::string::npos);
- table[name] = i;
- }
+
+ char const *name = &strchr(item, '/')[1];
+ if (!strncmp(tag.c_str(), name, tag.length()) && (name[tag.length()] == '/'))
+ table[name + tag.length() + 1] = i;
}
return table;
});
+ // FIXME: this is useless in its current form
device_type["roms"] = sol::property(
[this] (device_t &dev)
{
sol::table table = sol().create_table();
- for(auto rom : dev.rom_region_vector())
- if(!rom.name().empty())
+ for (auto rom : dev.rom_region_vector())
+ if (!rom.name().empty())
table[rom.name()] = rom;
return table;
});
+ auto screen_dev_type = sol().registry().new_usertype<screen_device>(
+ "screen_dev",
+ sol::no_constructor,
+ sol::base_classes, sol::bases<device_t>());
+ screen_dev_type["draw_box"] = sol::overload(
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t fgcolor, uint32_t bgcolor)
+ { do_draw_box(sdev, x1, y1, x2, y2, fgcolor, bgcolor); },
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t fgcolor)
+ { do_draw_box(sdev, x1, y1, x2, y2, fgcolor, mame_machine_manager::instance()->ui().colors().background_color()); },
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2)
+ { auto const &colors(mame_machine_manager::instance()->ui().colors()); do_draw_box(sdev, x1, y1, x2, y2, colors.text_color(), colors.background_color()); });
+ screen_dev_type["draw_line"] = sol::overload(
+ &do_draw_line,
+ [] (screen_device &sdev, float x1, float y1, float x2, float y2)
+ { do_draw_line(sdev, x1, y1, x2, y2, mame_machine_manager::instance()->ui().colors().text_color()); });
+ screen_dev_type["draw_text"] = sol::overload(
+ [this] (screen_device &sdev, sol::object xobj, float y, const char *msg, uint32_t fgcolor, uint32_t bgcolor)
+ { do_draw_text(m_lua_state, sdev, xobj, y, msg, fgcolor, bgcolor); },
+ [this] (screen_device &sdev, sol::object xobj, float y, const char *msg, uint32_t fgcolor)
+ { do_draw_text(m_lua_state, sdev, xobj, y, msg, fgcolor, 0); },
+ [this] (screen_device &sdev, sol::object xobj, float y, const char *msg)
+ { do_draw_text(m_lua_state, sdev, xobj, y, msg, mame_machine_manager::instance()->ui().colors().text_color(), 0); });
+ screen_dev_type["orientation"] =
+ [] (screen_device &sdev)
+ {
+ uint32_t flags = sdev.orientation();
+ int rotation_angle = 0;
+ switch (flags)
+ {
+ case ORIENTATION_SWAP_XY:
+ case ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X:
+ rotation_angle = 90;
+ flags ^= ORIENTATION_FLIP_X;
+ break;
+ case ORIENTATION_FLIP_Y:
+ case ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y:
+ rotation_angle = 180;
+ flags ^= ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y;
+ break;
+ case ORIENTATION_SWAP_XY | ORIENTATION_FLIP_Y:
+ case ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y:
+ rotation_angle = 270;
+ flags ^= ORIENTATION_FLIP_Y;
+ break;
+ }
+ return std::tuple<int, bool, bool>(rotation_angle, flags & ORIENTATION_FLIP_X, flags & ORIENTATION_FLIP_Y);
+ };
+ screen_dev_type["time_until_pos"] = sol::overload(
+ [] (screen_device &sdev, int vpos) { return sdev.time_until_pos(vpos).as_double(); },
+ [] (screen_device &sdev, int vpos, int hpos) { return sdev.time_until_pos(vpos, hpos).as_double(); });
+ screen_dev_type["time_until_vblank_start"] = &screen_device::time_until_vblank_start;
+ screen_dev_type["time_until_vblank_end"] = &screen_device::time_until_vblank_end;
+ screen_dev_type["snapshot"] =
+ [this] (screen_device &sdev, char const *filename) -> sol::object
+ {
+ std::string snapstr;
+ bool is_absolute_path = false;
+ if (filename)
+ {
+ // a filename was specified; if it isn't absolute post-process it
+ snapstr = process_snapshot_filename(machine(), filename);
+ is_absolute_path = osd_is_absolute_path(snapstr);
+ }
+
+ // open the file
+ emu_file file(is_absolute_path ? "" : machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ osd_file::error filerr;
+ if (!snapstr.empty())
+ filerr = file.open(snapstr);
+ else
+ filerr = machine().video().open_next(file, "png");
+ if (filerr != osd_file::error::NONE)
+ return sol::make_object(sol(), filerr);
+
+ // and save the snapshot
+ machine().video().save_snapshot(&sdev, file);
+ return sol::make_object(sol(), sol::lua_nil);
+ };
+ screen_dev_type["pixel"] = [] (screen_device &sdev, s32 x, s32 y) { return sdev.pixel(x, y); };
+ screen_dev_type["pixels"] =
+ [] (screen_device &sdev, sol::this_state s)
+ {
+ lua_State *L = s;
+ const rectangle &visarea = sdev.visible_area();
+ luaL_Buffer buff;
+ int size = visarea.height() * visarea.width() * 4;
+ u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
+ sdev.pixels(ptr);
+ luaL_pushresultsize(&buff, size);
+ return sol::make_reference(L, sol::stack_reference(L, -1));
+ };
+ screen_dev_type["screen_type"] = sol::property(&screen_device::screen_type);
+ screen_dev_type["width"] = sol::property([] (screen_device &sdev) { return sdev.visible_area().width(); });
+ screen_dev_type["height"] = sol::property([] (screen_device &sdev) { return sdev.visible_area().height(); });
+ screen_dev_type["refresh"] = sol::property([] (screen_device &sdev) { return ATTOSECONDS_TO_HZ(sdev.refresh_attoseconds()); });
+ screen_dev_type["refresh_attoseconds"] = sol::property([] (screen_device &sdev) { return sdev.refresh_attoseconds(); });
+ screen_dev_type["xofffset"] = sol::property(&screen_device::xoffset);
+ screen_dev_type["yofffset"] = sol::property(&screen_device::yoffset);
+ screen_dev_type["xscale"] = sol::property(&screen_device::xscale);
+ screen_dev_type["yscale"] = sol::property(&screen_device::yscale);
+ screen_dev_type["pixel_period"] = sol::property([] (screen_device &sdev) { return sdev.pixel_period().as_double(); });
+ screen_dev_type["scan_period"] = sol::property([] (screen_device &sdev) { return sdev.scan_period().as_double(); });
+ screen_dev_type["frame_period"] = sol::property([] (screen_device &sdev) { return sdev.frame_period().as_double(); });
+ screen_dev_type["frame_number"] = &screen_device::frame_number;
+ screen_dev_type["container"] = sol::property(&screen_device::container);
+
+
+ auto cass_type = sol().registry().new_usertype<cassette_image_device>(
+ "cassette",
+ sol::no_constructor,
+ sol::base_classes, sol::bases<device_t, device_image_interface>());
+ cass_type["stop"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); };
+ cass_type["play"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); };
+ cass_type["record"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); };
+ cass_type["forward"] = &cassette_image_device::go_forward;
+ cass_type["reverse"] = &cassette_image_device::go_reverse;
+ cass_type["seek"] = [] (cassette_image_device &c, double time, const char* origin) { if (c.exists()) c.seek(time, s_seek_parser(origin)); };
+ cass_type["is_stopped"] = sol::property(&cassette_image_device::is_stopped);
+ cass_type["is_playing"] = sol::property(&cassette_image_device::is_playing);
+ cass_type["is_recording"] = sol::property(&cassette_image_device::is_recording);
+ cass_type["motor_state"] = sol::property(&cassette_image_device::motor_on, &cassette_image_device::set_motor);
+ cass_type["speaker_state"] = sol::property(&cassette_image_device::speaker_on, &cassette_image_device::set_speaker);
+ cass_type["position"] = sol::property(&cassette_image_device::get_position);
+ cass_type["length"] = sol::property([] (cassette_image_device &c) { return c.exists() ? c.get_length() : 0.0; });
+
+
+ auto image_type = sol().registry().new_usertype<device_image_interface>("image", "new", sol::no_constructor);
+ image_type["load"] = &device_image_interface::load;
+ image_type["load_software"] = static_cast<image_init_result (device_image_interface::*)(const std::string &)>(&device_image_interface::load_software);
+ image_type["unload"] = &device_image_interface::unload;
+ image_type["create"] = static_cast<image_init_result (device_image_interface::*)(const std::string &)>(&device_image_interface::create);
+ image_type["display"] = &device_image_interface::call_display;
+ image_type["is_readable"] = sol::property(&device_image_interface::is_readable);
+ image_type["is_writeable"] = sol::property(&device_image_interface::is_writeable);
+ image_type["is_creatable"] = sol::property(&device_image_interface::is_creatable);
+ image_type["must_be_loaded"] = sol::property(&device_image_interface::must_be_loaded);
+ image_type["is_reset_on_load"] = sol::property(&device_image_interface::is_reset_on_load);
+ image_type["image_type_name"] = sol::property(&device_image_interface::image_type_name);
+ image_type["instance_name"] = sol::property(&device_image_interface::instance_name);
+ image_type["brief_instance_name"] = sol::property(&device_image_interface::brief_instance_name);
+ image_type["formatlist"] = sol::property([] (device_image_interface &image) { return image_interface_formats(image); });
+ image_type["exists"] = sol::property(&device_image_interface::exists);
+ image_type["readonly"] = sol::property(&device_image_interface::is_readonly);
+ image_type["filename"] = sol::property(&device_image_interface::filename);
+ image_type["crc"] = sol::property(&device_image_interface::crc);
+ image_type["loaded_through_softlist"] = sol::property(&device_image_interface::loaded_through_softlist);
+ image_type["software_list_name"] = sol::property(&device_image_interface::software_list_name);
+ image_type["software_longname"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->longname().c_str() : nullptr;
+ });
+ image_type["software_publisher"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->publisher().c_str() : nullptr;
+ });
+ image_type["software_year"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->year().c_str() : nullptr;
+ });
+ image_type["software_parent"] = sol::property(
+ [] (device_image_interface &di)
+ {
+ software_info const *const si(di.software_entry());
+ return si ? si->parentname().c_str() : nullptr;
+ });
+ image_type["device"] = sol::property(static_cast<device_t & (device_image_interface::*)()>(&device_image_interface::device));
+
+
+ auto format_type = sol().registry().new_usertype<image_device_format>("image_format", sol::no_constructor);
+ format_type["name"] = sol::property(&image_device_format::name);
+ format_type["description"] = sol::property(&image_device_format::description);
+ format_type["extensions"] = sol::property(
+ [this] (image_device_format const &format)
+ {
+ int index = 1;
+ sol::table option_table = sol().create_table();
+ for (std::string const &ext : format.extensions())
+ option_table[index++] = ext;
+ return option_table;
+ });
+ format_type["option_spec"] = sol::property(&image_device_format::optspec);
+
+
+ auto slot_type = sol().registry().new_usertype<device_slot_interface>("slot", sol::no_constructor);
+ slot_type["fixed"] = sol::property(&device_slot_interface::fixed);
+ slot_type["has_selectable_options"] = sol::property(&device_slot_interface::has_selectable_options);
+ slot_type["default_option"] = sol::property(&device_slot_interface::default_option);
+ slot_type["options"] = sol::property([] (device_slot_interface const &slot) { return standard_tag_object_ptr_map<device_slot_interface::slot_option>(slot.option_list()); });
+ slot_type["device"] = sol::property(static_cast<device_t & (device_slot_interface::*)()>(&device_slot_interface::device));
+
+
+ auto dislot_option_type = sol().registry().new_usertype<device_slot_interface::slot_option>("dislot_option", sol::no_constructor);
+ dislot_option_type["name"] = sol::property(&device_slot_interface::slot_option::name);
+ dislot_option_type["device_fullname"] = sol::property([] (device_slot_interface::slot_option &opt) { return opt.devtype().fullname(); });
+ dislot_option_type["device_shortname"] = sol::property([] (device_slot_interface::slot_option &opt) { return opt.devtype().shortname(); });
+ dislot_option_type["selectable"] = sol::property(&device_slot_interface::slot_option::selectable);
+ dislot_option_type["default_bios"] = sol::property(static_cast<char const * (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::default_bios));
+ dislot_option_type["clock"] = sol::property(static_cast<u32 (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::clock));
+
+
/* parameters_manager library
*
* manager:machine():parameters()
@@ -1537,160 +1778,6 @@ void lua_engine::initialize()
sound_type.set("attenuation", sol::property(&sound_manager::attenuation, &sound_manager::set_attenuation));
-/* screen_device library
- *
- * manager:machine().screens[screen_tag]
- *
- * screen:draw_box(x1, y1, x2, y2, fillcol, linecol) - draw box from (x1, y1)-(x2, y2) colored linecol
- * filled with fillcol, color is 32bit argb
- * screen:draw_line(x1, y1, x2, y2, linecol) - draw line from (x1, y1)-(x2, y2) colored linecol
- * screen:draw_text(x || justify, y, message, [opt] fgcolor, [opt] bgcolor) - draw message at (x, y) or at line y
- * with left/right/center justification
- * screen:height() - screen height
- * screen:width() - screen width
- * screen:orientation() - screen angle, flipx, flipy
- * screen:refresh() - screen refresh rate in Hz
- * screen:refresh_attoseconds() - screen refresh rate in attoseconds
- * screen:snapshot([opt] filename) - save snap shot
- * screen:type() - screen drawing type
- * screen:frame_number() - screen frame count
- * screen:xscale() - screen x scale factor
- * screen:yscale() - screen y scale factor
- * screen:pixel(x, y) - get pixel at (x, y) as packed RGB in a u32
- * screen:pixels() - get whole screen binary bitmap as string
- * screen:time_until_pos(vpos, hpos) - get the time until this screen pos is reached
- */
-
- auto screen_dev_type = sol().registry().new_usertype<screen_device>(
- "screen_dev",
- sol::no_constructor,
- sol::base_classes, sol::bases<device_t>());
- screen_dev_type.set("container", sol::property(&screen_device::container));
- screen_dev_type.set("draw_box", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t bgcolor, uint32_t fgcolor) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
- y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
- x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
- y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
- mame_machine_manager::instance()->ui().draw_outlined_box(sdev.container(), x1, y1, x2, y2, fgcolor, bgcolor);
- });
- screen_dev_type.set("draw_line", [](screen_device &sdev, float x1, float y1, float x2, float y2, uint32_t color) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- x1 = std::min(std::max(0.0f, x1), float(sc_width-1)) / float(sc_width);
- y1 = std::min(std::max(0.0f, y1), float(sc_height-1)) / float(sc_height);
- x2 = std::min(std::max(0.0f, x2), float(sc_width-1)) / float(sc_width);
- y2 = std::min(std::max(0.0f, y2), float(sc_height-1)) / float(sc_height);
- sdev.container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
- });
- screen_dev_type.set("draw_text", [this](screen_device &sdev, sol::object xobj, float y, const char *msg, sol::object color, sol::object bcolor) {
- int sc_width = sdev.visible_area().width();
- int sc_height = sdev.visible_area().height();
- auto justify = ui::text_layout::LEFT;
- float x = 0;
- if(xobj.is<float>())
- {
- x = std::min(std::max(0.0f, xobj.as<float>()), float(sc_width-1)) / float(sc_width);
- y = std::min(std::max(0.0f, y), float(sc_height-1)) / float(sc_height);
- }
- else if(xobj.is<const char *>())
- {
- justify = s_text_justify_parser(xobj.as<const char *>());
- }
- else
- {
- luaL_error(m_lua_state, "Error in param 1 to draw_text");
- return;
- }
- rgb_t textcolor = mame_machine_manager::instance()->ui().colors().text_color();
- rgb_t bgcolor = 0;
- if(color.is<uint32_t>())
- textcolor = rgb_t(color.as<uint32_t>());
- if(bcolor.is<uint32_t>())
- bgcolor = rgb_t(bcolor.as<uint32_t>());
- mame_machine_manager::instance()->ui().draw_text_full(sdev.container(), msg, x, y, (1.0f - x),
- justify, ui::text_layout::WORD, mame_ui_manager::OPAQUE_, textcolor, bgcolor);
- });
- screen_dev_type.set("height", [](screen_device &sdev) { return sdev.visible_area().height(); });
- screen_dev_type.set("width", [](screen_device &sdev) { return sdev.visible_area().width(); });
- screen_dev_type.set("orientation", [](screen_device &sdev) {
- uint32_t flags = sdev.orientation();
- int rotation_angle = 0;
- switch (flags)
- {
- case ORIENTATION_FLIP_X:
- rotation_angle = 0;
- break;
- case ORIENTATION_SWAP_XY:
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X:
- rotation_angle = 90;
- break;
- case ORIENTATION_FLIP_Y:
- case ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- rotation_angle = 180;
- break;
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_Y:
- case ORIENTATION_SWAP_XY|ORIENTATION_FLIP_X|ORIENTATION_FLIP_Y:
- rotation_angle = 270;
- break;
- }
- return std::tuple<int, bool, bool>(rotation_angle, flags & ORIENTATION_FLIP_X, flags & ORIENTATION_FLIP_Y);
- });
- screen_dev_type.set("refresh", [](screen_device &sdev) { return ATTOSECONDS_TO_HZ(sdev.refresh_attoseconds()); });
- screen_dev_type.set("refresh_attoseconds", [](screen_device &sdev) { return sdev.refresh_attoseconds(); });
- screen_dev_type.set("snapshot", [this](screen_device &sdev, sol::object filename) -> sol::object {
- std::string snapstr;
- bool is_absolute_path = false;
- if (filename.is<const char *>())
- {
- // a filename was specified; if it isn't absolute postprocess it
- snapstr = process_snapshot_filename(machine(), filename.as<const char *>());
- is_absolute_path = osd_is_absolute_path(snapstr);
- }
-
- // open the file
- emu_file file(is_absolute_path ? "" : machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- osd_file::error filerr;
- if (!snapstr.empty())
- filerr = file.open(snapstr);
- else
- filerr = machine().video().open_next(file, "png");
- if (filerr != osd_file::error::NONE)
- return sol::make_object(sol(), filerr);
-
- // and save the snapshot
- machine().video().save_snapshot(&sdev, file);
- return sol::make_object(sol(), sol::lua_nil);
- });
- screen_dev_type.set("type", [](screen_device &sdev) {
- switch (sdev.screen_type())
- {
- case SCREEN_TYPE_RASTER: return "raster"; break;
- case SCREEN_TYPE_VECTOR: return "vector"; break;
- case SCREEN_TYPE_LCD: return "lcd"; break;
- case SCREEN_TYPE_SVG: return "svg"; break;
- default: break;
- }
- return "unknown";
- });
- screen_dev_type.set("frame_number", &screen_device::frame_number);
- screen_dev_type.set("xscale", &screen_device::xscale);
- screen_dev_type.set("yscale", &screen_device::yscale);
- screen_dev_type.set("pixel", [](screen_device &sdev, float x, float y) { return sdev.pixel((s32)x, (s32)y); });
- screen_dev_type.set("pixels", [](screen_device &sdev, sol::this_state s) {
- lua_State *L = s;
- const rectangle &visarea = sdev.visible_area();
- luaL_Buffer buff;
- int size = visarea.height() * visarea.width() * 4;
- u32 *ptr = (u32 *)luaL_buffinitsize(L, &buff, size);
- sdev.pixels(ptr);
- luaL_pushresultsize(&buff, size);
- return sol::make_reference(L, sol::stack_reference(L, -1));
- });
- screen_dev_type.set("time_until_pos", [](screen_device &sdev, int vpos, int hpos) { return sdev.time_until_pos(vpos, hpos).as_double(); });
-
-
/* mame_ui_manager library
*
* manager:ui()
@@ -1799,160 +1886,6 @@ void lua_engine::initialize()
output_type.set("id_to_name", &output_manager::id_to_name);
-/* device_image_interface library
- *
- * manager:machine().images[image_type]
- *
- * image:exists()
- * image:filename() - full path to the image file
- * image:longname()
- * image:manufacturer()
- * image:year()
- * image:software_list_name()
- * image:image_type_name() - floppy/cart/cdrom/tape/hdd etc
- * image:load(filename)
- * image:load_software(softlist_name)
- * image:unload()
- * image:create()
- * image:crc()
- * image:display()
- *
- * image.device - get associated device_t
- * image.instance_name
- * image.brief_instance_name
- * image.software_parent
- * image.is_readable
- * image.is_writeable
- * image.is_creatable
- * image.is_reset_on_load
- * image.must_be_loaded
- * image.formatlist
- */
-
- auto image_type = sol().registry().new_usertype<device_image_interface>("image", "new", sol::no_constructor);
- image_type.set("exists", &device_image_interface::exists);
- image_type.set("filename", &device_image_interface::filename);
- image_type.set("longname", &device_image_interface::longname);
- image_type.set("manufacturer", &device_image_interface::manufacturer);
- image_type.set("year", &device_image_interface::year);
- image_type.set("software_list_name", &device_image_interface::software_list_name);
- image_type.set("software_parent", sol::property([](device_image_interface &di) {
- const software_info *si = di.software_entry();
- return si ? si->parentname() : "";
- }));
- image_type.set("image_type_name", &device_image_interface::image_type_name);
- image_type.set("load", &device_image_interface::load);
- image_type.set("load_software", static_cast<image_init_result (device_image_interface::*)(const std::string &)>(&device_image_interface::load_software));
- image_type.set("unload", &device_image_interface::unload);
- image_type.set("create", [](device_image_interface &di, const std::string &filename) { return di.create(filename); });
- image_type.set("crc", &device_image_interface::crc);
- image_type.set("display", [](device_image_interface &di) { return di.call_display(); });
- image_type.set("device", sol::property(static_cast<device_t & (device_image_interface::*)()>(&device_image_interface::device)));
- image_type.set("instance_name", sol::property(&device_image_interface::instance_name));
- image_type.set("brief_instance_name", sol::property(&device_image_interface::brief_instance_name));
- image_type.set("is_readable", sol::property(&device_image_interface::is_readable));
- image_type.set("is_writeable", sol::property(&device_image_interface::is_writeable));
- image_type.set("is_creatable", sol::property(&device_image_interface::is_creatable));
- image_type.set("is_reset_on_load", sol::property(&device_image_interface::is_reset_on_load));
- image_type.set("must_be_loaded", sol::property(&device_image_interface::must_be_loaded));
- image_type.set("formatlist", sol::property([](const device_image_interface &image) { return object_ptr_vector_wrapper<image_device_format>(image.formatlist()); }));
-
-
-/* image_device_format library
- *
- * manager:machine().images[tag].formatlist[index]
- *
- * format.name - name of the format (e.g. - "dsk")
- * format.description - the description of the format
- * format.extensions - all of the extensions, as an array
- * format.optspec - the option spec associated with the format
- *
- */
- auto format_type = sol().registry().new_usertype<image_device_format>("image_format", sol::no_constructor);
- format_type["name"] = sol::property(&image_device_format::name);
- format_type["description"] = sol::property(&image_device_format::description);
- format_type["optspec"] = sol::property(&image_device_format::optspec);
- format_type["extensions"] = sol::property([this](const image_device_format &format) {
- int index = 1;
- sol::table option_table = sol().create_table();
- for (const std::string &ext : format.extensions())
- option_table[index++] = ext;
- return option_table;
- });
-
-
-/* device_slot_interface library
- *
- * manager:machine().slots[slot_name]
- *
- * slot.fixed - whether this slot is fixed, and hence not selectable by the user
- * slot.has_selectable_options - does this slot have any selectable options at all?
- * slot.default_option - returns the default option if one exists
- * slot.options[] - get options table (k=name, v=device_slot_interface::slot_option)
- */
-
- auto slot_type = sol().registry().new_usertype<device_slot_interface>("slot", sol::no_constructor);
- slot_type["fixed"] = sol::property(&device_slot_interface::fixed);
- slot_type["has_selectable_options"] = sol::property(&device_slot_interface::has_selectable_options);
- slot_type["default_option"] = sol::property(&device_slot_interface::default_option);
- slot_type["options"] = sol::property([] (device_slot_interface const &slot) { return standard_tag_object_ptr_map<device_slot_interface::slot_option>(slot.option_list()); });
-
-
-/* device_slot_interface::slot_option library
- *
- * manager:machine().slots[slot_name].options[option_name]
- *
- * slot_option.selectable - is this item selectable by the user?
- * slot_option.default_bios - the default bios for this option
- * slot_option.clock - the clock speed associated with this option
- */
-
- auto dislot_option_type = sol().registry().new_usertype<device_slot_interface::slot_option>("dislot_option", sol::no_constructor);
- dislot_option_type["selectable"] = sol::property(&device_slot_interface::slot_option::selectable);
- dislot_option_type["default_bios"] = sol::property(static_cast<char const * (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::default_bios));
- dislot_option_type["clock"] = sol::property(static_cast<u32 (device_slot_interface::slot_option::*)() const>(&device_slot_interface::slot_option::clock));
-
-
-/* cassette_image_device library
- *
- * manager:machine().cassettes[cass_name]
- *
- * cass:play()
- * cass:stop()
- * cass:record()
- * cass:forward() - forward play direction
- * cass:reverse() - reverse play direction
- * cass:seek(time, origin) - seek time sec from origin: "set", "cur", "end"
- *
- * cass.is_stopped
- * cass.is_playing
- * cass.is_recording
- * cass.motor_state
- * cass.speaker_state
- * cass.position
- * cass.length
- * cass.image - get the device_image_interface for this cassette device
- */
-
- auto cass_type = sol().registry().new_usertype<cassette_image_device>(
- "cassette",
- sol::no_constructor,
- sol::base_classes, sol::bases<device_t, device_image_interface>());
- cass_type["stop"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); };
- cass_type["play"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); };
- cass_type["record"] = [] (cassette_image_device &c) { c.change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); };
- cass_type["forward"] = &cassette_image_device::go_forward;
- cass_type["reverse"] = &cassette_image_device::go_reverse;
- cass_type["seek"] = [] (cassette_image_device &c, double time, const char* origin) { if (c.exists()) c.seek(time, s_seek_parser(origin)); };
- cass_type["is_stopped"] = sol::property(&cassette_image_device::is_stopped);
- cass_type["is_playing"] = sol::property(&cassette_image_device::is_playing);
- cass_type["is_recording"] = sol::property(&cassette_image_device::is_recording);
- cass_type["motor_state"] = sol::property(&cassette_image_device::motor_on, &cassette_image_device::set_motor);
- cass_type["speaker_state"] = sol::property(&cassette_image_device::speaker_on, &cassette_image_device::set_speaker);
- cass_type["position"] = sol::property(&cassette_image_device::get_position);
- cass_type["length"] = sol::property([] (cassette_image_device &c) { return c.exists() ? c.get_length() : 0.0; });
-
-
/* mame_machine_manager library
*
* manager
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index b0bbf2210c3..973dfedfd89 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -34,11 +34,11 @@ public:
// helper structures
template <typename T> struct devenum;
template <typename T> struct simple_list_wrapper;
- template <typename T> struct object_ptr_vector_wrapper;
template <typename T> struct tag_object_ptr_map;
template <typename T> using standard_tag_object_ptr_map = tag_object_ptr_map<std::unordered_map<std::string, std::unique_ptr<T> > >;
template <typename T> struct immutable_container_helper;
template <typename T, typename C, typename I = typename C::iterator> struct immutable_collection_helper;
+ template <typename T, typename C, typename I = typename C::iterator> struct immutable_sequence_helper;
// construction/destruction
lua_engine();
diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp
index 8d51fb0a092..d532b8be1b4 100644
--- a/src/frontend/mame/luaengine.ipp
+++ b/src/frontend/mame/luaengine.ipp
@@ -89,7 +89,6 @@ int sol_lua_push(sol::types<buffer *>, lua_State *L, buffer *value);
template <typename T> struct is_container<lua_engine::devenum<T> > : std::true_type { };
template <typename T> struct is_container<lua_engine::simple_list_wrapper<T> > : std::true_type { };
template <typename T> struct is_container<lua_engine::tag_object_ptr_map<T> > : std::true_type { };
-template <typename T> struct is_container<lua_engine::object_ptr_vector_wrapper<T> > : std::true_type { };
template <typename T> struct usertype_container<lua_engine::devenum<T> >;
@@ -256,7 +255,6 @@ public:
static int ipairs(lua_State *L) { return start_pairs<true>(L); }
};
-
} // namespace sol
@@ -265,10 +263,10 @@ int sol_lua_push(sol::types<osd_file::error>, lua_State *L, osd_file::error &&va
template <typename Handler>
bool sol_lua_check(sol::types<osd_file::error>, lua_State *L, int index, Handler &&handler, sol::stack::record &tracking);
-// map_handler_type customisation
+// enums to automatically convert to strings
int sol_lua_push(sol::types<map_handler_type>, lua_State *L, map_handler_type &&value);
-
-// endianness_t customisation
+int sol_lua_push(sol::types<image_init_result>, lua_State *L, image_init_result &&value);
+int sol_lua_push(sol::types<image_verify_result>, lua_State *L, image_verify_result &&value);
int sol_lua_push(sol::types<endianness_t>, lua_State *L, endianness_t &&value);
@@ -353,6 +351,83 @@ protected:
};
+template <typename T, typename C, typename I>
+struct lua_engine::immutable_sequence_helper : immutable_collection_helper<T, C, I>
+{
+protected:
+ template <bool Indexed>
+ static int next_pairs(lua_State *L)
+ {
+ auto &i(sol::stack::unqualified_get<sol::user<typename immutable_sequence_helper::indexed_iterator> >(L, 1));
+ if (i.src.end() == i.it)
+ return sol::stack::push(L, sol::lua_nil);
+ int result;
+ if constexpr (Indexed)
+ result = sol::stack::push(L, i.ix + 1);
+ else
+ result = T::push_key(L, i.it, i.ix);
+ result += sol::stack::push_reference(L, T::unwrap(i.it));
+ ++i;
+ return result;
+ }
+
+ template <bool Indexed>
+ static int start_pairs(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ sol::stack::push(L, next_pairs<Indexed>);
+ sol::stack::push<sol::user<typename immutable_sequence_helper::indexed_iterator> >(L, self.items(), self.items().begin());
+ sol::stack::push(L, sol::lua_nil);
+ return 3;
+ }
+
+public:
+ static int at(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ std::ptrdiff_t const index(sol::stack::unqualified_get<std::ptrdiff_t>(L, 2));
+ if ((0 >= index) || (self.items().size() < index))
+ return sol::stack::push(L, sol::lua_nil);
+ else
+ return sol::stack::push_reference(L, T::unwrap(std::next(self.items().begin(), index - 1)));
+ }
+
+ static int index_of(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ auto it(self.items().begin());
+ std::ptrdiff_t ix(0);
+ auto const &item(sol::stack::unqualified_get<decltype(T::unwrap(it))>(L, 2));
+ while ((self.items().end() != it) && (&item != &T::unwrap(it)))
+ {
+ ++it;
+ ++ix;
+ }
+ if (self.items().end() == it)
+ return sol::stack::push(L, sol::lua_nil);
+ else
+ return sol::stack::push(L, ix + 1);
+ }
+
+ static int size(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ return sol::stack::push(L, self.items().size());
+ }
+
+ static int empty(lua_State *L)
+ {
+ T &self(immutable_sequence_helper::get_self(L));
+ return sol::stack::push(L, self.items().empty());
+ }
+
+ static int next(lua_State *L) { return sol::stack::push(L, next_pairs<false>); }
+ static int pairs(lua_State *L) { return start_pairs<false>(L); }
+ static int ipairs(lua_State *L) { return start_pairs<true>(L); }
+};
+
+
+
struct lua_engine::addr_space
{
addr_space(address_space &s, device_memory_interface &d) : space(s), dev(d) { }
diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp
index ca472dba675..b910a717561 100644
--- a/src/frontend/mame/luaengine_render.cpp
+++ b/src/frontend/mame/luaengine_render.cpp
@@ -21,6 +21,10 @@ namespace {
struct layout_file_views
{
layout_file_views(layout_file &f) : file(f) { }
+ layout_file::view_list &items() { return file.views(); }
+
+ static layout_view &unwrap(layout_file::view_list::iterator const &it) { return *it; }
+ static int push_key(lua_State *L, layout_file::view_list::iterator const &it, std::size_t ix) { return sol::stack::push_reference(L, it->unqualified_name()); }
layout_file &file;
};
@@ -29,6 +33,10 @@ struct layout_file_views
struct layout_view_items
{
layout_view_items(layout_view &v) : view(v) { }
+ layout_view::item_list &items() { return view.items(); }
+
+ static layout_view::item &unwrap(layout_view::item_list::iterator const &it) { return *it; }
+ static int push_key(lua_State *L, layout_view::item_list::iterator const &it, std::size_t ix) { return sol::stack::push(L, ix + 1); }
layout_view &view;
};
@@ -53,48 +61,9 @@ template <> struct is_container<render_target_view_names> : std::true_type { };
template <>
-struct usertype_container<layout_file_views> : lua_engine::immutable_collection_helper<layout_file_views, layout_file::view_list>
+struct usertype_container<layout_file_views> : lua_engine::immutable_sequence_helper<layout_file_views, layout_file::view_list>
{
-private:
- using view_list = layout_file::view_list;
-
- template <bool Indexed>
- static int next_pairs(lua_State *L)
- {
- indexed_iterator &i(stack::unqualified_get<user<indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- if constexpr (Indexed)
- result = stack::push(L, i.ix + 1);
- else
- result = stack::push_reference(L, i.it->unqualified_name());
- result += stack::push_reference(L, *i.it);
- ++i;
- return result;
- }
-
- template <bool Indexed>
- static int start_pairs(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- stack::push(L, next_pairs<Indexed>);
- stack::push<user<indexed_iterator> >(L, self.file.views(), self.file.views().begin());
- stack::push(L, lua_nil);
- return 3;
- }
-
public:
- static int at(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.file.views().size() < index))
- return stack::push(L, lua_nil);
- else
- return stack::push_reference(L, *std::next(self.file.views().begin(), index - 1));
- }
-
static int get(lua_State *L)
{
layout_file_views &self(get_self(L));
@@ -113,72 +82,13 @@ public:
{
return get(L);
}
-
- static int index_of(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- layout_view &view(stack::unqualified_get<layout_view>(L, 2));
- auto it(self.file.views().begin());
- std::ptrdiff_t ix(0);
- while ((self.file.views().end() != it) && (&view != &*it))
- {
- ++it;
- ++ix;
- }
- if (self.file.views().end() == it)
- return stack::push(L, lua_nil);
- else
- return stack::push(L, ix + 1);
- }
-
- static int size(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- return stack::push(L, self.file.views().size());
- }
-
- static int empty(lua_State *L)
- {
- layout_file_views &self(get_self(L));
- return stack::push(L, self.file.views().empty());
- }
-
- static int next(lua_State *L) { return stack::push(L, next_pairs<false>); }
- static int pairs(lua_State *L) { return start_pairs<false>(L); }
- static int ipairs(lua_State *L) { return start_pairs<true>(L); }
};
template <>
-struct usertype_container<layout_view_items> : lua_engine::immutable_collection_helper<layout_view_items, layout_view::item_list>
+struct usertype_container<layout_view_items> : lua_engine::immutable_sequence_helper<layout_view_items, layout_view::item_list>
{
-private:
- using item_list = layout_view::item_list;
-
- static int next_pairs(lua_State *L)
- {
- indexed_iterator &i(stack::unqualified_get<user<indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- result = stack::push(L, i.ix + 1);
- result += stack::push_reference(L, *i.it);
- ++i.it;
- ++i.ix;
- return result;
- }
-
public:
- static int at(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.view.items().size() < index))
- return stack::push(L, lua_nil);
- else
- return stack::push_reference(L, *std::next(self.view.items().begin(), index - 1));
- }
-
static int get(lua_State *L)
{
layout_view_items &self(get_self(L));
@@ -195,50 +105,10 @@ public:
return get(L);
}
- static int index_of(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- layout_view::item &item(stack::unqualified_get<layout_view::item>(L, 2));
- auto it(self.view.items().begin());
- std::ptrdiff_t ix(0);
- while ((self.view.items().end() != it) && (&item != &*it))
- {
- ++it;
- ++ix;
- }
- if (self.view.items().end() == it)
- return stack::push(L, lua_nil);
- else
- return stack::push(L, ix + 1);
- }
-
- static int size(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- return stack::push(L, self.view.items().size());
- }
-
- static int empty(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- return stack::push(L, self.view.items().empty());
- }
-
- static int next(lua_State *L) { return stack::push(L, next_pairs); }
-
static int pairs(lua_State *L)
{
return luaL_error(L, "sol: cannot call 'pairs' on type '%s': not iterable by ID", sol::detail::demangle<layout_view_items>().c_str());
}
-
- static int ipairs(lua_State *L)
- {
- layout_view_items &self(get_self(L));
- stack::push(L, next_pairs);
- stack::push<user<indexed_iterator> >(L, self.view.items(), self.view.items().begin());
- stack::push(L, lua_nil);
- return 3;
- }
};
diff --git a/src/frontend/mame/ui/barcode.cpp b/src/frontend/mame/ui/barcode.cpp
index fad2af9ffc6..846f2cc97c5 100644
--- a/src/frontend/mame/ui/barcode.cpp
+++ b/src/frontend/mame/ui/barcode.cpp
@@ -74,8 +74,8 @@ void menu_barcode_reader::populate(float &customtop, float &custombottom)
item_append(_("New Barcode:"), new_barcode, 0, ITEMREF_NEW_BARCODE);
// finish up the menu
- item_append(menu_item_type::SEPARATOR);
item_append(_("Enter Code"), 0, ITEMREF_ENTER_BARCODE);
+ item_append(menu_item_type::SEPARATOR);
customtop = ui().get_line_height() + 3.0f * ui().box_tb_border();
}
@@ -88,9 +88,6 @@ void menu_barcode_reader::populate(float &customtop, float &custombottom)
void menu_barcode_reader::handle()
{
- // rebuild the menu (so to update the selected device, if the user has pressed L or R)
- repopulate(reset_options::REMEMBER_POSITION);
-
// process the menu
const event *event = process(PROCESS_LR_REPEAT);
@@ -127,6 +124,14 @@ void menu_barcode_reader::handle()
}
break;
+ case IPT_UI_CLEAR:
+ if (get_selection_ref() == ITEMREF_NEW_BARCODE)
+ {
+ m_barcode_buffer.clear();
+ reset(reset_options::REMEMBER_POSITION);
+ }
+ break;
+
case IPT_SPECIAL:
if (get_selection_ref() == ITEMREF_NEW_BARCODE)
{
@@ -134,11 +139,6 @@ void menu_barcode_reader::handle()
reset(reset_options::REMEMBER_POSITION);
}
break;
-
- case IPT_UI_CANCEL:
- // reset the char buffer also in this case
- m_barcode_buffer.clear();
- break;
}
}
}
diff --git a/src/frontend/mame/ui/devctrl.h b/src/frontend/mame/ui/devctrl.h
index 1be2385a66f..ec9dc0d2928 100644
--- a/src/frontend/mame/ui/devctrl.h
+++ b/src/frontend/mame/ui/devctrl.h
@@ -84,8 +84,8 @@ int menu_device_control<DeviceType>::current_index()
template<class DeviceType>
void menu_device_control<DeviceType>::previous()
{
- // left arrow - rotate left through cassette devices
- if (m_device != nullptr)
+ // left arrow - rotate left through devices
+ if (m_device && (1 < m_count))
{
enumerator iter(machine().root_device());
int index = iter.indexof(*m_device);
@@ -94,6 +94,7 @@ void menu_device_control<DeviceType>::previous()
else
index = m_count - 1;
m_device = iter.byindex(index);
+ reset(reset_options::REMEMBER_POSITION);
}
}
@@ -106,7 +107,7 @@ template<class DeviceType>
void menu_device_control<DeviceType>::next()
{
// right arrow - rotate right through cassette devices
- if (m_device != nullptr)
+ if (m_device && (1 < m_count))
{
enumerator iter(machine().root_device());
int index = iter.indexof(*m_device);
@@ -115,6 +116,7 @@ void menu_device_control<DeviceType>::next()
else
index = 0;
m_device = iter.byindex(index);
+ reset(reset_options::REMEMBER_POSITION);
}
}
@@ -129,7 +131,7 @@ std::string menu_device_control<DeviceType>::current_display_name()
std::string display_name;
display_name.assign(current_device()->name());
if (count() > 1)
- display_name.append(string_format("%d", current_index() + 1));
+ display_name.append(string_format(" %d", current_index() + 1));
return display_name;
}
diff --git a/src/frontend/mame/ui/devopt.cpp b/src/frontend/mame/ui/devopt.cpp
index e423bfd4370..f5e73f290e0 100644
--- a/src/frontend/mame/ui/devopt.cpp
+++ b/src/frontend/mame/ui/devopt.cpp
@@ -9,12 +9,14 @@
*********************************************************************/
#include "emu.h"
-#include "ui/ui.h"
#include "ui/devopt.h"
+
+#include "ui/ui.h"
#include "romload.h"
namespace ui {
+
/*-------------------------------------------------
device_config - handle the game information
menu
diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp
index 7d11970966f..3a57aac42c0 100644
--- a/src/frontend/mame/ui/info.cpp
+++ b/src/frontend/mame/ui/info.cpp
@@ -567,28 +567,30 @@ void menu_image_info::image_info(device_image_interface *image)
// if image has been loaded through softlist, let's add some more info
if (image->loaded_through_softlist())
{
- // display long filename
- item_append(image->longname(), FLAG_DISABLE, nullptr);
+ software_info const &swinfo(*image->software_entry());
- // display manufacturer and year
- item_append(string_format("%s, %s", image->manufacturer(), image->year()), FLAG_DISABLE, nullptr);
+ // display full name, publisher and year
+ item_append(swinfo.longname(), FLAG_DISABLE, nullptr);
+ item_append(string_format("%1$s, %2$s", swinfo.publisher(), swinfo.year()), FLAG_DISABLE, nullptr);
// display supported information, if available
- switch (image->supported())
+ switch (swinfo.supported())
{
- case SOFTWARE_SUPPORTED_NO:
- item_append(_("Not supported"), FLAG_DISABLE, nullptr);
- break;
- case SOFTWARE_SUPPORTED_PARTIAL:
- item_append(_("Partially supported"), FLAG_DISABLE, nullptr);
- break;
- default:
- break;
+ case SOFTWARE_SUPPORTED_NO:
+ item_append(_("Not supported"), FLAG_DISABLE, nullptr);
+ break;
+ case SOFTWARE_SUPPORTED_PARTIAL:
+ item_append(_("Partially supported"), FLAG_DISABLE, nullptr);
+ break;
+ default:
+ break;
}
}
}
else
+ {
item_append(image->brief_instance_name(), _("[empty]"), 0, nullptr);
+ }
item_append(std::string(), FLAG_DISABLE, nullptr);
}
diff --git a/src/frontend/mame/ui/inifile.cpp b/src/frontend/mame/ui/inifile.cpp
index 253c52c07f3..77dfd1088dc 100644
--- a/src/frontend/mame/ui/inifile.cpp
+++ b/src/frontend/mame/ui/inifile.cpp
@@ -298,11 +298,11 @@ void favorite_manager::add_favorite(running_machine &machine)
// start with simple stuff that can just be copied
info.shortname = software->shortname();
- info.longname = imagedev->longname();
+ info.longname = software->longname();
info.parentname = software->parentname();
- info.year = imagedev->year();
- info.publisher = imagedev->manufacturer();
- info.supported = imagedev->supported();
+ info.year = software->year();
+ info.publisher = software->publisher();
+ info.supported = software->supported();
info.part = part->name();
info.driver = &driver;
info.listname = imagedev->software_list_name();
diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp
index 23a68c979c5..1051b322d99 100644
--- a/src/frontend/mame/ui/mainmenu.cpp
+++ b/src/frontend/mame/ui/mainmenu.cpp
@@ -114,7 +114,7 @@ void menu_main::populate(float &customtop, float &custombottom)
item_append(_("Slider Controls"), 0, (void *)SLIDERS);
- item_append(_("Video Options"), 0, (machine().render().target_by_index(1) != nullptr) ? (void *)VIDEO_TARGETS : (void *)VIDEO_OPTIONS);
+ item_append(_("Video Options"), 0, (machine().render().target_by_index(1) || machine().video().snapshot_target().view_name(1)) ? (void *)VIDEO_TARGETS : (void *)VIDEO_OPTIONS);
if (machine().crosshair().get_usage())
item_append(_("Crosshair Options"), 0, (void *)CROSSHAIR);
@@ -229,7 +229,7 @@ void menu_main::handle()
break;
case VIDEO_OPTIONS:
- menu::stack_push<menu_video_options>(ui(), container(), *machine().render().first_target());
+ menu::stack_push<menu_video_options>(ui(), container(), *machine().render().first_target(), false);
break;
case CROSSHAIR:
diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp
index 068780f2b6e..4fb9616c355 100644
--- a/src/frontend/mame/ui/menu.cpp
+++ b/src/frontend/mame/ui/menu.cpp
@@ -136,7 +136,6 @@ void menu::global_state::stack_push(std::unique_ptr<menu> &&menu)
{
menu->m_parent = std::move(m_stack);
m_stack = std::move(menu);
- m_stack->reset(reset_options::SELECT_FIRST);
m_stack->machine().ui_input().reset();
}
@@ -289,26 +288,6 @@ void menu::reset(reset_options options)
m_items.clear();
m_visible_items = 0;
m_selected = 0;
-
- // add an item to return
- if (!m_parent)
- {
- item_append(_("Return to Machine"), 0, nullptr);
- }
- else if (m_parent->is_special_main_menu())
- {
- if (machine().options().ui() == emu_options::UI_SIMPLE)
- item_append(_("Exit"), 0, nullptr);
- else
- item_append(_("Exit"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
- }
- else
- {
- if (machine().options().ui() != emu_options::UI_SIMPLE && stack_has_special_main_menu())
- item_append(_("Return to Previous Menu"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
- else
- item_append(_("Return to Previous Menu"), 0, nullptr);
- }
}
@@ -403,17 +382,6 @@ void menu::item_append_on_off(const std::string &text, bool state, uint32_t flag
//-------------------------------------------------
-// repopulate - repopulate menu items
-//-------------------------------------------------
-
-void menu::repopulate(reset_options options)
-{
- reset(options);
- populate(m_customtop, m_custombottom);
-}
-
-
-//-------------------------------------------------
// process - process a menu, drawing it
// and returning any interesting events
//-------------------------------------------------
@@ -1201,8 +1169,31 @@ void menu::validate_selection(int scandir)
void menu::do_handle()
{
- if (m_items.size() < 2)
+ if (m_items.empty())
+ {
+ // add an item to return - this is a really hacky way of doing this
+ if (!m_parent)
+ {
+ item_append(_("Return to Machine"), 0, nullptr);
+ }
+ else if (m_parent->is_special_main_menu())
+ {
+ if (machine().options().ui() == emu_options::UI_SIMPLE)
+ item_append(_("Exit"), 0, nullptr);
+ else
+ item_append(_("Exit"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
+ }
+ else
+ {
+ if (machine().options().ui() != emu_options::UI_SIMPLE && stack_has_special_main_menu())
+ item_append(_("Return to Previous Menu"), FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, nullptr);
+ else
+ item_append(_("Return to Previous Menu"), 0, nullptr);
+ }
+
+ // let implementation add other items
populate(m_customtop, m_custombottom);
+ }
handle();
}
diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h
index eacbae32609..8cd0057fc58 100644
--- a/src/frontend/mame/ui/menu.h
+++ b/src/frontend/mame/ui/menu.h
@@ -182,9 +182,6 @@ protected:
void add_cleanup_callback(cleanup_callback &&callback) { m_global_state->add_cleanup_callback(std::move(callback)); }
- // repopulate the menu items
- void repopulate(reset_options options);
-
// process a menu, drawing it and returning any interesting events
const event *process(uint32_t flags, float x0 = 0.0f, float y0 = 0.0f);
void process_parent() { m_parent->process(PROCESS_NOINPUT); }
diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp
index 5de57de2ea6..dc5cc2ba9a3 100644
--- a/src/frontend/mame/ui/miscmenu.cpp
+++ b/src/frontend/mame/ui/miscmenu.cpp
@@ -176,33 +176,23 @@ void menu_network_devices::handle()
information menu
-------------------------------------------------*/
-void menu_bookkeeping::handle()
+menu_bookkeeping::menu_bookkeeping(mame_ui_manager &mui, render_container &container) : menu(mui, container)
{
- attotime curtime;
-
- /* if the time has rolled over another second, regenerate */
- curtime = machine().time();
- if (prevtime.seconds() != curtime.seconds())
- {
- prevtime = curtime;
- repopulate(reset_options::SELECT_FIRST);
- }
-
- /* process the menu */
- process(0);
}
-
-/*-------------------------------------------------
- menu_bookkeeping - handle the bookkeeping
- information menu
--------------------------------------------------*/
-menu_bookkeeping::menu_bookkeeping(mame_ui_manager &mui, render_container &container) : menu(mui, container)
+menu_bookkeeping::~menu_bookkeeping()
{
}
-menu_bookkeeping::~menu_bookkeeping()
+void menu_bookkeeping::handle()
{
+ /* process the menu */
+ process(0);
+
+ /* if the time has rolled over another second, regenerate */
+ attotime const curtime = machine().time();
+ if (prevtime.seconds() != curtime.seconds())
+ reset(reset_options::REMEMBER_POSITION);
}
void menu_bookkeeping::populate(float &customtop, float &custombottom)
@@ -212,6 +202,7 @@ void menu_bookkeeping::populate(float &customtop, float &custombottom)
int ctrnum;
/* show total time first */
+ prevtime = machine().time();
if (prevtime.seconds() >= (60 * 60))
util::stream_format(tempstring, _("Uptime: %1$d:%2$02d:%3$02d\n\n"), prevtime.seconds() / (60 * 60), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60);
else
diff --git a/src/frontend/mame/ui/tapectrl.cpp b/src/frontend/mame/ui/tapectrl.cpp
index 75d62038931..720622f0e81 100644
--- a/src/frontend/mame/ui/tapectrl.cpp
+++ b/src/frontend/mame/ui/tapectrl.cpp
@@ -116,14 +116,11 @@ void menu_tape_control::populate(float &customtop, float &custombottom)
void menu_tape_control::handle()
{
- // rebuild the menu (so to update the selected device, if the user has pressed L or R, and the tape counter)
- repopulate(reset_options::REMEMBER_POSITION);
-
// process the menu
const event *event = process(PROCESS_LR_REPEAT);
if (event != nullptr)
{
- switch(event->iptkey)
+ switch (event->iptkey)
{
case IPT_UI_LEFT:
if (event->itemref == TAPECMD_SLIDER)
@@ -155,6 +152,9 @@ void menu_tape_control::handle()
break;
}
}
+
+ // hacky way to update the tape counter by repopulating every frame
+ reset(reset_options::REMEMBER_POSITION);
}
diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp
index ccb39306208..21ba181ecb7 100644
--- a/src/frontend/mame/ui/videoopt.cpp
+++ b/src/frontend/mame/ui/videoopt.cpp
@@ -55,6 +55,10 @@ void menu_video_targets::populate(float &customtop, float &custombottom)
// add a menu item
item_append(util::string_format(_("Screen #%d"), targetnum), 0, target);
}
+
+ // add option for snapshot target if it has multiple views
+ if (machine().video().snapshot_target().view_name(1))
+ item_append("Snapshot", 0, &machine().video().snapshot_target());
}
/*-------------------------------------------------
@@ -66,7 +70,15 @@ void menu_video_targets::handle()
{
event const *const menu_event = process(0);
if (menu_event && (menu_event->iptkey == IPT_UI_SELECT))
- menu::stack_push<menu_video_options>(ui(), container(), *reinterpret_cast<render_target *>(menu_event->itemref));
+ {
+ render_target *const target = reinterpret_cast<render_target *>(menu_event->itemref);
+ menu::stack_push<menu_video_options>(
+ ui(),
+ container(),
+ std::string(selected_item().text),
+ *target,
+ &machine().video().snapshot_target() == target);
+ }
}
@@ -75,10 +87,35 @@ void menu_video_targets::handle()
video options menu
-------------------------------------------------*/
-menu_video_options::menu_video_options(mame_ui_manager &mui, render_container &container, render_target &target)
+menu_video_options::menu_video_options(
+ mame_ui_manager &mui,
+ render_container &container,
+ render_target &target,
+ bool snapshot)
: menu(mui, container)
, m_target(target)
+ , m_title()
+ , m_show_title(false)
+ , m_snapshot(snapshot)
{
+ set_selected_index(target.view());
+ reset(reset_options::REMEMBER_POSITION);
+}
+
+menu_video_options::menu_video_options(
+ mame_ui_manager &mui,
+ render_container &container,
+ std::string &&title,
+ render_target &target,
+ bool snapshot)
+ : menu(mui, container)
+ , m_target(target)
+ , m_title(std::move(title))
+ , m_show_title(true)
+ , m_snapshot(snapshot)
+{
+ set_selected_index(target.view() + 2);
+ reset(reset_options::REMEMBER_POSITION);
}
menu_video_options::~menu_video_options()
@@ -89,6 +126,13 @@ void menu_video_options::populate(float &customtop, float &custombottom)
{
uintptr_t ref;
+ // add title if requested
+ if (m_show_title)
+ {
+ item_append(m_title, FLAG_DISABLE, nullptr);
+ item_append(menu_item_type::SEPARATOR);
+ }
+
// add items for each view
for (char const *name = m_target.view_name(ref = 0); name; name = m_target.view_name(++ref))
item_append(name, 0, reinterpret_cast<void *>(ITEM_VIEW_FIRST + ref));
@@ -127,33 +171,36 @@ void menu_video_options::populate(float &customtop, float &custombottom)
// cropping
item_append_on_off(_("Zoom to Screen Area"), m_target.zoom_to_screen(), 0, reinterpret_cast<void *>(ITEM_ZOOM));
- // uneven stretch
- switch (m_target.scale_mode())
+ if (!m_snapshot)
{
- case SCALE_FRACTIONAL:
- subtext = _("On");
- break;
+ // uneven stretch
+ switch (m_target.scale_mode())
+ {
+ case SCALE_FRACTIONAL:
+ subtext = _("On");
+ break;
+
+ case SCALE_FRACTIONAL_X:
+ subtext = _("X Only");
+ break;
- case SCALE_FRACTIONAL_X:
- subtext = _("X Only");
- break;
+ case SCALE_FRACTIONAL_Y:
+ subtext = _("Y Only");
+ break;
- case SCALE_FRACTIONAL_Y:
- subtext = _("Y Only");
- break;
+ case SCALE_FRACTIONAL_AUTO:
+ subtext = _("X or Y (Auto)");
+ break;
- case SCALE_FRACTIONAL_AUTO:
- subtext = _("X or Y (Auto)");
- break;
+ case SCALE_INTEGER:
+ subtext = _("Off");
+ break;
+ }
+ item_append(_("Non-Integer Scaling"), subtext, FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, reinterpret_cast<void *>(ITEM_UNEVENSTRETCH));
- case SCALE_INTEGER:
- subtext = _("Off");
- break;
+ // keep aspect
+ item_append_on_off(_("Maintain Aspect Ratio"), m_target.keepaspect(), 0, reinterpret_cast<void *>(ITEM_KEEPASPECT));
}
- item_append(_("Non-Integer Scaling"), subtext, FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, reinterpret_cast<void *>(ITEM_UNEVENSTRETCH));
-
- // keep aspect
- item_append_on_off(_("Keep Aspect"), m_target.keepaspect(), 0, reinterpret_cast<void *>(ITEM_KEEPASPECT));
}
@@ -164,6 +211,8 @@ void menu_video_options::populate(float &customtop, float &custombottom)
void menu_video_options::handle()
{
+ auto const lockout_popup([this] () { machine().popmessage(_("Cannot change options while recording!")); });
+ bool const snap_lockout(m_snapshot && machine().video().is_recording());
bool changed(false);
// process the menu
@@ -176,6 +225,8 @@ void menu_video_options::handle()
case ITEM_ROTATE:
if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT)
{
+ if (snap_lockout)
+ return lockout_popup();
int const delta((menu_event->iptkey == IPT_UI_LEFT) ? ROT270 : ROT90);
m_target.set_orientation(orientation_add(delta, m_target.orientation()));
if (m_target.is_ui_target())
@@ -192,6 +243,8 @@ void menu_video_options::handle()
case ITEM_ZOOM:
if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT))
{
+ if (snap_lockout)
+ return lockout_popup();
m_target.set_zoom_to_screen(menu_event->iptkey == IPT_UI_RIGHT);
changed = true;
}
@@ -201,6 +254,8 @@ void menu_video_options::handle()
case ITEM_UNEVENSTRETCH:
if (menu_event->iptkey == IPT_UI_LEFT)
{
+ if (snap_lockout)
+ return lockout_popup();
switch (m_target.scale_mode())
{
case SCALE_FRACTIONAL:
@@ -227,6 +282,8 @@ void menu_video_options::handle()
}
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
+ if (snap_lockout)
+ return lockout_popup();
switch (m_target.scale_mode())
{
case SCALE_FRACTIONAL:
@@ -257,6 +314,8 @@ void menu_video_options::handle()
case ITEM_KEEPASPECT:
if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT))
{
+ if (snap_lockout)
+ return lockout_popup();
m_target.set_keepaspect(menu_event->iptkey == IPT_UI_RIGHT);
changed = true;
}
@@ -266,6 +325,8 @@ void menu_video_options::handle()
default:
if (reinterpret_cast<uintptr_t>(menu_event->itemref) >= ITEM_VIEW_FIRST)
{
+ if (snap_lockout)
+ return lockout_popup();
if (menu_event->iptkey == IPT_UI_SELECT)
{
m_target.set_view(reinterpret_cast<uintptr_t>(menu_event->itemref) - ITEM_VIEW_FIRST);
@@ -274,6 +335,8 @@ void menu_video_options::handle()
}
else if (reinterpret_cast<uintptr_t>(menu_event->itemref) >= ITEM_TOGGLE_FIRST)
{
+ if (snap_lockout)
+ return lockout_popup();
if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT))
{
m_target.set_visibility_toggle(reinterpret_cast<uintptr_t>(menu_event->itemref) - ITEM_TOGGLE_FIRST, menu_event->iptkey == IPT_UI_RIGHT);
@@ -284,7 +347,7 @@ void menu_video_options::handle()
}
}
- /* if something changed, rebuild the menu */
+ // if something changed, rebuild the menu
if (changed)
reset(reset_options::REMEMBER_REF);
}
diff --git a/src/frontend/mame/ui/videoopt.h b/src/frontend/mame/ui/videoopt.h
index a70e7b8aa94..44a172cf8f5 100644
--- a/src/frontend/mame/ui/videoopt.h
+++ b/src/frontend/mame/ui/videoopt.h
@@ -32,7 +32,8 @@ private:
class menu_video_options : public menu
{
public:
- menu_video_options(mame_ui_manager &mui, render_container &container, render_target &target);
+ menu_video_options(mame_ui_manager &mui, render_container &container, render_target &target, bool snapshot);
+ menu_video_options(mame_ui_manager &mui, render_container &container, std::string &&title, render_target &target, bool snapshot);
virtual ~menu_video_options() override;
private:
@@ -40,6 +41,9 @@ private:
virtual void handle() override;
render_target &m_target;
+ std::string const m_title;
+ bool const m_show_title;
+ bool const m_snapshot;
};
} // namespace ui
diff --git a/src/lib/util/strformat.h b/src/lib/util/strformat.h
index 2ed90669284..0ce57606436 100644
--- a/src/lib/util/strformat.h
+++ b/src/lib/util/strformat.h
@@ -106,11 +106,12 @@
The format string type can be a pointer to a NUL-terminated string,
an array containing a NUL-terminated or non-terminated string, or a
STL contiguous container holding a string (e.g. std::string,
- std::vector or std::array). Note that NUL characters characters are
- only treated as terminators for pointers and arrays, they are
- treated as normal characters for other containers. A non-contiguous
- container (e.g. std::list or std::deque) will result in undesirable
- behaviour likely culminating in a crash.
+ std::string_view, std::vector or std::array). Note that NUL
+ characters characters are only treated as terminators for pointers
+ and arrays, they are treated as normal characters for other
+ containers. Using a non-contiguous container (e.g. std::list or
+ std::deque) will result in undesirable behaviour likely culminating
+ in a crash.
The value type of the format string and the character type of the
output stream/string need to match. You can't use a wchar_t format
@@ -184,6 +185,7 @@
#include <locale>
#include <sstream>
#include <string>
+#include <string_view>
#include <type_traits>
#include <utility>
@@ -576,10 +578,16 @@ template <typename Stream, typename T>
class format_output
{
private:
+ template <typename U> struct string_semantics
+ { static constexpr bool value = false; };
+ template <typename CharT, typename Traits, typename Allocator> struct string_semantics<std::basic_string<CharT, Traits, Allocator> >
+ { static constexpr bool value = true; };
+ template <typename CharT, typename Traits> struct string_semantics<std::basic_string_view<CharT, Traits> >
+ { static constexpr bool value = true; };
template <typename U> struct signed_integer_semantics
- { static constexpr bool value = std::is_integral<U>::value && std::is_signed<U>::value; };
+ { static constexpr bool value = std::is_integral_v<U>&& std::is_signed_v<U>; };
template <typename U> struct unsigned_integer_semantics
- { static constexpr bool value = std::is_integral<U>::value && !std::is_signed<U>::value; };
+ { static constexpr bool value = std::is_integral_v<U>&& !std::is_signed_v<U>; };
static void apply_signed(Stream &str, char16_t const &value)
{
@@ -590,19 +598,14 @@ private:
str << std::make_signed_t<std::uint_least32_t>(std::uint_least32_t(value));
}
template <typename U>
- static std::enable_if_t<std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value> apply_signed(Stream &str, U const &value)
- {
- str << int(std::make_signed_t<U>(value));
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value && signed_integer_semantics<U>::value> apply_signed(Stream &str, U const &value)
- {
- str << value;
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_signed_t<U>, std::make_signed_t<char> >::value && unsigned_integer_semantics<U>::value> apply_signed(Stream &str, U const &value)
+ static std::enable_if_t<std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> > || std::is_integral_v<U> > apply_signed(Stream &str, U const &value)
{
- str << std::make_signed_t<U>(value);
+ if constexpr (std::is_same_v<std::make_signed_t<U>, std::make_signed_t<char> >)
+ str << int(std::make_signed_t<U>(value));
+ else if constexpr (std::is_signed_v<U>)
+ str << value;
+ else
+ str << std::make_signed_t<U>(value);
}
static void apply_unsigned(Stream &str, char16_t const &value)
@@ -614,26 +617,49 @@ private:
str << std::uint_least32_t(value);
}
template <typename U>
- static std::enable_if_t<std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value> apply_unsigned(Stream &str, U const &value)
- {
- str << unsigned(std::make_unsigned_t<U>(value));
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value && signed_integer_semantics<U>::value> apply_unsigned(Stream &str, U const &value)
+ static std::enable_if_t<std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> > || std::is_integral_v<U> > apply_unsigned(Stream &str, U const &value)
{
- str << std::make_unsigned_t<U>(value);
- }
- template <typename U>
- static std::enable_if_t<!std::is_same<std::make_unsigned_t<U>, std::make_unsigned_t<char> >::value && unsigned_integer_semantics<U>::value> apply_unsigned(Stream &str, U const &value)
- {
- str << value;
+ if constexpr (std::is_same_v<std::make_unsigned_t<U>, std::make_unsigned_t<char> >)
+ str << unsigned(std::make_unsigned_t<U>(value));
+ else if constexpr (std::is_signed_v<U>)
+ str << std::make_unsigned_t<U>(value);
+ else
+ str << value;
}
public:
template <typename U>
static void apply(Stream &str, format_flags const &flags, U const &value)
{
- if constexpr (signed_integer_semantics<U>::value)
+ if constexpr (string_semantics<U>::value)
+ {
+ int const precision(flags.get_precision());
+ if ((0 <= precision) && (value.size() > unsigned(precision)))
+ {
+ if constexpr (std::is_same_v<typename U::value_type, typename Stream::char_type>)
+ {
+ unsigned width(flags.get_field_width());
+ bool const pad(unsigned(precision) < width);
+ typename Stream::fmtflags const adjust(str.flags() & Stream::adjustfield);
+ if (!pad || (Stream::left == adjust)) str.write(&*value.begin(), unsigned(precision));
+ if (pad)
+ {
+ for (width -= precision; 0U < width; --width) str.put(str.fill());
+ if (Stream::left != adjust) str.write(&*value.begin(), unsigned(precision));
+ }
+ str.width(0);
+ }
+ else
+ {
+ str << value.substr(0, unsigned(precision));
+ }
+ }
+ else
+ {
+ str << value;
+ }
+ }
+ else if constexpr (signed_integer_semantics<U>::value)
{
switch (flags.get_conversion())
{
@@ -833,35 +859,6 @@ public:
str << value;
}
}
- template <typename CharT, typename Traits, typename Allocator>
- static void apply(Stream &str, format_flags const &flags, std::basic_string<CharT, Traits, Allocator> const &value)
- {
- int const precision(flags.get_precision());
- if ((0 <= precision) && (value.size() > unsigned(precision)))
- {
- if constexpr (std::is_same_v<CharT, typename Stream::char_type>)
- {
- unsigned width(flags.get_field_width());
- bool const pad(unsigned(precision) < width);
- typename Stream::fmtflags const adjust(str.flags() & Stream::adjustfield);
- if (!pad || (Stream::left == adjust)) str.write(&*value.begin(), unsigned(precision));
- if (pad)
- {
- for (width -= precision; 0U < width; --width) str.put(str.fill());
- if (Stream::left != adjust) str.write(&*value.begin(), unsigned(precision));
- }
- str.width(0);
- }
- else
- {
- str << value.substr(0, unsigned(precision));
- }
- }
- else
- {
- str << value;
- }
- }
};
template <typename Stream, typename T>
diff --git a/src/mame/drivers/goldnpkr.cpp b/src/mame/drivers/goldnpkr.cpp
index e331c4e5630..76455b87f7e 100644
--- a/src/mame/drivers/goldnpkr.cpp
+++ b/src/mame/drivers/goldnpkr.cpp
@@ -2406,8 +2406,8 @@ SW4 OFF ON OFF ON
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "1 Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, "Frequency" ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, "50 Hz." )
PORT_DIPSETTING( 0x00, "60 Hz." )
@@ -2645,6 +2645,16 @@ static INPUT_PORTS_START( witchjol )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("IN0-1-8")
PORT_MODIFY("IN0-2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / Take") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_NAME("Hold 2 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_NAME("Hold 3 / Bet") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_NAME("Hold 4 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5 / Double Up") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("IN0-2-6")
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("IN0-2-7")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("IN0-2-8")
@@ -2712,12 +2722,12 @@ static INPUT_PORTS_START( witchjol )
PORT_DIPNAME( 0x04, 0x04, "Game Type" ) PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING( 0x04, "Jolli Witch" )
PORT_DIPSETTING( 0x00, "Witch Card" )
- PORT_DIPNAME( 0x08, 0x08, "Taster?" ) PORT_DIPLOCATION("SW2:4")
- PORT_DIPSETTING( 0x00, "6 Taster" )
- PORT_DIPSETTING( 0x08, "12 Taster" )
+ PORT_DIPNAME( 0x08, 0x08, "Control Type" ) PORT_DIPLOCATION("SW2:4")
+ PORT_DIPSETTING( 0x00, "6-Button" )
+ PORT_DIPSETTING( 0x08, "12-Button" )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "1 Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x60, 0x20, "Uncommented 1" ) PORT_DIPLOCATION("SW2:6,7")
PORT_DIPSETTING( 0x60, "1 DM - 1 PKT" )
PORT_DIPSETTING( 0x20, "1 DM - 10 PKT" )
@@ -2821,11 +2831,16 @@ static INPUT_PORTS_START( wldwitch )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN0-2")
- PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / Take")
- PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 )
- PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 )
- PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 )
- PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5 / Double-Up")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_CONDITION("SW2", 0x08, EQUALS, 0x08)
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) PORT_NAME("Hold 1 / Take") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) PORT_NAME("Hold 2 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) PORT_NAME("Hold 3 / Bet") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) PORT_NAME("Hold 4 / Small") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) PORT_NAME("Hold 5 / Double Up") PORT_CONDITION("SW2", 0x08, EQUALS, 0x00)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
@@ -2921,11 +2936,11 @@ static INPUT_PORTS_START( wldwitch )
PORT_DIPSETTING( 0x04, "Wild Witch" )
PORT_DIPSETTING( 0x00, "Witch Game" )
PORT_DIPNAME( 0x08, 0x08, "Control Type" ) PORT_DIPLOCATION("SW2:4")
- PORT_DIPSETTING( 0x00, "6 Taster" )
- PORT_DIPSETTING( 0x08, "12 Taster" )
+ PORT_DIPSETTING( 0x00, "6-Button" )
+ PORT_DIPSETTING( 0x08, "12-Button" )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "1 Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, "Uncommented 1" ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, "64er" )
PORT_DIPSETTING( 0x00, "128er" )
@@ -3019,8 +3034,8 @@ static INPUT_PORTS_START( wupndown )
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "Hohes Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
@@ -3211,8 +3226,8 @@ static INPUT_PORTS_START( wtchjack )
PORT_DIPSETTING( 0x08, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x00, "Minimal Hand" ) PORT_DIPLOCATION("SW2:5")
- PORT_DIPSETTING( 0x10, "2 Paar" )
- PORT_DIPSETTING( 0x00, "Hohes Paar" )
+ PORT_DIPSETTING( 0x10, "Two Pairs" )
+ PORT_DIPSETTING( 0x00, "High Pair" )
PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
diff --git a/src/mame/layout/goldnpkr.lay b/src/mame/layout/goldnpkr.lay
index 92d32275393..a5d11cbeb62 100644
--- a/src/mame/layout/goldnpkr.lay
+++ b/src/mame/layout/goldnpkr.lay
@@ -4,106 +4,74 @@ license:CC0
-->
<mamelayout version="2">
<element name="BET" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.0" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.0" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.0" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.0" blue="0.0" /></rect>
<text string="BET">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="DEAL" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.0" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.0" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.0" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.0" blue="0.0" /></rect>
<text string="DEAL">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="HOLD" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.5" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.1" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.5" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.1" blue="0.0" /></rect>
<text string="HOLD">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="D-UP" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="D-UP">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="TAKE" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="TAKE">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="BIG" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="BIG">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="SMALL" defstate="0">
- <rect state="1">
- <color red="1.0" green="1.0" blue="1.0" />
- </rect>
- <rect state="0">
- <color red="0.2" green="0.2" blue="0.2" />
- </rect>
+ <rect state="1"><color red="1.0" green="1.0" blue="1.0" /></rect>
+ <rect state="0"><color red="0.2" green="0.2" blue="0.2" /></rect>
<text string="SMALL">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
<element name="CANCEL" defstate="0">
- <rect state="1">
- <color red="1.0" green="0.0" blue="0.0" />
- </rect>
- <rect state="0">
- <color red="0.3" green="0.0" blue="0.0" />
- </rect>
+ <rect state="1"><color red="1.0" green="0.0" blue="0.0" /></rect>
+ <rect state="0"><color red="0.3" green="0.0" blue="0.0" /></rect>
<text string="CANCEL">
<color red="0.0" green="0.0" blue="0.0" />
- <bounds x="0" y="0.1" width="1" height="0.8" />
+ <bounds x="0.1" y="0.15" width="0.8" height="0.7" />
</text>
</element>
@@ -111,41 +79,43 @@ license:CC0
<screen index="0">
<bounds left="0" top="0" right="4" bottom="3" />
</screen>
- <element name="lamp0" ref="BET" inputtag="IN0-0" inputmask="0x01">
- <bounds x="3.0" y="3.45" width="0.40" height="0.24" />
- </element>
- <element name="lamp1" ref="DEAL" inputtag="IN0-0" inputmask="0x08">
- <bounds x="2.5" y="3.45" width="0.40" height="0.24" />
- </element>
+
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x01">
- <bounds x="0.0" y="3.13" width="0.40" height="0.24" />
- </element>
- <element name="lamp3" ref="D-UP" inputtag="IN0-0" inputmask="0x04">
- <bounds x="1.5" y="3.45" width="0.40" height="0.24" />
- </element>
- <element name="lamp4" ref="BIG" inputtag="IN0-1" inputmask="0x08">
- <bounds x="0.5" y="3.45" width="0.40" height="0.24" />
+ <bounds x="0.25" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x02">
- <bounds x="0.5" y="3.13" width="0.40" height="0.24" />
+ <bounds x="0.85" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x04">
- <bounds x="1.0" y="3.13" width="0.40" height="0.24" />
+ <bounds x="1.45" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x08">
- <bounds x="1.5" y="3.13" width="0.40" height="0.24" />
+ <bounds x="2.05" y="3.13" width="0.50" height="0.24" />
</element>
<element name="lamp2" ref="HOLD" inputtag="IN0-2" inputmask="0x10">
- <bounds x="2.0" y="3.13" width="0.40" height="0.24" />
+ <bounds x="2.65" y="3.13" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp2" ref="CANCEL" inputtag="IN0-0" inputmask="0x10">
+ <bounds x="3.25" y="3.13" width="0.50" height="0.24" />
</element>
+
<element name="lamp3" ref="TAKE" inputtag="IN0-1" inputmask="0x04">
- <bounds x="2.0" y="3.45" width="0.40" height="0.24" />
+ <bounds x="0.25" y="3.45" width="0.50" height="0.24" />
</element>
<element name="lamp4" ref="SMALL" inputtag="IN0-1" inputmask="0x10">
- <bounds x="1.0" y="3.45" width="0.40" height="0.24" />
+ <bounds x="0.85" y="3.45" width="0.50" height="0.24" />
</element>
- <element name="lamp2" ref="CANCEL" inputtag="IN0-0" inputmask="0x10">
- <bounds x="0.0" y="3.45" width="0.40" height="0.24" />
+ <element name="lamp0" ref="BET" inputtag="IN0-0" inputmask="0x01">
+ <bounds x="1.45" y="3.45" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp4" ref="BIG" inputtag="IN0-1" inputmask="0x08">
+ <bounds x="2.05" y="3.45" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp3" ref="D-UP" inputtag="IN0-0" inputmask="0x04">
+ <bounds x="2.65" y="3.45" width="0.50" height="0.24" />
+ </element>
+ <element name="lamp1" ref="DEAL" inputtag="IN0-0" inputmask="0x08">
+ <bounds x="3.25" y="3.45" width="0.50" height="0.24" />
</element>
</view>
</mamelayout>