summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author MooglyGuy <MooglyGuy@users.noreply.github.com>2026-02-19 17:45:26 +0100
committer GitHub <noreply@github.com>2026-02-20 03:45:26 +1100
commit57cf10f09f79fab5fef3544bca98aeca6eadcfe3 (patch)
tree0478fd0e05bb52363b4247161b17a6cdfe1e05a2 /src
parent644147eb50a94c33ee1307c5fe903b4b8cf90d11 (diff)
video/vector.cpp, frontend/mame/luaengine.cpp: Refactored recently-added Lua hooks for vector devices. (#14991)
Diffstat (limited to 'src')
-rw-r--r--src/devices/video/vector.cpp154
-rw-r--r--src/devices/video/vector.h66
-rw-r--r--src/frontend/mame/luaengine.cpp96
3 files changed, 180 insertions, 136 deletions
diff --git a/src/devices/video/vector.cpp b/src/devices/video/vector.cpp
index 9c0bb682d32..8e499bf56bc 100644
--- a/src/devices/video/vector.cpp
+++ b/src/devices/video/vector.cpp
@@ -2,31 +2,11 @@
// copyright-holders:Brad Oliver,Aaron Giles,Bernd Wiebelt,Allard van der Bas
/******************************************************************************
*
- * vector.c
+ * vector.cpp
*
* anti-alias code by Andrew Caldwell
* (still more to add)
*
- * 040227 Fixed miny clip scaling which was breaking in mhavoc. AREK
- * 010903 added support for direct RGB modes MLR
- * 980611 use translucent vectors. Thanks to Peter Hirschberg
- * and Neil Bradley for the inspiration. BW
- * 980307 added cleverer dirty handling. BW, ASG
- * fixed antialias table .ac
- * 980221 rewrote anti-alias line draw routine
- * added inline assembly multiply fuction for 8086 based machines
- * beam diameter added to draw routine
- * beam diameter is accurate in anti-alias line draw (Tcosin)
- * flicker added .ac
- * 980203 moved LBO's routines for drawing into a buffer of vertices
- * from avgdvg.c to this location. Scaling is now initialized
- * by calling vector_init(...). BW
- * 980202 moved out of msdos.c ASG
- * 980124 added anti-alias line draw routine
- * modified avgdvg.c and sega.c to support new line draw routine
- * added two new tables Tinten and Tmerge (for 256 color support)
- * added find_color routine to build above tables .ac
- *
* Vector Team
*
* Brad Oliver
@@ -60,11 +40,7 @@ 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)
+void vector_options::init(emu_options &options)
{
s_beam_width_min = options.beam_width_min();
s_beam_width_max = options.beam_width_max();
@@ -95,9 +71,51 @@ void vector_device::device_start()
m_vector_list = std::make_unique<point[]>(MAX_POINTS);
}
-/*
- * www.dinodini.wordpress.com/2010/04/05/normalized-tunable-sigmoid-functions/
- */
+
+//-------------------------------------------------
+// subscribe for frame-begin notifications
+//-------------------------------------------------
+
+util::notifier_subscription vector_device::add_frame_begin_notifier(frame_begin_delegate &&n)
+{
+ return m_frame_begin_notifier.subscribe(std::move(n));
+}
+
+
+//-------------------------------------------------
+// subscribe for frame-end notifications
+//-------------------------------------------------
+
+util::notifier_subscription vector_device::add_frame_end_notifier(frame_end_delegate &&n)
+{
+ return m_frame_end_notifier.subscribe(std::move(n));
+}
+
+
+//-------------------------------------------------
+// subscribe for hidden-move notifications
+//-------------------------------------------------
+
+util::notifier_subscription vector_device::add_move_notifier(move_delegate &&n)
+{
+ return m_move_notifier.subscribe(std::move(n));
+}
+
+
+//-------------------------------------------------
+// subscribe for visible-line notifications
+//-------------------------------------------------
+
+util::notifier_subscription vector_device::add_line_notifier(line_delegate &&n)
+{
+ return m_line_notifier.subscribe(std::move(n));
+}
+
+
+//-------------------------------------------------
+// www.dinodini.wordpress.com/2010/04/05/normalized-tunable-sigmoid-functions/
+//-------------------------------------------------
+
float vector_device::normalized_sigmoid(float n, float k)
{
// valid for n and k in range of -1.0 and 1.0
@@ -105,10 +123,11 @@ float vector_device::normalized_sigmoid(float n, float k)
}
-/*
- * Adds a line end point to the vertices list. The vector processor emulation
- * needs to call this.
- */
+//-------------------------------------------------
+// Adds a line end point to the vertices list. The vector processor emulation
+// needs to call this.
+//-------------------------------------------------
+
void vector_device::add_point(int x, int y, rgb_t color, int intensity)
{
point *newpoint;
@@ -120,9 +139,9 @@ void vector_device::add_point(int x, int y, rgb_t color, int intensity)
if (vector_options::s_flicker && (intensity > 0))
{
- float random = (float)(machine().rand() & 255) / 255.0f; // random value between 0.0 and 1.0
+ float random = float(machine().rand() & 255) / 255.0f; // random value between 0.0 and 1.0
- intensity -= (int)(intensity * random * vector_options::s_flicker);
+ intensity -= int(intensity * random * vector_options::s_flicker);
intensity = std::clamp(intensity, 0, 255);
}
@@ -142,20 +161,19 @@ void vector_device::add_point(int x, int y, rgb_t color, int intensity)
}
-/*
- * The vector CPU creates a new display list. We save the old display list,
- * but only once per refresh.
- */
-void vector_device::clear_list(void)
-{
- m_vector_index = 0;
-}
+//-------------------------------------------------
+// The vector CPU creates a new display list. We save the old display list,
+// but only once per refresh.
+//-------------------------------------------------
-void vector_device::set_hook_callback(hook_callback callback)
+void vector_device::clear_list()
{
- s_hook_callback = std::move(callback);
+ m_vector_index = 0;
}
+//-------------------------------------------------
+// Update the screen container with queued vectors.
+//-------------------------------------------------
uint32_t vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
@@ -175,11 +193,7 @@ 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);
- }
+ m_frame_begin_notifier();
for (int i = 0; i < m_vector_index; i++)
{
@@ -200,35 +214,23 @@ uint32_t vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma
if (lastx == curpoint->x && lasty == curpoint->y)
beam_width *= vector_options::s_beam_dot_size;
- coords.x0 = ((float)lastx - xoffs) * xscale;
- coords.y0 = ((float)lasty - yoffs) * yscale;
- coords.x1 = ((float)curpoint->x - xoffs) * xscale;
- coords.y1 = ((float)curpoint->y - yoffs) * yscale;
+ coords.x0 = (float(lastx) - xoffs) * xscale;
+ coords.y0 = (float(lasty) - yoffs) * yscale;
+ coords.x1 = (float(curpoint->x) - xoffs) * xscale;
+ coords.y1 = (float(curpoint->y) - yoffs) * yscale;
if (curpoint->intensity != 0)
{
screen.container().add_line(
- coords.x0, coords.y0, coords.x1, coords.y1,
- beam_width,
- (curpoint->intensity << 24) | (curpoint->col & 0xffffff),
- flags);
+ coords.x0, coords.y0, coords.x1, coords.y1,
+ beam_width,
+ (curpoint->intensity << 24) | (curpoint->col & 0xffffff),
+ flags);
+ m_line_notifier(lastx, lasty, curpoint->x, curpoint->y, curpoint->col, curpoint->intensity, visarea.width(), visarea.height());
}
-
- if (s_hook_callback)
+ else
{
- 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);
+ m_move_notifier(curpoint->x, curpoint->y, curpoint->col, visarea.width(), visarea.height());
}
lastx = curpoint->x;
@@ -237,11 +239,7 @@ uint32_t vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitma
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);
- }
+ m_frame_end_notifier();
return 0;
}
diff --git a/src/devices/video/vector.h b/src/devices/video/vector.h
index bb2c95f62e1..b98bd026b2b 100644
--- a/src/devices/video/vector.h
+++ b/src/devices/video/vector.h
@@ -5,11 +5,12 @@
#pragma once
-#include <functional>
+#include "notifier.h"
+
+#include <utility>
class vector_device;
-class running_machine;
class vector_options
{
@@ -29,46 +30,50 @@ protected:
class vector_device : public device_t, public device_video_interface
{
public:
+ using frame_begin_delegate = delegate<void ()>;
+ using frame_end_delegate = delegate<void ()>;
+ using move_delegate = delegate<void (int, int, uint32_t, int, int)>;
+ using line_delegate = delegate<void (int, int, int, int, uint32_t, int, int, int)>;
+
template <typename T> static constexpr rgb_t color111(T c) { return rgb_t(pal1bit(c >> 2), pal1bit(c >> 1), pal1bit(c >> 0)); }
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);
// device-level overrides
virtual void device_start() override ATTR_COLD;
+ // notifiers
+ util::notifier_subscription add_frame_begin_notifier(frame_begin_delegate &&n);
+ template <typename T>
+ util::notifier_subscription add_frame_begin_notifier(T &&n)
+ { return add_frame_begin_notifier(frame_begin_delegate(std::forward<T>(n))); }
+
+ util::notifier_subscription add_frame_end_notifier(frame_end_delegate &&n);
+ template <typename T>
+ util::notifier_subscription add_frame_end_notifier(T &&n)
+ { return add_frame_end_notifier(frame_end_delegate(std::forward<T>(n))); }
+
+ util::notifier_subscription add_move_notifier(move_delegate &&n);
+ template <typename T>
+ util::notifier_subscription add_move_notifier(T &&n)
+ { return add_move_notifier(move_delegate(std::forward<T>(n))); }
+
+ util::notifier_subscription add_line_notifier(line_delegate &&n);
+ template <typename T>
+ util::notifier_subscription add_line_notifier(T &&n)
+ { return add_line_notifier(line_delegate(std::forward<T>(n))); }
+
private:
+ float normalized_sigmoid(float n, float k);
+
/* The vertices are buffered here */
struct point
{
@@ -84,10 +89,17 @@ private:
int m_min_intensity;
int m_max_intensity;
- float normalized_sigmoid(float n, float k);
+ // notify interested parties about vector-drawing activities
+ util::notifier<> m_frame_begin_notifier;
+ util::notifier<> m_frame_end_notifier;
+ util::notifier<int, int, uint32_t, int, int> m_move_notifier;
+ util::notifier<int, int, int, int, uint32_t, int, int, int> m_line_notifier;
};
// device type definition
DECLARE_DEVICE_TYPE(VECTOR, vector_device)
+// device iterator
+typedef device_type_enumerator<vector_device> vector_device_enumerator;
+
#endif // MAME_VIDEO_VECTOR_H
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index bacb788c54f..d0c01053c55 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -819,10 +819,6 @@ 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
@@ -836,28 +832,6 @@ 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)
{
@@ -967,10 +941,6 @@ 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"] =
@@ -1024,6 +994,9 @@ void lua_engine::initialize()
emu["slot_enumerator"] = sol::overload(
[] (device_t &dev) { return devenum<slot_interface_enumerator>(dev); },
[] (device_t &dev, int maxdepth) { return devenum<slot_interface_enumerator>(dev, maxdepth); });
+ emu["vector_device_enumerator"] = sol::overload(
+ [] (device_t &dev) { return devenum<vector_device_enumerator>(dev); },
+ [] (device_t &dev, int maxdepth) { return devenum<vector_device_enumerator>(dev, maxdepth); });
auto notifier_subscription_type = sol().registry().new_usertype<util::notifier_subscription>("notifier_subscription", sol::no_constructor);
@@ -1527,6 +1500,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["vector_devices"] = sol::property([] (running_machine &m) { return devenum<vector_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()); });
@@ -1938,6 +1912,67 @@ void lua_engine::initialize()
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 vector_dev_type = sol().registry().new_usertype<vector_device>(
+ "vector_dev",
+ sol::no_constructor,
+ sol::base_classes, sol::bases<device_t, device_video_interface>());
+ vector_dev_type.set_function("add_frame_begin_notifier",
+ [this] (vector_device &v, sol::protected_function cb)
+ {
+ return v.add_frame_begin_notifier(
+ [this, cbfunc = sol::protected_function(m_lua_state, cb)] (void)
+ {
+ auto status(invoke(cbfunc));
+ if (!status.valid())
+ {
+ auto err(status.template get<sol::error>());
+ osd_printf_error("[LUA ERROR] error in vector frame-begin callback: %s\n", err.what());
+ }
+ });
+ });
+ vector_dev_type.set_function("add_frame_end_notifier",
+ [this] (vector_device &v, sol::protected_function cb)
+ {
+ return v.add_frame_end_notifier(
+ [this, cbfunc = sol::protected_function(m_lua_state, cb)] (void)
+ {
+ auto status(invoke(cbfunc));
+ if (!status.valid())
+ {
+ auto err(status.template get<sol::error>());
+ osd_printf_error("[LUA ERROR] error in vector frame-end callback: %s\n", err.what());
+ }
+ });
+ });
+ vector_dev_type.set_function("add_move_notifier",
+ [this] (vector_device &v, sol::protected_function cb)
+ {
+ return v.add_move_notifier(
+ [this, cbfunc = sol::protected_function(m_lua_state, cb)] (int x, int y, uint32_t color, int vis_x, int vis_y)
+ {
+ auto status(invoke(cbfunc, x / 65536.0, y / 65536.0, color, vis_x, vis_y));
+ if (!status.valid())
+ {
+ auto err(status.template get<sol::error>());
+ osd_printf_error("[LUA ERROR] error in vector move callback: %s\n", err.what());
+ }
+ });
+ });
+ vector_dev_type.set_function("add_line_notifier",
+ [this] (vector_device &v, sol::protected_function cb)
+ {
+ return v.add_line_notifier(
+ [this, cbfunc = sol::protected_function(m_lua_state, cb)] (int prev_x, int prev_y, int x, int y, uint32_t color, int intensity, int vis_x, int vis_y)
+ {
+ auto status(invoke(cbfunc, prev_x / 65536.0, prev_y / 65536.0, x / 65536.0, y / 65536.0, color, intensity, vis_x, vis_y));
+ if (!status.valid())
+ {
+ auto err(status.template get<sol::error>());
+ osd_printf_error("[LUA ERROR] error in vector line callback: %s\n", err.what());
+ }
+ });
+ });
+
auto cass_type = sol().registry().new_usertype<cassette_image_device>(
"cassette",
@@ -2297,7 +2332,6 @@ 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();