summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author David W Plummer <davepl@davepl.com>2026-02-09 10:26:40 -0800
committer GitHub <noreply@github.com>2026-02-09 19:26:40 +0100
commit6b6fd5cdce494fb7474f79cf0c8eba14982190d2 (patch)
treede6b387b861fc4946ce34964641313b51dedb60d /src
parentd24b0cf898d1759c746593af1c9d461705c5d6a8 (diff)
Added LUA bindings for vector-screen interfaces.
- screen.cpp: Added a callback mechanism to expose vector drawing to the LUA interface, allowing external hardware devices to interface with MAME's vector rendering code. [Dave Plummer]
Diffstat (limited to 'src')
-rw-r--r--src/devices/video/vector.cpp38
-rw-r--r--src/devices/video/vector.h27
-rw-r--r--src/frontend/mame/luaengine.cpp32
3 files changed, 97 insertions, 0 deletions
diff --git a/src/devices/video/vector.cpp b/src/devices/video/vector.cpp
index aa0210eda28..9c0bb682d32 100644
--- a/src/devices/video/vector.cpp
+++ b/src/devices/video/vector.cpp
@@ -60,6 +60,10 @@ float vector_options::s_beam_width_max = 0.0f;
float vector_options::s_beam_dot_size = 0.0f;
float vector_options::s_beam_intensity_weight = 0.0f;
+namespace {
+ vector_device::hook_callback s_hook_callback;
+}
+
void vector_options::init(emu_options& options)
{
s_beam_width_min = options.beam_width_min();
@@ -147,6 +151,11 @@ void vector_device::clear_list(void)
m_vector_index = 0;
}
+void vector_device::set_hook_callback(hook_callback callback)
+{
+ s_hook_callback = std::move(callback);
+}
+
uint32_t vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
@@ -166,6 +175,12 @@ uint32_t vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma
screen.container().empty();
screen.container().add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(0xff,0x00,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_VECTORBUF(1));
+ if (s_hook_callback)
+ {
+ hook_data begin = { hook_event::FRAME_BEGIN, 0, 0, 0, 0, rgb_t(0xff, 0x00, 0x00, 0x00), 0, visarea.width(), visarea.height() };
+ s_hook_callback(machine(), begin);
+ }
+
for (int i = 0; i < m_vector_index; i++)
{
render_bounds coords;
@@ -199,11 +214,34 @@ uint32_t vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma
flags);
}
+ if (s_hook_callback)
+ {
+ hook_data point_data =
+ {
+ (curpoint->intensity != 0) ? hook_event::LINE_TO : hook_event::MOVE_TO,
+ lastx,
+ lasty,
+ curpoint->x,
+ curpoint->y,
+ curpoint->col,
+ curpoint->intensity,
+ visarea.width(),
+ visarea.height()
+ };
+ s_hook_callback(machine(), point_data);
+ }
+
lastx = curpoint->x;
lasty = curpoint->y;
curpoint++;
}
+ if (s_hook_callback)
+ {
+ hook_data end = { hook_event::FRAME_END, 0, 0, 0, 0, rgb_t(0xff, 0x00, 0x00, 0x00), 0, visarea.width(), visarea.height() };
+ s_hook_callback(machine(), end);
+ }
+
return 0;
}
diff --git a/src/devices/video/vector.h b/src/devices/video/vector.h
index 46731de11a1..bb2c95f62e1 100644
--- a/src/devices/video/vector.h
+++ b/src/devices/video/vector.h
@@ -5,8 +5,11 @@
#pragma once
+#include <functional>
+
class vector_device;
+class running_machine;
class vector_options
{
@@ -30,11 +33,35 @@ public:
template <typename T> static constexpr rgb_t color222(T c) { return rgb_t(pal2bit(c >> 4), pal2bit(c >> 2), pal2bit(c >> 0)); }
template <typename T> static constexpr rgb_t color444(T c) { return rgb_t(pal4bit(c >> 8), pal4bit(c >> 4), pal4bit(c >> 0)); }
+ enum class hook_event
+ {
+ FRAME_BEGIN,
+ MOVE_TO,
+ LINE_TO,
+ FRAME_END
+ };
+
+ struct hook_data
+ {
+ hook_event event;
+ int x0;
+ int y0;
+ int x1;
+ int y1;
+ rgb_t color;
+ int intensity;
+ int width;
+ int height;
+ };
+
+ using hook_callback = std::function<void (running_machine &, hook_data const &)>;
+
// construction/destruction
vector_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
void clear_list();
+ static void set_hook_callback(hook_callback callback);
void add_point(int x, int y, rgb_t color, int intensity);
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index 17bdc819538..bacb788c54f 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -17,6 +17,7 @@
#include "ui/ui.h"
#include "imagedev/cassette.h"
+#include "video/vector.h"
#include "debugger.h"
#include "drivenum.h"
@@ -818,6 +819,10 @@ void lua_engine::initialize()
* emu.register_frame_done(callback) - register callback after frame is drawn to screen (for overlays)
* emu.register_sound_update(callback) - register callback after sound update has generated new samples
* emu.register_periodic(callback) - register periodic callback while program is running
+ * emu.register_vector_begin(callback) - register callback before each vector screen render
+ * emu.register_vector_move_to(callback) - register callback for each vector move operation
+ * emu.register_vector_line_to(callback) - register callback for each vector line operation
+ * emu.register_vector_end(callback) - register callback after each vector screen render
* emu.register_callback(callback, name) - register callback to be used by MAME via lua_engine::call_plugin()
* emu.register_menu(event_callback, populate_callback, name) - register callbacks for plugin menu
* emu.register_mandatory_file_manager_override(callback) - register callback invoked to override mandatory file manager
@@ -831,6 +836,28 @@ void lua_engine::initialize()
*/
sol::table emu = sol().create_named_table("emu");
+ vector_device::set_hook_callback(
+ [this] (running_machine &machine, vector_device::hook_data const &data)
+ {
+ if (!m_machine || (&machine != m_machine))
+ return;
+
+ switch (data.event)
+ {
+ case vector_device::hook_event::FRAME_BEGIN:
+ execute_function("LUA_ON_VECTOR_BEGIN", data.width, data.height);
+ break;
+ case vector_device::hook_event::MOVE_TO:
+ execute_function("LUA_ON_VECTOR_MOVE_TO", data.x1, data.y1);
+ break;
+ case vector_device::hook_event::LINE_TO:
+ execute_function("LUA_ON_VECTOR_LINE_TO", data.x0, data.y0, data.x1, data.y1, data.intensity, uint32_t(data.color));
+ break;
+ case vector_device::hook_event::FRAME_END:
+ execute_function("LUA_ON_VECTOR_END");
+ break;
+ }
+ });
emu["wait"] = sol::yielding(
[this] (sol::this_state s, sol::object duration, sol::variadic_args args)
{
@@ -940,6 +967,10 @@ void lua_engine::initialize()
emu["register_frame_done"] = [this] (sol::function func) { register_function(func, "LUA_ON_FRAME_DONE"); };
emu["register_sound_update"] = [this] (sol::function func) { register_function(func, "LUA_ON_SOUND_UPDATE"); };
emu["register_periodic"] = [this] (sol::function func) { register_function(func, "LUA_ON_PERIODIC"); };
+ emu["register_vector_begin"] = [this] (sol::function func) { register_function(func, "LUA_ON_VECTOR_BEGIN"); };
+ emu["register_vector_move_to"] = [this] (sol::function func) { register_function(func, "LUA_ON_VECTOR_MOVE_TO"); };
+ emu["register_vector_line_to"] = [this] (sol::function func) { register_function(func, "LUA_ON_VECTOR_LINE_TO"); };
+ emu["register_vector_end"] = [this] (sol::function func) { register_function(func, "LUA_ON_VECTOR_END"); };
emu["register_mandatory_file_manager_override"] = [this] (sol::function func) { register_function(func, "LUA_ON_MANDATORY_FILE_MANAGER_OVERRIDE"); };
emu["register_before_load_settings"] = [this](sol::function func) { register_function(func, "LUA_ON_BEFORE_LOAD_SETTINGS"); };
emu["register_menu"] =
@@ -2266,6 +2297,7 @@ bool lua_engine::frame_hook()
void lua_engine::close()
{
+ vector_device::set_hook_callback(vector_device::hook_callback());
m_notifiers.reset();
m_menu.clear();
m_update_tasks.clear();