Previous 199869 Revisions Next

r36597 Monday 16th March, 2015 at 11:03:09 UTC by Luca Bruno
docs: add initial documentation for luaengine API

This commits add some initial documentation for current API
exposed via luaengine. This doc is meant to be a quick
walkthrough for script writers coming from mame-rr.

Full methods reference is not yet included, as the API is still
rapidly changing.

Signed-off-by: Luca Bruno <lucab@debian.org>
[docs]luaengine.md*

trunk/docs/luaengine.md
r0r245109
1# Scripting MAME via LUA
2
3## Introduction
4
5It is now possible to externally drive MAME via LUA scripts.
6This feature initially appeared in version 0.148, when a minimal `luaengine`
7was implemented. Nowadays, the LUA interface is rich enough
8to let you inspect and manipulate devices state, access CPU
9registers, read and write memory, and draw a custom HUD on screen.
10
11Internally, MAME makes extensive use of `luabridge` to implement
12this feature: the idea is to transparently expose as many of
13the useful internals as possible.
14
15Finally, a warning: LUA API is not yet declared stable and may
16suddenly change without prior notice.
17However, we expose methods to let you know at runtime which API
18version you are running against, and you can introspect most of the
19objects at runtime.
20
21## Features
22
23The API is not yet complete, but this is a partial list of capabilities
24currently available to LUA scripts:
25
26 * machine metadata (app version, current rom, rom details)
27 * machine control (starting, pausing, resetting, stopping)
28 * machine hooks (on frame painting and on user events)
29 * devices introspection (device tree listing, memory and register enumeration)
30 * screens introspection (screens listing, screen details, frames counting)
31 * screen HUD drawing (text, lines, boxes on multiple screens)
32 * memory read/write (8/16/32/64 bits, signed and unsigned)
33 * registers and states control (states enumeration, get and set)
34
35## Usage
36
37MAME supports external scripting via LUA (>= 5.3) scripts, either
38written on the interactive console or loaded as a file.
39To reach the console, just run MAME with `-console`; you will be
40greeted by a naked `>` prompt where you can input your script.
41
42To load a whole script at once, store it in a plaintext file and
43pass it via the `-autoboot_script`. Please note that script
44loading may be delayed (few seconds by default), but you can
45override the default with the `-autoboot_delay` argument.
46
47To control the execution of your code, you can use a loop-based or
48an event-based approach. The former is not encouraged as it is
49resource-intensive and makes control flow unnecessarily complex.
50Instead, we suggest to register custom hooks to be invoked on specific
51events (eg. at each frame rendering).
52
53## Walktrough
54
55Let's first run MAME in a terminal to reach the LUA console:
56```
57$ mame -console YOUR_ROM
58M.A.M.E. v0.158 (Feb  5 2015) - Multiple Arcade Machine Emulator
59Copyright Nicola Salmoria and the MAME team
60Lua 5.3.0  Copyright (C) 1994-2015 Lua.org, PUC-Rio
61
62>
63```
64
65At this point, your game is probably running in demo mode, let's pause it:
66```
67> emu.pause()
68>
69```
70Even without textual feedback on the console, you'll notice the game is now paused.
71In general, commands are quiet and only print back error messages.
72
73You can check at runtime which version of MAME you are running, with:
74```
75> print(emu.app_name() .. " " .. emu.app_version())
76mame 0.158
77```
78
79We now start exploring screen related methods. First, let's enumerate available screens:
80```
81> for i,v in pairs(manager:machine().screens) do print(i) end
82:screen
83```
84
85`manager:machine()` is the root object of your currently running machine:
86we will be using this often. `screens` is a table with all available screens;
87most machines only have one main screen.
88In our case, the main and only screen is tagged as `:screen`, and we can further
89inspect it:
90```
91> -- let's define a shorthand for the main screen
92> s = manager:machine().screens[":screen"]
93> print(s:width() .. "x" .. s:height())
94320x224
95```
96
97We have several methods to draw on the screen a HUD composed of lines, boxes and text:
98```
99> -- we define a HUD-drawing function, and then call it
100> function draw_hud()
101>> s:draw_text(40, 40, "foo"); -- (x0, y0, msg)
102>> s:draw_box(20, 20, 80, 80, 0, 0xff00ffff); -- (x0, y0, x1, y1, fill-color, line-color)
103>> s:draw_line(20, 20, 80, 80, 0xff00ffff); -- (x0, y0, x1, y1, line-color)
104>> end
105> draw_hud();
106```
107
108This will draw some useless art on the screen. However, when unpausing the game, your HUD
109needs to be refreshed otherwise it will just disappear. In order to do this, you have to register
110your hook to be called on every frame repaint:
111```
112> emu.sethook(draw_hud, "frame")
113```
114
115Similarly to screens, you can inspect all the devices attached to a
116machine:
117```
118> for k,v in pairs(manager:machine().devices) do print(k) end
119:audiocpu
120:maincpu
121:saveram
122:screen
123:palette
124[...]
125```
126
127On some of them, you can also inspect and manipulate memory and state:
128```
129> cpu = manager:machine().devices[":maincpu"]
130> -- enumerate, read and write state registers
131> for k,v in pairs(cpu.state) do print(k) end
132D5
133SP
134A4
135A3
136D0
137PC
138[...]
139> print(cpu.state["D0"].value)
140303
141> cpu.state["D0"].value = 255
142> print(cpu.state["D0"].value)
143255
144```
145
146```
147> -- inspect memory
148> for k,v in pairs(cpu.spaces) do print(k) end
149program
150> mem = cpu.spaces["program"]
151> print(mem:read_i8(0xC000))
15241
153```
154

Previous 199869 Revisions Next


© 1997-2024 The MAME Team