summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2022-08-23 05:01:26 +1000
committer Vas Crabb <vas@vastheman.com>2022-08-23 05:01:26 +1000
commit53d32b27d14738140e1b3488c86819385c3c8f71 (patch)
tree8cef00323db75b1619a37e97e048cee2febce09b
parent7bd9db575b27db74e8bee8bd3ed4517b0e21b414 (diff)
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.
-rw-r--r--docs/source/techspecs/luareference.rst420
-rw-r--r--src/frontend/mame/luaengine.cpp53
-rw-r--r--src/frontend/mame/luaengine_render.cpp320
-rw-r--r--src/lib/util/bitmap.cpp54
4 files changed, 800 insertions, 47 deletions
diff --git a/docs/source/techspecs/luareference.rst b/docs/source/techspecs/luareference.rst
index e2e33b362f0..8e1f4151936 100644
--- a/docs/source/techspecs/luareference.rst
+++ b/docs/source/techspecs/luareference.rst
@@ -305,6 +305,9 @@ machine.hard_reset_pending (read-only)
machine.devices (read-only)
A :ref:`device enumerator <luareference-dev-enum>` that yields all
: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)
A :ref:`device enumerator <luareference-dev-enum>` that yields all
:ref:`screen devices <luareference-dev-screen>` in the emulated system.
@@ -725,6 +728,9 @@ Instantiation
manager.machine.devices
Returns a device enumerator that will iterate over
: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
Returns a device enumerator that will iterate over
: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
iterate below the specified device (i.e. 1 will limit iteration to the
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])
Returns a device enumerator that will iterate over
: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
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:
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
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, [color])
- Draws a line from (x1, y1) to (x2, y2).
+screen:draw_line(x0, y0, x1, y1, [color])
+ Draws a line from (x0, y0) to (x1, y1).
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
@@ -1016,6 +1113,10 @@ screen.frame_number (read-only)
screen.container (read-only)
The :ref:`render container <luareference-render-container>` used to draw the
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:
@@ -2596,6 +2697,276 @@ color.b (read/write)
Blue channel value, in the range of zero (0, off) to one (1, full
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:
Render manager
@@ -2610,6 +2981,16 @@ Instantiation
manager.machine.render
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
^^^^^^^^^^
@@ -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),
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.
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
provided, the UI text colour is used; if the fill colour is not provided,
the UI background colour is used.
-container:draw_line(x1, y1, x2, y2, [color])
- Draws a line from (x1, y1) to (x2, y2).
+container:draw_line(x0, y0, x1, y1, [color])
+ Draws a line from (x0, y0) to (x1, y1).
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
- 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.
- 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.
@@ -2751,6 +3125,24 @@ container:draw_line(x1, y1, x2, y2, [color])
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.
+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])
Draws text at the specified position. If the screen is rotated the text
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),
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.
The foreground and background colours are in alpha/red/green/blue (ARGB)
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 43449a62184..1d0bfca5e76 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -720,6 +720,9 @@ void lua_engine::initialize()
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["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(
[] (device_t &dev) { return devenum<screen_device_enumerator>(dev); },
[] (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["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["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["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()); });
@@ -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>(
"screen_dev",
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_number"] = &screen_device::frame_number;
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>(
diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp
index 893412a4b30..ed56d7470b2 100644
--- a/src/frontend/mame/luaengine_render.cpp
+++ b/src/frontend/mame/luaengine_render.cpp
@@ -17,11 +17,181 @@
#include "render.h"
#include "rendlay.h"
+#include <atomic>
#include <iterator>
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
{
layout_file_views(layout_file &f) : file(f) { }
@@ -54,6 +224,84 @@ struct render_target_view_names
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 &registry, 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
@@ -226,9 +474,9 @@ void lua_engine::initialize_render(sol::table &emu)
sol::call_constructor, sol::initializers(
[] (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 }; }));
- bounds_type["includes"] = &render_bounds::includes;
- bounds_type["set_xy"] = &render_bounds::set_xy;
- bounds_type["set_wh"] = &render_bounds::set_wh;
+ bounds_type.set_function("includes", &render_bounds::includes);
+ bounds_type.set_function("set_xy", &render_bounds::set_xy);
+ bounds_type.set_function("set_wh", &render_bounds::set_wh);
bounds_type["x0"] = &render_bounds::x0;
bounds_type["y0"] = &render_bounds::y0;
bounds_type["x1"] = &render_bounds::x1;
@@ -243,13 +491,43 @@ void lua_engine::initialize_render(sol::table &emu)
sol::call_constructor, sol::initializers(
[] (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 }; }));
- color_type["set"] = &render_color::set;
+ color_type.set_function("set", &render_color::set);
color_type["a"] = &render_color::a;
color_type["r"] = &render_color::r;
color_type["g"] = &render_color::g;
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);
layout_view_type["has_screen"] = &layout_view::has_screen;
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);
- 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)
{
x1 = std::clamp(x1, 0.0f, 1.0f);
@@ -405,8 +684,9 @@ void lua_engine::initialize_render(sol::table &emu)
if (!bgcolor)
bgcolor = ui.colors().background_color();
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)
{
x1 = std::clamp(x1, 0.0f, 1.0f);
@@ -416,8 +696,15 @@ void lua_engine::initialize_render(sol::table &emu)
if (!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));
- };
- 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)
{
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),
justify, ui::text_layout::word_wrapping::WORD,
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["orientation"] = sol::property(
&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);
+ 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["ui_target"] = sol::property(&render_manager::ui_target);
render_type["ui_container"] = sol::property(&render_manager::ui_container);
diff --git a/src/lib/util/bitmap.cpp b/src/lib/util/bitmap.cpp
index 8757d928fff..5f4d2adfacb 100644
--- a/src/lib/util/bitmap.cpp
+++ b/src/lib/util/bitmap.cpp
@@ -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)
{
- 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();
// handle empty requests cleanly
- if (width <= 0 || height <= 0)
- return;
-
- // initialize fields
- m_rowpixels = compute_rowpixels(width, xslop);
- m_width = width;
- m_height = height;
- m_cliprect.set(0, width - 1, 0, height - 1);
-
- // allocate memory for the bitmap itself
- m_allocbytes = m_rowpixels * (m_height + 2 * yslop) * m_bpp / 8;
- 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);
+ if ((0 < width) && (0 < height))
+ {
+ // 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);
+
+ // 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);
// handle empty requests cleanly
- if (width <= 0 || height <= 0)
+ if ((width <= 0) || (height <= 0))
width = height = 0;
// determine how much memory we need for the new bitmap
- int new_rowpixels = compute_rowpixels(width, xslop);
- uint32_t new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8;
+ int32_t const new_rowpixels = compute_rowpixels(width, xslop);
+ uint32_t const new_allocbytes = new_rowpixels * (height + 2 * yslop) * m_bpp / 8;
if (new_allocbytes > m_allocbytes)
{
@@ -290,7 +294,6 @@ void bitmap_t::resize(int width, int height, int xslop, int yslop)
}
else
{
-
// otherwise, reconfigure
m_rowpixels = new_rowpixels;
m_width = width;
@@ -318,6 +321,7 @@ void bitmap_t::reset()
m_base = nullptr;
// reset all fields
+ m_allocbytes = 0;
m_rowpixels = 0;
m_width = 0;
m_height = 0;
@@ -339,6 +343,9 @@ void bitmap_t::reset()
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
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)
{
+ assert(&source != this);
assert(m_format == source.m_format);
assert(m_bpp == source.m_bpp);
assert(source.cliprect().contains(subrect));