Back to the Computer Controlled Player for MAME page

MAME architecture and its use in machine learning

Alejandro Dubrovsky (33289401)


Contents

1 Overview

1.1 What is MAME?

MAME (Multiple Arcade Machine Emulator) is, as its name suggests, an emulator of arcade machines' hardware. It first got released in February 1997 by Nicola Salmoria, and while it was slower than the many other emulators available at the time, it quickly gathered a strong following due to the quick accumulation of emulated games. That it managed to do this was at least partly due to its strongly modularised design and its clean inter-CPU interfaces. MAME currently (as of June 2005) provides the hardware emulation for about 5600 games, including clones and variants, spanning release dates from 1975 to 2002. It is released with a BSD-style license (as of version 0.97) with further restrictions on selling either source code or binaries.

1.2 What is XMAME?

MAME was originally a DOS program, but a clean interface dividing all operating system-dependant parts from the core of the program was conducive to it being ported to other platforms. The port to a POSIXish platform, and the XWindows graphical environment was named XMAME and was originally done by Allard Van Der Bas, Dick the Ridder, Juan Antonio Martinez, and Hans de Goede only a couple of months after the first MAME release. It later grew many video and audio backends. It still tracks mainline development closely, and an XMAME release almost always follows very soon after a MAME release. XMAME will be the main focus of this report, and it is the X11 video backend which will be tapped to supply an interface to an external agent.

1.3 What is an agent?

In the context of this report, an agent, and, more specifically, a game playing agent, will be understood to be a program that takes input from the system, say video, score, and other miscellaneous game state data, and outputs its actions as a player would, in the case of arcade games, joystick movements and button presses.

2 MAME Architecture

MAME was designed for speed and portability, and is therefore written in C. It is divided into two layers joined by a thin connecting interface. The platform-independent emulation layer writes its video output to a 16-bit indexed or 32-bit RGB framebuffer, its audio to an audio buffer in a standard 44KHz 16-bit stereo wav format and takes its input from an input array of MAME-defined input constants (such as button 1 press or joystick 1 left release). The operating system dependent (OSD) layer is responsible for making that framebuffer visible on the screen, piping the audio buffer to the sound card, transforming it into a suitable format if needed, and grabbing the hardware input and filling the input array. The interface is the common definition of how these two layers talk to each other.

2.1 Emulation Layer

Each game emulated has an assigned driver which defines the system the game runs on. The system definition consists of the CPUs involved and the memory mappings and ports that each CPU has access to and their interconnections. It also defines what video and audio hardware the game uses and their memory mappings, the ROM mapping and references to a machine definition for other miscellaneous bits of hardware (e.g. ROM decoding, real-time clocks, coin and joystick mapping). The CPU, video hardware, audio hardware and machine emulations referenced in the driver are kept in the cpu, vidhrdw, sndhrdw and machine subdirectories respectively, and are each used by many games.

2.2 Operating System Dependant Interface

The interface to the operating system dependant calls is defined in osdepend.h. It defines calls which the operating system dependant layer should implement, like opening and closing a display, outputting video and audio data, open, read, write and close files, read keyboard and game input data, get time data, and other less critical tasks.

2.3 XMAME

XMAME is implemented as fulfilling the operating system dependant layer defined in osdepend.h. It consists of a unix core, which provides the file calls and timing implementations, and video, audio, joystick, and frameskip drivers, the video drivers usually having to provide keyboard and mouse handling since they are interdependent. XMAME also provides capabilities to produce many video effects to make the image look like the original games did on their monitors.

Available video drivers as of version 0.97 are SVGA, which does not require XWindows, xgl (OpenGL backends), SDL, itself an interface library that can write to many different backends, and the X11 backend, which can output in XV, DGA or plain Xlib modes. The XV output of the X11 backend is likely the fastest XMAME backend for which root access is not needed.

3 Interfacing to a controlling program

3.1 Required and desirable features

A program trying to play a game as an agent would need have access to the framebuffer and would need to make its actions be considered as inputs to MAME. It would be preferable for it to be platform-independent and to be unobtrusive if its not in use, and in implementation code so as to ease the complexity of keeping up with the main branch of MAME development. It would also be preferable for the action of the game to be optionally visible just like in normal settings, and for a human to be able to intervene in case overriding or triggering some actions was desired.

3.2 Interface design and implementation details

While the desirability of a platform-independent interface would make it imperative to modify the emulation layer only, all other requirements could be easily met by acting as an extra video driver under the XMAME implementation, so the platform-independent feature was eliminated. XMAME's x11 video driver already handles several different video modes, and it was quite natural to implement the controller as another video mode. The only difference between this controller mode and a standard mode is that it acts as a secondary video mode, that is, all data is sent to the controller mode and input taken from the controller mode as well as to and from whichever video mode is being used for normal display. This satisfies all other requirements. 1

The controller module, when compiled in and enabled, is called at initialisation stage (sysdep_display_init in x11.c), when opening a display (sysdep_display_open in x11.c), when outputting the frame buffer (sysdep_display_update in x11.c), when closing the display (sysdep_display_close in x11.c) and when exiting (sysdep_display_exit in x11.c). Its actions are captured by requesting them when the x11 driver polls the keyboard (sysdep_display_driver_update_keyboard in xinput.c). These are the same points at which the normal video drivers are called.

The controller module itself is a thin interface that mostly calls the initialisation, frame buffer update, action polling and exiting functions of the real agent selected at runtime. It also converts from MAME's internal indexed bitmap format to a BGRA format, keeps track of keyboard states to avoid confusing MAME in case the agent reports illegal action or keyboard events (e.g. releasing a key twice in a row), provides Python bindings for the interface functions so that agents can be written in that language if desired,2 and provides the current score of the game being played to the agent.

4 Limitations For Research

While MAME presents a great opportunity to try machine learning algorithms in a variety of environments, it also presents some special challenges of its own. These include legal issues, lack of control of the environment, lack of state inspection capabilities, and dealing with ancient optimisation techniques and encodings.

4.1 Legal issues

While MAME presents a uniform interface to a wide variety of predesigned environments, these environments are almost all commercially produced and a license needed to make use of them. There is a short collection of games that have been supposedly released to be used free of charge at Legal MAME ROMs http://www.sys2064.com/legalroms.htm. There is also a collection of about 25 Atari games being sold for small amounts of money ($2 and $6 at the time of writing) at StarRoms http://www.starroms.com. Other ROM licences can be bought on-line. Trying to obtain a new license from the copyright holders for old games is a tricky procedure since it is hard to find out who the current copyright holders are, and once they are found, they seem to be quite unresponsive to enquiries. If you own a game PCB board then in some countries you are allowed to read the ROM contents from the board. Unfortunately, this is not the case in Australia at the moment (as far as I know, consult your local lawyer).

4.2 Closed environments and opaque states

The source code for arcade games are almost universally unavailable to the public3. This makes modification of the environment almost impossible and observation of the environment's internal state very hard. The only possibility is to observe the emulated memory state and extract information from it.

The most vital piece of information that would be desirable to extract for machine learning purposes would be an end of game marker (i.e. ``Game Over''). I have found no way of extracting this information internally in a game generic manner and have resorted to ad-hoc per game methods extracting features from the resulting framebuffer that only occur at the end of the game (e.g detecting the presence of the ``E'' in ``Game Over'' at a certain location on the screen). Other important information that would help a program would be feedback on its current score and state of bitmaps in the game. I do not think a generic internal way for extracting bitmaps is feasible, but the current score does.

4.2.1 Extracting current scores

One of the possible forms of feedback that can be supplied to an agent is its current score in the game since a score is an almost universal way of measuring performance in games. Supplying scores though, is a labour intensive, per game, or at least per game family, process. The score has to be found somewhere in the emulated CPU's RAM and decoded. Luckily, MAME comes with a very useful in-game debugger, and people have been very interested in keeping their high scores table, so a short tutorial available at Mame high score tutorial http://www.mameworld.net/highscore/tutorial.htm on how to find these high scores can be easily adapted to finding the current score. The size of the score in bytes can also be guessed from the large collection of high score address ranges described in the hiscore.dat file available from Mame high score download page http://www.mameworld.net/highscore/download.htm which MAME uses to save these high scores table.

The process involves playing the game, pausing at some point, and searching for some encoding of your current score in RAM with the debugger. Since the encoding is unknown prior to finding the score, a lot of different encodings probably have to be tried. The CPU family used for the game should be consulted since this will likely limit the types of encodings that are likely to be used, especially regarding little versus big-endian choices. A non-complete list of encodings follows:

  1. 8, 16 or 32 bit numbers encoded in big-endian format. Big-endian format is easy to spot since it looks natural on the screen of a debugger. In big-endian format, the most significant byte is stored at the lowest address, the second most significant byte at the second lowest address, and so on, so for example, the hexadecimal number 0x12 34 56 78 will appear on a debugger as 12 34 56 78.
  2. 8, 16 or 32 bit numbers encoded in little-endian format. Little-endian format stores the numbers in reverse, i.e. the least significant byte is stored in the lowest address and the most significant byte in the highest address. This gets slightly more complicated due to the data width of the CPU, since if the number does not fit in the data width, the number is likely to be stored with the least significant word in the lowest address and the most significant word in the highest. Going back to the example, 0x12 34 56 78 would be encoded as 78 56 34 12 in a 32-bit width word CPU, but as 34 12 78 56 in a 16-bit word CPU.
  3. Decimal encoding stores numbers as if each nibble could only store 10 states instead of 16. This makes the number very easy to spot on a debugger since it becomes the decimal score as normally written. For example if the score is 1857 then the memory in hexadecimal will be 0x18 57. Big and little-endian formats of this encoding are likely to be encountered. Although this kind of encoding seems to have been popular in early arcade machines (late 70s, early 80s), it is not common in later games.
  4. Modifications of current score. For example, if the score is always a multiple of 10, then it is likely that the last zero is not stored in RAM, only getting added at display time, so if the score is 18530 then encodings of 1853 should be looked for as well.
Once the location and encoding of the score is known, the memory can be read by the MAME utility function cpunum_read_byte defined in src/cpuintrf.h, and decoded.

5 Future Work

The interface design has not been finalised, and the current implementation does not exactly match the design presented above. Intermediate layers of preprocessing could be added in the future which would extract various bits of information from the framebuffer image, and which the agent could request. Interfacing with the OpenCV library OpenCV library http://sourceforge.net/projects/opencvlibrary/ is planned to help with this part. Another tempting option is to make the agents more independent from the main MAME process by communicating with it through pipes or TCP connections, but speed is usually at a premium in machine learning and this setup could have a significant impact on performance.

The latest version of this document and the interface implementation will be found at Mame Machine Learning interface http://www.organicrobot.com/mame/.

About this document ...

MAME architecture and its use in machine learning

This document was generated using the LaTeX2HTML translator Version 2002-2-1 (1.71)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -no_subdir -split 0 -show_section_numbers /tmp/lyx_tmpdir12104YZsyV/lyx_tmpbuf0/mamereport.tex

The translation was initiated by Alejandro Dubrovsky on 2005-08-02


Footnotes

...1
A case could be put to tap higher and create a pass-through to all video drivers, but the increased complexity of this task did not seem worth the effort. This could change in the future.
...2
The current implementation is not as flexible as this suggests. The agent is not selectable at runtime and the Python bindings are the only way of interfacing, but this will be fixed in the short term.
... public3
I say almost since there could be some, but I am not aware of any that are.

Alejandro Dubrovsky 2005-08-02