summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/luaengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/luaengine.cpp')
-rw-r--r--src/emu/luaengine.cpp663
1 files changed, 656 insertions, 7 deletions
diff --git a/src/emu/luaengine.cpp b/src/emu/luaengine.cpp
index 62667ee0eef..b1ebf60d88a 100644
--- a/src/emu/luaengine.cpp
+++ b/src/emu/luaengine.cpp
@@ -16,10 +16,14 @@
#include "emu.h"
#include "cheat.h"
#include "drivenum.h"
+#include "emuopts.h"
#include "ui/ui.h"
#include "luaengine.h"
#include <mutex>
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wshift-count-overflow"
+#endif
//**************************************************************************
// LUA ENGINE
//**************************************************************************
@@ -108,6 +112,93 @@ int lua_engine::docall(int narg, int nres)
return status;
}
+namespace luabridge
+{
+template <>
+struct Stack <osd_file::error>
+{
+ static void push(lua_State *L, osd_file::error error)
+ {
+ std::string strerror;
+ switch(error)
+ {
+ case osd_file::error::NONE:
+ lua_pushboolean(L, false);
+ return;
+ case osd_file::error::FAILURE:
+ strerror = "failure";
+ break;
+ case osd_file::error::OUT_OF_MEMORY:
+ strerror = "out_of_memory";
+ break;
+ case osd_file::error::NOT_FOUND:
+ strerror = "not_found";
+ break;
+ case osd_file::error::ACCESS_DENIED:
+ strerror = "access_denied";
+ break;
+ case osd_file::error::ALREADY_OPEN:
+ strerror = "already_open";
+ break;
+ case osd_file::error::TOO_MANY_FILES:
+ strerror = "too_many_files";
+ break;
+ case osd_file::error::INVALID_DATA:
+ strerror = "invalid_data";
+ break;
+ case osd_file::error::INVALID_ACCESS:
+ strerror = "invalid_access";
+ break;
+ default:
+ strerror = "unknown_error";
+ break;
+ }
+ lua_pushstring(L, strerror.c_str());
+ }
+};
+template <>
+struct Stack <map_handler_type>
+{
+ static void push(lua_State *L, map_handler_type error)
+ {
+ std::string type;
+ switch(error)
+ {
+ case AMH_NONE:
+ type = "none";
+ break;
+ case AMH_RAM:
+ type = "ram";
+ break;
+ case AMH_ROM:
+ type = "rom";
+ break;
+ case AMH_NOP:
+ type = "nop";
+ break;
+ case AMH_UNMAP:
+ type = "unmap";
+ break;
+ case AMH_DEVICE_DELEGATE:
+ type = "delegate";
+ break;
+ case AMH_PORT:
+ type = "port";
+ break;
+ case AMH_BANK:
+ type = "bank";
+ break;
+ case AMH_DEVICE_SUBMAP:
+ type = "submap";
+ break;
+ default:
+ type = "unknown";
+ break;
+ }
+ lua_pushstring(L, type.c_str());
+ }
+};
+}
/* mark in error messages for incomplete statements */
#define EOFMARK "<eof>"
#define marklen (sizeof(EOFMARK)/sizeof(char) - 1)
@@ -447,6 +538,61 @@ luabridge::LuaRef lua_engine::l_machine_get_devices(const running_machine *r)
}
//-------------------------------------------------
+// machine_get_images - return table of available image devices userdata
+// -> manager:machine().images["flop1"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_machine_get_images(const running_machine *r)
+{
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef image_table = luabridge::LuaRef::newTable(L);
+
+ image_interface_iterator iter(r->root_device());
+ for (device_image_interface *image = iter.first(); image != nullptr; image = iter.next()) {
+ image_table[image->brief_instance_name()] = image;
+ image_table[image->instance_name()] = image;
+ }
+
+ return image_table;
+}
+
+//-------------------------------------------------
+// memory_banks - return memory_banks
+// -> manager:machine():memory().banks["maincpu"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_memory_get_banks(const memory_manager *m)
+{
+ memory_manager *mm = const_cast<memory_manager *>(m);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef table = luabridge::LuaRef::newTable(L);
+
+ for (memory_bank &bank : mm->banks()) {
+ table[bank.tag()] = &bank;
+ }
+
+ return table;
+}
+
+//-------------------------------------------------
+// memory_regions - return memory_regions
+// -> manager:machine():memory().region[":maincpu"]
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_memory_get_regions(const memory_manager *m)
+{
+ memory_manager *mm = const_cast<memory_manager *>(m);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef table = luabridge::LuaRef::newTable(L);
+
+ for (memory_region &region: mm->regions()) {
+ table[region.name()] = &region;
+ }
+
+ return table;
+}
+
+//-------------------------------------------------
// machine_cheat_entries - return cheat entries
// -> manager:machine():cheat().entries[0]
//-------------------------------------------------
@@ -566,6 +712,9 @@ luabridge::LuaRef lua_engine::l_dev_get_memspaces(const device_t *d)
lua_State *L = luaThis->m_lua_state;
luabridge::LuaRef sp_table = luabridge::LuaRef::newTable(L);
+ if(!&dev->memory())
+ return sp_table;
+
for (address_spacenum sp = AS_0; sp < ADDRESS_SPACES; ++sp) {
if (dev->memory().has_space(sp)) {
sp_table[dev->memory().space(sp).name()] = &(dev->memory().space(sp));
@@ -585,6 +734,10 @@ luabridge::LuaRef lua_engine::l_dev_get_states(const device_t *d)
device_t *dev = const_cast<device_t *>(d);
lua_State *L = luaThis->m_lua_state;
luabridge::LuaRef st_table = luabridge::LuaRef::newTable(L);
+
+ if(!&dev->state())
+ return st_table;
+
for (device_state_entry &s : dev->state().state_entries())
{
// XXX: refrain from exporting non-visible entries?
@@ -595,6 +748,126 @@ luabridge::LuaRef lua_engine::l_dev_get_states(const device_t *d)
}
//-------------------------------------------------
+// device_get_item - return table of indexed items owned by this device
+// -> manager:machine().devices[":maincpu"].items
+//-------------------------------------------------
+
+luabridge::LuaRef lua_engine::l_dev_get_items(const device_t *d)
+{
+ device_t *dev = const_cast<device_t *>(d);
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef table = luabridge::LuaRef::newTable(L);
+ std::string tag = dev->tag();
+
+ // 10000 is enough?
+ for(int i = 0; i < 10000; i++)
+ {
+ std::string name;
+ const char *item;
+ unsigned int size, count;
+ void *base;
+ item = dev->machine().save().indexed_item(i, base, size, count);
+ if(!item)
+ break;
+ name = &(strchr(item, '/')[1]);
+ if(name.substr(0, name.find("/")) == tag)
+ {
+ name = name.substr(name.find("/") + 1, std::string::npos);
+ table[name] = i;
+ }
+ }
+ return table;
+}
+
+lua_engine::lua_item::lua_item(int index)
+{
+ std::string name;
+ const char *item;
+ item = luaThis->machine().save().indexed_item(index, l_item_base, l_item_size, l_item_count);
+ if(!item)
+ {
+ l_item_base = nullptr;
+ l_item_size = 0;
+ l_item_count= 0;
+ }
+}
+
+int lua_engine::lua_item::l_item_read(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "offset (integer) expected");
+ int offset = lua_tounsigned(L, 2);
+ int ret = 0;
+ if(!l_item_base || (offset > l_item_count))
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+ switch(l_item_size)
+ {
+ case 1:
+ default:
+ ret = ((UINT8 *)l_item_base)[offset];
+ break;
+ case 2:
+ ret = ((UINT16 *)l_item_base)[offset];
+ break;
+ case 4:
+ ret = ((UINT32 *)l_item_base)[offset];
+ break;
+ case 8:
+ ret = ((UINT64 *)l_item_base)[offset];
+ break;
+ }
+ lua_pushunsigned(L, ret);
+ return 1;
+}
+
+int lua_engine::lua_item::l_item_write(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "offset (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected");
+ int offset = lua_tounsigned(L, 2);
+ UINT64 value = lua_tounsigned(L, 3);
+ if(!l_item_base || (offset > l_item_count))
+ return 1;
+ switch(l_item_size)
+ {
+ case 1:
+ default:
+ ((UINT8 *)l_item_base)[offset] = (UINT8)value;
+ break;
+ case 2:
+ ((UINT16 *)l_item_base)[offset] = (UINT16)value;
+ break;
+ case 4:
+ ((UINT32 *)l_item_base)[offset] = (UINT32)value;
+ break;
+ case 8:
+ ((UINT64 *)l_item_base)[offset] = (UINT64)value;
+ break;
+ }
+ return 1;
+}
+
+int lua_engine::lua_item::l_item_read_block(lua_State *L)
+{
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "offset (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "length (integer) expected");
+ int offset = lua_tounsigned(L, 2);
+ int len = lua_tonumber(L, 3);
+ if(!l_item_base || ((offset + len) > (l_item_size * l_item_count)))
+ {
+ lua_pushnil(L);
+ return 1;
+ }
+ luaL_Buffer buff;
+ char *ptr = luaL_buffinitsize(L, &buff, len);
+ memcpy(ptr, l_item_base, len);
+ luaL_pushresultsize(&buff, len);
+ return 1;
+}
+
+//-------------------------------------------------
// state_get_value - return value of a device state entry
// -> manager:machine().devices[":maincpu"].state["PC"].value
//-------------------------------------------------
@@ -697,7 +970,7 @@ int lua_engine::lua_addr_space::l_mem_write(lua_State *L)
if (WORD_ALIGNED(address)) {
sp.write_word(address, val);
} else {
- sp.read_word_unaligned(address, val);
+ sp.write_word_unaligned(address, val);
}
break;
case 32:
@@ -721,6 +994,170 @@ int lua_engine::lua_addr_space::l_mem_write(lua_State *L)
return 0;
}
+//-------------------------------------------------
+// mem_direct_read - templated direct memory readers for <sign>,<size>
+// -> manager:machine().devices[":maincpu"].spaces["program"]:read_direct_i8(0xC000)
+//-------------------------------------------------
+
+UINT8 lua_engine::read_direct_byte(address_space &space, offs_t addr)
+{
+ UINT8 *base = (UINT8 *)space.get_read_ptr(space.address_to_byte(addr));
+ if(base)
+ return base[addr];
+ else
+ return 0;
+}
+
+template <typename T>
+int lua_engine::lua_addr_space::l_direct_mem_read(lua_State *L)
+{
+ address_space &sp = luabridge::Stack<address_space &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T mem_content = 0;
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ UINT8 byte;
+ mem_content <<= 8;
+ if(sp.endianness() == ENDIANNESS_BIG)
+ byte = read_direct_byte(sp, address + sizeof(T) - i);
+ else
+ byte = read_direct_byte(sp, address + i);
+ mem_content |= byte;
+ }
+
+ if (std::numeric_limits<T>::is_signed) {
+ lua_pushinteger(L, mem_content);
+ } else {
+ lua_pushunsigned(L, mem_content);
+ }
+
+ return 1;
+}
+
+//-------------------------------------------------
+// mem_direct_write - templated memory writer for <sign>,<size>
+// -> manager:machine().devices[":maincpu"].spaces["program"]:write_direct_u16(0xC000, 0xF00D)
+//-------------------------------------------------
+
+void lua_engine::write_direct_byte(address_space &space, offs_t addr, UINT8 byte)
+{
+ UINT8 *base = (UINT8 *)space.get_read_ptr(space.address_to_byte(addr));
+ if(base)
+ base[addr] = byte;
+}
+
+template <typename T>
+int lua_engine::lua_addr_space::l_direct_mem_write(lua_State *L)
+{
+ address_space &sp = luabridge::Stack<address_space &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T val = lua_tounsigned(L, 3);
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ if(sp.endianness() == ENDIANNESS_BIG)
+ write_direct_byte(sp, address + sizeof(T) - i, val & 0xff);
+ else
+ write_direct_byte(sp, address + i, val & 0xff);
+ val >>= 8;
+ }
+
+ return 0;
+}
+
+//-------------------------------------------------
+// region_read - templated region readers for <sign>,<size>
+// -> manager:machine():memory().region[":maincpu"]:read_i8(0xC000)
+//-------------------------------------------------
+
+UINT8 lua_engine::read_region_byte(memory_region &region, offs_t addr)
+{
+ if(addr >= region.bytes())
+ return 0;
+
+ return region.u8(addr);
+}
+
+template <typename T>
+int lua_engine::lua_memory_region::l_region_read(lua_State *L)
+{
+ memory_region &region = luabridge::Stack<memory_region &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T mem_content = 0;
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ UINT8 byte;
+ mem_content <<= 8;
+ if(region.endianness() == ENDIANNESS_BIG)
+ byte = read_region_byte(region, address + sizeof(T) - i);
+ else
+ byte = read_region_byte(region, address + i);
+ mem_content |= byte;
+ }
+
+ if (std::numeric_limits<T>::is_signed) {
+ lua_pushinteger(L, mem_content);
+ } else {
+ lua_pushunsigned(L, mem_content);
+ }
+
+ return 1;
+}
+
+//-------------------------------------------------
+// region_write - templated region writer for <sign>,<size>
+// -> manager:machine():memory().region[":maincpu"]:write_u16(0xC000, 0xF00D)
+//-------------------------------------------------
+
+void lua_engine::write_region_byte(memory_region &region, offs_t addr, UINT8 byte)
+{
+ if(addr >= region.bytes())
+ return;
+
+ region.base()[addr] = byte;
+}
+
+template <typename T>
+int lua_engine::lua_memory_region::l_region_write(lua_State *L)
+{
+ memory_region &region = luabridge::Stack<memory_region &>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "address (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 3), 3, "value (integer) expected");
+ offs_t address = lua_tounsigned(L, 2);
+ T val = lua_tounsigned(L, 3);
+ for(int i = 0; i < sizeof(T); i++)
+ {
+ if(region.endianness() == ENDIANNESS_BIG)
+ write_region_byte(region, address + sizeof(T) - i, val & 0xff);
+ else
+ write_region_byte(region, address + i, val & 0xff);
+ val >>= 8;
+ }
+
+ return 0;
+}
+
+luabridge::LuaRef lua_engine::l_addr_space_map(const address_space *space)
+{
+ lua_State *L = luaThis->m_lua_state;
+ luabridge::LuaRef map = luabridge::LuaRef::newTable(L);
+
+ int i = 1;
+ for (address_map_entry &entry : space->map()->m_entrylist)
+ {
+ luabridge::LuaRef mapentry = luabridge::LuaRef::newTable(L);
+ mapentry["offset"] = space->address_to_byte(entry.m_addrstart) & space->bytemask();
+ mapentry["endoff"] = space->address_to_byte(entry.m_addrend) & space->bytemask();
+ mapentry["readtype"] = entry.m_read.m_type;
+ mapentry["writetype"] = entry.m_write.m_type;
+ map[i++] = mapentry;
+ }
+ return map;
+}
+
int lua_engine::lua_options_entry::l_entry_value(lua_State *L)
{
core_options::entry *e = luabridge::Stack<core_options::entry *>::get(L, 1);
@@ -968,6 +1405,7 @@ int lua_engine::lua_screen::l_type(lua_State *L)
case SCREEN_TYPE_RASTER: lua_pushliteral(L, "raster"); break;
case SCREEN_TYPE_VECTOR: lua_pushliteral(L, "vector"); break;
case SCREEN_TYPE_LCD: lua_pushliteral(L, "lcd"); break;
+ case SCREEN_TYPE_SVG: lua_pushliteral(L, "svg"); break;
default: lua_pushliteral(L, "unknown"); break;
}
@@ -1049,6 +1487,7 @@ int lua_engine::lua_screen::l_draw_line(lua_State *L)
//-------------------------------------------------
// draw_text - draw text on a screen container
+// if x is a position, then y is a pixel position, otherwise x and y are screen size relative
// -> manager:machine().screens[":screen"]:draw_text(x, y, message)
//-------------------------------------------------
@@ -1060,7 +1499,7 @@ int lua_engine::lua_screen::l_draw_text(lua_State *L)
}
// ensure that we got proper parameters
- luaL_argcheck(L, lua_isnumber(L, 2), 2, "x (integer) expected");
+ luaL_argcheck(L, lua_isnumber(L, 2) || lua_isstring(L, 2), 2, "x (integer or string) expected");
luaL_argcheck(L, lua_isnumber(L, 3), 3, "y (integer) expected");
luaL_argcheck(L, lua_isstring(L, 4), 4, "message (string) expected");
luaL_argcheck(L, lua_isinteger(L, 5) || lua_isnone(L, 5), 5, "optional argument: text color, integer expected (default: 0xffffffff)");
@@ -1068,8 +1507,22 @@ int lua_engine::lua_screen::l_draw_text(lua_State *L)
// retrieve all parameters
int sc_width = sc->visible_area().width();
int sc_height = sc->visible_area().height();
- float x = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width);
- float y = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height);
+ int justify = JUSTIFY_LEFT;
+ float y, x = 0;
+ if(lua_isnumber(L, 2))
+ {
+ x = MIN(MAX(0, (float) lua_tonumber(L, 2)), sc_width-1) / static_cast<float>(sc_width);
+ y = MIN(MAX(0, (float) lua_tonumber(L, 3)), sc_height-1) / static_cast<float>(sc_height);
+ }
+ else
+ {
+ std::string just_str = lua_tostring(L, 2);
+ if(just_str == "right")
+ justify = JUSTIFY_RIGHT;
+ else if(just_str == "center")
+ justify = JUSTIFY_CENTER;
+ y = lua_tonumber(L, 3);
+ }
const char *msg = luaL_checkstring(L,4);
rgb_t textcolor = UI_TEXT_COLOR;
if (!lua_isnone(L, 5)) {
@@ -1079,13 +1532,25 @@ int lua_engine::lua_screen::l_draw_text(lua_State *L)
// draw the text
render_container &rc = sc->container();
ui_manager &ui = sc->machine().ui();
- ui.draw_text_full(&rc, msg, x, y , (1.0f - x),
- JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, textcolor,
+ ui.draw_text_full(&rc, msg, x, y, (1.0f - x),
+ justify, WRAP_WORD, DRAW_NORMAL, textcolor,
UI_TEXT_BG_COLOR, nullptr, nullptr);
return 0;
}
+int lua_engine::lua_emu_file::l_emu_file_read(lua_State *L)
+{
+ emu_file *file = luabridge::Stack<emu_file *>::get(L, 1);
+ luaL_argcheck(L, lua_isnumber(L, 2), 2, "length (integer) expected");
+ int ret, len = lua_tonumber(L, 2);
+ luaL_Buffer buff;
+ char *ptr = luaL_buffinitsize(L, &buff, len);
+ ret = file->read(ptr, len);
+ luaL_pushresultsize(&buff, ret);
+ return 1;
+}
+
void *lua_engine::checkparam(lua_State *L, int idx, const char *tname)
{
const char *name;
@@ -1273,6 +1738,92 @@ lua_engine::~lua_engine()
close();
}
+void lua_engine::menu_populate(std::string &menu, std::vector<menu_item> &menu_list)
+{
+ std::string field = "menu_pop_" + menu;
+ lua_settop(m_lua_state, 0);
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+
+ if(!lua_isfunction(m_lua_state, -1))
+ {
+ lua_pop(m_lua_state, 1);
+ return;
+ }
+ if(int error = lua_pcall(m_lua_state, 0, 1, 0))
+ {
+ if(error == 2)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ return;
+ }
+ if(!lua_istable(m_lua_state, -1))
+ {
+ lua_pop(m_lua_state, 1);
+ return;
+ }
+
+ lua_pushnil(m_lua_state);
+ while(lua_next(m_lua_state, -2))
+ {
+ if(lua_istable(m_lua_state, -1))
+ {
+ menu_item item;
+ lua_rawgeti(m_lua_state, -1, 1);
+ item.text = lua_tostring(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ lua_rawgeti(m_lua_state, -1, 2);
+ item.subtext = lua_tostring(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ lua_rawgeti(m_lua_state, -1, 3);
+ item.flags = lua_tostring(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ menu_list.push_back(item);
+ }
+ lua_pop(m_lua_state, 1);
+ }
+ lua_pop(m_lua_state, 1);
+}
+
+bool lua_engine::menu_callback(std::string &menu, int index, std::string event)
+{
+ std::string field = "menu_cb_" + menu;
+ bool ret = false;
+ lua_settop(m_lua_state, 0);
+ lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str());
+
+ if(lua_isfunction(m_lua_state, -1))
+ {
+ lua_pushinteger(m_lua_state, index);
+ lua_pushstring(m_lua_state, event.c_str());
+ if(int error = lua_pcall(m_lua_state, 2, 1, 0))
+ {
+ if(error == 2)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ return false;
+ }
+ ret = lua_toboolean(m_lua_state, -1);
+ lua_pop(m_lua_state, 1);
+ }
+ return ret;
+}
+
+int lua_engine::l_emu_register_menu(lua_State *L)
+{
+ luaL_argcheck(L, lua_isfunction(L, 1), 1, "callback function expected");
+ luaL_argcheck(L, lua_isfunction(L, 2), 2, "callback function expected");
+ luaL_argcheck(L, lua_isstring(L, 3), 3, "message (string) expected");
+ std::string name = luaL_checkstring(L, 3);
+ std::string cbfield = "menu_cb_" + name;
+ std::string popfield = "menu_pop_" + name;
+ luaThis->m_menu.push_back(std::string(name));
+ lua_pushvalue(L, 1);
+ lua_setfield(L, LUA_REGISTRYINDEX, cbfield.c_str());
+ lua_pushvalue(L, 2);
+ lua_setfield(L, LUA_REGISTRYINDEX, popfield.c_str());
+ return 1;
+}
+
void lua_engine::execute_function(const char *id)
{
lua_settop(m_lua_state, 0);
@@ -1285,7 +1836,12 @@ void lua_engine::execute_function(const char *id)
{
if (lua_isfunction(m_lua_state, -1))
{
- lua_pcall(m_lua_state, 0, 0, 0);
+ if(int error = lua_pcall(m_lua_state, 0, 0, 0))
+ {
+ if(error == 2)
+ printf("%s\n", lua_tostring(m_lua_state, -1));
+ lua_pop(m_lua_state, 1);
+ }
}
else
{
@@ -1346,6 +1902,11 @@ int lua_engine::l_emu_register_frame(lua_State *L)
return register_function(L, "LUA_ON_FRAME");
}
+int lua_engine::l_emu_register_frame_done(lua_State *L)
+{
+ return register_function(L, "LUA_ON_FRAME_DONE");
+}
+
void lua_engine::on_machine_prestart()
{
execute_function("LUA_ON_PRESTART");
@@ -1376,6 +1937,11 @@ void lua_engine::on_machine_frame()
execute_function("LUA_ON_FRAME");
}
+void lua_engine::on_frame_done()
+{
+ execute_function("LUA_ON_FRAME_DONE");
+}
+
void lua_engine::update_machine()
{
lua_newtable(m_lua_state);
@@ -1452,6 +2018,8 @@ void lua_engine::initialize()
.addCFunction ("register_pause", l_emu_register_pause )
.addCFunction ("register_resume",l_emu_register_resume )
.addCFunction ("register_frame", l_emu_register_frame )
+ .addCFunction ("register_frame_done", l_emu_register_frame_done )
+ .addCFunction ("register_menu", l_emu_register_menu )
.beginClass <machine_manager> ("manager")
.addFunction ("machine", &machine_manager::machine)
.addFunction ("options", &machine_manager::options)
@@ -1474,9 +2042,11 @@ void lua_engine::initialize()
.addFunction ("ioport", &running_machine::ioport)
.addFunction ("parameters", &running_machine::parameters)
.addFunction ("cheat", &running_machine::cheat)
+ .addFunction ("memory", &running_machine::memory)
.addFunction ("options", &running_machine::options)
.addProperty <luabridge::LuaRef, void> ("devices", &lua_engine::l_machine_get_devices)
.addProperty <luabridge::LuaRef, void> ("screens", &lua_engine::l_machine_get_screens)
+ .addProperty <luabridge::LuaRef, void> ("images", &lua_engine::l_machine_get_images)
.endClass ()
.beginClass <game_driver> ("game_driver")
.addData ("source_file", &game_driver::source_file)
@@ -1492,8 +2062,10 @@ void lua_engine::initialize()
.addFunction ("name", &device_t::name)
.addFunction ("shortname", &device_t::shortname)
.addFunction ("tag", &device_t::tag)
+ .addFunction ("owner", &device_t::owner)
.addProperty <luabridge::LuaRef, void> ("spaces", &lua_engine::l_dev_get_memspaces)
.addProperty <luabridge::LuaRef, void> ("state", &lua_engine::l_dev_get_states)
+ .addProperty <luabridge::LuaRef, void> ("items", &lua_engine::l_dev_get_items)
.endClass()
.beginClass <cheat_manager> ("cheat")
.addProperty <bool, bool> ("enabled", &cheat_manager::enabled, &cheat_manager::set_enable)
@@ -1621,9 +2193,26 @@ void lua_engine::initialize()
.addCFunction ("write_u32", &lua_addr_space::l_mem_write<UINT32>)
.addCFunction ("write_i64", &lua_addr_space::l_mem_write<INT64>)
.addCFunction ("write_u64", &lua_addr_space::l_mem_write<UINT64>)
+ .addCFunction ("read_direct_i8", &lua_addr_space::l_direct_mem_read<INT8>)
+ .addCFunction ("read_direct_u8", &lua_addr_space::l_direct_mem_read<UINT8>)
+ .addCFunction ("read_direct_i16", &lua_addr_space::l_direct_mem_read<INT16>)
+ .addCFunction ("read_direct_u16", &lua_addr_space::l_direct_mem_read<UINT16>)
+ .addCFunction ("read_direct_i32", &lua_addr_space::l_direct_mem_read<INT32>)
+ .addCFunction ("read_direct_u32", &lua_addr_space::l_direct_mem_read<UINT32>)
+ .addCFunction ("read_direct_i64", &lua_addr_space::l_direct_mem_read<INT64>)
+ .addCFunction ("read_direct_u64", &lua_addr_space::l_direct_mem_read<UINT64>)
+ .addCFunction ("write_direct_i8", &lua_addr_space::l_direct_mem_write<INT8>)
+ .addCFunction ("write_direct_u8", &lua_addr_space::l_direct_mem_write<UINT8>)
+ .addCFunction ("write_direct_i16", &lua_addr_space::l_direct_mem_write<INT16>)
+ .addCFunction ("write_direct_u16", &lua_addr_space::l_direct_mem_write<UINT16>)
+ .addCFunction ("write_direct_i32", &lua_addr_space::l_direct_mem_write<INT32>)
+ .addCFunction ("write_direct_u32", &lua_addr_space::l_direct_mem_write<UINT32>)
+ .addCFunction ("write_direct_i64", &lua_addr_space::l_direct_mem_write<INT64>)
+ .addCFunction ("write_direct_u64", &lua_addr_space::l_direct_mem_write<UINT64>)
.endClass()
.deriveClass <address_space, lua_addr_space> ("addr_space")
.addFunction("name", &address_space::name)
+ .addProperty <luabridge::LuaRef, void> ("map", &lua_engine::l_addr_space_map)
.endClass()
.beginClass <render_target> ("target")
.addFunction ("width", &render_target::width)
@@ -1662,6 +2251,7 @@ void lua_engine::initialize()
.addProperty <bool, bool> ("show_fps", &ui_manager::show_fps, &ui_manager::set_show_fps)
.addProperty <bool, bool> ("show_profiler", &ui_manager::show_profiler, &ui_manager::set_show_profiler)
.addProperty <bool, bool> ("single_step", &ui_manager::single_step, &ui_manager::set_single_step)
+ .addFunction ("get_line_height", &ui_manager::get_line_height)
.endClass()
.beginClass <lua_screen> ("lua_screen_dev")
.addCFunction ("draw_box", &lua_screen::l_draw_box)
@@ -1688,6 +2278,65 @@ void lua_engine::initialize()
.addFunction ("is_visible", &device_state_entry::visible)
.addFunction ("is_divider", &device_state_entry::divider)
.endClass()
+ .beginClass <memory_manager> ("memory")
+ .addProperty <luabridge::LuaRef, void> ("banks", &lua_engine::l_memory_get_banks)
+ .addProperty <luabridge::LuaRef, void> ("regions", &lua_engine::l_memory_get_regions)
+ .endClass()
+ .beginClass <lua_memory_region> ("lua_region")
+ .addCFunction ("read_i8", &lua_memory_region::l_region_read<INT8>)
+ .addCFunction ("read_u8", &lua_memory_region::l_region_read<UINT8>)
+ .addCFunction ("read_i16", &lua_memory_region::l_region_read<INT16>)
+ .addCFunction ("read_u16", &lua_memory_region::l_region_read<UINT16>)
+ .addCFunction ("read_i32", &lua_memory_region::l_region_read<INT32>)
+ .addCFunction ("read_u32", &lua_memory_region::l_region_read<UINT32>)
+ .addCFunction ("read_i64", &lua_memory_region::l_region_read<INT64>)
+ .addCFunction ("read_u64", &lua_memory_region::l_region_read<UINT64>)
+ .addCFunction ("write_i8", &lua_memory_region::l_region_write<INT8>)
+ .addCFunction ("write_u8", &lua_memory_region::l_region_write<UINT8>)
+ .addCFunction ("write_i16", &lua_memory_region::l_region_write<INT16>)
+ .addCFunction ("write_u16", &lua_memory_region::l_region_write<UINT16>)
+ .addCFunction ("write_i32", &lua_memory_region::l_region_write<INT32>)
+ .addCFunction ("write_u32", &lua_memory_region::l_region_write<UINT32>)
+ .addCFunction ("write_i64", &lua_memory_region::l_region_write<INT64>)
+ .addCFunction ("write_u64", &lua_memory_region::l_region_write<UINT64>)
+ .endClass()
+ .deriveClass <memory_region, lua_memory_region> ("region")
+ .addProperty <UINT32> ("size", &memory_region::bytes)
+ .endClass()
+ .beginClass <device_image_interface> ("image")
+ .addFunction ("exists", &device_image_interface::exists)
+ .addFunction ("filename", &device_image_interface::filename)
+ .addFunction ("longname", &device_image_interface::longname)
+ .addFunction ("manufacturer", &device_image_interface::manufacturer)
+ .addFunction ("year", &device_image_interface::year)
+ .addFunction ("software_list_name", &device_image_interface::software_list_name)
+ .addFunction ("image_type_name", &device_image_interface::image_type_name)
+ .addFunction ("load", &device_image_interface::load)
+ .addFunction ("unload", &device_image_interface::unload)
+ .addFunction ("crc", &device_image_interface::crc)
+ .addProperty <const device_t &> ("device", static_cast<const device_t &(device_image_interface::*)() const>(&device_image_interface::device))
+ .addProperty <bool> ("is_readable", &device_image_interface::is_readable)
+ .addProperty <bool> ("is_writeable", &device_image_interface::is_writeable)
+ .addProperty <bool> ("is_creatable", &device_image_interface::is_creatable)
+ .addProperty <bool> ("is_reset_on_load", &device_image_interface::is_reset_on_load)
+ .endClass()
+ .beginClass <lua_emu_file> ("lua_file")
+ .addCFunction ("read", &lua_emu_file::l_emu_file_read)
+ .endClass()
+ .deriveClass <emu_file, lua_emu_file> ("file")
+ .addConstructor <void (*)(const char *, UINT32)> ()
+ .addFunction ("open", static_cast<osd_file::error (emu_file::*)(const char *)>(&emu_file::open))
+ .addFunction ("seek", &emu_file::seek)
+ .addFunction ("size", &emu_file::size)
+ .endClass()
+ .beginClass <lua_item> ("item")
+ .addConstructor <void (*)(int)> ()
+ .addData ("size", &lua_item::l_item_size, false)
+ .addData ("count", &lua_item::l_item_count, false)
+ .addCFunction ("read", &lua_item::l_item_read)
+ .addCFunction ("read_block", &lua_item::l_item_read_block)
+ .addCFunction ("write", &lua_item::l_item_write)
+ .endClass()
.endNamespace();
luabridge::push (m_lua_state, machine_manager::instance());