diff --git a/src/emu/luaengine.c b/src/emu/luaengine.c index 62e7d02563a..984a47195a4 100644 --- a/src/emu/luaengine.c +++ b/src/emu/luaengine.c @@ -17,6 +17,7 @@ #include "emuopts.h" #include "osdepend.h" #include "drivenum.h" +#include "ui/ui.h" #include "web/mongoose.h" //************************************************************************** @@ -336,6 +337,51 @@ int lua_engine::l_emu_hook_output(lua_State *L) return 0; } +int lua_engine::l_emu_set_hook(lua_State *L) +{ + luaThis->emu_set_hook(L); + return 0; +} + +void lua_engine::emu_set_hook(lua_State *L) +{ + luaL_argcheck(L, lua_isfunction(L, 1) || lua_isnil(L, 1), 1, "callback function expected"); + luaL_argcheck(L, lua_isstring(L, 2), 2, "message (string) expected"); + const char *hookname = luaL_checkstring(L,2); + + if (strcmp(hookname, "output") == 0) { + hook_output_cb.set(L, 1); + if (!output_notifier_set) { + output_set_notifier(NULL, s_output_notifier, this); + output_notifier_set = true; + } + } else if (strcmp(hookname, "frame") == 0) { + hook_frame_cb.set(L, 1); + } else { + luai_writestringerror("%s", "Unknown hook name, aborting.\n"); + } +} + +//------------------------------------------------- +// machine_get_screens - return table of available screens userdata +// -> manager:machine().screens[":screen"] +//------------------------------------------------- + +luabridge::LuaRef lua_engine::l_machine_get_screens(const running_machine *r) +{ + lua_State *L = luaThis->m_lua_state; + luabridge::LuaRef screens_table = luabridge::LuaRef::newTable(L); + + for (device_t *dev = r->first_screen(); dev != NULL; dev = dev->next()) { + screen_device *sc = dynamic_cast(dev); + if (sc && sc->configured() && sc->started() && sc->type()) { + screens_table[sc->tag()] = sc; + } + } + + return screens_table; +} + //------------------------------------------------- // machine_get_devices - return table of available devices userdata // -> manager:machine().devices[":maincpu"] @@ -438,6 +484,108 @@ int lua_engine::lua_addr_space::l_mem_read(lua_State *L) } +//------------------------------------------------- +// draw_box - draw a box on a screen container +// -> manager:machine().screens[":screen"]:draw_box(x1, y1, x2, y2, bgcolor, linecolor) +//------------------------------------------------- + +int lua_engine::lua_screen::l_draw_box(lua_State *L) +{ + screen_device *sc = luabridge::Stack::get(L, 1); + if(!sc) { + return 0; + } + + // ensure that we got 6 numerical parameters + luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 6), 6, "background color (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 7), 7, "outline color (integer) expected"); + + // retrieve all parameters + float x1, y1, x2, y2; + x1 = MIN(lua_tounsigned(L, 2) / static_cast(sc->width()) , 1.0f); + y1 = MIN(lua_tounsigned(L, 3) / static_cast(sc->height()), 1.0f); + x2 = MIN(lua_tounsigned(L, 4) / static_cast(sc->width()) , 1.0f); + y2 = MIN(lua_tounsigned(L, 5) / static_cast(sc->height()), 1.0f); + UINT32 bgcolor = lua_tounsigned(L, 6); + UINT32 fgcolor = lua_tounsigned(L, 7); + + // draw the box + render_container &rc = sc->container(); + ui_manager &ui = sc->machine().ui(); + ui.draw_outlined_box(&rc, x1, y1, x2, y2, fgcolor, bgcolor); + + return 0; +} + +//------------------------------------------------- +// draw_line - draw a line on a screen container +// -> manager:machine().screens[":screen"]:draw_line(x1, y1, x2, y2, linecolor) +//------------------------------------------------- + +int lua_engine::lua_screen::l_draw_line(lua_State *L) +{ + screen_device *sc = luabridge::Stack::get(L, 1); + if(!sc) { + return 0; + } + + // ensure that we got 5 numerical parameters + luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 6), 6, "color (integer) expected"); + + // retrieve all parameters + float x1, y1, x2, y2; + x1 = MIN(lua_tounsigned(L, 2) / static_cast(sc->width()) , 1.0f); + y1 = MIN(lua_tounsigned(L, 3) / static_cast(sc->height()), 1.0f); + x2 = MIN(lua_tounsigned(L, 4) / static_cast(sc->width()) , 1.0f); + y2 = MIN(lua_tounsigned(L, 5) / static_cast(sc->height()), 1.0f); + UINT32 color = lua_tounsigned(L, 6); + + // draw the line + sc->container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + return 0; +} + +//------------------------------------------------- +// draw_text - draw text on a screen container +// -> manager:machine().screens[":screen"]:draw_text(x, y, message) +//------------------------------------------------- + +int lua_engine::lua_screen::l_draw_text(lua_State *L) +{ + screen_device *sc = luabridge::Stack::get(L, 1); + if(!sc) { + return 0; + } + + // ensure that we got proper parameters + luaL_argcheck(L, lua_isnumber(L, 2), 2, "x (integer) expected"); + luaL_argcheck(L, lua_isnumber(L, 3), 3, "y (integer) expected"); + luaL_argcheck(L, lua_isstring(L, 4), 4, "message (string) expected"); + + // retrieve all parameters + float x = MIN(lua_tounsigned(L, 2) / static_cast(sc->width()) , 1.0f); + float y = MIN(lua_tounsigned(L, 3) / static_cast(sc->height()), 1.0f); + const char *msg = luaL_checkstring(L,4); + // TODO: add optional parameters (colors, etc.) + + // 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, UI_TEXT_COLOR, + UI_TEXT_BG_COLOR, NULL, NULL); + + return 0; +} + void *lua_engine::checkparam(lua_State *L, int idx, const char *tname) { const char *name; @@ -650,6 +798,7 @@ void lua_engine::initialize() .addCFunction ("romname", l_emu_romname ) .addCFunction ("keypost", l_emu_keypost ) .addCFunction ("hook_output", l_emu_hook_output ) + .addCFunction ("sethook", l_emu_set_hook ) .addCFunction ("time", l_emu_time ) .addCFunction ("wait", l_emu_wait ) .addCFunction ("after", l_emu_after ) @@ -667,6 +816,7 @@ void lua_engine::initialize() .addFunction ("soft_reset", &running_machine::schedule_soft_reset) .addFunction ("system", &running_machine::system) .addProperty ("devices", &lua_engine::l_machine_get_devices) + .addProperty ("screens", &lua_engine::l_machine_get_screens) .endClass () .beginClass ("game_driver") .addData ("name", &game_driver::name) @@ -691,7 +841,17 @@ void lua_engine::initialize() .deriveClass ("addr_space") .addFunction("name", &address_space::name) .endClass() - .endNamespace (); + .beginClass ("lua_screen_dev") + .addCFunction ("draw_box", &lua_screen::l_draw_box) + .addCFunction ("draw_line", &lua_screen::l_draw_line) + .addCFunction ("draw_text", &lua_screen::l_draw_text) + .endClass() + .deriveClass ("screen_dev") + .addFunction ("name", &screen_device::name) + .addFunction ("height", &screen_device::height) + .addFunction ("width", &screen_device::width) + .endClass() + .endNamespace(); luabridge::push (m_lua_state, machine_manager::instance()); lua_setglobal(m_lua_state, "manager"); @@ -702,6 +862,23 @@ void lua_engine::start_console() mg_start_thread(::serve_lua, this); } +//------------------------------------------------- +// frame_hook - called at each frame refresh, used to draw a HUD +//------------------------------------------------- +bool lua_engine::frame_hook() +{ + bool is_cb_hooked = false; + if (m_machine != NULL) { + // invoke registered callback (if any) + is_cb_hooked = hook_frame_cb.active(); + if (is_cb_hooked) { + lua_State *L = hook_frame_cb.precall(); + hook_frame_cb.call(this, L, 0); + } + } + return is_cb_hooked; +} + void lua_engine::periodic_check() { osd_lock_acquire(lock); diff --git a/src/emu/luaengine.h b/src/emu/luaengine.h index ae1221415ff..0f5fcdda2b0 100644 --- a/src/emu/luaengine.h +++ b/src/emu/luaengine.h @@ -44,6 +44,7 @@ public: void serve_lua(); void periodic_check(); + bool frame_hook(); void resume(lua_State *L, int nparam = 0, lua_State *root = NULL); void set_machine(running_machine *machine) { m_machine = machine; update_machine(); } @@ -68,6 +69,8 @@ private: hook hook_output_cb; bool output_notifier_set; + hook hook_frame_cb; + static lua_engine* luaThis; std::map > thread_registry; @@ -82,6 +85,7 @@ private: int emu_after(lua_State *L); int emu_wait(lua_State *L); void emu_hook_output(lua_State *L); + void emu_set_hook(lua_State *L); static int l_ioport_write(lua_State *L); static int l_emu_after(lua_State *L); @@ -97,6 +101,7 @@ private: static int l_emu_start(lua_State *L); static int l_emu_pause(lua_State *L); static int l_emu_unpause(lua_State *L); + static int l_emu_set_hook(lua_State *L); // "emu.machine" namespace static luabridge::LuaRef l_machine_get_devices(const running_machine *r); @@ -105,6 +110,12 @@ private: struct lua_addr_space { template int l_mem_read(lua_State *L); }; + static luabridge::LuaRef l_machine_get_screens(const running_machine *r); + struct lua_screen { + int l_draw_box(lua_State *L); + int l_draw_line(lua_State *L); + int l_draw_text(lua_State *L); + }; void resume(void *L, INT32 param); void report_errors(int status); diff --git a/src/emu/video.c b/src/emu/video.c index 63c8e6d4b80..2cc4ff225f2 100644 --- a/src/emu/video.c +++ b/src/emu/video.c @@ -655,6 +655,9 @@ bool video_manager::finish_screen_updates() if (screen->update_quads()) anything_changed = true; + // draw HUD from LUA callback (if any) + anything_changed |= machine().manager().lua()->frame_hook(); + // update our movie recording and burn-in state if (!machine().paused()) { diff --git a/src/mame/drivers/gts80a.c b/src/mame/drivers/gts80a.c index 6d10197e621..ae9bd7ca49c 100644 --- a/src/mame/drivers/gts80a.c +++ b/src/mame/drivers/gts80a.c @@ -15,6 +15,7 @@ #include "audio/gottlieb.h" #include "cpu/i86/i86.h" #include "gts80a.lh" +#include "gts80a_caveman.lh" class gts80a_state : public genpin_class { @@ -384,25 +385,75 @@ public: caveman_state(const machine_config &mconfig, device_type type, const char *tag) : gts80a_state(mconfig, type, tag) , m_videocpu(*this, "video_cpu") + , m_vram(*this, "vram") + { } + + UINT32 screen_update_caveman(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + private: required_device m_videocpu; + required_shared_ptr m_vram; }; +UINT32 caveman_state::screen_update_caveman(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + int count = 0; + for (int y = 0; y < 256; y++) + { + for (int x = 0; x < 256; x += 4) + { + UINT8 pix = m_vram[count]; + + bitmap.pix16(y, x+0) = (pix >> 6)&0x3; + bitmap.pix16(y, x+1) = (pix >> 4)&0x3; + bitmap.pix16(y, x+2) = (pix >> 2)&0x3; + bitmap.pix16(y, x+3) = (pix >> 0)&0x3; + + count++; + } + } + + return 0; +} + + static ADDRESS_MAP_START( video_map, AS_PROGRAM, 8, caveman_state ) ADDRESS_MAP_GLOBAL_MASK(0xffff) - AM_RANGE(0x0000, 0x5fff) AM_RAM + AM_RANGE(0x0000, 0x07ff) AM_RAM + AM_RANGE(0x2000, 0x5fff) AM_RAM AM_SHARE("vram") AM_RANGE(0x8000, 0xffff) AM_ROM ADDRESS_MAP_END static ADDRESS_MAP_START( video_io_map, AS_IO, 8, caveman_state ) +// AM_RANGE(0x000, 0x002) AM_READWRITE() // 8259 irq controller +// AM_RANGE(0x100, 0x102) AM_READWRITE() // HD46505 +// AM_RANGE(0x200, 0x200) AM_READWRITE() // 8212 in, ?? out +// AM_RANGE(0x300, 0x300) AM_READWRITE() // soundlatch (command?) in, ?? out + +// AM_RANGE(0x400, 0x400) AM_READ() // joystick inputs +// AM_RANGE(0x500, 0x506) AM_WRITE() // palette + ADDRESS_MAP_END -static MACHINE_CONFIG_DERIVED( caveman, gts80a_ss ) +static MACHINE_CONFIG_DERIVED_CLASS( caveman, gts80a_ss, caveman_state ) MCFG_CPU_ADD("video_cpu", I8088, 5000000) MCFG_CPU_PROGRAM_MAP(video_map) MCFG_CPU_IO_MAP(video_io_map) + + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(60) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) + MCFG_SCREEN_SIZE(256, 256) + MCFG_SCREEN_VISIBLE_AREA(0, 256-1, 0, 248-1) + MCFG_SCREEN_UPDATE_DRIVER(caveman_state, screen_update_caveman) + MCFG_SCREEN_PALETTE("palette") + + MCFG_PALETTE_ADD("palette", 16) + + MCFG_DEFAULT_LAYOUT(layout_gts80a_caveman) + MACHINE_CONFIG_END static INPUT_PORTS_START( caveman ) diff --git a/src/mame/layout/gts80a_caveman.lay b/src/mame/layout/gts80a_caveman.lay new file mode 100644 index 00000000000..cf5950d2c24 --- /dev/null +++ b/src/mame/layout/gts80a_caveman.lay @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 74247ca6b2d..7bf393a5727 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -2661,7 +2661,8 @@ $(DRIVERS)/goldnpkr.o: $(LAYOUT)/goldnpkr.lh \ $(DRIVERS)/gts1.o: $(LAYOUT)/gts1.lh $(DRIVERS)/gts3.o: $(LAYOUT)/gts3.lh $(DRIVERS)/gts80.o: $(LAYOUT)/gts80.lh -$(DRIVERS)/gts80a.o: $(LAYOUT)/gts80a.lh +$(DRIVERS)/gts80a.o: $(LAYOUT)/gts80a.lh \ + $(LAYOUT)/gts80a_caveman.lh $(DRIVERS)/gts80b.o: $(LAYOUT)/gts80b.lh $(DRIVERS)/lbeach.o: $(LAYOUT)/lbeach.lh diff --git a/src/osd/windows/windows.mak b/src/osd/windows/windows.mak index f268ade1e8b..ce3a283f615 100644 --- a/src/osd/windows/windows.mak +++ b/src/osd/windows/windows.mak @@ -302,7 +302,11 @@ CCOMFLAGS += -include $(WINSRC)/winprefix.h include $(SRC)/build/cc_detection.mak # ensure we statically link the gcc runtime lib -LDFLAGS += -static-libgcc -static +LDFLAGS += -static-libgcc + +ifeq ($(CROSS_BUILD),1) + LDFLAGS += -static +endif # TODO: needs to use $(CC) TEST_GCC := $(shell gcc --version)