mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
Lua scripting enhancements:
Added minimal support for manipulating bitmaps and drawing them in render containers. Y'CbCr 4:2:2, RGB and ARGB are supported. Argument order doesn't always match the underlying classes to make the Lua interface more consistent with render bounds and render containers. Added bindings for device_palette_interface. Fixed some errors in the documentation as well as documenting new functionality.
This commit is contained in:
parent
7bd9db575b
commit
53d32b27d1
@ -305,6 +305,9 @@ machine.hard_reset_pending (read-only)
|
|||||||
machine.devices (read-only)
|
machine.devices (read-only)
|
||||||
A :ref:`device enumerator <luareference-dev-enum>` that yields all
|
A :ref:`device enumerator <luareference-dev-enum>` that yields all
|
||||||
:ref:`devices <luareference-dev-device>` in the emulated system.
|
:ref:`devices <luareference-dev-device>` in the emulated system.
|
||||||
|
machine.palettes (read-only)
|
||||||
|
A :ref:`device enumerator <luareference-dev-enum>` that yields all
|
||||||
|
:ref:`palette devices <luareference-dev-dipalette>` in the emulated system.
|
||||||
machine.screens (read-only)
|
machine.screens (read-only)
|
||||||
A :ref:`device enumerator <luareference-dev-enum>` that yields all
|
A :ref:`device enumerator <luareference-dev-enum>` that yields all
|
||||||
:ref:`screen devices <luareference-dev-screen>` in the emulated system.
|
:ref:`screen devices <luareference-dev-screen>` in the emulated system.
|
||||||
@ -725,6 +728,9 @@ Instantiation
|
|||||||
manager.machine.devices
|
manager.machine.devices
|
||||||
Returns a device enumerator that will iterate over
|
Returns a device enumerator that will iterate over
|
||||||
:ref:`devices <luareference-dev-device>` in the system.
|
:ref:`devices <luareference-dev-device>` in the system.
|
||||||
|
manager.machine.palettes
|
||||||
|
Returns a device enumerator that will iterate over
|
||||||
|
:ref:`palette devices <luareference-dev-dipalette>` in the system.
|
||||||
manager.machine.screens
|
manager.machine.screens
|
||||||
Returns a device enumerator that will iterate over
|
Returns a device enumerator that will iterate over
|
||||||
:ref:`screen devices <luareference-dev-screen>` in the system.
|
:ref:`screen devices <luareference-dev-screen>` in the system.
|
||||||
@ -744,6 +750,13 @@ emu.device_enumerator(device, [depth])
|
|||||||
provided, it must be an integer specifying the maximum number of levels to
|
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
|
iterate below the specified device (i.e. 1 will limit iteration to the
|
||||||
device and its immediate children).
|
device and its immediate children).
|
||||||
|
emu.palette_enumerator(device, [depth])
|
||||||
|
Returns a device enumerator that will iterate over
|
||||||
|
:ref:`palette devices <luareference-dev-dipalette>` in the sub-tree starting
|
||||||
|
at the specified device. The specified device will be included if it is a
|
||||||
|
palette 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.screen_enumerator(device, [depth])
|
emu.screen_enumerator(device, [depth])
|
||||||
Returns a device enumerator that will iterate over
|
Returns a device enumerator that will iterate over
|
||||||
:ref:`screen devices <luareference-dev-screen>` in the sub-tree starting at
|
:ref:`screen devices <luareference-dev-screen>` in the sub-tree starting at
|
||||||
@ -849,6 +862,90 @@ device.spaces[] (read-only)
|
|||||||
interface. Note that the names are specific to the device type and have no
|
interface. Note that the names are specific to the device type and have no
|
||||||
special significance.
|
special significance.
|
||||||
|
|
||||||
|
.. _luareference-dev-dipalette:
|
||||||
|
|
||||||
|
Palette device
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Wraps MAME’s ``device_palette_interface`` class, which represents a device that
|
||||||
|
translates pen values to colours.
|
||||||
|
|
||||||
|
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. Channel values
|
||||||
|
are packed into the bytes of 32-bit unsigned integers, in the order alpha, red,
|
||||||
|
green, blue from most-significant to least-significant byte.
|
||||||
|
|
||||||
|
Instantiation
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
manager.machine.palettes[tag]
|
||||||
|
Gets a palette device by tag relative to the root machine device, or ``nil``
|
||||||
|
if no such device exists or it is not a palette device.
|
||||||
|
|
||||||
|
Methods
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
palette:pen(index)
|
||||||
|
Gets the remapped pen number for the specified palette index.
|
||||||
|
palette:pen_color(pen)
|
||||||
|
Gets the colour for the specified pen number.
|
||||||
|
palette:pen_contrast(pen)
|
||||||
|
Gets the contrast value for the specified pen number. The contrast is a
|
||||||
|
floating-point number.
|
||||||
|
palette:pen_indirect(index)
|
||||||
|
Gets the indirect pen index for the specified palette index.
|
||||||
|
palette:indirect_color(index)
|
||||||
|
Gets the indirect pen colour for the specified palette index.
|
||||||
|
palette:set_pen_color(pen, color)
|
||||||
|
Sets the colour for the specified pen number. The colour may be specified
|
||||||
|
as a single packed 32-bit value; or as individual red, green and blue
|
||||||
|
channel values, in that order.
|
||||||
|
palette:set_pen_red_level(pen, level)
|
||||||
|
Sets the red channel value of the colour for the specified pen number.
|
||||||
|
Other channel values are not affected.
|
||||||
|
palette:set_pen_green_level(pen, level)
|
||||||
|
Sets the green channel value of the colour for the specified pen number.
|
||||||
|
Other channel values are not affected.
|
||||||
|
palette:set_pen_blue_level(pen, level)
|
||||||
|
Sets the blue channel value of the colour for the specified pen number.
|
||||||
|
Other channel values are not affected.
|
||||||
|
palette:set_pen_contrast(pen, factor)
|
||||||
|
Sets the contrast value for the specified pen number. The value must be a
|
||||||
|
floating-point number.
|
||||||
|
palette:set_pen_indirect(pen, index)
|
||||||
|
Sets the indirect pen index for the specified pen number.
|
||||||
|
palette:set_indirect_color(index, color)
|
||||||
|
Sets the indirect pen colour for the specified palette index. The colour
|
||||||
|
may be specified as a single packed 32-bit value; or as individual red,
|
||||||
|
green and blue channel values, in that order.
|
||||||
|
palette:set_shadow_factor(factor)
|
||||||
|
Sets the contrast value for the current shadow group. The value must be a
|
||||||
|
floating-point number.
|
||||||
|
palette:set_highlight_factor(factor)
|
||||||
|
Sets the contrast value for the current highlight group. The value must be
|
||||||
|
a floating-point number.
|
||||||
|
palette:set_shadow_mode(mode)
|
||||||
|
Sets the shadow mode. The value is the index of the desired shadow table.
|
||||||
|
|
||||||
|
Properties
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
palette.entries (read-only)
|
||||||
|
The number of colour entries in the palette.
|
||||||
|
palette.indirect_entries (read-only)
|
||||||
|
The number of indirect pen entries in the palette.
|
||||||
|
palette.black_pen (read-only)
|
||||||
|
The index of the fixed black pen entry.
|
||||||
|
palette.white_pen (read-only)
|
||||||
|
The index of the fixed white pen.
|
||||||
|
palette.shadows_enabled (read-only)
|
||||||
|
A Boolean indicating whether shadow colours are enabled.
|
||||||
|
palette.highlights_enabled (read-only)
|
||||||
|
A Boolean indicating whether highlight colours are enabled.
|
||||||
|
palette.device (read-only)
|
||||||
|
The underlying :ref:`device <luareference-dev-device>`.
|
||||||
|
|
||||||
.. _luareference-dev-screen:
|
.. _luareference-dev-screen:
|
||||||
|
|
||||||
Screen device
|
Screen device
|
||||||
@ -926,8 +1023,8 @@ screen:draw_box(left, top, right, bottom, [line], [fill])
|
|||||||
most-significant to least-significant byte. If the line colour is not
|
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,
|
provided, the UI text colour is used; if the fill colour is not provided,
|
||||||
the UI background colour is used.
|
the UI background colour is used.
|
||||||
screen:draw_line(x1, y1, x2, y2, [color])
|
screen:draw_line(x0, y0, x1, y1, [color])
|
||||||
Draws a line from (x1, y1) to (x2, y2).
|
Draws a line from (x0, y0) to (x1, y1).
|
||||||
|
|
||||||
Coordinates are floating-point numbers in units of emulated screen pixels,
|
Coordinates are floating-point numbers in units of emulated screen pixels,
|
||||||
with the origin at (0, 0). Note that emulated screen pixels often aren’t
|
with the origin at (0, 0). Note that emulated screen pixels often aren’t
|
||||||
@ -1016,6 +1113,10 @@ screen.frame_number (read-only)
|
|||||||
screen.container (read-only)
|
screen.container (read-only)
|
||||||
The :ref:`render container <luareference-render-container>` used to draw the
|
The :ref:`render container <luareference-render-container>` used to draw the
|
||||||
screen.
|
screen.
|
||||||
|
screen.palette (read-only)
|
||||||
|
The :ref:`palette device <luareference-dev-dipalette>` used to translate
|
||||||
|
pixel values to colours, or ``nil`` if the screen uses a direct colour pixel
|
||||||
|
format.
|
||||||
|
|
||||||
.. _luareference-dev-cass:
|
.. _luareference-dev-cass:
|
||||||
|
|
||||||
@ -2596,6 +2697,276 @@ color.b (read/write)
|
|||||||
Blue channel value, in the range of zero (0, off) to one (1, full
|
Blue channel value, in the range of zero (0, off) to one (1, full
|
||||||
intensity).
|
intensity).
|
||||||
|
|
||||||
|
.. _luareference-render-bitmap:
|
||||||
|
|
||||||
|
Bitmap
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
Wraps implementation of MAME’s ``bitmap_t`` and ``bitmap_specific`` classes,
|
||||||
|
which represent two-dimensional bitmaps stored in row-major order. Pixel
|
||||||
|
coordinates are zero-based, increasing to the right and down. Several pixel
|
||||||
|
formats are supported.
|
||||||
|
|
||||||
|
Instantiation
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
emu.bitmap_yuy16([width, height], [xslop], yslop])
|
||||||
|
Creates a Y'CbCr format bitmap with 4:2:2 chroma subsampling (horizontal
|
||||||
|
pairs of pixels have individual luma values but share chroma values). Each
|
||||||
|
pixel is a 16-bit integer value. The most significant byte of the pixel
|
||||||
|
value is the unsigned 8-bit Y' (luma) component of the pixel colour. For
|
||||||
|
each horizontal pair of pixels, the least significant byte of the first
|
||||||
|
pixel (even zero-based X coordinate) value is the signed 8-bit Cb value for
|
||||||
|
the pair of pixels, and the least significant byte of the second pixel (odd
|
||||||
|
zero-based X coordinate) value is the signed 8-bit Cr value for the pair of
|
||||||
|
pixels.
|
||||||
|
|
||||||
|
If no width and height are specified, they are assumed to be zero. If the
|
||||||
|
width is specified, the height must also be specified. The X and Y slop
|
||||||
|
values set the amount of extra storage in pixels to reserve at the
|
||||||
|
left/right of each row and top/bottom of each column, respectively. If an X
|
||||||
|
slop value is specified, a Y slop value must be specified as well. If no X
|
||||||
|
and Y slop values are specified, they are assumed to be zero (the storage
|
||||||
|
will be sized to fit the bitmap content). If the width and/or height is
|
||||||
|
less than or equal to zero, no storage will be allocated, irrespective of
|
||||||
|
the X and Y slop values, and the width and height of the bitmap will both be
|
||||||
|
set to zero.
|
||||||
|
|
||||||
|
The initial clipping rectangle is set to the entirety of the bitmap.
|
||||||
|
emu.bitmap_rgb32([width, height], [xslop, yslop])
|
||||||
|
Creates an RGB format bitmap with no alpha (transparency) channel. Each
|
||||||
|
pixel is represented by a 32-bit integer value. The most significant byte
|
||||||
|
of the pixel value is ignored. The remaining three bytes, from most
|
||||||
|
significant to least significant, are the unsigned 8-bit unsigned red, green
|
||||||
|
and blue channel values (larger values correspond to higher intensities).
|
||||||
|
|
||||||
|
If no width and height are specified, they are assumed to be zero. If the
|
||||||
|
width is specified, the height must also be specified. The X and Y slop
|
||||||
|
values set the amount of extra storage in pixels to reserve at the
|
||||||
|
left/right of each row and top/bottom of each column, respectively. If an X
|
||||||
|
slop value is specified, a Y slop value must be specified as well. If no X
|
||||||
|
and Y slop values are specified, they are assumed to be zero (the storage
|
||||||
|
will be sized to fit the bitmap content). If the width and/or height is
|
||||||
|
less than or equal to zero, no storage will be allocated, irrespective of
|
||||||
|
the X and Y slop values, and the width and height of the bitmap will both be
|
||||||
|
set to zero.
|
||||||
|
|
||||||
|
The initial clipping rectangle is set to the entirety of the bitmap.
|
||||||
|
emu.bitmap_argb32([width, height], [xslop, yslop])
|
||||||
|
Creates an ARGB format bitmap. Each pixel is represented by a 32-bit
|
||||||
|
integer value. The most significant byte of the pixel is the 8-bit unsigned
|
||||||
|
alpha (transparency) channel value (smaller values are more transparent).
|
||||||
|
The remaining three bytes, from most significant to least significant, are
|
||||||
|
the unsigned 8-bit unsigned red, green and blue channel values (larger
|
||||||
|
values correspond to higher intensities). Colour channel values are not
|
||||||
|
pre-multiplied by the alpha channel value.
|
||||||
|
|
||||||
|
If no width and height are specified, they are assumed to be zero. If the
|
||||||
|
width is specified, the height must also be specified. The X and Y slop
|
||||||
|
values set the amount of extra storage in pixels to reserve at the
|
||||||
|
left/right of each row and top/bottom of each column, respectively. If an X
|
||||||
|
slop value is specified, a Y slop value must be specified as well. If no X
|
||||||
|
and Y slop values are specified, they are assumed to be zero (the storage
|
||||||
|
will be sized to fit the bitmap content). If the width and/or height is
|
||||||
|
less than or equal to zero, no storage will be allocated, irrespective of
|
||||||
|
the X and Y slop values, and the width and height of the bitmap will both be
|
||||||
|
set to zero.
|
||||||
|
|
||||||
|
The initial clipping rectangle is set to the entirety of the bitmap.
|
||||||
|
emu.bitmap_yuy16(source, [x0, y0, x1, y1])
|
||||||
|
Creates a Y'CbCr format bitmap with 4:2:2 chroma subsampling representing a
|
||||||
|
view of a portion of an existing bitmap. The initial clipping rectangle is
|
||||||
|
set to the bounds of the view. The source bitmap will be locked, preventing
|
||||||
|
resizing and reallocation.
|
||||||
|
|
||||||
|
If no coordinates are specified, the new bitmap will represent a view of the
|
||||||
|
source bitmap’s current clipping rectangle. If coordinates are specified,
|
||||||
|
the new bitmap will represent a view of the rectangle with top left corner
|
||||||
|
at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap.
|
||||||
|
Coordinates are in units of pixels. The bottom right coordinates are
|
||||||
|
inclusive.
|
||||||
|
|
||||||
|
The source bitmap must be owned by the Lua script and must use the Y'CbCr
|
||||||
|
format. Raises an error if coordinates are specified representing a
|
||||||
|
rectangle not fully contained within the source bitmap’s clipping rectangle.
|
||||||
|
emu.bitmap_rgb32(source, [x0, y0, x1, y1])
|
||||||
|
Creates an RGB format bitmap with 4:2:2 chroma subsampling representing a
|
||||||
|
view of a portion of an existing bitmap. The initial clipping rectangle is
|
||||||
|
set to the bounds of the view. The source bitmap will be locked, preventing
|
||||||
|
resizing and reallocation.
|
||||||
|
|
||||||
|
If no coordinates are specified, the new bitmap will represent a view of the
|
||||||
|
source bitmap’s current clipping rectangle. If coordinates are specified,
|
||||||
|
the new bitmap will represent a view of the rectangle with top left corner
|
||||||
|
at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap.
|
||||||
|
Coordinates are in units of pixels. The bottom right coordinates are
|
||||||
|
inclusive.
|
||||||
|
|
||||||
|
The source bitmap must be owned by the Lua script and must use the RGB
|
||||||
|
format. Raises an error if coordinates are specified representing a
|
||||||
|
rectangle not fully contained within the source bitmap’s clipping rectangle.
|
||||||
|
emu.bitmap_argb32(source, [x0, y0, x1, y1])
|
||||||
|
Creates an ARGB format bitmap with 4:2:2 chroma subsampling representing a
|
||||||
|
view of a portion of an existing bitmap. The initial clipping rectangle is
|
||||||
|
set to the bounds of the view. The source bitmap will be locked, preventing
|
||||||
|
resizing and reallocation.
|
||||||
|
|
||||||
|
If no coordinates are specified, the new bitmap will represent a view of the
|
||||||
|
source bitmap’s current clipping rectangle. If coordinates are specified,
|
||||||
|
the new bitmap will represent a view of the rectangle with top left corner
|
||||||
|
at (x0, y0) and bottom right corner at (x1, y1) in the source bitmap.
|
||||||
|
Coordinates are in units of pixels. The bottom right coordinates are
|
||||||
|
inclusive.
|
||||||
|
|
||||||
|
The source bitmap must be owned by the Lua script and must use the ARGB
|
||||||
|
format. Raises an error if coordinates are specified representing a
|
||||||
|
rectangle not fully contained within the source bitmap’s clipping rectangle.
|
||||||
|
|
||||||
|
Methods
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
bitmap:reset()
|
||||||
|
Sets the width and height to zero, and frees the pixel storage if the bitmap
|
||||||
|
owns its own storage, or releases the source bitmap if the it represents a
|
||||||
|
view of another bitmap.
|
||||||
|
|
||||||
|
The bitmap must be owned by the Lua script. Raises an error if the bitmap’s
|
||||||
|
storage is referenced by another bitmap or a :ref:`texture
|
||||||
|
<luareference-render-texture>`.
|
||||||
|
bitmap:allocate(width, height, [xslop, yslop])
|
||||||
|
Reallocates storage for the bitmap, sets its width and height, and sets the
|
||||||
|
clipping rectangle to the entirety of the bitmap. If the bitmap already
|
||||||
|
owns allocated storage, it will always be freed and reallocated; if the
|
||||||
|
bitmap represents a view of another bitmap, the source bitmap will be
|
||||||
|
released. The storage will be filled with pixel value zero.
|
||||||
|
|
||||||
|
The X and Y slop values set the amount of extra storage in pixels to reserve
|
||||||
|
at the left/right of each row and top/bottom of each column, respectively.
|
||||||
|
If an X slop value is specified, a Y slop value must be specified as well.
|
||||||
|
If no X and Y slop values are specified, they are assumed to be zero (the
|
||||||
|
storage will be sized to fit the bitmap content). If the width and/or
|
||||||
|
height is less than or equal to zero, no storage will be allocated,
|
||||||
|
irrespective of the X and Y slop values, and the width and height of the
|
||||||
|
bitmap will both be set to zero.
|
||||||
|
|
||||||
|
The bitmap must be owned by the Lua script. Raises an error if the bitmap’s
|
||||||
|
storage is referenced by another bitmap or a :ref:`texture
|
||||||
|
<luareference-render-texture>`.
|
||||||
|
bitmap:resize(width, height, [xslop, yslop])
|
||||||
|
Changes the width and height, and sets the clipping rectangle to the
|
||||||
|
entirety of the bitmap.
|
||||||
|
|
||||||
|
The X and Y slop values set the amount of extra storage in pixels to reserve
|
||||||
|
at the left/right of each row and top/bottom of each column, respectively.
|
||||||
|
If an X slop value is specified, a Y slop value must be specified as well.
|
||||||
|
If no X and Y slop values are specified, they are assumed to be zero (rows
|
||||||
|
will be stored contiguously, and the top row will be placed at the beginning
|
||||||
|
of the bitmap’s storage).
|
||||||
|
|
||||||
|
If the bitmap already owns allocated storage and it is large enough for the
|
||||||
|
updated size, it will be used without being freed; if it is too small for
|
||||||
|
the updated size, it will always be freed and reallocated. If the bitmap
|
||||||
|
represents a view of another bitmap, the source bitmap will be released. If
|
||||||
|
storage is allocated, it will be filled with pixel value zero (if existing
|
||||||
|
storage is used, its contents will not be changed).
|
||||||
|
|
||||||
|
Raises an error if the bitmap’s storage is referenced by another bitmap or a
|
||||||
|
:ref:`texture <luareference-render-texture>`.
|
||||||
|
bitmap:wrap(source, [x0, y0, x1, y1])
|
||||||
|
Makes the bitmap represent a view of a portion of another bitmap and sets
|
||||||
|
the clipping rectangle to the bounds of the view.
|
||||||
|
|
||||||
|
If no coordinates are specified, the target bitmap will represent a view of
|
||||||
|
the source bitmap’s current clipping rectangle. If coordinates are
|
||||||
|
specified, the target bitmap will represent a view of the rectangle with top
|
||||||
|
left corner at (x0, y0) and bottom right corner at (x1, y1) in the source
|
||||||
|
bitmap. Coordinates are in units of pixels. The bottom right coordinates
|
||||||
|
are inclusive.
|
||||||
|
|
||||||
|
The source bitmap will be locked, preventing resizing and reallocation. If
|
||||||
|
the target bitmap owns allocated storage, it will be freed; if it represents
|
||||||
|
a view of another bitmap, the current source bitmap will be released.
|
||||||
|
|
||||||
|
The source and target bitmaps must both be owned by the Lua script and must
|
||||||
|
use the same pixel format. Raises an error if coordinates are specified
|
||||||
|
representing a rectangle not fully contained within the source bitmap’s
|
||||||
|
clipping rectangle; if the bitmap’s storage is referenced by another bitmap
|
||||||
|
or a :ref:`texture <luareference-render-texture>`; or if the source and
|
||||||
|
target are the same bitmap.
|
||||||
|
bitmap:pix(x, y)
|
||||||
|
Returns the colour value of the pixel at the specified location.
|
||||||
|
Coordinates are zero-based in units of pixels.
|
||||||
|
bitmap:fill(color, [x0, y0, x1, y1])
|
||||||
|
Fills a portion of the bitmap with the specified colour value. If
|
||||||
|
coordinates are not specified, the clipping rectangle is filled; if
|
||||||
|
coordinates are specified, the intersection of the clipping rectangle and
|
||||||
|
the rectangle with top left corner at (x0, y0) and bottom right corner at
|
||||||
|
(x1, y1) is filled. Coordinates are in units of pixels. The bottom right
|
||||||
|
coordinates are inclusive.
|
||||||
|
bitmap:plot(x, y, color)
|
||||||
|
Sets the colour value of the pixel at the specified location if it is within
|
||||||
|
the clipping rectangle. Coordinates are zero-based in units of pixels.
|
||||||
|
bitmap:plot_box(x, y, width, height, color)
|
||||||
|
Fills the intersection of the clipping rectangle and the rectangle with top
|
||||||
|
left (x, y) and the specified height and width with the specified colour
|
||||||
|
value. Coordinates and dimensions are in units of pixels.
|
||||||
|
|
||||||
|
Properties
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
bitmap.width (read-only)
|
||||||
|
Width of the bitmap in pixels.
|
||||||
|
bitmap.height (read-only)
|
||||||
|
Height of the bitmap in pixels.
|
||||||
|
bitmap.rowpixels (read-only)
|
||||||
|
Row stride of the bitmap’s storage in pixels. That is, the difference in
|
||||||
|
pixel offsets of the pixels at the same horizontal location in consecutive
|
||||||
|
rows. May be greater than the width.
|
||||||
|
bitmap.rowbytes (read-only)
|
||||||
|
Row stride of the bitmap’s storage in bytes. That is, the difference in
|
||||||
|
byte addresses of the pixels at the same horizontal location in consecutive
|
||||||
|
rows.
|
||||||
|
bitmap.bpp (read-only)
|
||||||
|
Size of the type used to represent pixels in the bitmap in bits (may be
|
||||||
|
larger than the number of significant bits).
|
||||||
|
bitmap.valid (read-only)
|
||||||
|
A Boolean indicating whether the bitmap has storage available (may be false
|
||||||
|
for empty bitmaps).
|
||||||
|
bitmap.locked (read-only)
|
||||||
|
A Boolean indicating whether the bitmap’s storage is referenced by another
|
||||||
|
bitmap or a :ref:`texture <luareference-render-texture>`.
|
||||||
|
|
||||||
|
.. _luareference-render-texture:
|
||||||
|
|
||||||
|
Render texture
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Wraps MAME’s ``render_texture`` class, representing a texture that cam be drawn
|
||||||
|
in a :ref:`render container <luareference-render-container>`. Render textures
|
||||||
|
must be freed before the emulation session ends.
|
||||||
|
|
||||||
|
Instantiation
|
||||||
|
^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
manager.machine.render:texture_alloc(bitmap)
|
||||||
|
Creates a render texture based on a :ref:`bitmap
|
||||||
|
<luareference-render-bitmap>`. The bitmap must be owned by the Lua script,
|
||||||
|
and must use the Y'CbCr, RGB or ARGB format. The bitmap’s storage will be
|
||||||
|
locked, preventing resizing and reallocation.
|
||||||
|
|
||||||
|
Methods
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
texture:free()
|
||||||
|
Frees the texture. The storage of the underlying bitmap will be released.
|
||||||
|
|
||||||
|
Properties
|
||||||
|
^^^^^^^^^^
|
||||||
|
|
||||||
|
texture.valid (read-only)
|
||||||
|
A Boolean indicating whether the texture is valid (false if the texture has
|
||||||
|
been freed).
|
||||||
|
|
||||||
.. _luareference-render-manager:
|
.. _luareference-render-manager:
|
||||||
|
|
||||||
Render manager
|
Render manager
|
||||||
@ -2610,6 +2981,16 @@ Instantiation
|
|||||||
manager.machine.render
|
manager.machine.render
|
||||||
Gets the global render manager instance for the emulation session.
|
Gets the global render manager instance for the emulation session.
|
||||||
|
|
||||||
|
Methods
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
render:texture_alloc(bitmap)
|
||||||
|
Creates a :ref:`render texture <luareference-render-texture>` based on a
|
||||||
|
:ref:`bitmap <luareference-render-bitmap>`. The bitmap must be owned by the
|
||||||
|
Lua script, and must use the Y'CbCr, RGB or ARGB format. The bitmap’s
|
||||||
|
storage will be locked, preventing resizing and reallocation. Render
|
||||||
|
textures must be freed before the emulation session ends.
|
||||||
|
|
||||||
Properties
|
Properties
|
||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
@ -2718,7 +3099,7 @@ container:draw_box(left, top, right, bottom, [line], [fill])
|
|||||||
|
|
||||||
Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one),
|
Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one),
|
||||||
with (0, 0) at the top left and (1, 1) at the bottom right of the window or
|
with (0, 0) at the top left and (1, 1) at the bottom right of the window or
|
||||||
screen that showss the user interface. Note that the aspect ratio is
|
the screen that shows the user interface. Note that the aspect ratio is
|
||||||
usually not square. Coordinates are limited to the window or screen area.
|
usually not square. Coordinates are limited to the window or screen area.
|
||||||
|
|
||||||
The fill and line colours are in alpha/red/green/blue (ARGB) format.
|
The fill and line colours are in alpha/red/green/blue (ARGB) format.
|
||||||
@ -2729,21 +3110,14 @@ container:draw_box(left, top, right, bottom, [line], [fill])
|
|||||||
most-significant to least-significant byte. If the line colour is not
|
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,
|
provided, the UI text colour is used; if the fill colour is not provided,
|
||||||
the UI background colour is used.
|
the UI background colour is used.
|
||||||
container:draw_line(x1, y1, x2, y2, [color])
|
container:draw_line(x0, y0, x1, y1, [color])
|
||||||
Draws a line from (x1, y1) to (x2, y2).
|
Draws a line from (x0, y0) to (x1, y1).
|
||||||
|
|
||||||
Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one),
|
Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one),
|
||||||
with (0, 0) at the top left and (1, 1) at the bottom right of the window or
|
with (0, 0) at the top left and (1, 1) at the bottom right of the window or
|
||||||
screen that showss the user interface. Note that the aspect ratio is
|
the screen that shows the user interface. Note that the aspect ratio is
|
||||||
usually not square. Coordinates are limited to the window or screen area.
|
usually not square. Coordinates are limited to the window or screen area.
|
||||||
|
|
||||||
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
|
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),
|
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.
|
inclusive. Colour channel values are not pre-multiplied by the alpha value.
|
||||||
@ -2751,6 +3125,24 @@ container:draw_line(x1, y1, x2, y2, [color])
|
|||||||
integer, in the order alpha, red, green, blue from most-significant to
|
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
|
least-significant byte. If the line colour is not provided, the UI text
|
||||||
colour is used.
|
colour is used.
|
||||||
|
container:draw_quad(texture, x0, y0, x1, y1, [color])
|
||||||
|
Draws a textured rectangle with top left corner at (x0, y0) and bottom right
|
||||||
|
corner at (x1, y1). If a colour is specified, the ARGB channel values of
|
||||||
|
the texture’s pixels are multiplied by the corresponding values of the
|
||||||
|
specified colour.
|
||||||
|
|
||||||
|
Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one),
|
||||||
|
with (0, 0) at the top left and (1, 1) at the bottom right of the window or
|
||||||
|
the screen that shows the user interface. Note that the aspect ratio is
|
||||||
|
usually not square. If the rectangle extends beyond the container’s bounds,
|
||||||
|
it will be cropped.
|
||||||
|
|
||||||
|
The 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.
|
||||||
container:draw_text(x|justify, y, text, [foreground], [background])
|
container:draw_text(x|justify, y, text, [foreground], [background])
|
||||||
Draws text at the specified position. If the screen is rotated the text
|
Draws text at the specified position. If the screen is rotated the text
|
||||||
will be rotated.
|
will be rotated.
|
||||||
@ -2765,7 +3157,7 @@ container:draw_text(x|justify, y, text, [foreground], [background])
|
|||||||
|
|
||||||
Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one),
|
Coordinates are floating-point numbers in the range of 0 (zero) to 1 (one),
|
||||||
with (0, 0) at the top left and (1, 1) at the bottom right of the window or
|
with (0, 0) at the top left and (1, 1) at the bottom right of the window or
|
||||||
screen that showss the user interface. Note that the aspect ratio is
|
the screen that shows the user interface. Note that the aspect ratio is
|
||||||
usually not square. Coordinates are limited to the window or screen area.
|
usually not square. Coordinates are limited to the window or screen area.
|
||||||
|
|
||||||
The foreground and background colours are in alpha/red/green/blue (ARGB)
|
The foreground and background colours are in alpha/red/green/blue (ARGB)
|
||||||
|
@ -720,6 +720,9 @@ void lua_engine::initialize()
|
|||||||
emu["device_enumerator"] = sol::overload(
|
emu["device_enumerator"] = sol::overload(
|
||||||
[] (device_t &dev) { return devenum<device_enumerator>(dev); },
|
[] (device_t &dev) { return devenum<device_enumerator>(dev); },
|
||||||
[] (device_t &dev, int maxdepth) { return devenum<device_enumerator>(dev, maxdepth); });
|
[] (device_t &dev, int maxdepth) { return devenum<device_enumerator>(dev, maxdepth); });
|
||||||
|
emu["palette_enumerator"] = sol::overload(
|
||||||
|
[] (device_t &dev) { return devenum<palette_interface_enumerator>(dev); },
|
||||||
|
[] (device_t &dev, int maxdepth) { return devenum<palette_interface_enumerator>(dev, maxdepth); });
|
||||||
emu["screen_enumerator"] = sol::overload(
|
emu["screen_enumerator"] = sol::overload(
|
||||||
[] (device_t &dev) { return devenum<screen_device_enumerator>(dev); },
|
[] (device_t &dev) { return devenum<screen_device_enumerator>(dev); },
|
||||||
[] (device_t &dev, int maxdepth) { return devenum<screen_device_enumerator>(dev, maxdepth); });
|
[] (device_t &dev, int maxdepth) { return devenum<screen_device_enumerator>(dev, maxdepth); });
|
||||||
@ -1271,6 +1274,7 @@ void lua_engine::initialize()
|
|||||||
machine_type["exit_pending"] = sol::property(&running_machine::exit_pending);
|
machine_type["exit_pending"] = sol::property(&running_machine::exit_pending);
|
||||||
machine_type["hard_reset_pending"] = sol::property(&running_machine::hard_reset_pending);
|
machine_type["hard_reset_pending"] = sol::property(&running_machine::hard_reset_pending);
|
||||||
machine_type["devices"] = sol::property([] (running_machine &m) { return devenum<device_enumerator>(m.root_device()); });
|
machine_type["devices"] = sol::property([] (running_machine &m) { return devenum<device_enumerator>(m.root_device()); });
|
||||||
|
machine_type["palettes"] = sol::property([] (running_machine &m) { return devenum<palette_interface_enumerator>(m.root_device()); });
|
||||||
machine_type["screens"] = sol::property([] (running_machine &m) { return devenum<screen_device_enumerator>(m.root_device()); });
|
machine_type["screens"] = sol::property([] (running_machine &m) { return devenum<screen_device_enumerator>(m.root_device()); });
|
||||||
machine_type["cassettes"] = sol::property([] (running_machine &m) { return devenum<cassette_device_enumerator>(m.root_device()); });
|
machine_type["cassettes"] = sol::property([] (running_machine &m) { return devenum<cassette_device_enumerator>(m.root_device()); });
|
||||||
machine_type["images"] = sol::property([] (running_machine &m) { return devenum<image_interface_enumerator>(m.root_device()); });
|
machine_type["images"] = sol::property([] (running_machine &m) { return devenum<image_interface_enumerator>(m.root_device()); });
|
||||||
@ -1432,6 +1436,54 @@ void lua_engine::initialize()
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
auto dipalette_type = sol().registry().new_usertype<device_palette_interface>("dipalette", sol::no_constructor);
|
||||||
|
dipalette_type.set_function("pen", &device_palette_interface::pen);
|
||||||
|
dipalette_type.set_function(
|
||||||
|
"pen_color",
|
||||||
|
[] (device_palette_interface const &pal, pen_t pen)
|
||||||
|
{
|
||||||
|
return uint32_t(pal.pen_color(pen));
|
||||||
|
});
|
||||||
|
dipalette_type.set_function("pen_contrast", &device_palette_interface::pen_contrast);
|
||||||
|
dipalette_type.set_function("pen_indirect", &device_palette_interface::pen_indirect);
|
||||||
|
dipalette_type.set_function(
|
||||||
|
"indirect_color",
|
||||||
|
[] (device_palette_interface const &pal, int index)
|
||||||
|
{
|
||||||
|
return uint32_t(pal.indirect_color(index));
|
||||||
|
});
|
||||||
|
dipalette_type["set_pen_color"] = sol::overload(
|
||||||
|
[] (device_palette_interface &pal, pen_t pen, uint32_t color)
|
||||||
|
{
|
||||||
|
pal.set_pen_color(pen, rgb_t(color));
|
||||||
|
},
|
||||||
|
static_cast<void (device_palette_interface::*)(pen_t, uint8_t, uint8_t, uint8_t)>(&device_palette_interface::set_pen_color));
|
||||||
|
dipalette_type.set_function("set_pen_red_level", &device_palette_interface::set_pen_red_level);
|
||||||
|
dipalette_type.set_function("set_pen_green_level", &device_palette_interface::set_pen_green_level);
|
||||||
|
dipalette_type.set_function("set_pen_blue_level", &device_palette_interface::set_pen_blue_level);
|
||||||
|
dipalette_type.set_function("set_pen_contrast", &device_palette_interface::set_pen_contrast);
|
||||||
|
dipalette_type.set_function("set_pen_indirect", &device_palette_interface::set_pen_indirect);
|
||||||
|
dipalette_type["set_indirect_color"] = sol::overload(
|
||||||
|
[] (device_palette_interface &pal, int index, uint32_t color)
|
||||||
|
{
|
||||||
|
pal.set_indirect_color(index, rgb_t(color));
|
||||||
|
},
|
||||||
|
[] (device_palette_interface &pal, int index, uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
{
|
||||||
|
pal.set_indirect_color(index, rgb_t(r, g, b));
|
||||||
|
});
|
||||||
|
dipalette_type.set_function("set_shadow_factor", &device_palette_interface::set_shadow_factor);
|
||||||
|
dipalette_type.set_function("set_highlight_factor", &device_palette_interface::set_highlight_factor);
|
||||||
|
dipalette_type.set_function("set_shadow_mode", &device_palette_interface::set_shadow_mode);
|
||||||
|
dipalette_type["entries"] = sol::property(&device_palette_interface::entries);
|
||||||
|
dipalette_type["indirect_entries"] = sol::property(&device_palette_interface::indirect_entries);
|
||||||
|
dipalette_type["black_pen"] = sol::property(&device_palette_interface::black_pen);
|
||||||
|
dipalette_type["white_pen"] = sol::property(&device_palette_interface::white_pen);
|
||||||
|
dipalette_type["shadows_enabled"] = sol::property(&device_palette_interface::shadows_enabled);
|
||||||
|
dipalette_type["highlights_enabled"] = sol::property(&device_palette_interface::hilights_enabled);
|
||||||
|
dipalette_type["device"] = sol::property(static_cast<device_t & (device_palette_interface::*)()>(&device_palette_interface::device));
|
||||||
|
|
||||||
|
|
||||||
auto screen_dev_type = sol().registry().new_usertype<screen_device>(
|
auto screen_dev_type = sol().registry().new_usertype<screen_device>(
|
||||||
"screen_dev",
|
"screen_dev",
|
||||||
sol::no_constructor,
|
sol::no_constructor,
|
||||||
@ -1589,6 +1641,7 @@ void lua_engine::initialize()
|
|||||||
screen_dev_type["frame_period"] = sol::property([] (screen_device &sdev) { return sdev.frame_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["frame_number"] = &screen_device::frame_number;
|
||||||
screen_dev_type["container"] = sol::property(&screen_device::container);
|
screen_dev_type["container"] = sol::property(&screen_device::container);
|
||||||
|
screen_dev_type["palette"] = sol::property([] (screen_device const &sdev) { return sdev.has_palette() ? &sdev.palette() : nullptr; });
|
||||||
|
|
||||||
|
|
||||||
auto cass_type = sol().registry().new_usertype<cassette_image_device>(
|
auto cass_type = sol().registry().new_usertype<cassette_image_device>(
|
||||||
|
@ -17,11 +17,181 @@
|
|||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "rendlay.h"
|
#include "rendlay.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class bitmap_helper : public T
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ptr = std::shared_ptr<bitmap_helper>;
|
||||||
|
|
||||||
|
bitmap_helper(bitmap_helper const &) = delete;
|
||||||
|
bitmap_helper(bitmap_helper &&) = delete;
|
||||||
|
bitmap_helper &operator=(bitmap_helper const &) = delete;
|
||||||
|
bitmap_helper &operator=(bitmap_helper &&) = delete;
|
||||||
|
|
||||||
|
bitmap_helper(sol::this_state s, int width, int height, int xslop, int yslop)
|
||||||
|
: T(width, height, xslop, yslop)
|
||||||
|
, lock_count(0)
|
||||||
|
, storage()
|
||||||
|
{
|
||||||
|
if ((0 < width) && (0 < height) && !this->valid())
|
||||||
|
luaL_error(s, "Error allocating bitmap storage");
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_helper(ptr const &source, rectangle const &subrect)
|
||||||
|
: T(*source, subrect)
|
||||||
|
, lock_count(0)
|
||||||
|
, storage(source->storage ? source->storage : source)
|
||||||
|
{
|
||||||
|
++storage->lock_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
~bitmap_helper()
|
||||||
|
{
|
||||||
|
assert(!lock_count);
|
||||||
|
release_storage();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool locked() const
|
||||||
|
{
|
||||||
|
return bool(lock_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(sol::this_state s)
|
||||||
|
{
|
||||||
|
if (lock_count)
|
||||||
|
luaL_error(s, "Cannot reset bitmap while in use");
|
||||||
|
T::reset();
|
||||||
|
release_storage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void allocate(sol::this_state s, int width, int height, int xslop, int yslop)
|
||||||
|
{
|
||||||
|
if (lock_count)
|
||||||
|
luaL_error(s, "Cannot reallocate bitmap while in use");
|
||||||
|
T::allocate(width, height, xslop, yslop);
|
||||||
|
release_storage();
|
||||||
|
if ((0 < width) && (0 < height) && !this->valid())
|
||||||
|
luaL_error(s, "Error allocating bitmap storage");
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(sol::this_state s, int width, int height, int xslop, int yslop)
|
||||||
|
{
|
||||||
|
if (lock_count)
|
||||||
|
luaL_error(s, "Cannot resize bitmap while in use");
|
||||||
|
T::resize(width, height, xslop, yslop);
|
||||||
|
release_storage();
|
||||||
|
if ((0 < width) && (0 < height) && !this->valid())
|
||||||
|
luaL_error(s, "Error allocating bitmap storage");
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap(sol::this_state s, ptr const &source, rectangle const &subrect)
|
||||||
|
{
|
||||||
|
if (source.get() == this)
|
||||||
|
luaL_error(s, "Bitmap cannot wrap itself");
|
||||||
|
if (lock_count)
|
||||||
|
luaL_error(s, "Cannot free bitmap storage while in use");
|
||||||
|
if (!source->cliprect().contains(subrect))
|
||||||
|
luaL_error(s, "Bounds exceed source clipping rectangle");
|
||||||
|
T::wrap(*source, subrect);
|
||||||
|
release_storage();
|
||||||
|
storage = source->storage ? source->storage : source;
|
||||||
|
++storage->lock_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::atomic<unsigned> lock_count;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void release_storage()
|
||||||
|
{
|
||||||
|
if (storage)
|
||||||
|
{
|
||||||
|
assert(storage->lock_count);
|
||||||
|
--storage->lock_count;
|
||||||
|
storage.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr storage;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class render_texture_helper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
render_texture_helper(render_texture_helper const &) = delete;
|
||||||
|
|
||||||
|
render_texture_helper(render_texture_helper &&that)
|
||||||
|
: texture(that.texture)
|
||||||
|
, bitmap(that.bitmap)
|
||||||
|
, manager(that.manager)
|
||||||
|
, lock_count(that.lock_count)
|
||||||
|
{
|
||||||
|
that.texture = nullptr;
|
||||||
|
that.bitmap.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
render_texture_helper(sol::this_state s, render_manager &m, std::shared_ptr<T> const &b, texture_format f)
|
||||||
|
: texture(nullptr)
|
||||||
|
, bitmap(b)
|
||||||
|
, manager(m)
|
||||||
|
, lock_count(b->lock_count)
|
||||||
|
{
|
||||||
|
if (bitmap)
|
||||||
|
{
|
||||||
|
texture = manager.texture_alloc();
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
++lock_count;
|
||||||
|
texture->set_bitmap(*bitmap, bitmap->cliprect(), f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
luaL_error(s, "Error allocating texture");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~render_texture_helper()
|
||||||
|
{
|
||||||
|
free();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valid() const
|
||||||
|
{
|
||||||
|
return texture && bitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free()
|
||||||
|
{
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
manager.texture_free(texture);
|
||||||
|
texture = nullptr;
|
||||||
|
}
|
||||||
|
if (bitmap)
|
||||||
|
{
|
||||||
|
assert(lock_count);
|
||||||
|
--lock_count;
|
||||||
|
bitmap.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_texture *texture;
|
||||||
|
std::shared_ptr<bitmap_t> bitmap;
|
||||||
|
|
||||||
|
private:
|
||||||
|
render_manager &manager;
|
||||||
|
std::atomic<unsigned> &lock_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct layout_file_views
|
struct layout_file_views
|
||||||
{
|
{
|
||||||
layout_file_views(layout_file &f) : file(f) { }
|
layout_file_views(layout_file &f) : file(f) { }
|
||||||
@ -54,6 +224,84 @@ struct render_target_view_names
|
|||||||
int count;
|
int count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto make_bitmap_specific_type(sol::table registry, char const *name)
|
||||||
|
{
|
||||||
|
auto result = registry.new_usertype<T>(
|
||||||
|
name,
|
||||||
|
sol::no_constructor,
|
||||||
|
sol::base_classes, sol::bases<bitmap_t>());
|
||||||
|
result.set_function("pix", [] (T &bitmap, int32_t x, int32_t y) { return bitmap.pix(y, x); });
|
||||||
|
result["fill"] = sol::overload(
|
||||||
|
static_cast<void (T::*)(typename T::pixel_t)>(&T::fill),
|
||||||
|
[] (T &bitmap, typename T::pixel_t color, int32_t minx, int32_t miny, int32_t maxx, int32_t maxy)
|
||||||
|
{
|
||||||
|
bitmap.fill(color, rectangle(minx, maxx, miny, maxy));
|
||||||
|
});
|
||||||
|
result.set_function(
|
||||||
|
"plot",
|
||||||
|
[] (T &bitmap, int32_t x, int32_t y, typename T::pixel_t color)
|
||||||
|
{
|
||||||
|
if (bitmap.cliprect().contains(x, y))
|
||||||
|
bitmap.pix(y, x) = color;
|
||||||
|
});
|
||||||
|
result.set_function("plot_box", &T::plot_box);
|
||||||
|
result["bpp"] = sol::property(&T::bpp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T, typename B>
|
||||||
|
auto make_bitmap_type(sol::table ®istry, char const *name)
|
||||||
|
{
|
||||||
|
auto result = registry.new_usertype<T>(
|
||||||
|
name,
|
||||||
|
sol::call_constructor, sol::factories(
|
||||||
|
[] (sol::this_state s)
|
||||||
|
{
|
||||||
|
return std::make_shared<T>(s, 0, 0, 0, 0);
|
||||||
|
},
|
||||||
|
[] (sol::this_state s, int width, int height)
|
||||||
|
{
|
||||||
|
return std::make_shared<T>(s, width, height, 0, 0);
|
||||||
|
},
|
||||||
|
[] (sol::this_state s, int width, int height, int xslop, int yslop)
|
||||||
|
{
|
||||||
|
return std::make_shared<T>(s, width, height, xslop, yslop);
|
||||||
|
},
|
||||||
|
[] (typename T::ptr const &source)
|
||||||
|
{
|
||||||
|
return std::make_shared<T>(source, source->cliprect());
|
||||||
|
},
|
||||||
|
[] (sol::this_state s, typename T::ptr const &source, int32_t minx, int32_t miny, int32_t maxx, int32_t maxy)
|
||||||
|
{
|
||||||
|
rectangle const subrect(minx, maxx, miny, maxy);
|
||||||
|
if (!source->cliprect().contains(subrect))
|
||||||
|
luaL_error(s, "Bounds exceed source clipping rectangle");
|
||||||
|
return std::make_shared<T>(source, subrect);
|
||||||
|
}),
|
||||||
|
sol::base_classes, sol::bases<B, bitmap_t>());
|
||||||
|
result.set_function("reset", &T::reset);
|
||||||
|
result["allocate"] = sol::overload(
|
||||||
|
&T::allocate,
|
||||||
|
[] (T &bitmap, sol::this_state s, int width, int height) { bitmap.allocate(s, width, height, 0, 0); });
|
||||||
|
result["resize"] = sol::overload(
|
||||||
|
&T::resize,
|
||||||
|
[] (T &bitmap, sol::this_state s, int width, int height) { bitmap.resize(s, width, height, 0, 0); });
|
||||||
|
result["wrap"] = sol::overload(
|
||||||
|
[] (T &bitmap, sol::this_state s, typename T::ptr const &source)
|
||||||
|
{
|
||||||
|
bitmap.wrap(s, source, source->cliprect());
|
||||||
|
},
|
||||||
|
[] (T &bitmap, sol::this_state s, typename T::ptr const &source, int32_t minx, int32_t miny, int32_t maxx, int32_t maxy)
|
||||||
|
{
|
||||||
|
bitmap.wrap(s, source, rectangle(minx, maxx, miny, maxy));
|
||||||
|
});
|
||||||
|
result["locked"] = sol::property(&T::locked);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
@ -226,9 +474,9 @@ void lua_engine::initialize_render(sol::table &emu)
|
|||||||
sol::call_constructor, sol::initializers(
|
sol::call_constructor, sol::initializers(
|
||||||
[] (render_bounds &b) { new (&b) render_bounds{ 0.0F, 0.0F, 1.0F, 1.0F }; },
|
[] (render_bounds &b) { new (&b) render_bounds{ 0.0F, 0.0F, 1.0F, 1.0F }; },
|
||||||
[] (render_bounds &b, float x0, float y0, float x1, float y1) { new (&b) render_bounds{ x0, y0, x1, y1 }; }));
|
[] (render_bounds &b, float x0, float y0, float x1, float y1) { new (&b) render_bounds{ x0, y0, x1, y1 }; }));
|
||||||
bounds_type["includes"] = &render_bounds::includes;
|
bounds_type.set_function("includes", &render_bounds::includes);
|
||||||
bounds_type["set_xy"] = &render_bounds::set_xy;
|
bounds_type.set_function("set_xy", &render_bounds::set_xy);
|
||||||
bounds_type["set_wh"] = &render_bounds::set_wh;
|
bounds_type.set_function("set_wh", &render_bounds::set_wh);
|
||||||
bounds_type["x0"] = &render_bounds::x0;
|
bounds_type["x0"] = &render_bounds::x0;
|
||||||
bounds_type["y0"] = &render_bounds::y0;
|
bounds_type["y0"] = &render_bounds::y0;
|
||||||
bounds_type["x1"] = &render_bounds::x1;
|
bounds_type["x1"] = &render_bounds::x1;
|
||||||
@ -243,13 +491,43 @@ void lua_engine::initialize_render(sol::table &emu)
|
|||||||
sol::call_constructor, sol::initializers(
|
sol::call_constructor, sol::initializers(
|
||||||
[] (render_color &c) { new (&c) render_color{ 1.0F, 1.0F, 1.0F, 1.0F }; },
|
[] (render_color &c) { new (&c) render_color{ 1.0F, 1.0F, 1.0F, 1.0F }; },
|
||||||
[] (render_color &c, float a, float r, float g, float b) { new (&c) render_color{ a, r, g, b }; }));
|
[] (render_color &c, float a, float r, float g, float b) { new (&c) render_color{ a, r, g, b }; }));
|
||||||
color_type["set"] = &render_color::set;
|
color_type.set_function("set", &render_color::set);
|
||||||
color_type["a"] = &render_color::a;
|
color_type["a"] = &render_color::a;
|
||||||
color_type["r"] = &render_color::r;
|
color_type["r"] = &render_color::r;
|
||||||
color_type["g"] = &render_color::g;
|
color_type["g"] = &render_color::g;
|
||||||
color_type["b"] = &render_color::b;
|
color_type["b"] = &render_color::b;
|
||||||
|
|
||||||
|
|
||||||
|
auto bitmap_type = sol().registry().new_usertype<bitmap_t>("bitmap", sol::no_constructor);
|
||||||
|
bitmap_type["fill"] = sol::overload(
|
||||||
|
static_cast<void (bitmap_t::*)(uint64_t)>(&bitmap_t::fill),
|
||||||
|
[] (bitmap_t &bitmap, uint64_t color, int32_t minx, int32_t miny, int32_t maxx, int32_t maxy)
|
||||||
|
{
|
||||||
|
bitmap.fill(color, rectangle(minx, maxx, miny, maxy));
|
||||||
|
});
|
||||||
|
bitmap_type.set_function("plot_box", &bitmap_t::plot_box);
|
||||||
|
bitmap_type["width"] = sol::property(&bitmap_t::width);
|
||||||
|
bitmap_type["height"] = sol::property(&bitmap_t::height);
|
||||||
|
bitmap_type["rowpixels"] = sol::property(&bitmap_t::rowpixels);
|
||||||
|
bitmap_type["rowbytes"] = sol::property(&bitmap_t::rowbytes);
|
||||||
|
bitmap_type["bpp"] = sol::property(&bitmap_t::bpp);
|
||||||
|
bitmap_type["valid"] = sol::property(&bitmap_t::valid);
|
||||||
|
|
||||||
|
make_bitmap_specific_type<bitmap8_t>(sol().registry(), "bitmap8");
|
||||||
|
make_bitmap_specific_type<bitmap16_t>(sol().registry(), "bitmap16");
|
||||||
|
make_bitmap_specific_type<bitmap32_t>(sol().registry(), "bitmap32");
|
||||||
|
make_bitmap_specific_type<bitmap64_t>(sol().registry(), "bitmap64");
|
||||||
|
|
||||||
|
make_bitmap_type<bitmap_helper<bitmap_yuy16>, bitmap16_t>(emu, "bitmap_yuy16");
|
||||||
|
make_bitmap_type<bitmap_helper<bitmap_rgb32>, bitmap32_t>(emu, "bitmap_rgb32");
|
||||||
|
make_bitmap_type<bitmap_helper<bitmap_argb32>, bitmap32_t>(emu, "bitmap_argb32");
|
||||||
|
|
||||||
|
|
||||||
|
auto render_texture_type = emu.new_usertype<render_texture_helper>("render_texture", sol::no_constructor);
|
||||||
|
render_texture_type.set_function("free", &render_texture_helper::free);
|
||||||
|
render_texture_type["valid"] = sol::property(&render_texture_helper::valid);
|
||||||
|
|
||||||
|
|
||||||
auto layout_view_type = sol().registry().new_usertype<layout_view>("layout_view", sol::no_constructor);
|
auto layout_view_type = sol().registry().new_usertype<layout_view>("layout_view", sol::no_constructor);
|
||||||
layout_view_type["has_screen"] = &layout_view::has_screen;
|
layout_view_type["has_screen"] = &layout_view::has_screen;
|
||||||
layout_view_type["set_prepare_items_callback"] =
|
layout_view_type["set_prepare_items_callback"] =
|
||||||
@ -392,7 +670,8 @@ void lua_engine::initialize_render(sol::table &emu)
|
|||||||
|
|
||||||
|
|
||||||
auto render_container_type = sol().registry().new_usertype<render_container>("render_container", sol::no_constructor);
|
auto render_container_type = sol().registry().new_usertype<render_container>("render_container", sol::no_constructor);
|
||||||
render_container_type["draw_box"] =
|
render_container_type.set_function(
|
||||||
|
"draw_box",
|
||||||
[] (render_container &ctnr, float x1, float y1, float x2, float y2, std::optional<uint32_t> fgcolor, std::optional<uint32_t> bgcolor)
|
[] (render_container &ctnr, float x1, float y1, float x2, float y2, std::optional<uint32_t> fgcolor, std::optional<uint32_t> bgcolor)
|
||||||
{
|
{
|
||||||
x1 = std::clamp(x1, 0.0f, 1.0f);
|
x1 = std::clamp(x1, 0.0f, 1.0f);
|
||||||
@ -405,8 +684,9 @@ void lua_engine::initialize_render(sol::table &emu)
|
|||||||
if (!bgcolor)
|
if (!bgcolor)
|
||||||
bgcolor = ui.colors().background_color();
|
bgcolor = ui.colors().background_color();
|
||||||
ui.draw_outlined_box(ctnr, x1, y1, x2, y2, *fgcolor, *bgcolor);
|
ui.draw_outlined_box(ctnr, x1, y1, x2, y2, *fgcolor, *bgcolor);
|
||||||
};
|
});
|
||||||
render_container_type["draw_line"] =
|
render_container_type.set_function(
|
||||||
|
"draw_line",
|
||||||
[] (render_container &ctnr, float x1, float y1, float x2, float y2, std::optional<uint32_t> color)
|
[] (render_container &ctnr, float x1, float y1, float x2, float y2, std::optional<uint32_t> color)
|
||||||
{
|
{
|
||||||
x1 = std::clamp(x1, 0.0f, 1.0f);
|
x1 = std::clamp(x1, 0.0f, 1.0f);
|
||||||
@ -416,8 +696,15 @@ void lua_engine::initialize_render(sol::table &emu)
|
|||||||
if (!color)
|
if (!color)
|
||||||
color = mame_machine_manager::instance()->ui().colors().text_color();
|
color = mame_machine_manager::instance()->ui().colors().text_color();
|
||||||
ctnr.add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(*color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
ctnr.add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(*color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
||||||
};
|
});
|
||||||
render_container_type["draw_text"] =
|
render_container_type.set_function(
|
||||||
|
"draw_quad",
|
||||||
|
[] (render_container &cntr, render_texture_helper const &tex, float x1, float y1, float x2, float y2, std::optional<uint32_t> color)
|
||||||
|
{
|
||||||
|
cntr.add_quad(x1, y1, x2, y2, color ? *color : uint32_t(0xffffffff), tex.texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
|
||||||
|
});
|
||||||
|
render_container_type.set_function(
|
||||||
|
"draw_text",
|
||||||
[] (render_container &ctnr, sol::this_state s, sol::object xobj, float y, char const *msg, std::optional<uint32_t> fgcolor, std::optional<uint32_t> bgcolor)
|
[] (render_container &ctnr, sol::this_state s, sol::object xobj, float y, char const *msg, std::optional<uint32_t> fgcolor, std::optional<uint32_t> bgcolor)
|
||||||
{
|
{
|
||||||
auto justify = ui::text_layout::text_justify::LEFT;
|
auto justify = ui::text_layout::text_justify::LEFT;
|
||||||
@ -453,7 +740,7 @@ void lua_engine::initialize_render(sol::table &emu)
|
|||||||
x, y, (1.0f - x),
|
x, y, (1.0f - x),
|
||||||
justify, ui::text_layout::word_wrapping::WORD,
|
justify, ui::text_layout::word_wrapping::WORD,
|
||||||
mame_ui_manager::OPAQUE_, *fgcolor, *bgcolor);
|
mame_ui_manager::OPAQUE_, *fgcolor, *bgcolor);
|
||||||
};
|
});
|
||||||
render_container_type["user_settings"] = sol::property(&render_container::get_user_settings, &render_container::set_user_settings);
|
render_container_type["user_settings"] = sol::property(&render_container::get_user_settings, &render_container::set_user_settings);
|
||||||
render_container_type["orientation"] = sol::property(
|
render_container_type["orientation"] = sol::property(
|
||||||
&render_container::orientation,
|
&render_container::orientation,
|
||||||
@ -510,6 +797,19 @@ void lua_engine::initialize_render(sol::table &emu)
|
|||||||
|
|
||||||
|
|
||||||
auto render_type = sol().registry().new_usertype<render_manager>("render", sol::no_constructor);
|
auto render_type = sol().registry().new_usertype<render_manager>("render", sol::no_constructor);
|
||||||
|
render_type["texture_alloc"] = sol::overload(
|
||||||
|
[] (render_manager &manager, sol::this_state s, bitmap_helper<bitmap_yuy16>::ptr const &bitmap)
|
||||||
|
{
|
||||||
|
return render_texture_helper(s, manager, bitmap, TEXFORMAT_YUY16);
|
||||||
|
},
|
||||||
|
[] (render_manager &manager, sol::this_state s, bitmap_helper<bitmap_rgb32>::ptr const &bitmap)
|
||||||
|
{
|
||||||
|
return render_texture_helper(s, manager, bitmap, TEXFORMAT_RGB32);
|
||||||
|
},
|
||||||
|
[] (render_manager &manager, sol::this_state s, bitmap_helper<bitmap_argb32>::ptr const &bitmap)
|
||||||
|
{
|
||||||
|
return render_texture_helper(s, manager, bitmap, TEXFORMAT_ARGB32);
|
||||||
|
});
|
||||||
render_type["max_update_rate"] = sol::property(&render_manager::max_update_rate);
|
render_type["max_update_rate"] = sol::property(&render_manager::max_update_rate);
|
||||||
render_type["ui_target"] = sol::property(&render_manager::ui_target);
|
render_type["ui_target"] = sol::property(&render_manager::ui_target);
|
||||||
render_type["ui_container"] = sol::property(&render_manager::ui_container);
|
render_type["ui_container"] = sol::property(&render_manager::ui_container);
|
||||||
|
@ -36,7 +36,7 @@ inline int32_t bitmap_t::compute_rowpixels(int width, int xslop)
|
|||||||
|
|
||||||
inline void bitmap_t::compute_base(int xslop, int yslop)
|
inline void bitmap_t::compute_base(int xslop, int yslop)
|
||||||
{
|
{
|
||||||
m_base = m_alloc.get() + (m_rowpixels * yslop + xslop) * (m_bpp / 8);
|
m_base = &m_alloc[(m_rowpixels * yslop + xslop) * (m_bpp / 8)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -234,24 +234,28 @@ void bitmap_t::allocate(int width, int height, int xslop, int yslop)
|
|||||||
reset();
|
reset();
|
||||||
|
|
||||||
// handle empty requests cleanly
|
// handle empty requests cleanly
|
||||||
if (width <= 0 || height <= 0)
|
if ((0 < width) && (0 < height))
|
||||||
return;
|
{
|
||||||
|
// allocate memory for the bitmap itself
|
||||||
|
int32_t const new_rowpixels = compute_rowpixels(width, xslop);
|
||||||
|
uint32_t const new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8;
|
||||||
|
m_alloc.reset(new (std::nothrow) uint8_t[new_allocbytes]);
|
||||||
|
if (m_alloc)
|
||||||
|
{
|
||||||
|
// initialize fields
|
||||||
|
m_allocbytes = new_allocbytes;
|
||||||
|
m_rowpixels = new_rowpixels;
|
||||||
|
m_width = width;
|
||||||
|
m_height = height;
|
||||||
|
m_cliprect.set(0, width - 1, 0, height - 1);
|
||||||
|
|
||||||
// initialize fields
|
// clear to 0 by default
|
||||||
m_rowpixels = compute_rowpixels(width, xslop);
|
memset(m_alloc.get(), 0, m_allocbytes);
|
||||||
m_width = width;
|
|
||||||
m_height = height;
|
|
||||||
m_cliprect.set(0, width - 1, 0, height - 1);
|
|
||||||
|
|
||||||
// allocate memory for the bitmap itself
|
// compute the base
|
||||||
m_allocbytes = m_rowpixels * (m_height + 2 * yslop) * m_bpp / 8;
|
compute_base(xslop, yslop);
|
||||||
m_alloc.reset(new uint8_t[m_allocbytes]);
|
}
|
||||||
|
}
|
||||||
// clear to 0 by default
|
|
||||||
memset(m_alloc.get(), 0, m_allocbytes);
|
|
||||||
|
|
||||||
// compute the base
|
|
||||||
compute_base(xslop, yslop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,12 +278,12 @@ void bitmap_t::resize(int width, int height, int xslop, int yslop)
|
|||||||
assert(m_bpp == 8 || m_bpp == 16 || m_bpp == 32 || m_bpp == 64);
|
assert(m_bpp == 8 || m_bpp == 16 || m_bpp == 32 || m_bpp == 64);
|
||||||
|
|
||||||
// handle empty requests cleanly
|
// handle empty requests cleanly
|
||||||
if (width <= 0 || height <= 0)
|
if ((width <= 0) || (height <= 0))
|
||||||
width = height = 0;
|
width = height = 0;
|
||||||
|
|
||||||
// determine how much memory we need for the new bitmap
|
// determine how much memory we need for the new bitmap
|
||||||
int new_rowpixels = compute_rowpixels(width, xslop);
|
int32_t const new_rowpixels = compute_rowpixels(width, xslop);
|
||||||
uint32_t new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8;
|
uint32_t const new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8;
|
||||||
|
|
||||||
if (new_allocbytes > m_allocbytes)
|
if (new_allocbytes > m_allocbytes)
|
||||||
{
|
{
|
||||||
@ -290,7 +294,6 @@ void bitmap_t::resize(int width, int height, int xslop, int yslop)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
// otherwise, reconfigure
|
// otherwise, reconfigure
|
||||||
m_rowpixels = new_rowpixels;
|
m_rowpixels = new_rowpixels;
|
||||||
m_width = width;
|
m_width = width;
|
||||||
@ -318,6 +321,7 @@ void bitmap_t::reset()
|
|||||||
m_base = nullptr;
|
m_base = nullptr;
|
||||||
|
|
||||||
// reset all fields
|
// reset all fields
|
||||||
|
m_allocbytes = 0;
|
||||||
m_rowpixels = 0;
|
m_rowpixels = 0;
|
||||||
m_width = 0;
|
m_width = 0;
|
||||||
m_height = 0;
|
m_height = 0;
|
||||||
@ -339,6 +343,9 @@ void bitmap_t::reset()
|
|||||||
|
|
||||||
void bitmap_t::wrap(void *base, int width, int height, int rowpixels)
|
void bitmap_t::wrap(void *base, int width, int height, int rowpixels)
|
||||||
{
|
{
|
||||||
|
assert(base || (!width && !height));
|
||||||
|
assert(!m_alloc || (&m_alloc[0] > base) || (&m_alloc[m_allocbytes] <= base));
|
||||||
|
|
||||||
// delete any existing stuff
|
// delete any existing stuff
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
@ -364,6 +371,7 @@ void bitmap_t::wrap(void *base, int width, int height, int rowpixels)
|
|||||||
|
|
||||||
void bitmap_t::wrap(bitmap_t &source, const rectangle &subrect)
|
void bitmap_t::wrap(bitmap_t &source, const rectangle &subrect)
|
||||||
{
|
{
|
||||||
|
assert(&source != this);
|
||||||
assert(m_format == source.m_format);
|
assert(m_format == source.m_format);
|
||||||
assert(m_bpp == source.m_bpp);
|
assert(m_bpp == source.m_bpp);
|
||||||
assert(source.cliprect().contains(subrect));
|
assert(source.cliprect().contains(subrect));
|
||||||
|
Loading…
Reference in New Issue
Block a user